@bobbykim/manguito-cms-api 0.6.0 → 0.8.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/{chunk-JVP33FI2.mjs → chunk-IHEIX6P4.mjs} +67 -48
- package/dist/chunk-IHEIX6P4.mjs.map +1 -0
- package/dist/{chunk-XNXM4W4K.mjs → chunk-Y5SWT7PO.mjs} +24 -26
- package/dist/chunk-Y5SWT7PO.mjs.map +1 -0
- package/dist/codegen/index.js +3 -2
- package/dist/codegen/index.js.map +1 -1
- package/dist/codegen/index.mjs +3 -2
- package/dist/codegen/index.mjs.map +1 -1
- package/dist/graphql/index.d.mts +1 -0
- package/dist/graphql/index.d.ts +1 -0
- package/dist/graphql/index.js +40 -45
- package/dist/graphql/index.js.map +1 -1
- package/dist/graphql/index.mjs +2 -2
- package/dist/handler-VEOWJRAL.mjs +8 -0
- package/dist/index.js +454 -265
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +323 -150
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/dist/chunk-JVP33FI2.mjs.map +0 -1
- package/dist/chunk-XNXM4W4K.mjs.map +0 -1
- package/dist/handler-XZVDLKZ2.mjs +0 -8
- /package/dist/{handler-XZVDLKZ2.mjs.map → handler-VEOWJRAL.mjs.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/graphql/handler.ts","../src/graphql/schema.ts","../src/graphql/scalars.ts","../src/graphql/type-mapping.ts","../src/graphql/naming.ts","../src/graphql/filters.ts","../src/graphql/resolvers.ts","../src/graphql/version-view.ts","../src/graphql/dataloaders.ts","../src/graphql/security.ts"],"sourcesContent":["import { createYoga, maskError } from 'graphql-yoga'\nimport type { Handler } from 'hono'\nimport type { SchemaRegistry, ContentRepository, VersionProjection } from '@bobbykim/manguito-cms-core'\nimport type { DrizzlePostgresInstance } from '@bobbykim/manguito-cms-db'\nimport type { ProgrammaticResolver } from '../programmatic/resolve.js'\nimport type { FieldKeyMap } from '../field-keys.js'\nimport type { GraphQLContext } from './context.js'\nimport { buildGraphQLSchema } from './schema.js'\nimport { buildVersionView, type VersionView } from './version-view.js'\nimport { createRelationLoaders } from './dataloaders.js'\nimport { buildArmorPlugin, introspectionPlugin } from './security.js'\n\nexport type ResolvedGraphQLOptions = {\n enabled: boolean\n maxDepth: number\n maxComplexity: number\n graphiql: boolean\n introspection: boolean\n}\n\n// Yoga decides whether an error is safe to show a client with\n// `error instanceof GraphQLError`. That check is realm-sensitive: GraphQL Armor\n// is CJS and throws a GraphQLError built from graphql's CJS entry, while Yoga is\n// ESM and compares against the class from graphql's ESM entry. Same version, two\n// classes — so `instanceof` fails and a depth/complexity rejection, which is the\n// client's own query being too large, was masked as\n// `INTERNAL_SERVER_ERROR: Unexpected error.` and logged server-side as a fault.\n//\n// Identify by name instead (what envelop's own masking does), walking the\n// originalError chain the same way. A GraphQLError with no originalError was\n// constructed deliberately by a validation rule or by us and carries no internals;\n// anything else — a resolver throwing, a driver error — still goes to Yoga's\n// masking untouched, dev-mode originalError detail included.\nfunction isClientSafeGraphQLError(error: unknown): boolean {\n let current = error as { name?: string; originalError?: unknown } | null | undefined\n while (current != null && typeof current === 'object' && current.name === 'GraphQLError') {\n if (current.originalError == null) return true\n current = current.originalError as typeof current\n }\n return false\n}\n\nexport function createGraphQLHandler(\n registry: SchemaRegistry,\n repos: Record<string, ContentRepository<unknown>>,\n fieldKeyMaps: Record<string, FieldKeyMap>,\n resolver: ProgrammaticResolver,\n db: DrizzlePostgresInstance,\n options: ResolvedGraphQLOptions,\n // The view is built HERE, not in app.ts: the `.` entry must keep no static\n // import of anything under graphql/ (ADR api/0006), so app.ts passes the\n // plain projection data it already imports as types from core.\n versioning: {\n endpoint?: string\n projection?: VersionProjection\n currentProjection?: VersionProjection\n currentVersion?: string\n // Current's field-key maps. A programmatic resolver reads its record in\n // current's labels on every version; omitted, it reads `fieldKeyMaps`.\n currentFieldKeyMaps?: Record<string, FieldKeyMap>\n } = {}\n): Handler {\n let view: VersionView | undefined\n if (versioning.projection !== undefined) {\n if (versioning.currentVersion === undefined) {\n throw new Error(\n 'createGraphQLHandler: currentVersion is required when a projection is supplied — ' +\n 'deprecation reasons name it, and an empty one ships \"Removed in .\" into published SDL.'\n )\n }\n view = buildVersionView({\n registry,\n projection: versioning.projection,\n currentProjection: versioning.currentProjection,\n currentVersion: versioning.currentVersion,\n })\n }\n const schema = buildGraphQLSchema(registry, fieldKeyMaps, view, versioning.currentFieldKeyMaps ?? fieldKeyMaps)\n const { plugins } = buildArmorPlugin({\n maxDepth: options.maxDepth,\n maxComplexity: options.maxComplexity,\n })\n\n const yoga = createYoga<Record<string, never>, GraphQLContext>({\n schema,\n graphqlEndpoint: versioning.endpoint ?? '/graphql',\n graphiql: options.graphiql,\n landingPage: false,\n maskedErrors: {\n maskError: (error, message, isDev) =>\n isClientSafeGraphQLError(error) ? (error as Error) : maskError(error, message, isDev),\n },\n // buildArmorPlugin's return type is `unknown[]` (see security.ts) since Armor's\n // plugin shapes aren't part of its public typings; Yoga's `plugins` option only\n // accepts its own `Plugin` type, so the cast bridges the two.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n plugins: [...(plugins as any[]), introspectionPlugin(options.introspection)],\n context: (): GraphQLContext => ({\n db,\n registry,\n repos,\n resolver,\n loaders: createRelationLoaders(db, registry),\n programmaticMemo: new WeakMap(),\n }),\n })\n\n return (c) => yoga.fetch(c.req.raw, {})\n}\n","import {\n GraphQLSchema,\n GraphQLObjectType,\n GraphQLEnumType,\n GraphQLNonNull,\n GraphQLList,\n GraphQLID,\n GraphQLString,\n GraphQLInt,\n GraphQLBoolean,\n type GraphQLFieldConfig,\n type GraphQLOutputType,\n type GraphQLFieldConfigMap,\n} from 'graphql'\nimport type {\n SchemaRegistry,\n ParsedContentType,\n ParsedTaxonomyType,\n ParsedParagraphType,\n ParsedField,\n ParsedEnumType,\n} from '@bobbykim/manguito-cms-core'\nimport { relationCardinality } from '@bobbykim/manguito-cms-core'\nimport type { GraphQLContext } from './context.js'\nimport type { FieldKeyMap } from '../field-keys.js'\nimport type { VersionView, ViewField } from './version-view.js'\nimport { DateTimeScalar } from './scalars.js'\nimport { scalarOutputType } from './type-mapping.js'\nimport {\n graphqlTypeName,\n singleQueryName,\n collectionQueryName,\n toCamelCase,\n isValidGraphQLName,\n buildFieldNameMap,\n} from './naming.js'\nimport { SortOrderEnum, buildSortFieldEnum, buildFilterInputType } from './filters.js'\nimport {\n scalarFieldResolver,\n relationFieldResolver,\n programmaticFieldResolver,\n collectionResolver,\n singleBySlugResolver,\n singletonResolver,\n taxonomySingleResolver,\n} from './resolvers.js'\n\nconst PAGE_META = new GraphQLObjectType({\n name: 'PageMeta',\n fields: {\n total: { type: new GraphQLNonNull(GraphQLInt), resolve: (m) => m.total },\n page: { type: new GraphQLNonNull(GraphQLInt), resolve: (m) => m.page },\n perPage: { type: new GraphQLNonNull(GraphQLInt), resolve: (m) => m.per_page },\n totalPages: { type: new GraphQLNonNull(GraphQLInt), resolve: (m) => m.total_pages },\n hasNext: { type: new GraphQLNonNull(GraphQLBoolean), resolve: (m) => m.has_next },\n hasPrev: { type: new GraphQLNonNull(GraphQLBoolean), resolve: (m) => m.has_prev },\n },\n})\n\nconst MEDIA = new GraphQLObjectType({\n name: 'Media',\n fields: {\n id: { type: new GraphQLNonNull(GraphQLID), resolve: (m) => m.id },\n type: { type: new GraphQLNonNull(GraphQLString), resolve: (m) => m.type },\n url: { type: new GraphQLNonNull(GraphQLString), resolve: (m) => m.url },\n mimeType: { type: new GraphQLNonNull(GraphQLString), resolve: (m) => m.mime_type },\n alt: { type: GraphQLString, resolve: (m) => m.alt },\n fileSize: { type: GraphQLInt, resolve: (m) => m.file_size },\n width: { type: GraphQLInt, resolve: (m) => m.width },\n height: { type: GraphQLInt, resolve: (m) => m.height },\n duration: { type: GraphQLInt, resolve: (m) => m.duration },\n },\n})\n\nexport function buildGraphQLSchema(\n registry: SchemaRegistry,\n fieldKeyMaps: Record<string, FieldKeyMap> = {},\n view?: VersionView,\n // The maps a programmatic resolver's record is built with: current's, on\n // every version. Defaults to `fieldKeyMaps`, which is right when they ARE\n // current's (no view, or the current version's own endpoint).\n programmaticKeyMaps: Record<string, FieldKeyMap> = fieldKeyMaps\n): GraphQLSchema {\n const objectTypes = new Map<string, GraphQLObjectType>() // machineName → type\n const enumTypes = new Map<string, GraphQLEnumType>() // enum machineName → type (only when valid)\n\n // Enum types (only when every value is a valid GraphQL identifier).\n for (const [name, enumType] of Object.entries(registry.enum_types) as [string, ParsedEnumType][]) {\n if (enumType.values.every(isValidGraphQLName)) {\n enumTypes.set(\n name,\n new GraphQLEnumType({\n name: graphqlTypeName(name),\n values: Object.fromEntries(enumType.values.map((v) => [v, { value: v }])),\n })\n )\n } else {\n process.stderr.write(\n `⚠ enum '${name}' has values that aren't valid GraphQL identifiers; exposing as String\\n`\n )\n }\n }\n\n // Output type for one field (scalar, enum, relation, media, programmatic).\n function outputTypeForField(field: ParsedField, required: boolean): GraphQLOutputType {\n const scalar = scalarOutputType(field.field_type)\n if (scalar) return required ? new GraphQLNonNull(scalar) : scalar\n\n if (field.field_type === 'enum') {\n const ref = field.ui_component.component === 'select' ? field.ui_component.enum_ref : undefined\n const et = ref ? enumTypes.get(ref) : undefined\n const t = et ?? GraphQLString\n return required ? new GraphQLNonNull(t) : t\n }\n\n if (field.field_type === 'image' || field.field_type === 'video' || field.field_type === 'file') {\n return MEDIA\n }\n\n if (field.field_type === 'paragraph') {\n const ref = field.ui_component.component === 'paragraph-embed' ? field.ui_component.ref : undefined\n const target = ref ? objectTypes.get(ref) : undefined\n if (ref && !target) {\n process.stderr.write(\n `⚠ paragraph field '${field.name}' targets unknown paragraph type '${ref}'; exposing as Media\\n`\n )\n }\n const t = (target ?? MEDIA) as GraphQLObjectType\n return relationCardinality(field) === 'one' ? t : new GraphQLList(new GraphQLNonNull(t))\n }\n\n if (field.field_type === 'reference') {\n const ref = field.ui_component.component === 'typeahead-select' ? field.ui_component.ref : undefined\n const target = ref ? objectTypes.get(ref) : undefined\n if (ref && !target) {\n process.stderr.write(`⚠ reference field '${field.name}' targets unknown type '${ref}'; exposing as Media\\n`)\n }\n const isMany = relationCardinality(field) === 'many'\n const t = (target ?? MEDIA) as GraphQLObjectType\n return isMany ? new GraphQLList(new GraphQLNonNull(t)) : t\n }\n\n return GraphQLString\n }\n\n /**\n * A type's fields minus its tombstones.\n *\n * A tombstone (`removed: true`) is column-backed — the parser keeps its\n * column alive for older live versions — but the version being served must\n * never expose it. REST drops it via the FieldKeyMap's drop-set, which\n * `remap` applies; GraphQL resolves per field by column through\n * `resolveFieldValue` and never touches that map, so the exclusion has to\n * happen where the schema is BUILT. A field absent from the schema is a\n * validation error, so the retained value cannot reach a response at all.\n */\n function exposedFields(type: { fields: ParsedField[] }): ParsedField[] {\n return type.fields.filter((f) => f.removed !== true)\n }\n\n /**\n * The fields one schema exposes for a type, as ViewFields. With a view, the\n * served version's own list; without one, the registry's minus tombstones.\n */\n function viewFieldsFor(machineName: string, type: { fields: ParsedField[] }): ViewField[] {\n return (\n view?.[machineName]?.fields ??\n exposedFields(type).map((f) => ({ field: f, exposedAs: f.name, required: f.required }))\n )\n }\n\n // Build the object type for a content/taxonomy/paragraph type. Fields are a\n // thunk so relations can reference types created later (circular graphs).\n function buildObjectType(\n machineName: string,\n type: ParsedContentType | ParsedTaxonomyType | ParsedParagraphType\n ): GraphQLObjectType {\n const visible = viewFieldsFor(machineName, type)\n\n // Every live media field the type has NOW, by registry name. That is the\n // key ctx.loaders.load looks a field up by. The set is current's, not this\n // version's visible one: the programmatic record speaks current's labels,\n // and REST resolves every media field in the registry for it too.\n // Tombstones are excluded; current's map drops their column regardless.\n const mediaFieldNames = type.fields\n .filter(\n (f) =>\n f.removed !== true &&\n (f.field_type === 'image' || f.field_type === 'video' || f.field_type === 'file')\n )\n .map((f) => f.name)\n\n return new GraphQLObjectType({\n name: graphqlTypeName(machineName),\n fields: () => {\n const fields: GraphQLFieldConfigMap<Record<string, unknown>, GraphQLContext> = {}\n // System fields.\n fields['id'] = { type: new GraphQLNonNull(GraphQLID), resolve: (p) => p['id'] }\n if (type.schema_type !== 'paragraph-type') {\n fields['published'] = { type: new GraphQLNonNull(GraphQLBoolean), resolve: (p) => p['published'] }\n }\n if (type.schema_type === 'content-type') {\n fields['slug'] = { type: new GraphQLNonNull(GraphQLString), resolve: (p) => p['slug'] }\n }\n fields['createdAt'] = { type: new GraphQLNonNull(DateTimeScalar), resolve: (p) => p['created_at'] }\n fields['updatedAt'] = { type: new GraphQLNonNull(DateTimeScalar), resolve: (p) => p['updated_at'] }\n\n for (const vf of visible) {\n const field = vf.field\n const gqlName = toCamelCase(vf.exposedAs)\n const outType = outputTypeForField(field, vf.required)\n let resolve: GraphQLFieldConfig<Record<string, unknown>, GraphQLContext>['resolve']\n if (field.field_type === 'programmatic') {\n resolve = programmaticFieldResolver(machineName, field.name, mediaFieldNames, programmaticKeyMaps[machineName])\n } else if (\n field.field_type === 'reference' ||\n field.field_type === 'paragraph' ||\n field.field_type === 'image' ||\n field.field_type === 'video' ||\n field.field_type === 'file'\n ) {\n resolve = relationFieldResolver(machineName, field.name)\n } else {\n resolve = scalarFieldResolver(field, vf.fallback)\n }\n fields[gqlName] = {\n type: outType,\n resolve,\n // Conditional spread, not `deprecationReason: vf.deprecationReason`\n // — exactOptionalPropertyTypes forbids present-and-undefined.\n ...(vf.deprecationReason !== undefined && { deprecationReason: vf.deprecationReason }),\n }\n }\n return fields\n },\n })\n }\n\n // Pass 1: create every object type (empty-safe thunks resolve later).\n // Track GraphQL type name → machine name so two schemas that collapse to the\n // same GraphQL type name (e.g. content--author / taxonomy--author both → \"Author\")\n // fail loud here instead of surfacing as a cryptic GraphQLSchema build error.\n const typeNameOwners = new Map<string, string>() // graphqlTypeName → machineName\n function registerTypeName(machineName: string): void {\n const gqlName = graphqlTypeName(machineName)\n const owner = typeNameOwners.get(gqlName)\n if (owner !== undefined && owner !== machineName) {\n throw new Error(\n `GraphQL type name collision: '${gqlName}' is produced by both '${owner}' and '${machineName}'. ` +\n `Rename one schema's machine name segment so their GraphQL type names differ.`\n )\n }\n typeNameOwners.set(gqlName, machineName)\n }\n\n for (const [name, ct] of Object.entries(registry.content_types)) {\n registerTypeName(name)\n objectTypes.set(name, buildObjectType(name, ct))\n }\n for (const [name, tt] of Object.entries(registry.taxonomy_types)) {\n registerTypeName(name)\n objectTypes.set(name, buildObjectType(name, tt))\n }\n for (const [name, pt] of Object.entries(registry.paragraph_types)) {\n registerTypeName(name)\n objectTypes.set(name, buildObjectType(name, pt))\n }\n\n // Pass 2: build the root Query type.\n const queryFields: GraphQLFieldConfigMap<unknown, GraphQLContext> = {}\n\n for (const [name, ct] of Object.entries(registry.content_types) as [string, ParsedContentType][]) {\n const objType = objectTypes.get(name)!\n const visible = viewFieldsFor(name, ct)\n // The version's own labels: translateFilters maps a GraphQL name back to a\n // label, and columnFor then takes that label to the storage column. System\n // fields go in too, because buildFilterInputType advertises createdAt and\n // updatedAt on every filter. Without them `createdAt` would fall through as\n // its own column name. columnFor returns nothing for a system field, so\n // translateFilters falls back to the name itself, which IS its column.\n const nameMap = buildFieldNameMap([\n ...visible.map((v) => v.exposedAs),\n ...ct.system_fields.map((s) => s.name),\n ])\n\n if (ct.only_one) {\n queryFields[singleQueryName(name)] = { type: objType, resolve: singletonResolver(name) }\n continue\n }\n\n const listType = new GraphQLObjectType({\n name: `${graphqlTypeName(name)}List`,\n fields: {\n data: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(objType))), resolve: (r) => r.data },\n meta: { type: new GraphQLNonNull(PAGE_META), resolve: (r) => r.meta },\n },\n })\n const filterType = buildFilterInputType(ct, visible)\n\n queryFields[collectionQueryName(name)] = {\n type: new GraphQLNonNull(listType),\n args: {\n page: { type: GraphQLInt },\n perPage: { type: GraphQLInt },\n sortBy: { type: buildSortFieldEnum(graphqlTypeName(name), fieldKeyMaps[name]) },\n sortOrder: { type: SortOrderEnum },\n ...(filterType ? { filter: { type: filterType } } : {}),\n },\n resolve: collectionResolver(name, nameMap, fieldKeyMaps[name]),\n }\n queryFields[singleQueryName(name)] = {\n type: objType,\n args: { slug: { type: new GraphQLNonNull(GraphQLString) } },\n resolve: singleBySlugResolver(name),\n }\n }\n\n for (const [name, tt] of Object.entries(registry.taxonomy_types) as [string, ParsedTaxonomyType][]) {\n const objType = objectTypes.get(name)!\n const listType = new GraphQLObjectType({\n name: `${graphqlTypeName(name)}List`,\n fields: {\n data: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(objType))), resolve: (r) => r.data },\n meta: { type: new GraphQLNonNull(PAGE_META), resolve: (r) => r.meta },\n },\n })\n queryFields[collectionQueryName(name)] = {\n type: new GraphQLNonNull(listType),\n args: { page: { type: GraphQLInt }, perPage: { type: GraphQLInt } },\n resolve: collectionResolver(\n name,\n buildFieldNameMap(viewFieldsFor(name, tt).map((v) => v.exposedAs)),\n fieldKeyMaps[name]\n ),\n }\n queryFields[singleQueryName(name)] = {\n type: objType,\n args: { id: { type: new GraphQLNonNull(GraphQLID) } },\n resolve: taxonomySingleResolver(name),\n }\n }\n\n return new GraphQLSchema({\n query: new GraphQLObjectType({ name: 'Query', fields: queryFields }),\n })\n}\n","import { GraphQLScalarType, Kind, valueFromASTUntyped } from 'graphql'\n\nexport const DateTimeScalar = new GraphQLScalarType({\n name: 'DateTime',\n description: 'ISO-8601 date-time string',\n serialize(value) {\n if (value instanceof Date) return value.toISOString()\n if (typeof value === 'string') return value\n if (typeof value === 'number') return new Date(value).toISOString()\n throw new TypeError(`DateTime cannot serialize value: ${String(value)}`)\n },\n parseValue(value) {\n if (typeof value !== 'string') throw new TypeError('DateTime must be a string')\n return value\n },\n parseLiteral(ast) {\n if (ast.kind !== Kind.STRING) throw new TypeError('DateTime must be a string')\n return ast.value\n },\n})\n\nexport const JSONScalar = new GraphQLScalarType({\n name: 'JSON',\n description: 'Arbitrary JSON value',\n serialize: (value) => value,\n parseValue: (value) => value,\n parseLiteral: (ast, variables) => valueFromASTUntyped(ast, variables ?? undefined),\n})\n","import {\n GraphQLString,\n GraphQLInt,\n GraphQLFloat,\n GraphQLBoolean,\n type GraphQLScalarType,\n} from 'graphql'\nimport type { FieldType } from '@bobbykim/manguito-cms-core'\nimport { DateTimeScalar, JSONScalar } from './scalars.js'\n\n// Scalar output type for a field. Relation/enum fields return null — schema.ts\n// resolves those against its type caches.\nexport function scalarOutputType(fieldType: FieldType): GraphQLScalarType | null {\n switch (fieldType) {\n case 'text/plain':\n case 'text/rich':\n return GraphQLString\n case 'integer':\n return GraphQLInt\n case 'float':\n return GraphQLFloat\n case 'boolean':\n return GraphQLBoolean\n case 'date':\n return DateTimeScalar\n case 'programmatic':\n return JSONScalar\n default:\n return null\n }\n}\n","// \"content--blog_post\" → \"blog_post\"; \"category\" → \"category\"\nexport function schemaSegment(machineName: string): string {\n const idx = machineName.indexOf('--')\n return idx === -1 ? machineName : machineName.slice(idx + 2)\n}\n\nfunction words(input: string): string[] {\n return input.split(/[_\\s-]+/).filter(Boolean)\n}\n\nexport function toPascalCase(input: string): string {\n return words(input)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('')\n}\n\nexport function toCamelCase(input: string): string {\n const pascal = toPascalCase(input)\n return pascal.charAt(0).toLowerCase() + pascal.slice(1)\n}\n\n// Deterministic English pluralization for the common cases; irregular plurals\n// (person→people) are a known limitation — an optional per-type override can be\n// added later if one is wrong.\nexport function pluralize(word: string): string {\n if (/[^aeiou]y$/.test(word)) return word.slice(0, -1) + 'ies'\n if (/(s|x|z|ch|sh)$/.test(word)) return word + 'es'\n return word + 's'\n}\n\nconst GRAPHQL_NAME = /^[_A-Za-z][_0-9A-Za-z]*$/\nexport function isValidGraphQLName(name: string): boolean {\n return GRAPHQL_NAME.test(name)\n}\n\nexport function graphqlTypeName(machineName: string): string {\n return toPascalCase(schemaSegment(machineName))\n}\n\nexport function singleQueryName(machineName: string): string {\n return toCamelCase(schemaSegment(machineName))\n}\n\nexport function collectionQueryName(machineName: string): string {\n return pluralize(singleQueryName(machineName))\n}\n\nexport function buildFieldNameMap(schemaNames: string[]): {\n toGraphql(schemaName: string): string\n toSchema(graphqlName: string): string\n} {\n const toG = new Map<string, string>()\n const toS = new Map<string, string>()\n for (const name of schemaNames) {\n const g = toCamelCase(name)\n toG.set(name, g)\n toS.set(g, name)\n }\n return {\n toGraphql: (schemaName) => toG.get(schemaName) ?? toCamelCase(schemaName),\n toSchema: (graphqlName) => toS.get(graphqlName) ?? graphqlName,\n }\n}\n","import {\n GraphQLEnumType,\n GraphQLInputObjectType,\n GraphQLList,\n GraphQLNonNull,\n GraphQLString,\n GraphQLBoolean,\n GraphQLInt,\n GraphQLFloat,\n type GraphQLInputType,\n} from 'graphql'\nimport type {\n ParsedContentType,\n ParsedTaxonomyType,\n ParsedField,\n FilterValue,\n FilterOperator,\n FieldType,\n} from '@bobbykim/manguito-cms-core'\nimport { graphqlTypeName, buildFieldNameMap } from './naming.js'\nimport { scalarOutputType } from './type-mapping.js'\nimport { DateTimeScalar } from './scalars.js'\nimport type { FieldKeyMap } from '../field-keys.js'\nimport type { ViewField } from './version-view.js'\n\nexport const SortOrderEnum = new GraphQLEnumType({\n name: 'SortOrder',\n values: { ASC: { value: 'asc' }, DESC: { value: 'desc' } },\n})\n\n// Only these fields are sortable (mirrors the REST SORTABLE_FIELDS).\n//\n// `value` is the enum's internal value, and it is NOT uniformly a storage\n// column: `created_at` / `updated_at` are the snake_case forms of real system\n// columns, but `title` is a schema field's LABEL — the same value REST accepts\n// in `?sort_by=`. `collectionResolver` maps it to a column through the type's\n// FieldKeyMap before the repository builds its ORDER BY.\nconst SORTABLE: Array<{ gql: string; value: string }> = [\n { gql: 'title', value: 'title' },\n { gql: 'createdAt', value: 'created_at' },\n { gql: 'updatedAt', value: 'updated_at' },\n]\n\n/**\n * `fieldKeys` is THIS version's map. `title` in SORTABLE is a schema field's\n * LABEL, not a column, so a version that has no field with that label cannot\n * resolve it — and offering it anyway hands the repository a label that maps\n * to nothing, which surfaces as a 500 from SQL rather than a rejected query.\n * Mirrors `sortableColumnsFor` in versions.ts.\n *\n * `createdAt`/`updatedAt` are real system columns on every content type, so\n * they are always offered and the enum can never end up empty — which\n * GraphQL rejects.\n *\n * With no map, every value is kept: callers that have not threaded a\n * FieldKeyMap through behave exactly as before.\n */\nexport function buildSortFieldEnum(typeName: string, fieldKeys?: FieldKeyMap): GraphQLEnumType {\n const resolvable = SORTABLE.filter(\n (s) =>\n s.gql === 'createdAt' ||\n s.gql === 'updatedAt' ||\n fieldKeys === undefined ||\n fieldKeys.columnFor(s.value) !== undefined\n )\n return new GraphQLEnumType({\n name: `${typeName}SortField`,\n values: Object.fromEntries(resolvable.map((s) => [s.gql, { value: s.value }])),\n })\n}\n\n// A comparable filter input (eq/in/gt/gte/lt/lte) for a given scalar input type.\nfunction comparableFilterInput(name: string, scalar: GraphQLInputType): GraphQLInputObjectType {\n return new GraphQLInputObjectType({\n name,\n fields: {\n eq: { type: scalar },\n in: { type: new GraphQLList(new GraphQLNonNull(scalar)) },\n gt: { type: scalar },\n gte: { type: scalar },\n lt: { type: scalar },\n lte: { type: scalar },\n },\n })\n}\n\nfunction equalityFilterInput(name: string, scalar: GraphQLInputType): GraphQLInputObjectType {\n return new GraphQLInputObjectType({\n name,\n fields: {\n eq: { type: scalar },\n in: { type: new GraphQLList(new GraphQLNonNull(scalar)) },\n },\n })\n}\n\n// Shared per-scalar filter inputs (built once).\nconst StringFilter = equalityFilterInput('StringFilter', GraphQLString)\nconst BooleanFilter = new GraphQLInputObjectType({\n name: 'BooleanFilter',\n fields: { eq: { type: GraphQLBoolean } },\n})\nconst DateTimeFilter = comparableFilterInput('DateTimeFilter', DateTimeScalar)\nconst IDFilter = equalityFilterInput('IDFilter', GraphQLString)\nconst IntFilter = comparableFilterInput('IntFilter', GraphQLInt)\nconst FloatFilter = comparableFilterInput('FloatFilter', GraphQLFloat)\n\n// Choose a filter input for a field based on its scalar output type.\nfunction filterInputForField(fieldType: FieldType): GraphQLInputObjectType | null {\n const scalar = scalarOutputType(fieldType)\n if (fieldType === 'boolean') return BooleanFilter\n if (fieldType === 'date') return DateTimeFilter\n if (fieldType === 'integer') return IntFilter\n if (fieldType === 'float') return FloatFilter\n if (fieldType === 'reference') return IDFilter\n if (scalar === null) return null // only 'enum' reaches here — not filterable via a scalar input\n return StringFilter\n}\n\n// Build the <Type>Filter input. Programmatic fields are excluded (no column).\nexport function buildFilterInputType(\n type: ParsedContentType | ParsedTaxonomyType,\n viewFields?: ViewField[]\n): GraphQLInputObjectType | null {\n const fields: Record<string, { type: GraphQLInputObjectType }> = {}\n\n // System fields that are filterable columns.\n fields['id'] = { type: IDFilter }\n fields['published'] = { type: BooleanFilter }\n fields['createdAt'] = { type: DateTimeFilter }\n fields['updatedAt'] = { type: DateTimeFilter }\n if (type.schema_type === 'content-type') fields['slug'] = { type: StringFilter }\n\n // A view states the label THIS version exposes each field under; without\n // one, fall back to the field's own name minus tombstones (Task 2's rule).\n const entries: Array<{ field: ParsedField; exposedAs: string }> =\n viewFields !== undefined\n ? viewFields.map((v) => ({ field: v.field, exposedAs: v.exposedAs }))\n : type.fields.filter((f) => f.removed !== true).map((f) => ({ field: f, exposedAs: f.name }))\n\n for (const { field: f, exposedAs } of entries) {\n if (f.field_type === 'programmatic' || f.field_type === 'paragraph') continue\n if (f.field_type === 'image' || f.field_type === 'video' || f.field_type === 'file') continue\n const input = filterInputForField(f.field_type)\n if (input) fields[buildFieldNameMap([exposedAs]).toGraphql(exposedAs)] = { type: input }\n }\n\n if (Object.keys(fields).length === 0) return null\n return new GraphQLInputObjectType({ name: `${graphqlTypeName(type.name)}Filter`, fields })\n}\n\n// Convert a GraphQL filter argument into the repository's filters map, keyed by\n// snake_case column. eq → scalar, in → array (OR/IN), gt/gte/lt/lte → operator.\n//\n// `nameMap.toSchema` only ever recovers the schema field's LABEL (`field.name`)\n// from the GraphQL name — that mapping is unaware of storage columns. `columnFor`\n// (typically `FieldKeyMap.columnFor`) takes that label the rest of the way to the\n// storage column the repository actually filters on. It's optional so callers\n// that haven't threaded a FieldKeyMap through yet keep working unchanged: with no\n// mapper, or when it returns nothing for a given label, the label itself is used —\n// correct as long as it equals its column.\nexport function translateFilters(\n input: Record<string, unknown> | undefined,\n nameMap: { toSchema(g: string): string },\n columnFor?: (label: string) => string | undefined\n): Record<string, FilterValue> {\n const out: Record<string, FilterValue> = {}\n if (!input) return out\n\n for (const [gqlField, raw] of Object.entries(input)) {\n if (raw === null || typeof raw !== 'object') continue\n const label = nameMap.toSchema(gqlField)\n const column = columnFor?.(label) ?? label\n const spec = raw as Record<string, unknown>\n\n // eq/in take priority over range operators (gt/gte/lt/lte) when a client sends\n // both in one field filter — the range operators are silently dropped.\n if (spec['eq'] !== undefined) {\n out[column] = spec['eq'] as FilterValue\n } else if (Array.isArray(spec['in'])) {\n out[column] = spec['in'] as FilterValue\n } else {\n const op: FilterOperator = {}\n for (const k of ['gt', 'gte', 'lt', 'lte'] as const) {\n if (spec[k] !== undefined) op[k] = spec[k] as number | string\n }\n if (Object.keys(op).length > 0) out[column] = op\n }\n }\n return out\n}\n","import { GraphQLError } from 'graphql'\nimport type { ParsedField } from '@bobbykim/manguito-cms-core'\nimport type { GraphQLContext } from './context.js'\nimport { translateFilters } from './filters.js'\nimport { isColumnBacked, type FieldKeyMap } from '../field-keys.js'\n\ntype Row = Record<string, unknown>\n\nfunction codeError(code: string, message: string): GraphQLError {\n return new GraphQLError(message, { extensions: { code } })\n}\n\nfunction isPublished(item: Row | null): boolean {\n return !!item && item['published'] === true\n}\n\n/**\n * A GraphQL field's value on a content row. The GraphQL field NAME comes from\n * the field's label (see naming.ts), but the value lives under its storage\n * column, which differs once a field has been renamed.\n *\n * `fallback` is the value a version declares for a column that stopped being\n * written: rows created since the removal hold null there. Substituted on\n * null/undefined ONLY — never on '' or 0 — matching projectRow's rule, so the\n * REST and GraphQL surfaces cannot disagree about the same version.\n */\nexport function resolveFieldValue(\n field: ParsedField,\n row: Record<string, unknown>,\n fallback?: unknown\n): unknown {\n const key = isColumnBacked(field) ? field.db_column.column_name : field.name\n const value = row[key]\n if ((value === null || value === undefined) && fallback !== undefined) return fallback\n return value ?? null\n}\n\nexport function scalarFieldResolver(field: ParsedField, fallback?: unknown) {\n return (parent: Row): unknown => resolveFieldValue(field, parent, fallback)\n}\n\nexport function relationFieldResolver(typeName: string, schemaFieldName: string) {\n return (parent: Row, _args: unknown, ctx: GraphQLContext): Promise<unknown> =>\n ctx.loaders.load(typeName, schemaFieldName, parent)\n}\n\nexport function programmaticFieldResolver(\n typeName: string,\n schemaFieldName: string,\n mediaFieldNames: readonly string[] = [],\n fieldKeys?: FieldKeyMap\n) {\n return async (parent: Row, _args: unknown, ctx: GraphQLContext): Promise<unknown> => {\n let p = ctx.programmaticMemo.get(parent)\n if (!p) {\n p = resolveProgrammaticRow(typeName, parent, ctx, mediaFieldNames, fieldKeys)\n ctx.programmaticMemo.set(parent, p)\n }\n return (await p)[schemaFieldName]\n }\n}\n\n// A programmatic resolver reads its record through `ctx.get()`, so that record\n// must look the same on both public surfaces. REST resolves media fields to full\n// objects before running resolvers; GraphQL reads through repositories that\n// resolve nothing, so without this `ctx.get('hero').url` would work over REST and\n// silently fall back to null over GraphQL.\n//\n// Media is resolved into a COPY, never the row itself: the programmatic record is\n// built from a copy so that projecting it to current's labels (toLabels below)\n// never touches the parent row, which the field resolvers still read by column.\n// The dataloaders resolve relations in place and idempotently now, so handing the\n// parent itself back to the loader would no longer break anything either — the\n// copy is kept to keep this path from mutating the parent, and it is harmless:\n// loaders still batch across the copy, so this costs no extra query.\n//\n// `ctx.get(fieldName)` takes the schema field name (the LABEL), so the record is\n// projected to CURRENT's labels (the caller passes current's map on every\n// version) before the resolver runs — the same order REST uses (see \"Response\n// projection order\" in routes/content.ts). GraphQL has no route-level\n// projection to double up with: every other field resolves per field by column\n// (resolveFieldValue), so this copy is the only mapped row, and it is mapped\n// strictly after the media loaders have run.\nasync function resolveProgrammaticRow(\n typeName: string,\n parent: Row,\n ctx: GraphQLContext,\n mediaFieldNames: readonly string[],\n fieldKeys?: FieldKeyMap\n): Promise<Record<string, unknown>> {\n const toLabels = (row: Row): Row => (fieldKeys ? fieldKeys.toLabels(row) : row)\n\n if (mediaFieldNames.length === 0) return ctx.resolver.resolveItem(typeName, toLabels(parent))\n\n const enriched: Row = { ...parent }\n await Promise.all(mediaFieldNames.map((name) => ctx.loaders.load(typeName, name, enriched)))\n // The loaders resolve each media object IN PLACE under its storage column,\n // so toLabels carries it to its label like any scalar.\n return ctx.resolver.resolveItem(typeName, toLabels(enriched))\n}\n\ntype CollectionArgs = {\n page?: number\n perPage?: number\n /**\n * The sort enum's internal value (filters.ts `SORTABLE`), which mixes two key\n * spaces: `created_at` / `updated_at` are system COLUMNS, but `title` is a\n * schema field's LABEL. It must be mapped before it reaches the repository.\n */\n sortBy?: string\n sortOrder?: 'asc' | 'desc'\n filter?: Record<string, unknown>\n}\n\nexport function collectionResolver(\n typeName: string,\n nameMap: { toSchema(g: string): string },\n fieldKeys?: FieldKeyMap\n) {\n return async (_root: unknown, args: CollectionArgs, ctx: GraphQLContext) => {\n const page = args.page ?? 1\n const perPage = args.perPage ?? 10\n if (!Number.isInteger(page) || page < 1) {\n throw codeError('INVALID_PAGINATION', 'page must be ≥ 1')\n }\n if (!Number.isInteger(perPage) || perPage < 1 || perPage > 100) {\n throw codeError('INVALID_PAGINATION', 'perPage must be between 1 and 100')\n }\n const repo = ctx.repos[typeName]!\n // `ORDER BY` takes a storage column, never a label. `columnFor` resolves a\n // schema field's label to its column; a system column (`created_at`,\n // `updated_at`) is not a label at all, so it has no entry and falls\n // through unchanged. Identity today, since every label equals its column.\n const sortBy = args.sortBy ?? 'created_at'\n const sortColumn = fieldKeys?.columnFor(sortBy) ?? sortBy\n const result = await repo.findMany({\n published_only: true,\n page,\n per_page: perPage,\n sort_by: sortColumn as 'title' | 'created_at' | 'updated_at',\n sort_order: args.sortOrder ?? 'asc',\n filters: translateFilters(args.filter, nameMap, fieldKeys?.columnFor),\n })\n return { data: result.data as Row[], meta: result.meta }\n }\n}\n\nexport function singleBySlugResolver(typeName: string) {\n return async (_root: unknown, args: { slug: string }, ctx: GraphQLContext): Promise<Row | null> => {\n const repo = ctx.repos[typeName]!\n const item = (await repo.findBySlug(args.slug)) as Row | null\n return isPublished(item) ? item : null\n }\n}\n\nexport function singletonResolver(typeName: string) {\n return async (_root: unknown, _args: unknown, ctx: GraphQLContext): Promise<Row | null> => {\n const repo = ctx.repos[typeName]!\n const result = await repo.findMany({ published_only: true, page: 1, per_page: 1 })\n return (result.data[0] as Row | undefined) ?? null\n }\n}\n\nexport function taxonomySingleResolver(typeName: string) {\n return async (_root: unknown, args: { id: string }, ctx: GraphQLContext): Promise<Row | null> => {\n const repo = ctx.repos[typeName]!\n const item = (await repo.findOne(args.id)) as Row | null\n return isPublished(item) ? item : null\n }\n}\n","import type { ParsedField, SchemaRegistry, VersionProjection } from '@bobbykim/manguito-cms-core'\nimport { isColumnBacked } from '../field-keys.js'\n\n// ─── One live version's view of the schema ────────────────────────────────────\n//\n// A VersionProjection says WHICH columns a version exposes, under WHICH labels,\n// and whether each is required. It deliberately says nothing about a field's\n// type: `field_type` and `ui_component` are recovered from CURRENT's field for\n// the same column instead.\n//\n// That join is sound, not convenient. `VERSION_COLUMN_MISSING` guarantees every\n// column a live version exposes still exists in current, and\n// `FIELD_TYPE_CHANGED_WHILE_LIVE` guarantees its type has not moved under it —\n// so current's field is a faithful source for everything except the label and\n// the requiredness, which the projection carries precisely because they DO\n// move. See the 2e design, \"Deriving a version's types\".\n\nexport type ViewField = {\n /** Current's field for this column — the source of `field_type` and `ui_component`. */\n field: ParsedField\n /** The name THIS version exposes the column under. */\n exposedAs: string\n /** THIS version's requiredness. Never current's — see VersionProjection. */\n required: boolean\n /**\n * The value to serve when the column holds null, for a column that stopped\n * being written. REST substitutes this in `projectRow`; GraphQL has no\n * route-level projection, so its scalar resolver has to do it or the two\n * surfaces disagree about the same version's contract.\n */\n fallback?: unknown\n /** Present only when this version's contract differs from current's. */\n deprecationReason?: string\n}\n\n/** Keyed by machine name, for content, taxonomy AND paragraph types. */\nexport type VersionView = Record<string, { fields: ViewField[] }>\n\n/** A type's column-backed fields keyed by column. Tombstones included — they hold a real column. */\nfunction byColumn(fields: ParsedField[]): Map<string, ParsedField> {\n const out = new Map<string, ParsedField>()\n for (const f of fields) {\n if (!isColumnBacked(f)) continue\n out.set(f.db_column.column_name, f)\n }\n return out\n}\n\n/**\n * Why this version's contract differs from current's, or undefined when it\n * does not. Keyed by COLUMN, because the label is exactly what may have moved.\n *\n * The reason names CURRENT, not the intermediate version where the change\n * happened: pinpointing that would mean walking every snapshot in between, and\n * \"what it is called now\" is the actionable fact for someone deciding whether\n * to upgrade.\n */\nfunction deprecationFor(\n field: { column_name: string; exposed_as: string },\n currentLabels: Map<string, string>,\n currentVersion: string\n): string | undefined {\n const currentLabel = currentLabels.get(field.column_name)\n if (currentLabel === undefined) {\n return `Removed in ${currentVersion}; column retained while this version is live.`\n }\n if (currentLabel !== field.exposed_as) {\n return `Renamed to '${currentLabel}' in ${currentVersion}.`\n }\n return undefined\n}\n\n/**\n * `projection` undefined means this version has no projection for a type — or\n * none at all. Those types fall back to the registry's own fields minus\n * tombstones, which is the inherited 2d boundary: paragraph types are never\n * projected, so nested paragraph content follows current's shape on every\n * version, by design.\n */\nexport function buildVersionView(input: {\n registry: SchemaRegistry\n projection: VersionProjection | undefined\n currentProjection: VersionProjection | undefined\n currentVersion: string\n}): VersionView {\n const { registry, projection, currentProjection, currentVersion } = input\n const out: VersionView = {}\n\n const sources: Array<Record<string, { fields: ParsedField[] }>> = [\n registry.content_types,\n registry.taxonomy_types,\n registry.paragraph_types,\n ]\n\n for (const source of sources) {\n for (const [typeName, type] of Object.entries(source)) {\n const projectionType = projection?.types[typeName]\n\n // No projection for this type: follow current, minus tombstones.\n if (projectionType === undefined) {\n out[typeName] = {\n fields: type.fields\n .filter((f) => f.removed !== true)\n .map((f) => ({ field: f, exposedAs: f.name, required: f.required })),\n }\n continue\n }\n\n const columns = byColumn(type.fields)\n const currentLabels = new Map<string, string>()\n for (const f of currentProjection?.types[typeName]?.fields ?? []) {\n currentLabels.set(f.column_name, f.exposed_as)\n }\n\n const fields: ViewField[] = []\n\n for (const pf of projectionType.fields) {\n const field = columns.get(pf.column_name)\n // Unreachable on a model that loaded — VERSION_COLUMN_MISSING rejects\n // it. Skipped rather than thrown so a hand-built baked model cannot\n // take the whole schema down over one field.\n if (field === undefined) continue\n const reason = deprecationFor(pf, currentLabels, currentVersion)\n fields.push({\n field,\n exposedAs: pf.exposed_as,\n required: pf.required,\n ...(pf.fallback !== undefined && { fallback: pf.fallback }),\n ...(reason !== undefined && { deprecationReason: reason }),\n })\n }\n\n // Fields with no column of their own — paragraph, many-to-many,\n // programmatic — never appear in a projection, so they must be appended\n // from the registry or an older version's schema would silently lose\n // every relation and computed field. They follow current on every\n // version (the 2d boundary), hence no deprecation reason.\n for (const f of type.fields) {\n if (isColumnBacked(f) || f.removed === true) continue\n fields.push({ field: f, exposedAs: f.name, required: f.required })\n }\n\n out[typeName] = { fields }\n }\n }\n\n return out\n}\n","import DataLoader from 'dataloader'\nimport type { DrizzlePostgresInstance } from '@bobbykim/manguito-cms-db'\nimport type {\n SchemaRegistry,\n ParsedContentType,\n ParsedTaxonomyType,\n ParsedParagraphType,\n} from '@bobbykim/manguito-cms-core'\nimport { buildRelationsMap, resolveRelationField, type RelationDef } from '../relations.js'\n\nexport interface RelationLoaders {\n load(typeName: string, fieldName: string, parent: Record<string, unknown>): Promise<unknown>\n}\n\ntype ParentRow = Record<string, unknown>\n\n// One RelationLoaders instance per request. Loaders batch sibling parents per\n// (type, field); the shared cache dedupes target lookups across all loaders in\n// the request, mirroring the repository's resolveRows cache.\nexport function createRelationLoaders(\n db: DrizzlePostgresInstance,\n registry: SchemaRegistry\n): RelationLoaders {\n const relMaps = new Map<string, Record<string, RelationDef>>()\n const loaders = new Map<string, DataLoader<ParentRow, unknown>>()\n const cache = new Map<string, unknown>()\n\n function relationsFor(typeName: string): Record<string, RelationDef> {\n let m = relMaps.get(typeName)\n if (!m) {\n const type = (registry.content_types[typeName] ??\n registry.taxonomy_types[typeName] ??\n registry.paragraph_types[typeName]) as\n | ParsedContentType\n | ParsedTaxonomyType\n | ParsedParagraphType\n | undefined\n m = type ? buildRelationsMap(type.fields, registry) : {}\n relMaps.set(typeName, m)\n }\n return m\n }\n\n function loaderFor(typeName: string, fieldName: string, rel: RelationDef): DataLoader<ParentRow, unknown> {\n const key = `${typeName}:${fieldName}`\n let dl = loaders.get(key)\n if (!dl) {\n dl = new DataLoader<ParentRow, unknown>(\n async (parents) => {\n const rows = parents as ParentRow[]\n // GraphQL is public-only (see app.ts) — always filter relation targets\n // to published rows, mirroring the REST public repos' publishedRelations.\n await resolveRelationField(db, rows, fieldName, rel, cache, true)\n // Column-backed relations resolve in place under their storage\n // column. Paragraph and junction relations have no column, so they\n // resolve under the field's name.\n // Not named `key`: loaderFor already declares one, for the cache.\n const resultKey = rel.type === 'reference' || rel.type === 'media' ? rel.fk_column : fieldName\n return rows.map((r) => r[resultKey])\n },\n // Batch within a tick; do not memoize by parent identity (rows are mutated\n // and may recur across nesting levels).\n { cache: false }\n )\n loaders.set(key, dl)\n }\n return dl\n }\n\n return {\n async load(typeName, fieldName, parent) {\n const rel = relationsFor(typeName)[fieldName]\n if (!rel) return null\n return loaderFor(typeName, fieldName, rel).load(parent)\n },\n }\n}\n","import { EnvelopArmor } from '@escape.tech/graphql-armor'\nimport { NoSchemaIntrospectionCustomRule } from 'graphql'\n\n// Depth + cost + alias + directive limits via GraphQL Armor. Returns { plugins } to\n// spread into Yoga's `plugins` array.\n//\n// Note: the installed `@escape.tech/graphql-armor` (3.2.0) exports `EnvelopArmor`, a\n// class whose `.protect()` returns `{ plugins }` — the standalone `EnvelopArmorPlugin`\n// export is a function that returns a single plugin, not a class with `.protect()`.\nexport function buildArmorPlugin(options: { maxDepth: number; maxComplexity: number }): {\n plugins: unknown[]\n} {\n const armor = new EnvelopArmor({\n maxDepth: { n: options.maxDepth },\n costLimit: { maxCost: options.maxComplexity },\n maxAliases: { n: 15 },\n maxDirectives: { n: 50 },\n blockFieldSuggestion: { enabled: true },\n // maxTokens is intentionally left at Armor's secure default (n=1000) to bound\n // GraphQL document token count at parse time, a layer the depth/cost/alias/directive\n // limits do not cover.\n })\n return armor.protect()\n}\n\n// Disables introspection (and the __schema/__type meta-fields) in production by\n// adding graphql's built-in validation rule when `enabled` is false.\nexport function introspectionPlugin(enabled: boolean): {\n onValidate(payload: { addValidationRule: (rule: unknown) => void }): void\n} {\n return {\n onValidate({ addValidationRule }) {\n if (!enabled) addValidationRule(NoSchemaIntrospectionCustomRule)\n },\n }\n}\n"],"mappings":";;;;;;;AAAA,SAAS,YAAY,iBAAiB;;;ACAtC;AAAA,EACE;AAAA,EACA;AAAA,EACA,mBAAAA;AAAA,EACA,kBAAAC;AAAA,EACA,eAAAC;AAAA,EACA;AAAA,EACA,iBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,kBAAAC;AAAA,OAIK;AASP,SAAS,2BAA2B;;;ACtBpC,SAAS,mBAAmB,MAAM,2BAA2B;AAEtD,IAAM,iBAAiB,IAAI,kBAAkB;AAAA,EAClD,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU,OAAO;AACf,QAAI,iBAAiB,KAAM,QAAO,MAAM,YAAY;AACpD,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAI,OAAO,UAAU,SAAU,QAAO,IAAI,KAAK,KAAK,EAAE,YAAY;AAClE,UAAM,IAAI,UAAU,oCAAoC,OAAO,KAAK,CAAC,EAAE;AAAA,EACzE;AAAA,EACA,WAAW,OAAO;AAChB,QAAI,OAAO,UAAU,SAAU,OAAM,IAAI,UAAU,2BAA2B;AAC9E,WAAO;AAAA,EACT;AAAA,EACA,aAAa,KAAK;AAChB,QAAI,IAAI,SAAS,KAAK,OAAQ,OAAM,IAAI,UAAU,2BAA2B;AAC7E,WAAO,IAAI;AAAA,EACb;AACF,CAAC;AAEM,IAAM,aAAa,IAAI,kBAAkB;AAAA,EAC9C,MAAM;AAAA,EACN,aAAa;AAAA,EACb,WAAW,CAAC,UAAU;AAAA,EACtB,YAAY,CAAC,UAAU;AAAA,EACvB,cAAc,CAAC,KAAK,cAAc,oBAAoB,KAAK,aAAa,MAAS;AACnF,CAAC;;;AC3BD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAMA,SAAS,iBAAiB,WAAgD;AAC/E,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;;;AC7BO,SAAS,cAAc,aAA6B;AACzD,QAAM,MAAM,YAAY,QAAQ,IAAI;AACpC,SAAO,QAAQ,KAAK,cAAc,YAAY,MAAM,MAAM,CAAC;AAC7D;AAEA,SAAS,MAAM,OAAyB;AACtC,SAAO,MAAM,MAAM,SAAS,EAAE,OAAO,OAAO;AAC9C;AAEO,SAAS,aAAa,OAAuB;AAClD,SAAO,MAAM,KAAK,EACf,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,CAAC,EACjD,KAAK,EAAE;AACZ;AAEO,SAAS,YAAY,OAAuB;AACjD,QAAM,SAAS,aAAa,KAAK;AACjC,SAAO,OAAO,OAAO,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,CAAC;AACxD;AAKO,SAAS,UAAU,MAAsB;AAC9C,MAAI,aAAa,KAAK,IAAI,EAAG,QAAO,KAAK,MAAM,GAAG,EAAE,IAAI;AACxD,MAAI,iBAAiB,KAAK,IAAI,EAAG,QAAO,OAAO;AAC/C,SAAO,OAAO;AAChB;AAEA,IAAM,eAAe;AACd,SAAS,mBAAmB,MAAuB;AACxD,SAAO,aAAa,KAAK,IAAI;AAC/B;AAEO,SAAS,gBAAgB,aAA6B;AAC3D,SAAO,aAAa,cAAc,WAAW,CAAC;AAChD;AAEO,SAAS,gBAAgB,aAA6B;AAC3D,SAAO,YAAY,cAAc,WAAW,CAAC;AAC/C;AAEO,SAAS,oBAAoB,aAA6B;AAC/D,SAAO,UAAU,gBAAgB,WAAW,CAAC;AAC/C;AAEO,SAAS,kBAAkB,aAGhC;AACA,QAAM,MAAM,oBAAI,IAAoB;AACpC,QAAM,MAAM,oBAAI,IAAoB;AACpC,aAAW,QAAQ,aAAa;AAC9B,UAAM,IAAI,YAAY,IAAI;AAC1B,QAAI,IAAI,MAAM,CAAC;AACf,QAAI,IAAI,GAAG,IAAI;AAAA,EACjB;AACA,SAAO;AAAA,IACL,WAAW,CAAC,eAAe,IAAI,IAAI,UAAU,KAAK,YAAY,UAAU;AAAA,IACxE,UAAU,CAAC,gBAAgB,IAAI,IAAI,WAAW,KAAK;AAAA,EACrD;AACF;;;AC9DA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,gBAAAC;AAAA,OAEK;AAeA,IAAM,gBAAgB,IAAI,gBAAgB;AAAA,EAC/C,MAAM;AAAA,EACN,QAAQ,EAAE,KAAK,EAAE,OAAO,MAAM,GAAG,MAAM,EAAE,OAAO,OAAO,EAAE;AAC3D,CAAC;AASD,IAAM,WAAkD;AAAA,EACtD,EAAE,KAAK,SAAS,OAAO,QAAQ;AAAA,EAC/B,EAAE,KAAK,aAAa,OAAO,aAAa;AAAA,EACxC,EAAE,KAAK,aAAa,OAAO,aAAa;AAC1C;AAgBO,SAAS,mBAAmB,UAAkB,WAA0C;AAC7F,QAAM,aAAa,SAAS;AAAA,IAC1B,CAAC,MACC,EAAE,QAAQ,eACV,EAAE,QAAQ,eACV,cAAc,UACd,UAAU,UAAU,EAAE,KAAK,MAAM;AAAA,EACrC;AACA,SAAO,IAAI,gBAAgB;AAAA,IACzB,MAAM,GAAG,QAAQ;AAAA,IACjB,QAAQ,OAAO,YAAY,WAAW,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAAA,EAC/E,CAAC;AACH;AAGA,SAAS,sBAAsB,MAAc,QAAkD;AAC7F,SAAO,IAAI,uBAAuB;AAAA,IAChC;AAAA,IACA,QAAQ;AAAA,MACN,IAAI,EAAE,MAAM,OAAO;AAAA,MACnB,IAAI,EAAE,MAAM,IAAI,YAAY,IAAI,eAAe,MAAM,CAAC,EAAE;AAAA,MACxD,IAAI,EAAE,MAAM,OAAO;AAAA,MACnB,KAAK,EAAE,MAAM,OAAO;AAAA,MACpB,IAAI,EAAE,MAAM,OAAO;AAAA,MACnB,KAAK,EAAE,MAAM,OAAO;AAAA,IACtB;AAAA,EACF,CAAC;AACH;AAEA,SAAS,oBAAoB,MAAc,QAAkD;AAC3F,SAAO,IAAI,uBAAuB;AAAA,IAChC;AAAA,IACA,QAAQ;AAAA,MACN,IAAI,EAAE,MAAM,OAAO;AAAA,MACnB,IAAI,EAAE,MAAM,IAAI,YAAY,IAAI,eAAe,MAAM,CAAC,EAAE;AAAA,IAC1D;AAAA,EACF,CAAC;AACH;AAGA,IAAM,eAAe,oBAAoB,gBAAgBC,cAAa;AACtE,IAAM,gBAAgB,IAAI,uBAAuB;AAAA,EAC/C,MAAM;AAAA,EACN,QAAQ,EAAE,IAAI,EAAE,MAAMC,gBAAe,EAAE;AACzC,CAAC;AACD,IAAM,iBAAiB,sBAAsB,kBAAkB,cAAc;AAC7E,IAAM,WAAW,oBAAoB,YAAYD,cAAa;AAC9D,IAAM,YAAY,sBAAsB,aAAaE,WAAU;AAC/D,IAAM,cAAc,sBAAsB,eAAeC,aAAY;AAGrE,SAAS,oBAAoB,WAAqD;AAChF,QAAM,SAAS,iBAAiB,SAAS;AACzC,MAAI,cAAc,UAAW,QAAO;AACpC,MAAI,cAAc,OAAQ,QAAO;AACjC,MAAI,cAAc,UAAW,QAAO;AACpC,MAAI,cAAc,QAAS,QAAO;AAClC,MAAI,cAAc,YAAa,QAAO;AACtC,MAAI,WAAW,KAAM,QAAO;AAC5B,SAAO;AACT;AAGO,SAAS,qBACd,MACA,YAC+B;AAC/B,QAAM,SAA2D,CAAC;AAGlE,SAAO,IAAI,IAAI,EAAE,MAAM,SAAS;AAChC,SAAO,WAAW,IAAI,EAAE,MAAM,cAAc;AAC5C,SAAO,WAAW,IAAI,EAAE,MAAM,eAAe;AAC7C,SAAO,WAAW,IAAI,EAAE,MAAM,eAAe;AAC7C,MAAI,KAAK,gBAAgB,eAAgB,QAAO,MAAM,IAAI,EAAE,MAAM,aAAa;AAI/E,QAAM,UACJ,eAAe,SACX,WAAW,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,WAAW,EAAE,UAAU,EAAE,IAClE,KAAK,OAAO,OAAO,CAAC,MAAM,EAAE,YAAY,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,EAAE,KAAK,EAAE;AAEhG,aAAW,EAAE,OAAO,GAAG,UAAU,KAAK,SAAS;AAC7C,QAAI,EAAE,eAAe,kBAAkB,EAAE,eAAe,YAAa;AACrE,QAAI,EAAE,eAAe,WAAW,EAAE,eAAe,WAAW,EAAE,eAAe,OAAQ;AACrF,UAAM,QAAQ,oBAAoB,EAAE,UAAU;AAC9C,QAAI,MAAO,QAAO,kBAAkB,CAAC,SAAS,CAAC,EAAE,UAAU,SAAS,CAAC,IAAI,EAAE,MAAM,MAAM;AAAA,EACzF;AAEA,MAAI,OAAO,KAAK,MAAM,EAAE,WAAW,EAAG,QAAO;AAC7C,SAAO,IAAI,uBAAuB,EAAE,MAAM,GAAG,gBAAgB,KAAK,IAAI,CAAC,UAAU,OAAO,CAAC;AAC3F;AAYO,SAAS,iBACd,OACA,SACA,WAC6B;AAC7B,QAAM,MAAmC,CAAC;AAC1C,MAAI,CAAC,MAAO,QAAO;AAEnB,aAAW,CAAC,UAAU,GAAG,KAAK,OAAO,QAAQ,KAAK,GAAG;AACnD,QAAI,QAAQ,QAAQ,OAAO,QAAQ,SAAU;AAC7C,UAAM,QAAQ,QAAQ,SAAS,QAAQ;AACvC,UAAM,SAAS,YAAY,KAAK,KAAK;AACrC,UAAM,OAAO;AAIb,QAAI,KAAK,IAAI,MAAM,QAAW;AAC5B,UAAI,MAAM,IAAI,KAAK,IAAI;AAAA,IACzB,WAAW,MAAM,QAAQ,KAAK,IAAI,CAAC,GAAG;AACpC,UAAI,MAAM,IAAI,KAAK,IAAI;AAAA,IACzB,OAAO;AACL,YAAM,KAAqB,CAAC;AAC5B,iBAAW,KAAK,CAAC,MAAM,OAAO,MAAM,KAAK,GAAY;AACnD,YAAI,KAAK,CAAC,MAAM,OAAW,IAAG,CAAC,IAAI,KAAK,CAAC;AAAA,MAC3C;AACA,UAAI,OAAO,KAAK,EAAE,EAAE,SAAS,EAAG,KAAI,MAAM,IAAI;AAAA,IAChD;AAAA,EACF;AACA,SAAO;AACT;;;AC9LA,SAAS,oBAAoB;AAQ7B,SAAS,UAAU,MAAc,SAA+B;AAC9D,SAAO,IAAI,aAAa,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AAC3D;AAEA,SAAS,YAAY,MAA2B;AAC9C,SAAO,CAAC,CAAC,QAAQ,KAAK,WAAW,MAAM;AACzC;AAYO,SAAS,kBACd,OACA,KACA,UACS;AACT,QAAM,MAAM,eAAe,KAAK,IAAI,MAAM,UAAU,cAAc,MAAM;AACxE,QAAM,QAAQ,IAAI,GAAG;AACrB,OAAK,UAAU,QAAQ,UAAU,WAAc,aAAa,OAAW,QAAO;AAC9E,SAAO,SAAS;AAClB;AAEO,SAAS,oBAAoB,OAAoB,UAAoB;AAC1E,SAAO,CAAC,WAAyB,kBAAkB,OAAO,QAAQ,QAAQ;AAC5E;AAEO,SAAS,sBAAsB,UAAkB,iBAAyB;AAC/E,SAAO,CAAC,QAAa,OAAgB,QACnC,IAAI,QAAQ,KAAK,UAAU,iBAAiB,MAAM;AACtD;AAEO,SAAS,0BACd,UACA,iBACA,kBAAqC,CAAC,GACtC,WACA;AACA,SAAO,OAAO,QAAa,OAAgB,QAA0C;AACnF,QAAI,IAAI,IAAI,iBAAiB,IAAI,MAAM;AACvC,QAAI,CAAC,GAAG;AACN,UAAI,uBAAuB,UAAU,QAAQ,KAAK,iBAAiB,SAAS;AAC5E,UAAI,iBAAiB,IAAI,QAAQ,CAAC;AAAA,IACpC;AACA,YAAQ,MAAM,GAAG,eAAe;AAAA,EAClC;AACF;AAuBA,eAAe,uBACb,UACA,QACA,KACA,iBACA,WACkC;AAClC,QAAM,WAAW,CAAC,QAAmB,YAAY,UAAU,SAAS,GAAG,IAAI;AAE3E,MAAI,gBAAgB,WAAW,EAAG,QAAO,IAAI,SAAS,YAAY,UAAU,SAAS,MAAM,CAAC;AAE5F,QAAM,WAAgB,EAAE,GAAG,OAAO;AAClC,QAAM,QAAQ,IAAI,gBAAgB,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,UAAU,MAAM,QAAQ,CAAC,CAAC;AAG3F,SAAO,IAAI,SAAS,YAAY,UAAU,SAAS,QAAQ,CAAC;AAC9D;AAeO,SAAS,mBACd,UACA,SACA,WACA;AACA,SAAO,OAAO,OAAgB,MAAsB,QAAwB;AAC1E,UAAM,OAAO,KAAK,QAAQ;AAC1B,UAAM,UAAU,KAAK,WAAW;AAChC,QAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,GAAG;AACvC,YAAM,UAAU,sBAAsB,uBAAkB;AAAA,IAC1D;AACA,QAAI,CAAC,OAAO,UAAU,OAAO,KAAK,UAAU,KAAK,UAAU,KAAK;AAC9D,YAAM,UAAU,sBAAsB,mCAAmC;AAAA,IAC3E;AACA,UAAM,OAAO,IAAI,MAAM,QAAQ;AAK/B,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM,aAAa,WAAW,UAAU,MAAM,KAAK;AACnD,UAAM,SAAS,MAAM,KAAK,SAAS;AAAA,MACjC,gBAAgB;AAAA,MAChB;AAAA,MACA,UAAU;AAAA,MACV,SAAS;AAAA,MACT,YAAY,KAAK,aAAa;AAAA,MAC9B,SAAS,iBAAiB,KAAK,QAAQ,SAAS,WAAW,SAAS;AAAA,IACtE,CAAC;AACD,WAAO,EAAE,MAAM,OAAO,MAAe,MAAM,OAAO,KAAK;AAAA,EACzD;AACF;AAEO,SAAS,qBAAqB,UAAkB;AACrD,SAAO,OAAO,OAAgB,MAAwB,QAA6C;AACjG,UAAM,OAAO,IAAI,MAAM,QAAQ;AAC/B,UAAM,OAAQ,MAAM,KAAK,WAAW,KAAK,IAAI;AAC7C,WAAO,YAAY,IAAI,IAAI,OAAO;AAAA,EACpC;AACF;AAEO,SAAS,kBAAkB,UAAkB;AAClD,SAAO,OAAO,OAAgB,OAAgB,QAA6C;AACzF,UAAM,OAAO,IAAI,MAAM,QAAQ;AAC/B,UAAM,SAAS,MAAM,KAAK,SAAS,EAAE,gBAAgB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;AACjF,WAAQ,OAAO,KAAK,CAAC,KAAyB;AAAA,EAChD;AACF;AAEO,SAAS,uBAAuB,UAAkB;AACvD,SAAO,OAAO,OAAgB,MAAsB,QAA6C;AAC/F,UAAM,OAAO,IAAI,MAAM,QAAQ;AAC/B,UAAM,OAAQ,MAAM,KAAK,QAAQ,KAAK,EAAE;AACxC,WAAO,YAAY,IAAI,IAAI,OAAO;AAAA,EACpC;AACF;;;AL1HA,IAAM,YAAY,IAAI,kBAAkB;AAAA,EACtC,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,OAAO,EAAE,MAAM,IAAIC,gBAAeC,WAAU,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM;AAAA,IACvE,MAAM,EAAE,MAAM,IAAID,gBAAeC,WAAU,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK;AAAA,IACrE,SAAS,EAAE,MAAM,IAAID,gBAAeC,WAAU,GAAG,SAAS,CAAC,MAAM,EAAE,SAAS;AAAA,IAC5E,YAAY,EAAE,MAAM,IAAID,gBAAeC,WAAU,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY;AAAA,IAClF,SAAS,EAAE,MAAM,IAAID,gBAAeE,eAAc,GAAG,SAAS,CAAC,MAAM,EAAE,SAAS;AAAA,IAChF,SAAS,EAAE,MAAM,IAAIF,gBAAeE,eAAc,GAAG,SAAS,CAAC,MAAM,EAAE,SAAS;AAAA,EAClF;AACF,CAAC;AAED,IAAM,QAAQ,IAAI,kBAAkB;AAAA,EAClC,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,IAAI,EAAE,MAAM,IAAIF,gBAAe,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,GAAG;AAAA,IAChE,MAAM,EAAE,MAAM,IAAIA,gBAAeG,cAAa,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK;AAAA,IACxE,KAAK,EAAE,MAAM,IAAIH,gBAAeG,cAAa,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI;AAAA,IACtE,UAAU,EAAE,MAAM,IAAIH,gBAAeG,cAAa,GAAG,SAAS,CAAC,MAAM,EAAE,UAAU;AAAA,IACjF,KAAK,EAAE,MAAMA,gBAAe,SAAS,CAAC,MAAM,EAAE,IAAI;AAAA,IAClD,UAAU,EAAE,MAAMF,aAAY,SAAS,CAAC,MAAM,EAAE,UAAU;AAAA,IAC1D,OAAO,EAAE,MAAMA,aAAY,SAAS,CAAC,MAAM,EAAE,MAAM;AAAA,IACnD,QAAQ,EAAE,MAAMA,aAAY,SAAS,CAAC,MAAM,EAAE,OAAO;AAAA,IACrD,UAAU,EAAE,MAAMA,aAAY,SAAS,CAAC,MAAM,EAAE,SAAS;AAAA,EAC3D;AACF,CAAC;AAEM,SAAS,mBACd,UACA,eAA4C,CAAC,GAC7C,MAIA,sBAAmD,cACpC;AACf,QAAM,cAAc,oBAAI,IAA+B;AACvD,QAAM,YAAY,oBAAI,IAA6B;AAGnD,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,SAAS,UAAU,GAAiC;AAChG,QAAI,SAAS,OAAO,MAAM,kBAAkB,GAAG;AAC7C,gBAAU;AAAA,QACR;AAAA,QACA,IAAIG,iBAAgB;AAAA,UAClB,MAAM,gBAAgB,IAAI;AAAA,UAC1B,QAAQ,OAAO,YAAY,SAAS,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;AAAA,QAC1E,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL,cAAQ,OAAO;AAAA,QACb,gBAAW,IAAI;AAAA;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAGA,WAAS,mBAAmB,OAAoB,UAAsC;AACpF,UAAM,SAAS,iBAAiB,MAAM,UAAU;AAChD,QAAI,OAAQ,QAAO,WAAW,IAAIJ,gBAAe,MAAM,IAAI;AAE3D,QAAI,MAAM,eAAe,QAAQ;AAC/B,YAAM,MAAM,MAAM,aAAa,cAAc,WAAW,MAAM,aAAa,WAAW;AACtF,YAAM,KAAK,MAAM,UAAU,IAAI,GAAG,IAAI;AACtC,YAAM,IAAI,MAAMG;AAChB,aAAO,WAAW,IAAIH,gBAAe,CAAC,IAAI;AAAA,IAC5C;AAEA,QAAI,MAAM,eAAe,WAAW,MAAM,eAAe,WAAW,MAAM,eAAe,QAAQ;AAC/F,aAAO;AAAA,IACT;AAEA,QAAI,MAAM,eAAe,aAAa;AACpC,YAAM,MAAM,MAAM,aAAa,cAAc,oBAAoB,MAAM,aAAa,MAAM;AAC1F,YAAM,SAAS,MAAM,YAAY,IAAI,GAAG,IAAI;AAC5C,UAAI,OAAO,CAAC,QAAQ;AAClB,gBAAQ,OAAO;AAAA,UACb,2BAAsB,MAAM,IAAI,qCAAqC,GAAG;AAAA;AAAA,QAC1E;AAAA,MACF;AACA,YAAM,IAAK,UAAU;AACrB,aAAO,oBAAoB,KAAK,MAAM,QAAQ,IAAI,IAAIK,aAAY,IAAIL,gBAAe,CAAC,CAAC;AAAA,IACzF;AAEA,QAAI,MAAM,eAAe,aAAa;AACpC,YAAM,MAAM,MAAM,aAAa,cAAc,qBAAqB,MAAM,aAAa,MAAM;AAC3F,YAAM,SAAS,MAAM,YAAY,IAAI,GAAG,IAAI;AAC5C,UAAI,OAAO,CAAC,QAAQ;AAClB,gBAAQ,OAAO,MAAM,2BAAsB,MAAM,IAAI,2BAA2B,GAAG;AAAA,CAAwB;AAAA,MAC7G;AACA,YAAM,SAAS,oBAAoB,KAAK,MAAM;AAC9C,YAAM,IAAK,UAAU;AACrB,aAAO,SAAS,IAAIK,aAAY,IAAIL,gBAAe,CAAC,CAAC,IAAI;AAAA,IAC3D;AAEA,WAAOG;AAAA,EACT;AAaA,WAAS,cAAc,MAAgD;AACrE,WAAO,KAAK,OAAO,OAAO,CAAC,MAAM,EAAE,YAAY,IAAI;AAAA,EACrD;AAMA,WAAS,cAAc,aAAqB,MAA8C;AACxF,WACE,OAAO,WAAW,GAAG,UACrB,cAAc,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,EAAE,MAAM,UAAU,EAAE,SAAS,EAAE;AAAA,EAE1F;AAIA,WAAS,gBACP,aACA,MACmB;AACnB,UAAM,UAAU,cAAc,aAAa,IAAI;AAO/C,UAAM,kBAAkB,KAAK,OAC1B;AAAA,MACC,CAAC,MACC,EAAE,YAAY,SACb,EAAE,eAAe,WAAW,EAAE,eAAe,WAAW,EAAE,eAAe;AAAA,IAC9E,EACC,IAAI,CAAC,MAAM,EAAE,IAAI;AAEpB,WAAO,IAAI,kBAAkB;AAAA,MAC3B,MAAM,gBAAgB,WAAW;AAAA,MACjC,QAAQ,MAAM;AACZ,cAAM,SAAyE,CAAC;AAEhF,eAAO,IAAI,IAAI,EAAE,MAAM,IAAIH,gBAAe,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE;AAC9E,YAAI,KAAK,gBAAgB,kBAAkB;AACzC,iBAAO,WAAW,IAAI,EAAE,MAAM,IAAIA,gBAAeE,eAAc,GAAG,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE;AAAA,QACnG;AACA,YAAI,KAAK,gBAAgB,gBAAgB;AACvC,iBAAO,MAAM,IAAI,EAAE,MAAM,IAAIF,gBAAeG,cAAa,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE;AAAA,QACxF;AACA,eAAO,WAAW,IAAI,EAAE,MAAM,IAAIH,gBAAe,cAAc,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE;AAClG,eAAO,WAAW,IAAI,EAAE,MAAM,IAAIA,gBAAe,cAAc,GAAG,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE;AAElG,mBAAW,MAAM,SAAS;AACxB,gBAAM,QAAQ,GAAG;AACjB,gBAAM,UAAU,YAAY,GAAG,SAAS;AACxC,gBAAM,UAAU,mBAAmB,OAAO,GAAG,QAAQ;AACrD,cAAI;AACJ,cAAI,MAAM,eAAe,gBAAgB;AACvC,sBAAU,0BAA0B,aAAa,MAAM,MAAM,iBAAiB,oBAAoB,WAAW,CAAC;AAAA,UAChH,WACE,MAAM,eAAe,eACrB,MAAM,eAAe,eACrB,MAAM,eAAe,WACrB,MAAM,eAAe,WACrB,MAAM,eAAe,QACrB;AACA,sBAAU,sBAAsB,aAAa,MAAM,IAAI;AAAA,UACzD,OAAO;AACL,sBAAU,oBAAoB,OAAO,GAAG,QAAQ;AAAA,UAClD;AACA,iBAAO,OAAO,IAAI;AAAA,YAChB,MAAM;AAAA,YACN;AAAA;AAAA;AAAA,YAGA,GAAI,GAAG,sBAAsB,UAAa,EAAE,mBAAmB,GAAG,kBAAkB;AAAA,UACtF;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAMA,QAAM,iBAAiB,oBAAI,IAAoB;AAC/C,WAAS,iBAAiB,aAA2B;AACnD,UAAM,UAAU,gBAAgB,WAAW;AAC3C,UAAM,QAAQ,eAAe,IAAI,OAAO;AACxC,QAAI,UAAU,UAAa,UAAU,aAAa;AAChD,YAAM,IAAI;AAAA,QACR,iCAAiC,OAAO,0BAA0B,KAAK,UAAU,WAAW;AAAA,MAE9F;AAAA,IACF;AACA,mBAAe,IAAI,SAAS,WAAW;AAAA,EACzC;AAEA,aAAW,CAAC,MAAM,EAAE,KAAK,OAAO,QAAQ,SAAS,aAAa,GAAG;AAC/D,qBAAiB,IAAI;AACrB,gBAAY,IAAI,MAAM,gBAAgB,MAAM,EAAE,CAAC;AAAA,EACjD;AACA,aAAW,CAAC,MAAM,EAAE,KAAK,OAAO,QAAQ,SAAS,cAAc,GAAG;AAChE,qBAAiB,IAAI;AACrB,gBAAY,IAAI,MAAM,gBAAgB,MAAM,EAAE,CAAC;AAAA,EACjD;AACA,aAAW,CAAC,MAAM,EAAE,KAAK,OAAO,QAAQ,SAAS,eAAe,GAAG;AACjE,qBAAiB,IAAI;AACrB,gBAAY,IAAI,MAAM,gBAAgB,MAAM,EAAE,CAAC;AAAA,EACjD;AAGA,QAAM,cAA8D,CAAC;AAErE,aAAW,CAAC,MAAM,EAAE,KAAK,OAAO,QAAQ,SAAS,aAAa,GAAoC;AAChG,UAAM,UAAU,YAAY,IAAI,IAAI;AACpC,UAAM,UAAU,cAAc,MAAM,EAAE;AAOtC,UAAM,UAAU,kBAAkB;AAAA,MAChC,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,SAAS;AAAA,MACjC,GAAG,GAAG,cAAc,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,IACvC,CAAC;AAED,QAAI,GAAG,UAAU;AACf,kBAAY,gBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,SAAS,SAAS,kBAAkB,IAAI,EAAE;AACvF;AAAA,IACF;AAEA,UAAM,WAAW,IAAI,kBAAkB;AAAA,MACrC,MAAM,GAAG,gBAAgB,IAAI,CAAC;AAAA,MAC9B,QAAQ;AAAA,QACN,MAAM,EAAE,MAAM,IAAIA,gBAAe,IAAIK,aAAY,IAAIL,gBAAe,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK;AAAA,QACvG,MAAM,EAAE,MAAM,IAAIA,gBAAe,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK;AAAA,MACtE;AAAA,IACF,CAAC;AACD,UAAM,aAAa,qBAAqB,IAAI,OAAO;AAEnD,gBAAY,oBAAoB,IAAI,CAAC,IAAI;AAAA,MACvC,MAAM,IAAIA,gBAAe,QAAQ;AAAA,MACjC,MAAM;AAAA,QACJ,MAAM,EAAE,MAAMC,YAAW;AAAA,QACzB,SAAS,EAAE,MAAMA,YAAW;AAAA,QAC5B,QAAQ,EAAE,MAAM,mBAAmB,gBAAgB,IAAI,GAAG,aAAa,IAAI,CAAC,EAAE;AAAA,QAC9E,WAAW,EAAE,MAAM,cAAc;AAAA,QACjC,GAAI,aAAa,EAAE,QAAQ,EAAE,MAAM,WAAW,EAAE,IAAI,CAAC;AAAA,MACvD;AAAA,MACA,SAAS,mBAAmB,MAAM,SAAS,aAAa,IAAI,CAAC;AAAA,IAC/D;AACA,gBAAY,gBAAgB,IAAI,CAAC,IAAI;AAAA,MACnC,MAAM;AAAA,MACN,MAAM,EAAE,MAAM,EAAE,MAAM,IAAID,gBAAeG,cAAa,EAAE,EAAE;AAAA,MAC1D,SAAS,qBAAqB,IAAI;AAAA,IACpC;AAAA,EACF;AAEA,aAAW,CAAC,MAAM,EAAE,KAAK,OAAO,QAAQ,SAAS,cAAc,GAAqC;AAClG,UAAM,UAAU,YAAY,IAAI,IAAI;AACpC,UAAM,WAAW,IAAI,kBAAkB;AAAA,MACrC,MAAM,GAAG,gBAAgB,IAAI,CAAC;AAAA,MAC9B,QAAQ;AAAA,QACN,MAAM,EAAE,MAAM,IAAIH,gBAAe,IAAIK,aAAY,IAAIL,gBAAe,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK;AAAA,QACvG,MAAM,EAAE,MAAM,IAAIA,gBAAe,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK;AAAA,MACtE;AAAA,IACF,CAAC;AACD,gBAAY,oBAAoB,IAAI,CAAC,IAAI;AAAA,MACvC,MAAM,IAAIA,gBAAe,QAAQ;AAAA,MACjC,MAAM,EAAE,MAAM,EAAE,MAAMC,YAAW,GAAG,SAAS,EAAE,MAAMA,YAAW,EAAE;AAAA,MAClE,SAAS;AAAA,QACP;AAAA,QACA,kBAAkB,cAAc,MAAM,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,QACjE,aAAa,IAAI;AAAA,MACnB;AAAA,IACF;AACA,gBAAY,gBAAgB,IAAI,CAAC,IAAI;AAAA,MACnC,MAAM;AAAA,MACN,MAAM,EAAE,IAAI,EAAE,MAAM,IAAID,gBAAe,SAAS,EAAE,EAAE;AAAA,MACpD,SAAS,uBAAuB,IAAI;AAAA,IACtC;AAAA,EACF;AAEA,SAAO,IAAI,cAAc;AAAA,IACvB,OAAO,IAAI,kBAAkB,EAAE,MAAM,SAAS,QAAQ,YAAY,CAAC;AAAA,EACrE,CAAC;AACH;;;AMlTA,SAAS,SAAS,QAAiD;AACjE,QAAM,MAAM,oBAAI,IAAyB;AACzC,aAAW,KAAK,QAAQ;AACtB,QAAI,CAAC,eAAe,CAAC,EAAG;AACxB,QAAI,IAAI,EAAE,UAAU,aAAa,CAAC;AAAA,EACpC;AACA,SAAO;AACT;AAWA,SAAS,eACP,OACA,eACA,gBACoB;AACpB,QAAM,eAAe,cAAc,IAAI,MAAM,WAAW;AACxD,MAAI,iBAAiB,QAAW;AAC9B,WAAO,cAAc,cAAc;AAAA,EACrC;AACA,MAAI,iBAAiB,MAAM,YAAY;AACrC,WAAO,eAAe,YAAY,QAAQ,cAAc;AAAA,EAC1D;AACA,SAAO;AACT;AASO,SAAS,iBAAiB,OAKjB;AACd,QAAM,EAAE,UAAU,YAAY,mBAAmB,eAAe,IAAI;AACpE,QAAM,MAAmB,CAAC;AAE1B,QAAM,UAA4D;AAAA,IAChE,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AAEA,aAAW,UAAU,SAAS;AAC5B,eAAW,CAAC,UAAU,IAAI,KAAK,OAAO,QAAQ,MAAM,GAAG;AACrD,YAAM,iBAAiB,YAAY,MAAM,QAAQ;AAGjD,UAAI,mBAAmB,QAAW;AAChC,YAAI,QAAQ,IAAI;AAAA,UACd,QAAQ,KAAK,OACV,OAAO,CAAC,MAAM,EAAE,YAAY,IAAI,EAChC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,EAAE,MAAM,UAAU,EAAE,SAAS,EAAE;AAAA,QACvE;AACA;AAAA,MACF;AAEA,YAAM,UAAU,SAAS,KAAK,MAAM;AACpC,YAAM,gBAAgB,oBAAI,IAAoB;AAC9C,iBAAW,KAAK,mBAAmB,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG;AAChE,sBAAc,IAAI,EAAE,aAAa,EAAE,UAAU;AAAA,MAC/C;AAEA,YAAM,SAAsB,CAAC;AAE7B,iBAAW,MAAM,eAAe,QAAQ;AACtC,cAAM,QAAQ,QAAQ,IAAI,GAAG,WAAW;AAIxC,YAAI,UAAU,OAAW;AACzB,cAAM,SAAS,eAAe,IAAI,eAAe,cAAc;AAC/D,eAAO,KAAK;AAAA,UACV;AAAA,UACA,WAAW,GAAG;AAAA,UACd,UAAU,GAAG;AAAA,UACb,GAAI,GAAG,aAAa,UAAa,EAAE,UAAU,GAAG,SAAS;AAAA,UACzD,GAAI,WAAW,UAAa,EAAE,mBAAmB,OAAO;AAAA,QAC1D,CAAC;AAAA,MACH;AAOA,iBAAW,KAAK,KAAK,QAAQ;AAC3B,YAAI,eAAe,CAAC,KAAK,EAAE,YAAY,KAAM;AAC7C,eAAO,KAAK,EAAE,OAAO,GAAG,WAAW,EAAE,MAAM,UAAU,EAAE,SAAS,CAAC;AAAA,MACnE;AAEA,UAAI,QAAQ,IAAI,EAAE,OAAO;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO;AACT;;;ACnJA,OAAO,gBAAgB;AAmBhB,SAAS,sBACd,IACA,UACiB;AACjB,QAAM,UAAU,oBAAI,IAAyC;AAC7D,QAAM,UAAU,oBAAI,IAA4C;AAChE,QAAM,QAAQ,oBAAI,IAAqB;AAEvC,WAAS,aAAa,UAA+C;AACnE,QAAI,IAAI,QAAQ,IAAI,QAAQ;AAC5B,QAAI,CAAC,GAAG;AACN,YAAM,OAAQ,SAAS,cAAc,QAAQ,KAC3C,SAAS,eAAe,QAAQ,KAChC,SAAS,gBAAgB,QAAQ;AAKnC,UAAI,OAAO,kBAAkB,KAAK,QAAQ,QAAQ,IAAI,CAAC;AACvD,cAAQ,IAAI,UAAU,CAAC;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AAEA,WAAS,UAAU,UAAkB,WAAmB,KAAkD;AACxG,UAAM,MAAM,GAAG,QAAQ,IAAI,SAAS;AACpC,QAAI,KAAK,QAAQ,IAAI,GAAG;AACxB,QAAI,CAAC,IAAI;AACP,WAAK,IAAI;AAAA,QACP,OAAO,YAAY;AACjB,gBAAM,OAAO;AAGb,gBAAM,qBAAqB,IAAI,MAAM,WAAW,KAAK,OAAO,IAAI;AAKhE,gBAAM,YAAY,IAAI,SAAS,eAAe,IAAI,SAAS,UAAU,IAAI,YAAY;AACrF,iBAAO,KAAK,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,QACrC;AAAA;AAAA;AAAA,QAGA,EAAE,OAAO,MAAM;AAAA,MACjB;AACA,cAAQ,IAAI,KAAK,EAAE;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM,KAAK,UAAU,WAAW,QAAQ;AACtC,YAAM,MAAM,aAAa,QAAQ,EAAE,SAAS;AAC5C,UAAI,CAAC,IAAK,QAAO;AACjB,aAAO,UAAU,UAAU,WAAW,GAAG,EAAE,KAAK,MAAM;AAAA,IACxD;AAAA,EACF;AACF;;;AC5EA,SAAS,oBAAoB;AAC7B,SAAS,uCAAuC;AAQzC,SAAS,iBAAiB,SAE/B;AACA,QAAM,QAAQ,IAAI,aAAa;AAAA,IAC7B,UAAU,EAAE,GAAG,QAAQ,SAAS;AAAA,IAChC,WAAW,EAAE,SAAS,QAAQ,cAAc;AAAA,IAC5C,YAAY,EAAE,GAAG,GAAG;AAAA,IACpB,eAAe,EAAE,GAAG,GAAG;AAAA,IACvB,sBAAsB,EAAE,SAAS,KAAK;AAAA;AAAA;AAAA;AAAA,EAIxC,CAAC;AACD,SAAO,MAAM,QAAQ;AACvB;AAIO,SAAS,oBAAoB,SAElC;AACA,SAAO;AAAA,IACL,WAAW,EAAE,kBAAkB,GAAG;AAChC,UAAI,CAAC,QAAS,mBAAkB,+BAA+B;AAAA,IACjE;AAAA,EACF;AACF;;;ATFA,SAAS,yBAAyB,OAAyB;AACzD,MAAI,UAAU;AACd,SAAO,WAAW,QAAQ,OAAO,YAAY,YAAY,QAAQ,SAAS,gBAAgB;AACxF,QAAI,QAAQ,iBAAiB,KAAM,QAAO;AAC1C,cAAU,QAAQ;AAAA,EACpB;AACA,SAAO;AACT;AAEO,SAAS,qBACd,UACA,OACA,cACA,UACA,IACA,SAIA,aAQI,CAAC,GACI;AACT,MAAI;AACJ,MAAI,WAAW,eAAe,QAAW;AACvC,QAAI,WAAW,mBAAmB,QAAW;AAC3C,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AACA,WAAO,iBAAiB;AAAA,MACtB;AAAA,MACA,YAAY,WAAW;AAAA,MACvB,mBAAmB,WAAW;AAAA,MAC9B,gBAAgB,WAAW;AAAA,IAC7B,CAAC;AAAA,EACH;AACA,QAAM,SAAS,mBAAmB,UAAU,cAAc,MAAM,WAAW,uBAAuB,YAAY;AAC9G,QAAM,EAAE,QAAQ,IAAI,iBAAiB;AAAA,IACnC,UAAU,QAAQ;AAAA,IAClB,eAAe,QAAQ;AAAA,EACzB,CAAC;AAED,QAAM,OAAO,WAAkD;AAAA,IAC7D;AAAA,IACA,iBAAiB,WAAW,YAAY;AAAA,IACxC,UAAU,QAAQ;AAAA,IAClB,aAAa;AAAA,IACb,cAAc;AAAA,MACZ,WAAW,CAAC,OAAO,SAAS,UAC1B,yBAAyB,KAAK,IAAK,QAAkB,UAAU,OAAO,SAAS,KAAK;AAAA,IACxF;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,SAAS,CAAC,GAAI,SAAmB,oBAAoB,QAAQ,aAAa,CAAC;AAAA,IAC3E,SAAS,OAAuB;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,sBAAsB,IAAI,QAAQ;AAAA,MAC3C,kBAAkB,oBAAI,QAAQ;AAAA,IAChC;AAAA,EACF,CAAC;AAED,SAAO,CAAC,MAAM,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,CAAC;AACxC;","names":["GraphQLEnumType","GraphQLNonNull","GraphQLList","GraphQLString","GraphQLInt","GraphQLBoolean","GraphQLString","GraphQLBoolean","GraphQLInt","GraphQLFloat","GraphQLString","GraphQLBoolean","GraphQLInt","GraphQLFloat","GraphQLNonNull","GraphQLInt","GraphQLBoolean","GraphQLString","GraphQLEnumType","GraphQLList"]}
|
package/dist/codegen/index.js
CHANGED
|
@@ -27,6 +27,7 @@ __export(codegen_exports, {
|
|
|
27
27
|
module.exports = __toCommonJS(codegen_exports);
|
|
28
28
|
|
|
29
29
|
// src/codegen/routes.ts
|
|
30
|
+
var import_manguito_cms_core = require("@bobbykim/manguito-cms-core");
|
|
30
31
|
function getSegment(machineName) {
|
|
31
32
|
const idx = machineName.indexOf("--");
|
|
32
33
|
return idx !== -1 ? machineName.slice(idx + 2) : machineName;
|
|
@@ -117,12 +118,12 @@ function fieldToZodSchema(field, registry) {
|
|
|
117
118
|
const paragraphType = registry?.paragraph_types[ui.ref];
|
|
118
119
|
if (!paragraphType) return "z.unknown()";
|
|
119
120
|
const inner = generateParagraphObjectSchema(paragraphType, registry);
|
|
120
|
-
return
|
|
121
|
+
return (0, import_manguito_cms_core.relationCardinality)(field) === "many" ? `z.array(${inner})` : inner;
|
|
121
122
|
}
|
|
122
123
|
case "reference": {
|
|
123
124
|
const ui = field.ui_component;
|
|
124
125
|
if (ui.component !== "typeahead-select") return "z.string().uuid()";
|
|
125
|
-
return
|
|
126
|
+
return (0, import_manguito_cms_core.relationCardinality)(field) === "many" ? "z.array(z.string().uuid())" : "z.string().uuid()";
|
|
126
127
|
}
|
|
127
128
|
default:
|
|
128
129
|
return "z.unknown()";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/codegen/index.ts","../../src/codegen/routes.ts"],"sourcesContent":["export { generateRoutes, generateContentSchema, fieldToZodSchema } from './routes.js'\n","// generateRoutes() — pure function that returns a Hono route group from parsed schema\nimport type {\n SchemaRegistry,\n ParsedField,\n ParsedContentType,\n ParsedTaxonomyType,\n ParsedParagraphType,\n} from '@bobbykim/manguito-cms-core'\n\n// ─── Name helpers ─────────────────────────────────────────────────────────────\n\nfunction getSegment(machineName: string): string {\n const idx = machineName.indexOf('--')\n return idx !== -1 ? machineName.slice(idx + 2) : machineName\n}\n\nfunction toPascalCase(snakeOrKebab: string): string {\n return snakeOrKebab\n .split(/[_-]/)\n .filter(Boolean)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1))\n .join('')\n}\n\nfunction schemaVar(machineName: string): string {\n return toPascalCase(getSegment(machineName)) + 'Schema'\n}\n\nfunction routeVar(prefix: string, machineName: string, suffix: string): string {\n return `${prefix}${toPascalCase(getSegment(machineName))}${suffix}Route`\n}\n\n// Convert Hono :param notation to OpenAPI {param} notation\nfunction openApiPath(honoPath: string): string {\n return honoPath.replace(/:([^/]+)/g, '{$1}')\n}\n\n// ─── Field → Zod type string ──────────────────────────────────────────────────\n\nexport function fieldToZodSchema(field: ParsedField, registry?: SchemaRegistry): string {\n const { field_type, validation } = field\n\n switch (field_type) {\n case 'text/plain': {\n let s = 'z.string()'\n if (validation.limit !== undefined) s += `.max(${validation.limit})`\n if (validation.pattern !== undefined) s += `.regex(new RegExp(${JSON.stringify(validation.pattern)}))`\n return s\n }\n\n case 'text/rich':\n return 'z.string()'\n\n case 'integer': {\n let s = 'z.number().int()'\n if (validation.min !== undefined) s += `.min(${validation.min})`\n if (validation.max !== undefined) s += `.max(${validation.max})`\n return s\n }\n\n case 'float': {\n let s = 'z.number()'\n if (validation.min !== undefined) s += `.min(${validation.min})`\n if (validation.max !== undefined) s += `.max(${validation.max})`\n return s\n }\n\n case 'boolean':\n return 'z.boolean()'\n\n case 'date':\n return 'z.string().datetime()'\n\n case 'image': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n 'width: z.number().int().optional()',\n 'height: z.number().int().optional()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'video': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n 'width: z.number().int().optional()',\n 'height: z.number().int().optional()',\n 'duration: z.number().optional()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'file': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'enum': {\n const values = validation.allowed_values ?? []\n if (values.length === 0) return 'z.string()'\n const quoted = values.map((v) => JSON.stringify(v)).join(', ')\n return `z.enum([${quoted}])`\n }\n\n case 'paragraph': {\n const ui = field.ui_component\n if (ui.component !== 'paragraph-embed') return 'z.unknown()'\n const paragraphType = registry?.paragraph_types[ui.ref]\n if (!paragraphType) return 'z.unknown()'\n const inner = generateParagraphObjectSchema(paragraphType, registry)\n return ui.rel === 'one-to-many' ? `z.array(${inner})` : inner\n }\n\n case 'reference': {\n const ui = field.ui_component\n if (ui.component !== 'typeahead-select') return 'z.string().uuid()'\n return ui.rel === 'one-to-many' ? 'z.array(z.string().uuid())' : 'z.string().uuid()'\n }\n\n default:\n return 'z.unknown()'\n }\n}\n\n// Generates inline z.object({...}) for a paragraph type — used recursively inside fieldToZodSchema\nfunction generateParagraphObjectSchema(\n paragraph: ParsedParagraphType,\n registry?: SchemaRegistry\n): string {\n const entries = paragraph.fields.map((f) => {\n const zodType = fieldToZodSchema(f, registry)\n return `${f.name}: ${f.required ? zodType : `${zodType}.optional()`}`\n })\n if (entries.length === 0) return 'z.object({})'\n return `z.object({ ${entries.join(', ')} })`\n}\n\n// ─── Schema declaration generators ───────────────────────────────────────────\n\nfunction systemFieldEntries(schema: ParsedContentType | ParsedTaxonomyType): string[] {\n const entries: string[] = ['id: z.string().uuid()']\n if (schema.schema_type === 'content-type' && !schema.only_one) {\n entries.push('slug: z.string()')\n }\n entries.push('published: z.boolean()')\n entries.push('created_at: z.string().datetime()')\n entries.push('updated_at: z.string().datetime()')\n return entries\n}\n\nfunction schemaFieldEntries(\n fields: ParsedField[],\n registry?: SchemaRegistry\n): string[] {\n return fields.map((f) => {\n const zodType = fieldToZodSchema(f, registry)\n return ` ${f.name}: ${f.required ? zodType : `${zodType}.optional()`}`\n })\n}\n\nexport function generateContentSchema(\n schema: ParsedContentType | ParsedTaxonomyType,\n registry?: SchemaRegistry\n): string {\n const name = schemaVar(schema.name)\n const sysEntries = systemFieldEntries(schema).map((e) => ` ${e}`)\n const fieldEntries = schemaFieldEntries(schema.fields, registry)\n const allEntries = [...sysEntries, ...fieldEntries]\n return `const ${name} = z.object({\\n${allEntries.join(',\\n')},\\n})`\n}\n\n// Internal: paragraph schema const declaration (not exported but emitted into generated file)\nfunction generateParagraphSchemaDecl(\n paragraph: ParsedParagraphType,\n registry?: SchemaRegistry\n): string {\n const name = schemaVar(paragraph.name)\n const inner = generateParagraphObjectSchema(paragraph, registry)\n return `const ${name} = ${inner}`\n}\n\n// ─── Shared schemas block ─────────────────────────────────────────────────────\n\nconst SHARED_SCHEMAS_BLOCK = `const ErrorResponseSchema = z.object({\n ok: z.literal(false),\n error: z.object({\n code: z.string(),\n message: z.string(),\n details: z.unknown().optional(),\n }),\n})\n\nfunction listResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n ok: z.literal(true),\n data: z.array(dataSchema),\n meta: z.object({\n total: z.number().int(),\n page: z.number().int(),\n per_page: z.number().int(),\n total_pages: z.number().int(),\n has_next: z.boolean(),\n has_prev: z.boolean(),\n }),\n })\n}\n\nfunction itemResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n ok: z.literal(true),\n data: dataSchema,\n })\n}`\n\n// ─── Query param schema strings ───────────────────────────────────────────────\n\nconst PUBLIC_LIST_QUERY = `z.object({\n page: z.coerce.number().int().min(1).default(1),\n per_page: z.coerce.number().int().min(1).max(100).default(10),\n include: z.string().optional().describe('Comma-separated relation field names to expand'),\n sort_by: z.enum(['title', 'created_at', 'updated_at']).optional().default('created_at'),\n sort_order: z.enum(['asc', 'desc']).optional().default('asc'),\n })`\n\nconst ADMIN_LIST_QUERY = `z.object({\n page: z.coerce.number().int().min(1).default(1),\n per_page: z.coerce.number().int().min(1).max(100).default(10),\n include: z.string().optional().describe('Comma-separated relation field names to expand'),\n sort_by: z.enum(['title', 'created_at', 'updated_at']).optional().default('created_at'),\n sort_order: z.enum(['asc', 'desc']).optional().default('asc'),\n published: z.enum(['true', 'false']).optional().describe('Filter by published state'),\n })`\n\nconst SLUG_PARAMS = `z.object({ slug: z.string() })`\nconst ID_PARAMS = `z.object({ id: z.string().uuid() })`\nconst INCLUDE_QUERY = `z.object({ include: z.string().optional().describe('Comma-separated relation field names to expand') })`\n\n// ─── Content route generators ─────────────────────────────────────────────────\n\nfunction generateContentRoutes(contentType: ParsedContentType): string {\n const sVar = schemaVar(contentType.name)\n const label = contentType.label\n const tag = label\n const lines: string[] = []\n\n if (!contentType.only_one) {\n const collPath = contentType.api.collection_path!\n const itemPath = contentType.api.item_path\n\n // Public — GET list\n lines.push(\n `export const ${routeVar('get', contentType.name, 'List')} = createRoute({\n method: 'get',\n path: '${collPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${PUBLIC_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Public — GET single by slug\n lines.push(\n `export const ${routeVar('get', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${openApiPath(itemPath)}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${SLUG_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET list\n const adminCollPath = '/admin' + collPath\n const adminItemPath = adminCollPath + '/{id}'\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, 'List')} = createRoute({\n method: 'get',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${ADMIN_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Admin — GET single by id\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST\n lines.push(\n `export const ${routeVar('adminCreate', contentType.name, '')} = createRoute({\n method: 'post',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', contentType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — DELETE\n lines.push(\n `export const ${routeVar('adminDelete', contentType.name, '')} = createRoute({\n method: 'delete',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: z.object({ ok: z.literal(true) }) } },\n description: '${label} deleted',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n } else {\n // only_one: true — no list, no slug, fixed paths\n const itemPath = contentType.api.item_path\n const adminItemBase = '/admin' + itemPath\n const adminPatchPath = '/admin/api/' + contentType.default_base_path + '/{id}'\n\n // Public — GET singleton\n lines.push(\n `export const ${routeVar('get', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${itemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET singleton\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemBase}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST (create singleton)\n const adminPostPath = '/admin/api/' + contentType.default_base_path\n lines.push(\n `export const ${routeVar('adminCreate', contentType.name, '')} = createRoute({\n method: 'post',\n path: '${adminPostPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 409: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Singleton already exists',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', contentType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminPatchPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n }\n\n return lines.join('\\n\\n')\n}\n\n// ─── Taxonomy route generators ────────────────────────────────────────────────\n\nfunction generateTaxonomyRoutes(taxonomyType: ParsedTaxonomyType): string {\n const sVar = schemaVar(taxonomyType.name)\n const label = taxonomyType.label\n const tag = label\n const collPath = taxonomyType.api.collection_path\n const itemPath = taxonomyType.api.item_path\n const adminCollPath = '/admin' + collPath\n const adminItemPath = '/admin' + openApiPath(itemPath)\n const lines: string[] = []\n\n // Public — GET list\n lines.push(\n `export const ${routeVar('get', taxonomyType.name, 'List')} = createRoute({\n method: 'get',\n path: '${collPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${PUBLIC_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Public — GET single by id\n lines.push(\n `export const ${routeVar('get', taxonomyType.name, '')} = createRoute({\n method: 'get',\n path: '${openApiPath(itemPath)}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET list\n lines.push(\n `export const ${routeVar('adminGet', taxonomyType.name, 'List')} = createRoute({\n method: 'get',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${ADMIN_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Admin — GET single by id\n lines.push(\n `export const ${routeVar('adminGet', taxonomyType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST\n lines.push(\n `export const ${routeVar('adminCreate', taxonomyType.name, '')} = createRoute({\n method: 'post',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', taxonomyType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — DELETE\n lines.push(\n `export const ${routeVar('adminDelete', taxonomyType.name, '')} = createRoute({\n method: 'delete',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: z.object({ ok: z.literal(true) }) } },\n description: '${label} deleted',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n return lines.join('\\n\\n')\n}\n\n// ─── generateRoutes ───────────────────────────────────────────────────────────\n\nexport function generateRoutes(registry: SchemaRegistry): string {\n const parts: string[] = []\n\n parts.push('// Auto-generated by generateRoutes() — do not hand-edit')\n parts.push(\"import { createRoute, z } from '@hono/zod-openapi'\")\n parts.push('')\n parts.push('// ─── Shared schemas ──────────────────────────────────────────────────────────')\n parts.push('')\n parts.push(SHARED_SCHEMAS_BLOCK)\n parts.push('')\n\n const paragraphEntries = Object.entries(registry.paragraph_types)\n if (paragraphEntries.length > 0) {\n parts.push('// ─── Paragraph schemas ───────────────────────────────────────────────────────')\n parts.push('')\n for (const [, paragraphType] of paragraphEntries) {\n parts.push(generateParagraphSchemaDecl(paragraphType, registry))\n }\n parts.push('')\n }\n\n const contentEntries = Object.entries(registry.content_types)\n if (contentEntries.length > 0) {\n parts.push('// ─── Content type schemas ────────────────────────────────────────────────────')\n parts.push('')\n for (const [, contentType] of contentEntries) {\n parts.push(generateContentSchema(contentType, registry))\n parts.push('')\n }\n }\n\n const taxonomyEntries = Object.entries(registry.taxonomy_types)\n if (taxonomyEntries.length > 0) {\n parts.push('// ─── Taxonomy type schemas ───────────────────────────────────────────────────')\n parts.push('')\n for (const [, taxonomyType] of taxonomyEntries) {\n parts.push(generateContentSchema(taxonomyType, registry))\n parts.push('')\n }\n }\n\n if (contentEntries.length > 0) {\n parts.push('// ─── Content routes ─────────────────────────────────────────────────────────')\n parts.push('')\n for (const [, contentType] of contentEntries) {\n parts.push(generateContentRoutes(contentType))\n parts.push('')\n }\n }\n\n if (taxonomyEntries.length > 0) {\n parts.push('// ─── Taxonomy routes ────────────────────────────────────────────────────────')\n parts.push('')\n for (const [, taxonomyType] of taxonomyEntries) {\n parts.push(generateTaxonomyRoutes(taxonomyType))\n parts.push('')\n }\n }\n\n return parts.join('\\n')\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/codegen/index.ts","../../src/codegen/routes.ts"],"sourcesContent":["export { generateRoutes, generateContentSchema, fieldToZodSchema } from './routes.js'\n","// generateRoutes() — pure function that returns a Hono route group from parsed schema\nimport type {\n SchemaRegistry,\n ParsedField,\n ParsedContentType,\n ParsedTaxonomyType,\n ParsedParagraphType,\n} from '@bobbykim/manguito-cms-core'\nimport { relationCardinality } from '@bobbykim/manguito-cms-core'\n\n// ─── Name helpers ─────────────────────────────────────────────────────────────\n\nfunction getSegment(machineName: string): string {\n const idx = machineName.indexOf('--')\n return idx !== -1 ? machineName.slice(idx + 2) : machineName\n}\n\nfunction toPascalCase(snakeOrKebab: string): string {\n return snakeOrKebab\n .split(/[_-]/)\n .filter(Boolean)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1))\n .join('')\n}\n\nfunction schemaVar(machineName: string): string {\n return toPascalCase(getSegment(machineName)) + 'Schema'\n}\n\nfunction routeVar(prefix: string, machineName: string, suffix: string): string {\n return `${prefix}${toPascalCase(getSegment(machineName))}${suffix}Route`\n}\n\n// Convert Hono :param notation to OpenAPI {param} notation\nfunction openApiPath(honoPath: string): string {\n return honoPath.replace(/:([^/]+)/g, '{$1}')\n}\n\n// ─── Field → Zod type string ──────────────────────────────────────────────────\n\nexport function fieldToZodSchema(field: ParsedField, registry?: SchemaRegistry): string {\n const { field_type, validation } = field\n\n switch (field_type) {\n case 'text/plain': {\n let s = 'z.string()'\n if (validation.limit !== undefined) s += `.max(${validation.limit})`\n if (validation.pattern !== undefined) s += `.regex(new RegExp(${JSON.stringify(validation.pattern)}))`\n return s\n }\n\n case 'text/rich':\n return 'z.string()'\n\n case 'integer': {\n let s = 'z.number().int()'\n if (validation.min !== undefined) s += `.min(${validation.min})`\n if (validation.max !== undefined) s += `.max(${validation.max})`\n return s\n }\n\n case 'float': {\n let s = 'z.number()'\n if (validation.min !== undefined) s += `.min(${validation.min})`\n if (validation.max !== undefined) s += `.max(${validation.max})`\n return s\n }\n\n case 'boolean':\n return 'z.boolean()'\n\n case 'date':\n return 'z.string().datetime()'\n\n case 'image': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n 'width: z.number().int().optional()',\n 'height: z.number().int().optional()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'video': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n 'width: z.number().int().optional()',\n 'height: z.number().int().optional()',\n 'duration: z.number().optional()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'file': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'enum': {\n const values = validation.allowed_values ?? []\n if (values.length === 0) return 'z.string()'\n const quoted = values.map((v) => JSON.stringify(v)).join(', ')\n return `z.enum([${quoted}])`\n }\n\n case 'paragraph': {\n const ui = field.ui_component\n if (ui.component !== 'paragraph-embed') return 'z.unknown()'\n const paragraphType = registry?.paragraph_types[ui.ref]\n if (!paragraphType) return 'z.unknown()'\n const inner = generateParagraphObjectSchema(paragraphType, registry)\n return relationCardinality(field) === 'many' ? `z.array(${inner})` : inner\n }\n\n case 'reference': {\n const ui = field.ui_component\n if (ui.component !== 'typeahead-select') return 'z.string().uuid()'\n return relationCardinality(field) === 'many' ? 'z.array(z.string().uuid())' : 'z.string().uuid()'\n }\n\n default:\n return 'z.unknown()'\n }\n}\n\n// Generates inline z.object({...}) for a paragraph type — used recursively inside fieldToZodSchema\nfunction generateParagraphObjectSchema(\n paragraph: ParsedParagraphType,\n registry?: SchemaRegistry\n): string {\n const entries = paragraph.fields.map((f) => {\n const zodType = fieldToZodSchema(f, registry)\n return `${f.name}: ${f.required ? zodType : `${zodType}.optional()`}`\n })\n if (entries.length === 0) return 'z.object({})'\n return `z.object({ ${entries.join(', ')} })`\n}\n\n// ─── Schema declaration generators ───────────────────────────────────────────\n\nfunction systemFieldEntries(schema: ParsedContentType | ParsedTaxonomyType): string[] {\n const entries: string[] = ['id: z.string().uuid()']\n if (schema.schema_type === 'content-type' && !schema.only_one) {\n entries.push('slug: z.string()')\n }\n entries.push('published: z.boolean()')\n entries.push('created_at: z.string().datetime()')\n entries.push('updated_at: z.string().datetime()')\n return entries\n}\n\nfunction schemaFieldEntries(\n fields: ParsedField[],\n registry?: SchemaRegistry\n): string[] {\n return fields.map((f) => {\n const zodType = fieldToZodSchema(f, registry)\n return ` ${f.name}: ${f.required ? zodType : `${zodType}.optional()`}`\n })\n}\n\nexport function generateContentSchema(\n schema: ParsedContentType | ParsedTaxonomyType,\n registry?: SchemaRegistry\n): string {\n const name = schemaVar(schema.name)\n const sysEntries = systemFieldEntries(schema).map((e) => ` ${e}`)\n const fieldEntries = schemaFieldEntries(schema.fields, registry)\n const allEntries = [...sysEntries, ...fieldEntries]\n return `const ${name} = z.object({\\n${allEntries.join(',\\n')},\\n})`\n}\n\n// Internal: paragraph schema const declaration (not exported but emitted into generated file)\nfunction generateParagraphSchemaDecl(\n paragraph: ParsedParagraphType,\n registry?: SchemaRegistry\n): string {\n const name = schemaVar(paragraph.name)\n const inner = generateParagraphObjectSchema(paragraph, registry)\n return `const ${name} = ${inner}`\n}\n\n// ─── Shared schemas block ─────────────────────────────────────────────────────\n\nconst SHARED_SCHEMAS_BLOCK = `const ErrorResponseSchema = z.object({\n ok: z.literal(false),\n error: z.object({\n code: z.string(),\n message: z.string(),\n details: z.unknown().optional(),\n }),\n})\n\nfunction listResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n ok: z.literal(true),\n data: z.array(dataSchema),\n meta: z.object({\n total: z.number().int(),\n page: z.number().int(),\n per_page: z.number().int(),\n total_pages: z.number().int(),\n has_next: z.boolean(),\n has_prev: z.boolean(),\n }),\n })\n}\n\nfunction itemResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n ok: z.literal(true),\n data: dataSchema,\n })\n}`\n\n// ─── Query param schema strings ───────────────────────────────────────────────\n\nconst PUBLIC_LIST_QUERY = `z.object({\n page: z.coerce.number().int().min(1).default(1),\n per_page: z.coerce.number().int().min(1).max(100).default(10),\n include: z.string().optional().describe('Comma-separated relation field names to expand'),\n sort_by: z.enum(['title', 'created_at', 'updated_at']).optional().default('created_at'),\n sort_order: z.enum(['asc', 'desc']).optional().default('asc'),\n })`\n\nconst ADMIN_LIST_QUERY = `z.object({\n page: z.coerce.number().int().min(1).default(1),\n per_page: z.coerce.number().int().min(1).max(100).default(10),\n include: z.string().optional().describe('Comma-separated relation field names to expand'),\n sort_by: z.enum(['title', 'created_at', 'updated_at']).optional().default('created_at'),\n sort_order: z.enum(['asc', 'desc']).optional().default('asc'),\n published: z.enum(['true', 'false']).optional().describe('Filter by published state'),\n })`\n\nconst SLUG_PARAMS = `z.object({ slug: z.string() })`\nconst ID_PARAMS = `z.object({ id: z.string().uuid() })`\nconst INCLUDE_QUERY = `z.object({ include: z.string().optional().describe('Comma-separated relation field names to expand') })`\n\n// ─── Content route generators ─────────────────────────────────────────────────\n\nfunction generateContentRoutes(contentType: ParsedContentType): string {\n const sVar = schemaVar(contentType.name)\n const label = contentType.label\n const tag = label\n const lines: string[] = []\n\n if (!contentType.only_one) {\n const collPath = contentType.api.collection_path!\n const itemPath = contentType.api.item_path\n\n // Public — GET list\n lines.push(\n `export const ${routeVar('get', contentType.name, 'List')} = createRoute({\n method: 'get',\n path: '${collPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${PUBLIC_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Public — GET single by slug\n lines.push(\n `export const ${routeVar('get', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${openApiPath(itemPath)}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${SLUG_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET list\n const adminCollPath = '/admin' + collPath\n const adminItemPath = adminCollPath + '/{id}'\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, 'List')} = createRoute({\n method: 'get',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${ADMIN_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Admin — GET single by id\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST\n lines.push(\n `export const ${routeVar('adminCreate', contentType.name, '')} = createRoute({\n method: 'post',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', contentType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — DELETE\n lines.push(\n `export const ${routeVar('adminDelete', contentType.name, '')} = createRoute({\n method: 'delete',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: z.object({ ok: z.literal(true) }) } },\n description: '${label} deleted',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n } else {\n // only_one: true — no list, no slug, fixed paths\n const itemPath = contentType.api.item_path\n const adminItemBase = '/admin' + itemPath\n const adminPatchPath = '/admin/api/' + contentType.default_base_path + '/{id}'\n\n // Public — GET singleton\n lines.push(\n `export const ${routeVar('get', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${itemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET singleton\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemBase}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST (create singleton)\n const adminPostPath = '/admin/api/' + contentType.default_base_path\n lines.push(\n `export const ${routeVar('adminCreate', contentType.name, '')} = createRoute({\n method: 'post',\n path: '${adminPostPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 409: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Singleton already exists',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', contentType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminPatchPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n }\n\n return lines.join('\\n\\n')\n}\n\n// ─── Taxonomy route generators ────────────────────────────────────────────────\n\nfunction generateTaxonomyRoutes(taxonomyType: ParsedTaxonomyType): string {\n const sVar = schemaVar(taxonomyType.name)\n const label = taxonomyType.label\n const tag = label\n const collPath = taxonomyType.api.collection_path\n const itemPath = taxonomyType.api.item_path\n const adminCollPath = '/admin' + collPath\n const adminItemPath = '/admin' + openApiPath(itemPath)\n const lines: string[] = []\n\n // Public — GET list\n lines.push(\n `export const ${routeVar('get', taxonomyType.name, 'List')} = createRoute({\n method: 'get',\n path: '${collPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${PUBLIC_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Public — GET single by id\n lines.push(\n `export const ${routeVar('get', taxonomyType.name, '')} = createRoute({\n method: 'get',\n path: '${openApiPath(itemPath)}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET list\n lines.push(\n `export const ${routeVar('adminGet', taxonomyType.name, 'List')} = createRoute({\n method: 'get',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${ADMIN_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Admin — GET single by id\n lines.push(\n `export const ${routeVar('adminGet', taxonomyType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST\n lines.push(\n `export const ${routeVar('adminCreate', taxonomyType.name, '')} = createRoute({\n method: 'post',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', taxonomyType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — DELETE\n lines.push(\n `export const ${routeVar('adminDelete', taxonomyType.name, '')} = createRoute({\n method: 'delete',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: z.object({ ok: z.literal(true) }) } },\n description: '${label} deleted',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n return lines.join('\\n\\n')\n}\n\n// ─── generateRoutes ───────────────────────────────────────────────────────────\n\nexport function generateRoutes(registry: SchemaRegistry): string {\n const parts: string[] = []\n\n parts.push('// Auto-generated by generateRoutes() — do not hand-edit')\n parts.push(\"import { createRoute, z } from '@hono/zod-openapi'\")\n parts.push('')\n parts.push('// ─── Shared schemas ──────────────────────────────────────────────────────────')\n parts.push('')\n parts.push(SHARED_SCHEMAS_BLOCK)\n parts.push('')\n\n const paragraphEntries = Object.entries(registry.paragraph_types)\n if (paragraphEntries.length > 0) {\n parts.push('// ─── Paragraph schemas ───────────────────────────────────────────────────────')\n parts.push('')\n for (const [, paragraphType] of paragraphEntries) {\n parts.push(generateParagraphSchemaDecl(paragraphType, registry))\n }\n parts.push('')\n }\n\n const contentEntries = Object.entries(registry.content_types)\n if (contentEntries.length > 0) {\n parts.push('// ─── Content type schemas ────────────────────────────────────────────────────')\n parts.push('')\n for (const [, contentType] of contentEntries) {\n parts.push(generateContentSchema(contentType, registry))\n parts.push('')\n }\n }\n\n const taxonomyEntries = Object.entries(registry.taxonomy_types)\n if (taxonomyEntries.length > 0) {\n parts.push('// ─── Taxonomy type schemas ───────────────────────────────────────────────────')\n parts.push('')\n for (const [, taxonomyType] of taxonomyEntries) {\n parts.push(generateContentSchema(taxonomyType, registry))\n parts.push('')\n }\n }\n\n if (contentEntries.length > 0) {\n parts.push('// ─── Content routes ─────────────────────────────────────────────────────────')\n parts.push('')\n for (const [, contentType] of contentEntries) {\n parts.push(generateContentRoutes(contentType))\n parts.push('')\n }\n }\n\n if (taxonomyEntries.length > 0) {\n parts.push('// ─── Taxonomy routes ────────────────────────────────────────────────────────')\n parts.push('')\n for (const [, taxonomyType] of taxonomyEntries) {\n parts.push(generateTaxonomyRoutes(taxonomyType))\n parts.push('')\n }\n }\n\n return parts.join('\\n')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQA,+BAAoC;AAIpC,SAAS,WAAW,aAA6B;AAC/C,QAAM,MAAM,YAAY,QAAQ,IAAI;AACpC,SAAO,QAAQ,KAAK,YAAY,MAAM,MAAM,CAAC,IAAI;AACnD;AAEA,SAAS,aAAa,cAA8B;AAClD,SAAO,aACJ,MAAM,MAAM,EACZ,OAAO,OAAO,EACd,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,CAAC,EACjD,KAAK,EAAE;AACZ;AAEA,SAAS,UAAU,aAA6B;AAC9C,SAAO,aAAa,WAAW,WAAW,CAAC,IAAI;AACjD;AAEA,SAAS,SAAS,QAAgB,aAAqB,QAAwB;AAC7E,SAAO,GAAG,MAAM,GAAG,aAAa,WAAW,WAAW,CAAC,CAAC,GAAG,MAAM;AACnE;AAGA,SAAS,YAAY,UAA0B;AAC7C,SAAO,SAAS,QAAQ,aAAa,MAAM;AAC7C;AAIO,SAAS,iBAAiB,OAAoB,UAAmC;AACtF,QAAM,EAAE,YAAY,WAAW,IAAI;AAEnC,UAAQ,YAAY;AAAA,IAClB,KAAK,cAAc;AACjB,UAAI,IAAI;AACR,UAAI,WAAW,UAAU,OAAW,MAAK,QAAQ,WAAW,KAAK;AACjE,UAAI,WAAW,YAAY,OAAW,MAAK,qBAAqB,KAAK,UAAU,WAAW,OAAO,CAAC;AAClG,aAAO;AAAA,IACT;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,IAET,KAAK,WAAW;AACd,UAAI,IAAI;AACR,UAAI,WAAW,QAAQ,OAAW,MAAK,QAAQ,WAAW,GAAG;AAC7D,UAAI,WAAW,QAAQ,OAAW,MAAK,QAAQ,WAAW,GAAG;AAC7D,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,SAAS;AACZ,UAAI,IAAI;AACR,UAAI,WAAW,QAAQ,OAAW,MAAK,QAAQ,WAAW,GAAG;AAC7D,UAAI,WAAW,QAAQ,OAAW,MAAK,QAAQ,WAAW,GAAG;AAC7D,aAAO;AAAA,IACT;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK,SAAS;AACZ,YAAM,SAAS;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,cAAc,OAAO,KAAK,IAAI,CAAC;AAAA,IACxC;AAAA,IAEA,KAAK,SAAS;AACZ,YAAM,SAAS;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,cAAc,OAAO,KAAK,IAAI,CAAC;AAAA,IACxC;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,SAAS;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,cAAc,OAAO,KAAK,IAAI,CAAC;AAAA,IACxC;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,SAAS,WAAW,kBAAkB,CAAC;AAC7C,UAAI,OAAO,WAAW,EAAG,QAAO;AAChC,YAAM,SAAS,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI;AAC7D,aAAO,WAAW,MAAM;AAAA,IAC1B;AAAA,IAEA,KAAK,aAAa;AAChB,YAAM,KAAK,MAAM;AACjB,UAAI,GAAG,cAAc,kBAAmB,QAAO;AAC/C,YAAM,gBAAgB,UAAU,gBAAgB,GAAG,GAAG;AACtD,UAAI,CAAC,cAAe,QAAO;AAC3B,YAAM,QAAQ,8BAA8B,eAAe,QAAQ;AACnE,iBAAO,8CAAoB,KAAK,MAAM,SAAS,WAAW,KAAK,MAAM;AAAA,IACvE;AAAA,IAEA,KAAK,aAAa;AAChB,YAAM,KAAK,MAAM;AACjB,UAAI,GAAG,cAAc,mBAAoB,QAAO;AAChD,iBAAO,8CAAoB,KAAK,MAAM,SAAS,+BAA+B;AAAA,IAChF;AAAA,IAEA;AACE,aAAO;AAAA,EACX;AACF;AAGA,SAAS,8BACP,WACA,UACQ;AACR,QAAM,UAAU,UAAU,OAAO,IAAI,CAAC,MAAM;AAC1C,UAAM,UAAU,iBAAiB,GAAG,QAAQ;AAC5C,WAAO,GAAG,EAAE,IAAI,KAAK,EAAE,WAAW,UAAU,GAAG,OAAO,aAAa;AAAA,EACrE,CAAC;AACD,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SAAO,cAAc,QAAQ,KAAK,IAAI,CAAC;AACzC;AAIA,SAAS,mBAAmB,QAA0D;AACpF,QAAM,UAAoB,CAAC,uBAAuB;AAClD,MAAI,OAAO,gBAAgB,kBAAkB,CAAC,OAAO,UAAU;AAC7D,YAAQ,KAAK,kBAAkB;AAAA,EACjC;AACA,UAAQ,KAAK,wBAAwB;AACrC,UAAQ,KAAK,mCAAmC;AAChD,UAAQ,KAAK,mCAAmC;AAChD,SAAO;AACT;AAEA,SAAS,mBACP,QACA,UACU;AACV,SAAO,OAAO,IAAI,CAAC,MAAM;AACvB,UAAM,UAAU,iBAAiB,GAAG,QAAQ;AAC5C,WAAO,KAAK,EAAE,IAAI,KAAK,EAAE,WAAW,UAAU,GAAG,OAAO,aAAa;AAAA,EACvE,CAAC;AACH;AAEO,SAAS,sBACd,QACA,UACQ;AACR,QAAM,OAAO,UAAU,OAAO,IAAI;AAClC,QAAM,aAAa,mBAAmB,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;AACjE,QAAM,eAAe,mBAAmB,OAAO,QAAQ,QAAQ;AAC/D,QAAM,aAAa,CAAC,GAAG,YAAY,GAAG,YAAY;AAClD,SAAO,SAAS,IAAI;AAAA,EAAkB,WAAW,KAAK,KAAK,CAAC;AAAA;AAC9D;AAGA,SAAS,4BACP,WACA,UACQ;AACR,QAAM,OAAO,UAAU,UAAU,IAAI;AACrC,QAAM,QAAQ,8BAA8B,WAAW,QAAQ;AAC/D,SAAO,SAAS,IAAI,MAAM,KAAK;AACjC;AAIA,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiC7B,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ1B,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASzB,IAAM,cAAc;AACpB,IAAM,YAAY;AAClB,IAAM,gBAAgB;AAItB,SAAS,sBAAsB,aAAwC;AACrE,QAAM,OAAO,UAAU,YAAY,IAAI;AACvC,QAAM,QAAQ,YAAY;AAC1B,QAAM,MAAM;AACZ,QAAM,QAAkB,CAAC;AAEzB,MAAI,CAAC,YAAY,UAAU;AACzB,UAAM,WAAW,YAAY,IAAI;AACjC,UAAM,WAAW,YAAY,IAAI;AAGjC,UAAM;AAAA,MACJ,gBAAgB,SAAS,OAAO,YAAY,MAAM,MAAM,CAAC;AAAA;AAAA,WAEpD,QAAQ;AAAA,WACR,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,iBAAiB;AAAA;AAAA;AAAA;AAAA,oEAIsC,IAAI;AAAA,8BAC1C,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQ/B;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,OAAO,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAEhD,YAAY,QAAQ,CAAC;AAAA,WACrB,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,WAAW;AAAA,aACZ,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,IAIvB;AAGA,UAAM,gBAAgB,WAAW;AACjC,UAAM,gBAAgB,gBAAgB;AACtC,UAAM;AAAA,MACJ,gBAAgB,SAAS,YAAY,YAAY,MAAM,MAAM,CAAC;AAAA;AAAA,WAEzD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,gBAAgB;AAAA;AAAA;AAAA;AAAA,oEAIuC,IAAI;AAAA,8BAC1C,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQ/B;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,YAAY,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAErD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA,aACV,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,IAIvB;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,eAAe,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAExD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA;AAAA,iDAGmB,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQvB;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,eAAe,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAExD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA;AAAA,iDAE0B,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQvB;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,eAAe,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAExD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,sBAKD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,IAIvB;AAAA,EACF,OAAO;AAEL,UAAM,WAAW,YAAY,IAAI;AACjC,UAAM,gBAAgB,WAAW;AACjC,UAAM,iBAAiB,gBAAgB,YAAY,oBAAoB;AAGvE,UAAM;AAAA,MACJ,gBAAgB,SAAS,OAAO,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAEhD,QAAQ;AAAA,WACR,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,IAIvB;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,YAAY,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAErD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,IAIvB;AAGA,UAAM,gBAAgB,gBAAgB,YAAY;AAClD,UAAM;AAAA,MACJ,gBAAgB,SAAS,eAAe,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAExD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA;AAAA,iDAGmB,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYvB;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,eAAe,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAExD,cAAc;AAAA,WACd,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA;AAAA,iDAE0B,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQvB;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,MAAM;AAC1B;AAIA,SAAS,uBAAuB,cAA0C;AACxE,QAAM,OAAO,UAAU,aAAa,IAAI;AACxC,QAAM,QAAQ,aAAa;AAC3B,QAAM,MAAM;AACZ,QAAM,WAAW,aAAa,IAAI;AAClC,QAAM,WAAW,aAAa,IAAI;AAClC,QAAM,gBAAgB,WAAW;AACjC,QAAM,gBAAgB,WAAW,YAAY,QAAQ;AACrD,QAAM,QAAkB,CAAC;AAGzB,QAAM;AAAA,IACJ,gBAAgB,SAAS,OAAO,aAAa,MAAM,MAAM,CAAC;AAAA;AAAA,WAEnD,QAAQ;AAAA,WACR,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,iBAAiB;AAAA;AAAA;AAAA;AAAA,oEAIsC,IAAI;AAAA,8BAC1C,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQjC;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,OAAO,aAAa,MAAM,EAAE,CAAC;AAAA;AAAA,WAE/C,YAAY,QAAQ,CAAC;AAAA,WACrB,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA,aACV,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,EAIzB;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,YAAY,aAAa,MAAM,MAAM,CAAC;AAAA;AAAA,WAExD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,gBAAgB;AAAA;AAAA;AAAA;AAAA,oEAIuC,IAAI;AAAA,8BAC1C,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQjC;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,YAAY,aAAa,MAAM,EAAE,CAAC;AAAA;AAAA,WAEpD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA,aACV,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,EAIzB;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,eAAe,aAAa,MAAM,EAAE,CAAC;AAAA;AAAA,WAEvD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA;AAAA,iDAGmB,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQzB;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,eAAe,aAAa,MAAM,EAAE,CAAC;AAAA;AAAA,WAEvD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA;AAAA,iDAE0B,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQzB;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,eAAe,aAAa,MAAM,EAAE,CAAC;AAAA;AAAA,WAEvD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,sBAKD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,EAIzB;AAEA,SAAO,MAAM,KAAK,MAAM;AAC1B;AAIO,SAAS,eAAe,UAAkC;AAC/D,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,+DAA0D;AACrE,QAAM,KAAK,oDAAoD;AAC/D,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,mYAAkF;AAC7F,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,oBAAoB;AAC/B,QAAM,KAAK,EAAE;AAEb,QAAM,mBAAmB,OAAO,QAAQ,SAAS,eAAe;AAChE,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,KAAK,oXAAkF;AAC7F,UAAM,KAAK,EAAE;AACb,eAAW,CAAC,EAAE,aAAa,KAAK,kBAAkB;AAChD,YAAM,KAAK,4BAA4B,eAAe,QAAQ,CAAC;AAAA,IACjE;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,iBAAiB,OAAO,QAAQ,SAAS,aAAa;AAC5D,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,KAAK,qWAAkF;AAC7F,UAAM,KAAK,EAAE;AACb,eAAW,CAAC,EAAE,WAAW,KAAK,gBAAgB;AAC5C,YAAM,KAAK,sBAAsB,aAAa,QAAQ,CAAC;AACvD,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,QAAM,kBAAkB,OAAO,QAAQ,SAAS,cAAc;AAC9D,MAAI,gBAAgB,SAAS,GAAG;AAC9B,UAAM,KAAK,gWAAkF;AAC7F,UAAM,KAAK,EAAE;AACb,eAAW,CAAC,EAAE,YAAY,KAAK,iBAAiB;AAC9C,YAAM,KAAK,sBAAsB,cAAc,QAAQ,CAAC;AACxD,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,KAAK,6XAAiF;AAC5F,UAAM,KAAK,EAAE;AACb,eAAW,CAAC,EAAE,WAAW,KAAK,gBAAgB;AAC5C,YAAM,KAAK,sBAAsB,WAAW,CAAC;AAC7C,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,MAAI,gBAAgB,SAAS,GAAG;AAC9B,UAAM,KAAK,wXAAiF;AAC5F,UAAM,KAAK,EAAE;AACb,eAAW,CAAC,EAAE,YAAY,KAAK,iBAAiB;AAC9C,YAAM,KAAK,uBAAuB,YAAY,CAAC;AAC/C,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;","names":[]}
|
package/dist/codegen/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/codegen/routes.ts
|
|
2
|
+
import { relationCardinality } from "@bobbykim/manguito-cms-core";
|
|
2
3
|
function getSegment(machineName) {
|
|
3
4
|
const idx = machineName.indexOf("--");
|
|
4
5
|
return idx !== -1 ? machineName.slice(idx + 2) : machineName;
|
|
@@ -89,12 +90,12 @@ function fieldToZodSchema(field, registry) {
|
|
|
89
90
|
const paragraphType = registry?.paragraph_types[ui.ref];
|
|
90
91
|
if (!paragraphType) return "z.unknown()";
|
|
91
92
|
const inner = generateParagraphObjectSchema(paragraphType, registry);
|
|
92
|
-
return
|
|
93
|
+
return relationCardinality(field) === "many" ? `z.array(${inner})` : inner;
|
|
93
94
|
}
|
|
94
95
|
case "reference": {
|
|
95
96
|
const ui = field.ui_component;
|
|
96
97
|
if (ui.component !== "typeahead-select") return "z.string().uuid()";
|
|
97
|
-
return
|
|
98
|
+
return relationCardinality(field) === "many" ? "z.array(z.string().uuid())" : "z.string().uuid()";
|
|
98
99
|
}
|
|
99
100
|
default:
|
|
100
101
|
return "z.unknown()";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/codegen/routes.ts"],"sourcesContent":["// generateRoutes() — pure function that returns a Hono route group from parsed schema\nimport type {\n SchemaRegistry,\n ParsedField,\n ParsedContentType,\n ParsedTaxonomyType,\n ParsedParagraphType,\n} from '@bobbykim/manguito-cms-core'\n\n// ─── Name helpers ─────────────────────────────────────────────────────────────\n\nfunction getSegment(machineName: string): string {\n const idx = machineName.indexOf('--')\n return idx !== -1 ? machineName.slice(idx + 2) : machineName\n}\n\nfunction toPascalCase(snakeOrKebab: string): string {\n return snakeOrKebab\n .split(/[_-]/)\n .filter(Boolean)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1))\n .join('')\n}\n\nfunction schemaVar(machineName: string): string {\n return toPascalCase(getSegment(machineName)) + 'Schema'\n}\n\nfunction routeVar(prefix: string, machineName: string, suffix: string): string {\n return `${prefix}${toPascalCase(getSegment(machineName))}${suffix}Route`\n}\n\n// Convert Hono :param notation to OpenAPI {param} notation\nfunction openApiPath(honoPath: string): string {\n return honoPath.replace(/:([^/]+)/g, '{$1}')\n}\n\n// ─── Field → Zod type string ──────────────────────────────────────────────────\n\nexport function fieldToZodSchema(field: ParsedField, registry?: SchemaRegistry): string {\n const { field_type, validation } = field\n\n switch (field_type) {\n case 'text/plain': {\n let s = 'z.string()'\n if (validation.limit !== undefined) s += `.max(${validation.limit})`\n if (validation.pattern !== undefined) s += `.regex(new RegExp(${JSON.stringify(validation.pattern)}))`\n return s\n }\n\n case 'text/rich':\n return 'z.string()'\n\n case 'integer': {\n let s = 'z.number().int()'\n if (validation.min !== undefined) s += `.min(${validation.min})`\n if (validation.max !== undefined) s += `.max(${validation.max})`\n return s\n }\n\n case 'float': {\n let s = 'z.number()'\n if (validation.min !== undefined) s += `.min(${validation.min})`\n if (validation.max !== undefined) s += `.max(${validation.max})`\n return s\n }\n\n case 'boolean':\n return 'z.boolean()'\n\n case 'date':\n return 'z.string().datetime()'\n\n case 'image': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n 'width: z.number().int().optional()',\n 'height: z.number().int().optional()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'video': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n 'width: z.number().int().optional()',\n 'height: z.number().int().optional()',\n 'duration: z.number().optional()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'file': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'enum': {\n const values = validation.allowed_values ?? []\n if (values.length === 0) return 'z.string()'\n const quoted = values.map((v) => JSON.stringify(v)).join(', ')\n return `z.enum([${quoted}])`\n }\n\n case 'paragraph': {\n const ui = field.ui_component\n if (ui.component !== 'paragraph-embed') return 'z.unknown()'\n const paragraphType = registry?.paragraph_types[ui.ref]\n if (!paragraphType) return 'z.unknown()'\n const inner = generateParagraphObjectSchema(paragraphType, registry)\n return ui.rel === 'one-to-many' ? `z.array(${inner})` : inner\n }\n\n case 'reference': {\n const ui = field.ui_component\n if (ui.component !== 'typeahead-select') return 'z.string().uuid()'\n return ui.rel === 'one-to-many' ? 'z.array(z.string().uuid())' : 'z.string().uuid()'\n }\n\n default:\n return 'z.unknown()'\n }\n}\n\n// Generates inline z.object({...}) for a paragraph type — used recursively inside fieldToZodSchema\nfunction generateParagraphObjectSchema(\n paragraph: ParsedParagraphType,\n registry?: SchemaRegistry\n): string {\n const entries = paragraph.fields.map((f) => {\n const zodType = fieldToZodSchema(f, registry)\n return `${f.name}: ${f.required ? zodType : `${zodType}.optional()`}`\n })\n if (entries.length === 0) return 'z.object({})'\n return `z.object({ ${entries.join(', ')} })`\n}\n\n// ─── Schema declaration generators ───────────────────────────────────────────\n\nfunction systemFieldEntries(schema: ParsedContentType | ParsedTaxonomyType): string[] {\n const entries: string[] = ['id: z.string().uuid()']\n if (schema.schema_type === 'content-type' && !schema.only_one) {\n entries.push('slug: z.string()')\n }\n entries.push('published: z.boolean()')\n entries.push('created_at: z.string().datetime()')\n entries.push('updated_at: z.string().datetime()')\n return entries\n}\n\nfunction schemaFieldEntries(\n fields: ParsedField[],\n registry?: SchemaRegistry\n): string[] {\n return fields.map((f) => {\n const zodType = fieldToZodSchema(f, registry)\n return ` ${f.name}: ${f.required ? zodType : `${zodType}.optional()`}`\n })\n}\n\nexport function generateContentSchema(\n schema: ParsedContentType | ParsedTaxonomyType,\n registry?: SchemaRegistry\n): string {\n const name = schemaVar(schema.name)\n const sysEntries = systemFieldEntries(schema).map((e) => ` ${e}`)\n const fieldEntries = schemaFieldEntries(schema.fields, registry)\n const allEntries = [...sysEntries, ...fieldEntries]\n return `const ${name} = z.object({\\n${allEntries.join(',\\n')},\\n})`\n}\n\n// Internal: paragraph schema const declaration (not exported but emitted into generated file)\nfunction generateParagraphSchemaDecl(\n paragraph: ParsedParagraphType,\n registry?: SchemaRegistry\n): string {\n const name = schemaVar(paragraph.name)\n const inner = generateParagraphObjectSchema(paragraph, registry)\n return `const ${name} = ${inner}`\n}\n\n// ─── Shared schemas block ─────────────────────────────────────────────────────\n\nconst SHARED_SCHEMAS_BLOCK = `const ErrorResponseSchema = z.object({\n ok: z.literal(false),\n error: z.object({\n code: z.string(),\n message: z.string(),\n details: z.unknown().optional(),\n }),\n})\n\nfunction listResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n ok: z.literal(true),\n data: z.array(dataSchema),\n meta: z.object({\n total: z.number().int(),\n page: z.number().int(),\n per_page: z.number().int(),\n total_pages: z.number().int(),\n has_next: z.boolean(),\n has_prev: z.boolean(),\n }),\n })\n}\n\nfunction itemResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n ok: z.literal(true),\n data: dataSchema,\n })\n}`\n\n// ─── Query param schema strings ───────────────────────────────────────────────\n\nconst PUBLIC_LIST_QUERY = `z.object({\n page: z.coerce.number().int().min(1).default(1),\n per_page: z.coerce.number().int().min(1).max(100).default(10),\n include: z.string().optional().describe('Comma-separated relation field names to expand'),\n sort_by: z.enum(['title', 'created_at', 'updated_at']).optional().default('created_at'),\n sort_order: z.enum(['asc', 'desc']).optional().default('asc'),\n })`\n\nconst ADMIN_LIST_QUERY = `z.object({\n page: z.coerce.number().int().min(1).default(1),\n per_page: z.coerce.number().int().min(1).max(100).default(10),\n include: z.string().optional().describe('Comma-separated relation field names to expand'),\n sort_by: z.enum(['title', 'created_at', 'updated_at']).optional().default('created_at'),\n sort_order: z.enum(['asc', 'desc']).optional().default('asc'),\n published: z.enum(['true', 'false']).optional().describe('Filter by published state'),\n })`\n\nconst SLUG_PARAMS = `z.object({ slug: z.string() })`\nconst ID_PARAMS = `z.object({ id: z.string().uuid() })`\nconst INCLUDE_QUERY = `z.object({ include: z.string().optional().describe('Comma-separated relation field names to expand') })`\n\n// ─── Content route generators ─────────────────────────────────────────────────\n\nfunction generateContentRoutes(contentType: ParsedContentType): string {\n const sVar = schemaVar(contentType.name)\n const label = contentType.label\n const tag = label\n const lines: string[] = []\n\n if (!contentType.only_one) {\n const collPath = contentType.api.collection_path!\n const itemPath = contentType.api.item_path\n\n // Public — GET list\n lines.push(\n `export const ${routeVar('get', contentType.name, 'List')} = createRoute({\n method: 'get',\n path: '${collPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${PUBLIC_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Public — GET single by slug\n lines.push(\n `export const ${routeVar('get', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${openApiPath(itemPath)}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${SLUG_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET list\n const adminCollPath = '/admin' + collPath\n const adminItemPath = adminCollPath + '/{id}'\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, 'List')} = createRoute({\n method: 'get',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${ADMIN_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Admin — GET single by id\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST\n lines.push(\n `export const ${routeVar('adminCreate', contentType.name, '')} = createRoute({\n method: 'post',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', contentType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — DELETE\n lines.push(\n `export const ${routeVar('adminDelete', contentType.name, '')} = createRoute({\n method: 'delete',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: z.object({ ok: z.literal(true) }) } },\n description: '${label} deleted',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n } else {\n // only_one: true — no list, no slug, fixed paths\n const itemPath = contentType.api.item_path\n const adminItemBase = '/admin' + itemPath\n const adminPatchPath = '/admin/api/' + contentType.default_base_path + '/{id}'\n\n // Public — GET singleton\n lines.push(\n `export const ${routeVar('get', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${itemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET singleton\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemBase}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST (create singleton)\n const adminPostPath = '/admin/api/' + contentType.default_base_path\n lines.push(\n `export const ${routeVar('adminCreate', contentType.name, '')} = createRoute({\n method: 'post',\n path: '${adminPostPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 409: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Singleton already exists',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', contentType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminPatchPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n }\n\n return lines.join('\\n\\n')\n}\n\n// ─── Taxonomy route generators ────────────────────────────────────────────────\n\nfunction generateTaxonomyRoutes(taxonomyType: ParsedTaxonomyType): string {\n const sVar = schemaVar(taxonomyType.name)\n const label = taxonomyType.label\n const tag = label\n const collPath = taxonomyType.api.collection_path\n const itemPath = taxonomyType.api.item_path\n const adminCollPath = '/admin' + collPath\n const adminItemPath = '/admin' + openApiPath(itemPath)\n const lines: string[] = []\n\n // Public — GET list\n lines.push(\n `export const ${routeVar('get', taxonomyType.name, 'List')} = createRoute({\n method: 'get',\n path: '${collPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${PUBLIC_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Public — GET single by id\n lines.push(\n `export const ${routeVar('get', taxonomyType.name, '')} = createRoute({\n method: 'get',\n path: '${openApiPath(itemPath)}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET list\n lines.push(\n `export const ${routeVar('adminGet', taxonomyType.name, 'List')} = createRoute({\n method: 'get',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${ADMIN_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Admin — GET single by id\n lines.push(\n `export const ${routeVar('adminGet', taxonomyType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST\n lines.push(\n `export const ${routeVar('adminCreate', taxonomyType.name, '')} = createRoute({\n method: 'post',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', taxonomyType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — DELETE\n lines.push(\n `export const ${routeVar('adminDelete', taxonomyType.name, '')} = createRoute({\n method: 'delete',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: z.object({ ok: z.literal(true) }) } },\n description: '${label} deleted',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n return lines.join('\\n\\n')\n}\n\n// ─── generateRoutes ───────────────────────────────────────────────────────────\n\nexport function generateRoutes(registry: SchemaRegistry): string {\n const parts: string[] = []\n\n parts.push('// Auto-generated by generateRoutes() — do not hand-edit')\n parts.push(\"import { createRoute, z } from '@hono/zod-openapi'\")\n parts.push('')\n parts.push('// ─── Shared schemas ──────────────────────────────────────────────────────────')\n parts.push('')\n parts.push(SHARED_SCHEMAS_BLOCK)\n parts.push('')\n\n const paragraphEntries = Object.entries(registry.paragraph_types)\n if (paragraphEntries.length > 0) {\n parts.push('// ─── Paragraph schemas ───────────────────────────────────────────────────────')\n parts.push('')\n for (const [, paragraphType] of paragraphEntries) {\n parts.push(generateParagraphSchemaDecl(paragraphType, registry))\n }\n parts.push('')\n }\n\n const contentEntries = Object.entries(registry.content_types)\n if (contentEntries.length > 0) {\n parts.push('// ─── Content type schemas ────────────────────────────────────────────────────')\n parts.push('')\n for (const [, contentType] of contentEntries) {\n parts.push(generateContentSchema(contentType, registry))\n parts.push('')\n }\n }\n\n const taxonomyEntries = Object.entries(registry.taxonomy_types)\n if (taxonomyEntries.length > 0) {\n parts.push('// ─── Taxonomy type schemas ───────────────────────────────────────────────────')\n parts.push('')\n for (const [, taxonomyType] of taxonomyEntries) {\n parts.push(generateContentSchema(taxonomyType, registry))\n parts.push('')\n }\n }\n\n if (contentEntries.length > 0) {\n parts.push('// ─── Content routes ─────────────────────────────────────────────────────────')\n parts.push('')\n for (const [, contentType] of contentEntries) {\n parts.push(generateContentRoutes(contentType))\n parts.push('')\n }\n }\n\n if (taxonomyEntries.length > 0) {\n parts.push('// ─── Taxonomy routes ────────────────────────────────────────────────────────')\n parts.push('')\n for (const [, taxonomyType] of taxonomyEntries) {\n parts.push(generateTaxonomyRoutes(taxonomyType))\n parts.push('')\n }\n }\n\n return parts.join('\\n')\n}\n"],"mappings":";AAWA,SAAS,WAAW,aAA6B;AAC/C,QAAM,MAAM,YAAY,QAAQ,IAAI;AACpC,SAAO,QAAQ,KAAK,YAAY,MAAM,MAAM,CAAC,IAAI;AACnD;AAEA,SAAS,aAAa,cAA8B;AAClD,SAAO,aACJ,MAAM,MAAM,EACZ,OAAO,OAAO,EACd,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,CAAC,EACjD,KAAK,EAAE;AACZ;AAEA,SAAS,UAAU,aAA6B;AAC9C,SAAO,aAAa,WAAW,WAAW,CAAC,IAAI;AACjD;AAEA,SAAS,SAAS,QAAgB,aAAqB,QAAwB;AAC7E,SAAO,GAAG,MAAM,GAAG,aAAa,WAAW,WAAW,CAAC,CAAC,GAAG,MAAM;AACnE;AAGA,SAAS,YAAY,UAA0B;AAC7C,SAAO,SAAS,QAAQ,aAAa,MAAM;AAC7C;AAIO,SAAS,iBAAiB,OAAoB,UAAmC;AACtF,QAAM,EAAE,YAAY,WAAW,IAAI;AAEnC,UAAQ,YAAY;AAAA,IAClB,KAAK,cAAc;AACjB,UAAI,IAAI;AACR,UAAI,WAAW,UAAU,OAAW,MAAK,QAAQ,WAAW,KAAK;AACjE,UAAI,WAAW,YAAY,OAAW,MAAK,qBAAqB,KAAK,UAAU,WAAW,OAAO,CAAC;AAClG,aAAO;AAAA,IACT;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,IAET,KAAK,WAAW;AACd,UAAI,IAAI;AACR,UAAI,WAAW,QAAQ,OAAW,MAAK,QAAQ,WAAW,GAAG;AAC7D,UAAI,WAAW,QAAQ,OAAW,MAAK,QAAQ,WAAW,GAAG;AAC7D,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,SAAS;AACZ,UAAI,IAAI;AACR,UAAI,WAAW,QAAQ,OAAW,MAAK,QAAQ,WAAW,GAAG;AAC7D,UAAI,WAAW,QAAQ,OAAW,MAAK,QAAQ,WAAW,GAAG;AAC7D,aAAO;AAAA,IACT;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK,SAAS;AACZ,YAAM,SAAS;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,cAAc,OAAO,KAAK,IAAI,CAAC;AAAA,IACxC;AAAA,IAEA,KAAK,SAAS;AACZ,YAAM,SAAS;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,cAAc,OAAO,KAAK,IAAI,CAAC;AAAA,IACxC;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,SAAS;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,cAAc,OAAO,KAAK,IAAI,CAAC;AAAA,IACxC;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,SAAS,WAAW,kBAAkB,CAAC;AAC7C,UAAI,OAAO,WAAW,EAAG,QAAO;AAChC,YAAM,SAAS,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,EAAE,KAAK,IAAI;AAC7D,aAAO,WAAW,MAAM;AAAA,IAC1B;AAAA,IAEA,KAAK,aAAa;AAChB,YAAM,KAAK,MAAM;AACjB,UAAI,GAAG,cAAc,kBAAmB,QAAO;AAC/C,YAAM,gBAAgB,UAAU,gBAAgB,GAAG,GAAG;AACtD,UAAI,CAAC,cAAe,QAAO;AAC3B,YAAM,QAAQ,8BAA8B,eAAe,QAAQ;AACnE,aAAO,GAAG,QAAQ,gBAAgB,WAAW,KAAK,MAAM;AAAA,IAC1D;AAAA,IAEA,KAAK,aAAa;AAChB,YAAM,KAAK,MAAM;AACjB,UAAI,GAAG,cAAc,mBAAoB,QAAO;AAChD,aAAO,GAAG,QAAQ,gBAAgB,+BAA+B;AAAA,IACnE;AAAA,IAEA;AACE,aAAO;AAAA,EACX;AACF;AAGA,SAAS,8BACP,WACA,UACQ;AACR,QAAM,UAAU,UAAU,OAAO,IAAI,CAAC,MAAM;AAC1C,UAAM,UAAU,iBAAiB,GAAG,QAAQ;AAC5C,WAAO,GAAG,EAAE,IAAI,KAAK,EAAE,WAAW,UAAU,GAAG,OAAO,aAAa;AAAA,EACrE,CAAC;AACD,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SAAO,cAAc,QAAQ,KAAK,IAAI,CAAC;AACzC;AAIA,SAAS,mBAAmB,QAA0D;AACpF,QAAM,UAAoB,CAAC,uBAAuB;AAClD,MAAI,OAAO,gBAAgB,kBAAkB,CAAC,OAAO,UAAU;AAC7D,YAAQ,KAAK,kBAAkB;AAAA,EACjC;AACA,UAAQ,KAAK,wBAAwB;AACrC,UAAQ,KAAK,mCAAmC;AAChD,UAAQ,KAAK,mCAAmC;AAChD,SAAO;AACT;AAEA,SAAS,mBACP,QACA,UACU;AACV,SAAO,OAAO,IAAI,CAAC,MAAM;AACvB,UAAM,UAAU,iBAAiB,GAAG,QAAQ;AAC5C,WAAO,KAAK,EAAE,IAAI,KAAK,EAAE,WAAW,UAAU,GAAG,OAAO,aAAa;AAAA,EACvE,CAAC;AACH;AAEO,SAAS,sBACd,QACA,UACQ;AACR,QAAM,OAAO,UAAU,OAAO,IAAI;AAClC,QAAM,aAAa,mBAAmB,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;AACjE,QAAM,eAAe,mBAAmB,OAAO,QAAQ,QAAQ;AAC/D,QAAM,aAAa,CAAC,GAAG,YAAY,GAAG,YAAY;AAClD,SAAO,SAAS,IAAI;AAAA,EAAkB,WAAW,KAAK,KAAK,CAAC;AAAA;AAC9D;AAGA,SAAS,4BACP,WACA,UACQ;AACR,QAAM,OAAO,UAAU,UAAU,IAAI;AACrC,QAAM,QAAQ,8BAA8B,WAAW,QAAQ;AAC/D,SAAO,SAAS,IAAI,MAAM,KAAK;AACjC;AAIA,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiC7B,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ1B,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASzB,IAAM,cAAc;AACpB,IAAM,YAAY;AAClB,IAAM,gBAAgB;AAItB,SAAS,sBAAsB,aAAwC;AACrE,QAAM,OAAO,UAAU,YAAY,IAAI;AACvC,QAAM,QAAQ,YAAY;AAC1B,QAAM,MAAM;AACZ,QAAM,QAAkB,CAAC;AAEzB,MAAI,CAAC,YAAY,UAAU;AACzB,UAAM,WAAW,YAAY,IAAI;AACjC,UAAM,WAAW,YAAY,IAAI;AAGjC,UAAM;AAAA,MACJ,gBAAgB,SAAS,OAAO,YAAY,MAAM,MAAM,CAAC;AAAA;AAAA,WAEpD,QAAQ;AAAA,WACR,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,iBAAiB;AAAA;AAAA;AAAA;AAAA,oEAIsC,IAAI;AAAA,8BAC1C,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQ/B;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,OAAO,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAEhD,YAAY,QAAQ,CAAC;AAAA,WACrB,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,WAAW;AAAA,aACZ,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,IAIvB;AAGA,UAAM,gBAAgB,WAAW;AACjC,UAAM,gBAAgB,gBAAgB;AACtC,UAAM;AAAA,MACJ,gBAAgB,SAAS,YAAY,YAAY,MAAM,MAAM,CAAC;AAAA;AAAA,WAEzD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,gBAAgB;AAAA;AAAA;AAAA;AAAA,oEAIuC,IAAI;AAAA,8BAC1C,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQ/B;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,YAAY,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAErD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA,aACV,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,IAIvB;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,eAAe,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAExD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA;AAAA,iDAGmB,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQvB;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,eAAe,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAExD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA;AAAA,iDAE0B,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQvB;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,eAAe,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAExD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,sBAKD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,IAIvB;AAAA,EACF,OAAO;AAEL,UAAM,WAAW,YAAY,IAAI;AACjC,UAAM,gBAAgB,WAAW;AACjC,UAAM,iBAAiB,gBAAgB,YAAY,oBAAoB;AAGvE,UAAM;AAAA,MACJ,gBAAgB,SAAS,OAAO,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAEhD,QAAQ;AAAA,WACR,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,IAIvB;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,YAAY,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAErD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,IAIvB;AAGA,UAAM,gBAAgB,gBAAgB,YAAY;AAClD,UAAM;AAAA,MACJ,gBAAgB,SAAS,eAAe,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAExD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA;AAAA,iDAGmB,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYvB;AAGA,UAAM;AAAA,MACJ,gBAAgB,SAAS,eAAe,YAAY,MAAM,EAAE,CAAC;AAAA;AAAA,WAExD,cAAc;AAAA,WACd,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA;AAAA,iDAE0B,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQvB;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,MAAM;AAC1B;AAIA,SAAS,uBAAuB,cAA0C;AACxE,QAAM,OAAO,UAAU,aAAa,IAAI;AACxC,QAAM,QAAQ,aAAa;AAC3B,QAAM,MAAM;AACZ,QAAM,WAAW,aAAa,IAAI;AAClC,QAAM,WAAW,aAAa,IAAI;AAClC,QAAM,gBAAgB,WAAW;AACjC,QAAM,gBAAgB,WAAW,YAAY,QAAQ;AACrD,QAAM,QAAkB,CAAC;AAGzB,QAAM;AAAA,IACJ,gBAAgB,SAAS,OAAO,aAAa,MAAM,MAAM,CAAC;AAAA;AAAA,WAEnD,QAAQ;AAAA,WACR,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,iBAAiB;AAAA;AAAA;AAAA;AAAA,oEAIsC,IAAI;AAAA,8BAC1C,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQjC;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,OAAO,aAAa,MAAM,EAAE,CAAC;AAAA;AAAA,WAE/C,YAAY,QAAQ,CAAC;AAAA,WACrB,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA,aACV,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,EAIzB;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,YAAY,aAAa,MAAM,MAAM,CAAC;AAAA;AAAA,WAExD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,aAEjB,gBAAgB;AAAA;AAAA;AAAA;AAAA,oEAIuC,IAAI;AAAA,8BAC1C,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQjC;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,YAAY,aAAa,MAAM,EAAE,CAAC;AAAA;AAAA,WAEpD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA,aACV,aAAa;AAAA;AAAA;AAAA;AAAA,oEAI0C,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,EAIzB;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,eAAe,aAAa,MAAM,EAAE,CAAC;AAAA;AAAA,WAEvD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA;AAAA,iDAGmB,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQzB;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,eAAe,aAAa,MAAM,EAAE,CAAC;AAAA;AAAA,WAEvD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA;AAAA,iDAE0B,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,oEAKe,IAAI;AAAA,sBAClD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQzB;AAGA,QAAM;AAAA,IACJ,gBAAgB,SAAS,eAAe,aAAa,MAAM,EAAE,CAAC;AAAA;AAAA,WAEvD,aAAa;AAAA,WACb,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,cAEhB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,sBAKD,KAAK;AAAA;AAAA;AAAA;AAAA,sBAIL,KAAK;AAAA;AAAA;AAAA;AAAA,EAIzB;AAEA,SAAO,MAAM,KAAK,MAAM;AAC1B;AAIO,SAAS,eAAe,UAAkC;AAC/D,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,+DAA0D;AACrE,QAAM,KAAK,oDAAoD;AAC/D,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,mYAAkF;AAC7F,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,oBAAoB;AAC/B,QAAM,KAAK,EAAE;AAEb,QAAM,mBAAmB,OAAO,QAAQ,SAAS,eAAe;AAChE,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,KAAK,oXAAkF;AAC7F,UAAM,KAAK,EAAE;AACb,eAAW,CAAC,EAAE,aAAa,KAAK,kBAAkB;AAChD,YAAM,KAAK,4BAA4B,eAAe,QAAQ,CAAC;AAAA,IACjE;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,iBAAiB,OAAO,QAAQ,SAAS,aAAa;AAC5D,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,KAAK,qWAAkF;AAC7F,UAAM,KAAK,EAAE;AACb,eAAW,CAAC,EAAE,WAAW,KAAK,gBAAgB;AAC5C,YAAM,KAAK,sBAAsB,aAAa,QAAQ,CAAC;AACvD,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,QAAM,kBAAkB,OAAO,QAAQ,SAAS,cAAc;AAC9D,MAAI,gBAAgB,SAAS,GAAG;AAC9B,UAAM,KAAK,gWAAkF;AAC7F,UAAM,KAAK,EAAE;AACb,eAAW,CAAC,EAAE,YAAY,KAAK,iBAAiB;AAC9C,YAAM,KAAK,sBAAsB,cAAc,QAAQ,CAAC;AACxD,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,KAAK,6XAAiF;AAC5F,UAAM,KAAK,EAAE;AACb,eAAW,CAAC,EAAE,WAAW,KAAK,gBAAgB;AAC5C,YAAM,KAAK,sBAAsB,WAAW,CAAC;AAC7C,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,MAAI,gBAAgB,SAAS,GAAG;AAC9B,UAAM,KAAK,wXAAiF;AAC5F,UAAM,KAAK,EAAE;AACb,eAAW,CAAC,EAAE,YAAY,KAAK,iBAAiB;AAC9C,YAAM,KAAK,uBAAuB,YAAY,CAAC;AAC/C,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/codegen/routes.ts"],"sourcesContent":["// generateRoutes() — pure function that returns a Hono route group from parsed schema\nimport type {\n SchemaRegistry,\n ParsedField,\n ParsedContentType,\n ParsedTaxonomyType,\n ParsedParagraphType,\n} from '@bobbykim/manguito-cms-core'\nimport { relationCardinality } from '@bobbykim/manguito-cms-core'\n\n// ─── Name helpers ─────────────────────────────────────────────────────────────\n\nfunction getSegment(machineName: string): string {\n const idx = machineName.indexOf('--')\n return idx !== -1 ? machineName.slice(idx + 2) : machineName\n}\n\nfunction toPascalCase(snakeOrKebab: string): string {\n return snakeOrKebab\n .split(/[_-]/)\n .filter(Boolean)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1))\n .join('')\n}\n\nfunction schemaVar(machineName: string): string {\n return toPascalCase(getSegment(machineName)) + 'Schema'\n}\n\nfunction routeVar(prefix: string, machineName: string, suffix: string): string {\n return `${prefix}${toPascalCase(getSegment(machineName))}${suffix}Route`\n}\n\n// Convert Hono :param notation to OpenAPI {param} notation\nfunction openApiPath(honoPath: string): string {\n return honoPath.replace(/:([^/]+)/g, '{$1}')\n}\n\n// ─── Field → Zod type string ──────────────────────────────────────────────────\n\nexport function fieldToZodSchema(field: ParsedField, registry?: SchemaRegistry): string {\n const { field_type, validation } = field\n\n switch (field_type) {\n case 'text/plain': {\n let s = 'z.string()'\n if (validation.limit !== undefined) s += `.max(${validation.limit})`\n if (validation.pattern !== undefined) s += `.regex(new RegExp(${JSON.stringify(validation.pattern)}))`\n return s\n }\n\n case 'text/rich':\n return 'z.string()'\n\n case 'integer': {\n let s = 'z.number().int()'\n if (validation.min !== undefined) s += `.min(${validation.min})`\n if (validation.max !== undefined) s += `.max(${validation.max})`\n return s\n }\n\n case 'float': {\n let s = 'z.number()'\n if (validation.min !== undefined) s += `.min(${validation.min})`\n if (validation.max !== undefined) s += `.max(${validation.max})`\n return s\n }\n\n case 'boolean':\n return 'z.boolean()'\n\n case 'date':\n return 'z.string().datetime()'\n\n case 'image': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n 'width: z.number().int().optional()',\n 'height: z.number().int().optional()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'video': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n 'width: z.number().int().optional()',\n 'height: z.number().int().optional()',\n 'duration: z.number().optional()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'file': {\n const fields = [\n 'id: z.string().uuid()',\n 'url: z.string().url()',\n 'mime_type: z.string()',\n 'alt: z.string().optional()',\n 'file_size: z.number().int()',\n ]\n return `z.object({ ${fields.join(', ')} })`\n }\n\n case 'enum': {\n const values = validation.allowed_values ?? []\n if (values.length === 0) return 'z.string()'\n const quoted = values.map((v) => JSON.stringify(v)).join(', ')\n return `z.enum([${quoted}])`\n }\n\n case 'paragraph': {\n const ui = field.ui_component\n if (ui.component !== 'paragraph-embed') return 'z.unknown()'\n const paragraphType = registry?.paragraph_types[ui.ref]\n if (!paragraphType) return 'z.unknown()'\n const inner = generateParagraphObjectSchema(paragraphType, registry)\n return relationCardinality(field) === 'many' ? `z.array(${inner})` : inner\n }\n\n case 'reference': {\n const ui = field.ui_component\n if (ui.component !== 'typeahead-select') return 'z.string().uuid()'\n return relationCardinality(field) === 'many' ? 'z.array(z.string().uuid())' : 'z.string().uuid()'\n }\n\n default:\n return 'z.unknown()'\n }\n}\n\n// Generates inline z.object({...}) for a paragraph type — used recursively inside fieldToZodSchema\nfunction generateParagraphObjectSchema(\n paragraph: ParsedParagraphType,\n registry?: SchemaRegistry\n): string {\n const entries = paragraph.fields.map((f) => {\n const zodType = fieldToZodSchema(f, registry)\n return `${f.name}: ${f.required ? zodType : `${zodType}.optional()`}`\n })\n if (entries.length === 0) return 'z.object({})'\n return `z.object({ ${entries.join(', ')} })`\n}\n\n// ─── Schema declaration generators ───────────────────────────────────────────\n\nfunction systemFieldEntries(schema: ParsedContentType | ParsedTaxonomyType): string[] {\n const entries: string[] = ['id: z.string().uuid()']\n if (schema.schema_type === 'content-type' && !schema.only_one) {\n entries.push('slug: z.string()')\n }\n entries.push('published: z.boolean()')\n entries.push('created_at: z.string().datetime()')\n entries.push('updated_at: z.string().datetime()')\n return entries\n}\n\nfunction schemaFieldEntries(\n fields: ParsedField[],\n registry?: SchemaRegistry\n): string[] {\n return fields.map((f) => {\n const zodType = fieldToZodSchema(f, registry)\n return ` ${f.name}: ${f.required ? zodType : `${zodType}.optional()`}`\n })\n}\n\nexport function generateContentSchema(\n schema: ParsedContentType | ParsedTaxonomyType,\n registry?: SchemaRegistry\n): string {\n const name = schemaVar(schema.name)\n const sysEntries = systemFieldEntries(schema).map((e) => ` ${e}`)\n const fieldEntries = schemaFieldEntries(schema.fields, registry)\n const allEntries = [...sysEntries, ...fieldEntries]\n return `const ${name} = z.object({\\n${allEntries.join(',\\n')},\\n})`\n}\n\n// Internal: paragraph schema const declaration (not exported but emitted into generated file)\nfunction generateParagraphSchemaDecl(\n paragraph: ParsedParagraphType,\n registry?: SchemaRegistry\n): string {\n const name = schemaVar(paragraph.name)\n const inner = generateParagraphObjectSchema(paragraph, registry)\n return `const ${name} = ${inner}`\n}\n\n// ─── Shared schemas block ─────────────────────────────────────────────────────\n\nconst SHARED_SCHEMAS_BLOCK = `const ErrorResponseSchema = z.object({\n ok: z.literal(false),\n error: z.object({\n code: z.string(),\n message: z.string(),\n details: z.unknown().optional(),\n }),\n})\n\nfunction listResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n ok: z.literal(true),\n data: z.array(dataSchema),\n meta: z.object({\n total: z.number().int(),\n page: z.number().int(),\n per_page: z.number().int(),\n total_pages: z.number().int(),\n has_next: z.boolean(),\n has_prev: z.boolean(),\n }),\n })\n}\n\nfunction itemResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n ok: z.literal(true),\n data: dataSchema,\n })\n}`\n\n// ─── Query param schema strings ───────────────────────────────────────────────\n\nconst PUBLIC_LIST_QUERY = `z.object({\n page: z.coerce.number().int().min(1).default(1),\n per_page: z.coerce.number().int().min(1).max(100).default(10),\n include: z.string().optional().describe('Comma-separated relation field names to expand'),\n sort_by: z.enum(['title', 'created_at', 'updated_at']).optional().default('created_at'),\n sort_order: z.enum(['asc', 'desc']).optional().default('asc'),\n })`\n\nconst ADMIN_LIST_QUERY = `z.object({\n page: z.coerce.number().int().min(1).default(1),\n per_page: z.coerce.number().int().min(1).max(100).default(10),\n include: z.string().optional().describe('Comma-separated relation field names to expand'),\n sort_by: z.enum(['title', 'created_at', 'updated_at']).optional().default('created_at'),\n sort_order: z.enum(['asc', 'desc']).optional().default('asc'),\n published: z.enum(['true', 'false']).optional().describe('Filter by published state'),\n })`\n\nconst SLUG_PARAMS = `z.object({ slug: z.string() })`\nconst ID_PARAMS = `z.object({ id: z.string().uuid() })`\nconst INCLUDE_QUERY = `z.object({ include: z.string().optional().describe('Comma-separated relation field names to expand') })`\n\n// ─── Content route generators ─────────────────────────────────────────────────\n\nfunction generateContentRoutes(contentType: ParsedContentType): string {\n const sVar = schemaVar(contentType.name)\n const label = contentType.label\n const tag = label\n const lines: string[] = []\n\n if (!contentType.only_one) {\n const collPath = contentType.api.collection_path!\n const itemPath = contentType.api.item_path\n\n // Public — GET list\n lines.push(\n `export const ${routeVar('get', contentType.name, 'List')} = createRoute({\n method: 'get',\n path: '${collPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${PUBLIC_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Public — GET single by slug\n lines.push(\n `export const ${routeVar('get', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${openApiPath(itemPath)}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${SLUG_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET list\n const adminCollPath = '/admin' + collPath\n const adminItemPath = adminCollPath + '/{id}'\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, 'List')} = createRoute({\n method: 'get',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${ADMIN_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Admin — GET single by id\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST\n lines.push(\n `export const ${routeVar('adminCreate', contentType.name, '')} = createRoute({\n method: 'post',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', contentType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — DELETE\n lines.push(\n `export const ${routeVar('adminDelete', contentType.name, '')} = createRoute({\n method: 'delete',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: z.object({ ok: z.literal(true) }) } },\n description: '${label} deleted',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n } else {\n // only_one: true — no list, no slug, fixed paths\n const itemPath = contentType.api.item_path\n const adminItemBase = '/admin' + itemPath\n const adminPatchPath = '/admin/api/' + contentType.default_base_path + '/{id}'\n\n // Public — GET singleton\n lines.push(\n `export const ${routeVar('get', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${itemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET singleton\n lines.push(\n `export const ${routeVar('adminGet', contentType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemBase}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST (create singleton)\n const adminPostPath = '/admin/api/' + contentType.default_base_path\n lines.push(\n `export const ${routeVar('adminCreate', contentType.name, '')} = createRoute({\n method: 'post',\n path: '${adminPostPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 409: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Singleton already exists',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', contentType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminPatchPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n }\n\n return lines.join('\\n\\n')\n}\n\n// ─── Taxonomy route generators ────────────────────────────────────────────────\n\nfunction generateTaxonomyRoutes(taxonomyType: ParsedTaxonomyType): string {\n const sVar = schemaVar(taxonomyType.name)\n const label = taxonomyType.label\n const tag = label\n const collPath = taxonomyType.api.collection_path\n const itemPath = taxonomyType.api.item_path\n const adminCollPath = '/admin' + collPath\n const adminItemPath = '/admin' + openApiPath(itemPath)\n const lines: string[] = []\n\n // Public — GET list\n lines.push(\n `export const ${routeVar('get', taxonomyType.name, 'List')} = createRoute({\n method: 'get',\n path: '${collPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${PUBLIC_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Public — GET single by id\n lines.push(\n `export const ${routeVar('get', taxonomyType.name, '')} = createRoute({\n method: 'get',\n path: '${openApiPath(itemPath)}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — GET list\n lines.push(\n `export const ${routeVar('adminGet', taxonomyType.name, 'List')} = createRoute({\n method: 'get',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n query: ${ADMIN_LIST_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: listResponseSchema(${sVar}) } },\n description: 'List of ${label}',\n },\n 400: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Invalid query parameters',\n },\n },\n})`\n )\n\n // Admin — GET single by id\n lines.push(\n `export const ${routeVar('adminGet', taxonomyType.name, '')} = createRoute({\n method: 'get',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n query: ${INCLUDE_QUERY},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label}',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n // Admin — POST\n lines.push(\n `export const ${routeVar('adminCreate', taxonomyType.name, '')} = createRoute({\n method: 'post',\n path: '${adminCollPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n body: {\n content: { 'application/json': { schema: ${sVar} } },\n },\n },\n responses: {\n 201: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} created',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — PATCH\n lines.push(\n `export const ${routeVar('adminUpdate', taxonomyType.name, '')} = createRoute({\n method: 'patch',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n body: {\n content: { 'application/json': { schema: ${sVar}.partial().extend({ published: z.boolean().optional() }) } },\n },\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: itemResponseSchema(${sVar}) } },\n description: '${label} updated',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n 422: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: 'Validation error',\n },\n },\n})`\n )\n\n // Admin — DELETE\n lines.push(\n `export const ${routeVar('adminDelete', taxonomyType.name, '')} = createRoute({\n method: 'delete',\n path: '${adminItemPath}',\n tags: [${JSON.stringify(tag)}],\n request: {\n params: ${ID_PARAMS},\n },\n responses: {\n 200: {\n content: { 'application/json': { schema: z.object({ ok: z.literal(true) }) } },\n description: '${label} deleted',\n },\n 404: {\n content: { 'application/json': { schema: ErrorResponseSchema } },\n description: '${label} not found',\n },\n },\n})`\n )\n\n return lines.join('\\n\\n')\n}\n\n// ─── generateRoutes ───────────────────────────────────────────────────────────\n\nexport function generateRoutes(registry: SchemaRegistry): string {\n const parts: string[] = []\n\n parts.push('// Auto-generated by generateRoutes() — do not hand-edit')\n parts.push(\"import { createRoute, z } from '@hono/zod-openapi'\")\n parts.push('')\n parts.push('// ─── Shared schemas ──────────────────────────────────────────────────────────')\n parts.push('')\n parts.push(SHARED_SCHEMAS_BLOCK)\n parts.push('')\n\n const paragraphEntries = Object.entries(registry.paragraph_types)\n if (paragraphEntries.length > 0) {\n parts.push('// ─── Paragraph schemas ───────────────────────────────────────────────────────')\n parts.push('')\n for (const [, paragraphType] of paragraphEntries) {\n parts.push(generateParagraphSchemaDecl(paragraphType, registry))\n }\n parts.push('')\n }\n\n const contentEntries = Object.entries(registry.content_types)\n if (contentEntries.length > 0) {\n parts.push('// ─── Content type schemas ────────────────────────────────────────────────────')\n parts.push('')\n for (const [, contentType] of contentEntries) {\n parts.push(generateContentSchema(contentType, registry))\n parts.push('')\n }\n }\n\n const taxonomyEntries = Object.entries(registry.taxonomy_types)\n if (taxonomyEntries.length > 0) {\n parts.push('// ─── Taxonomy type schemas ───────────────────────────────────────────────────')\n parts.push('')\n for (const [, taxonomyType] of taxonomyEntries) {\n parts.push(generateContentSchema(taxonomyType, registry))\n parts.push('')\n }\n }\n\n if (contentEntries.length > 0) {\n parts.push('// ─── Content routes ─────────────────────────────────────────────────────────')\n parts.push('')\n for (const [, contentType] of contentEntries) {\n parts.push(generateContentRoutes(contentType))\n parts.push('')\n }\n }\n\n if (taxonomyEntries.length > 0) {\n parts.push('// ─── Taxonomy routes ────────────────────────────────────────────────────────')\n parts.push('')\n for (const [, taxonomyType] of taxonomyEntries) {\n parts.push(generateTaxonomyRoutes(taxonomyType))\n parts.push('')\n }\n }\n\n return parts.join('\\n')\n}\n"],"mappings":"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","names":[]}
|
package/dist/graphql/index.d.mts
CHANGED
|
@@ -28,6 +28,7 @@ declare function createGraphQLHandler(registry: SchemaRegistry, repos: Record<st
|
|
|
28
28
|
projection?: VersionProjection;
|
|
29
29
|
currentProjection?: VersionProjection;
|
|
30
30
|
currentVersion?: string;
|
|
31
|
+
currentFieldKeyMaps?: Record<string, FieldKeyMap>;
|
|
31
32
|
}): Handler;
|
|
32
33
|
|
|
33
34
|
export { type ResolvedGraphQLOptions, createGraphQLHandler };
|