Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,18 @@ v.validate({ roles: ["user", "admin"] }, schema); // Valid
v.validate({ roles: ["guest"] }, schema); // Fail
```

**Example for `unique`:**
```js
const schema = {
roles: { type: "array", unique: true }
}

v.validate({ roles: ["user"] }, schema); // Valid
v.validate({ roles: [{role:"user"},{role:"admin"},{role:"user"}] }, schema); // Valid
v.validate({ roles: ["user", "admin", "user"] }, schema); // Fail
v.validate({ roles: [1, 2, 1] }, schema); // Fail
```

### Properties
Property | Default | Description
-------- | -------- | -----------
Expand All @@ -363,6 +375,7 @@ Property | Default | Description
`max` | `null` | Maximum count of elements.
`length` | `null` | Fix count of elements.
`contains` | `null` | The array must contain this element too.
`unique` | `null` | The array must be unique (array of objects is always unique).
`enum` | `null` | Every element must be an element of the `enum` array.
`items` | `null` | Schema for array items.

Expand Down Expand Up @@ -969,6 +982,7 @@ Name | Default text
`arrayMax` | The '{field}' field must contain less than or equal to {expected} items.
`arrayLength` | The '{field}' field must contain {expected} items.
`arrayContains` | The '{field}' field must contain the '{expected}' item.
`arrayUnique` | The '{actual}' value in '{field}' field does not unique the '{expected}' values.
`arrayEnum` | The '{actual}' value in '{field}' field does not match any of the '{expected}' values.
`boolean` | The '{field}' field must be a boolean.
`function` | The '{field}' field must be a function.
Expand Down
1 change: 1 addition & 0 deletions lib/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module.exports = {
arrayMax: "The '{field}' field must contain less than or equal to {expected} items.",
arrayLength: "The '{field}' field must contain {expected} items.",
arrayContains: "The '{field}' field must contain the '{expected}' item.",
arrayUnique: "The '{actual}' value in '{field}' field does not unique the '{expected}' values.",
arrayEnum: "The '{actual}' value in '{field}' field does not match any of the '{expected}' values.",

boolean: "The '{field}' field must be a boolean.",
Expand Down
8 changes: 8 additions & 0 deletions lib/rules/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ module.exports = function({ schema, messages }, path, context) {
`);
}

if (schema.unique === true) {
src.push(`
if(len > (new Set(value)).size) {
${this.makeError({ type: "arrayUnique", expected: "Array.from(new Set(value.filter((item, index) => value.indexOf(item) !== index)))", actual: "value", messages })}
}
`);
}

if (schema.enum != null) {
const enumStr = JSON.stringify(schema.enum);
src.push(`
Expand Down
1 change: 1 addition & 0 deletions test/messages.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ describe("Test Messages", () => {
expect(msg.arrayMax).toBeDefined();
expect(msg.arrayLength).toBeDefined();
expect(msg.arrayContains).toBeDefined();
expect(msg.arrayUnique).toBeDefined();
expect(msg.arrayEnum).toBeDefined();
expect(msg.boolean).toBeDefined();
expect(msg.function).toBeDefined();
Expand Down
10 changes: 10 additions & 0 deletions test/rules/array.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ describe("Test rule: array", () => {
expect(check([8, 5, 2])).toEqual(true);
});

it("check unique", () => {
const check = v.compile({ $$root: true, type: "array", unique: true });

expect(check(["bob","john","bob"])).toEqual([{ type: "arrayUnique", expected: ["bob"], actual: ["bob", "john", "bob"], message: "The 'bob,john,bob' value in '' field does not unique the 'bob' values." }]);
expect(check(["bob","john","bob","bob","john"])).toEqual([{ type: "arrayUnique", expected: ["bob","john"], actual: ["bob","john","bob","bob","john"], message: "The 'bob,john,bob,bob,john' value in '' field does not unique the 'bob,john' values." }]);
expect(check([1,2,1,false,true,false])).toEqual([{ type: "arrayUnique", expected: [1,false], actual: [1,2,1,false,true,false], message: "The '1,2,1,false,true,false' value in '' field does not unique the '1,false' values." }]);
expect(check([{name:"bob"},{name:"john"},{name:"bob"}])).toEqual(true);
expect(check(["john", "bob"])).toEqual(true);
});

it("check enum", () => {
const check = v.compile({ $$root: true, type: "array", enum: ["male", "female"] });

Expand Down