- 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
96 lines
3.3 KiB
JavaScript
96 lines
3.3 KiB
JavaScript
import { isNodeKind } from "./shared/implement.js";
|
|
import { $ark } from "./shared/registry.js";
|
|
import { ToJsonSchema } from "./shared/toJsonSchema.js";
|
|
// $ark.config could already be set if it were imported previously from the
|
|
// dedicated config entrypoint, in which case we don't want to reinitialize it
|
|
$ark.config ??= {};
|
|
export const configureSchema = (config) => {
|
|
const result = Object.assign($ark.config, mergeConfigs($ark.config, config));
|
|
if ($ark.resolvedConfig)
|
|
$ark.resolvedConfig = mergeConfigs($ark.resolvedConfig, result);
|
|
return result;
|
|
};
|
|
export const mergeConfigs = (base, merged) => {
|
|
if (!merged)
|
|
return base;
|
|
const result = { ...base };
|
|
let k;
|
|
for (k in merged) {
|
|
const keywords = { ...base.keywords };
|
|
if (k === "keywords") {
|
|
for (const flatAlias in merged[k]) {
|
|
const v = merged.keywords[flatAlias];
|
|
if (v === undefined)
|
|
continue;
|
|
keywords[flatAlias] = typeof v === "string" ? { description: v } : v;
|
|
}
|
|
result.keywords = keywords;
|
|
}
|
|
else if (k === "toJsonSchema") {
|
|
result[k] = mergeToJsonSchemaConfigs(base.toJsonSchema, merged.toJsonSchema);
|
|
}
|
|
else if (isNodeKind(k)) {
|
|
result[k] =
|
|
// not casting this makes TS compute a very inefficient
|
|
// type that is not needed
|
|
{
|
|
...base[k],
|
|
...merged[k]
|
|
};
|
|
}
|
|
else
|
|
result[k] = merged[k];
|
|
}
|
|
return result;
|
|
};
|
|
const jsonSchemaTargetToDialect = {
|
|
"draft-2020-12": "https://json-schema.org/draft/2020-12/schema",
|
|
"draft-07": "http://json-schema.org/draft-07/schema#"
|
|
};
|
|
export const mergeToJsonSchemaConfigs = ((baseConfig, mergedConfig) => {
|
|
if (!baseConfig)
|
|
return resolveTargetToDialect(mergedConfig ?? {}, undefined);
|
|
if (!mergedConfig)
|
|
return baseConfig;
|
|
const result = { ...baseConfig };
|
|
let k;
|
|
for (k in mergedConfig) {
|
|
if (k === "fallback") {
|
|
result.fallback = mergeFallbacks(baseConfig.fallback, mergedConfig.fallback);
|
|
}
|
|
else
|
|
result[k] = mergedConfig[k];
|
|
}
|
|
return resolveTargetToDialect(result, mergedConfig);
|
|
});
|
|
const resolveTargetToDialect = (opts, userOpts) => {
|
|
// If user explicitly provided a dialect, use it
|
|
// Otherwise, if user provided a target, resolve it to dialect
|
|
// If neither, use the default dialect from opts
|
|
if (userOpts?.dialect !== undefined)
|
|
return opts; // dialect was already merged
|
|
if (userOpts?.target !== undefined) {
|
|
return {
|
|
...opts,
|
|
dialect: jsonSchemaTargetToDialect[userOpts.target]
|
|
};
|
|
}
|
|
return opts;
|
|
};
|
|
const mergeFallbacks = (base, merged) => {
|
|
base = normalizeFallback(base);
|
|
merged = normalizeFallback(merged);
|
|
const result = {};
|
|
let code;
|
|
for (code in ToJsonSchema.defaultConfig.fallback) {
|
|
result[code] =
|
|
merged[code] ??
|
|
merged.default ??
|
|
base[code] ??
|
|
base.default ??
|
|
ToJsonSchema.defaultConfig.fallback[code];
|
|
}
|
|
return result;
|
|
};
|
|
const normalizeFallback = (fallback) => typeof fallback === "function" ? { default: fallback } : (fallback ?? {});
|