import { mkdirSync, writeFileSync } from 'node:fs'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; const scriptDir = dirname(fileURLToPath(import.meta.url)); // `tsx` resolves the library source's `.js` specifiers to the `.ts` files on disk. Node's type // stripping does not remap them. const contractPath = resolve(scriptDir, '../../../packages/@luke-ui/react/src/theme/contract.ts'); const outputPath = resolve(scriptDir, '../src/generated/token-reference.generated.ts'); const { flattenThemeContract } = (await import(contractPath)) as { flattenThemeContract: () => Array<[path: string, variable: string]>; }; interface GeneratedToken { family: string; path: string; variable: string; } /** * Emits the docs app's single runtime source of truth for the public token contract: one entry per * contract leaf, plus the family union those entries are keyed by. The token explorer renders from * this array, so the documented set can never drift from the set `flattenThemeContract()` produces. */ export function generateTokenReference(): string { const tokens = flattenThemeContract().map(([path, variable]): GeneratedToken => { const family = path.split('.')[0]; if (family === undefined) throw new Error(`Theme contract path "${path}" has no family`); return { family, path, variable }; }); const families = [...new Set(tokens.map((token) => token.family))]; const familyUnion = families.map((family) => `\n\t| ${quote(family)}`).join(''); const tokenEntries = tokens .map(({ family, path, variable }) => { return `\t{ family: ${quote(family)}, path: ${quote(path)}, variable: ${quote(variable)} },`; }) .join('\n'); return `// Generated by scripts/generate-token-reference.ts — do not edit. /** A top-level branch of the public theme contract, for example \`color\` or \`motion\`. */ export type ThemeTokenFamily =${familyUnion}; /** One public token: the \`vars\` path and the \`--luke-*\` custom property it resolves to. */ export interface ThemeToken { family: ThemeTokenFamily; path: string; variable: string; } /** Every leaf of the public theme contract, in contract order. */ export const themeTokens: ReadonlyArray = [ ${tokenEntries} ]; `; } function quote(text: string): string { return `'${text.replaceAll('\\', '\\\\').replaceAll("'", "\\'")}'`; } if (process.argv[1] !== undefined && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { const output = generateTokenReference(); mkdirSync(dirname(outputPath), { recursive: true }); writeFileSync(outputPath, output); // oxlint-disable-next-line no-console console.log(`generate-token-reference: wrote ${flattenThemeContract().length} token entries`); }