[79a0317] | 1 | import type {FuncKeywordDefinition, AnySchemaObject} from "ajv"
|
---|
| 2 | import equal = require("fast-deep-equal")
|
---|
| 3 |
|
---|
| 4 | const SCALAR_TYPES = ["number", "integer", "string", "boolean", "null"]
|
---|
| 5 |
|
---|
| 6 | export default function getDef(): FuncKeywordDefinition {
|
---|
| 7 | return {
|
---|
| 8 | keyword: "uniqueItemProperties",
|
---|
| 9 | type: "array",
|
---|
| 10 | schemaType: "array",
|
---|
| 11 | compile(keys: string[], parentSchema: AnySchemaObject) {
|
---|
| 12 | const scalar = getScalarKeys(keys, parentSchema)
|
---|
| 13 |
|
---|
| 14 | return (data) => {
|
---|
| 15 | if (data.length <= 1) return true
|
---|
| 16 | for (let k = 0; k < keys.length; k++) {
|
---|
| 17 | const key = keys[k]
|
---|
| 18 | if (scalar[k]) {
|
---|
| 19 | const hash: Record<string, any> = {}
|
---|
| 20 | for (const x of data) {
|
---|
| 21 | if (!x || typeof x != "object") continue
|
---|
| 22 | let p = x[key]
|
---|
| 23 | if (p && typeof p == "object") continue
|
---|
| 24 | if (typeof p == "string") p = '"' + p
|
---|
| 25 | if (hash[p]) return false
|
---|
| 26 | hash[p] = true
|
---|
| 27 | }
|
---|
| 28 | } else {
|
---|
| 29 | for (let i = data.length; i--; ) {
|
---|
| 30 | const x = data[i]
|
---|
| 31 | if (!x || typeof x != "object") continue
|
---|
| 32 | for (let j = i; j--; ) {
|
---|
| 33 | const y = data[j]
|
---|
| 34 | if (y && typeof y == "object" && equal(x[key], y[key])) return false
|
---|
| 35 | }
|
---|
| 36 | }
|
---|
| 37 | }
|
---|
| 38 | }
|
---|
| 39 | return true
|
---|
| 40 | }
|
---|
| 41 | },
|
---|
| 42 | metaSchema: {
|
---|
| 43 | type: "array",
|
---|
| 44 | items: {type: "string"},
|
---|
| 45 | },
|
---|
| 46 | }
|
---|
| 47 | }
|
---|
| 48 |
|
---|
| 49 | function getScalarKeys(keys: string[], schema: AnySchemaObject): boolean[] {
|
---|
| 50 | return keys.map((key) => {
|
---|
| 51 | const t = schema.items?.properties?.[key]?.type
|
---|
| 52 | return Array.isArray(t)
|
---|
| 53 | ? !t.includes("object") && !t.includes("array")
|
---|
| 54 | : SCALAR_TYPES.includes(t)
|
---|
| 55 | })
|
---|
| 56 | }
|
---|
| 57 |
|
---|
| 58 | module.exports = getDef
|
---|