- 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
90 lines
3.8 KiB
JavaScript
90 lines
3.8 KiB
JavaScript
import { append, printable, stringAndSymbolicEntriesOf, throwParseError } from "@ark/util";
|
|
import { BaseConstraint } from "../constraint.js";
|
|
import { flatRef } from "../node.js";
|
|
import { Disjoint } from "../shared/disjoint.js";
|
|
import { implementNode } from "../shared/implement.js";
|
|
import { intersectOrPipeNodes } from "../shared/intersections.js";
|
|
import { $ark } from "../shared/registry.js";
|
|
import { traverseKey } from "../shared/traversal.js";
|
|
const implementation = implementNode({
|
|
kind: "index",
|
|
hasAssociatedError: false,
|
|
intersectionIsOpen: true,
|
|
keys: {
|
|
signature: {
|
|
child: true,
|
|
parse: (schema, ctx) => {
|
|
const key = ctx.$.parseSchema(schema);
|
|
if (!key.extends($ark.intrinsic.key)) {
|
|
return throwParseError(writeInvalidPropertyKeyMessage(key.expression));
|
|
}
|
|
const enumerableBranches = key.branches.filter(b => b.hasKind("unit"));
|
|
if (enumerableBranches.length) {
|
|
return throwParseError(writeEnumerableIndexBranches(enumerableBranches.map(b => printable(b.unit))));
|
|
}
|
|
return key;
|
|
}
|
|
},
|
|
value: {
|
|
child: true,
|
|
parse: (schema, ctx) => ctx.$.parseSchema(schema)
|
|
}
|
|
},
|
|
normalize: schema => schema,
|
|
defaults: {
|
|
description: node => `[${node.signature.expression}]: ${node.value.description}`
|
|
},
|
|
intersections: {
|
|
index: (l, r, ctx) => {
|
|
if (l.signature.equals(r.signature)) {
|
|
const valueIntersection = intersectOrPipeNodes(l.value, r.value, ctx);
|
|
const value = valueIntersection instanceof Disjoint ?
|
|
$ark.intrinsic.never.internal
|
|
: valueIntersection;
|
|
return ctx.$.node("index", { signature: l.signature, value });
|
|
}
|
|
// if r constrains all of l's keys to a subtype of l's value, r is a subtype of l
|
|
if (l.signature.extends(r.signature) && l.value.subsumes(r.value))
|
|
return r;
|
|
// if l constrains all of r's keys to a subtype of r's value, l is a subtype of r
|
|
if (r.signature.extends(l.signature) && r.value.subsumes(l.value))
|
|
return l;
|
|
// other relationships between index signatures can't be generally reduced
|
|
return null;
|
|
}
|
|
}
|
|
});
|
|
export class IndexNode extends BaseConstraint {
|
|
impliedBasis = $ark.intrinsic.object.internal;
|
|
expression = `[${this.signature.expression}]: ${this.value.expression}`;
|
|
flatRefs = append(this.value.flatRefs.map(ref => flatRef([this.signature, ...ref.path], ref.node)), flatRef([this.signature], this.value));
|
|
traverseAllows = (data, ctx) => stringAndSymbolicEntriesOf(data).every(entry => {
|
|
if (this.signature.traverseAllows(entry[0], ctx)) {
|
|
return traverseKey(entry[0], () => this.value.traverseAllows(entry[1], ctx), ctx);
|
|
}
|
|
return true;
|
|
});
|
|
traverseApply = (data, ctx) => {
|
|
for (const entry of stringAndSymbolicEntriesOf(data)) {
|
|
if (this.signature.traverseAllows(entry[0], ctx)) {
|
|
traverseKey(entry[0], () => this.value.traverseApply(entry[1], ctx), ctx);
|
|
}
|
|
}
|
|
};
|
|
_transform(mapper, ctx) {
|
|
ctx.path.push(this.signature);
|
|
const result = super._transform(mapper, ctx);
|
|
ctx.path.pop();
|
|
return result;
|
|
}
|
|
compile() {
|
|
// this is currently handled by StructureNode
|
|
}
|
|
}
|
|
export const Index = {
|
|
implementation,
|
|
Node: IndexNode
|
|
};
|
|
export const writeEnumerableIndexBranches = (keys) => `Index keys ${keys.join(", ")} should be specified as named props.`;
|
|
export const writeInvalidPropertyKeyMessage = (indexSchema) => `Indexed key definition '${indexSchema}' must be a string or symbol`;
|