Comparing version 0.1.2 to 0.1.3
@@ -112,3 +112,3 @@ "use strict"; | ||
createAnonymousTypeName() { | ||
return `anonymousType${++_classPrivateFieldUpdate(this, _anonymousTypeCount).value}`; | ||
return `type${++_classPrivateFieldUpdate(this, _anonymousTypeCount).value}`; | ||
} | ||
@@ -246,6 +246,6 @@ get infer() { | ||
const initializeType = (definition, opts, scope)=>{ | ||
const name = opts.name ?? scope.createAnonymousTypeName(); | ||
const name = opts.name ?? "type"; | ||
const meta = { | ||
name, | ||
id: `${scope.name}.${name}`, | ||
id: `${scope.name}.${opts.name ? name : scope.createAnonymousTypeName()}`, | ||
definition, | ||
@@ -327,3 +327,3 @@ scope, | ||
const scope = (aliases, opts = {})=>new Scope(aliases, opts); | ||
const ts = scope({ | ||
const tsKeywords = scope({ | ||
any: [ | ||
@@ -410,4 +410,9 @@ "node", | ||
} | ||
], | ||
// TODO: Add remaining JS object types | ||
] | ||
}, { | ||
name: "ts", | ||
standard: false | ||
}); | ||
const tsKeywordsSpace = tsKeywords.compile(); | ||
const jsObjects = scope({ | ||
Function: [ | ||
@@ -417,11 +422,115 @@ "node", | ||
object: { | ||
subdomain: "Function" | ||
objectKind: "Function" | ||
} | ||
} | ||
], | ||
Array: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Array" | ||
} | ||
} | ||
], | ||
Date: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Date" | ||
} | ||
} | ||
], | ||
Error: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Error" | ||
} | ||
} | ||
], | ||
Map: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Map" | ||
} | ||
} | ||
], | ||
RegExp: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "RegExp" | ||
} | ||
} | ||
], | ||
Set: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Set" | ||
} | ||
} | ||
], | ||
Object: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Object" | ||
} | ||
} | ||
], | ||
String: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "String" | ||
} | ||
} | ||
], | ||
Number: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Number" | ||
} | ||
} | ||
], | ||
Boolean: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Boolean" | ||
} | ||
} | ||
], | ||
WeakMap: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "WeakMap" | ||
} | ||
} | ||
], | ||
WeakSet: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "WeakSet" | ||
} | ||
} | ||
], | ||
Promise: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Promise" | ||
} | ||
} | ||
] | ||
}, { | ||
name: "ts", | ||
name: "jsObjects", | ||
standard: false | ||
}); | ||
const tsTypes = ts.compile(); | ||
const jsObjectsSpace = jsObjects.compile(); | ||
const validation = scope({ | ||
@@ -445,8 +554,9 @@ email: /^(.+)@(.+)\.(.+)$/, | ||
}); | ||
const validationTypes = validation.compile(); | ||
const validationSpace = validation.compile(); | ||
const standard = scope({}, { | ||
name: "standard", | ||
includes: [ | ||
tsTypes, | ||
validationTypes | ||
tsKeywordsSpace, | ||
jsObjectsSpace, | ||
validationSpace | ||
], | ||
@@ -457,3 +567,4 @@ standard: false | ||
const scopes = { | ||
ts, | ||
tsKeywords, | ||
jsObjects, | ||
validation, | ||
@@ -463,4 +574,5 @@ standard | ||
const spaces = { | ||
ts: tsTypes, | ||
validation: validationTypes, | ||
tsKeywords: tsKeywordsSpace, | ||
jsObjects: jsObjectsSpace, | ||
validation: validationSpace, | ||
standard: standardTypes | ||
@@ -467,0 +579,0 @@ }; |
@@ -19,9 +19,9 @@ "use strict"; | ||
const _rulesTs = require("./rules/rules.js"); | ||
const isBranchComparison = (comparison)=>comparison?.lConditions !== undefined; | ||
const isBranchComparison = (comparison)=>comparison?.lBranches !== undefined; | ||
const compareBranches = (lConditions, rConditions, state)=>{ | ||
const result = { | ||
lConditions, | ||
rConditions, | ||
lSubconditionsOfR: [], | ||
rSubconditionsOfL: [], | ||
lBranches: lConditions, | ||
rBranches: rConditions, | ||
lExtendsR: [], | ||
rExtendsL: [], | ||
equalities: [], | ||
@@ -46,3 +46,3 @@ distinctIntersections: [] | ||
} else if (subresult === l) { | ||
result.lSubconditionsOfR.push(lIndex); | ||
result.lExtendsR.push(lIndex); | ||
// If l is a subtype of the current r branch, intersections | ||
@@ -54,3 +54,3 @@ // with the remaining branches of r won't lead to distinct | ||
} else if (subresult === r) { | ||
result.rSubconditionsOfL.push(rIndex); | ||
result.rExtendsL.push(rIndex); | ||
// If r is a subtype of the current l branch, it is removed | ||
@@ -57,0 +57,0 @@ // from pairsByR because future intersections won't lead to |
@@ -71,3 +71,3 @@ "use strict"; | ||
domain: ({ l , r })=>`${l.join(", ")} and ${r.join(", ")}`, | ||
subdomain: ({ l , r })=>`${l} and ${r}`, | ||
objectKind: ({ l , r })=>`${l} and ${r}`, | ||
range: ({ l , r })=>`${stringifyRange(l)} and ${stringifyRange(r)}`, | ||
@@ -78,3 +78,4 @@ class: ({ l , r })=>`classes ${l.name} and ${r.name}`, | ||
leftAssignability: ({ l , r })=>`literal value ${(0, _serializeTs.serialize)(l.value)} and ${(0, _serializeTs.serialize)(r)}`, | ||
rightAssignability: ({ l , r })=>`literal value ${(0, _serializeTs.serialize)(r.value)} and ${(0, _serializeTs.serialize)(l)}` | ||
rightAssignability: ({ l , r })=>`literal value ${(0, _serializeTs.serialize)(r.value)} and ${(0, _serializeTs.serialize)(l)}`, | ||
union: ({ l , r })=>`branches ${(0, _serializeTs.serialize)(l)} and branches ${(0, _serializeTs.serialize)(r)}` | ||
}; | ||
@@ -81,0 +82,0 @@ const stringifyRange = (range)=>"limit" in range ? `the range of exactly ${range.limit}` : range.min ? range.max ? `the range bounded by ${range.min.comparator}${range.min.limit} and ${range.max.comparator}${range.max.limit}` : `${range.min.comparator}${range.min.limit}` : range.max ? `${range.max.comparator}${range.max.limit}` : "the unbounded range"; |
@@ -20,2 +20,3 @@ "use strict"; | ||
const _genericsTs = require("../utils/generics.js"); | ||
const _objectKindsTs = require("../utils/objectKinds.js"); | ||
const _pathsTs = require("../utils/paths.js"); | ||
@@ -63,3 +64,3 @@ const _serializeTs = require("../utils/serialize.js"); | ||
domain: true, | ||
subdomain: true, | ||
objectKind: true, | ||
value: true | ||
@@ -81,3 +82,3 @@ }; | ||
for(const path in intersectionState.disjoints){ | ||
// designed to match subdomain path segments like "${number}" | ||
// designed to match objectKind path segments like "${number}" | ||
if (path.includes("${")) { | ||
@@ -197,3 +198,3 @@ continue; | ||
value: (data)=>serializeIfPrimitive(data) ?? "default", | ||
subdomain: _domainsTs.subdomainOf, | ||
objectKind: (data)=>(0, _objectKindsTs.objectKindOf)(data) ?? "default", | ||
domain: _domainsTs.domainOf | ||
@@ -203,2 +204,2 @@ }; | ||
const branchIncludesMorph = (branch, $)=>"morph" in branch ? true : "props" in branch ? Object.values(branch.props).some((prop)=>nodeIncludesMorph((0, _propsTs.isOptional)(prop) ? prop[1] : prop, $)) : false; | ||
const nodeIncludesMorph = (node, $)=>typeof node === "string" ? $.resolve(node).meta.includesMorph : Object.values(node).some((predicate)=>predicate === true ? false : (0, _domainsTs.hasSubdomain)(predicate, "Array") ? predicate.some((branch)=>branchIncludesMorph(branch, $)) : branchIncludesMorph(predicate, $)); | ||
const nodeIncludesMorph = (node, $)=>typeof node === "string" ? $.resolve(node).meta.includesMorph : Object.values(node).some((predicate)=>predicate === true ? false : (0, _objectKindsTs.isArray)(predicate) ? predicate.some((branch)=>branchIncludesMorph(branch, $)) : branchIncludesMorph(predicate, $)); |
@@ -12,3 +12,3 @@ "use strict"; | ||
object: { | ||
subdomain: [ | ||
objectKind: [ | ||
"Array", | ||
@@ -21,3 +21,3 @@ node | ||
object: { | ||
subdomain: [ | ||
objectKind: [ | ||
"Set", | ||
@@ -30,3 +30,3 @@ node | ||
object: { | ||
subdomain: [ | ||
objectKind: [ | ||
"Map", | ||
@@ -33,0 +33,0 @@ k, |
@@ -64,3 +64,3 @@ "use strict"; | ||
}; | ||
const hasImpliedDomain = (flatPredicate)=>flatPredicate[0] && (flatPredicate[0][0] === "subdomain" || flatPredicate[0][0] === "value"); | ||
const hasImpliedDomain = (flatPredicate)=>flatPredicate[0] && (flatPredicate[0][0] === "objectKind" || flatPredicate[0][0] === "value"); | ||
const flattenType = (type)=>{ | ||
@@ -67,0 +67,0 @@ const ctx = { |
@@ -19,4 +19,4 @@ "use strict"; | ||
}); | ||
const _domainsTs = require("../utils/domains.js"); | ||
const _genericsTs = require("../utils/generics.js"); | ||
const _objectKindsTs = require("../utils/objectKinds.js"); | ||
const _branchesTs = require("./branches.js"); | ||
@@ -31,3 +31,3 @@ const _composeTs = require("./compose.js"); | ||
} | ||
if (!(0, _domainsTs.hasSubdomain)(l, "Array") && !(0, _domainsTs.hasSubdomain)(r, "Array")) { | ||
if (!(0, _objectKindsTs.isArray)(l) && !(0, _objectKindsTs.isArray)(r)) { | ||
const result = (0, _rulesTs.branchIntersection)(emptyRulesIfTrue(l), emptyRulesIfTrue(r), context); | ||
@@ -42,6 +42,6 @@ return result === l ? l : result === r ? r : result; | ||
} | ||
if (comparison.lSubconditionsOfR.length + comparison.equalities.length === lBranches.length) { | ||
if (comparison.lExtendsR.length + comparison.equalities.length === lBranches.length) { | ||
return l; | ||
} | ||
if (comparison.rSubconditionsOfL.length + comparison.equalities.length === rBranches.length) { | ||
if (comparison.rExtendsL.length + comparison.equalities.length === rBranches.length) { | ||
return r; | ||
@@ -57,8 +57,12 @@ } | ||
} | ||
return (0, _genericsTs.collapseIfSingleton)([ | ||
const resultBranches = [ | ||
...comparison.distinctIntersections, | ||
...comparison.equalities.map((indices)=>comparison.lConditions[indices[0]]), | ||
...comparison.lSubconditionsOfR.map((lIndex)=>comparison.lConditions[lIndex]), | ||
...comparison.rSubconditionsOfL.map((rIndex)=>comparison.rConditions[rIndex]) | ||
]); | ||
...comparison.equalities.map((indices)=>comparison.lBranches[indices[0]]), | ||
...comparison.lExtendsR.map((lIndex)=>comparison.lBranches[lIndex]), | ||
...comparison.rExtendsL.map((rIndex)=>comparison.rBranches[rIndex]) | ||
]; | ||
if (resultBranches.length === 0) { | ||
state.addDisjoint("union", comparison.lBranches, comparison.rBranches); | ||
} | ||
return resultBranches.length === 1 ? resultBranches[0] : resultBranches; | ||
}; | ||
@@ -76,6 +80,7 @@ const predicateUnion = (domain, l, r, type)=>{ | ||
} | ||
return (0, _genericsTs.collapseIfSingleton)([ | ||
...comparison.lConditions.filter((_, lIndex)=>!comparison.lSubconditionsOfR.includes(lIndex) && !comparison.equalities.some((indexPair)=>indexPair[0] === lIndex)), | ||
...comparison.rConditions.filter((_, rIndex)=>!comparison.rSubconditionsOfL.includes(rIndex) && !comparison.equalities.some((indexPair)=>indexPair[1] === rIndex)) | ||
]); | ||
const resultBranches = [ | ||
...comparison.lBranches.filter((_, lIndex)=>!comparison.lExtendsR.includes(lIndex) && !comparison.equalities.some((indexPair)=>indexPair[0] === lIndex)), | ||
...comparison.rBranches.filter((_, rIndex)=>!comparison.rExtendsL.includes(rIndex) && !comparison.equalities.some((indexPair)=>indexPair[1] === rIndex)) | ||
]; | ||
return resultBranches.length === 1 ? resultBranches[0] : resultBranches; | ||
}; | ||
@@ -86,3 +91,3 @@ const flattenPredicate = (predicate, context)=>{ | ||
} | ||
return (0, _domainsTs.hasSubdomain)(predicate, "Array") ? (0, _discriminateTs.flattenBranches)(predicate, context) : (0, _rulesTs.flattenBranch)(predicate, context); | ||
return (0, _objectKindsTs.isArray)(predicate) ? (0, _discriminateTs.flattenBranches)(predicate, context) : (0, _rulesTs.flattenBranch)(predicate, context); | ||
}; | ||
@@ -89,0 +94,0 @@ const isLiteralCondition = (predicate)=>typeof predicate === "object" && "value" in predicate; |
@@ -15,7 +15,6 @@ "use strict"; | ||
}); | ||
const _domainsTs = require("../../utils/domains.js"); | ||
const _composeTs = require("../compose.js"); | ||
const collapsibleListUnion = (l, r)=>{ | ||
if ((0, _domainsTs.hasSubdomain)(l, "Array")) { | ||
if ((0, _domainsTs.hasSubdomain)(r, "Array")) { | ||
if (Array.isArray(l)) { | ||
if (Array.isArray(r)) { | ||
const result = listUnion(l, r); | ||
@@ -29,3 +28,3 @@ return result.length === l.length ? result.length === r.length ? (0, _composeTs.equality)() : l : result.length === r.length ? r : result; | ||
} | ||
if ((0, _domainsTs.hasSubdomain)(r, "Array")) { | ||
if (Array.isArray(r)) { | ||
return r.includes(l) ? r : [ | ||
@@ -32,0 +31,0 @@ ...r, |
@@ -20,3 +20,3 @@ "use strict"; | ||
}); | ||
const _domainsTs = require("../../utils/domains.js"); | ||
const _sizeTs = require("../../utils/size.js"); | ||
const _composeTs = require("../compose.js"); | ||
@@ -98,3 +98,3 @@ const minComparators = { | ||
const checkBound = (data, bound, state)=>{ | ||
if (!comparatorCheckers[bound.comparator]((0, _domainsTs.sizeOf)(data), bound.limit)) { | ||
if (!comparatorCheckers[bound.comparator]((0, _sizeTs.sizeOf)(data), bound.limit)) { | ||
state.problems.add("bound", data, bound); | ||
@@ -101,0 +101,0 @@ } |
@@ -26,6 +26,6 @@ "use strict"; | ||
const _divisorTs = require("./divisor.js"); | ||
const _objectKindTs = require("./objectKind.js"); | ||
const _propsTs = require("./props.js"); | ||
const _rangeTs = require("./range.js"); | ||
const _regexTs = require("./regex.js"); | ||
const _subdomainTs = require("./subdomain.js"); | ||
const rulesOf = (branch)=>branch.input ?? branch; | ||
@@ -62,3 +62,3 @@ const branchIntersection = (l, r, state)=>{ | ||
const narrowableRulesIntersection = (0, _composeTs.composeKeyedIntersection)({ | ||
subdomain: _subdomainTs.subdomainIntersection, | ||
objectKind: _objectKindTs.objectKindIntersection, | ||
divisor: _divisorTs.divisorIntersection, | ||
@@ -74,3 +74,3 @@ regex: _regexTs.regexIntersection, | ||
const ruleFlatteners = { | ||
subdomain: _subdomainTs.flattenSubdomain, | ||
objectKind: _objectKindTs.flattenObjectKind, | ||
regex: (entries, rule)=>{ | ||
@@ -119,3 +119,3 @@ for (const source of (0, _genericsTs.listFrom)(rule)){ | ||
branches: 0, | ||
subdomain: 0, | ||
objectKind: 0, | ||
switch: 0, | ||
@@ -122,0 +122,0 @@ alias: 0, |
@@ -20,2 +20,4 @@ "use strict"; | ||
const _errorsTs = require("../utils/errors.js"); | ||
const _objectKindsTs = require("../utils/objectKinds.js"); | ||
const _serializeTs = require("../utils/serialize.js"); | ||
const _recordTs = require("./record.js"); | ||
@@ -25,8 +27,26 @@ const _stringTs = require("./string/string.js"); | ||
const parseDefinition = (def, ctx)=>{ | ||
const subdomain = (0, _domainsTs.subdomainOf)(def); | ||
return subdomain === "string" ? (0, _stringTs.parseString)(def, ctx) : subdomain === "object" ? (0, _recordTs.parseRecord)(def, ctx) : subdomain === "Array" ? (0, _tupleTs.parseTuple)(def, ctx) : subdomain === "RegExp" ? { | ||
string: { | ||
regex: def.source | ||
} | ||
} : (0, _mainTs.isType)(def) ? def.node : (0, _errorsTs.throwParseError)(writeBadDefinitionTypeMessage(subdomain)); | ||
const domain = (0, _domainsTs.domainOf)(def); | ||
if (domain === "string") { | ||
return (0, _stringTs.parseString)(def, ctx); | ||
} | ||
if (domain !== "object") { | ||
return (0, _errorsTs.throwParseError)(writeBadDefinitionTypeMessage(domain)); | ||
} | ||
const objectKind = (0, _objectKindsTs.objectKindOf)(def); | ||
switch(objectKind){ | ||
case "Object": | ||
return (0, _recordTs.parseRecord)(def, ctx); | ||
case "Array": | ||
return (0, _tupleTs.parseTuple)(def, ctx); | ||
case "RegExp": | ||
return { | ||
string: { | ||
regex: def.source | ||
} | ||
}; | ||
case "Function": | ||
return (0, _mainTs.isType)(def) ? def.node : (0, _errorsTs.throwParseError)(writeBadDefinitionTypeMessage("Function")); | ||
default: | ||
return (0, _errorsTs.throwParseError)(writeBadDefinitionTypeMessage(objectKind ?? (0, _serializeTs.stringify)(def))); | ||
} | ||
}; | ||
@@ -33,0 +53,0 @@ const as = Symbol("as"); |
@@ -74,3 +74,3 @@ "use strict"; | ||
} | ||
return (0, _genericsTs.listFrom)(resolution.object).every((branch)=>(0, _genericsTs.hasKey)(branch, "subdomain") && (branch.subdomain === "Array" || branch.subdomain[0] === "Array")); | ||
return (0, _genericsTs.listFrom)(resolution.object).every((branch)=>(0, _genericsTs.hasKey)(branch, "objectKind") && (branch.objectKind === "Array" || branch.objectKind[0] === "Array")); | ||
default: | ||
@@ -77,0 +77,0 @@ return false; |
@@ -15,4 +15,4 @@ "use strict"; | ||
}); | ||
const _domainsTs = require("../../utils/domains.js"); | ||
const _errorsTs = require("../../utils/errors.js"); | ||
const _objectKindsTs = require("../../utils/objectKinds.js"); | ||
const _serializeTs = require("../../utils/serialize.js"); | ||
@@ -37,3 +37,3 @@ const _definitionTs = require("../definition.js"); | ||
} else if (typeof predicate === "object") { | ||
result[domain] = (0, _domainsTs.hasSubdomain)(predicate, "Array") ? predicate.map((branch)=>applyMorph(branch, morph)) : applyMorph(predicate, morph); | ||
result[domain] = (0, _objectKindsTs.isArray)(predicate) ? predicate.map((branch)=>applyMorph(branch, morph)) : applyMorph(predicate, morph); | ||
} else { | ||
@@ -40,0 +40,0 @@ (0, _errorsTs.throwInternalError)(`Unexpected predicate value for domain '${domain}': ${(0, _serializeTs.stringify)(predicate)}`); |
@@ -39,3 +39,3 @@ "use strict"; | ||
object: { | ||
subdomain: "Array", | ||
objectKind: "Array", | ||
props, | ||
@@ -42,0 +42,0 @@ range: { |
@@ -15,5 +15,4 @@ "use strict"; | ||
Problems: ()=>Problems, | ||
describeSubdomains: ()=>describeSubdomains, | ||
describeDomains: ()=>describeDomains, | ||
describeBranches: ()=>describeBranches, | ||
subdomainDescriptions: ()=>subdomainDescriptions, | ||
DataWrapper: ()=>DataWrapper, | ||
@@ -26,2 +25,3 @@ defaultProblemWriters: ()=>defaultProblemWriters, | ||
const _genericsTs = require("../utils/generics.js"); | ||
const _objectKindsTs = require("../utils/objectKinds.js"); | ||
const _pathsTs = require("../utils/paths.js"); | ||
@@ -102,10 +102,10 @@ const _serializeTs = require("../utils/serialize.js"); | ||
const capitalize = (s)=>s[0].toUpperCase() + s.slice(1); | ||
const describeSubdomains = (subdomains)=>{ | ||
if (subdomains.length === 1) { | ||
return subdomainDescriptions[subdomains[0]]; | ||
const describeDomains = (domains)=>{ | ||
if (domains.length === 1) { | ||
return _domainsTs.domainDescriptions[domains[0]]; | ||
} | ||
if (subdomains.length === 0) { | ||
if (domains.length === 0) { | ||
return "never"; | ||
} | ||
return describeBranches(subdomains.map((subdomain)=>subdomainDescriptions[subdomain])); | ||
return describeBranches(domains.map((objectKind)=>_domainsTs.domainDescriptions[objectKind])); | ||
}; | ||
@@ -123,19 +123,2 @@ const describeBranches = (descriptions)=>{ | ||
}; | ||
const subdomainDescriptions = { | ||
bigint: "a bigint", | ||
boolean: "boolean", | ||
null: "null", | ||
number: "a number", | ||
object: "an object", | ||
string: "a string", | ||
symbol: "a symbol", | ||
undefined: "undefined", | ||
Array: "an array", | ||
Function: "a function", | ||
Date: "a Date", | ||
RegExp: "a RegExp", | ||
Error: "an Error", | ||
Map: "a Map", | ||
Set: "a Set" | ||
}; | ||
class DataWrapper { | ||
@@ -148,14 +131,13 @@ toString() { | ||
} | ||
// TODO: object kind? | ||
get subdomain() { | ||
return (0, _domainsTs.subdomainOf)(this.value); | ||
get objectKind() { | ||
return (0, _objectKindsTs.objectKindOf)(this.value) ?? "non-object"; | ||
} | ||
get size() { | ||
return (0, _domainsTs.sizeOf)(this.value); | ||
return typeof this.value === "string" || Array.isArray(this.value) ? this.value.length : typeof this.value === "number" ? this.value : 0; | ||
} | ||
get units() { | ||
return (0, _domainsTs.unitsOf)(this.value); | ||
return typeof this.value === "string" ? "characters" : Array.isArray(this.value) ? "items" : ""; | ||
} | ||
get className() { | ||
return (0, _domainsTs.classNameOf)(this.value); | ||
return Object(this.value).constructor.name; | ||
} | ||
@@ -187,9 +169,13 @@ constructor(value){ | ||
domain: { | ||
mustBe: (domain)=>subdomainDescriptions[domain], | ||
mustBe: (domain)=>_domainsTs.domainDescriptions[domain], | ||
was: (data)=>data.domain | ||
}, | ||
domainBranches: { | ||
mustBe: (domains)=>describeSubdomains(domains), | ||
mustBe: (domains)=>describeDomains(domains), | ||
was: (data)=>data.domain | ||
}, | ||
objectKind: { | ||
mustBe: (kind)=>_objectKindsTs.objectKindDescriptions[kind], | ||
was: (data)=>data.objectKind | ||
}, | ||
missing: { | ||
@@ -196,0 +182,0 @@ mustBe: ()=>"defined", |
@@ -15,3 +15,3 @@ "use strict"; | ||
checkEntries: ()=>checkEntries, | ||
checkSubdomain: ()=>checkSubdomain | ||
checkObjectKind: ()=>checkObjectKind | ||
}); | ||
@@ -27,2 +27,3 @@ const _discriminateJs = require("../nodes/discriminate.js"); | ||
const _genericsJs = require("../utils/generics.js"); | ||
const _objectKindsJs = require("../utils/objectKinds.js"); | ||
const _pathsJs = require("../utils/paths.js"); | ||
@@ -178,3 +179,2 @@ const _serializeJs = require("../utils/serialize.js"); | ||
if (propKind !== "optionalProps") { | ||
// TODO: update | ||
state.problems.add("missing", undefined, undefined); | ||
@@ -191,14 +191,14 @@ } | ||
const checkOptionalProps = createPropChecker("optionalProps"); | ||
const checkSubdomain = (data, rule, state)=>{ | ||
const dataSubdomain = (0, _domainsJs.subdomainOf)(data); | ||
const checkObjectKind = (data, rule, state)=>{ | ||
const dataObjectKind = (0, _objectKindsJs.objectKindOf)(data); | ||
if (typeof rule === "string") { | ||
if (dataSubdomain !== rule) { | ||
return state.problems.add("domain", data, rule); | ||
if (dataObjectKind !== rule) { | ||
return state.problems.add("objectKind", data, rule); | ||
} | ||
return; | ||
} | ||
if (dataSubdomain !== rule[0]) { | ||
return state.problems.add("domain", data, rule[0]); | ||
if (dataObjectKind !== rule[0]) { | ||
return state.problems.add("objectKind", data, rule[0]); | ||
} | ||
if (dataSubdomain === "Array" && typeof rule[2] === "number") { | ||
if (dataObjectKind === "Array" && typeof rule[2] === "number") { | ||
const actual = data.length; | ||
@@ -214,3 +214,3 @@ const expected = rule[2]; | ||
} | ||
if (dataSubdomain === "Array" || dataSubdomain === "Set") { | ||
if (dataObjectKind === "Array" || dataObjectKind === "Set") { | ||
let i = 0; | ||
@@ -224,3 +224,3 @@ for (const item of data){ | ||
} else { | ||
return (0, _errorsJs.throwInternalError)(`Unexpected subdomain entry ${(0, _serializeJs.stringify)(rule)}`); | ||
return (0, _errorsJs.throwInternalError)(`Unexpected objectKind entry ${(0, _serializeJs.stringify)(rule)}`); | ||
} | ||
@@ -245,3 +245,3 @@ return true; | ||
}, | ||
subdomain: checkSubdomain, | ||
objectKind: checkObjectKind, | ||
bound: _rangeJs.checkBound, | ||
@@ -248,0 +248,0 @@ requiredProps: checkRequiredProps, |
@@ -14,9 +14,4 @@ "use strict"; | ||
domainOf: ()=>domainOf, | ||
subdomainOf: ()=>subdomainOf, | ||
hasSubdomain: ()=>hasSubdomain, | ||
sizeOf: ()=>sizeOf, | ||
unitsOf: ()=>unitsOf, | ||
classNameOf: ()=>classNameOf | ||
domainDescriptions: ()=>domainDescriptions | ||
}); | ||
const _genericsTs = require("./generics.js"); | ||
const hasDomain = (data, domain)=>domainOf(data) === domain; | ||
@@ -27,43 +22,11 @@ const domainOf = (data)=>{ | ||
}; | ||
const objectSubdomains = { | ||
Array, | ||
Date, | ||
Error, | ||
Function, | ||
Map, | ||
RegExp, | ||
Set, | ||
object: Object | ||
const domainDescriptions = { | ||
bigint: "a bigint", | ||
boolean: "boolean", | ||
null: "null", | ||
number: "a number", | ||
object: "an object", | ||
string: "a string", | ||
symbol: "a symbol", | ||
undefined: "undefined" | ||
}; | ||
const subdomainOf = (data)=>{ | ||
const domain = domainOf(data); | ||
if (domain !== "object") { | ||
return domain; | ||
} | ||
if (Array.isArray(data)) { | ||
return "Array"; | ||
} | ||
// The raw result will be something like [object Date] | ||
const prototypeName = Object.prototype.toString.call(data).slice(8, -1); | ||
if ((0, _genericsTs.isKeyOf)(prototypeName, objectSubdomains)) { | ||
return data instanceof objectSubdomains[prototypeName] ? prototypeName : "object"; | ||
} | ||
if (prototypeName.endsWith("Error")) { | ||
return data instanceof Error ? "Error" : "object"; | ||
} | ||
return "object"; | ||
}; | ||
const hasSubdomain = (data, subdomain)=>subdomainOf(data) === subdomain; | ||
const sizeOf = (data)=>sizedSubdomains[subdomainOf(data)]?.(data) ?? 0; | ||
const sizedSubdomains = { | ||
number: (data)=>data, | ||
string: (data)=>data.length, | ||
Array: (data)=>data.length | ||
}; | ||
const unitsOf = (data)=>sizeUnits[subdomainOf(data)] ?? ""; | ||
const sizeUnits = { | ||
number: "", | ||
string: "characters", | ||
Array: "items" | ||
}; | ||
const classNameOf = (data)=>Object(data).constructor.name; |
@@ -19,4 +19,3 @@ "use strict"; | ||
hasKeys: ()=>hasKeys, | ||
listFrom: ()=>listFrom, | ||
collapseIfSingleton: ()=>collapseIfSingleton | ||
listFrom: ()=>listFrom | ||
}); | ||
@@ -37,2 +36,1 @@ const _domainsTs = require("./domains.js"); | ||
]; | ||
const collapseIfSingleton = (array)=>array.length === 1 ? array[0] : array; |
@@ -92,3 +92,3 @@ function _checkPrivateRedeclaration(obj, privateCollection) { | ||
createAnonymousTypeName() { | ||
return `anonymousType${++_classPrivateFieldUpdate(this, _anonymousTypeCount).value}`; | ||
return `type${++_classPrivateFieldUpdate(this, _anonymousTypeCount).value}`; | ||
} | ||
@@ -226,6 +226,6 @@ get infer() { | ||
const initializeType = (definition, opts, scope)=>{ | ||
const name = opts.name ?? scope.createAnonymousTypeName(); | ||
const name = opts.name ?? "type"; | ||
const meta = { | ||
name, | ||
id: `${scope.name}.${name}`, | ||
id: `${scope.name}.${opts.name ? name : scope.createAnonymousTypeName()}`, | ||
definition, | ||
@@ -307,3 +307,3 @@ scope, | ||
export const scope = (aliases, opts = {})=>new Scope(aliases, opts); | ||
const ts = scope({ | ||
const tsKeywords = scope({ | ||
any: [ | ||
@@ -390,4 +390,9 @@ "node", | ||
} | ||
], | ||
// TODO: Add remaining JS object types | ||
] | ||
}, { | ||
name: "ts", | ||
standard: false | ||
}); | ||
const tsKeywordsSpace = tsKeywords.compile(); | ||
const jsObjects = scope({ | ||
Function: [ | ||
@@ -397,11 +402,115 @@ "node", | ||
object: { | ||
subdomain: "Function" | ||
objectKind: "Function" | ||
} | ||
} | ||
], | ||
Array: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Array" | ||
} | ||
} | ||
], | ||
Date: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Date" | ||
} | ||
} | ||
], | ||
Error: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Error" | ||
} | ||
} | ||
], | ||
Map: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Map" | ||
} | ||
} | ||
], | ||
RegExp: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "RegExp" | ||
} | ||
} | ||
], | ||
Set: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Set" | ||
} | ||
} | ||
], | ||
Object: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Object" | ||
} | ||
} | ||
], | ||
String: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "String" | ||
} | ||
} | ||
], | ||
Number: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Number" | ||
} | ||
} | ||
], | ||
Boolean: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Boolean" | ||
} | ||
} | ||
], | ||
WeakMap: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "WeakMap" | ||
} | ||
} | ||
], | ||
WeakSet: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "WeakSet" | ||
} | ||
} | ||
], | ||
Promise: [ | ||
"node", | ||
{ | ||
object: { | ||
objectKind: "Promise" | ||
} | ||
} | ||
] | ||
}, { | ||
name: "ts", | ||
name: "jsObjects", | ||
standard: false | ||
}); | ||
const tsTypes = ts.compile(); | ||
const jsObjectsSpace = jsObjects.compile(); | ||
const validation = scope({ | ||
@@ -425,8 +534,9 @@ email: /^(.+)@(.+)\.(.+)$/, | ||
}); | ||
const validationTypes = validation.compile(); | ||
const validationSpace = validation.compile(); | ||
const standard = scope({}, { | ||
name: "standard", | ||
includes: [ | ||
tsTypes, | ||
validationTypes | ||
tsKeywordsSpace, | ||
jsObjectsSpace, | ||
validationSpace | ||
], | ||
@@ -437,3 +547,4 @@ standard: false | ||
export const scopes = { | ||
ts, | ||
tsKeywords, | ||
jsObjects, | ||
validation, | ||
@@ -443,4 +554,5 @@ standard | ||
export const spaces = { | ||
ts: tsTypes, | ||
validation: validationTypes, | ||
tsKeywords: tsKeywordsSpace, | ||
jsObjects: jsObjectsSpace, | ||
validation: validationSpace, | ||
standard: standardTypes | ||
@@ -447,0 +559,0 @@ }; |
@@ -5,9 +5,9 @@ import { domainOf, hasDomain } from "../utils/domains.js"; | ||
import { branchIntersection } from "./rules/rules.js"; | ||
export const isBranchComparison = (comparison)=>comparison?.lConditions !== undefined; | ||
export const isBranchComparison = (comparison)=>comparison?.lBranches !== undefined; | ||
export const compareBranches = (lConditions, rConditions, state)=>{ | ||
const result = { | ||
lConditions, | ||
rConditions, | ||
lSubconditionsOfR: [], | ||
rSubconditionsOfL: [], | ||
lBranches: lConditions, | ||
rBranches: rConditions, | ||
lExtendsR: [], | ||
rExtendsL: [], | ||
equalities: [], | ||
@@ -32,3 +32,3 @@ distinctIntersections: [] | ||
} else if (subresult === l) { | ||
result.lSubconditionsOfR.push(lIndex); | ||
result.lExtendsR.push(lIndex); | ||
// If l is a subtype of the current r branch, intersections | ||
@@ -40,3 +40,3 @@ // with the remaining branches of r won't lead to distinct | ||
} else if (subresult === r) { | ||
result.rSubconditionsOfL.push(rIndex); | ||
result.rExtendsL.push(rIndex); | ||
// If r is a subtype of the current l branch, it is removed | ||
@@ -43,0 +43,0 @@ // from pairsByR because future intersections won't lead to |
@@ -49,3 +49,3 @@ function _checkPrivateRedeclaration(obj, privateCollection) { | ||
domain: ({ l , r })=>`${l.join(", ")} and ${r.join(", ")}`, | ||
subdomain: ({ l , r })=>`${l} and ${r}`, | ||
objectKind: ({ l , r })=>`${l} and ${r}`, | ||
range: ({ l , r })=>`${stringifyRange(l)} and ${stringifyRange(r)}`, | ||
@@ -56,3 +56,4 @@ class: ({ l , r })=>`classes ${l.name} and ${r.name}`, | ||
leftAssignability: ({ l , r })=>`literal value ${serialize(l.value)} and ${serialize(r)}`, | ||
rightAssignability: ({ l , r })=>`literal value ${serialize(r.value)} and ${serialize(l)}` | ||
rightAssignability: ({ l , r })=>`literal value ${serialize(r.value)} and ${serialize(l)}`, | ||
union: ({ l , r })=>`branches ${serialize(l)} and branches ${serialize(r)}` | ||
}; | ||
@@ -59,0 +60,0 @@ export const stringifyRange = (range)=>"limit" in range ? `the range of exactly ${range.limit}` : range.min ? range.max ? `the range bounded by ${range.min.comparator}${range.min.limit} and ${range.max.comparator}${range.max.limit}` : `${range.min.comparator}${range.min.limit}` : range.max ? `${range.max.comparator}${range.max.limit}` : "the unbounded range"; |
import { writeUndiscriminatableMorphUnionMessage } from "../parse/string/ast.js"; | ||
import { domainOf, hasSubdomain, subdomainOf } from "../utils/domains.js"; | ||
import { domainOf } from "../utils/domains.js"; | ||
import { throwParseError } from "../utils/errors.js"; | ||
import { hasKey, isKeyOf, keysOf } from "../utils/generics.js"; | ||
import { isArray, objectKindOf } from "../utils/objectKinds.js"; | ||
import { Path } from "../utils/paths.js"; | ||
@@ -47,3 +48,3 @@ import { serializePrimitive } from "../utils/serialize.js"; | ||
domain: true, | ||
subdomain: true, | ||
objectKind: true, | ||
value: true | ||
@@ -65,3 +66,3 @@ }; | ||
for(const path in intersectionState.disjoints){ | ||
// designed to match subdomain path segments like "${number}" | ||
// designed to match objectKind path segments like "${number}" | ||
if (path.includes("${")) { | ||
@@ -181,3 +182,3 @@ continue; | ||
value: (data)=>serializeIfPrimitive(data) ?? "default", | ||
subdomain: subdomainOf, | ||
objectKind: (data)=>objectKindOf(data) ?? "default", | ||
domain: domainOf | ||
@@ -187,2 +188,2 @@ }; | ||
const branchIncludesMorph = (branch, $)=>"morph" in branch ? true : "props" in branch ? Object.values(branch.props).some((prop)=>nodeIncludesMorph(isOptional(prop) ? prop[1] : prop, $)) : false; | ||
const nodeIncludesMorph = (node, $)=>typeof node === "string" ? $.resolve(node).meta.includesMorph : Object.values(node).some((predicate)=>predicate === true ? false : hasSubdomain(predicate, "Array") ? predicate.some((branch)=>branchIncludesMorph(branch, $)) : branchIncludesMorph(predicate, $)); | ||
const nodeIncludesMorph = (node, $)=>typeof node === "string" ? $.resolve(node).meta.includesMorph : Object.values(node).some((predicate)=>predicate === true ? false : isArray(predicate) ? predicate.some((branch)=>branchIncludesMorph(branch, $)) : branchIncludesMorph(predicate, $)); |
export const functors = { | ||
Array: (node)=>({ | ||
object: { | ||
subdomain: [ | ||
objectKind: [ | ||
"Array", | ||
@@ -12,3 +12,3 @@ node | ||
object: { | ||
subdomain: [ | ||
objectKind: [ | ||
"Set", | ||
@@ -21,3 +21,3 @@ node | ||
object: { | ||
subdomain: [ | ||
objectKind: [ | ||
"Map", | ||
@@ -24,0 +24,0 @@ k, |
@@ -46,3 +46,3 @@ import { compileDisjointReasonsMessage } from "../parse/string/ast.js"; | ||
}; | ||
const hasImpliedDomain = (flatPredicate)=>flatPredicate[0] && (flatPredicate[0][0] === "subdomain" || flatPredicate[0][0] === "value"); | ||
const hasImpliedDomain = (flatPredicate)=>flatPredicate[0] && (flatPredicate[0][0] === "objectKind" || flatPredicate[0][0] === "value"); | ||
export const flattenType = (type)=>{ | ||
@@ -49,0 +49,0 @@ const ctx = { |
@@ -1,3 +0,3 @@ | ||
import { hasSubdomain } from "../utils/domains.js"; | ||
import { collapseIfSingleton, keysOf, listFrom } from "../utils/generics.js"; | ||
import { keysOf, listFrom } from "../utils/generics.js"; | ||
import { isArray } from "../utils/objectKinds.js"; | ||
import { compareBranches, isBranchComparison } from "./branches.js"; | ||
@@ -12,3 +12,3 @@ import { equality, IntersectionState, isEquality } from "./compose.js"; | ||
} | ||
if (!hasSubdomain(l, "Array") && !hasSubdomain(r, "Array")) { | ||
if (!isArray(l) && !isArray(r)) { | ||
const result = branchIntersection(emptyRulesIfTrue(l), emptyRulesIfTrue(r), context); | ||
@@ -23,6 +23,6 @@ return result === l ? l : result === r ? r : result; | ||
} | ||
if (comparison.lSubconditionsOfR.length + comparison.equalities.length === lBranches.length) { | ||
if (comparison.lExtendsR.length + comparison.equalities.length === lBranches.length) { | ||
return l; | ||
} | ||
if (comparison.rSubconditionsOfL.length + comparison.equalities.length === rBranches.length) { | ||
if (comparison.rExtendsL.length + comparison.equalities.length === rBranches.length) { | ||
return r; | ||
@@ -38,8 +38,12 @@ } | ||
} | ||
return collapseIfSingleton([ | ||
const resultBranches = [ | ||
...comparison.distinctIntersections, | ||
...comparison.equalities.map((indices)=>comparison.lConditions[indices[0]]), | ||
...comparison.lSubconditionsOfR.map((lIndex)=>comparison.lConditions[lIndex]), | ||
...comparison.rSubconditionsOfL.map((rIndex)=>comparison.rConditions[rIndex]) | ||
]); | ||
...comparison.equalities.map((indices)=>comparison.lBranches[indices[0]]), | ||
...comparison.lExtendsR.map((lIndex)=>comparison.lBranches[lIndex]), | ||
...comparison.rExtendsL.map((rIndex)=>comparison.rBranches[rIndex]) | ||
]; | ||
if (resultBranches.length === 0) { | ||
state.addDisjoint("union", comparison.lBranches, comparison.rBranches); | ||
} | ||
return resultBranches.length === 1 ? resultBranches[0] : resultBranches; | ||
}; | ||
@@ -57,6 +61,7 @@ export const predicateUnion = (domain, l, r, type)=>{ | ||
} | ||
return collapseIfSingleton([ | ||
...comparison.lConditions.filter((_, lIndex)=>!comparison.lSubconditionsOfR.includes(lIndex) && !comparison.equalities.some((indexPair)=>indexPair[0] === lIndex)), | ||
...comparison.rConditions.filter((_, rIndex)=>!comparison.rSubconditionsOfL.includes(rIndex) && !comparison.equalities.some((indexPair)=>indexPair[1] === rIndex)) | ||
]); | ||
const resultBranches = [ | ||
...comparison.lBranches.filter((_, lIndex)=>!comparison.lExtendsR.includes(lIndex) && !comparison.equalities.some((indexPair)=>indexPair[0] === lIndex)), | ||
...comparison.rBranches.filter((_, rIndex)=>!comparison.rExtendsL.includes(rIndex) && !comparison.equalities.some((indexPair)=>indexPair[1] === rIndex)) | ||
]; | ||
return resultBranches.length === 1 ? resultBranches[0] : resultBranches; | ||
}; | ||
@@ -67,3 +72,3 @@ export const flattenPredicate = (predicate, context)=>{ | ||
} | ||
return hasSubdomain(predicate, "Array") ? flattenBranches(predicate, context) : flattenBranch(predicate, context); | ||
return isArray(predicate) ? flattenBranches(predicate, context) : flattenBranch(predicate, context); | ||
}; | ||
@@ -70,0 +75,0 @@ export const isLiteralCondition = (predicate)=>typeof predicate === "object" && "value" in predicate; |
@@ -1,6 +0,5 @@ | ||
import { hasSubdomain } from "../../utils/domains.js"; | ||
import { equality } from "../compose.js"; | ||
export const collapsibleListUnion = (l, r)=>{ | ||
if (hasSubdomain(l, "Array")) { | ||
if (hasSubdomain(r, "Array")) { | ||
if (Array.isArray(l)) { | ||
if (Array.isArray(r)) { | ||
const result = listUnion(l, r); | ||
@@ -14,3 +13,3 @@ return result.length === l.length ? result.length === r.length ? equality() : l : result.length === r.length ? r : result; | ||
} | ||
if (hasSubdomain(r, "Array")) { | ||
if (Array.isArray(r)) { | ||
return r.includes(l) ? r : [ | ||
@@ -17,0 +16,0 @@ ...r, |
@@ -1,2 +0,2 @@ | ||
import { sizeOf } from "../../utils/domains.js"; | ||
import { sizeOf } from "../../utils/size.js"; | ||
import { composeIntersection, equality } from "../compose.js"; | ||
@@ -3,0 +3,0 @@ export const minComparators = { |
@@ -8,6 +8,6 @@ import { writeImplicitNeverMessage } from "../../parse/string/ast.js"; | ||
import { divisorIntersection } from "./divisor.js"; | ||
import { flattenObjectKind, objectKindIntersection } from "./objectKind.js"; | ||
import { flattenProps, propsIntersection } from "./props.js"; | ||
import { flattenRange, rangeIntersection } from "./range.js"; | ||
import { getRegex, regexIntersection } from "./regex.js"; | ||
import { flattenSubdomain, subdomainIntersection } from "./subdomain.js"; | ||
const rulesOf = (branch)=>branch.input ?? branch; | ||
@@ -44,3 +44,3 @@ export const branchIntersection = (l, r, state)=>{ | ||
export const narrowableRulesIntersection = composeKeyedIntersection({ | ||
subdomain: subdomainIntersection, | ||
objectKind: objectKindIntersection, | ||
divisor: divisorIntersection, | ||
@@ -56,3 +56,3 @@ regex: regexIntersection, | ||
const ruleFlatteners = { | ||
subdomain: flattenSubdomain, | ||
objectKind: flattenObjectKind, | ||
regex: (entries, rule)=>{ | ||
@@ -101,3 +101,3 @@ for (const source of listFrom(rule)){ | ||
branches: 0, | ||
subdomain: 0, | ||
objectKind: 0, | ||
switch: 0, | ||
@@ -104,0 +104,0 @@ alias: 0, |
import { isType } from "../main.js"; | ||
import { subdomainOf } from "../utils/domains.js"; | ||
import { domainOf } from "../utils/domains.js"; | ||
import { throwParseError } from "../utils/errors.js"; | ||
import { objectKindOf } from "../utils/objectKinds.js"; | ||
import { stringify } from "../utils/serialize.js"; | ||
import { parseRecord } from "./record.js"; | ||
@@ -8,8 +10,26 @@ import { parseString } from "./string/string.js"; | ||
export const parseDefinition = (def, ctx)=>{ | ||
const subdomain = subdomainOf(def); | ||
return subdomain === "string" ? parseString(def, ctx) : subdomain === "object" ? parseRecord(def, ctx) : subdomain === "Array" ? parseTuple(def, ctx) : subdomain === "RegExp" ? { | ||
string: { | ||
regex: def.source | ||
} | ||
} : isType(def) ? def.node : throwParseError(writeBadDefinitionTypeMessage(subdomain)); | ||
const domain = domainOf(def); | ||
if (domain === "string") { | ||
return parseString(def, ctx); | ||
} | ||
if (domain !== "object") { | ||
return throwParseError(writeBadDefinitionTypeMessage(domain)); | ||
} | ||
const objectKind = objectKindOf(def); | ||
switch(objectKind){ | ||
case "Object": | ||
return parseRecord(def, ctx); | ||
case "Array": | ||
return parseTuple(def, ctx); | ||
case "RegExp": | ||
return { | ||
string: { | ||
regex: def.source | ||
} | ||
}; | ||
case "Function": | ||
return isType(def) ? def.node : throwParseError(writeBadDefinitionTypeMessage("Function")); | ||
default: | ||
return throwParseError(writeBadDefinitionTypeMessage(objectKind ?? stringify(def))); | ||
} | ||
}; | ||
@@ -16,0 +36,0 @@ export const as = Symbol("as"); |
@@ -57,3 +57,3 @@ import { stringifyRange } from "../../../../nodes/compose.js"; | ||
} | ||
return listFrom(resolution.object).every((branch)=>hasKey(branch, "subdomain") && (branch.subdomain === "Array" || branch.subdomain[0] === "Array")); | ||
return listFrom(resolution.object).every((branch)=>hasKey(branch, "objectKind") && (branch.objectKind === "Array" || branch.objectKind[0] === "Array")); | ||
default: | ||
@@ -60,0 +60,0 @@ return false; |
@@ -1,3 +0,3 @@ | ||
import { hasSubdomain } from "../../utils/domains.js"; | ||
import { throwInternalError, throwParseError } from "../../utils/errors.js"; | ||
import { isArray } from "../../utils/objectKinds.js"; | ||
import { stringify } from "../../utils/serialize.js"; | ||
@@ -22,3 +22,3 @@ import { parseDefinition } from "../definition.js"; | ||
} else if (typeof predicate === "object") { | ||
result[domain] = hasSubdomain(predicate, "Array") ? predicate.map((branch)=>applyMorph(branch, morph)) : applyMorph(predicate, morph); | ||
result[domain] = isArray(predicate) ? predicate.map((branch)=>applyMorph(branch, morph)) : applyMorph(predicate, morph); | ||
} else { | ||
@@ -25,0 +25,0 @@ throwInternalError(`Unexpected predicate value for domain '${domain}': ${stringify(predicate)}`); |
@@ -25,3 +25,3 @@ import { functors } from "../../nodes/functors.js"; | ||
object: { | ||
subdomain: "Array", | ||
objectKind: "Array", | ||
props, | ||
@@ -28,0 +28,0 @@ range: { |
var _definitions_code, _definitions_code1, _definitions_code2, _clausesByPath, _pathKey; | ||
import { Scanner } from "../parse/string/shift/scanner.js"; | ||
import { classNameOf, domainOf, sizeOf, subdomainOf, unitsOf } from "../utils/domains.js"; | ||
import { domainDescriptions, domainOf } from "../utils/domains.js"; | ||
import { keysOf } from "../utils/generics.js"; | ||
import { objectKindDescriptions, objectKindOf } from "../utils/objectKinds.js"; | ||
import { Path } from "../utils/paths.js"; | ||
@@ -79,10 +80,10 @@ import { stringify } from "../utils/serialize.js"; | ||
const capitalize = (s)=>s[0].toUpperCase() + s.slice(1); | ||
export const describeSubdomains = (subdomains)=>{ | ||
if (subdomains.length === 1) { | ||
return subdomainDescriptions[subdomains[0]]; | ||
export const describeDomains = (domains)=>{ | ||
if (domains.length === 1) { | ||
return domainDescriptions[domains[0]]; | ||
} | ||
if (subdomains.length === 0) { | ||
if (domains.length === 0) { | ||
return "never"; | ||
} | ||
return describeBranches(subdomains.map((subdomain)=>subdomainDescriptions[subdomain])); | ||
return describeBranches(domains.map((objectKind)=>domainDescriptions[objectKind])); | ||
}; | ||
@@ -100,19 +101,2 @@ export const describeBranches = (descriptions)=>{ | ||
}; | ||
/** Each Subdomain's completion for the phrase "Must be _____" */ export const subdomainDescriptions = { | ||
bigint: "a bigint", | ||
boolean: "boolean", | ||
null: "null", | ||
number: "a number", | ||
object: "an object", | ||
string: "a string", | ||
symbol: "a symbol", | ||
undefined: "undefined", | ||
Array: "an array", | ||
Function: "a function", | ||
Date: "a Date", | ||
RegExp: "a RegExp", | ||
Error: "an Error", | ||
Map: "a Map", | ||
Set: "a Set" | ||
}; | ||
export class DataWrapper { | ||
@@ -125,14 +109,13 @@ toString() { | ||
} | ||
// TODO: object kind? | ||
get subdomain() { | ||
return subdomainOf(this.value); | ||
get objectKind() { | ||
return objectKindOf(this.value) ?? "non-object"; | ||
} | ||
get size() { | ||
return sizeOf(this.value); | ||
return typeof this.value === "string" || Array.isArray(this.value) ? this.value.length : typeof this.value === "number" ? this.value : 0; | ||
} | ||
get units() { | ||
return unitsOf(this.value); | ||
return typeof this.value === "string" ? "characters" : Array.isArray(this.value) ? "items" : ""; | ||
} | ||
get className() { | ||
return classNameOf(this.value); | ||
return Object(this.value).constructor.name; | ||
} | ||
@@ -164,9 +147,13 @@ constructor(value){ | ||
domain: { | ||
mustBe: (domain)=>subdomainDescriptions[domain], | ||
mustBe: (domain)=>domainDescriptions[domain], | ||
was: (data)=>data.domain | ||
}, | ||
domainBranches: { | ||
mustBe: (domains)=>describeSubdomains(domains), | ||
mustBe: (domains)=>describeDomains(domains), | ||
was: (data)=>data.domain | ||
}, | ||
objectKind: { | ||
mustBe: (kind)=>objectKindDescriptions[kind], | ||
was: (data)=>data.objectKind | ||
}, | ||
missing: { | ||
@@ -173,0 +160,0 @@ mustBe: ()=>"defined", |
@@ -47,5 +47,6 @@ function _checkPrivateRedeclaration(obj, privateCollection) { | ||
import { precedenceMap } from "../nodes/rules/rules.js"; | ||
import { domainOf, hasDomain, subdomainOf } from "../utils/domains.js"; | ||
import { domainOf, hasDomain } from "../utils/domains.js"; | ||
import { throwInternalError } from "../utils/errors.js"; | ||
import { hasKey, keysOf } from "../utils/generics.js"; | ||
import { objectKindOf } from "../utils/objectKinds.js"; | ||
import { getPath, Path } from "../utils/paths.js"; | ||
@@ -161,3 +162,2 @@ import { deserializePrimitive, stringify } from "../utils/serialize.js"; | ||
if (propKind !== "optionalProps") { | ||
// TODO: update | ||
state.problems.add("missing", undefined, undefined); | ||
@@ -174,14 +174,14 @@ } | ||
const checkOptionalProps = createPropChecker("optionalProps"); | ||
export const checkSubdomain = (data, rule, state)=>{ | ||
const dataSubdomain = subdomainOf(data); | ||
export const checkObjectKind = (data, rule, state)=>{ | ||
const dataObjectKind = objectKindOf(data); | ||
if (typeof rule === "string") { | ||
if (dataSubdomain !== rule) { | ||
return state.problems.add("domain", data, rule); | ||
if (dataObjectKind !== rule) { | ||
return state.problems.add("objectKind", data, rule); | ||
} | ||
return; | ||
} | ||
if (dataSubdomain !== rule[0]) { | ||
return state.problems.add("domain", data, rule[0]); | ||
if (dataObjectKind !== rule[0]) { | ||
return state.problems.add("objectKind", data, rule[0]); | ||
} | ||
if (dataSubdomain === "Array" && typeof rule[2] === "number") { | ||
if (dataObjectKind === "Array" && typeof rule[2] === "number") { | ||
const actual = data.length; | ||
@@ -197,3 +197,3 @@ const expected = rule[2]; | ||
} | ||
if (dataSubdomain === "Array" || dataSubdomain === "Set") { | ||
if (dataObjectKind === "Array" || dataObjectKind === "Set") { | ||
let i = 0; | ||
@@ -207,3 +207,3 @@ for (const item of data){ | ||
} else { | ||
return throwInternalError(`Unexpected subdomain entry ${stringify(rule)}`); | ||
return throwInternalError(`Unexpected objectKind entry ${stringify(rule)}`); | ||
} | ||
@@ -228,3 +228,3 @@ return true; | ||
}, | ||
subdomain: checkSubdomain, | ||
objectKind: checkObjectKind, | ||
bound: checkBound, | ||
@@ -231,0 +231,0 @@ requiredProps: checkRequiredProps, |
@@ -1,2 +0,1 @@ | ||
import { isKeyOf } from "./generics.js"; | ||
export const hasDomain = (data, domain)=>domainOf(data) === domain; | ||
@@ -7,43 +6,11 @@ export const domainOf = (data)=>{ | ||
}; | ||
const objectSubdomains = { | ||
Array, | ||
Date, | ||
Error, | ||
Function, | ||
Map, | ||
RegExp, | ||
Set, | ||
object: Object | ||
/** Each domain's completion for the phrase "Must be _____" */ export const domainDescriptions = { | ||
bigint: "a bigint", | ||
boolean: "boolean", | ||
null: "null", | ||
number: "a number", | ||
object: "an object", | ||
string: "a string", | ||
symbol: "a symbol", | ||
undefined: "undefined" | ||
}; | ||
export const subdomainOf = (data)=>{ | ||
const domain = domainOf(data); | ||
if (domain !== "object") { | ||
return domain; | ||
} | ||
if (Array.isArray(data)) { | ||
return "Array"; | ||
} | ||
// The raw result will be something like [object Date] | ||
const prototypeName = Object.prototype.toString.call(data).slice(8, -1); | ||
if (isKeyOf(prototypeName, objectSubdomains)) { | ||
return data instanceof objectSubdomains[prototypeName] ? prototypeName : "object"; | ||
} | ||
if (prototypeName.endsWith("Error")) { | ||
return data instanceof Error ? "Error" : "object"; | ||
} | ||
return "object"; | ||
}; | ||
export const hasSubdomain = (data, subdomain)=>subdomainOf(data) === subdomain; | ||
export const sizeOf = (data)=>sizedSubdomains[subdomainOf(data)]?.(data) ?? 0; | ||
const sizedSubdomains = { | ||
number: (data)=>data, | ||
string: (data)=>data.length, | ||
Array: (data)=>data.length | ||
}; | ||
export const unitsOf = (data)=>sizeUnits[subdomainOf(data)] ?? ""; | ||
const sizeUnits = { | ||
number: "", | ||
string: "characters", | ||
Array: "items" | ||
}; | ||
export const classNameOf = (data)=>Object(data).constructor.name; |
@@ -15,2 +15,1 @@ import { hasDomain } from "./domains.js"; | ||
]; | ||
export const collapseIfSingleton = (array)=>array.length === 1 ? array[0] : array; |
@@ -6,2 +6,3 @@ import type { ResolvedNode, TraversalNode, TypeNode } from "./nodes/node.js"; | ||
import type { defer, Dict, error, evaluateObject, isAny, List, nominal } from "./utils/generics.js"; | ||
import type { BuiltinClass, InferredObjectKinds } from "./utils/objectKinds.js"; | ||
import type { stringifyUnion } from "./utils/unionToTuple.js"; | ||
@@ -103,3 +104,3 @@ type ScopeParser = { | ||
export declare const scopes: { | ||
ts: Scope<[{ | ||
tsKeywords: Scope<[{ | ||
any: any; | ||
@@ -119,4 +120,21 @@ bigint: bigint; | ||
undefined: undefined; | ||
Function: Function; | ||
}, {}, false]>; | ||
jsObjects: Scope<[{ | ||
Function: (...args: any[]) => unknown; | ||
Array: unknown[]; | ||
Date: Date; | ||
Error: Error; | ||
Map: Map<unknown, unknown>; | ||
RegExp: RegExp; | ||
Set: Set<unknown>; | ||
Object: { | ||
[x: string]: unknown; | ||
}; | ||
String: String; | ||
Number: Number; | ||
Boolean: Boolean; | ||
WeakMap: WeakMap<object, unknown>; | ||
WeakSet: WeakSet<object>; | ||
Promise: Promise<unknown>; | ||
}, {}, false]>; | ||
validation: Scope<[{ | ||
@@ -145,3 +163,18 @@ email: string; | ||
undefined: undefined; | ||
Function: Function; | ||
Function: (...args: any[]) => unknown; | ||
Array: unknown[]; | ||
Date: Date; | ||
Error: Error; | ||
Map: Map<unknown, unknown>; | ||
RegExp: RegExp; | ||
Set: Set<unknown>; | ||
Object: { | ||
[x: string]: unknown; | ||
}; | ||
String: String; | ||
Number: Number; | ||
Boolean: Boolean; | ||
WeakMap: WeakMap<object, unknown>; | ||
WeakSet: WeakSet<object>; | ||
Promise: Promise<unknown>; | ||
email: string; | ||
@@ -156,3 +189,3 @@ alphanumeric: string; | ||
export declare const spaces: { | ||
ts: Space<{ | ||
tsKeywords: Space<{ | ||
any: any; | ||
@@ -172,4 +205,21 @@ bigint: bigint; | ||
undefined: undefined; | ||
Function: Function; | ||
}>; | ||
jsObjects: Space<{ | ||
Function: (...args: any[]) => unknown; | ||
Array: unknown[]; | ||
Date: Date; | ||
Error: Error; | ||
Map: Map<unknown, unknown>; | ||
RegExp: RegExp; | ||
Set: Set<unknown>; | ||
Object: { | ||
[x: string]: unknown; | ||
}; | ||
String: String; | ||
Number: Number; | ||
Boolean: Boolean; | ||
WeakMap: WeakMap<object, unknown>; | ||
WeakSet: WeakSet<object>; | ||
Promise: Promise<unknown>; | ||
}>; | ||
validation: Space<{ | ||
@@ -198,3 +248,18 @@ email: string; | ||
undefined: undefined; | ||
Function: Function; | ||
Function: (...args: any[]) => unknown; | ||
Array: unknown[]; | ||
Date: Date; | ||
Error: Error; | ||
Map: Map<unknown, unknown>; | ||
RegExp: RegExp; | ||
Set: Set<unknown>; | ||
Object: { | ||
[x: string]: unknown; | ||
}; | ||
String: String; | ||
Number: Number; | ||
Boolean: Boolean; | ||
WeakMap: WeakMap<object, unknown>; | ||
WeakSet: WeakSet<object>; | ||
Promise: Promise<unknown>; | ||
email: string; | ||
@@ -229,4 +294,3 @@ alphanumeric: string; | ||
undefined: undefined; | ||
Function: Function; | ||
}; | ||
} & InferredObjectKinds; | ||
export declare const type: TypeParser<PrecompiledDefaults>; | ||
@@ -262,5 +326,5 @@ export declare const writeDuplicateAliasMessage: <name_1 extends string>(name: name_1) => `Alias '${name_1}' is already defined`; | ||
export type asOut<t> = asIo<t, "out">; | ||
type asIo<t, io extends "in" | "out"> = t extends ParsedMorph<infer i, infer o> ? io extends "in" ? i : o : t extends object ? t extends Function ? t : { | ||
type asIo<t, io extends "in" | "out"> = t extends ParsedMorph<infer i, infer o> ? io extends "in" ? i : o : t extends object ? t extends Function | BuiltinClass ? t : { | ||
[k in keyof t]: asIo<t[k], io>; | ||
} : t; | ||
export {}; |
@@ -7,6 +7,6 @@ import type { List } from "../utils/generics.js"; | ||
export type BranchesComparison = { | ||
lConditions: Branches; | ||
rConditions: Branches; | ||
lSubconditionsOfR: number[]; | ||
rSubconditionsOfL: number[]; | ||
lBranches: Branches; | ||
rBranches: Branches; | ||
lExtendsR: number[]; | ||
rExtendsL: number[]; | ||
equalities: [lIndex: number, rIndex: number][]; | ||
@@ -13,0 +13,0 @@ distinctIntersections: Branches; |
import type { Type } from "../main.js"; | ||
import type { Domain, Subdomain } from "../utils/domains.js"; | ||
import type { Domain } from "../utils/domains.js"; | ||
import type { constructor, Dict, extend } from "../utils/generics.js"; | ||
import type { DefaultObjectKind } from "../utils/objectKinds.js"; | ||
import { Path } from "../utils/paths.js"; | ||
import type { Branches } from "./branches.js"; | ||
import type { Range } from "./rules/range.js"; | ||
@@ -20,5 +22,5 @@ import type { LiteralRules, NarrowableRules } from "./rules/rules.js"; | ||
}; | ||
subdomain: { | ||
l: Subdomain; | ||
r: Subdomain; | ||
objectKind: { | ||
l: DefaultObjectKind; | ||
r: DefaultObjectKind; | ||
}; | ||
@@ -49,6 +51,10 @@ range: { | ||
}; | ||
union: { | ||
l: Branches; | ||
r: Branches; | ||
}; | ||
}>; | ||
export declare const disjointDescriptionWriters: { | ||
domain: ({ l, r }: DisjointContext<"domain">) => string; | ||
subdomain: ({ l, r }: DisjointContext<"subdomain">) => string; | ||
objectKind: ({ l, r }: DisjointContext<"objectKind">) => string; | ||
range: ({ l, r }: DisjointContext<"range">) => string; | ||
@@ -60,2 +66,3 @@ class: ({ l, r }: DisjointContext<"class">) => string; | ||
rightAssignability: ({ l, r }: DisjointContext<"rightAssignability">) => string; | ||
union: ({ l, r }: DisjointContext<"union">) => string; | ||
}; | ||
@@ -62,0 +69,0 @@ export declare const stringifyRange: (range: Range) => string; |
@@ -1,4 +0,5 @@ | ||
import type { Domain, Subdomain } from "../utils/domains.js"; | ||
import type { Domain } from "../utils/domains.js"; | ||
import type { evaluate } from "../utils/generics.js"; | ||
import type { NumberLiteral } from "../utils/numericLiterals.js"; | ||
import type { DefaultObjectKind } from "../utils/objectKinds.js"; | ||
import { Path } from "../utils/paths.js"; | ||
@@ -20,3 +21,3 @@ import type { SerializedPrimitive } from "../utils/serialize.js"; | ||
domain: Domain; | ||
subdomain: Subdomain; | ||
objectKind: DefaultObjectKind; | ||
value: unknown; | ||
@@ -23,0 +24,0 @@ }; |
import type { inferTerminal } from "../parse/string/ast.js"; | ||
import type { Out } from "../parse/tuple/morph.js"; | ||
import type { Domain, inferDomain, inferSubdomain, Subdomain } from "../utils/domains.js"; | ||
import type { evaluate, HomogenousTuple, List, returnOf } from "../utils/generics.js"; | ||
import type { Domain, inferDomain } from "../utils/domains.js"; | ||
import type { evaluate, evaluateObject, HomogenousTuple, List, returnOf } from "../utils/generics.js"; | ||
import type { BuiltinClass, DefaultObjectKind, inferObjectKind } from "../utils/objectKinds.js"; | ||
import type { ResolvedNode, TypeNode } from "./node.js"; | ||
import type { Predicate } from "./predicate.js"; | ||
import type { ObjectKindRule } from "./rules/objectKind.js"; | ||
import type { OptionalProp, PropsRule } from "./rules/props.js"; | ||
import type { Bound, Range } from "./rules/range.js"; | ||
import type { LiteralRules, MorphBranch, NarrowableRules } from "./rules/rules.js"; | ||
import type { SubdomainRule } from "./rules/subdomain.js"; | ||
export type inferNode<node extends TypeNode<$>, $ = {}> = node extends string ? inferTerminal<node, $> : node extends ResolvedNode<$> ? inferResolution<node, $> : never; | ||
export type inferResolution<node extends ResolvedNode<$>, $> = evaluate<{ | ||
export type inferNode<node extends TypeNode<$>, $ = {}> = node extends string ? inferTerminal<node, $> : node extends ResolvedNode<$> ? inferResolution<node, $> extends infer result ? result extends BuiltinClass ? result : evaluate<result> : never : never; | ||
export type inferResolution<node extends ResolvedNode<$>, $> = { | ||
[domain in keyof node]: inferPredicate<domain, node[domain], $>; | ||
}[keyof node]>; | ||
}[keyof node]; | ||
type inferPredicate<domain extends Domain, predicate extends Predicate, $> = predicate extends true ? inferDomain<domain> : inferBranch<domain, branchFrom<predicate>, $>; | ||
@@ -20,4 +21,4 @@ type branchFrom<predicate extends Predicate> = predicate extends List ? predicate[number] : predicate; | ||
type inferRules<domain extends Domain, branch, $> = branch extends LiteralRules ? branch["value"] : domain extends "object" ? branch extends NarrowableRules ? inferObjectRules<branch, $> : object : inferDomain<domain>; | ||
type inferObjectRules<rules extends NarrowableRules, $> = evaluate<(rules["subdomain"] extends SubdomainRule ? inferSubdomainRule<rules["subdomain"], rules["range"], $> : unknown) & (rules["props"] extends PropsRule ? inferProps<rules["props"], $> : unknown)>; | ||
type inferSubdomainRule<rule extends SubdomainRule, possibleRange extends Range | undefined, $> = rule extends Subdomain ? inferSubdomain<rule> : rule extends readonly ["Array", infer item extends TypeNode<$>] ? possibleRange extends Bound<"=="> ? HomogenousTuple<inferNode<item, $>, possibleRange["limit"]> : inferNode<item, $>[] : rule extends readonly ["Set", infer item extends TypeNode<$>] ? Set<inferNode<item, $>> : rule extends readonly [ | ||
type inferObjectRules<rules extends NarrowableRules, $> = rules["objectKind"] extends ObjectKindRule ? rules["props"] extends PropsRule ? inferProps<rules["props"], $> & inferObjectKindRule<rules["objectKind"], rules["range"], $> : inferObjectKindRule<rules["objectKind"], rules["range"], $> : rules["props"] extends PropsRule ? inferProps<rules["props"], $> : unknown; | ||
type inferObjectKindRule<rule extends ObjectKindRule, possibleRange extends Range | undefined, $> = rule extends DefaultObjectKind ? inferObjectKind<rule> : rule extends readonly ["Array", infer item extends TypeNode<$>] ? possibleRange extends Bound<"=="> ? HomogenousTuple<inferNode<item, $>, possibleRange["limit"]> : inferNode<item, $>[] : rule extends readonly ["Set", infer item extends TypeNode<$>] ? Set<inferNode<item, $>> : rule extends readonly [ | ||
"Map", | ||
@@ -27,7 +28,7 @@ infer k extends TypeNode<$>, | ||
] ? Map<inferNode<k, $>, inferNode<v, $>> : never; | ||
type inferProps<props extends PropsRule, $> = { | ||
type inferProps<props extends PropsRule, $> = evaluateObject<{ | ||
[k in requiredKeyOf<props>]: props[k] extends TypeNode<$> ? inferNode<props[k], $> : never; | ||
} & { | ||
[k in optionalKeyOf<props>]?: props[k] extends OptionalProp<$> ? inferNode<props[k][1], $> : never; | ||
}; | ||
}>; | ||
type optionalKeyOf<props extends PropsRule> = { | ||
@@ -34,0 +35,0 @@ [k in keyof props]: props[k] extends OptionalProp ? k : never; |
@@ -19,3 +19,3 @@ import type { Type } from "../main.js"; | ||
export declare const predicateUnion: (domain: Domain, l: Predicate, r: Predicate, type: Type) => true | { | ||
readonly subdomain?: import("./rules/subdomain.js").SubdomainRule<Dict>; | ||
readonly objectKind?: import("./rules/objectKind.js").ObjectKindRule<Dict>; | ||
readonly regex?: CollapsibleList<string>; | ||
@@ -45,3 +45,3 @@ readonly divisor?: number; | ||
morph: CollapsibleList<Morph>; | ||
readonly subdomain?: undefined; | ||
readonly objectKind?: undefined; | ||
readonly regex?: undefined; | ||
@@ -48,0 +48,0 @@ readonly divisor?: undefined; |
@@ -32,3 +32,3 @@ import type { Scanner } from "../../parse/string/shift/scanner.js"; | ||
export declare const flattenRange: FlattenAndPushRule<Range>; | ||
export declare const checkBound: (data: import("../../utils/domains.js").SizedData, bound: FlatBound, state: import("../../traverse/traverse.js").TraversalState) => void; | ||
export declare const checkBound: (data: import("../../utils/size.js").SizedData, bound: FlatBound, state: import("../../traverse/traverse.js").TraversalState) => void; | ||
export declare const compareStrictness: (kind: "min" | "max", l: Bound | undefined, r: Bound | undefined) => "=" | "r" | "l"; |
@@ -7,7 +7,7 @@ import type { Morph } from "../../parse/tuple/morph.js"; | ||
import type { FlattenContext, TraversalEntry } from "../node.js"; | ||
import type { ObjectKindRule, TraversalObjectKindRule } from "./objectKind.js"; | ||
import type { PropsRule, TraversalOptionalProps, TraversalRequiredProps } from "./props.js"; | ||
import type { FlatBound, Range } from "./range.js"; | ||
import type { SubdomainRule, TraversalSubdomainRule } from "./subdomain.js"; | ||
export type NarrowableRules<$ = Dict> = { | ||
readonly subdomain?: SubdomainRule<$>; | ||
readonly objectKind?: ObjectKindRule<$>; | ||
readonly regex?: CollapsibleList<string>; | ||
@@ -32,5 +32,5 @@ readonly divisor?: number; | ||
type FlatMorphedBranch = [...rules: FlatRules, morph: MorphEntry]; | ||
export type RuleEntry = ["subdomain", TraversalSubdomainRule] | ["regex", RegExp] | ["divisor", number] | ["bound", FlatBound] | ["class", constructor] | TraversalRequiredProps | TraversalOptionalProps | ["narrow", Narrow] | ["value", unknown]; | ||
export type RuleEntry = ["objectKind", TraversalObjectKindRule] | ["regex", RegExp] | ["divisor", number] | ["bound", FlatBound] | ["class", constructor] | TraversalRequiredProps | TraversalOptionalProps | ["narrow", Narrow] | ["value", unknown]; | ||
export type MorphEntry = ["morph", CollapsibleList<Morph>]; | ||
export type Rules<domain extends Domain = Domain, $ = Dict> = Domain extends domain ? NarrowableRules | LiteralRules : domain extends "object" ? defineRuleSet<domain, "subdomain" | "props" | "range" | "narrow" | "class", $> : domain extends "string" ? defineRuleSet<domain, "regex" | "range" | "narrow", $> : domain extends "number" ? defineRuleSet<domain, "divisor" | "range" | "narrow", $> : defineRuleSet<domain, "narrow", $>; | ||
export type Rules<domain extends Domain = Domain, $ = Dict> = Domain extends domain ? NarrowableRules | LiteralRules : domain extends "object" ? defineRuleSet<domain, "objectKind" | "props" | "range" | "narrow" | "class", $> : domain extends "string" ? defineRuleSet<domain, "regex" | "range" | "narrow", $> : domain extends "number" ? defineRuleSet<domain, "divisor" | "range" | "narrow", $> : defineRuleSet<domain, "narrow", $>; | ||
type defineRuleSet<domain extends Domain, keys extends keyof NarrowableRules, $> = Pick<NarrowableRules<$>, keys> | LiteralRules<domain>; | ||
@@ -37,0 +37,0 @@ export declare const branchIntersection: Intersector<Branch>; |
import type { Type } from "../main.js"; | ||
import type { TypeNode } from "../nodes/node.js"; | ||
import type { Primitive, Subdomain } from "../utils/domains.js"; | ||
import { subdomainOf } from "../utils/domains.js"; | ||
import type { Primitive } from "../utils/domains.js"; | ||
import { domainOf } from "../utils/domains.js"; | ||
import type { Dict, evaluateObject, isAny, isUnknown, List } from "../utils/generics.js"; | ||
import { objectKindOf } from "../utils/objectKinds.js"; | ||
import type { Path } from "../utils/paths.js"; | ||
@@ -16,3 +17,3 @@ import type { inferRecord } from "./record.js"; | ||
export type inferDefinition<def, $> = isAny<def> extends true ? never : def extends inferred<infer t> ? t : def extends string ? inferString<def, $> : def extends List ? inferTuple<def, $> : def extends RegExp ? string : def extends Dict ? inferRecord<def, $> : never; | ||
export type validateDefinition<def, $> = def extends Terminal ? def : def extends string ? validateString<def, $> : def extends TupleExpression ? validateTupleExpression<def, $> : def extends BadDefinitionType ? writeBadDefinitionTypeMessage<subdomainOf<def>> : isUnknown<def> extends true ? unknownDefinitionMessage : evaluateObject<{ | ||
export type validateDefinition<def, $> = def extends Terminal ? def : def extends string ? validateString<def, $> : def extends TupleExpression ? validateTupleExpression<def, $> : def extends BadDefinitionType ? writeBadDefinitionTypeMessage<objectKindOf<def> extends string ? objectKindOf<def> : domainOf<def>> : isUnknown<def> extends true ? unknownDefinitionMessage : evaluateObject<{ | ||
[k in keyof def]: validateDefinition<def[k], $>; | ||
@@ -28,4 +29,4 @@ }>; | ||
type BadDefinitionType = Exclude<Primitive, string> | Function; | ||
export declare const writeBadDefinitionTypeMessage: <actual extends Subdomain>(actual: actual) => `Type definitions must be strings or objects (was ${actual})`; | ||
type writeBadDefinitionTypeMessage<actual extends Subdomain> = `Type definitions must be strings or objects (was ${actual})`; | ||
export declare const writeBadDefinitionTypeMessage: <actual extends string>(actual: actual) => `Type definitions must be strings or objects (was ${actual})`; | ||
type writeBadDefinitionTypeMessage<actual extends string> = `Type definitions must be strings or objects (was ${actual})`; | ||
export {}; |
import type { asIn, resolve } from "../../main.js"; | ||
import type { DisjointsByPath } from "../../nodes/compose.js"; | ||
import type { SizedData, subdomainOf } from "../../utils/domains.js"; | ||
import type { domainOf } from "../../utils/domains.js"; | ||
import type { asConst, castOnError, Dict, equals, error, evaluate, evaluateObject, extractValues, isAny, List, Literalable, RegexLiteral, requiredKeyOf, stringKeyOf, tryCatch } from "../../utils/generics.js"; | ||
import type { objectKindOf } from "../../utils/objectKinds.js"; | ||
import type { Path, pathToString } from "../../utils/paths.js"; | ||
import type { SizedData } from "../../utils/size.js"; | ||
import type { Out, ParsedMorph } from "../tuple/morph.js"; | ||
@@ -22,3 +24,3 @@ import type { StringLiteral } from "./shift/operand/enclosed.js"; | ||
type discriminatable<l, r> = discriminatableRecurse<l, r, []> extends never ? false : true; | ||
type discriminatableRecurse<l, r, path extends string[]> = path["length"] extends 10 ? never : l & r extends never ? path : subdomainOf<l> & subdomainOf<r> extends never ? path : [subdomainOf<l>, subdomainOf<r>] extends ["object", "object"] ? extractValues<{ | ||
type discriminatableRecurse<l, r, path extends string[]> = path["length"] extends 10 ? never : l & r extends never ? path : domainOf<l> & domainOf<r> extends never ? path : objectKindOf<l> & objectKindOf<r> extends never ? path : [objectKindOf<l>, objectKindOf<r>] extends ["Object", "Object"] ? extractValues<{ | ||
[k in requiredKeyOf<l>]: k extends requiredKeyOf<r> ? discriminatableRecurse<l[k], r[k], [...path, k & string]> : never; | ||
@@ -25,0 +27,0 @@ }, string[]> : never; |
@@ -10,3 +10,3 @@ import type { MinComparator } from "../../../nodes/rules/range.js"; | ||
export type writeUnpairableComparatorMessage<comparator extends Scanner.Comparator> = `Left-bounded expressions must specify their limits using < or <= (was ${comparator})`; | ||
export declare const writeUnpairableComparatorMessage: <comparator extends ">" | "<" | ">=" | "<=" | "==">(comparator: comparator) => `Left-bounded expressions must specify their limits using < or <= (was ${comparator})`; | ||
export declare const writeUnpairableComparatorMessage: <comparator extends "==" | ">" | "<" | ">=" | "<=">(comparator: comparator) => `Left-bounded expressions must specify their limits using < or <= (was ${comparator})`; | ||
export declare const writeMultipleLeftBoundsMessage: <openLimit extends number, openComparator extends ">" | ">=", limit extends number, comparator extends ">" | ">=">(openLimit: openLimit, openComparator: openComparator, limit: limit, comparator: comparator) => `An expression may have at most one left bound (parsed ${openLimit}${{ | ||
@@ -13,0 +13,0 @@ readonly "<": ">"; |
@@ -16,3 +16,3 @@ import type { MaxComparator, Range } from "../../../../nodes/rules/range.js"; | ||
export type parseRightBound<s extends StaticState, comparator extends Scanner.Comparator, unscanned extends string> = Scanner.shiftUntilNextTerminator<unscanned> extends Scanner.shiftResult<infer scanned, infer nextUnscanned> ? tryParseWellFormedNumber<scanned, writeInvalidLimitMessage<comparator, scanned>> extends infer limit ? limit extends number ? s["branches"]["range"] extends {} ? comparator extends MaxComparator ? state.reduceRange<s, s["branches"]["range"]["limit"], s["branches"]["range"]["comparator"], comparator, limit, nextUnscanned> : error<writeUnpairableComparatorMessage<comparator>> : state.reduceSingleBound<s, comparator, limit, nextUnscanned> : error<limit & string> : never : never; | ||
export declare const writeInvalidLimitMessage: <comparator extends ">" | "<" | ">=" | "<=" | "==", limit extends string>(comparator: comparator, limit: limit) => `Comparator ${comparator} must be followed by a number literal (was '${limit}')`; | ||
export declare const writeInvalidLimitMessage: <comparator extends "==" | ">" | "<" | ">=" | "<=", limit extends string>(comparator: comparator, limit: limit) => `Comparator ${comparator} must be followed by a number literal (was '${limit}')`; | ||
export type writeInvalidLimitMessage<comparator extends Scanner.Comparator, limit extends string> = `Comparator ${comparator} must be followed by a number literal (was '${limit}')`; | ||
@@ -19,0 +19,0 @@ export declare const writeEmptyRangeMessage: (range: Range) => string; |
import type { FlatBound } from "../nodes/rules/range.js"; | ||
import type { Subdomain } from "../utils/domains.js"; | ||
import { domainOf, subdomainOf } from "../utils/domains.js"; | ||
import type { Domain } from "../utils/domains.js"; | ||
import { domainOf } from "../utils/domains.js"; | ||
import type { constructor, evaluate, evaluateObject, instanceOf } from "../utils/generics.js"; | ||
import type { DefaultObjectKind } from "../utils/objectKinds.js"; | ||
import { objectKindOf } from "../utils/objectKinds.js"; | ||
import { Path } from "../utils/paths.js"; | ||
@@ -37,27 +39,10 @@ import type { ConstrainedRuleTraversalData, TraversalState } from "./traverse.js"; | ||
export type Problems = instanceOf<typeof Problems>; | ||
export declare const describeSubdomains: (subdomains: Subdomain[]) => string; | ||
export declare const describeDomains: (domains: Domain[]) => string; | ||
export declare const describeBranches: (descriptions: string[]) => string; | ||
/** Each Subdomain's completion for the phrase "Must be _____" */ | ||
export declare const subdomainDescriptions: { | ||
readonly bigint: "a bigint"; | ||
readonly boolean: "boolean"; | ||
readonly null: "null"; | ||
readonly number: "a number"; | ||
readonly object: "an object"; | ||
readonly string: "a string"; | ||
readonly symbol: "a symbol"; | ||
readonly undefined: "undefined"; | ||
readonly Array: "an array"; | ||
readonly Function: "a function"; | ||
readonly Date: "a Date"; | ||
readonly RegExp: "a RegExp"; | ||
readonly Error: "an Error"; | ||
readonly Map: "a Map"; | ||
readonly Set: "a Set"; | ||
}; | ||
type ProblemRuleInputs = { | ||
divisor: number; | ||
class: constructor; | ||
domain: Subdomain; | ||
domainBranches: Subdomain[]; | ||
domain: Domain; | ||
domainBranches: Domain[]; | ||
objectKind: DefaultObjectKind; | ||
missing: undefined; | ||
@@ -93,21 +78,20 @@ bound: FlatBound; | ||
get domain(): domainOf<value>; | ||
get subdomain(): subdomainOf<value>; | ||
get objectKind(): "non-object" | NonNullable<objectKindOf<value, { | ||
Array: ArrayConstructor; | ||
Date: DateConstructor; | ||
Error: ErrorConstructor; | ||
Function: FunctionConstructor; | ||
Map: MapConstructor; | ||
RegExp: RegExpConstructor; | ||
Set: SetConstructor; | ||
Object: ObjectConstructor; | ||
String: StringConstructor; | ||
Number: NumberConstructor; | ||
Boolean: BooleanConstructor; | ||
WeakMap: WeakMapConstructor; | ||
WeakSet: WeakSetConstructor; | ||
Promise: PromiseConstructor; | ||
}>>; | ||
get size(): number; | ||
get units(): "" | NonNullable<{ | ||
string?: string; | ||
number?: string; | ||
bigint?: string; | ||
boolean?: string; | ||
symbol?: string; | ||
undefined?: string; | ||
object?: string; | ||
null?: string; | ||
Array?: string; | ||
Date?: string; | ||
Error?: string; | ||
Function?: string; | ||
Map?: string; | ||
RegExp?: string; | ||
Set?: string; | ||
}[subdomainOf<value>]>; | ||
get units(): "" | "characters" | "items"; | ||
get className(): any; | ||
@@ -114,0 +98,0 @@ } |
import type { Type } from "../main.js"; | ||
import type { TraversalEntry, TraversalKey, TraversalNode } from "../nodes/node.js"; | ||
import type { SizedData, Subdomain } from "../utils/domains.js"; | ||
import type { Dict, extend, List } from "../utils/generics.js"; | ||
import { Path } from "../utils/paths.js"; | ||
import type { SizedData } from "../utils/size.js"; | ||
import type { Problem } from "./problems.js"; | ||
@@ -16,4 +16,23 @@ export declare class TraversalState { | ||
class: import("../utils/generics.js").constructor; | ||
domain: Subdomain; | ||
domainBranches: Subdomain[]; | ||
domain: keyof { | ||
bigint: bigint; | ||
boolean: boolean; | ||
number: number; | ||
object: object; | ||
string: string; | ||
symbol: symbol; | ||
undefined: undefined; | ||
null: null; | ||
}; | ||
domainBranches: (keyof { | ||
bigint: bigint; | ||
boolean: boolean; | ||
number: number; | ||
object: object; | ||
string: string; | ||
symbol: symbol; | ||
undefined: undefined; | ||
null: null; | ||
})[]; | ||
objectKind: "Array" | "Date" | "Error" | "Function" | "Map" | "RegExp" | "Set" | "Object" | "String" | "Number" | "Boolean" | "WeakMap" | "WeakSet" | "Promise"; | ||
missing: undefined; | ||
@@ -37,3 +56,3 @@ bound: import("../nodes/rules/range.js").FlatBound; | ||
export declare const checkEntries: (data: unknown, entries: List<TraversalEntry>, state: TraversalState) => unknown; | ||
export declare const checkSubdomain: TraversalCheck<"subdomain">; | ||
export declare const checkObjectKind: TraversalCheck<"objectKind">; | ||
export type TraversalCheck<k extends TraversalKey> = (data: RuleData<k>, rule: Extract<TraversalEntry, [k, unknown]>[1], state: TraversalState) => void; | ||
@@ -48,4 +67,5 @@ export type ConstrainedRuleTraversalData = extend<{ | ||
optionalProps: Dict; | ||
objectKind: object; | ||
class: object; | ||
}>; | ||
export type RuleData<k extends TraversalKey> = k extends keyof ConstrainedRuleTraversalData ? ConstrainedRuleTraversalData[k] : unknown; |
@@ -1,2 +0,2 @@ | ||
import type { Dict, evaluate, isTopType, List } from "./generics.js"; | ||
import type { evaluate, isTopType } from "./generics.js"; | ||
export declare const hasDomain: <data, domain extends keyof DomainTypes>(data: data, domain: domain) => data is data & inferDomain<domain>; | ||
@@ -21,39 +21,13 @@ type DomainTypes = { | ||
export declare const domainOf: <data>(data: data) => domainOf<data>; | ||
export type ObjectSubdomains = { | ||
Array: readonly unknown[]; | ||
Date: Date; | ||
Error: Error; | ||
Function: Function; | ||
Map: Map<unknown, unknown>; | ||
RegExp: RegExp; | ||
Set: Set<unknown>; | ||
object: Dict; | ||
/** Each domain's completion for the phrase "Must be _____" */ | ||
export declare const domainDescriptions: { | ||
readonly bigint: "a bigint"; | ||
readonly boolean: "boolean"; | ||
readonly null: "null"; | ||
readonly number: "a number"; | ||
readonly object: "an object"; | ||
readonly string: "a string"; | ||
readonly symbol: "a symbol"; | ||
readonly undefined: "undefined"; | ||
}; | ||
export type ObjectSubdomain = keyof ObjectSubdomains; | ||
export type Subdomain<domain extends Domain = Domain> = domain | (domain extends "object" ? ObjectSubdomain : never); | ||
export type subdomainOf<data> = isTopType<data> extends true ? Subdomain : data extends object ? object extends data ? ObjectSubdomain : data extends List ? "Array" : data extends Date ? "Date" : data extends Error ? "Error" : data extends Function ? "Function" : data extends Map<unknown, unknown> ? "Map" : data extends RegExp ? "RegExp" : data extends Set<unknown> ? "Set" : "object" : domainOf<data>; | ||
export declare const subdomainOf: <data>(data: data) => subdomainOf<data>; | ||
export type inferSubdomain<subdomain extends Subdomain> = subdomain extends ObjectSubdomain ? ObjectSubdomains[subdomain] : subdomain extends Domain ? DomainTypes[subdomain] : never; | ||
export declare const hasSubdomain: <subdomain extends Subdomain<keyof DomainTypes>>(data: unknown, subdomain: subdomain) => data is inferSubdomain<subdomain>; | ||
export declare const sizeOf: <data>(data: data) => number; | ||
export declare const unitsOf: <data>(data: data) => "" | NonNullable<{ | ||
string?: string; | ||
number?: string; | ||
bigint?: string; | ||
boolean?: string; | ||
symbol?: string; | ||
undefined?: string; | ||
object?: string; | ||
null?: string; | ||
Array?: string; | ||
Date?: string; | ||
Error?: string; | ||
Function?: string; | ||
Map?: string; | ||
RegExp?: string; | ||
Set?: string; | ||
}[subdomainOf<data>]>; | ||
export type SizedSubdomain = "number" | "string" | "Array"; | ||
export type SizedData = inferSubdomain<SizedSubdomain>; | ||
export declare const classNameOf: <data>(data: data) => any; | ||
export {}; |
@@ -107,3 +107,2 @@ export type asConst<t> = castWithExclusion<t, asConstRecurse<t>, []>; | ||
export type CollapsibleList<t> = t | readonly t[]; | ||
export declare const collapseIfSingleton: <t extends List<unknown>>(array: t) => t | t[number]; | ||
/** Either: | ||
@@ -110,0 +109,0 @@ * A, with all properties of B undefined |
{ | ||
"name": "arktype", | ||
"description": "Isomorphic type syntax for TS/JS", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"author": { | ||
@@ -86,7 +86,7 @@ "name": "David Blass", | ||
"//temporarily disabled pr checks": "pnpm testRepo", | ||
"prChecks": "pnpm install && pnpm build && pnpm typecheck && pnpm lint && pnpm test && pnpm buildDocs", | ||
"prChecks": "pnpm install && pnpm build && pnpm typecheck && pnpm lint && pnpm test && pnpm docgen && pnpm buildSite", | ||
"typecheck": "tsc --noEmit", | ||
"build": "ts-node ./dev/scripts/build.ts", | ||
"buildRepo": "pnpm build && pnpm buildDocs", | ||
"buildDocs": "pnpm docgen && cd dev/arktype.io && pnpm install && pnpm build", | ||
"buildRepo": "pnpm build && pnpm docgen && pnpm buildSite", | ||
"buildSite": "cd dev/arktype.io && pnpm install && pnpm build", | ||
"docgen": "ts-node ./dev/scripts/docgen.ts", | ||
@@ -93,0 +93,0 @@ "test": "ts-node ./dev/attest/cli.ts --cmd mocha", |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
390707
153
8710