@ark/schema
Advanced tools
@@ -215,2 +215,4 @@ import { arrayEquals, flatMorph, includes, inferred, omit, throwInternalError, throwParseError } from "@ark/util"; | ||
| extends(r) { | ||
| if (this.isNever()) | ||
| return true; | ||
| const intersection = this.intersect(r); | ||
@@ -217,0 +219,0 @@ return (!(intersection instanceof Disjoint) && this.equals(intersection)); |
@@ -1,2 +0,2 @@ | ||
| import { type array, type Key, type listable } from "@ark/util"; | ||
| import { type array, type describe, type Key, type listable } from "@ark/util"; | ||
| import { BaseConstraint } from "../constraint.ts"; | ||
@@ -7,3 +7,3 @@ import type { GettableKeyOrNode, KeyOrKeyNode } from "../node.ts"; | ||
| import type { BaseScope } from "../scope.ts"; | ||
| import type { NodeCompiler } from "../shared/compile.ts"; | ||
| import { type NodeCompiler } from "../shared/compile.ts"; | ||
| import type { BaseNormalizedSchema, declareNode } from "../shared/declare.ts"; | ||
@@ -113,1 +113,3 @@ import { type nodeImplementationOf, type StructuralKind } from "../shared/implement.ts"; | ||
| export declare const writeInvalidKeysMessage: <o extends string, keys extends array<KeyOrKeyNode>>(o: o, keys: keys) => string; | ||
| export declare const writeDuplicateKeyMessage: <key extends Key>(key: key) => writeDuplicateKeyMessage<key>; | ||
| export type writeDuplicateKeyMessage<key extends Key> = `Duplicate key '${describe<key>}'`; |
@@ -5,2 +5,3 @@ import { append, conflatenate, flatMorph, printable, spliterate, throwInternalError, throwParseError } from "@ark/util"; | ||
| import { typeOrTermExtends } from "../roots/root.js"; | ||
| import { compileSerializedValue } from "../shared/compile.js"; | ||
| import { Disjoint } from "../shared/disjoint.js"; | ||
@@ -194,29 +195,46 @@ import { implementNode } from "../shared/implement.js"; | ||
| reduce: (inner, $) => { | ||
| if (inner.index) { | ||
| if (!(inner.required || inner.optional)) | ||
| return; | ||
| let updated = false; | ||
| const requiredProps = inner.required ?? []; | ||
| const optionalProps = inner.optional ?? []; | ||
| const newOptionalProps = [...optionalProps]; | ||
| for (const index of inner.index) { | ||
| for (const requiredProp of requiredProps) { | ||
| const intersection = intersectPropsAndIndex(requiredProp, index, $); | ||
| if (intersection instanceof Disjoint) | ||
| return intersection; | ||
| if (!inner.required && !inner.optional) | ||
| return; | ||
| const seen = {}; | ||
| let updated = false; | ||
| const newOptionalProps = inner.optional ? [...inner.optional] : []; | ||
| // check required keys for duplicates and handle index intersections | ||
| if (inner.required) { | ||
| for (let i = 0; i < inner.required.length; i++) { | ||
| const requiredProp = inner.required[i]; | ||
| if (requiredProp.key in seen) | ||
| throwParseError(writeDuplicateKeyMessage(requiredProp.key)); | ||
| seen[requiredProp.key] = true; | ||
| if (inner.index) { | ||
| for (const index of inner.index) { | ||
| const intersection = intersectPropsAndIndex(requiredProp, index, $); | ||
| if (intersection instanceof Disjoint) | ||
| return intersection; | ||
| } | ||
| } | ||
| for (const [indx, optionalProp] of optionalProps.entries()) { | ||
| const intersection = intersectPropsAndIndex(optionalProp, index, $); | ||
| if (intersection instanceof Disjoint) | ||
| return intersection; | ||
| if (intersection === null) | ||
| continue; | ||
| newOptionalProps[indx] = intersection; | ||
| updated = true; | ||
| } | ||
| } | ||
| // check optional keys for duplicates and handle index intersections | ||
| if (inner.optional) { | ||
| for (let i = 0; i < inner.optional.length; i++) { | ||
| const optionalProp = inner.optional[i]; | ||
| if (optionalProp.key in seen) | ||
| throwParseError(writeDuplicateKeyMessage(optionalProp.key)); | ||
| seen[optionalProp.key] = true; | ||
| if (inner.index) { | ||
| for (const index of inner.index) { | ||
| const intersection = intersectPropsAndIndex(optionalProp, index, $); | ||
| if (intersection instanceof Disjoint) | ||
| return intersection; | ||
| if (intersection !== null) { | ||
| newOptionalProps[i] = intersection; | ||
| updated = true; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| if (updated) { | ||
| return $.node("structure", { ...inner, optional: newOptionalProps }, { prereduced: true }); | ||
| } | ||
| } | ||
| if (updated) { | ||
| return $.node("structure", { ...inner, optional: newOptionalProps }, { prereduced: true }); | ||
| } | ||
| } | ||
@@ -731,1 +749,2 @@ }); | ||
| export const writeInvalidKeysMessage = (o, keys) => `Key${keys.length === 1 ? "" : "s"} ${keys.map(typeKeyToString).join(", ")} ${keys.length === 1 ? "does" : "do"} not exist on ${o}`; | ||
| export const writeDuplicateKeyMessage = (key) => `Duplicate key ${compileSerializedValue(key)}`; |
+10
-2
| { | ||
| "name": "@ark/schema", | ||
| "version": "0.51.0", | ||
| "version": "0.52.0", | ||
| "license": "MIT", | ||
@@ -26,2 +26,10 @@ "author": { | ||
| "default": "./out/config.js" | ||
| }, | ||
| "./internal/*.ts": { | ||
| "ark-ts": "./*.ts", | ||
| "default": "./out/*.js" | ||
| }, | ||
| "./internal/*.js": { | ||
| "ark-ts": "./*.ts", | ||
| "default": "./out/*.js" | ||
| } | ||
@@ -33,3 +41,3 @@ }, | ||
| "dependencies": { | ||
| "@ark/util": "0.51.0" | ||
| "@ark/util": "0.52.0" | ||
| }, | ||
@@ -36,0 +44,0 @@ "publishConfig": { |
432531
0.32%10114
0.23%+ Added
- Removed
Updated