@bobbykim/manguito-cms-core 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.
- package/dist/index.d.mts +527 -0
- package/dist/index.d.ts +527 -0
- package/dist/index.js +1165 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1119 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config/defineConfig.ts","../src/parser/validators.ts","../src/parser/validate.ts","../src/parser/loader.ts","../src/registry/fieldTypeRegistry.ts","../src/parser/parseSchema.ts","../src/parser/parseRoles.ts","../src/auth.ts"],"sourcesContent":["// @bobbykim/manguito-cms-core\n// Schema parser and field type registry — no runtime dependencies beyond Zod.\n\nexport type {\n SchemaFolders,\n SchemaConfig,\n ResolvedSchemaConfig,\n MigrationsConfig,\n ResolvedMigrationsConfig,\n MigrationResult,\n MigrationStatus,\n DbAdapter,\n PresignedOptions,\n PresignedResult,\n StorageAdapter,\n CorsConfig,\n ServerAdapter,\n ResolvedMediaConfig,\n APIAdapter,\n ResolvedRateLimitConfig,\n AdminAdapter,\n ManguitoConfig,\n ResolvedManguitoConfig,\n} from './config/types.js'\n\nexport { defineConfig } from './config/defineConfig.js'\n\nexport type {\n DbColumnType,\n DbColumn,\n FieldValidation,\n FieldType,\n RelationType,\n UiComponent,\n ParsedField,\n SystemField,\n} from './registry/types.js'\n\nexport type {\n ParsedSchemaBase,\n UiTab,\n UiMeta,\n JunctionTable,\n ContentDbMeta,\n ParagraphDbMeta,\n TaxonomyDbMeta,\n ParsedContentType,\n ParsedParagraphType,\n ParsedTaxonomyType,\n ParsedEnumType,\n ParsedSchema,\n ParseResult,\n} from './parser/parseSchema.js'\n\nexport type {\n ParsedBasePath,\n ParsedRoutes,\n ParsedRole,\n ParsedRoles,\n SchemaRegistry,\n} from './parser/validate.js'\n\nexport {\n buildSchemaRegistry,\n validateCrossReferences,\n parseRoutes,\n} from './parser/validate.js'\n\nexport type {\n Result,\n ParseError,\n ParseErrorCode,\n SchemaFile,\n SchemaType,\n} from './parser/loader.js'\n\nexport { walkSchemaDirectory, loadSchemaFile } from './parser/loader.js'\n\nexport { parseSchema } from './parser/parseSchema.js'\n\nexport { parseRoles } from './parser/parseRoles.js'\n\nexport type { ErrorCode } from './errors.js'\n\nexport type {\n PermissionTarget,\n PermissionAction,\n Permission,\n JWTPayload,\n User,\n FilterOperator,\n FilterValue,\n PaginatedResult,\n FindManyOptions,\n FindAllOptions,\n CreateInput,\n UpdateInput,\n ContentRepository,\n MediaItem,\n CreateMediaInput,\n MediaFindManyOptions,\n MediaRepository,\n} from './types.js'\n\nexport { hashPassword, verifyPassword } from './auth.js'\n","import type {\n DbAdapter,\n ManguitoConfig,\n MigrationsConfig,\n ResolvedManguitoConfig,\n ResolvedMigrationsConfig,\n ResolvedSchemaConfig,\n SchemaConfig,\n} from './types'\n\nexport function defineConfig(config: ManguitoConfig): ResolvedManguitoConfig {\n return {\n name: config.name ?? 'Manguito CMS',\n schema: resolveSchemaConfig(config.schema),\n db: config.db,\n migrations: resolveMigrationsConfig(config.migrations, config.db),\n storage: config.storage,\n server: config.server,\n api: config.api,\n admin: config.admin,\n }\n}\n\nfunction resolveSchemaConfig(config?: SchemaConfig): ResolvedSchemaConfig {\n return {\n base_path: config?.base_path ?? './schemas',\n folders: {\n content_types: config?.folders?.content_types ?? 'content-types',\n paragraph_types: config?.folders?.paragraph_types ?? 'paragraph-types',\n taxonomy_types: config?.folders?.taxonomy_types ?? 'taxonomy-types',\n enum_types: config?.folders?.enum_types ?? 'enum-types',\n },\n }\n}\n\nfunction resolveMigrationsConfig(\n config?: MigrationsConfig,\n db?: DbAdapter\n): ResolvedMigrationsConfig | null {\n if (db?.type === 'mongodb') return null\n return {\n table: config?.table ?? '__manguito_migrations',\n folder: config?.folder ?? './migrations',\n }\n}\n","import { z } from 'zod'\n\n// ─── Shared helpers ───────────────────────────────────────────────────────────\n\n// Snake-case identifier: starts with lowercase letter, then letters/digits/underscores.\nconst snakeCaseName = z\n .string()\n .regex(/^[a-z][a-z0-9_]*$/, 'Must be snake_case (e.g. \"blog_post\")')\n\n// Human-readable file size strings as authored in schema files.\n// Normalisation to bytes happens in the parser, not here.\nconst maxSizeString = z\n .string()\n .regex(\n /^\\d+(\\.\\d+)?\\s*(B|KB|MB|GB)$/i,\n 'Must be a file size string like \"512KB\" or \"2MB\"'\n )\n\n// ─── Machine name validators ──────────────────────────────────────────────────\n\nconst contentMachineName = z\n .string()\n .regex(\n /^content--[a-z][a-z0-9_]*$/,\n 'Must match \"content--<snake_case_name>\" (e.g. \"content--blog_post\")'\n )\n\nconst paragraphMachineName = z\n .string()\n .regex(\n /^paragraph--[a-z][a-z0-9_]*$/,\n 'Must match \"paragraph--<snake_case_name>\" (e.g. \"paragraph--photo_card\")'\n )\n\nconst taxonomyMachineName = z\n .string()\n .regex(\n /^taxonomy--[a-z][a-z0-9_]*$/,\n 'Must match \"taxonomy--<snake_case_name>\" (e.g. \"taxonomy--daily_post\")'\n )\n\nconst enumMachineName = z\n .string()\n .regex(\n /^enum--[a-z][a-z0-9_]*$/,\n 'Must match \"enum--<snake_case_name>\" (e.g. \"enum--link_target\")'\n )\n\n// Reference target must be a content-type or taxonomy-type machine name.\nconst refTargetMachineName = z\n .string()\n .regex(\n /^(content|taxonomy)--[a-z][a-z0-9_]*$/,\n 'Target must be a content-type or taxonomy-type machine name'\n )\n\n// ─── Field base ───────────────────────────────────────────────────────────────\n\n// Properties shared across every field type.\nconst RawFieldBase = z.object({\n name: snakeCaseName,\n label: z.string().min(1),\n required: z.boolean(),\n})\n\n// ─── Primitive field schemas ──────────────────────────────────────────────────\n\nexport const RawTextPlainFieldSchema = RawFieldBase.extend({\n type: z.literal('text/plain'),\n limit: z.number().int().positive().optional(),\n pattern: z.string().optional(),\n})\n\nexport const RawTextRichFieldSchema = RawFieldBase.extend({\n type: z.literal('text/rich'),\n})\n\nexport const RawIntegerFieldSchema = RawFieldBase.extend({\n type: z.literal('integer'),\n // min/max are value bounds — can be any integer, including negative.\n min: z.number().int().optional(),\n max: z.number().int().optional(),\n})\n\nexport const RawFloatFieldSchema = RawFieldBase.extend({\n type: z.literal('float'),\n min: z.number().optional(),\n max: z.number().optional(),\n})\n\nexport const RawBooleanFieldSchema = RawFieldBase.extend({\n type: z.literal('boolean'),\n})\n\nexport const RawDateFieldSchema = RawFieldBase.extend({\n type: z.literal('date'),\n})\n\n// ─── Media field schemas ──────────────────────────────────────────────────────\n\nexport const RawImageFieldSchema = RawFieldBase.extend({\n type: z.literal('image'),\n max_size: maxSizeString.optional(),\n alt: z.boolean().optional(),\n})\n\nexport const RawVideoFieldSchema = RawFieldBase.extend({\n type: z.literal('video'),\n max_size: maxSizeString.optional(),\n alt: z.boolean().optional(),\n})\n\nexport const RawFileFieldSchema = RawFieldBase.extend({\n type: z.literal('file'),\n max_size: maxSizeString.optional(),\n alt: z.boolean().optional(),\n})\n\n// ─── Enum field schema ────────────────────────────────────────────────────────\n\n// Either ref (standalone enum) or values (inline enum) must be present — not both,\n// not neither. The .refine() below enforces the XOR constraint.\n//\n// Note: .refine() promotes this schema from ZodObject to ZodEffects, which means\n// it cannot participate in z.discriminatedUnion(). See RawFieldSchema below.\nexport const RawEnumFieldSchema = RawFieldBase.extend({\n type: z.literal('enum'),\n ref: enumMachineName.optional(),\n values: z.array(z.string().min(1)).min(1).optional(),\n}).refine(\n (d) => (d.ref !== undefined) !== (d.values !== undefined),\n { message: 'Enum field must have either ref or values — not both, not neither' }\n)\n\n// ─── Relation field schemas ───────────────────────────────────────────────────\n\n// Paragraph: rel is restricted to one-to-one and one-to-many.\n// many-to-many is not supported for paragraphs (polymorphic parent association).\nexport const RawParagraphFieldSchema = RawFieldBase.extend({\n type: z.literal('paragraph'),\n ref: paragraphMachineName,\n rel: z.enum(['one-to-one', 'one-to-many']),\n max: z.number().int().positive().optional(),\n})\n\n// Reference: supports all three relation types.\n// target must be a content-type or taxonomy-type.\nexport const RawReferenceFieldSchema = RawFieldBase.extend({\n type: z.literal('reference'),\n target: refTargetMachineName,\n rel: z.enum(['one-to-one', 'one-to-many', 'many-to-many']),\n max: z.number().int().positive().optional(),\n})\n\n// ─── Field union ──────────────────────────────────────────────────────────────\n\n// The 11 non-enum field types form a proper discriminated union on 'type'.\n// RawEnumFieldSchema is excluded here because .refine() makes it ZodEffects,\n// which z.discriminatedUnion() does not accept.\nconst RawNonEnumFieldSchema = z.discriminatedUnion('type', [\n RawTextPlainFieldSchema,\n RawTextRichFieldSchema,\n RawIntegerFieldSchema,\n RawFloatFieldSchema,\n RawBooleanFieldSchema,\n RawDateFieldSchema,\n RawImageFieldSchema,\n RawVideoFieldSchema,\n RawFileFieldSchema,\n RawParagraphFieldSchema,\n RawReferenceFieldSchema,\n])\n\n// Complete field union. z.union() tries RawNonEnumFieldSchema first via the\n// discriminant, then falls back to RawEnumFieldSchema for type === 'enum'.\nexport const RawFieldSchema = z.union([RawNonEnumFieldSchema, RawEnumFieldSchema])\n\n// ─── Tab schema (content types only) ─────────────────────────────────────────\n\n// Tabs are cosmetic wrappers for content type fields. The parser strips them\n// to produce a flat fields array; tab structure is preserved in UiMeta.\nconst RawTabSchema = z.object({\n tab: z.object({\n name: snakeCaseName,\n label: z.string().min(1),\n fields: z.array(RawFieldSchema).min(1),\n }),\n})\n\n// ─── Schema file validators ───────────────────────────────────────────────────\n\n// Content type: fields are wrapped in tabs. At least one tab required.\nexport const ContentTypeRawSchema = z.object({\n name: contentMachineName,\n label: z.string().min(1),\n type: z.literal('content-type'),\n default_base_path: z.string().min(1),\n only_one: z.boolean(),\n fields: z.array(RawTabSchema).min(1),\n})\n\n// Paragraph type: flat fields array. No tabs.\n// Empty fields array is valid — system fields (id, parent_id, etc.) are always injected.\nexport const ParagraphTypeRawSchema = z.object({\n name: paragraphMachineName,\n label: z.string().min(1),\n type: z.literal('paragraph-type'),\n fields: z.array(RawFieldSchema),\n})\n\n// Taxonomy type: flat fields array. No tabs.\n// Empty fields array is valid — system fields are always injected.\nexport const TaxonomyTypeRawSchema = z.object({\n name: taxonomyMachineName,\n label: z.string().min(1),\n type: z.literal('taxonomy-type'),\n fields: z.array(RawFieldSchema),\n})\n\n// Enum type: no fields — just a name and an array of string values.\nexport const EnumTypeRawSchema = z.object({\n name: enumMachineName,\n label: z.string().min(1),\n type: z.literal('enum-type'),\n values: z.array(z.string().min(1)).min(1),\n})\n\n// routes.json: defines the valid base paths that content types can reference.\nexport const RoutesFileSchema = z.object({\n base_paths: z\n .array(\n z.object({\n name: snakeCaseName,\n path: z.string().regex(/^\\//, 'Path must start with /'),\n })\n )\n .min(1),\n})\n\n// ─── Inferred types ───────────────────────────────────────────────────────────\n\nexport type RawContentType = z.infer<typeof ContentTypeRawSchema>\nexport type RawParagraphType = z.infer<typeof ParagraphTypeRawSchema>\nexport type RawTaxonomyType = z.infer<typeof TaxonomyTypeRawSchema>\nexport type RawEnumType = z.infer<typeof EnumTypeRawSchema>\nexport type RawRoutesFile = z.infer<typeof RoutesFileSchema>\n\nexport type RawTextField = z.infer<typeof RawTextPlainFieldSchema>\nexport type RawTextRichField = z.infer<typeof RawTextRichFieldSchema>\nexport type RawIntegerField = z.infer<typeof RawIntegerFieldSchema>\nexport type RawFloatField = z.infer<typeof RawFloatFieldSchema>\nexport type RawBooleanField = z.infer<typeof RawBooleanFieldSchema>\nexport type RawDateField = z.infer<typeof RawDateFieldSchema>\nexport type RawImageField = z.infer<typeof RawImageFieldSchema>\nexport type RawVideoField = z.infer<typeof RawVideoFieldSchema>\nexport type RawFileField = z.infer<typeof RawFileFieldSchema>\nexport type RawEnumField = z.infer<typeof RawEnumFieldSchema>\nexport type RawParagraphField = z.infer<typeof RawParagraphFieldSchema>\nexport type RawReferenceField = z.infer<typeof RawReferenceFieldSchema>\nexport type RawField = z.infer<typeof RawFieldSchema>\n","import type { Result, ParseError, ParseErrorCode } from './loader'\nimport type { Permission } from '../types.js'\nimport { RoutesFileSchema } from './validators.js'\nimport type {\n ParsedSchema,\n ParsedContentType,\n ParsedParagraphType,\n ParsedTaxonomyType,\n ParsedEnumType,\n} from './parseSchema'\nimport type { ParsedField } from '../registry/types'\n\n// ─── Parsed Routes ────────────────────────────────────────────────────────────\n\nexport type ParsedBasePath = {\n name: string\n path: string\n}\n\nexport type ParsedRoutes = {\n base_paths: ParsedBasePath[]\n}\n\n// ─── Parsed Roles ─────────────────────────────────────────────────────────────\n\nexport type ParsedRole = {\n name: string\n label: string\n is_system: boolean\n hierarchy_level: number\n permissions: Permission[]\n}\n\nexport type ParsedRoles = {\n roles: ParsedRole[]\n valid_permissions: string[]\n}\n\n// ─── SchemaRegistry ───────────────────────────────────────────────────────────\n\nexport type SchemaRegistry = {\n routes: ParsedRoutes\n roles: ParsedRoles\n /** All schemas keyed by machine name. When two schemas share a name, last-write-wins. */\n schemas: Record<string, ParsedSchema>\n content_types: Record<string, ParsedContentType>\n paragraph_types: Record<string, ParsedParagraphType>\n taxonomy_types: Record<string, ParsedTaxonomyType>\n enum_types: Record<string, ParsedEnumType>\n /**\n * All schemas in the original input order, preserving duplicates.\n * Used by validateCrossReferences to detect DUPLICATE_SCHEMA_NAME errors —\n * the keyed maps above deduplicate by name and would hide them.\n */\n all_schemas: readonly ParsedSchema[]\n}\n\n// ─── buildSchemaRegistry ──────────────────────────────────────────────────────\n\n/**\n * Assembles the final SchemaRegistry from all individually parsed schemas,\n * routes, and roles.\n *\n * When two schemas share the same machine name, last-write-wins in the keyed\n * maps. The all_schemas array preserves all entries (including duplicates) so\n * that validateCrossReferences can detect DUPLICATE_SCHEMA_NAME errors.\n *\n * Also resolves enum refs: any enum field that uses `ref` (rather than inline\n * `values`) has its allowed_values, check_constraint, and select options\n * populated from the matching enum-type schema. Fields whose enum ref does not\n * exist in the registry are left empty — validateCrossReferences will report\n * UNKNOWN_REF for them.\n */\nexport function buildSchemaRegistry(\n parsedSchemas: ParsedSchema[],\n parsedRoutes: ParsedRoutes,\n parsedRoles: ParsedRoles\n): SchemaRegistry {\n const schemas: Record<string, ParsedSchema> = {}\n const content_types: Record<string, ParsedContentType> = {}\n const paragraph_types: Record<string, ParsedParagraphType> = {}\n const taxonomy_types: Record<string, ParsedTaxonomyType> = {}\n const enum_types: Record<string, ParsedEnumType> = {}\n\n // First pass: populate all keyed maps.\n for (const schema of parsedSchemas) {\n schemas[schema.name] = schema\n\n switch (schema.schema_type) {\n case 'content-type':\n content_types[schema.name] = schema as ParsedContentType\n break\n case 'paragraph-type':\n paragraph_types[schema.name] = schema as ParsedParagraphType\n break\n case 'taxonomy-type':\n taxonomy_types[schema.name] = schema as ParsedTaxonomyType\n break\n case 'enum-type':\n enum_types[schema.name] = schema as ParsedEnumType\n break\n }\n }\n\n // Second pass: resolve enum refs.\n // Fields with type \"enum\" and a stored enum_ref have their allowed_values,\n // check_constraint, and options populated from the referenced enum-type.\n for (const schema of Object.values(schemas)) {\n if (schema.schema_type === 'enum-type') continue\n\n for (const field of schema.fields) {\n if (field.field_type !== 'enum') continue\n\n const ui = field.ui_component as {\n component: 'select'\n options: string[]\n enum_ref?: string\n }\n\n if (ui.enum_ref === undefined) continue // inline enum — already populated\n\n const enumSchema = enum_types[ui.enum_ref]\n if (enumSchema === undefined) continue // UNKNOWN_REF — validateCrossReferences reports this\n\n const values = enumSchema.values\n field.validation.allowed_values = values\n if (field.db_column !== null) {\n field.db_column.check_constraint = values\n }\n ui.options = values\n }\n }\n\n return {\n routes: parsedRoutes,\n roles: parsedRoles,\n schemas,\n content_types,\n paragraph_types,\n taxonomy_types,\n enum_types,\n all_schemas: parsedSchemas,\n }\n}\n\n// ─── validateCrossReferences ──────────────────────────────────────────────────\n\n/**\n * Validates cross-schema references after all schemas have been individually\n * parsed and assembled into a registry. Returns all cross-reference errors.\n *\n * Error codes covered:\n * - DUPLICATE_SCHEMA_NAME — two schema files share the same machine name\n * - UNKNOWN_REF — ref or target points to a non-existent schema\n * - INVALID_REF_TARGET — ref points to a schema of the wrong type\n * - CIRCULAR_REFERENCE — paragraph A refs paragraph B which refs paragraph A\n * - MAX_SIZE_EXCEEDS_GLOBAL_LIMIT — field max_size exceeds the global limit\n *\n * @param registry The assembled SchemaRegistry (from buildSchemaRegistry).\n * @param globalMaxFileSize Global max file size in bytes from api.media.max_file_size.\n * When provided, MAX_SIZE_EXCEEDS_GLOBAL_LIMIT is checked for all media fields.\n */\nexport function validateCrossReferences(\n registry: SchemaRegistry,\n globalMaxFileSize?: number\n): ParseError[] {\n const errors: ParseError[] = []\n\n errors.push(...checkDuplicateSchemaNames(registry.all_schemas))\n errors.push(...checkFieldRefs(registry))\n errors.push(...checkCircularParagraphRefs(registry))\n\n if (globalMaxFileSize !== undefined) {\n errors.push(...checkMaxSizeLimit(registry, globalMaxFileSize))\n }\n\n return errors\n}\n\n// ─── DUPLICATE_SCHEMA_NAME ────────────────────────────────────────────────────\n\nfunction checkDuplicateSchemaNames(allSchemas: readonly ParsedSchema[]): ParseError[] {\n const errors: ParseError[] = []\n const seen = new Map<string, string>() // name → source_file of first occurrence\n\n for (const schema of allSchemas) {\n const firstFile = seen.get(schema.name)\n if (firstFile !== undefined) {\n errors.push({\n file: schema.source_file,\n code: 'DUPLICATE_SCHEMA_NAME',\n message: `Duplicate schema name \"${schema.name}\": already defined in \"${firstFile}\"`,\n })\n } else {\n seen.set(schema.name, schema.source_file)\n }\n }\n\n return errors\n}\n\n// ─── UNKNOWN_REF / INVALID_REF_TARGET ────────────────────────────────────────\n\n// Narrow ui_component shapes for the three relational field types.\ntype ParagraphEmbedUi = { component: 'paragraph-embed'; ref: string; rel: string; max?: number }\ntype TypeaheadSelectUi = { component: 'typeahead-select'; ref: string; rel: string }\ntype SelectUi = { component: 'select'; options: string[]; enum_ref?: string }\n\nfunction checkFieldRefs(registry: SchemaRegistry): ParseError[] {\n const errors: ParseError[] = []\n\n for (const schema of Object.values(registry.schemas)) {\n if (schema.schema_type === 'enum-type') continue\n\n for (const field of schema.fields) {\n errors.push(...checkSingleFieldRef(field, schema.source_file, registry))\n }\n }\n\n return errors\n}\n\nfunction checkSingleFieldRef(\n field: ParsedField,\n sourceFile: string,\n registry: SchemaRegistry\n): ParseError[] {\n const errors: ParseError[] = []\n const fieldPath = (prop: string): string => `fields[${field.order}].${prop}`\n\n switch (field.field_type) {\n case 'paragraph': {\n const ref = (field.ui_component as ParagraphEmbedUi).ref\n\n if (ref in registry.paragraph_types) break // valid\n\n errors.push({\n file: sourceFile,\n code: ref in registry.schemas ? 'INVALID_REF_TARGET' : 'UNKNOWN_REF',\n message:\n ref in registry.schemas\n ? `Field \"${field.name}\": paragraph ref \"${ref}\" exists but is not a paragraph-type`\n : `Field \"${field.name}\": paragraph ref \"${ref}\" does not exist`,\n path: fieldPath('ref'),\n })\n break\n }\n\n case 'reference': {\n // typeahead-select stores the original `target` as ui.ref.\n const target = (field.ui_component as TypeaheadSelectUi).ref\n\n if (target in registry.content_types || target in registry.taxonomy_types) break // valid\n\n errors.push({\n file: sourceFile,\n code: target in registry.schemas ? 'INVALID_REF_TARGET' : 'UNKNOWN_REF',\n message:\n target in registry.schemas\n ? `Field \"${field.name}\": reference target \"${target}\" exists but is not a content-type or taxonomy-type`\n : `Field \"${field.name}\": reference target \"${target}\" does not exist`,\n path: fieldPath('target'),\n })\n break\n }\n\n case 'enum': {\n const enumRef = (field.ui_component as SelectUi).enum_ref\n if (enumRef === undefined) break // inline enum — no ref to validate\n\n if (enumRef in registry.enum_types) break // valid\n\n errors.push({\n file: sourceFile,\n code: enumRef in registry.schemas ? 'INVALID_REF_TARGET' : 'UNKNOWN_REF',\n message:\n enumRef in registry.schemas\n ? `Field \"${field.name}\": enum ref \"${enumRef}\" exists but is not an enum-type`\n : `Field \"${field.name}\": enum ref \"${enumRef}\" does not exist`,\n path: fieldPath('ref'),\n })\n break\n }\n }\n\n return errors\n}\n\n// ─── CIRCULAR_REFERENCE ───────────────────────────────────────────────────────\n\n/**\n * Detects cycles in the paragraph-to-paragraph reference graph using iterative\n * DFS with an explicit call stack to avoid recursion depth limits.\n *\n * Only edges to paragraph types that exist in the registry are traversed —\n * missing refs are reported as UNKNOWN_REF by checkFieldRefs, not here.\n */\nfunction checkCircularParagraphRefs(registry: SchemaRegistry): ParseError[] {\n const errors: ParseError[] = []\n\n // Build adjacency list: paragraph machine name → paragraph machine names it refs.\n const adjList = new Map<string, string[]>()\n\n for (const [name, para] of Object.entries(registry.paragraph_types)) {\n const refs: string[] = []\n for (const field of para.fields) {\n if (field.field_type !== 'paragraph') continue\n const ref = (field.ui_component as ParagraphEmbedUi).ref\n // Only follow edges that exist — unknown refs handled by checkFieldRefs.\n if (ref in registry.paragraph_types) {\n refs.push(ref)\n }\n }\n adjList.set(name, refs)\n }\n\n // Standard DFS cycle detection:\n // visited — fully explored nodes (no cycles reachable from them)\n // inStack — nodes currently on the active DFS path\n // stack — ordered active DFS path for cycle description\n const visited = new Set<string>()\n const inStack = new Set<string>()\n const stack: string[] = []\n\n function dfs(node: string): void {\n if (inStack.has(node)) {\n // node is already on the current path → cycle found.\n const cycleStart = stack.indexOf(node)\n const cyclePath = stack.slice(cycleStart)\n const cycleStr = [...cyclePath, node].join(' → ')\n\n // Attribute the error to the schema that introduced the back-edge.\n const lastNode = stack[stack.length - 1]!\n const sourceFile = registry.paragraph_types[lastNode]?.source_file ?? ''\n\n errors.push({\n file: sourceFile,\n code: 'CIRCULAR_REFERENCE',\n message: `Circular paragraph reference detected: ${cycleStr}`,\n })\n return\n }\n\n if (visited.has(node)) return // already fully explored — no cycle from here\n\n visited.add(node)\n inStack.add(node)\n stack.push(node)\n\n for (const neighbor of adjList.get(node) ?? []) {\n dfs(neighbor)\n }\n\n stack.pop()\n inStack.delete(node)\n }\n\n for (const name of adjList.keys()) {\n dfs(name)\n }\n\n return errors\n}\n\n// ─── MAX_SIZE_EXCEEDS_GLOBAL_LIMIT ────────────────────────────────────────────\n\nfunction checkMaxSizeLimit(\n registry: SchemaRegistry,\n globalMaxFileSize: number\n): ParseError[] {\n const errors: ParseError[] = []\n\n for (const schema of Object.values(registry.schemas)) {\n if (schema.schema_type === 'enum-type') continue\n\n for (const field of schema.fields) {\n if (\n field.field_type !== 'image' &&\n field.field_type !== 'video' &&\n field.field_type !== 'file'\n ) {\n continue\n }\n\n const fieldMaxSize = field.validation.max_size\n if (fieldMaxSize === undefined || fieldMaxSize <= globalMaxFileSize) continue\n\n errors.push({\n file: schema.source_file,\n code: 'MAX_SIZE_EXCEEDS_GLOBAL_LIMIT',\n message:\n `Field \"${field.name}\": max_size ${fieldMaxSize} bytes exceeds ` +\n `global limit of ${globalMaxFileSize} bytes`,\n path: `fields[${field.order}].max_size`,\n })\n }\n }\n\n return errors\n}\n\n// ─── parseRoutes ──────────────────────────────────────────────────────────────\n\n/**\n * Validates a raw routes.json object and produces a ParsedRoutes value.\n * Returns Result<ParsedRoutes> — never throws for expected failures.\n * sourceFile is optional; supply it for accurate error file paths.\n */\nexport function parseRoutes(\n raw: unknown,\n sourceFile = 'routes.json'\n): Result<ParsedRoutes> {\n const result = RoutesFileSchema.safeParse(raw)\n if (!result.success) {\n return {\n ok: false,\n errors: result.error.issues.map((issue) => ({\n file: sourceFile,\n code: 'MISSING_REQUIRED_FIELD' as ParseErrorCode,\n message: issue.message,\n ...(issue.path.length > 0 ? { path: issue.path.map(String).join('.') } : {}),\n })),\n }\n }\n return { ok: true, value: result.data }\n}\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { parse as parseYaml } from 'yaml'\nimport type { ResolvedSchemaConfig } from '../config/types'\n\n// ─── Result type ──────────────────────────────────────────────────────────────\n\nexport type Result<T> =\n | { ok: true; value: T }\n | { ok: false; errors: ParseError[] }\n\n// ─── ParseError ───────────────────────────────────────────────────────────────\n\nexport type ParseErrorCode =\n | 'INVALID_SCHEMA_TYPE'\n | 'INVALID_FIELD_TYPE'\n | 'UNKNOWN_BASE_PATH'\n | 'UNKNOWN_REF'\n | 'INVALID_REF_TARGET'\n | 'DUPLICATE_FIELD_NAME'\n | 'DUPLICATE_SCHEMA_NAME'\n | 'INVALID_MACHINE_NAME'\n | 'CIRCULAR_REFERENCE'\n | 'MISSING_REQUIRED_FIELD'\n | 'MAX_SIZE_EXCEEDS_GLOBAL_LIMIT'\n | 'SCHEMA_DIR_NOT_FOUND'\n | 'SCHEMA_FOLDER_NOT_FOUND'\n | 'DUPLICATE_SCHEMA_FOLDER'\n | 'ROUTES_FILE_NOT_FOUND'\n | 'FILE_READ_ERROR'\n | 'FILE_PARSE_ERROR'\n | 'DUPLICATE_HIERARCHY_LEVEL'\n | 'UNKNOWN_PERMISSION'\n | 'INVALID_PERMISSION'\n\nexport type ParseError = {\n file: string\n code: ParseErrorCode\n message: string\n path?: string\n}\n\n// ─── SchemaType / SchemaFile ──────────────────────────────────────────────────\n\nexport type SchemaType =\n | 'content-type'\n | 'paragraph-type'\n | 'taxonomy-type'\n | 'enum-type'\n\nexport type SchemaFile = {\n path: string\n raw: unknown\n schema_type: SchemaType\n}\n\n// ─── Folder → SchemaType mapping ──────────────────────────────────────────────\n\n// The four schema folder keys — excludes 'roles' which is handled separately.\ntype SchemaFolderKey = 'content_types' | 'paragraph_types' | 'taxonomy_types' | 'enum_types'\n\n// Maps each schema folder key to the expected schema type.\nconst FOLDER_KEY_TO_SCHEMA_TYPE: Record<SchemaFolderKey, SchemaType> = {\n content_types: 'content-type',\n paragraph_types: 'paragraph-type',\n taxonomy_types: 'taxonomy-type',\n enum_types: 'enum-type',\n}\n\n// The filename prefix (before '--') that identifies each schema type.\nconst SCHEMA_TYPE_TO_PREFIX: Record<SchemaType, string> = {\n 'content-type': 'content',\n 'paragraph-type': 'paragraph',\n 'taxonomy-type': 'taxonomy',\n 'enum-type': 'enum',\n}\n\n// ─── loadSchemaFile ───────────────────────────────────────────────────────────\n\n/**\n * Reads a single JSON or YAML schema file and returns the raw parsed object.\n * Supported extensions: .json, .yaml, .yml\n * Never throws — file system and parse errors are returned as Result failures.\n */\nexport function loadSchemaFile(filePath: string): Result<unknown> {\n let raw: string\n\n try {\n raw = fs.readFileSync(filePath, 'utf-8')\n } catch (err) {\n return {\n ok: false,\n errors: [\n {\n file: filePath,\n code: 'FILE_READ_ERROR',\n message: `Could not read file: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n }\n }\n\n const ext = path.extname(filePath).toLowerCase()\n\n if (ext === '.json') {\n try {\n return { ok: true, value: JSON.parse(raw) as unknown }\n } catch (err) {\n return {\n ok: false,\n errors: [\n {\n file: filePath,\n code: 'FILE_PARSE_ERROR',\n message: `JSON parse error: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n }\n }\n }\n\n if (ext === '.yaml' || ext === '.yml') {\n try {\n return { ok: true, value: parseYaml(raw) as unknown }\n } catch (err) {\n return {\n ok: false,\n errors: [\n {\n file: filePath,\n code: 'FILE_PARSE_ERROR',\n message: `YAML parse error: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n }\n }\n }\n\n return {\n ok: false,\n errors: [\n {\n file: filePath,\n code: 'FILE_PARSE_ERROR',\n message: `Unsupported file extension \"${ext}\" — expected .json, .yaml, or .yml`,\n },\n ],\n }\n}\n\n// ─── walkSchemaDirectory ──────────────────────────────────────────────────────\n\n/**\n * Walks each schema folder defined in config and collects all schema files.\n * For each file:\n * - Validates that the filename prefix matches the folder's expected schema type.\n * - Reads and parses the file content via loadSchemaFile.\n *\n * Collects all errors rather than stopping at the first failure.\n * Returns { ok: false, errors } only when structural problems prevent loading;\n * individual file errors are accumulated and returned together.\n */\nexport function walkSchemaDirectory(\n config: ResolvedSchemaConfig\n): Result<SchemaFile[]> {\n const errors: ParseError[] = []\n const files: SchemaFile[] = []\n\n // ── Validate base_path exists ──────────────────────────────────────────────\n\n if (!directoryExists(config.base_path)) {\n return {\n ok: false,\n errors: [\n {\n file: config.base_path,\n code: 'SCHEMA_DIR_NOT_FOUND',\n message: `Schema base directory does not exist: ${config.base_path}`,\n },\n ],\n }\n }\n\n // ── Validate no two folders resolve to the same absolute path ──────────────\n\n const resolvedFolderPaths = new Map<string, SchemaFolderKey>()\n\n for (const folderKey of Object.keys(FOLDER_KEY_TO_SCHEMA_TYPE) as SchemaFolderKey[]) {\n const folderName = config.folders[folderKey]\n const absFolder = path.resolve(config.base_path, folderName)\n const existing = resolvedFolderPaths.get(absFolder)\n\n if (existing !== undefined) {\n errors.push({\n file: absFolder,\n code: 'DUPLICATE_SCHEMA_FOLDER',\n message: `Folders \"${existing}\" and \"${folderKey}\" resolve to the same path: ${absFolder}`,\n })\n } else {\n resolvedFolderPaths.set(absFolder, folderKey)\n }\n }\n\n if (errors.length > 0) return { ok: false, errors }\n\n // ── Walk each schema folder ────────────────────────────────────────────────\n\n for (const [folderKey, schemaType] of Object.entries(\n FOLDER_KEY_TO_SCHEMA_TYPE\n ) as [SchemaFolderKey, SchemaType][]) {\n const folderName = config.folders[folderKey]\n const folderPath = path.resolve(config.base_path, folderName)\n\n if (!directoryExists(folderPath)) {\n errors.push({\n file: folderPath,\n code: 'SCHEMA_FOLDER_NOT_FOUND',\n message: `Schema folder does not exist: ${folderPath} (configured as \"${folderName}\")`,\n })\n continue\n }\n\n const entries = readDirEntries(folderPath)\n const expectedPrefix = SCHEMA_TYPE_TO_PREFIX[schemaType]\n\n for (const entry of entries) {\n if (!isSupportedExtension(entry)) continue\n\n const filePath = path.join(folderPath, entry)\n const baseName = path.basename(entry, path.extname(entry))\n\n // ── Validate filename prefix matches the folder ──────────────────────\n if (!hasCorrectPrefix(baseName, expectedPrefix)) {\n errors.push({\n file: filePath,\n code: 'INVALID_MACHINE_NAME',\n message:\n `File \"${entry}\" in folder \"${folderName}\" does not match the expected ` +\n `\"${expectedPrefix}--<name>\" prefix for ${schemaType} schemas. ` +\n `Did you put this file in the wrong folder?`,\n })\n continue\n }\n\n // ── Load and parse the file ──────────────────────────────────────────\n const result = loadSchemaFile(filePath)\n\n if (!result.ok) {\n errors.push(...result.errors)\n continue\n }\n\n files.push({ path: filePath, raw: result.value, schema_type: schemaType })\n }\n }\n\n if (errors.length > 0) return { ok: false, errors }\n\n return { ok: true, value: files }\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nfunction directoryExists(dirPath: string): boolean {\n try {\n return fs.statSync(dirPath).isDirectory()\n } catch {\n return false\n }\n}\n\nfunction readDirEntries(dirPath: string): string[] {\n try {\n return fs.readdirSync(dirPath)\n } catch {\n return []\n }\n}\n\nfunction isSupportedExtension(filename: string): boolean {\n const ext = path.extname(filename).toLowerCase()\n return ext === '.json' || ext === '.yaml' || ext === '.yml'\n}\n\n/**\n * Validates that a basename (filename without extension) starts with the\n * expected type prefix followed by '--'.\n * e.g. \"content--blog_post\" with prefix \"content\" → true\n * \"paragraph--photo_card\" with prefix \"content\" → false\n */\nfunction hasCorrectPrefix(baseName: string, expectedPrefix: string): boolean {\n return baseName.startsWith(`${expectedPrefix}--`)\n}\n","import type { DbColumn, FieldType, FieldValidation, UiComponent } from './types'\nimport type {\n RawField,\n RawTextField,\n RawTextRichField,\n RawIntegerField,\n RawFloatField,\n RawBooleanField,\n RawDateField,\n RawImageField,\n RawVideoField,\n RawFileField,\n RawEnumField,\n RawParagraphField,\n RawReferenceField,\n} from '../parser/validators'\n\n// ─── Build context and result ─────────────────────────────────────────────────\n\n// Everything a field builder needs beyond the raw field itself.\n// ownerTableName is required to name a many-to-many junction table.\nexport type FieldBuildContext = {\n ownerTableName: string\n}\n\n// The three parsed parts a builder produces for one field. The parser wraps this\n// with name/label/field_type/required/nullable/order to form a ParsedField.\nexport type BuiltField = {\n validation: FieldValidation\n db_column: DbColumn | null\n ui_component: UiComponent\n}\n\n// A builder is a pure function from one raw field of a given type to its parts.\n// Each entry is typed to its own raw variant — no defensive narrowing inside.\ntype RawByType = {\n 'text/plain': RawTextField\n 'text/rich': RawTextRichField\n integer: RawIntegerField\n float: RawFloatField\n boolean: RawBooleanField\n date: RawDateField\n image: RawImageField\n video: RawVideoField\n file: RawFileField\n enum: RawEnumField\n paragraph: RawParagraphField\n reference: RawReferenceField\n}\n\nexport type FieldBuilder<T extends FieldType> = (\n raw: RawByType[T],\n ctx: FieldBuildContext\n) => BuiltField\n\nexport type FieldTypeRegistry = { [T in FieldType]: FieldBuilder<T> }\n\n// The discriminant-erased shape used at the single dispatch site. The registry is\n// keyed by the same field type the raw field carries, so the lookup is sound by\n// construction even though TypeScript cannot correlate the two across the union.\nexport type AnyFieldBuilder = (raw: RawField, ctx: FieldBuildContext) => BuiltField\n\n// ─── Shared naming helper ─────────────────────────────────────────────────────\n\n// \"content--blog_post\" → \"content_blog_post\". Used by the reference builder for\n// the FK / junction target table, and by the per-schema-type parsers for their\n// own table names.\nexport function machineNameToTableName(machineName: string): string {\n return machineName.replace('--', '_')\n}\n\n// ─── Media mime constants ─────────────────────────────────────────────────────\n\n// Specific types for server-side validation (FieldValidation.allowed_mime_types).\nconst MEDIA_ALLOWED_MIME: Record<'image' | 'video' | 'file', string[]> = {\n image: ['image/jpeg', 'image/png', 'image/webp', 'image/gif', 'image/svg+xml'],\n video: ['video/mp4', 'video/webm', 'video/quicktime'],\n file: ['application/pdf'],\n}\n\n// Wildcards for the HTML <input accept> attribute (UiComponent.accepted_mime_types).\nconst MEDIA_UI_MIME: Record<'image' | 'video' | 'file', string[]> = {\n image: ['image/*'],\n video: ['video/*'],\n file: ['application/pdf'],\n}\n\n// \"2MB\" → 2097152, \"512KB\" → 524288. Returns 0 for unrecognised input.\nfunction parseMaxSize(str: string): number {\n const m = /^(\\d+(?:\\.\\d+)?)\\s*(B|KB|MB|GB)$/i.exec(str)\n if (!m) return 0\n const value = parseFloat(m[1]!)\n switch (m[2]!.toUpperCase()) {\n case 'B': return Math.round(value)\n case 'KB': return Math.round(value * 1_024)\n case 'MB': return Math.round(value * 1_048_576)\n case 'GB': return Math.round(value * 1_073_741_824)\n default: return 0\n }\n}\n\n// Shared builder for the three media field types — identical but for mime lists.\nfunction buildMediaField(raw: RawImageField | RawVideoField | RawFileField): BuiltField {\n const mediaType = raw.type\n const maxSizeBytes = raw.max_size ? parseMaxSize(raw.max_size) : undefined\n return {\n validation: {\n required: raw.required,\n ...(maxSizeBytes !== undefined && { max_size: maxSizeBytes }),\n allowed_mime_types: MEDIA_ALLOWED_MIME[mediaType],\n },\n db_column: {\n column_name: raw.name,\n column_type: 'uuid',\n nullable: !raw.required,\n foreign_key: { table: 'media', column: 'id', on_delete: 'SET NULL' },\n },\n ui_component: {\n component: 'file-upload',\n accepted_mime_types: MEDIA_UI_MIME[mediaType],\n },\n }\n}\n\n// ─── Registry ─────────────────────────────────────────────────────────────────\n//\n// One builder per field type. Each turns a single authored field into its\n// { validation, db_column, ui_component } parts. The parser dispatches here\n// rather than branching per type; adding a field type means adding one entry.\n\nexport const fieldTypeRegistry: FieldTypeRegistry = {\n // ── Primitives ──────────────────────────────────────────────────────────────\n\n 'text/plain': (raw) => ({\n validation: {\n required: raw.required,\n ...(raw.limit !== undefined && { limit: raw.limit }),\n ...(raw.pattern !== undefined && { pattern: raw.pattern }),\n },\n db_column: { column_name: raw.name, column_type: 'varchar', nullable: !raw.required },\n ui_component: { component: 'text-input' },\n }),\n\n 'text/rich': (raw) => ({\n validation: { required: raw.required },\n db_column: { column_name: raw.name, column_type: 'text', nullable: !raw.required },\n ui_component: { component: 'rich-text-editor' },\n }),\n\n integer: (raw) => ({\n validation: {\n required: raw.required,\n ...(raw.min !== undefined && { min: raw.min }),\n ...(raw.max !== undefined && { max: raw.max }),\n },\n db_column: { column_name: raw.name, column_type: 'integer', nullable: !raw.required },\n ui_component: { component: 'number-input', step: 1 },\n }),\n\n float: (raw) => ({\n validation: {\n required: raw.required,\n ...(raw.min !== undefined && { min: raw.min }),\n ...(raw.max !== undefined && { max: raw.max }),\n },\n db_column: { column_name: raw.name, column_type: 'decimal', nullable: !raw.required },\n ui_component: { component: 'number-input', step: 0.01 },\n }),\n\n // Boolean columns are always NOT NULL — false is the natural empty value, not NULL.\n boolean: (raw) => ({\n validation: { required: raw.required },\n db_column: { column_name: raw.name, column_type: 'boolean', nullable: false },\n ui_component: { component: 'checkbox' },\n }),\n\n date: (raw) => ({\n validation: { required: raw.required },\n db_column: { column_name: raw.name, column_type: 'timestamp', nullable: !raw.required },\n ui_component: { component: 'date-picker' },\n }),\n\n // ── Media — FK → media.id, SET NULL on delete ───────────────────────────────\n\n image: (raw) => buildMediaField(raw),\n video: (raw) => buildMediaField(raw),\n file: (raw) => buildMediaField(raw),\n\n // ── Enum — varchar + check constraint ───────────────────────────────────────\n //\n // Inline enum: values are present on the field and fully resolved here.\n // Ref enum: values live in another schema not yet available, so allowed_values\n // and check_constraint stay empty and enum_ref is stashed in ui_component for\n // resolveEnumReferences() to fill once the full registry is assembled.\n enum: (raw) => {\n const allowedValues = raw.values ?? []\n return {\n validation: { required: raw.required, allowed_values: allowedValues },\n db_column: {\n column_name: raw.name,\n column_type: 'varchar',\n nullable: !raw.required,\n check_constraint: allowedValues,\n },\n ui_component: {\n component: 'select',\n options: allowedValues,\n ...(raw.ref !== undefined && { enum_ref: raw.ref }),\n },\n }\n },\n\n // ── Paragraph — no column on the owning table ───────────────────────────────\n // The association lives on the paragraph table via parent_id/parent_type/\n // parent_field/order system fields.\n paragraph: (raw) => ({\n validation: {\n required: raw.required,\n ...(raw.max !== undefined && { max_items: raw.max }),\n },\n db_column: null,\n ui_component: {\n component: 'paragraph-embed',\n ref: raw.ref,\n rel: raw.rel,\n ...(raw.max !== undefined && { max: raw.max }),\n },\n }),\n\n // ── Reference — FK column, or a junction table for many-to-many ─────────────\n reference: (raw, ctx) => {\n const targetTableName = machineNameToTableName(raw.target)\n const validation: FieldValidation = {\n required: raw.required,\n ...(raw.max !== undefined && { max_items: raw.max }),\n }\n\n const db_column: DbColumn =\n raw.rel === 'many-to-many'\n ? {\n // No FK column — the junction table owns the association.\n column_name: '',\n column_type: 'uuid',\n nullable: !raw.required,\n junction: {\n table_name: `junction_${ctx.ownerTableName}_${raw.name}`,\n left_column: 'left_id',\n right_column: 'right_id',\n right_table: targetTableName,\n order_column: false,\n },\n }\n : {\n // FK column on the owning table. References are independent → SET NULL.\n column_name: raw.name,\n column_type: 'uuid',\n nullable: !raw.required,\n foreign_key: { table: targetTableName, column: 'id', on_delete: 'SET NULL' },\n }\n\n return {\n validation,\n db_column,\n ui_component: { component: 'typeahead-select', ref: raw.target, rel: raw.rel },\n }\n },\n}\n","import type { ZodError } from 'zod'\nimport type { ParseError } from './loader'\nimport type { SchemaType } from './loader'\nimport {\n ContentTypeRawSchema,\n ParagraphTypeRawSchema,\n TaxonomyTypeRawSchema,\n EnumTypeRawSchema,\n} from './validators'\nimport type { RawField } from './validators'\nimport type { ParsedField, SystemField } from '../registry/types'\nimport {\n fieldTypeRegistry,\n machineNameToTableName,\n type AnyFieldBuilder,\n} from '../registry/fieldTypeRegistry'\n\n// ─── Output types ─────────────────────────────────────────────────────────────\n\nexport type ParsedSchemaBase = {\n schema_type: SchemaType\n name: string\n label: string\n source_file: string\n}\n\nexport type UiTab = {\n name: string\n label: string\n fields: string[] // ordered field names — no duplication of full field objects\n}\n\nexport type UiMeta = {\n tabs: UiTab[]\n}\n\nexport type JunctionTable = {\n table_name: string // \"junction_content_blog_post_blog_related\"\n left_column: string // \"left_id\"\n right_column: string // \"right_id\"\n right_table: string // \"content_blog_post\"\n order_column: boolean\n}\n\nexport type ContentDbMeta = {\n table_name: string\n junction_tables: JunctionTable[]\n}\n\nexport type ParagraphDbMeta = {\n table_name: string\n}\n\nexport type TaxonomyDbMeta = {\n table_name: string\n}\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n\nexport type ContentApiMeta = {\n default_base_path: string\n http_methods: HttpMethod[]\n collection_path?: string // only_one: false only\n item_path: string\n}\n\nexport type TaxonomyApiMeta = {\n collection_path: string\n item_path: string\n}\n\nexport type ParsedContentType = ParsedSchemaBase & {\n schema_type: 'content-type'\n only_one: boolean\n default_base_path: string\n system_fields: SystemField[]\n fields: ParsedField[]\n ui: UiMeta\n db: ContentDbMeta\n api: ContentApiMeta\n}\n\nexport type ParsedParagraphType = ParsedSchemaBase & {\n schema_type: 'paragraph-type'\n system_fields: SystemField[]\n fields: ParsedField[]\n db: ParagraphDbMeta\n}\n\nexport type ParsedTaxonomyType = ParsedSchemaBase & {\n schema_type: 'taxonomy-type'\n system_fields: SystemField[]\n fields: ParsedField[]\n db: TaxonomyDbMeta\n api: TaxonomyApiMeta\n}\n\nexport type ParsedEnumType = ParsedSchemaBase & {\n schema_type: 'enum-type'\n values: string[]\n}\n\nexport type ParsedSchema =\n | ParsedContentType\n | ParsedParagraphType\n | ParsedTaxonomyType\n | ParsedEnumType\n\nexport type ParseResult =\n | { ok: true; schema: ParsedSchema }\n | { ok: false; errors: ParseError[] }\n\n// ─── System fields (verbatim from phase-02-parser-output.md) ─────────────────\n\nconst CONTENT_SYSTEM_FIELDS: SystemField[] = [\n { name: 'id', db_type: 'uuid', primary_key: true, default: 'gen_random_uuid()', nullable: false },\n { name: 'slug', db_type: 'varchar', nullable: false },\n { name: 'base_path_id', db_type: 'uuid', nullable: false },\n { name: 'published', db_type: 'boolean', default: 'false', nullable: false },\n { name: 'created_at', db_type: 'timestamp', default: 'now()', nullable: false },\n { name: 'updated_at', db_type: 'timestamp', default: 'now()', nullable: false },\n]\n\nconst PARAGRAPH_SYSTEM_FIELDS: SystemField[] = [\n { name: 'id', db_type: 'uuid', primary_key: true, default: 'gen_random_uuid()', nullable: false },\n { name: 'parent_id', db_type: 'uuid', nullable: false },\n { name: 'parent_type', db_type: 'varchar', nullable: false },\n { name: 'parent_field', db_type: 'varchar', nullable: false },\n { name: 'order', db_type: 'integer', default: '0', nullable: false },\n { name: 'created_at', db_type: 'timestamp', default: 'now()', nullable: false },\n { name: 'updated_at', db_type: 'timestamp', default: 'now()', nullable: false },\n]\n\nconst TAXONOMY_SYSTEM_FIELDS: SystemField[] = [\n { name: 'id', db_type: 'uuid', primary_key: true, default: 'gen_random_uuid()', nullable: false },\n { name: 'published', db_type: 'boolean', default: 'false', nullable: false },\n { name: 'created_at', db_type: 'timestamp', default: 'now()', nullable: false },\n { name: 'updated_at', db_type: 'timestamp', default: 'now()', nullable: false },\n]\n\n// ─── Pure helpers ─────────────────────────────────────────────────────────────\n\n// machineNameToTableName lives with the field type registry (the reference builder\n// needs it too) and is imported above.\n\n// \"blog_post\" → \"blog-post\"\nfunction nameSegmentToKebab(segment: string): string {\n return segment.replace(/_/g, '-')\n}\n\n// \"content--blog_post\" → \"blog_post\"\nfunction getNameSegment(machineName: string): string {\n const idx = machineName.indexOf('--')\n return idx === -1 ? machineName : machineName.slice(idx + 2)\n}\n\n// Zod path array → \"fields[0].name\"\n// Zod v4 types issue.path as PropertyKey[] — symbols can't appear in practice.\nfunction zodPathToString(path: PropertyKey[]): string {\n return path.reduce<string>((acc, seg) => {\n const s = typeof seg === 'symbol' ? String(seg) : seg\n return typeof s === 'number' ? `${acc}[${s}]` : acc ? `${acc}.${s}` : s\n }, '')\n}\n\n// Map Zod validation issues to ParseError[], choosing the most relevant code.\nfunction zodErrorsToParseErrors(\n error: ZodError,\n sourceFile: string\n): ParseError[] {\n return error.issues.map((issue) => {\n const pathStr = zodPathToString(issue.path)\n const lastSeg = issue.path[issue.path.length - 1]\n\n let code: ParseError['code'] = 'MISSING_REQUIRED_FIELD'\n if (lastSeg === 'name') code = 'INVALID_MACHINE_NAME'\n else if (lastSeg === 'type' && issue.path.length <= 2) code = 'INVALID_SCHEMA_TYPE'\n else if (lastSeg === 'type') code = 'INVALID_FIELD_TYPE'\n\n return {\n file: sourceFile,\n code,\n message: issue.message,\n ...(pathStr ? { path: pathStr } : {}),\n }\n })\n}\n\n// Detect and report duplicate field names, returning a set of errors.\nfunction checkDuplicateFieldNames(\n fields: RawField[],\n sourceFile: string,\n schemaName: string\n): ParseError[] {\n const seen = new Set<string>()\n const errors: ParseError[] = []\n for (const f of fields) {\n if (seen.has(f.name)) {\n errors.push({\n file: sourceFile,\n code: 'DUPLICATE_FIELD_NAME',\n message: `Duplicate field name \"${f.name}\" in schema \"${schemaName}\"`,\n })\n }\n seen.add(f.name)\n }\n return errors\n}\n\n// ─── ParsedField construction ─────────────────────────────────────────────────\n\ntype FieldResult =\n | { ok: true; value: ParsedField }\n | { ok: false; errors: ParseError[] }\n\nfunction buildParsedField(\n rawField: RawField,\n order: number,\n sourceFile: string,\n ownerTableName: string\n): FieldResult {\n // Dispatch to the field type's builder. The registry is keyed by the same type\n // the raw field carries, so the lookup is sound by construction; the single cast\n // erases the discriminant TypeScript can't correlate across the union.\n const build = fieldTypeRegistry[rawField.type] as AnyFieldBuilder | undefined\n if (!build) {\n // Defensive: a validated RawField always has a registered type. Zod rejects\n // unknown field types before this point — but guard rather than throw.\n return {\n ok: false,\n errors: [{\n file: sourceFile,\n code: 'INVALID_FIELD_TYPE',\n message: `Unknown field type: ${String((rawField as { type: unknown }).type)}`,\n }],\n }\n }\n\n const { name, label, required } = rawField\n const { validation, db_column, ui_component } = build(rawField, { ownerTableName })\n\n return {\n ok: true,\n value: {\n name,\n label,\n field_type: rawField.type,\n required,\n nullable: !required,\n order,\n validation,\n db_column,\n ui_component,\n },\n }\n}\n\n// Build ParsedField[] from a flat raw field list, accumulating errors.\nfunction buildFields(\n rawFields: RawField[],\n sourceFile: string,\n ownerTableName: string\n): { fields: ParsedField[]; errors: ParseError[] } {\n const fields: ParsedField[] = []\n const errors: ParseError[] = []\n\n for (let i = 0; i < rawFields.length; i++) {\n const result = buildParsedField(rawFields[i]!, i, sourceFile, ownerTableName)\n if (result.ok) {\n fields.push(result.value)\n } else {\n errors.push(...result.errors)\n }\n }\n\n return { fields, errors }\n}\n\n// ─── Per-schema-type parsers ──────────────────────────────────────────────────\n\nfunction parseContentType(raw: unknown, sourceFile: string): ParseResult {\n const result = ContentTypeRawSchema.safeParse(raw)\n if (!result.success) {\n return { ok: false, errors: zodErrorsToParseErrors(result.error, sourceFile) }\n }\n const v = result.data\n\n // ── Strip tabs: collect flat fields + build UiMeta simultaneously ──────────\n\n const flatRawFields: RawField[] = []\n const tabs: UiTab[] = []\n\n for (const tabWrapper of v.fields) {\n const tab = tabWrapper.tab\n const tabFieldNames: string[] = []\n\n for (const f of tab.fields) {\n flatRawFields.push(f)\n tabFieldNames.push(f.name)\n }\n\n tabs.push({ name: tab.name, label: tab.label, fields: tabFieldNames })\n }\n\n // ── Duplicate field name check ─────────────────────────────────────────────\n\n const dupErrors = checkDuplicateFieldNames(flatRawFields, sourceFile, v.name)\n if (dupErrors.length > 0) return { ok: false, errors: dupErrors }\n\n // ── Build parsed fields ────────────────────────────────────────────────────\n\n const tableName = machineNameToTableName(v.name)\n const { fields, errors } = buildFields(flatRawFields, sourceFile, tableName)\n if (errors.length > 0) return { ok: false, errors }\n\n // ── Collect junction tables from many-to-many reference fields ─────────────\n\n const junctionTables: JunctionTable[] = []\n for (const field of fields) {\n if (field.field_type === 'reference' && field.db_column?.junction) {\n const j = field.db_column.junction\n junctionTables.push({\n table_name: j.table_name,\n left_column: j.left_column,\n right_column: j.right_column,\n right_table: j.right_table,\n order_column: j.order_column,\n })\n }\n }\n\n // ── ContentApiMeta ─────────────────────────────────────────────────────────\n\n const nameKebab = nameSegmentToKebab(getNameSegment(v.name))\n\n const api: ContentApiMeta = v.only_one\n ? {\n default_base_path: v.default_base_path,\n http_methods: ['GET', 'PUT', 'PATCH'],\n item_path: `/api/${v.default_base_path}/${nameKebab}`,\n }\n : {\n default_base_path: v.default_base_path,\n http_methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],\n collection_path: `/api/${nameKebab}`,\n item_path: `/api/${nameKebab}/:slug`,\n }\n\n const schema: ParsedContentType = {\n schema_type: 'content-type',\n name: v.name,\n label: v.label,\n source_file: sourceFile,\n only_one: v.only_one,\n default_base_path: v.default_base_path,\n system_fields: CONTENT_SYSTEM_FIELDS,\n fields,\n ui: { tabs },\n db: { table_name: tableName, junction_tables: junctionTables },\n api,\n }\n\n return { ok: true, schema }\n}\n\nfunction parseParagraphType(raw: unknown, sourceFile: string): ParseResult {\n const result = ParagraphTypeRawSchema.safeParse(raw)\n if (!result.success) {\n return { ok: false, errors: zodErrorsToParseErrors(result.error, sourceFile) }\n }\n const v = result.data\n\n const dupErrors = checkDuplicateFieldNames(v.fields, sourceFile, v.name)\n if (dupErrors.length > 0) return { ok: false, errors: dupErrors }\n\n const tableName = machineNameToTableName(v.name)\n const { fields, errors } = buildFields(v.fields, sourceFile, tableName)\n if (errors.length > 0) return { ok: false, errors }\n\n const schema: ParsedParagraphType = {\n schema_type: 'paragraph-type',\n name: v.name,\n label: v.label,\n source_file: sourceFile,\n system_fields: PARAGRAPH_SYSTEM_FIELDS,\n fields,\n db: { table_name: tableName },\n }\n\n return { ok: true, schema }\n}\n\nfunction parseTaxonomyType(raw: unknown, sourceFile: string): ParseResult {\n const result = TaxonomyTypeRawSchema.safeParse(raw)\n if (!result.success) {\n return { ok: false, errors: zodErrorsToParseErrors(result.error, sourceFile) }\n }\n const v = result.data\n\n const dupErrors = checkDuplicateFieldNames(v.fields, sourceFile, v.name)\n if (dupErrors.length > 0) return { ok: false, errors: dupErrors }\n\n const tableName = machineNameToTableName(v.name)\n const { fields, errors } = buildFields(v.fields, sourceFile, tableName)\n if (errors.length > 0) return { ok: false, errors }\n\n // Taxonomy API paths always live under /api/taxonomy/<name-in-kebab>\n const nameKebab = nameSegmentToKebab(getNameSegment(v.name))\n const basePath = `/api/taxonomy/${nameKebab}`\n\n const schema: ParsedTaxonomyType = {\n schema_type: 'taxonomy-type',\n name: v.name,\n label: v.label,\n source_file: sourceFile,\n system_fields: TAXONOMY_SYSTEM_FIELDS,\n fields,\n db: { table_name: tableName },\n api: {\n collection_path: basePath,\n item_path: `${basePath}/:id`,\n },\n }\n\n return { ok: true, schema }\n}\n\nfunction parseEnumType(raw: unknown, sourceFile: string): ParseResult {\n const result = EnumTypeRawSchema.safeParse(raw)\n if (!result.success) {\n return { ok: false, errors: zodErrorsToParseErrors(result.error, sourceFile) }\n }\n const v = result.data\n\n const schema: ParsedEnumType = {\n schema_type: 'enum-type',\n name: v.name,\n label: v.label,\n source_file: sourceFile,\n values: v.values,\n }\n\n return { ok: true, schema }\n}\n\n// ─── Public entry point ───────────────────────────────────────────────────────\n\n/**\n * Parses a raw schema object (from JSON or YAML) into the corresponding\n * Parsed* type. Returns a ParseResult — never throws for expected failures.\n *\n * sourceFile is optional but should be supplied for accurate error reporting.\n */\nexport function parseSchema(\n raw: unknown,\n schemaType: SchemaType,\n sourceFile = ''\n): ParseResult {\n switch (schemaType) {\n case 'content-type': return parseContentType(raw, sourceFile)\n case 'paragraph-type': return parseParagraphType(raw, sourceFile)\n case 'taxonomy-type': return parseTaxonomyType(raw, sourceFile)\n case 'enum-type': return parseEnumType(raw, sourceFile)\n }\n}\n","import { z } from 'zod'\nimport type { Result, ParseError } from './loader'\nimport type { ParsedRoles, ParsedRole } from './validate'\nimport type { Permission } from '../types.js'\n\n// All 17 valid permission strings. roles:create, roles:edit, roles:delete are\n// excluded — roles are managed through schema files and CLI only.\nconst VALID_PERMISSIONS = new Set<Permission>([\n 'content:read', 'content:create', 'content:edit', 'content:delete',\n 'media:read', 'media:create', 'media:edit', 'media:delete',\n 'taxonomy:read','taxonomy:create','taxonomy:edit','taxonomy:delete',\n 'users:read', 'users:create', 'users:edit', 'users:delete',\n 'roles:read',\n])\n\n// The three permission strings that look structurally valid but are explicitly\n// forbidden — roles are not manageable through the admin panel or API.\nconst INVALID_ROLE_PERMISSIONS = new Set(['roles:create', 'roles:edit', 'roles:delete'])\n\n// Sorted array for deterministic valid_permissions output.\nexport const VALID_PERMISSIONS_LIST: Permission[] = [\n 'content:read', 'content:create', 'content:edit', 'content:delete',\n 'media:read', 'media:create', 'media:edit', 'media:delete',\n 'taxonomy:read','taxonomy:create','taxonomy:edit','taxonomy:delete',\n 'users:read', 'users:create', 'users:edit', 'users:delete',\n 'roles:read',\n]\n\n// ─── Zod validators ───────────────────────────────────────────────────────────\n\nconst RawRoleSchema = z.object({\n name: z.string().min(1),\n label: z.string().min(1),\n is_system: z.boolean().default(false),\n hierarchy_level: z.number().int().min(0),\n permissions: z.array(z.string()),\n})\n\nconst RawRolesFileSchema = z.object({\n roles: z.array(RawRoleSchema).min(1),\n})\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nfunction zodRolesErrorsToParseErrors(\n error: z.ZodError,\n sourceFile: string\n): ParseError[] {\n return error.issues.map((issue) => ({\n file: sourceFile,\n code: 'MISSING_REQUIRED_FIELD' as const,\n message: issue.message,\n ...(issue.path.length > 0 ? { path: issue.path.join('.') } : {}),\n }))\n}\n\n// ─── parseRoles ───────────────────────────────────────────────────────────────\n\n/**\n * Validates a raw roles.json object and produces a ParsedRoles value.\n *\n * Validation rules (all errors are accumulated — none stop early):\n * MISSING_REQUIRED_FIELD — name, label, hierarchy_level, or permissions absent\n * INVALID_PERMISSION — roles:create, roles:edit, or roles:delete present\n * UNKNOWN_PERMISSION — any other unrecognised permission string\n * DUPLICATE_HIERARCHY_LEVEL — two roles share the same hierarchy_level value\n *\n * Returns Result<ParsedRoles> — never throws for expected failures.\n * sourceFile is optional; supply it for accurate error file paths.\n */\nexport function parseRoles(\n raw: unknown,\n sourceFile = 'roles/roles.json'\n): Result<ParsedRoles> {\n const result = RawRolesFileSchema.safeParse(raw)\n if (!result.success) {\n return { ok: false, errors: zodRolesErrorsToParseErrors(result.error, sourceFile) }\n }\n\n const { roles } = result.data\n const errors: ParseError[] = []\n\n // ── Permission validation ──────────────────────────────────────────────────\n\n for (const role of roles) {\n for (let i = 0; i < role.permissions.length; i++) {\n const perm = role.permissions[i]!\n\n if (INVALID_ROLE_PERMISSIONS.has(perm)) {\n errors.push({\n file: sourceFile,\n code: 'INVALID_PERMISSION',\n message:\n `Role \"${role.name}\" contains invalid permission \"${perm}\" — ` +\n 'roles:create, roles:edit, and roles:delete are not valid permissions; ' +\n 'roles are managed through schema files and CLI only',\n path: `roles[${roles.indexOf(role)}].permissions[${i}]`,\n })\n } else if (!VALID_PERMISSIONS.has(perm as Permission)) {\n errors.push({\n file: sourceFile,\n code: 'UNKNOWN_PERMISSION',\n message: `Role \"${role.name}\" contains unknown permission \"${perm}\"`,\n path: `roles[${roles.indexOf(role)}].permissions[${i}]`,\n })\n }\n }\n }\n\n // ── Duplicate hierarchy_level check ───────────────────────────────────────\n\n const levelsSeen = new Map<number, string>() // level → first role name\n\n for (let i = 0; i < roles.length; i++) {\n const role = roles[i]!\n const existing = levelsSeen.get(role.hierarchy_level)\n\n if (existing !== undefined) {\n errors.push({\n file: sourceFile,\n code: 'DUPLICATE_HIERARCHY_LEVEL',\n message:\n `Roles \"${existing}\" and \"${role.name}\" both have hierarchy_level ${role.hierarchy_level} — ` +\n 'each role must have a unique hierarchy_level',\n path: `roles[${i}].hierarchy_level`,\n })\n } else {\n levelsSeen.set(role.hierarchy_level, role.name)\n }\n }\n\n if (errors.length > 0) return { ok: false, errors }\n\n // ── Build output ───────────────────────────────────────────────────────────\n\n const parsedRoles: ParsedRole[] = roles\n .map((r) => ({\n name: r.name,\n label: r.label,\n is_system: r.is_system,\n hierarchy_level: r.hierarchy_level,\n permissions: r.permissions as Permission[],\n }))\n .sort((a, b) => a.hierarchy_level - b.hierarchy_level)\n\n const parsed: ParsedRoles = {\n roles: parsedRoles,\n valid_permissions: VALID_PERMISSIONS_LIST,\n }\n\n return { ok: true, value: parsed }\n}\n","import bcrypt from 'bcryptjs'\n\nconst SALT_ROUNDS = 12\n\nexport async function hashPassword(password: string): Promise<string> {\n return bcrypt.hash(password, SALT_ROUNDS)\n}\n\nexport async function verifyPassword(password: string, stored: string): Promise<boolean> {\n return bcrypt.compare(password, stored)\n}\n"],"mappings":"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","names":["parseYaml","path","import_zod","bcrypt"]}
|