Skip to content

Commit

Permalink
feat(arrays): add unique (#141)
Browse files Browse the repository at this point in the history
  • Loading branch information
imranbarbhuiya authored Jul 7, 2022
1 parent 43016a0 commit ad7af34
Show file tree
Hide file tree
Showing 14 changed files with 242 additions and 130 deletions.
154 changes: 68 additions & 86 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
@@ -1,88 +1,70 @@
{
"projectName": "shapeshift",
"projectOwner": "sapphiredev",
"repoType": "github",
"repoHost": "https://github.com",
"files": [
"README.md"
],
"imageSize": 100,
"commit": true,
"commitConvention": "angular",
"contributors": [
{
"login": "kyranet",
"name": "Antonio Román",
"avatar_url": "https://avatars.githubusercontent.com/u/24852502?v=4",
"profile": "https://github.com/kyranet",
"contributions": [
"code",
"doc",
"ideas"
]
},
{
"login": "vladfrangu",
"name": "Vlad Frangu",
"avatar_url": "https://avatars.githubusercontent.com/u/17960496?v=4",
"profile": "https://github.com/vladfrangu",
"contributions": [
"code",
"doc",
"ideas"
]
},
{
"login": "favna",
"name": "Jeroen Claassens",
"avatar_url": "https://avatars.githubusercontent.com/u/4019718?v=4",
"profile": "https://favware.tech/",
"contributions": [
"doc",
"maintenance",
"infra"
]
},
{
"login": "renovate[bot]",
"name": "renovate[bot]",
"avatar_url": "https://avatars.githubusercontent.com/in/2740?v=4",
"profile": "https://github.com/apps/renovate",
"contributions": [
"maintenance"
]
},
{
"login": "renovate-bot",
"name": "WhiteSource Renovate",
"avatar_url": "https://avatars.githubusercontent.com/u/25180681?v=4",
"profile": "https://renovate.whitesourcesoftware.com/",
"contributions": [
"maintenance"
]
},
{
"login": "Khasms",
"name": "John",
"avatar_url": "https://avatars.githubusercontent.com/u/36800359?v=4",
"profile": "https://github.com/Khasms",
"contributions": [
"code"
]
},
{
"login": "imranbarbhuiya",
"name": "Parbez",
"avatar_url": "https://avatars.githubusercontent.com/u/74945038?v=4",
"profile": "https://github.com/imranbarbhuiya",
"contributions": [
"code",
"test",
"bug",
"doc"
]
}
],
"contributorsPerLine": 7,
"skipCi": true
"projectName": "shapeshift",
"projectOwner": "sapphiredev",
"repoType": "github",
"repoHost": "https://github.com",
"files": ["README.md"],
"imageSize": 100,
"commit": true,
"commitConvention": "angular",
"contributors": [
{
"login": "kyranet",
"name": "Antonio Román",
"avatar_url": "https://avatars.githubusercontent.com/u/24852502?v=4",
"profile": "https://github.com/kyranet",
"contributions": ["code", "doc", "ideas"]
},
{
"login": "vladfrangu",
"name": "Vlad Frangu",
"avatar_url": "https://avatars.githubusercontent.com/u/17960496?v=4",
"profile": "https://github.com/vladfrangu",
"contributions": ["code", "doc", "ideas"]
},
{
"login": "favna",
"name": "Jeroen Claassens",
"avatar_url": "https://avatars.githubusercontent.com/u/4019718?v=4",
"profile": "https://favware.tech/",
"contributions": ["doc", "maintenance", "infra"]
},
{
"login": "renovate[bot]",
"name": "renovate[bot]",
"avatar_url": "https://avatars.githubusercontent.com/in/2740?v=4",
"profile": "https://github.com/apps/renovate",
"contributions": ["maintenance"]
},
{
"login": "renovate-bot",
"name": "WhiteSource Renovate",
"avatar_url": "https://avatars.githubusercontent.com/u/25180681?v=4",
"profile": "https://renovate.whitesourcesoftware.com/",
"contributions": ["maintenance"]
},
{
"login": "Khasms",
"name": "John",
"avatar_url": "https://avatars.githubusercontent.com/u/36800359?v=4",
"profile": "https://github.com/Khasms",
"contributions": ["code"]
},
{
"login": "imranbarbhuiya",
"name": "Parbez",
"avatar_url": "https://avatars.githubusercontent.com/u/74945038?v=4",
"profile": "https://github.com/imranbarbhuiya",
"contributions": ["code", "test", "bug", "doc"]
},
{
"login": "allcontributors[bot]",
"name": "allcontributors[bot]",
"avatar_url": "https://avatars.githubusercontent.com/in/23186?v=4",
"profile": "https://github.com/apps/allcontributors",
"contributions": ["doc"]
}
],
"contributorsPerLine": 7,
"skipCi": true
}
27 changes: 27 additions & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,33 @@ jobs:
run: yarn --immutable
- name: Typecheck And Build Code
run: yarn typecheck && yarn build
- name: Upload bundle to artifacts
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # tag=v3
with:
name: bundle
path: dist/
if-no-files-found: error

NoModulesTesting:
name: No Modules Testing
runs-on: ubuntu-latest
needs: Building
steps:
- name: Checkout Project
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- name: Download generated typings artifact
uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 # tag=v3
with:
name: bundle
path: dist/
- name: Use Node.js v18
uses: actions/setup-node@eeb10cff27034e7acf239c5d29f62154018672fd # tag=v3
with:
node-version: 18
cache: yarn
registry-url: https://registry.npmjs.org/
- name: Run test script
run: node scripts/no-bundle-test.mjs

Upload_Coverage_Report:
name: Upload coverage report to codecov
Expand Down
32 changes: 18 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# @sapphire/shapeshift

**ShapeShift**
**Shapeshift**

Blazing fast input validation and transformation ⚡

Expand Down Expand Up @@ -54,15 +54,15 @@ Blazing fast input validation and transformation ⚡
- [BaseValidator: methods and properties](#basevalidator-methods-and-properties)
- [Enabling and disabling validation](#enabling-and-disabling-validation)
- [Buy us some doughnuts](#buy-us-some-doughnuts)
- [Contributors](#contributors-%E2%9C%A8)
- [Contributors](#contributors)

## Description

[Back to top][toc]

A very fast and lightweight input validation and transformation library for JavaScript.

> **Note**: ShapeShift requires Node.js v14.0.0 or higher to work.
> **Note**: Shapeshift requires Node.js v14.0.0 or higher to work.
## Features

Expand Down Expand Up @@ -154,7 +154,7 @@ s.literal(new Date(1639278160000)); // s.date.equal(1639278160000);

[Back to top][toc]

ShapeShift includes a handful of string-specific validations:
Shapeshift includes a handful of string-specific validations:

```typescript
s.string.lengthLessThan(5);
Expand All @@ -176,7 +176,7 @@ s.string.ipv6;

[Back to top][toc]

ShapeShift includes a handful of number-specific validations:
Shapeshift includes a handful of number-specific validations:

```typescript
s.number.greaterThan(5); // > 5
Expand Down Expand Up @@ -216,7 +216,7 @@ s.number.ceil; // Transforms the number to the result of `Math.ceil`

[Back to top][toc]

ShapeShift includes a handful of number-specific validations:
Shapeshift includes a handful of number-specific validations:

```typescript
s.bigint.greaterThan(5n); // > 5n
Expand Down Expand Up @@ -245,7 +245,7 @@ s.bigint.uintN(5); // Clamps to a bigint to an unsigned bigint with 5 digits, se

[Back to top][toc]

ShapeShift includes a few boolean-specific validations:
Shapeshift includes a few boolean-specific validations:

```typescript
s.boolean.true; // value must be true
Expand All @@ -267,7 +267,7 @@ const stringArray = s.array(s.string);
const stringArray = s.string.array;
```

ShapeShift includes a handful of array-specific validations:
Shapeshift includes a handful of array-specific validations:

```typescript
s.string.array.lengthLessThan(5); // Must have less than 5 elements
Expand All @@ -279,6 +279,7 @@ s.string.array.lengthNotEqual(5); // Must not have exactly 5 elements
s.string.array.lengthRange(0, 4); // Must have at least 0 elements and less than 4 elements (in math, that is [0, 4))
s.string.array.lengthRangeInclusive(0, 4); // Must have at least 0 elements and at most 4 elements (in math, that is [0, 4])
s.string.array.lengthRangeExclusive(0, 4); // Must have more than 0 element and less than 4 elements (in math, that is (0, 4))
s.string.array.unique; // All elements must be unique. Deep equality is used to check for uniqueness.
```

> **Note**: All `.length` methods define tuple types with the given amount of elements. For example, `s.string.array.lengthGreaterThanOrEqual(2)`'s inferred type is `[string, string, ...string[]]`
Expand All @@ -303,7 +304,7 @@ dish.parse(['Iberian ham', 10, new Date()]);

[Back to top][toc]

ShapeShift includes a built-in method for composing OR types:
Shapeshift includes a built-in method for composing OR types:

```typescript
const stringOrNumber = s.union(s.string, s.number);
Expand Down Expand Up @@ -393,7 +394,7 @@ s.function([s.string]); // (arg0: string) => unknown
s.function([s.string, s.number], s.string); // (arg0: string, arg1: number) => string
```

> **Note**: ShapeShift will transform the given function into one with validation on arguments and output. You can access the `.raw` property of the function to get the unchecked function.
> **Note**: Shapeshift will transform the given function into one with validation on arguments and output. You can access the `.raw` property of the function to get the unchecked function.
---

Expand All @@ -416,7 +417,7 @@ const bigInt64Array = s.bigInt64Array;
const bigUint64Array = s.bigUint64Array;
```

ShapeShift includes a handful of validations specific to typed arrays.
Shapeshift includes a handful of validations specific to typed arrays.

```typescript
s.typedArray().lengthLessThan(5); // Length must be less than 5
Expand Down Expand Up @@ -633,7 +634,7 @@ const user = s.object({

[Back to top][toc]

By default, ShapeShift will not include keys that are not defined by the schema during parsing:
By default, Shapeshift will not include keys that are not defined by the schema during parsing:

```typescript
const person = s.object({
Expand Down Expand Up @@ -683,7 +684,7 @@ You can use the `.passthrough` getter to make the validator add the unrecognized

[Back to top][toc]

All validations in ShapeShift contain certain methods.
All validations in Shapeshift contain certain methods.

`.run(data: unknown): Result<T, Error>`: given a validation, you can call this method to check whether or not the input is valid. If it is, a `Result` with `success: true` and a deep-cloned value will be returned with the given constraints and transformations. Otherwise, a `Result` with `success: false` and an error is returned.

Expand Down Expand Up @@ -803,7 +804,7 @@ We accept donations through Open Collective, Ko-fi, Paypal, Patreon and GitHub S
| Patreon | [Click Here](https://sapphirejs.dev/patreon) |
| PayPal | [Click Here](https://sapphirejs.dev/paypal) |

## Contributors
## Contributors

[Back to top][toc]

Expand All @@ -822,6 +823,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center"><a href="https://github.com/Khasms"><img src="https://avatars.githubusercontent.com/u/36800359?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John</b></sub></a><br /><a href="https://github.com/sapphiredev/shapeshift/commits?author=Khasms" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/imranbarbhuiya"><img src="https://avatars.githubusercontent.com/u/74945038?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Parbez</b></sub></a><br /><a href="https://github.com/sapphiredev/shapeshift/commits?author=imranbarbhuiya" title="Code">💻</a> <a href="https://github.com/sapphiredev/shapeshift/commits?author=imranbarbhuiya" title="Tests">⚠️</a> <a href="https://github.com/sapphiredev/shapeshift/issues?q=author%3Aimranbarbhuiya" title="Bug reports">🐛</a> <a href="https://github.com/sapphiredev/shapeshift/commits?author=imranbarbhuiya" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/apps/allcontributors"><img src="https://avatars.githubusercontent.com/in/23186?v=4?s=100" width="100px;" alt=""/><br /><sub><b>allcontributors[bot]</b></sub></a><br /><a href="https://github.com/sapphiredev/shapeshift/commits?author=allcontributors[bot]" title="Documentation">📖</a></td>
</tr>
</table>

<!-- markdownlint-restore -->
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@sapphire/eslint-config": "^4.3.7",
"@sapphire/prettier-config": "^1.4.3",
"@sapphire/ts-config": "^3.3.4",
"@types/lodash.uniqwith": "^4.5.7",
"@types/node": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.30.3",
"@typescript-eslint/parser": "^5.30.3",
Expand All @@ -49,8 +50,10 @@
"eslint": "^8.19.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"fast-deep-equal": "^3.1.3",
"husky": "^8.0.1",
"lint-staged": "^13.0.3",
"lodash.uniqwith": "^4.5.0",
"pinst": "^3.0.0",
"prettier": "^2.7.1",
"pretty-quick": "^3.1.3",
Expand Down
16 changes: 16 additions & 0 deletions scripts/no-bundle-test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* A very simple file that can run without having a node_modules directory
* This way we can validate from a NodeJS environment that the bundle will
* work completely standalone
*/

import assert from 'node:assert/strict';
import { ExpectedConstraintError, s } from '../dist/index.mjs';

const uniqSchema = s.array(s.string).unique;
const goodData = ['a', 'b', 'c'];
const badData = ['a', 'b', 'a'];

assert.deepStrictEqual(uniqSchema.parse(goodData), goodData);

assert.throws(() => uniqSchema.parse(badData), ExpectedConstraintError);
Loading

0 comments on commit ad7af34

Please sign in to comment.