- 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
102 lines
4.3 KiB
JavaScript
102 lines
4.3 KiB
JavaScript
import { builtinConstructors, constructorExtends, domainOf, getBuiltinNameOfConstructor, hasKey, objectKindDescriptions, objectKindOrDomainOf, throwParseError } from "@ark/util";
|
|
import { Disjoint } from "../shared/disjoint.js";
|
|
import { defaultValueSerializer, implementNode } from "../shared/implement.js";
|
|
import { $ark } from "../shared/registry.js";
|
|
import { isNode } from "../shared/utils.js";
|
|
import { InternalBasis } from "./basis.js";
|
|
const implementation = implementNode({
|
|
kind: "proto",
|
|
hasAssociatedError: true,
|
|
collapsibleKey: "proto",
|
|
keys: {
|
|
proto: {
|
|
serialize: ctor => getBuiltinNameOfConstructor(ctor) ?? defaultValueSerializer(ctor)
|
|
},
|
|
dateAllowsInvalid: {}
|
|
},
|
|
normalize: schema => {
|
|
const normalized = typeof schema === "string" ? { proto: builtinConstructors[schema] }
|
|
: typeof schema === "function" ?
|
|
isNode(schema) ? schema
|
|
: { proto: schema }
|
|
: typeof schema.proto === "string" ?
|
|
{ ...schema, proto: builtinConstructors[schema.proto] }
|
|
: schema;
|
|
if (typeof normalized.proto !== "function")
|
|
throwParseError(Proto.writeInvalidSchemaMessage(normalized.proto));
|
|
if (hasKey(normalized, "dateAllowsInvalid") && normalized.proto !== Date)
|
|
throwParseError(Proto.writeBadInvalidDateMessage(normalized.proto));
|
|
return normalized;
|
|
},
|
|
applyConfig: (schema, config) => {
|
|
if (schema.dateAllowsInvalid === undefined &&
|
|
schema.proto === Date &&
|
|
config.dateAllowsInvalid)
|
|
return { ...schema, dateAllowsInvalid: true };
|
|
return schema;
|
|
},
|
|
defaults: {
|
|
description: node => node.builtinName ?
|
|
objectKindDescriptions[node.builtinName]
|
|
: `an instance of ${node.proto.name}`,
|
|
actual: data => data instanceof Date && data.toString() === "Invalid Date" ?
|
|
"an invalid Date"
|
|
: objectKindOrDomainOf(data)
|
|
},
|
|
intersections: {
|
|
proto: (l, r) => l.proto === Date && r.proto === Date ?
|
|
// since l === r is handled by default,
|
|
// exactly one of l or r must have allow invalid dates
|
|
l.dateAllowsInvalid ?
|
|
r
|
|
: l
|
|
: constructorExtends(l.proto, r.proto) ? l
|
|
: constructorExtends(r.proto, l.proto) ? r
|
|
: Disjoint.init("proto", l, r),
|
|
domain: (proto, domain) => domain.domain === "object" ?
|
|
proto
|
|
: Disjoint.init("domain", $ark.intrinsic.object.internal, domain)
|
|
}
|
|
});
|
|
export class ProtoNode extends InternalBasis {
|
|
builtinName = getBuiltinNameOfConstructor(this.proto);
|
|
serializedConstructor = this.json.proto;
|
|
requiresInvalidDateCheck = this.proto === Date && !this.dateAllowsInvalid;
|
|
traverseAllows = this.requiresInvalidDateCheck ?
|
|
data => data instanceof Date && data.toString() !== "Invalid Date"
|
|
: data => data instanceof this.proto;
|
|
compiledCondition = `data instanceof ${this.serializedConstructor}${this.requiresInvalidDateCheck ? ` && data.toString() !== "Invalid Date"` : ""}`;
|
|
compiledNegation = `!(${this.compiledCondition})`;
|
|
innerToJsonSchema(ctx) {
|
|
switch (this.builtinName) {
|
|
case "Array":
|
|
return {
|
|
type: "array"
|
|
};
|
|
case "Date":
|
|
return (ctx.fallback.date?.({ code: "date", base: {} }) ??
|
|
ctx.fallback.proto({ code: "proto", base: {}, proto: this.proto }));
|
|
default:
|
|
return ctx.fallback.proto({
|
|
code: "proto",
|
|
base: {},
|
|
proto: this.proto
|
|
});
|
|
}
|
|
}
|
|
expression = this.dateAllowsInvalid ? "Date | InvalidDate" : this.proto.name;
|
|
get nestableExpression() {
|
|
return this.dateAllowsInvalid ? `(${this.expression})` : this.expression;
|
|
}
|
|
domain = "object";
|
|
get defaultShortDescription() {
|
|
return this.description;
|
|
}
|
|
}
|
|
export const Proto = {
|
|
implementation,
|
|
Node: ProtoNode,
|
|
writeBadInvalidDateMessage: (actual) => `dateAllowsInvalid may only be specified with constructor Date (was ${actual.name})`,
|
|
writeInvalidSchemaMessage: (actual) => `instanceOf operand must be a function (was ${domainOf(actual)})`
|
|
};
|