- 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
99 lines
3.3 KiB
JavaScript
99 lines
3.3 KiB
JavaScript
import { flatMorph, printable, throwParseError } from "@ark/util";
|
|
import { compileSerializedValue } from "./compile.js";
|
|
import { isNode } from "./utils.js";
|
|
export const basisKinds = ["unit", "proto", "domain"];
|
|
export const structuralKinds = [
|
|
"required",
|
|
"optional",
|
|
"index",
|
|
"sequence"
|
|
];
|
|
export const prestructuralKinds = [
|
|
"pattern",
|
|
"divisor",
|
|
"exactLength",
|
|
"max",
|
|
"min",
|
|
"maxLength",
|
|
"minLength",
|
|
"before",
|
|
"after"
|
|
];
|
|
export const refinementKinds = [
|
|
...prestructuralKinds,
|
|
"structure",
|
|
"predicate"
|
|
];
|
|
export const constraintKinds = [...refinementKinds, ...structuralKinds];
|
|
export const rootKinds = [
|
|
"alias",
|
|
"union",
|
|
"morph",
|
|
"unit",
|
|
"intersection",
|
|
"proto",
|
|
"domain"
|
|
];
|
|
export const nodeKinds = [...rootKinds, ...constraintKinds];
|
|
export const constraintKeys = flatMorph(constraintKinds, (i, kind) => [kind, 1]);
|
|
export const structureKeys = flatMorph([...structuralKinds, "undeclared"], (i, k) => [k, 1]);
|
|
export const precedenceByKind = flatMorph(nodeKinds, (i, kind) => [kind, i]);
|
|
export const isNodeKind = (value) => typeof value === "string" && value in precedenceByKind;
|
|
export function assertNodeKind(value, kind) {
|
|
const valueIsNode = isNode(value);
|
|
if (!valueIsNode || value.kind !== kind) {
|
|
throwParseError(`Expected node of kind ${kind} (was ${valueIsNode ? `${value.kind} node` : printable(value)})`);
|
|
}
|
|
}
|
|
export const precedenceOfKind = (kind) => precedenceByKind[kind];
|
|
export const schemaKindsRightOf = (kind) => rootKinds.slice(precedenceOfKind(kind) + 1);
|
|
export const unionChildKinds = [
|
|
...schemaKindsRightOf("union"),
|
|
"alias"
|
|
];
|
|
export const morphChildKinds = [
|
|
...schemaKindsRightOf("morph"),
|
|
"alias"
|
|
];
|
|
export const defaultValueSerializer = (v) => {
|
|
if (typeof v === "string" || typeof v === "boolean" || v === null)
|
|
return v;
|
|
if (typeof v === "number") {
|
|
if (Number.isNaN(v))
|
|
return "NaN";
|
|
if (v === Number.POSITIVE_INFINITY)
|
|
return "Infinity";
|
|
if (v === Number.NEGATIVE_INFINITY)
|
|
return "-Infinity";
|
|
return v;
|
|
}
|
|
return compileSerializedValue(v);
|
|
};
|
|
export const compileObjectLiteral = (ctx) => {
|
|
let result = "{ ";
|
|
for (const [k, v] of Object.entries(ctx))
|
|
result += `${k}: ${compileSerializedValue(v)}, `;
|
|
return result + " }";
|
|
};
|
|
export const implementNode = (_) => {
|
|
const implementation = _;
|
|
if (implementation.hasAssociatedError) {
|
|
implementation.defaults.expected ??= ctx => "description" in ctx ?
|
|
ctx.description
|
|
: implementation.defaults.description(ctx);
|
|
implementation.defaults.actual ??= data => printable(data);
|
|
implementation.defaults.problem ??= ctx => `must be ${ctx.expected}${ctx.actual ? ` (was ${ctx.actual})` : ""}`;
|
|
implementation.defaults.message ??= ctx => {
|
|
if (ctx.path.length === 0)
|
|
return ctx.problem;
|
|
const problemWithLocation = `${ctx.propString} ${ctx.problem}`;
|
|
if (problemWithLocation[0] === "[") {
|
|
// clarify paths like [1], [0][1], and ["key!"] that could be confusing
|
|
return `value at ${problemWithLocation}`;
|
|
}
|
|
return problemWithLocation;
|
|
};
|
|
}
|
|
return implementation;
|
|
};
|