alinea
Version:
[](https://npmjs.org/package/alinea) [](https://packagephobia.com/result?p=alinea)
119 lines (115 loc) • 3.63 kB
JavaScript
import "../../chunks/chunk-U5RRZUYZ.js";
// src/cli/generate/GenerateTypes.ts
import { Type } from "alinea/core";
import { Hint } from "alinea/core/Hint";
import { code } from "alinea/core/util/CodeGen";
import { Lazy } from "alinea/core/util/Lazy";
function generateTypes({ schema }) {
const types = code();
const hints = Object.values(schema).map(Type.hint);
const seen = /* @__PURE__ */ new Map();
const rootTypes = [];
for (const definition of Hint.definitions(hints)) {
if (seen.has(definition.name)) {
const previous = seen.get(definition.name);
if (Hint.equals(previous, definition))
continue;
throw new Error(
code`
${previous.parents.join(".")} ${generateHint(
Hint.Object(Lazy.get(previous.fields))
)}
${definition.parents.join(".")} ${generateHint(
Hint.Object(Lazy.get(definition.fields))
)}
Duplicate definition for "${definition.name}"
`.toString()
);
}
seen.set(definition.name, definition);
const fields = Object.entries(Lazy.get(definition.fields)).filter(
([name]) => name !== "type"
);
const isRootType = definition.parents.length === 0;
const extend = isRootType ? "Entry" : definition.extend.map(generateHint).join(", ");
types.push(code`
export interface ${definition.name} ${extend.length > 0 ? "extends " + extend + " " : ""}{
type: ${JSON.stringify(definition.name)}
${fields.map(([name, hint]) => code`${name}: ${generateHint(hint)}`).join("\n")}
}
`);
if (isRootType)
rootTypes.push(definition.name);
}
const imports = code();
for (const [pkg, externs] of Hint.externs(hints).entries()) {
imports.push(code`
import {${Array.from(externs).join(", ")}} from ${JSON.stringify(pkg)}
`);
}
return code`
import {Pages as AlineaPages} from 'alinea/backend'
import {Entry} from 'alinea/core'
${imports}
export namespace Page {
${types}
}
export type Page =
${rootTypes.map((name) => `| Page.${name}`).join("\n")}
export type Pages = AlineaPages<Page>
`;
}
function generateHint(hint) {
switch (hint.type) {
case "string":
return code`string`;
case "number":
return code`number`;
case "boolean":
return code`boolean`;
case "array":
return code`
Array<${generateHint(hint.inner)}>
`;
case "literal":
return code(JSON.stringify(hint.value));
case "definition":
return code(hint.name);
case "object":
return generateObject(hint);
case "union":
return generateUnion(hint);
case "intersection":
return generateIntersection(hint);
case "extern":
if (hint.typeParams.length === 0)
return code(hint.from.name);
return code`${hint.from.name}<${hint.typeParams.map(generateHint).join(", ")}>`;
default:
throw new Error(`Unknown hint type ${hint}`);
}
}
function generateObject(hint) {
const fields = Object.entries(hint.fields);
if (fields.length === 0)
return code`{}`;
return code`
{
${fields.map(([name, hint2]) => code`${name}: ${generateHint(hint2)}`).join("\n")}
}
`;
}
function generateUnion(hint) {
if (hint.options.length === 0)
return code`never`;
return code(hint.options.map((inner) => `${generateHint(inner)}`).join(" | "));
}
function generateIntersection(hint) {
if (hint.options.length === 0)
return code`never`;
return code(hint.options.map((inner) => `${generateHint(inner)}`).join(" & "));
}
export {
generateHint,
generateTypes
};