p1-polymorph-studio 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/brunoantunesluis/mathematica/01_engineering/p1-polymorph-studio/dist/chunk-HGZJ53NR.cjs","../src/utils/errors.ts","../src/utils/api.ts","../src/client/kuds.ts","../src/types/registry.ts","../src/types/kud.ts","../src/utils/diff.ts","../src/utils/cosine.ts","../src/client/kuis.ts","../src/client/layouts.ts","../src/client/tokens.ts","../src/utils/css-parser.ts","../src/client/config.ts","../src/types/kui.ts","../src/types/layout.ts","../src/types/config.ts","../src/types/tokens.ts","../src/index.ts"],"names":[],"mappings":"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A;AAChC;AAI4C;AACd,EAAA;AACD,EAAA;AACK,EAAA;AAC8B,EAAA;AAChE;AbsmBmE;AACA;AchrBlD;AAGqB;AACpB,EAAA;AACD,EAAA;AACkB,EAAA;AACY,EAAA;AAC/C;AAIwC;AACnB,EAAA;AACA,EAAA;AACH,EAAA;AACc,EAAA;AACF,EAAA;AACT,EAAA;AACA,EAAA;AACrB;AAI0C;AACxB,EAAA;AACZ,EAAA;AACW,EAAA;AACjB;AAI0C;AACxB,EAAA;AACgB,EAAA;AAClC;AAI+C;AACjB,EAAA;AAC9B;AdoqBmE;AACA;Ae9sBlD;AAEsB;AACT,EAAA;AACL,EAAA;AACT,EAAA;AACK,EAAA;AAEH,EAAA;AACE,IAAA;AACH,IAAA;AACwC,IAAA;AAC5C,EAAA;AAEG,EAAA;AACO,IAAA;AACI,IAAA;AACyB,IAAA;AACd,IAAA;AACzB,EAAA;AAEI,EAAA;AACI,IAAA;AACgC,IAAA;AACxC,EAAA;AAEE,EAAA;AACM,IAAA;AACF,IAAA;AACyB,IAAA;AAC/B,EAAA;AAEK,EAAA;AACA,IAAA;AACmB,IAAA;AACxB,EAAA;AACb;AAI8C;AACrB,EAAA;AACD,EAAA;AACI,EAAA;AACE,EAAA;AAC9B;AfusBmE;AACA;AgBrvBlD;AAEwB;AACpB,EAAA;AACA,EAAA;AACC,EAAA;AACN,EAAA;AAC6B,EAAA;AACD,EAAA;AACK,EAAA;AAC5B,EAAA;AACrB;AAIuC;AACpB,EAAA;AACS,EAAA;AACO,EAAA;AACnC;AhBmvBmE;AACA;AiBvvBE;AACjC,EAAA;AAE5B,EAAA;AACwC,IAAA;AACA,IAAA;AACM,IAAA;AACF,IAAA;AACA,IAAA;AACnD,EAAA;AACF;AjBwvBoE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/Users/brunoantunesluis/mathematica/01_engineering/p1-polymorph-studio/dist/chunk-HGZJ53NR.cjs","sourcesContent":[null,"export class LexApiError extends Error {\n constructor(\n message: string,\n public statusCode: number,\n public body: unknown,\n ) {\n super(message)\n this.name = 'LexApiError'\n }\n}\n\nexport class LexValidationError extends Error {\n constructor(\n message: string,\n public errors: string[],\n ) {\n super(message)\n this.name = 'LexValidationError'\n }\n}\n\nexport class LexConfigError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'LexConfigError'\n }\n}\n","import type { LexClientOptions } from '../types/config.js'\nimport { LexApiError } from './errors.js'\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)\n}\n\nfunction toCamelCase(str: string): string {\n return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())\n}\n\nfunction convertKeys(obj: unknown, converter: (key: string) => string): unknown {\n if (obj === null || obj === undefined) return obj\n if (Array.isArray(obj)) return obj.map((item) => convertKeys(item, converter))\n if (typeof obj === 'object') {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n result[converter(key)] = convertKeys(value, converter)\n }\n return result\n }\n return obj\n}\n\nexport function toApiPayload(obj: unknown): unknown {\n return convertKeys(obj, toSnakeCase)\n}\n\nexport function fromApiResponse(obj: unknown): unknown {\n return convertKeys(obj, toCamelCase)\n}\n\nexport interface ApiClient {\n get<T = unknown>(path: string, params?: Record<string, string>): Promise<T>\n post<T = unknown>(path: string, body?: unknown): Promise<T>\n put<T = unknown>(path: string, body?: unknown): Promise<T>\n del<T = unknown>(path: string): Promise<T>\n}\n\nexport function createApiClient(options: LexClientOptions): ApiClient {\n const { baseUrl, token, projectId } = options\n const fetchFn = options.fetch ?? globalThis.fetch\n\n async function request<T>(method: string, path: string, body?: unknown, params?: Record<string, string>): Promise<T> {\n const url = new URL(path, baseUrl)\n url.searchParams.set('project_id', projectId)\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value)\n }\n }\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n }\n\n const init: RequestInit = { method, headers }\n if (body !== undefined) {\n init.body = JSON.stringify(toApiPayload(body))\n }\n\n const response = await fetchFn(url.toString(), init)\n\n if (!response.ok) {\n let errorBody: unknown\n try {\n errorBody = await response.json()\n } catch {\n errorBody = await response.text()\n }\n throw new LexApiError(\n `API request failed: ${method} ${path} → ${response.status}`,\n response.status,\n errorBody,\n )\n }\n\n if (response.status === 204) return undefined as T\n\n const data = await response.json()\n return fromApiResponse(data) as T\n }\n\n return {\n get: <T>(path: string, params?: Record<string, string>) => request<T>('GET', path, undefined, params),\n post: <T>(path: string, body?: unknown) => request<T>('POST', path, body),\n put: <T>(path: string, body?: unknown) => request<T>('PUT', path, body),\n del: <T>(path: string) => request<T>('DELETE', path),\n }\n}\n","import { readFile, writeFile } from 'node:fs/promises'\nimport type { ApiClient } from '../utils/api.js'\nimport type { KUD, CreateKUDInput, UpdateKUDInput } from '../types/kud.js'\nimport type { KudRegistry, KudRegistryEntry } from '../types/registry.js'\nimport { KudRegistrySchema } from '../types/registry.js'\nimport { diffRegistryVsDatabase } from '../utils/diff.js'\n\nexport interface SyncResult {\n created: number\n updated: number\n deleted: number\n unchanged: number\n}\n\nexport interface KudsClient {\n list(): Promise<KUD[]>\n getByType(type: string): Promise<KUD | null>\n create(input: CreateKUDInput): Promise<KUD>\n update(id: string, input: UpdateKUDInput): Promise<KUD>\n delete(id: string): Promise<void>\n syncFromRegistry(registryPath: string): Promise<SyncResult>\n syncToRegistry(registryPath: string): Promise<void>\n}\n\nexport function createKudsClient(api: ApiClient, projectId: string): KudsClient {\n return {\n async list(): Promise<KUD[]> {\n return api.get<KUD[]>('/kuds')\n },\n\n async getByType(type: string): Promise<KUD | null> {\n const kuds = await api.get<KUD[]>('/kuds', { type })\n return kuds[0] ?? null\n },\n\n async create(input: CreateKUDInput): Promise<KUD> {\n return api.post<KUD>('/kuds', input)\n },\n\n async update(id: string, input: UpdateKUDInput): Promise<KUD> {\n return api.put<KUD>(`/kuds/${id}`, input)\n },\n\n async delete(id: string): Promise<void> {\n await api.del(`/kuds/${id}`)\n },\n\n async syncFromRegistry(registryPath: string): Promise<SyncResult> {\n const raw = await readFile(registryPath, 'utf-8')\n const registry = KudRegistrySchema.parse(JSON.parse(raw))\n const dbKuds = await api.get<KUD[]>('/kuds')\n\n const diff = diffRegistryVsDatabase(registry.kuds, dbKuds)\n\n for (const entry of diff.toCreate) {\n await api.post('/kuds', {\n type: entry.type,\n label: entry.label,\n schema: entry.schema,\n metadata: entry.metadata,\n })\n }\n\n for (const { entry, existingId } of diff.toUpdate) {\n await api.put(`/kuds/${existingId}`, {\n schema: entry.schema,\n label: entry.label,\n metadata: entry.metadata,\n })\n }\n\n for (const kud of diff.toDelete) {\n await api.del(`/kuds/${kud.id}`)\n }\n\n return {\n created: diff.toCreate.length,\n updated: diff.toUpdate.length,\n deleted: diff.toDelete.length,\n unchanged: diff.unchanged.length,\n }\n },\n\n async syncToRegistry(registryPath: string): Promise<void> {\n const dbKuds = await api.get<KUD[]>('/kuds')\n\n const registry: KudRegistry = {\n version: 1,\n projectId,\n generatedAt: new Date().toISOString(),\n kuds: dbKuds.map((kud) => ({\n type: kud.type,\n label: kud.label ?? undefined,\n version: kud.version,\n schema: kud.schema,\n metadata: kud.metadata ?? undefined,\n })),\n }\n\n await writeFile(registryPath, JSON.stringify(registry, null, 2) + '\\n', 'utf-8')\n },\n }\n}\n","import { z } from 'zod'\nimport { KUDFieldDefSchema } from './kud.js'\n\nexport const KudRegistryEntrySchema = z.object({\n type: z.string(),\n label: z.string().optional(),\n version: z.number().int().default(1),\n schema: z.record(z.string(), KUDFieldDefSchema),\n componentPath: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport type KudRegistryEntry = z.infer<typeof KudRegistryEntrySchema>\n\nexport const KudRegistrySchema = z.object({\n version: z.number().int().default(1),\n projectId: z.string(),\n generatedAt: z.string(),\n kuds: z.array(KudRegistryEntrySchema),\n})\n\nexport type KudRegistry = z.infer<typeof KudRegistrySchema>\n","import { z } from 'zod'\n\nexport const KUDFieldTypeSchema = z.enum([\n 'string',\n 'text',\n 'number',\n 'boolean',\n 'image',\n 'link',\n 'array',\n 'object',\n])\n\nexport type KUDFieldType = z.infer<typeof KUDFieldTypeSchema>\n\nexport const KUDFieldDefSchema: z.ZodType<KUDFieldDef> = z.lazy(() =>\n z.object({\n type: KUDFieldTypeSchema,\n required: z.boolean().optional(),\n description: z.string().optional(),\n items: KUDFieldDefSchema.optional(),\n properties: z.record(z.string(), KUDFieldDefSchema).optional(),\n })\n)\n\nexport interface KUDFieldDef {\n type: KUDFieldType\n required?: boolean\n description?: string\n items?: KUDFieldDef\n properties?: Record<string, KUDFieldDef>\n}\n\nexport const KUDSchema = z.object({\n id: z.string().uuid(),\n projectId: z.string(),\n type: z.string(),\n label: z.string().nullable().optional(),\n version: z.number().int().default(1),\n schema: z.record(z.string(), KUDFieldDefSchema),\n defaultKuiId: z.string().uuid().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n})\n\nexport type KUD = z.infer<typeof KUDSchema>\n\nexport const CreateKUDInputSchema = z.object({\n type: z.string().min(1),\n label: z.string().optional(),\n schema: z.record(z.string(), KUDFieldDefSchema),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport type CreateKUDInput = z.infer<typeof CreateKUDInputSchema>\n\nexport const UpdateKUDInputSchema = z.object({\n label: z.string().optional(),\n schema: z.record(z.string(), KUDFieldDefSchema).optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport type UpdateKUDInput = z.infer<typeof UpdateKUDInputSchema>\n","import type { KUD } from '../types/kud.js'\nimport type { KudRegistryEntry } from '../types/registry.js'\n\nexport interface DiffResult {\n toCreate: KudRegistryEntry[]\n toUpdate: Array<{ entry: KudRegistryEntry; existingId: string }>\n toDelete: KUD[]\n unchanged: KUD[]\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (a === null || b === null) return false\n if (typeof a !== typeof b) return false\n if (typeof a !== 'object') return false\n\n const aObj = a as Record<string, unknown>\n const bObj = b as Record<string, unknown>\n const aKeys = Object.keys(aObj)\n const bKeys = Object.keys(bObj)\n\n if (aKeys.length !== bKeys.length) return false\n\n return aKeys.every((key) => deepEqual(aObj[key], bObj[key]))\n}\n\nexport function diffRegistryVsDatabase(\n registry: KudRegistryEntry[],\n dbKuds: KUD[],\n): DiffResult {\n const dbByType = new Map(dbKuds.map((kud) => [kud.type, kud]))\n const registryTypes = new Set(registry.map((e) => e.type))\n\n const toCreate: KudRegistryEntry[] = []\n const toUpdate: Array<{ entry: KudRegistryEntry; existingId: string }> = []\n const unchanged: KUD[] = []\n\n for (const entry of registry) {\n const existing = dbByType.get(entry.type)\n if (!existing) {\n toCreate.push(entry)\n } else if (!deepEqual(entry.schema, existing.schema)) {\n toUpdate.push({ entry, existingId: existing.id })\n } else {\n unchanged.push(existing)\n }\n }\n\n const toDelete = dbKuds.filter((kud) => !registryTypes.has(kud.type))\n\n return { toCreate, toUpdate, toDelete, unchanged }\n}\n","export function cosineSimilarity(a: number[], b: number[]): number {\n if (a.length !== b.length) {\n throw new Error(`Vector length mismatch: ${a.length} vs ${b.length}`)\n }\n\n let dot = 0\n let magA = 0\n let magB = 0\n\n for (let i = 0; i < a.length; i++) {\n dot += a[i] * b[i]\n magA += a[i] * a[i]\n magB += b[i] * b[i]\n }\n\n const magnitude = Math.sqrt(magA) * Math.sqrt(magB)\n if (magnitude === 0) return 0\n\n return dot / magnitude\n}\n\nexport interface RankedCandidate {\n id: string\n score: number\n positionScore: number\n velocityScore: number\n}\n\nexport interface ScoringOptions {\n queryVector: number[]\n queryVelocity?: number[]\n velocityWeight?: number\n}\n\n/**\n * Compute a blended score from position similarity and velocity similarity.\n *\n * finalScore = (1 - velocityWeight) * positionSimilarity + velocityWeight * velocitySimilarity\n *\n * If either the candidate or the query has no velocity vector, only position\n * similarity is used (velocity contribution is 0).\n */\nexport function blendedScore(\n candidatePosition: number[],\n candidateVelocity: number[] | null | undefined,\n query: ScoringOptions,\n): { score: number; positionScore: number; velocityScore: number } {\n const positionScore = cosineSimilarity(candidatePosition, query.queryVector)\n\n const weight = query.velocityWeight ?? 0.3\n if (!query.queryVelocity || !candidateVelocity || weight === 0) {\n return { score: positionScore, positionScore, velocityScore: 0 }\n }\n\n const velocityScore = cosineSimilarity(candidateVelocity, query.queryVelocity)\n const score = (1 - weight) * positionScore + weight * velocityScore\n\n return { score, positionScore, velocityScore }\n}\n\nexport function rankBySimilarity(\n candidates: Array<{ id: string; vector: number[]; velocity?: number[] | null; priority?: number }>,\n query: ScoringOptions,\n): RankedCandidate[] {\n return candidates\n .map((c) => {\n const { score, positionScore, velocityScore } = blendedScore(\n c.vector,\n c.velocity,\n query,\n )\n return {\n id: c.id,\n score,\n positionScore,\n velocityScore,\n priority: c.priority ?? 0,\n }\n })\n .sort((a, b) => {\n const scoreDiff = b.score - a.score\n if (Math.abs(scoreDiff) > 1e-9) return scoreDiff\n return b.priority - a.priority\n })\n .map(({ id, score, positionScore, velocityScore }) => ({ id, score, positionScore, velocityScore }))\n}\n","import type { ApiClient } from '../utils/api.js'\nimport type { KUI, CreateKUIInput, UpdateKUIInput, ResolveKUIInput, ListKUIsFilter } from '../types/kui.js'\nimport { blendedScore } from '../utils/cosine.js'\nimport { LexApiError } from '../utils/errors.js'\n\nexport interface BulkImportResult {\n created: number\n errors: Array<{ index: number; error: string }>\n}\n\nexport interface KuisClient {\n list(filter?: ListKUIsFilter): Promise<KUI[]>\n resolve(input: ResolveKUIInput): Promise<KUI | null>\n create(input: CreateKUIInput): Promise<KUI>\n update(id: string, input: UpdateKUIInput): Promise<KUI>\n publish(id: string): Promise<KUI>\n archive(id: string): Promise<KUI>\n bulkImport(items: CreateKUIInput[]): Promise<BulkImportResult>\n}\n\nexport function createKuisClient(api: ApiClient, _projectId: string): KuisClient {\n return {\n async list(filter?: ListKUIsFilter): Promise<KUI[]> {\n const params: Record<string, string> = {}\n if (filter?.kudType) params.kud_type = filter.kudType\n if (filter?.locale) params.locale = filter.locale\n if (filter?.status) params.status = filter.status\n if (filter?.intentStage) params.intent_stage = filter.intentStage\n return api.get<KUI[]>('/kuis', params)\n },\n\n async resolve(input: ResolveKUIInput): Promise<KUI | null> {\n try {\n return await api.post<KUI>('/kuis/resolve', input)\n } catch (err) {\n if (err instanceof LexApiError && err.statusCode === 404) {\n // Fallback: local cosine similarity\n const kuis = await api.get<KUI[]>('/kuis', {\n kud_type: input.kudType,\n locale: input.locale,\n status: 'published',\n })\n\n if (kuis.length === 0) return null\n\n let bestKui: KUI | null = null\n let bestScore = -Infinity\n\n for (const kui of kuis) {\n const { score } = blendedScore(\n kui.intentAffinity,\n kui.intentVelocity,\n {\n queryVector: input.intentVector,\n queryVelocity: input.intentVelocity,\n velocityWeight: input.velocityWeight,\n },\n )\n if (score > bestScore || (score === bestScore && kui.priority > (bestKui?.priority ?? 0))) {\n bestScore = score\n bestKui = kui\n }\n }\n\n return bestKui\n }\n throw err\n }\n },\n\n async create(input: CreateKUIInput): Promise<KUI> {\n return api.post<KUI>('/kuis', input)\n },\n\n async update(id: string, input: UpdateKUIInput): Promise<KUI> {\n return api.put<KUI>(`/kuis/${id}`, input)\n },\n\n async publish(id: string): Promise<KUI> {\n return api.put<KUI>(`/kuis/${id}`, { status: 'published' })\n },\n\n async archive(id: string): Promise<KUI> {\n return api.put<KUI>(`/kuis/${id}`, { status: 'archived' })\n },\n\n async bulkImport(items: CreateKUIInput[]): Promise<BulkImportResult> {\n let created = 0\n const errors: Array<{ index: number; error: string }> = []\n\n for (let i = 0; i < items.length; i++) {\n try {\n await api.post('/kuis', items[i])\n created++\n } catch (err) {\n errors.push({\n index: i,\n error: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n return { created, errors }\n },\n }\n}\n","import type { ApiClient } from '../utils/api.js'\nimport type { PageLayout, ResolvedPage, UpdateLayoutInput } from '../types/layout.js'\nimport type { KUI } from '../types/kui.js'\nimport type { IntentVector } from '../types/kui.js'\nimport { blendedScore } from '../utils/cosine.js'\nimport { LexApiError } from '../utils/errors.js'\n\nexport interface ResolveLayoutOptions {\n locale?: string\n intentVector: IntentVector\n intentVelocity?: IntentVector\n velocityWeight?: number\n}\n\nexport interface LayoutsClient {\n get(pageId: string, locale?: string): Promise<PageLayout>\n update(pageId: string, locale: string, input: UpdateLayoutInput): Promise<PageLayout>\n resolve(pageId: string, opts: ResolveLayoutOptions): Promise<ResolvedPage>\n}\n\nexport function createLayoutsClient(api: ApiClient, _projectId: string): LayoutsClient {\n return {\n async get(pageId: string, locale?: string): Promise<PageLayout> {\n const params: Record<string, string> = {}\n if (locale) params.locale = locale\n return api.get<PageLayout>(`/layouts/${pageId}`, params)\n },\n\n async update(pageId: string, locale: string, input: UpdateLayoutInput): Promise<PageLayout> {\n return api.put<PageLayout>(`/layouts/${pageId}`, { locale, ...input })\n },\n\n async resolve(pageId: string, opts: ResolveLayoutOptions): Promise<ResolvedPage> {\n try {\n return await api.post<ResolvedPage>(`/layouts/${pageId}/resolve`, {\n locale: opts.locale ?? 'en',\n intentVector: opts.intentVector,\n intentVelocity: opts.intentVelocity,\n velocityWeight: opts.velocityWeight,\n })\n } catch (err) {\n if (err instanceof LexApiError && err.statusCode === 404) {\n // Fallback: local resolution\n const locale = opts.locale ?? 'en'\n const layout = await this.get(pageId, locale)\n\n const resolvedSlots = await Promise.all(\n layout.slots.map(async (slot) => {\n const kuis = await api.get<KUI[]>('/kuis', {\n kud_type: slot.kudId,\n locale,\n status: 'published',\n })\n\n let bestKui: KUI | null = null\n let bestScore = -Infinity\n\n for (const kui of kuis) {\n const { score } = blendedScore(\n kui.intentAffinity,\n kui.intentVelocity,\n {\n queryVector: opts.intentVector,\n queryVelocity: opts.intentVelocity,\n velocityWeight: opts.velocityWeight,\n },\n )\n if (score > bestScore || (score === bestScore && kui.priority > (bestKui?.priority ?? 0))) {\n bestScore = score\n bestKui = kui\n }\n }\n\n return {\n slotId: slot.slotId,\n kui: bestKui!,\n score: bestScore,\n }\n })\n )\n\n return {\n pageId,\n slots: resolvedSlots.filter((s) => s.kui !== null),\n }\n }\n throw err\n }\n },\n }\n}\n","import { readFile, writeFile } from 'node:fs/promises'\nimport type { ApiClient } from '../utils/api.js'\nimport type { DesignToken } from '../types/tokens.js'\nimport { extractTokensFromCSS, generateCSSFromTokens } from '../utils/css-parser.js'\n\nexport interface PullFromFigmaOptions {\n fileKey: string\n figmaToken: string\n}\n\nexport interface TokensClient {\n pushFromCode(cssPath: string): Promise<{ upserted: number }>\n pullToCode(cssPath: string): Promise<void>\n pullFromFigma(opts: PullFromFigmaOptions): Promise<{ synced: number }>\n exportDTCG(): Promise<Record<string, unknown>>\n}\n\nexport function createTokensClient(api: ApiClient, _projectId: string): TokensClient {\n return {\n async pushFromCode(cssPath: string): Promise<{ upserted: number }> {\n const css = await readFile(cssPath, 'utf-8')\n const extracted = extractTokensFromCSS(css)\n\n let upserted = 0\n for (const token of extracted) {\n await api.post('/tokens', {\n collection: token.collection,\n name: token.name,\n valueLight: token.value,\n })\n upserted++\n }\n\n return { upserted }\n },\n\n async pullToCode(cssPath: string): Promise<void> {\n const tokens = await api.get<DesignToken[]>('/tokens')\n const css = generateCSSFromTokens(tokens)\n await writeFile(cssPath, css, 'utf-8')\n },\n\n async pullFromFigma(opts: PullFromFigmaOptions): Promise<{ synced: number }> {\n const url = `https://api.figma.com/v1/files/${opts.fileKey}/variables/local`\n const response = await fetch(url, {\n headers: { 'X-Figma-Token': opts.figmaToken },\n })\n\n if (!response.ok) {\n throw new Error(`Figma API error: ${response.status} ${response.statusText}`)\n }\n\n const data = await response.json() as {\n meta: {\n variables: Record<string, {\n id: string\n name: string\n resolvedType: string\n valuesByMode: Record<string, unknown>\n }>\n variableCollections: Record<string, {\n name: string\n modes: Array<{ modeId: string; name: string }>\n }>\n }\n }\n\n let synced = 0\n const variables = Object.values(data.meta.variables)\n\n for (const variable of variables) {\n const collection = variable.resolvedType.toLowerCase() === 'color' ? 'colors' : 'other'\n const modes = Object.entries(variable.valuesByMode)\n const lightValue = modes[0]?.[1]\n const darkValue = modes[1]?.[1]\n\n await api.post('/tokens', {\n collection,\n name: variable.name,\n valueLight: lightValue,\n valueDark: darkValue,\n figmaVariableId: variable.id,\n })\n synced++\n }\n\n return { synced }\n },\n\n async exportDTCG(): Promise<Record<string, unknown>> {\n const tokens = await api.get<DesignToken[]>('/tokens')\n\n const dtcg: Record<string, unknown> = {}\n\n for (const token of tokens) {\n const parts = token.name.split('/')\n let current = dtcg\n for (let i = 0; i < parts.length - 1; i++) {\n if (!current[parts[i]]) current[parts[i]] = {}\n current = current[parts[i]] as Record<string, unknown>\n }\n\n const leafName = parts[parts.length - 1]\n current[leafName] = {\n $value: token.valueLight,\n $type: token.collection === 'colors' ? 'color' : token.collection,\n ...(token.valueDark ? { $extensions: { 'com.figma': { dark: token.valueDark } } } : {}),\n }\n }\n\n return dtcg\n },\n }\n}\n","import type { DesignToken } from '../types/tokens.js'\n\ninterface ExtractedToken {\n collection: string\n name: string\n value: string\n}\n\nfunction classifyToken(name: string): string {\n if (name.startsWith('--color-') || name.startsWith('--tw-color-')) return 'colors'\n if (name.startsWith('--font-') || name.startsWith('--tw-font-')) return 'typography'\n if (name.startsWith('--spacing-') || name.startsWith('--tw-spacing-')) return 'spacing'\n if (name.startsWith('--radius-') || name.startsWith('--tw-radius-')) return 'borderRadius'\n if (name.startsWith('--shadow-') || name.startsWith('--tw-shadow-')) return 'shadows'\n return 'other'\n}\n\nfunction stripPrefix(name: string): string {\n return name.replace(/^--(?:tw-)?/, '')\n}\n\nexport function extractTokensFromCSS(cssContent: string): ExtractedToken[] {\n const tokens: ExtractedToken[] = []\n\n // Match :root { ... } blocks\n const rootBlockRegex = /:root\\s*\\{([^}]+)\\}/g\n let match: RegExpExecArray | null\n\n while ((match = rootBlockRegex.exec(cssContent)) !== null) {\n const block = match[1]\n parseCustomProperties(block, tokens)\n }\n\n // Match @theme { ... } blocks (Tailwind v4)\n const themeBlockRegex = /@theme\\s*\\{([^}]+)\\}/g\n while ((match = themeBlockRegex.exec(cssContent)) !== null) {\n const block = match[1]\n parseCustomProperties(block, tokens)\n }\n\n return tokens\n}\n\nfunction parseCustomProperties(block: string, tokens: ExtractedToken[]): void {\n const propRegex = /(--[\\w-]+)\\s*:\\s*([^;]+);/g\n let match: RegExpExecArray | null\n\n while ((match = propRegex.exec(block)) !== null) {\n const name = match[1]\n const value = match[2].trim()\n tokens.push({\n collection: classifyToken(name),\n name: stripPrefix(name),\n value,\n })\n }\n}\n\nexport function generateCSSFromTokens(tokens: DesignToken[]): string {\n const lines: string[] = [':root {']\n\n for (const token of tokens) {\n const cssName = `--${token.name}`\n const value = token.valueLight ?? token.valueDark\n if (value !== null && value !== undefined) {\n lines.push(` ${cssName}: ${String(value)};`)\n }\n }\n\n lines.push('}')\n\n // Dark mode tokens\n const darkTokens = tokens.filter((t) => t.valueDark !== null && t.valueDark !== undefined)\n if (darkTokens.length > 0) {\n lines.push('')\n lines.push('@media (prefers-color-scheme: dark) {')\n lines.push(' :root {')\n for (const token of darkTokens) {\n lines.push(` --${token.name}: ${String(token.valueDark)};`)\n }\n lines.push(' }')\n lines.push('}')\n }\n\n return lines.join('\\n') + '\\n'\n}\n","import { readFile, writeFile, watch as fsWatch } from 'node:fs/promises'\nimport { watch as fsWatchSync } from 'node:fs'\nimport type { ApiClient } from '../utils/api.js'\nimport type { LexConfig } from '../types/config.js'\nimport type { KudRegistry } from '../types/registry.js'\nimport type { KUD } from '../types/kud.js'\n\nexport interface WatchOptions {\n paths: string[]\n onChange: (changedFile: string) => Promise<void> | void\n}\n\nexport interface ConfigClient {\n generate(outputPath?: string): Promise<void>\n generateRegistry(outputPath?: string): Promise<void>\n watch(opts: WatchOptions): () => void\n}\n\nexport function createConfigClient(api: ApiClient, projectId: string): ConfigClient {\n return {\n async generate(outputPath = '314-lex.config.json'): Promise<void> {\n let existing: Partial<LexConfig> = {}\n try {\n const raw = await readFile(outputPath, 'utf-8')\n existing = JSON.parse(raw)\n } catch {\n // No existing config, start fresh\n }\n\n const config: LexConfig = {\n $schema: 'https://unpkg.com/@314-lex/sdk/schema/config.json',\n version: 2,\n name: existing.name ?? projectId,\n projectId: existing.projectId ?? projectId,\n tokens: existing.tokens,\n kuds: existing.kuds,\n figma: existing.figma,\n api: existing.api ?? {\n baseUrl: 'env:POLYMORPH_BASE_URL',\n token: 'env:POLYMORPH_TOKEN',\n routes: '/api/314-lex',\n },\n github: existing.github,\n }\n\n await writeFile(outputPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8')\n },\n\n async generateRegistry(outputPath = 'kuds.registry.json'): Promise<void> {\n const dbKuds = await api.get<KUD[]>('/kuds')\n\n const registry: KudRegistry = {\n version: 1,\n projectId,\n generatedAt: new Date().toISOString(),\n kuds: dbKuds.map((kud) => ({\n type: kud.type,\n label: kud.label ?? undefined,\n version: kud.version,\n schema: kud.schema,\n metadata: kud.metadata ?? undefined,\n })),\n }\n\n await writeFile(outputPath, JSON.stringify(registry, null, 2) + '\\n', 'utf-8')\n },\n\n watch(opts: WatchOptions): () => void {\n const watchers: ReturnType<typeof fsWatchSync>[] = []\n\n for (const path of opts.paths) {\n const watcher = fsWatchSync(path, { recursive: true }, (_event, filename) => {\n if (filename) {\n opts.onChange(filename)\n }\n })\n watchers.push(watcher)\n }\n\n return () => {\n for (const watcher of watchers) {\n watcher.close()\n }\n }\n },\n }\n}\n","import { z } from 'zod'\n\nexport const IntentVectorSchema = z.tuple([\n z.number(),\n z.number(),\n z.number(),\n z.number(),\n z.number(),\n])\n\nexport type IntentVector = z.infer<typeof IntentVectorSchema>\n\nexport const KUIStatusSchema = z.enum(['draft', 'published', 'archived'])\n\nexport type KUIStatus = z.infer<typeof KUIStatusSchema>\n\nexport const KUISchema = z.object({\n id: z.string().uuid(),\n kudId: z.string().uuid(),\n kudType: z.string(),\n projectId: z.string(),\n locale: z.string().default('en'),\n intentAffinity: IntentVectorSchema,\n intentVelocity: IntentVectorSchema.nullable().optional(),\n priority: z.number().int().default(0),\n content: z.record(z.string(), z.unknown()),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n status: KUIStatusSchema.default('draft'),\n createdAt: z.string(),\n updatedAt: z.string(),\n})\n\nexport type KUI = z.infer<typeof KUISchema>\n\nexport const CreateKUIInputSchema = z.object({\n kudType: z.string().min(1),\n locale: z.string().default('en'),\n intentAffinity: IntentVectorSchema,\n intentVelocity: IntentVectorSchema.optional(),\n priority: z.number().int().default(0),\n content: z.record(z.string(), z.unknown()),\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport type CreateKUIInput = z.infer<typeof CreateKUIInputSchema>\n\nexport const UpdateKUIInputSchema = z.object({\n locale: z.string().optional(),\n intentAffinity: IntentVectorSchema.optional(),\n intentVelocity: IntentVectorSchema.nullable().optional(),\n priority: z.number().int().optional(),\n content: z.record(z.string(), z.unknown()).optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n status: KUIStatusSchema.optional(),\n})\n\nexport type UpdateKUIInput = z.infer<typeof UpdateKUIInputSchema>\n\nexport const ResolveKUIInputSchema = z.object({\n kudType: z.string().min(1),\n intentVector: IntentVectorSchema,\n intentVelocity: IntentVectorSchema.optional(),\n velocityWeight: z.number().min(0).max(1).default(0.3),\n locale: z.string().default('en'),\n})\n\nexport type ResolveKUIInput = z.infer<typeof ResolveKUIInputSchema>\n\nexport const ListKUIsFilterSchema = z.object({\n kudType: z.string().optional(),\n locale: z.string().optional(),\n status: KUIStatusSchema.optional(),\n intentStage: z.enum(['awareness', 'interest', 'consideration', 'decision', 'evaluation']).optional(),\n})\n\nexport type ListKUIsFilter = z.infer<typeof ListKUIsFilterSchema>\n","import { z } from 'zod'\nimport { KUISchema } from './kui.js'\n\nexport const PageSlotSchema = z.object({\n slotId: z.string(),\n kudId: z.string(),\n required: z.boolean().default(true),\n candidateKuiIds: z.array(z.string()).optional(),\n})\n\nexport type PageSlot = z.infer<typeof PageSlotSchema>\n\nexport const PageLayoutSchema = z.object({\n id: z.string().uuid(),\n projectId: z.string(),\n pageId: z.string(),\n locale: z.string().default('en'),\n slots: z.array(PageSlotSchema),\n createdAt: z.string(),\n updatedAt: z.string(),\n})\n\nexport type PageLayout = z.infer<typeof PageLayoutSchema>\n\nexport const ResolvedSlotSchema = z.object({\n slotId: z.string(),\n kui: KUISchema,\n score: z.number(),\n})\n\nexport type ResolvedSlot = z.infer<typeof ResolvedSlotSchema>\n\nexport const ResolvedPageSchema = z.object({\n pageId: z.string(),\n slots: z.array(ResolvedSlotSchema),\n})\n\nexport type ResolvedPage = z.infer<typeof ResolvedPageSchema>\n\nexport const UpdateLayoutInputSchema = z.object({\n slots: z.array(PageSlotSchema),\n})\n\nexport type UpdateLayoutInput = z.infer<typeof UpdateLayoutInputSchema>\n","import { z } from 'zod'\n\nexport const LexConfigSchema = z.object({\n $schema: z.string().optional(),\n version: z.number().int(),\n name: z.string(),\n projectId: z.string(),\n\n tokens: z.object({\n source: z.string(),\n css: z.string(),\n overrides: z.record(z.string(), z.unknown()).optional(),\n }).optional(),\n\n kuds: z.object({\n typesFile: z.string(),\n componentsDir: z.string(),\n registry: z.string().default('kuds.registry.json'),\n autoSync: z.boolean().default(false),\n }).optional(),\n\n figma: z.object({\n fileKey: z.string(),\n variableCollections: z.array(z.string()).optional(),\n }).optional(),\n\n api: z.object({\n baseUrl: z.string(),\n token: z.string(),\n routes: z.string().default('/api/314-lex'),\n }).optional(),\n\n github: z.object({\n repo: z.string(),\n branchPrefix: z.string().optional(),\n }).optional(),\n})\n\nexport type LexConfig = z.infer<typeof LexConfigSchema>\n\nexport const LexClientOptionsSchema = z.object({\n baseUrl: z.string().url(),\n token: z.string().min(1),\n projectId: z.string().min(1),\n fetch: z.function().optional(),\n})\n\nexport interface LexClientOptions {\n baseUrl: string\n token: string\n projectId: string\n fetch?: typeof globalThis.fetch\n}\n","import { z } from 'zod'\n\nexport const DesignTokenSchema = z.object({\n id: z.string().uuid(),\n projectId: z.string(),\n collection: z.string(),\n name: z.string(),\n valueLight: z.unknown().nullable().optional(),\n valueDark: z.unknown().nullable().optional(),\n figmaVariableId: z.string().nullable().optional(),\n updatedAt: z.string(),\n})\n\nexport type DesignToken = z.infer<typeof DesignTokenSchema>\n\nexport const DTCGTokenSchema = z.object({\n $value: z.unknown(),\n $type: z.string().optional(),\n $description: z.string().optional(),\n})\n\nexport type DTCGToken = z.infer<typeof DTCGTokenSchema>\n","import type { LexClientOptions } from './types/config.js'\nimport { createApiClient } from './utils/api.js'\nimport { createKudsClient, type KudsClient } from './client/kuds.js'\nimport { createKuisClient, type KuisClient } from './client/kuis.js'\nimport { createLayoutsClient, type LayoutsClient } from './client/layouts.js'\nimport { createTokensClient, type TokensClient } from './client/tokens.js'\nimport { createConfigClient, type ConfigClient } from './client/config.js'\n\nexport interface LexClient {\n kuds: KudsClient\n kuis: KuisClient\n layouts: LayoutsClient\n tokens: TokensClient\n config: ConfigClient\n}\n\nexport function createLexClient(options: LexClientOptions): LexClient {\n const api = createApiClient(options)\n\n return {\n kuds: createKudsClient(api, options.projectId),\n kuis: createKuisClient(api, options.projectId),\n layouts: createLayoutsClient(api, options.projectId),\n tokens: createTokensClient(api, options.projectId),\n config: createConfigClient(api, options.projectId),\n }\n}\n\n// Re-export all types\nexport * from './types/index.js'\n\n// Re-export errors\nexport { LexApiError, LexValidationError, LexConfigError } from './utils/errors.js'\n\n// Re-export client types\nexport type { SyncResult } from './client/kuds.js'\nexport type { BulkImportResult } from './client/kuis.js'\nexport type { ResolveLayoutOptions } from './client/layouts.js'\nexport type { PullFromFigmaOptions } from './client/tokens.js'\nexport type { WatchOptions } from './client/config.js'\n"]}
@@ -0,0 +1,423 @@
1
+ "use strict"; function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+
5
+
6
+ var _chunkHGZJ53NRcjs = require('../chunk-HGZJ53NR.cjs');
7
+
8
+ // src/cli/index.ts
9
+ var _commander = require('commander');
10
+
11
+ // src/cli/commands/init.ts
12
+ var _promises = require('fs/promises');
13
+ var _path = require('path');
14
+ function registerInitCommand(program2) {
15
+ program2.command("init").description("Initialize 314-lex config for a new project").option("-n, --name <name>", "Project name").option("-p, --project-id <id>", "Project ID").action(async (opts) => {
16
+ const configPath = _path.resolve.call(void 0, process.cwd(), "314-lex.config.json");
17
+ const registryPath = _path.resolve.call(void 0, process.cwd(), "kuds.registry.json");
18
+ try {
19
+ await _promises.access.call(void 0, configPath);
20
+ console.log("314-lex.config.json already exists. Skipping.");
21
+ return;
22
+ } catch (e) {
23
+ }
24
+ const name = _nullishCoalesce(opts.name, () => ( "my-project"));
25
+ const projectId = _nullishCoalesce(opts.projectId, () => ( `proj_${name.toLowerCase().replace(/\s+/g, "_")}`));
26
+ const config = {
27
+ $schema: "https://unpkg.com/@314-lex/sdk/schema/config.json",
28
+ version: 2,
29
+ name,
30
+ projectId,
31
+ tokens: {
32
+ source: "tailwind-v4",
33
+ css: "src/app/globals.css"
34
+ },
35
+ kuds: {
36
+ typesFile: "src/types/intent.ts",
37
+ componentsDir: "src/components/sections/",
38
+ registry: "kuds.registry.json",
39
+ autoSync: false
40
+ },
41
+ api: {
42
+ baseUrl: "env:POLYMORPH_BASE_URL",
43
+ token: "env:POLYMORPH_TOKEN",
44
+ routes: "/api/314-lex"
45
+ }
46
+ };
47
+ const registry = {
48
+ version: 1,
49
+ projectId,
50
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
51
+ kuds: []
52
+ };
53
+ await _promises.writeFile.call(void 0, configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
54
+ await _promises.writeFile.call(void 0, registryPath, JSON.stringify(registry, null, 2) + "\n", "utf-8");
55
+ console.log("Created 314-lex.config.json");
56
+ console.log("Created kuds.registry.json");
57
+ console.log(`
58
+ Project: ${name} (${projectId})`);
59
+ console.log("\nNext steps:");
60
+ console.log(" 1. Set POLYMORPH_BASE_URL and POLYMORPH_TOKEN env vars");
61
+ console.log(' 2. Run "314-lex extract" to scan your codebase for KUD types');
62
+ console.log(' 3. Run "314-lex push kuds" to sync to the database');
63
+ });
64
+ }
65
+
66
+ // src/cli/commands/extract.ts
67
+
68
+
69
+
70
+ // src/cli/helpers.ts
71
+
72
+
73
+ async function loadConfig(configPath) {
74
+ const path = _nullishCoalesce(configPath, () => ( _path.resolve.call(void 0, process.cwd(), "314-lex.config.json")));
75
+ try {
76
+ const raw = await _promises.readFile.call(void 0, path, "utf-8");
77
+ return _chunkHGZJ53NRcjs.LexConfigSchema.parse(JSON.parse(raw));
78
+ } catch (err) {
79
+ if (err.code === "ENOENT") {
80
+ throw new (0, _chunkHGZJ53NRcjs.LexConfigError)(`Config file not found: ${path}. Run "314-lex init" first.`);
81
+ }
82
+ throw err;
83
+ }
84
+ }
85
+ function resolveEnvValue(value) {
86
+ if (value.startsWith("env:")) {
87
+ const envVar = value.slice(4);
88
+ const envValue = process.env[envVar];
89
+ if (!envValue) {
90
+ throw new (0, _chunkHGZJ53NRcjs.LexConfigError)(`Environment variable ${envVar} is not set`);
91
+ }
92
+ return envValue;
93
+ }
94
+ return value;
95
+ }
96
+ function createClientFromEnv(config) {
97
+ const baseUrl = _nullishCoalesce(process.env.POLYMORPH_BASE_URL, () => ( (_optionalChain([config, 'optionalAccess', _ => _.api, 'optionalAccess', _2 => _2.baseUrl]) ? resolveEnvValue(config.api.baseUrl) : void 0)));
98
+ const token = _nullishCoalesce(process.env.POLYMORPH_TOKEN, () => ( (_optionalChain([config, 'optionalAccess', _3 => _3.api, 'optionalAccess', _4 => _4.token]) ? resolveEnvValue(config.api.token) : void 0)));
99
+ const projectId = _nullishCoalesce(process.env.LEX_PROJECT_ID, () => ( _optionalChain([config, 'optionalAccess', _5 => _5.projectId])));
100
+ if (!baseUrl) throw new (0, _chunkHGZJ53NRcjs.LexConfigError)("POLYMORPH_BASE_URL is required");
101
+ if (!token) throw new (0, _chunkHGZJ53NRcjs.LexConfigError)("POLYMORPH_TOKEN is required");
102
+ if (!projectId) throw new (0, _chunkHGZJ53NRcjs.LexConfigError)("Project ID is required (set LEX_PROJECT_ID or configure projectId in config)");
103
+ return _chunkHGZJ53NRcjs.createLexClient.call(void 0, { baseUrl, token, projectId });
104
+ }
105
+ function printSyncResult(result) {
106
+ console.log(` Created: ${result.created}`);
107
+ console.log(` Updated: ${result.updated}`);
108
+ console.log(` Deleted: ${result.deleted}`);
109
+ console.log(` Unchanged: ${result.unchanged}`);
110
+ }
111
+
112
+ // src/cli/commands/extract.ts
113
+ function registerExtractCommand(program2) {
114
+ program2.command("extract").description("Extract KUD types from codebase into kuds.registry.json").option("-c, --config <path>", "Path to 314-lex.config.json").action(async (opts) => {
115
+ const config = await loadConfig(opts.config);
116
+ const kudsConfig = config.kuds;
117
+ if (!kudsConfig) {
118
+ console.error('No "kuds" section in config. Add typesFile and componentsDir.');
119
+ process.exit(1);
120
+ }
121
+ const typesFile = _path.resolve.call(void 0, process.cwd(), kudsConfig.typesFile);
122
+ const componentsDir = _path.resolve.call(void 0, process.cwd(), kudsConfig.componentsDir);
123
+ const registryPath = _path.resolve.call(void 0, process.cwd(), kudsConfig.registry);
124
+ console.log(`Scanning ${kudsConfig.typesFile}...`);
125
+ const typesContent = await _promises.readFile.call(void 0, typesFile, "utf-8");
126
+ const kudTypes = extractKUDTypes(typesContent);
127
+ if (kudTypes.length === 0) {
128
+ console.log('No KUD types found. Expected a union type like: type KUDType = "hero" | "cta" | ...');
129
+ return;
130
+ }
131
+ console.log(`Found ${kudTypes.length} KUD types: ${kudTypes.join(", ")}`);
132
+ const componentMap = await scanComponents(componentsDir);
133
+ const entries = kudTypes.map((type) => {
134
+ const componentPath = componentMap.get(type);
135
+ return {
136
+ type,
137
+ label: type.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" "),
138
+ version: 1,
139
+ schema: {},
140
+ ...componentPath ? { componentPath: _path.relative.call(void 0, process.cwd(), componentPath) } : {}
141
+ };
142
+ });
143
+ const registry = {
144
+ version: 1,
145
+ projectId: config.projectId,
146
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
147
+ kuds: entries
148
+ };
149
+ await _promises.writeFile.call(void 0, registryPath, JSON.stringify(registry, null, 2) + "\n", "utf-8");
150
+ console.log(`
151
+ Wrote ${entries.length} KUDs to ${kudsConfig.registry}`);
152
+ });
153
+ }
154
+ function extractKUDTypes(content) {
155
+ const unionRegex = /(?:export\s+)?type\s+KUDType\s*=\s*([^;]+)/;
156
+ const match = content.match(unionRegex);
157
+ if (!match) return [];
158
+ const unionBody = match[1];
159
+ const stringLiterals = unionBody.match(/['"]([^'"]+)['"]/g);
160
+ if (!stringLiterals) return [];
161
+ return stringLiterals.map((s) => s.replace(/['"]/g, ""));
162
+ }
163
+ async function scanComponents(dir) {
164
+ const map = /* @__PURE__ */ new Map();
165
+ try {
166
+ const entries = await _promises.readdir.call(void 0, dir, { withFileTypes: true });
167
+ for (const entry of entries) {
168
+ if (entry.isDirectory()) {
169
+ const name = entry.name.toLowerCase();
170
+ const fullPath = _path.join.call(void 0, dir, entry.name);
171
+ map.set(name, fullPath);
172
+ } else if (entry.isFile() && /\.(tsx?|jsx?)$/.test(entry.name)) {
173
+ const name = entry.name.replace(/\.(tsx?|jsx?)$/, "").toLowerCase();
174
+ const kebab = name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
175
+ map.set(kebab, _path.join.call(void 0, dir, entry.name));
176
+ }
177
+ }
178
+ } catch (e2) {
179
+ }
180
+ return map;
181
+ }
182
+
183
+ // src/cli/commands/push.ts
184
+
185
+ function registerPushCommand(program2) {
186
+ program2.command("push <target>").description("Push data to the database (kuds or tokens)").option("-c, --config <path>", "Path to 314-lex.config.json").action(async (target, opts) => {
187
+ const config = await loadConfig(opts.config);
188
+ const lex = createClientFromEnv(config);
189
+ switch (target) {
190
+ case "kuds": {
191
+ const registryPath = _path.resolve.call(void 0, process.cwd(), _nullishCoalesce(_optionalChain([config, 'access', _6 => _6.kuds, 'optionalAccess', _7 => _7.registry]), () => ( "kuds.registry.json")));
192
+ console.log(`Pushing KUDs from ${registryPath} to database...`);
193
+ const result = await lex.kuds.syncFromRegistry(registryPath);
194
+ console.log("KUD sync complete:");
195
+ printSyncResult(result);
196
+ break;
197
+ }
198
+ case "tokens": {
199
+ const cssPath = _path.resolve.call(void 0, process.cwd(), _nullishCoalesce(_optionalChain([config, 'access', _8 => _8.tokens, 'optionalAccess', _9 => _9.css]), () => ( "src/app/globals.css")));
200
+ console.log(`Pushing tokens from ${cssPath} to database...`);
201
+ const result = await lex.tokens.pushFromCode(cssPath);
202
+ console.log(`Token sync complete: ${result.upserted} tokens upserted`);
203
+ break;
204
+ }
205
+ default:
206
+ console.error(`Unknown target: ${target}. Use "kuds" or "tokens".`);
207
+ process.exit(1);
208
+ }
209
+ });
210
+ }
211
+
212
+ // src/cli/commands/pull.ts
213
+
214
+ function registerPullCommand(program2) {
215
+ program2.command("pull <target>").description("Pull data from the database (kuds or tokens)").option("-c, --config <path>", "Path to 314-lex.config.json").action(async (target, opts) => {
216
+ const config = await loadConfig(opts.config);
217
+ const lex = createClientFromEnv(config);
218
+ switch (target) {
219
+ case "kuds": {
220
+ const registryPath = _path.resolve.call(void 0, process.cwd(), _nullishCoalesce(_optionalChain([config, 'access', _10 => _10.kuds, 'optionalAccess', _11 => _11.registry]), () => ( "kuds.registry.json")));
221
+ console.log(`Pulling KUDs from database to ${registryPath}...`);
222
+ await lex.kuds.syncToRegistry(registryPath);
223
+ console.log("KUD pull complete.");
224
+ break;
225
+ }
226
+ case "tokens": {
227
+ const cssPath = _path.resolve.call(void 0, process.cwd(), _nullishCoalesce(_optionalChain([config, 'access', _12 => _12.tokens, 'optionalAccess', _13 => _13.css]), () => ( "src/app/globals.css")));
228
+ console.log(`Pulling tokens from database to ${cssPath}...`);
229
+ await lex.tokens.pullToCode(cssPath);
230
+ console.log("Token pull complete.");
231
+ break;
232
+ }
233
+ default:
234
+ console.error(`Unknown target: ${target}. Use "kuds" or "tokens".`);
235
+ process.exit(1);
236
+ }
237
+ });
238
+ }
239
+
240
+ // src/cli/commands/sync.ts
241
+
242
+ function registerSyncCommand(program2) {
243
+ program2.command("sync").description("Bidirectional sync of KUDs and tokens").option("-c, --config <path>", "Path to 314-lex.config.json").option("--prefer-local", "Prefer local registry over database on conflicts").action(async (opts) => {
244
+ const config = await loadConfig(opts.config);
245
+ const lex = createClientFromEnv(config);
246
+ const registryPath = _path.resolve.call(void 0, process.cwd(), _nullishCoalesce(_optionalChain([config, 'access', _14 => _14.kuds, 'optionalAccess', _15 => _15.registry]), () => ( "kuds.registry.json")));
247
+ if (opts.preferLocal) {
248
+ console.log("Syncing KUDs (local \u2192 database)...");
249
+ const result = await lex.kuds.syncFromRegistry(registryPath);
250
+ console.log("KUD sync complete:");
251
+ printSyncResult(result);
252
+ } else {
253
+ console.log("Syncing KUDs (database \u2192 local)...");
254
+ await lex.kuds.syncToRegistry(registryPath);
255
+ console.log("KUD pull complete.");
256
+ }
257
+ if (_optionalChain([config, 'access', _16 => _16.tokens, 'optionalAccess', _17 => _17.css])) {
258
+ const cssPath = _path.resolve.call(void 0, process.cwd(), config.tokens.css);
259
+ if (opts.preferLocal) {
260
+ console.log("\nSyncing tokens (local \u2192 database)...");
261
+ const result = await lex.tokens.pushFromCode(cssPath);
262
+ console.log(`Token sync complete: ${result.upserted} tokens upserted`);
263
+ } else {
264
+ console.log("\nSyncing tokens (database \u2192 local)...");
265
+ await lex.tokens.pullToCode(cssPath);
266
+ console.log("Token pull complete.");
267
+ }
268
+ }
269
+ console.log("\nSync complete.");
270
+ });
271
+ }
272
+
273
+ // src/cli/commands/validate.ts
274
+
275
+
276
+ function registerValidateCommand(program2) {
277
+ program2.command("validate").description("Validate 314-lex.config.json and kuds.registry.json").option("-c, --config <path>", "Path to 314-lex.config.json").action(async (opts) => {
278
+ let hasErrors = false;
279
+ const configPath = _nullishCoalesce(opts.config, () => ( _path.resolve.call(void 0, process.cwd(), "314-lex.config.json")));
280
+ console.log(`Validating ${configPath}...`);
281
+ try {
282
+ const raw = await _promises.readFile.call(void 0, configPath, "utf-8");
283
+ const result = _chunkHGZJ53NRcjs.LexConfigSchema.safeParse(JSON.parse(raw));
284
+ if (result.success) {
285
+ console.log(" Config: valid");
286
+ } else {
287
+ console.error(" Config: invalid");
288
+ for (const issue of result.error.issues) {
289
+ console.error(` - ${issue.path.join(".")}: ${issue.message}`);
290
+ }
291
+ hasErrors = true;
292
+ }
293
+ } catch (err) {
294
+ console.error(` Config: ${err.message}`);
295
+ hasErrors = true;
296
+ }
297
+ const registryPath = _path.resolve.call(void 0, process.cwd(), "kuds.registry.json");
298
+ console.log(`Validating ${registryPath}...`);
299
+ try {
300
+ const raw = await _promises.readFile.call(void 0, registryPath, "utf-8");
301
+ const result = _chunkHGZJ53NRcjs.KudRegistrySchema.safeParse(JSON.parse(raw));
302
+ if (result.success) {
303
+ console.log(` Registry: valid (${result.data.kuds.length} KUDs)`);
304
+ } else {
305
+ console.error(" Registry: invalid");
306
+ for (const issue of result.error.issues) {
307
+ console.error(` - ${issue.path.join(".")}: ${issue.message}`);
308
+ }
309
+ hasErrors = true;
310
+ }
311
+ } catch (err) {
312
+ console.error(` Registry: ${err.message}`);
313
+ hasErrors = true;
314
+ }
315
+ console.log("\nEnvironment:");
316
+ const baseUrl = process.env.POLYMORPH_BASE_URL;
317
+ const token = process.env.POLYMORPH_TOKEN;
318
+ console.log(` POLYMORPH_BASE_URL: ${baseUrl ? "set" : "NOT SET"}`);
319
+ console.log(` POLYMORPH_TOKEN: ${token ? "set" : "NOT SET"}`);
320
+ if (!baseUrl || !token) {
321
+ console.log("\n Warning: Required env vars are missing. API operations will fail.");
322
+ }
323
+ if (hasErrors) {
324
+ process.exit(1);
325
+ } else {
326
+ console.log("\nAll validations passed.");
327
+ }
328
+ });
329
+ }
330
+
331
+ // src/cli/commands/codegen.ts
332
+
333
+
334
+
335
+ function registerCodegenCommand(program2) {
336
+ program2.command("codegen").description("Generate TypeScript types from kuds.registry.json").option("-c, --config <path>", "Path to 314-lex.config.json").option("-o, --output <path>", "Output file path (defaults to src/types/generated-kuds.ts)").action(async (opts) => {
337
+ const config = await loadConfig(opts.config);
338
+ const registryPath = _path.resolve.call(void 0, process.cwd(), _nullishCoalesce(_optionalChain([config, 'access', _18 => _18.kuds, 'optionalAccess', _19 => _19.registry]), () => ( "kuds.registry.json")));
339
+ const raw = await _promises.readFile.call(void 0, registryPath, "utf-8");
340
+ const registry = _chunkHGZJ53NRcjs.KudRegistrySchema.parse(JSON.parse(raw));
341
+ if (registry.kuds.length === 0) {
342
+ console.log("No KUDs found in registry. Nothing to generate.");
343
+ return;
344
+ }
345
+ const outputPath = _nullishCoalesce(opts.output, () => ( _path.resolve.call(void 0, process.cwd(), "src/types/generated-kuds.ts")));
346
+ await _promises.mkdir.call(void 0, _path.dirname.call(void 0, outputPath), { recursive: true });
347
+ const lines = [
348
+ "// Auto-generated by 314-lex codegen",
349
+ `// Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}`,
350
+ "// Do not edit manually",
351
+ ""
352
+ ];
353
+ const types = registry.kuds.map((k) => `'${k.type}'`);
354
+ lines.push(`export type KUDType = ${types.join(" | ")}`);
355
+ lines.push("");
356
+ for (const kud of registry.kuds) {
357
+ const interfaceName = toPascalCase(kud.type) + "Content";
358
+ lines.push(`export interface ${interfaceName} {`);
359
+ for (const [fieldName, fieldDef] of Object.entries(kud.schema)) {
360
+ const tsType = fieldDefToTSType(fieldDef);
361
+ const optional = fieldDef.required ? "" : "?";
362
+ lines.push(` ${fieldName}${optional}: ${tsType}`);
363
+ }
364
+ lines.push("}");
365
+ lines.push("");
366
+ }
367
+ lines.push("export interface KUDContentMap {");
368
+ for (const kud of registry.kuds) {
369
+ const interfaceName = toPascalCase(kud.type) + "Content";
370
+ lines.push(` '${kud.type}': ${interfaceName}`);
371
+ }
372
+ lines.push("}");
373
+ lines.push("");
374
+ await _promises.writeFile.call(void 0, outputPath, lines.join("\n"), "utf-8");
375
+ console.log(`Generated ${registry.kuds.length} type definitions to ${outputPath}`);
376
+ });
377
+ }
378
+ function toPascalCase(str) {
379
+ return str.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
380
+ }
381
+ function fieldDefToTSType(fieldDef) {
382
+ switch (fieldDef.type) {
383
+ case "string":
384
+ case "text":
385
+ case "link":
386
+ return "string";
387
+ case "number":
388
+ return "number";
389
+ case "boolean":
390
+ return "boolean";
391
+ case "image":
392
+ return "{ url: string; alt?: string }";
393
+ case "array":
394
+ if (fieldDef.items) {
395
+ return `${fieldDefToTSType(fieldDef.items)}[]`;
396
+ }
397
+ return "unknown[]";
398
+ case "object":
399
+ if (fieldDef.properties) {
400
+ const props = Object.entries(fieldDef.properties).map(([name, def]) => {
401
+ const opt = def.required ? "" : "?";
402
+ return `${name}${opt}: ${fieldDefToTSType(def)}`;
403
+ }).join("; ");
404
+ return `{ ${props} }`;
405
+ }
406
+ return "Record<string, unknown>";
407
+ default:
408
+ return "unknown";
409
+ }
410
+ }
411
+
412
+ // src/cli/index.ts
413
+ var program = new (0, _commander.Command)();
414
+ program.name("314-lex").description("CLI for p1-polymorph-studio \u2014 KUD/KUI database sync & config management").version("0.1.0");
415
+ registerInitCommand(program);
416
+ registerExtractCommand(program);
417
+ registerPushCommand(program);
418
+ registerPullCommand(program);
419
+ registerSyncCommand(program);
420
+ registerValidateCommand(program);
421
+ registerCodegenCommand(program);
422
+ program.parse();
423
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/brunoantunesluis/mathematica/01_engineering/p1-polymorph-studio/dist/cli/index.cjs","../../src/cli/index.ts","../../src/cli/commands/init.ts","../../src/cli/commands/extract.ts","../../src/cli/helpers.ts","../../src/cli/commands/push.ts","../../src/cli/commands/pull.ts","../../src/cli/commands/sync.ts","../../src/cli/commands/validate.ts","../../src/cli/commands/codegen.ts"],"names":["program"],"mappings":"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","file":"/Users/brunoantunesluis/mathematica/01_engineering/p1-polymorph-studio/dist/cli/index.cjs","sourcesContent":[null,"import { Command } from 'commander'\nimport { registerInitCommand } from './commands/init.js'\nimport { registerExtractCommand } from './commands/extract.js'\nimport { registerPushCommand } from './commands/push.js'\nimport { registerPullCommand } from './commands/pull.js'\nimport { registerSyncCommand } from './commands/sync.js'\nimport { registerValidateCommand } from './commands/validate.js'\nimport { registerCodegenCommand } from './commands/codegen.js'\n\nconst program = new Command()\n\nprogram\n .name('314-lex')\n .description('CLI for p1-polymorph-studio — KUD/KUI database sync & config management')\n .version('0.1.0')\n\nregisterInitCommand(program)\nregisterExtractCommand(program)\nregisterPushCommand(program)\nregisterPullCommand(program)\nregisterSyncCommand(program)\nregisterValidateCommand(program)\nregisterCodegenCommand(program)\n\nprogram.parse()\n","import { writeFile, access } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport type { Command } from 'commander'\nimport type { LexConfig } from '../../types/config.js'\nimport type { KudRegistry } from '../../types/registry.js'\n\nexport function registerInitCommand(program: Command): void {\n program\n .command('init')\n .description('Initialize 314-lex config for a new project')\n .option('-n, --name <name>', 'Project name')\n .option('-p, --project-id <id>', 'Project ID')\n .action(async (opts) => {\n const configPath = resolve(process.cwd(), '314-lex.config.json')\n const registryPath = resolve(process.cwd(), 'kuds.registry.json')\n\n // Check if config already exists\n try {\n await access(configPath)\n console.log('314-lex.config.json already exists. Skipping.')\n return\n } catch {\n // File doesn't exist, proceed\n }\n\n const name = opts.name ?? 'my-project'\n const projectId = opts.projectId ?? `proj_${name.toLowerCase().replace(/\\s+/g, '_')}`\n\n const config: LexConfig = {\n $schema: 'https://unpkg.com/@314-lex/sdk/schema/config.json',\n version: 2,\n name,\n projectId,\n tokens: {\n source: 'tailwind-v4',\n css: 'src/app/globals.css',\n },\n kuds: {\n typesFile: 'src/types/intent.ts',\n componentsDir: 'src/components/sections/',\n registry: 'kuds.registry.json',\n autoSync: false,\n },\n api: {\n baseUrl: 'env:POLYMORPH_BASE_URL',\n token: 'env:POLYMORPH_TOKEN',\n routes: '/api/314-lex',\n },\n }\n\n const registry: KudRegistry = {\n version: 1,\n projectId,\n generatedAt: new Date().toISOString(),\n kuds: [],\n }\n\n await writeFile(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8')\n await writeFile(registryPath, JSON.stringify(registry, null, 2) + '\\n', 'utf-8')\n\n console.log('Created 314-lex.config.json')\n console.log('Created kuds.registry.json')\n console.log(`\\nProject: ${name} (${projectId})`)\n console.log('\\nNext steps:')\n console.log(' 1. Set POLYMORPH_BASE_URL and POLYMORPH_TOKEN env vars')\n console.log(' 2. Run \"314-lex extract\" to scan your codebase for KUD types')\n console.log(' 3. Run \"314-lex push kuds\" to sync to the database')\n })\n}\n","import { readFile, readdir, writeFile } from 'node:fs/promises'\nimport { resolve, relative, join } from 'node:path'\nimport type { Command } from 'commander'\nimport type { KudRegistryEntry, KudRegistry } from '../../types/registry.js'\nimport { loadConfig } from '../helpers.js'\n\nexport function registerExtractCommand(program: Command): void {\n program\n .command('extract')\n .description('Extract KUD types from codebase into kuds.registry.json')\n .option('-c, --config <path>', 'Path to 314-lex.config.json')\n .action(async (opts) => {\n const config = await loadConfig(opts.config)\n const kudsConfig = config.kuds\n\n if (!kudsConfig) {\n console.error('No \"kuds\" section in config. Add typesFile and componentsDir.')\n process.exit(1)\n }\n\n const typesFile = resolve(process.cwd(), kudsConfig.typesFile)\n const componentsDir = resolve(process.cwd(), kudsConfig.componentsDir)\n const registryPath = resolve(process.cwd(), kudsConfig.registry)\n\n // Extract KUD types from the TypeScript file\n console.log(`Scanning ${kudsConfig.typesFile}...`)\n const typesContent = await readFile(typesFile, 'utf-8')\n const kudTypes = extractKUDTypes(typesContent)\n\n if (kudTypes.length === 0) {\n console.log('No KUD types found. Expected a union type like: type KUDType = \"hero\" | \"cta\" | ...')\n return\n }\n\n console.log(`Found ${kudTypes.length} KUD types: ${kudTypes.join(', ')}`)\n\n // Scan components directory for matching section components\n const componentMap = await scanComponents(componentsDir)\n\n // Build registry entries\n const entries: KudRegistryEntry[] = kudTypes.map((type) => {\n const componentPath = componentMap.get(type)\n return {\n type,\n label: type\n .split('-')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' '),\n version: 1,\n schema: {},\n ...(componentPath ? { componentPath: relative(process.cwd(), componentPath) } : {}),\n }\n })\n\n const registry: KudRegistry = {\n version: 1,\n projectId: config.projectId,\n generatedAt: new Date().toISOString(),\n kuds: entries,\n }\n\n await writeFile(registryPath, JSON.stringify(registry, null, 2) + '\\n', 'utf-8')\n console.log(`\\nWrote ${entries.length} KUDs to ${kudsConfig.registry}`)\n })\n}\n\nfunction extractKUDTypes(content: string): string[] {\n // Match: type KUDType = 'hero' | 'pricing-card' | ...\n // or: export type KUDType = \"hero\" | \"pricing-card\" | ...\n const unionRegex = /(?:export\\s+)?type\\s+KUDType\\s*=\\s*([^;]+)/\n const match = content.match(unionRegex)\n if (!match) return []\n\n const unionBody = match[1]\n const stringLiterals = unionBody.match(/['\"]([^'\"]+)['\"]/g)\n if (!stringLiterals) return []\n\n return stringLiterals.map((s) => s.replace(/['\"]/g, ''))\n}\n\nasync function scanComponents(dir: string): Promise<Map<string, string>> {\n const map = new Map<string, string>()\n\n try {\n const entries = await readdir(dir, { withFileTypes: true })\n for (const entry of entries) {\n if (entry.isDirectory()) {\n // Look for index.tsx or component file inside\n const name = entry.name.toLowerCase()\n const fullPath = join(dir, entry.name)\n map.set(name, fullPath)\n } else if (entry.isFile() && /\\.(tsx?|jsx?)$/.test(entry.name)) {\n const name = entry.name.replace(/\\.(tsx?|jsx?)$/, '').toLowerCase()\n // Convert PascalCase to kebab-case\n const kebab = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()\n map.set(kebab, join(dir, entry.name))\n }\n }\n } catch {\n // Directory doesn't exist yet, that's OK\n }\n\n return map\n}\n","import { readFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport { createLexClient, type LexClient } from '../index.js'\nimport { LexConfigSchema, type LexConfig } from '../types/config.js'\nimport { LexConfigError } from '../utils/errors.js'\n\nexport async function loadConfig(configPath?: string): Promise<LexConfig> {\n const path = configPath ?? resolve(process.cwd(), '314-lex.config.json')\n try {\n const raw = await readFile(path, 'utf-8')\n return LexConfigSchema.parse(JSON.parse(raw))\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new LexConfigError(`Config file not found: ${path}. Run \"314-lex init\" first.`)\n }\n throw err\n }\n}\n\nfunction resolveEnvValue(value: string): string {\n if (value.startsWith('env:')) {\n const envVar = value.slice(4)\n const envValue = process.env[envVar]\n if (!envValue) {\n throw new LexConfigError(`Environment variable ${envVar} is not set`)\n }\n return envValue\n }\n return value\n}\n\nexport function createClientFromEnv(config?: LexConfig): LexClient {\n const baseUrl = process.env.POLYMORPH_BASE_URL\n ?? (config?.api?.baseUrl ? resolveEnvValue(config.api.baseUrl) : undefined)\n\n const token = process.env.POLYMORPH_TOKEN\n ?? (config?.api?.token ? resolveEnvValue(config.api.token) : undefined)\n\n const projectId = process.env.LEX_PROJECT_ID ?? config?.projectId\n\n if (!baseUrl) throw new LexConfigError('POLYMORPH_BASE_URL is required')\n if (!token) throw new LexConfigError('POLYMORPH_TOKEN is required')\n if (!projectId) throw new LexConfigError('Project ID is required (set LEX_PROJECT_ID or configure projectId in config)')\n\n return createLexClient({ baseUrl, token, projectId })\n}\n\nexport function printSyncResult(result: { created: number; updated: number; deleted: number; unchanged: number }): void {\n console.log(` Created: ${result.created}`)\n console.log(` Updated: ${result.updated}`)\n console.log(` Deleted: ${result.deleted}`)\n console.log(` Unchanged: ${result.unchanged}`)\n}\n","import { resolve } from 'node:path'\nimport type { Command } from 'commander'\nimport { loadConfig, createClientFromEnv, printSyncResult } from '../helpers.js'\n\nexport function registerPushCommand(program: Command): void {\n program\n .command('push <target>')\n .description('Push data to the database (kuds or tokens)')\n .option('-c, --config <path>', 'Path to 314-lex.config.json')\n .action(async (target, opts) => {\n const config = await loadConfig(opts.config)\n const lex = createClientFromEnv(config)\n\n switch (target) {\n case 'kuds': {\n const registryPath = resolve(process.cwd(), config.kuds?.registry ?? 'kuds.registry.json')\n console.log(`Pushing KUDs from ${registryPath} to database...`)\n const result = await lex.kuds.syncFromRegistry(registryPath)\n console.log('KUD sync complete:')\n printSyncResult(result)\n break\n }\n case 'tokens': {\n const cssPath = resolve(process.cwd(), config.tokens?.css ?? 'src/app/globals.css')\n console.log(`Pushing tokens from ${cssPath} to database...`)\n const result = await lex.tokens.pushFromCode(cssPath)\n console.log(`Token sync complete: ${result.upserted} tokens upserted`)\n break\n }\n default:\n console.error(`Unknown target: ${target}. Use \"kuds\" or \"tokens\".`)\n process.exit(1)\n }\n })\n}\n","import { resolve } from 'node:path'\nimport type { Command } from 'commander'\nimport { loadConfig, createClientFromEnv } from '../helpers.js'\n\nexport function registerPullCommand(program: Command): void {\n program\n .command('pull <target>')\n .description('Pull data from the database (kuds or tokens)')\n .option('-c, --config <path>', 'Path to 314-lex.config.json')\n .action(async (target, opts) => {\n const config = await loadConfig(opts.config)\n const lex = createClientFromEnv(config)\n\n switch (target) {\n case 'kuds': {\n const registryPath = resolve(process.cwd(), config.kuds?.registry ?? 'kuds.registry.json')\n console.log(`Pulling KUDs from database to ${registryPath}...`)\n await lex.kuds.syncToRegistry(registryPath)\n console.log('KUD pull complete.')\n break\n }\n case 'tokens': {\n const cssPath = resolve(process.cwd(), config.tokens?.css ?? 'src/app/globals.css')\n console.log(`Pulling tokens from database to ${cssPath}...`)\n await lex.tokens.pullToCode(cssPath)\n console.log('Token pull complete.')\n break\n }\n default:\n console.error(`Unknown target: ${target}. Use \"kuds\" or \"tokens\".`)\n process.exit(1)\n }\n })\n}\n","import { resolve } from 'node:path'\nimport type { Command } from 'commander'\nimport { loadConfig, createClientFromEnv, printSyncResult } from '../helpers.js'\n\nexport function registerSyncCommand(program: Command): void {\n program\n .command('sync')\n .description('Bidirectional sync of KUDs and tokens')\n .option('-c, --config <path>', 'Path to 314-lex.config.json')\n .option('--prefer-local', 'Prefer local registry over database on conflicts')\n .action(async (opts) => {\n const config = await loadConfig(opts.config)\n const lex = createClientFromEnv(config)\n\n // Sync KUDs\n const registryPath = resolve(process.cwd(), config.kuds?.registry ?? 'kuds.registry.json')\n\n if (opts.preferLocal) {\n console.log('Syncing KUDs (local → database)...')\n const result = await lex.kuds.syncFromRegistry(registryPath)\n console.log('KUD sync complete:')\n printSyncResult(result)\n } else {\n console.log('Syncing KUDs (database → local)...')\n await lex.kuds.syncToRegistry(registryPath)\n console.log('KUD pull complete.')\n }\n\n // Sync tokens\n if (config.tokens?.css) {\n const cssPath = resolve(process.cwd(), config.tokens.css)\n\n if (opts.preferLocal) {\n console.log('\\nSyncing tokens (local → database)...')\n const result = await lex.tokens.pushFromCode(cssPath)\n console.log(`Token sync complete: ${result.upserted} tokens upserted`)\n } else {\n console.log('\\nSyncing tokens (database → local)...')\n await lex.tokens.pullToCode(cssPath)\n console.log('Token pull complete.')\n }\n }\n\n console.log('\\nSync complete.')\n })\n}\n","import { readFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport type { Command } from 'commander'\nimport { LexConfigSchema } from '../../types/config.js'\nimport { KudRegistrySchema } from '../../types/registry.js'\n\nexport function registerValidateCommand(program: Command): void {\n program\n .command('validate')\n .description('Validate 314-lex.config.json and kuds.registry.json')\n .option('-c, --config <path>', 'Path to 314-lex.config.json')\n .action(async (opts) => {\n let hasErrors = false\n\n // Validate config\n const configPath = opts.config ?? resolve(process.cwd(), '314-lex.config.json')\n console.log(`Validating ${configPath}...`)\n try {\n const raw = await readFile(configPath, 'utf-8')\n const result = LexConfigSchema.safeParse(JSON.parse(raw))\n if (result.success) {\n console.log(' Config: valid')\n } else {\n console.error(' Config: invalid')\n for (const issue of result.error.issues) {\n console.error(` - ${issue.path.join('.')}: ${issue.message}`)\n }\n hasErrors = true\n }\n } catch (err) {\n console.error(` Config: ${(err as Error).message}`)\n hasErrors = true\n }\n\n // Validate registry\n const registryPath = resolve(process.cwd(), 'kuds.registry.json')\n console.log(`Validating ${registryPath}...`)\n try {\n const raw = await readFile(registryPath, 'utf-8')\n const result = KudRegistrySchema.safeParse(JSON.parse(raw))\n if (result.success) {\n console.log(` Registry: valid (${result.data.kuds.length} KUDs)`)\n } else {\n console.error(' Registry: invalid')\n for (const issue of result.error.issues) {\n console.error(` - ${issue.path.join('.')}: ${issue.message}`)\n }\n hasErrors = true\n }\n } catch (err) {\n console.error(` Registry: ${(err as Error).message}`)\n hasErrors = true\n }\n\n // Check env vars\n console.log('\\nEnvironment:')\n const baseUrl = process.env.POLYMORPH_BASE_URL\n const token = process.env.POLYMORPH_TOKEN\n console.log(` POLYMORPH_BASE_URL: ${baseUrl ? 'set' : 'NOT SET'}`)\n console.log(` POLYMORPH_TOKEN: ${token ? 'set' : 'NOT SET'}`)\n\n if (!baseUrl || !token) {\n console.log('\\n Warning: Required env vars are missing. API operations will fail.')\n }\n\n if (hasErrors) {\n process.exit(1)\n } else {\n console.log('\\nAll validations passed.')\n }\n })\n}\n","import { readFile, writeFile } from 'node:fs/promises'\nimport { resolve, dirname } from 'node:path'\nimport { mkdir } from 'node:fs/promises'\nimport type { Command } from 'commander'\nimport { KudRegistrySchema } from '../../types/registry.js'\nimport { loadConfig } from '../helpers.js'\nimport type { KUDFieldDef } from '../../types/kud.js'\n\nexport function registerCodegenCommand(program: Command): void {\n program\n .command('codegen')\n .description('Generate TypeScript types from kuds.registry.json')\n .option('-c, --config <path>', 'Path to 314-lex.config.json')\n .option('-o, --output <path>', 'Output file path (defaults to src/types/generated-kuds.ts)')\n .action(async (opts) => {\n const config = await loadConfig(opts.config)\n const registryPath = resolve(process.cwd(), config.kuds?.registry ?? 'kuds.registry.json')\n\n const raw = await readFile(registryPath, 'utf-8')\n const registry = KudRegistrySchema.parse(JSON.parse(raw))\n\n if (registry.kuds.length === 0) {\n console.log('No KUDs found in registry. Nothing to generate.')\n return\n }\n\n const outputPath = opts.output ?? resolve(process.cwd(), 'src/types/generated-kuds.ts')\n await mkdir(dirname(outputPath), { recursive: true })\n\n const lines: string[] = [\n '// Auto-generated by 314-lex codegen',\n `// Generated at: ${new Date().toISOString()}`,\n '// Do not edit manually',\n '',\n ]\n\n // Generate KUDType union\n const types = registry.kuds.map((k) => `'${k.type}'`)\n lines.push(`export type KUDType = ${types.join(' | ')}`)\n lines.push('')\n\n // Generate content interfaces for each KUD\n for (const kud of registry.kuds) {\n const interfaceName = toPascalCase(kud.type) + 'Content'\n lines.push(`export interface ${interfaceName} {`)\n\n for (const [fieldName, fieldDef] of Object.entries(kud.schema)) {\n const tsType = fieldDefToTSType(fieldDef)\n const optional = fieldDef.required ? '' : '?'\n lines.push(` ${fieldName}${optional}: ${tsType}`)\n }\n\n lines.push('}')\n lines.push('')\n }\n\n // Generate content type map\n lines.push('export interface KUDContentMap {')\n for (const kud of registry.kuds) {\n const interfaceName = toPascalCase(kud.type) + 'Content'\n lines.push(` '${kud.type}': ${interfaceName}`)\n }\n lines.push('}')\n lines.push('')\n\n await writeFile(outputPath, lines.join('\\n'), 'utf-8')\n console.log(`Generated ${registry.kuds.length} type definitions to ${outputPath}`)\n })\n}\n\nfunction toPascalCase(str: string): string {\n return str\n .split(/[-_]/)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('')\n}\n\nfunction fieldDefToTSType(fieldDef: KUDFieldDef): string {\n switch (fieldDef.type) {\n case 'string':\n case 'text':\n case 'link':\n return 'string'\n case 'number':\n return 'number'\n case 'boolean':\n return 'boolean'\n case 'image':\n return '{ url: string; alt?: string }'\n case 'array':\n if (fieldDef.items) {\n return `${fieldDefToTSType(fieldDef.items)}[]`\n }\n return 'unknown[]'\n case 'object':\n if (fieldDef.properties) {\n const props = Object.entries(fieldDef.properties)\n .map(([name, def]) => {\n const opt = def.required ? '' : '?'\n return `${name}${opt}: ${fieldDefToTSType(def)}`\n })\n .join('; ')\n return `{ ${props} }`\n }\n return 'Record<string, unknown>'\n default:\n return 'unknown'\n }\n}\n"]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }