Files
headroom/frontend/node_modules/@ark/schema/out/structure/structure.js
Santhosh Janardhanan de2d83092e feat: Reinitialize frontend with SvelteKit and TypeScript
- Delete old Vite+Svelte frontend
- Initialize new SvelteKit project with TypeScript
- Configure Tailwind CSS v4 + DaisyUI
- Implement JWT authentication with auto-refresh
- Create login page with form validation (Zod)
- Add protected route guards
- Update Docker configuration for single-stage build
- Add E2E tests with Playwright (6/11 passing)
- Fix Svelte 5 reactivity with $state() runes

Known issues:
- 5 E2E tests failing (timing/async issues)
- Token refresh implementation needs debugging
- Validation error display timing
2026-02-17 16:19:59 -05:00

748 lines
32 KiB
JavaScript

import { append, conflatenate, flatMorph, printable, spliterate, throwInternalError, throwParseError } from "@ark/util";
import { BaseConstraint, constraintKeyParser, flattenConstraints, intersectConstraints } from "../constraint.js";
import { intrinsic } from "../intrinsic.js";
import { typeOrTermExtends } from "../roots/root.js";
import { compileSerializedValue } from "../shared/compile.js";
import { Disjoint } from "../shared/disjoint.js";
import { implementNode } from "../shared/implement.js";
import { intersectNodesRoot } from "../shared/intersections.js";
import { $ark, registeredReference } from "../shared/registry.js";
import { ToJsonSchema } from "../shared/toJsonSchema.js";
import { traverseKey } from "../shared/traversal.js";
import { hasArkKind, isNode, makeRootAndArrayPropertiesMutable } from "../shared/utils.js";
import { Optional } from "./optional.js";
const createStructuralWriter = (childStringProp) => (node) => {
if (node.props.length || node.index) {
const parts = node.index?.map(index => index[childStringProp]) ?? [];
for (const prop of node.props)
parts.push(prop[childStringProp]);
if (node.undeclared)
parts.push(`+ (undeclared): ${node.undeclared}`);
const objectLiteralDescription = `{ ${parts.join(", ")} }`;
return node.sequence ?
`${objectLiteralDescription} & ${node.sequence.description}`
: objectLiteralDescription;
}
return node.sequence?.description ?? "{}";
};
const structuralDescription = createStructuralWriter("description");
const structuralExpression = createStructuralWriter("expression");
const intersectPropsAndIndex = (l, r, $) => {
const kind = l.required ? "required" : "optional";
if (!r.signature.allows(l.key))
return null;
const value = intersectNodesRoot(l.value, r.value, $);
if (value instanceof Disjoint) {
return kind === "optional" ?
$.node("optional", {
key: l.key,
value: $ark.intrinsic.never.internal
})
: value.withPrefixKey(l.key, l.kind);
}
return null;
};
const implementation = implementNode({
kind: "structure",
hasAssociatedError: false,
normalize: schema => schema,
applyConfig: (schema, config) => {
if (!schema.undeclared && config.onUndeclaredKey !== "ignore") {
return {
...schema,
undeclared: config.onUndeclaredKey
};
}
return schema;
},
keys: {
required: {
child: true,
parse: constraintKeyParser("required"),
reduceIo: (ioKind, inner, nodes) => {
// ensure we don't overwrite nodes added by optional
inner.required = append(inner.required, nodes.map(node => (ioKind === "in" ? node.rawIn : node.rawOut)));
return;
}
},
optional: {
child: true,
parse: constraintKeyParser("optional"),
reduceIo: (ioKind, inner, nodes) => {
if (ioKind === "in") {
inner.optional = nodes.map(node => node.rawIn);
return;
}
for (const node of nodes) {
inner[node.outProp.kind] = append(inner[node.outProp.kind], node.outProp.rawOut);
}
}
},
index: {
child: true,
parse: constraintKeyParser("index")
},
sequence: {
child: true,
parse: constraintKeyParser("sequence")
},
undeclared: {
parse: behavior => (behavior === "ignore" ? undefined : behavior),
reduceIo: (ioKind, inner, value) => {
if (value === "reject") {
inner.undeclared = "reject";
return;
}
// if base is "delete", undeclared keys are "ignore" (i.e. unconstrained)
// on input and "reject" on output
if (ioKind === "in")
delete inner.undeclared;
else
inner.undeclared = "reject";
}
}
},
defaults: {
description: structuralDescription
},
intersections: {
structure: (l, r, ctx) => {
const lInner = { ...l.inner };
const rInner = { ...r.inner };
const disjointResult = new Disjoint();
if (l.undeclared) {
const lKey = l.keyof();
for (const k of r.requiredKeys) {
if (!lKey.allows(k)) {
disjointResult.add("presence", $ark.intrinsic.never.internal, r.propsByKey[k].value, {
path: [k]
});
}
}
if (rInner.optional)
rInner.optional = rInner.optional.filter(n => lKey.allows(n.key));
if (rInner.index) {
rInner.index = rInner.index.flatMap(n => {
if (n.signature.extends(lKey))
return n;
const indexOverlap = intersectNodesRoot(lKey, n.signature, ctx.$);
if (indexOverlap instanceof Disjoint)
return [];
const normalized = normalizeIndex(indexOverlap, n.value, ctx.$);
if (normalized.required) {
rInner.required = conflatenate(rInner.required, normalized.required);
}
if (normalized.optional) {
rInner.optional = conflatenate(rInner.optional, normalized.optional);
}
return normalized.index ?? [];
});
}
}
if (r.undeclared) {
const rKey = r.keyof();
for (const k of l.requiredKeys) {
if (!rKey.allows(k)) {
disjointResult.add("presence", l.propsByKey[k].value, $ark.intrinsic.never.internal, {
path: [k]
});
}
}
if (lInner.optional)
lInner.optional = lInner.optional.filter(n => rKey.allows(n.key));
if (lInner.index) {
lInner.index = lInner.index.flatMap(n => {
if (n.signature.extends(rKey))
return n;
const indexOverlap = intersectNodesRoot(rKey, n.signature, ctx.$);
if (indexOverlap instanceof Disjoint)
return [];
const normalized = normalizeIndex(indexOverlap, n.value, ctx.$);
if (normalized.required) {
lInner.required = conflatenate(lInner.required, normalized.required);
}
if (normalized.optional) {
lInner.optional = conflatenate(lInner.optional, normalized.optional);
}
return normalized.index ?? [];
});
}
}
const baseInner = {};
if (l.undeclared || r.undeclared) {
baseInner.undeclared =
l.undeclared === "reject" || r.undeclared === "reject" ?
"reject"
: "delete";
}
const childIntersectionResult = intersectConstraints({
kind: "structure",
baseInner,
l: flattenConstraints(lInner),
r: flattenConstraints(rInner),
roots: [],
ctx
});
if (childIntersectionResult instanceof Disjoint)
disjointResult.push(...childIntersectionResult);
if (disjointResult.length)
return disjointResult;
return childIntersectionResult;
}
},
reduce: (inner, $) => {
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;
}
}
}
}
// 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 });
}
}
});
export class StructureNode extends BaseConstraint {
impliedBasis = $ark.intrinsic.object.internal;
impliedSiblings = this.children.flatMap(n => n.impliedSiblings ?? []);
props = conflatenate(this.required, this.optional);
propsByKey = flatMorph(this.props, (i, node) => [node.key, node]);
propsByKeyReference = registeredReference(this.propsByKey);
expression = structuralExpression(this);
requiredKeys = this.required?.map(node => node.key) ?? [];
optionalKeys = this.optional?.map(node => node.key) ?? [];
literalKeys = [...this.requiredKeys, ...this.optionalKeys];
_keyof;
keyof() {
if (this._keyof)
return this._keyof;
let branches = this.$.units(this.literalKeys).branches;
if (this.index) {
for (const { signature } of this.index)
branches = branches.concat(signature.branches);
}
return (this._keyof = this.$.node("union", branches));
}
map(flatMapProp) {
return this.$.node("structure", this.props
.flatMap(flatMapProp)
.reduce((structureInner, mapped) => {
const originalProp = this.propsByKey[mapped.key];
if (isNode(mapped)) {
if (mapped.kind !== "required" && mapped.kind !== "optional") {
return throwParseError(`Map result must have kind "required" or "optional" (was ${mapped.kind})`);
}
structureInner[mapped.kind] = append(structureInner[mapped.kind], mapped);
return structureInner;
}
const mappedKind = mapped.kind ?? originalProp?.kind ?? "required";
// extract the inner keys from the map result in case a node was spread,
// which would otherwise lead to invalid keys
const mappedPropInner = flatMorph(mapped, (k, v) => (k in Optional.implementation.keys ? [k, v] : []));
structureInner[mappedKind] = append(structureInner[mappedKind], this.$.node(mappedKind, mappedPropInner));
return structureInner;
}, {}));
}
assertHasKeys(keys) {
const invalidKeys = keys.filter(k => !typeOrTermExtends(k, this.keyof()));
if (invalidKeys.length) {
return throwParseError(writeInvalidKeysMessage(this.expression, invalidKeys));
}
}
get(indexer, ...path) {
let value;
let required = false;
const key = indexerToKey(indexer);
if ((typeof key === "string" || typeof key === "symbol") &&
this.propsByKey[key]) {
value = this.propsByKey[key].value;
required = this.propsByKey[key].required;
}
if (this.index) {
for (const n of this.index) {
if (typeOrTermExtends(key, n.signature))
value = value?.and(n.value) ?? n.value;
}
}
if (this.sequence &&
typeOrTermExtends(key, $ark.intrinsic.nonNegativeIntegerString)) {
if (hasArkKind(key, "root")) {
if (this.sequence.variadic)
// if there is a variadic element and we're accessing an index, return a union
// of all possible elements. If there is no variadic expression, we're in a tuple
// so this access wouldn't be safe based on the array indices
value = value?.and(this.sequence.element) ?? this.sequence.element;
}
else {
const index = Number.parseInt(key);
if (index < this.sequence.prevariadic.length) {
const fixedElement = this.sequence.prevariadic[index].node;
value = value?.and(fixedElement) ?? fixedElement;
required ||= index < this.sequence.prefixLength;
}
else if (this.sequence.variadic) {
// ideally we could return something more specific for postfix
// but there is no way to represent it using an index alone
const nonFixedElement = this.$.node("union", this.sequence.variadicOrPostfix);
value = value?.and(nonFixedElement) ?? nonFixedElement;
}
}
}
if (!value) {
if (this.sequence?.variadic &&
hasArkKind(key, "root") &&
key.extends($ark.intrinsic.number)) {
return throwParseError(writeNumberIndexMessage(key.expression, this.sequence.expression));
}
return throwParseError(writeInvalidKeysMessage(this.expression, [key]));
}
const result = value.get(...path);
return required ? result : result.or($ark.intrinsic.undefined);
}
pick(...keys) {
this.assertHasKeys(keys);
return this.$.node("structure", this.filterKeys("pick", keys));
}
omit(...keys) {
this.assertHasKeys(keys);
return this.$.node("structure", this.filterKeys("omit", keys));
}
optionalize() {
const { required, ...inner } = this.inner;
return this.$.node("structure", {
...inner,
optional: this.props.map(prop => prop.hasKind("required") ? this.$.node("optional", prop.inner) : prop)
});
}
require() {
const { optional, ...inner } = this.inner;
return this.$.node("structure", {
...inner,
required: this.props.map(prop => prop.hasKind("optional") ?
{
key: prop.key,
value: prop.value
}
: prop)
});
}
merge(r) {
const inner = this.filterKeys("omit", [r.keyof()]);
if (r.required)
inner.required = append(inner.required, r.required);
if (r.optional)
inner.optional = append(inner.optional, r.optional);
if (r.index)
inner.index = append(inner.index, r.index);
if (r.sequence)
inner.sequence = r.sequence;
if (r.undeclared)
inner.undeclared = r.undeclared;
else
delete inner.undeclared;
return this.$.node("structure", inner);
}
filterKeys(operation, keys) {
const result = makeRootAndArrayPropertiesMutable(this.inner);
const shouldKeep = (key) => {
const matchesKey = keys.some(k => typeOrTermExtends(key, k));
return operation === "pick" ? matchesKey : !matchesKey;
};
if (result.required)
result.required = result.required.filter(prop => shouldKeep(prop.key));
if (result.optional)
result.optional = result.optional.filter(prop => shouldKeep(prop.key));
if (result.index)
result.index = result.index.filter(index => shouldKeep(index.signature));
return result;
}
traverseAllows = (data, ctx) => this._traverse("Allows", data, ctx);
traverseApply = (data, ctx) => this._traverse("Apply", data, ctx);
_traverse = (traversalKind, data, ctx) => {
const errorCount = ctx?.currentErrorCount ?? 0;
for (let i = 0; i < this.props.length; i++) {
if (traversalKind === "Allows") {
if (!this.props[i].traverseAllows(data, ctx))
return false;
}
else {
this.props[i].traverseApply(data, ctx);
if (ctx.failFast && ctx.currentErrorCount > errorCount)
return false;
}
}
if (this.sequence) {
if (traversalKind === "Allows") {
if (!this.sequence.traverseAllows(data, ctx))
return false;
}
else {
this.sequence.traverseApply(data, ctx);
if (ctx.failFast && ctx.currentErrorCount > errorCount)
return false;
}
}
if (this.index || this.undeclared === "reject") {
const keys = Object.keys(data);
keys.push(...Object.getOwnPropertySymbols(data));
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
if (this.index) {
for (const node of this.index) {
if (node.signature.traverseAllows(k, ctx)) {
if (traversalKind === "Allows") {
const result = traverseKey(k, () => node.value.traverseAllows(data[k], ctx), ctx);
if (!result)
return false;
}
else {
traverseKey(k, () => node.value.traverseApply(data[k], ctx), ctx);
if (ctx.failFast && ctx.currentErrorCount > errorCount)
return false;
}
}
}
}
if (this.undeclared === "reject" && !this.declaresKey(k)) {
if (traversalKind === "Allows")
return false;
// this should have its own error code:
// https://github.com/arktypeio/arktype/issues/1403
ctx.errorFromNodeContext({
code: "predicate",
expected: "removed",
actual: "",
relativePath: [k],
meta: this.meta
});
if (ctx.failFast)
return false;
}
}
}
// added additional ctx check here to address
// https://github.com/arktypeio/arktype/issues/1346
if (this.structuralMorph && ctx && !ctx.hasError())
ctx.queueMorphs([this.structuralMorph]);
return true;
};
get defaultable() {
return this.cacheGetter("defaultable", this.optional?.filter(o => o.hasDefault()) ?? []);
}
declaresKey = (k) => k in this.propsByKey ||
this.index?.some(n => n.signature.allows(k)) ||
(this.sequence !== undefined &&
$ark.intrinsic.nonNegativeIntegerString.allows(k));
_compileDeclaresKey(js) {
const parts = [];
if (this.props.length)
parts.push(`k in ${this.propsByKeyReference}`);
if (this.index) {
for (const index of this.index)
parts.push(js.invoke(index.signature, { kind: "Allows", arg: "k" }));
}
if (this.sequence)
parts.push("$ark.intrinsic.nonNegativeIntegerString.allows(k)");
// if parts is empty, this is a structure like { "+": "reject" }
// that declares no keys, so return false
return parts.join(" || ") || "false";
}
get structuralMorph() {
return this.cacheGetter("structuralMorph", getPossibleMorph(this));
}
structuralMorphRef = this.structuralMorph && registeredReference(this.structuralMorph);
compile(js) {
if (js.traversalKind === "Apply")
js.initializeErrorCount();
for (const prop of this.props) {
js.check(prop);
if (js.traversalKind === "Apply")
js.returnIfFailFast();
}
if (this.sequence) {
js.check(this.sequence);
if (js.traversalKind === "Apply")
js.returnIfFailFast();
}
if (this.index || this.undeclared === "reject") {
js.const("keys", "Object.keys(data)");
js.line("keys.push(...Object.getOwnPropertySymbols(data))");
js.for("i < keys.length", () => this.compileExhaustiveEntry(js));
}
if (js.traversalKind === "Allows")
return js.return(true);
// always queue deleteUndeclared on valid traversal for "delete"
if (this.structuralMorphRef) {
// added additional ctx check here to address
// https://github.com/arktypeio/arktype/issues/1346
js.if("ctx && !ctx.hasError()", () => {
js.line(`ctx.queueMorphs([`);
precompileMorphs(js, this);
return js.line("])");
});
}
}
compileExhaustiveEntry(js) {
js.const("k", "keys[i]");
if (this.index) {
for (const node of this.index) {
js.if(`${js.invoke(node.signature, { arg: "k", kind: "Allows" })}`, () => js.traverseKey("k", "data[k]", node.value));
}
}
if (this.undeclared === "reject") {
js.if(`!(${this._compileDeclaresKey(js)})`, () => {
if (js.traversalKind === "Allows")
return js.return(false);
return js
.line(`ctx.errorFromNodeContext({ code: "predicate", expected: "removed", actual: "", relativePath: [k], meta: ${this.compiledMeta} })`)
.if("ctx.failFast", () => js.return());
});
}
return js;
}
reduceJsonSchema(schema, ctx) {
switch (schema.type) {
case "object":
return this.reduceObjectJsonSchema(schema, ctx);
case "array":
const arraySchema = this.sequence?.reduceJsonSchema(schema, ctx) ?? schema;
if (this.props.length || this.index) {
return ctx.fallback.arrayObject({
code: "arrayObject",
base: arraySchema,
object: this.reduceObjectJsonSchema({ type: "object" }, ctx)
});
}
return arraySchema;
default:
return ToJsonSchema.throwInternalOperandError("structure", schema);
}
}
reduceObjectJsonSchema(schema, ctx) {
if (this.props.length) {
schema.properties = {};
for (const prop of this.props) {
const valueSchema = prop.value.toJsonSchemaRecurse(ctx);
if (typeof prop.key === "symbol") {
ctx.fallback.symbolKey({
code: "symbolKey",
base: schema,
key: prop.key,
value: valueSchema,
optional: prop.optional
});
continue;
}
if (prop.hasDefault()) {
const value = typeof prop.default === "function" ? prop.default() : prop.default;
valueSchema.default =
$ark.intrinsic.jsonData.allows(value) ?
value
: ctx.fallback.defaultValue({
code: "defaultValue",
base: valueSchema,
value
});
}
schema.properties[prop.key] = valueSchema;
}
if (this.requiredKeys.length && schema.properties) {
schema.required = this.requiredKeys.filter((k) => typeof k === "string" && k in schema.properties);
}
}
if (this.index) {
for (const index of this.index) {
const valueJsonSchema = index.value.toJsonSchemaRecurse(ctx);
if (index.signature.equals($ark.intrinsic.string)) {
schema.additionalProperties = valueJsonSchema;
continue;
}
for (const keyBranch of index.signature.branches) {
if (!keyBranch.extends($ark.intrinsic.string)) {
schema = ctx.fallback.symbolKey({
code: "symbolKey",
base: schema,
key: null,
value: valueJsonSchema,
optional: false
});
continue;
}
let keySchema = { type: "string" };
if (keyBranch.hasKind("morph")) {
keySchema = ctx.fallback.morph({
code: "morph",
base: keyBranch.rawIn.toJsonSchemaRecurse(ctx),
out: keyBranch.rawOut.toJsonSchemaRecurse(ctx)
});
}
if (!keyBranch.hasKind("intersection")) {
return throwInternalError(`Unexpected index branch kind ${keyBranch.kind}.`);
}
const { pattern } = keyBranch.inner;
if (pattern) {
const keySchemaWithPattern = Object.assign(keySchema, {
pattern: pattern[0].rule
});
for (let i = 1; i < pattern.length; i++) {
keySchema = ctx.fallback.patternIntersection({
code: "patternIntersection",
base: keySchemaWithPattern,
pattern: pattern[i].rule
});
}
schema.patternProperties ??= {};
schema.patternProperties[keySchemaWithPattern.pattern] =
valueJsonSchema;
}
}
}
}
if (this.undeclared && !schema.additionalProperties)
schema.additionalProperties = false;
return schema;
}
}
const defaultableMorphsCache = {};
const constructStructuralMorphCacheKey = (node) => {
let cacheKey = "";
for (let i = 0; i < node.defaultable.length; i++)
cacheKey += node.defaultable[i].defaultValueMorphRef;
if (node.sequence?.defaultValueMorphsReference)
cacheKey += node.sequence?.defaultValueMorphsReference;
if (node.undeclared === "delete") {
cacheKey += "delete !(";
if (node.required)
for (const n of node.required)
cacheKey += n.compiledKey + " | ";
if (node.optional)
for (const n of node.optional)
cacheKey += n.compiledKey + " | ";
if (node.index)
for (const index of node.index)
cacheKey += index.signature.id + " | ";
if (node.sequence) {
if (node.sequence.maxLength === null)
cacheKey += intrinsic.nonNegativeIntegerString.id;
else {
for (let i = 0; i < node.sequence.tuple.length; i++)
cacheKey += i + " | ";
}
}
cacheKey += ")";
}
return cacheKey;
};
const getPossibleMorph = (node) => {
const cacheKey = constructStructuralMorphCacheKey(node);
if (!cacheKey)
return undefined;
if (defaultableMorphsCache[cacheKey])
return defaultableMorphsCache[cacheKey];
const $arkStructuralMorph = (data, ctx) => {
for (let i = 0; i < node.defaultable.length; i++) {
if (!(node.defaultable[i].key in data))
node.defaultable[i].defaultValueMorph(data, ctx);
}
if (node.sequence?.defaultables) {
for (let i = data.length - node.sequence.prefixLength; i < node.sequence.defaultables.length; i++)
node.sequence.defaultValueMorphs[i](data, ctx);
}
if (node.undeclared === "delete")
for (const k in data)
if (!node.declaresKey(k))
delete data[k];
return data;
};
return (defaultableMorphsCache[cacheKey] = $arkStructuralMorph);
};
const precompileMorphs = (js, node) => {
const requiresContext = node.defaultable.some(node => node.defaultValueMorph.length === 2) ||
node.sequence?.defaultValueMorphs.some(morph => morph.length === 2);
const args = `(data${requiresContext ? ", ctx" : ""})`;
return js.block(`${args} => `, js => {
for (let i = 0; i < node.defaultable.length; i++) {
const { serializedKey, defaultValueMorphRef } = node.defaultable[i];
js.if(`!(${serializedKey} in data)`, js => js.line(`${defaultValueMorphRef}${args}`));
}
if (node.sequence?.defaultables) {
js.for(`i < ${node.sequence.defaultables.length}`, js => js.set(`data[i]`, 5), `data.length - ${node.sequence.prefixLength}`);
}
if (node.undeclared === "delete") {
js.forIn("data", js => js.if(`!(${node._compileDeclaresKey(js)})`, js => js.line(`delete data[k]`)));
}
return js.return("data");
});
};
export const Structure = {
implementation,
Node: StructureNode
};
const indexerToKey = (indexable) => {
if (hasArkKind(indexable, "root") && indexable.hasKind("unit"))
indexable = indexable.unit;
if (typeof indexable === "number")
indexable = `${indexable}`;
return indexable;
};
export const writeNumberIndexMessage = (indexExpression, sequenceExpression) => `${indexExpression} is not allowed as an array index on ${sequenceExpression}. Use the 'nonNegativeIntegerString' keyword instead.`;
/** extract enumerable named props from an index signature */
export const normalizeIndex = (signature, value, $) => {
const [enumerableBranches, nonEnumerableBranches] = spliterate(signature.branches, k => k.hasKind("unit"));
if (!enumerableBranches.length)
return { index: $.node("index", { signature, value }) };
const normalized = {};
for (const n of enumerableBranches) {
// since required can be reduced to optional if it has a default or
// optional meta on its value, we have to assign it depending on the
// compiled kind
const prop = $.node("required", { key: n.unit, value });
normalized[prop.kind] = append(normalized[prop.kind], prop);
}
if (nonEnumerableBranches.length) {
normalized.index = $.node("index", {
signature: nonEnumerableBranches,
value
});
}
return normalized;
};
export const typeKeyToString = (k) => hasArkKind(k, "root") ? k.expression : printable(k);
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)}`;