cms-renderer 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../node_modules/ret/dist/types/tokens.js","../../../../node_modules/ret/lib/types/types.ts","../../../../node_modules/ret/dist/types/set-lookup.js","../../../../node_modules/ret/lib/types/index.ts","../../../../node_modules/ret/lib/sets.ts","../../../../node_modules/ret/lib/util.ts","../../../../node_modules/ret/lib/tokenizer.ts","../../../../node_modules/ret/lib/sets-lookup.ts","../../../../node_modules/ret/lib/write-set-tokens.ts","../../../../node_modules/ret/lib/reconstruct.ts","../../../../node_modules/ret/lib/index.ts","../../../../node_modules/safe-regex2/index.js","../../../../node_modules/object-hash/index.js","../../lib/custom-schemas.ts","../../../../packages/cms-schema/src/documents/registry.ts","../../../../packages/cms-schema/src/documents/schemas/country.ts","../../../../packages/cms-schema/src/documents/schemas/language.ts","../../../../packages/cms-schema/src/documents/unified-registry.ts","../../../../packages/cms-schema/src/documents/rehydration.ts","../../../../packages/cms-schema/src/fields/complex/media.ts","../../../../packages/cms-schema/src/validation/image.ts","../../../../packages/cms-schema/src/utils/safe-regex.ts","../../../../packages/cms-schema/src/documents/schema-hash.ts","../../../../packages/cms-schema/src/documents/validations/country.ts","../../../../packages/cms-schema/src/documents/generate-zod-code.ts","../../lib/cms-api.ts"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=tokens.js.map",null,"\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=set-lookup.js.map",null,null,null,null,null,null,null,null,"'use strict'\n\nconst parse = require('ret')\nconst types = parse.types\n\nfunction safeRegex (re, opts) {\n if (!opts) opts = {}\n /* c8 ignore next */\n const replimit = opts.limit === undefined ? 25 : opts.limit\n\n /* c8 ignore next 2 */\n if (isRegExp(re)) re = re.source\n else if (typeof re !== 'string') re = String(re)\n\n try { re = parse(re) } catch { return false }\n\n let reps = 0\n return (function walk (node, starHeight) {\n let i\n let ok\n let len\n\n if (node.type === types.REPETITION) {\n starHeight++\n reps++\n if (starHeight > 1) return false\n if (reps > replimit) return false\n }\n\n if (node.options) {\n for (i = 0, len = node.options.length; i < len; i++) {\n ok = walk({ stack: node.options[i] }, starHeight)\n if (!ok) return false\n }\n }\n const stack = node.stack || node.value?.stack\n if (!stack) return true\n\n for (i = 0; i < stack.length; i++) {\n ok = walk(stack[i], starHeight)\n if (!ok) return false\n }\n\n return true\n })(re, 0)\n}\n\nfunction isRegExp (x) {\n return {}.toString.call(x) === '[object RegExp]'\n}\n\nmodule.exports = safeRegex\nmodule.exports.default = safeRegex\nmodule.exports.safeRegex = safeRegex\n","'use strict';\n\nvar crypto = require('crypto');\n\n/**\n * Exported function\n *\n * Options:\n *\n * - `algorithm` hash algo to be used by this instance: *'sha1', 'md5'\n * - `excludeValues` {true|*false} hash object keys, values ignored\n * - `encoding` hash encoding, supports 'buffer', '*hex', 'binary', 'base64'\n * - `ignoreUnknown` {true|*false} ignore unknown object types\n * - `replacer` optional function that replaces values before hashing\n * - `respectFunctionProperties` {*true|false} consider function properties when hashing\n * - `respectFunctionNames` {*true|false} consider 'name' property of functions for hashing\n * - `respectType` {*true|false} Respect special properties (prototype, constructor)\n * when hashing to distinguish between types\n * - `unorderedArrays` {true|*false} Sort all arrays before hashing\n * - `unorderedSets` {*true|false} Sort `Set` and `Map` instances before hashing\n * * = default\n *\n * @param {object} object value to hash\n * @param {object} options hashing options\n * @return {string} hash value\n * @api public\n */\nexports = module.exports = objectHash;\n\nfunction objectHash(object, options){\n options = applyDefaults(object, options);\n\n return hash(object, options);\n}\n\n/**\n * Exported sugar methods\n *\n * @param {object} object value to hash\n * @return {string} hash value\n * @api public\n */\nexports.sha1 = function(object){\n return objectHash(object);\n};\nexports.keys = function(object){\n return objectHash(object, {excludeValues: true, algorithm: 'sha1', encoding: 'hex'});\n};\nexports.MD5 = function(object){\n return objectHash(object, {algorithm: 'md5', encoding: 'hex'});\n};\nexports.keysMD5 = function(object){\n return objectHash(object, {algorithm: 'md5', encoding: 'hex', excludeValues: true});\n};\n\n// Internals\nvar hashes = crypto.getHashes ? crypto.getHashes().slice() : ['sha1', 'md5'];\nhashes.push('passthrough');\nvar encodings = ['buffer', 'hex', 'binary', 'base64'];\n\nfunction applyDefaults(object, sourceOptions){\n sourceOptions = sourceOptions || {};\n\n // create a copy rather than mutating\n var options = {};\n options.algorithm = sourceOptions.algorithm || 'sha1';\n options.encoding = sourceOptions.encoding || 'hex';\n options.excludeValues = sourceOptions.excludeValues ? true : false;\n options.algorithm = options.algorithm.toLowerCase();\n options.encoding = options.encoding.toLowerCase();\n options.ignoreUnknown = sourceOptions.ignoreUnknown !== true ? false : true; // default to false\n options.respectType = sourceOptions.respectType === false ? false : true; // default to true\n options.respectFunctionNames = sourceOptions.respectFunctionNames === false ? false : true;\n options.respectFunctionProperties = sourceOptions.respectFunctionProperties === false ? false : true;\n options.unorderedArrays = sourceOptions.unorderedArrays !== true ? false : true; // default to false\n options.unorderedSets = sourceOptions.unorderedSets === false ? false : true; // default to false\n options.unorderedObjects = sourceOptions.unorderedObjects === false ? false : true; // default to true\n options.replacer = sourceOptions.replacer || undefined;\n options.excludeKeys = sourceOptions.excludeKeys || undefined;\n\n if(typeof object === 'undefined') {\n throw new Error('Object argument required.');\n }\n\n // if there is a case-insensitive match in the hashes list, accept it\n // (i.e. SHA256 for sha256)\n for (var i = 0; i < hashes.length; ++i) {\n if (hashes[i].toLowerCase() === options.algorithm.toLowerCase()) {\n options.algorithm = hashes[i];\n }\n }\n\n if(hashes.indexOf(options.algorithm) === -1){\n throw new Error('Algorithm \"' + options.algorithm + '\" not supported. ' +\n 'supported values: ' + hashes.join(', '));\n }\n\n if(encodings.indexOf(options.encoding) === -1 &&\n options.algorithm !== 'passthrough'){\n throw new Error('Encoding \"' + options.encoding + '\" not supported. ' +\n 'supported values: ' + encodings.join(', '));\n }\n\n return options;\n}\n\n/** Check if the given function is a native function */\nfunction isNativeFunction(f) {\n if ((typeof f) !== 'function') {\n return false;\n }\n var exp = /^function\\s+\\w*\\s*\\(\\s*\\)\\s*{\\s+\\[native code\\]\\s+}$/i;\n return exp.exec(Function.prototype.toString.call(f)) != null;\n}\n\nfunction hash(object, options) {\n var hashingStream;\n\n if (options.algorithm !== 'passthrough') {\n hashingStream = crypto.createHash(options.algorithm);\n } else {\n hashingStream = new PassThrough();\n }\n\n if (typeof hashingStream.write === 'undefined') {\n hashingStream.write = hashingStream.update;\n hashingStream.end = hashingStream.update;\n }\n\n var hasher = typeHasher(options, hashingStream);\n hasher.dispatch(object);\n if (!hashingStream.update) {\n hashingStream.end('');\n }\n\n if (hashingStream.digest) {\n return hashingStream.digest(options.encoding === 'buffer' ? undefined : options.encoding);\n }\n\n var buf = hashingStream.read();\n if (options.encoding === 'buffer') {\n return buf;\n }\n\n return buf.toString(options.encoding);\n}\n\n/**\n * Expose streaming API\n *\n * @param {object} object Value to serialize\n * @param {object} options Options, as for hash()\n * @param {object} stream A stream to write the serializiation to\n * @api public\n */\nexports.writeToStream = function(object, options, stream) {\n if (typeof stream === 'undefined') {\n stream = options;\n options = {};\n }\n\n options = applyDefaults(object, options);\n\n return typeHasher(options, stream).dispatch(object);\n};\n\nfunction typeHasher(options, writeTo, context){\n context = context || [];\n var write = function(str) {\n if (writeTo.update) {\n return writeTo.update(str, 'utf8');\n } else {\n return writeTo.write(str, 'utf8');\n }\n };\n\n return {\n dispatch: function(value){\n if (options.replacer) {\n value = options.replacer(value);\n }\n\n var type = typeof value;\n if (value === null) {\n type = 'null';\n }\n\n //console.log(\"[DEBUG] Dispatch: \", value, \"->\", type, \" -> \", \"_\" + type);\n\n return this['_' + type](value);\n },\n _object: function(object) {\n var pattern = (/\\[object (.*)\\]/i);\n var objString = Object.prototype.toString.call(object);\n var objType = pattern.exec(objString);\n if (!objType) { // object type did not match [object ...]\n objType = 'unknown:[' + objString + ']';\n } else {\n objType = objType[1]; // take only the class name\n }\n\n objType = objType.toLowerCase();\n\n var objectNumber = null;\n\n if ((objectNumber = context.indexOf(object)) >= 0) {\n return this.dispatch('[CIRCULAR:' + objectNumber + ']');\n } else {\n context.push(object);\n }\n\n if (typeof Buffer !== 'undefined' && Buffer.isBuffer && Buffer.isBuffer(object)) {\n write('buffer:');\n return write(object);\n }\n\n if(objType !== 'object' && objType !== 'function' && objType !== 'asyncfunction') {\n if(this['_' + objType]) {\n this['_' + objType](object);\n } else if (options.ignoreUnknown) {\n return write('[' + objType + ']');\n } else {\n throw new Error('Unknown object type \"' + objType + '\"');\n }\n }else{\n var keys = Object.keys(object);\n if (options.unorderedObjects) {\n keys = keys.sort();\n }\n // Make sure to incorporate special properties, so\n // Types with different prototypes will produce\n // a different hash and objects derived from\n // different functions (`new Foo`, `new Bar`) will\n // produce different hashes.\n // We never do this for native functions since some\n // seem to break because of that.\n if (options.respectType !== false && !isNativeFunction(object)) {\n keys.splice(0, 0, 'prototype', '__proto__', 'constructor');\n }\n\n if (options.excludeKeys) {\n keys = keys.filter(function(key) { return !options.excludeKeys(key); });\n }\n\n write('object:' + keys.length + ':');\n var self = this;\n return keys.forEach(function(key){\n self.dispatch(key);\n write(':');\n if(!options.excludeValues) {\n self.dispatch(object[key]);\n }\n write(',');\n });\n }\n },\n _array: function(arr, unordered){\n unordered = typeof unordered !== 'undefined' ? unordered :\n options.unorderedArrays !== false; // default to options.unorderedArrays\n\n var self = this;\n write('array:' + arr.length + ':');\n if (!unordered || arr.length <= 1) {\n return arr.forEach(function(entry) {\n return self.dispatch(entry);\n });\n }\n\n // the unordered case is a little more complicated:\n // since there is no canonical ordering on objects,\n // i.e. {a:1} < {a:2} and {a:1} > {a:2} are both false,\n // we first serialize each entry using a PassThrough stream\n // before sorting.\n // also: we can’t use the same context array for all entries\n // since the order of hashing should *not* matter. instead,\n // we keep track of the additions to a copy of the context array\n // and add all of them to the global context array when we’re done\n var contextAdditions = [];\n var entries = arr.map(function(entry) {\n var strm = new PassThrough();\n var localContext = context.slice(); // make copy\n var hasher = typeHasher(options, strm, localContext);\n hasher.dispatch(entry);\n // take only what was added to localContext and append it to contextAdditions\n contextAdditions = contextAdditions.concat(localContext.slice(context.length));\n return strm.read().toString();\n });\n context = context.concat(contextAdditions);\n entries.sort();\n return this._array(entries, false);\n },\n _date: function(date){\n return write('date:' + date.toJSON());\n },\n _symbol: function(sym){\n return write('symbol:' + sym.toString());\n },\n _error: function(err){\n return write('error:' + err.toString());\n },\n _boolean: function(bool){\n return write('bool:' + bool.toString());\n },\n _string: function(string){\n write('string:' + string.length + ':');\n write(string.toString());\n },\n _function: function(fn){\n write('fn:');\n if (isNativeFunction(fn)) {\n this.dispatch('[native]');\n } else {\n this.dispatch(fn.toString());\n }\n\n if (options.respectFunctionNames !== false) {\n // Make sure we can still distinguish native functions\n // by their name, otherwise String and Function will\n // have the same hash\n this.dispatch(\"function-name:\" + String(fn.name));\n }\n\n if (options.respectFunctionProperties) {\n this._object(fn);\n }\n },\n _number: function(number){\n return write('number:' + number.toString());\n },\n _xml: function(xml){\n return write('xml:' + xml.toString());\n },\n _null: function() {\n return write('Null');\n },\n _undefined: function() {\n return write('Undefined');\n },\n _regexp: function(regex){\n return write('regex:' + regex.toString());\n },\n _uint8array: function(arr){\n write('uint8array:');\n return this.dispatch(Array.prototype.slice.call(arr));\n },\n _uint8clampedarray: function(arr){\n write('uint8clampedarray:');\n return this.dispatch(Array.prototype.slice.call(arr));\n },\n _int8array: function(arr){\n write('int8array:');\n return this.dispatch(Array.prototype.slice.call(arr));\n },\n _uint16array: function(arr){\n write('uint16array:');\n return this.dispatch(Array.prototype.slice.call(arr));\n },\n _int16array: function(arr){\n write('int16array:');\n return this.dispatch(Array.prototype.slice.call(arr));\n },\n _uint32array: function(arr){\n write('uint32array:');\n return this.dispatch(Array.prototype.slice.call(arr));\n },\n _int32array: function(arr){\n write('int32array:');\n return this.dispatch(Array.prototype.slice.call(arr));\n },\n _float32array: function(arr){\n write('float32array:');\n return this.dispatch(Array.prototype.slice.call(arr));\n },\n _float64array: function(arr){\n write('float64array:');\n return this.dispatch(Array.prototype.slice.call(arr));\n },\n _arraybuffer: function(arr){\n write('arraybuffer:');\n return this.dispatch(new Uint8Array(arr));\n },\n _url: function(url) {\n return write('url:' + url.toString(), 'utf8');\n },\n _map: function(map) {\n write('map:');\n var arr = Array.from(map);\n return this._array(arr, options.unorderedSets !== false);\n },\n _set: function(set) {\n write('set:');\n var arr = Array.from(set);\n return this._array(arr, options.unorderedSets !== false);\n },\n _file: function(file) {\n write('file:');\n return this.dispatch([file.name, file.size, file.type, file.lastModfied]);\n },\n _blob: function() {\n if (options.ignoreUnknown) {\n return write('[blob]');\n }\n\n throw Error('Hashing Blob objects is currently not supported\\n' +\n '(see https://github.com/puleos/object-hash/issues/26)\\n' +\n 'Use \"options.replacer\" or \"options.ignoreUnknown\"\\n');\n },\n _domwindow: function() { return write('domwindow'); },\n _bigint: function(number){\n return write('bigint:' + number.toString());\n },\n /* Node.js standard native objects */\n _process: function() { return write('process'); },\n _timer: function() { return write('timer'); },\n _pipe: function() { return write('pipe'); },\n _tcp: function() { return write('tcp'); },\n _udp: function() { return write('udp'); },\n _tty: function() { return write('tty'); },\n _statwatcher: function() { return write('statwatcher'); },\n _securecontext: function() { return write('securecontext'); },\n _connection: function() { return write('connection'); },\n _zlib: function() { return write('zlib'); },\n _context: function() { return write('context'); },\n _nodescript: function() { return write('nodescript'); },\n _httpparser: function() { return write('httpparser'); },\n _dataview: function() { return write('dataview'); },\n _signal: function() { return write('signal'); },\n _fsevent: function() { return write('fsevent'); },\n _tlswrap: function() { return write('tlswrap'); },\n };\n}\n\n// Mini-implementation of stream.PassThrough\n// We are far from having need for the full implementation, and we can\n// make assumptions like \"many writes, then only one final read\"\n// and we can ignore encoding specifics\nfunction PassThrough() {\n return {\n buf: '',\n\n write: function(b) {\n this.buf += b;\n },\n\n end: function(b) {\n this.buf += b;\n },\n\n read: function() {\n return this.buf;\n }\n };\n}\n","/**\n * Custom Schema Fetcher\n *\n * Fetches custom schema definitions (field metadata as JSON) from the CMS API\n * for a given website. Uses the tRPC client to call the customSchema router.\n */\n\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport type { FieldDefinition } from '@repo/cms-schema/documents';\nimport { generateCombinedZodSchemaCode, generateZodSchemaCode, rehydrateSchema } from '@repo/cms-schema/documents';\nimport type { ZodObject, ZodRawShape } from 'zod';\nimport { type CmsConfig, getCmsClient } from './cms-api';\n\nexport interface CustomSchemaFields {\n name: string;\n displayName: string;\n description: string | null;\n fields: FieldDefinition[];\n routeSlugField: string | null;\n version: number;\n}\n\nexport type FetchCustomSchemasOptions = CmsConfig & { websiteId: string };\n\n/**\n * Fetches all custom schemas with their field definitions for a website.\n *\n * @example\n * ```ts\n * const schemas = await fetchAllCustomSchemaFields({\n * cmsUrl: 'http://localhost:3000',\n * apiKey: 'my-api-key',\n * websiteId: 'uuid-here',\n * });\n *\n * for (const schema of schemas) {\n * console.log(schema.name, schema.fields);\n * }\n * ```\n */\nexport async function fetchAllCustomSchemaFields(\n options: FetchCustomSchemasOptions\n): Promise<CustomSchemaFields[]> {\n const { websiteId } = options;\n\n const client = getCmsClient(options);\n\n // Get the list of all custom schemas (summaries only)\n const summaries = await client.customSchema.list.query({\n websiteId,\n includeSystem: false,\n });\n\n // Fetch full field definitions for each schema in parallel\n const schemas = await Promise.all(\n summaries.map(async (summary) => {\n const detail = await client.customSchema.getByName.query({\n websiteId,\n name: summary.name,\n });\n\n return {\n name: detail.name,\n displayName: detail.displayName,\n description: detail.description ?? null,\n fields: detail.fields,\n routeSlugField: detail.routeSlugField ?? null,\n version: detail.version,\n } satisfies CustomSchemaFields;\n })\n );\n\n return schemas;\n}\n\n/**\n * Fetches a single custom schema's field definitions by name.\n *\n * @example\n * ```ts\n * const schema = await fetchCustomSchemaFields({\n * cmsUrl: 'http://localhost:3000',\n * apiKey: 'my-api-key',\n * websiteId: 'uuid-here',\n * }, 'blog_post');\n *\n * console.log(schema.fields);\n * ```\n */\nexport async function fetchCustomSchemaFields(\n options: FetchCustomSchemasOptions,\n schemaName: string\n): Promise<CustomSchemaFields> {\n const { websiteId } = options;\n const client = getCmsClient(options);\n\n const detail = await client.customSchema.getByName.query({\n websiteId,\n name: schemaName,\n });\n\n return {\n name: detail.name,\n displayName: detail.displayName,\n description: detail.description ?? null,\n fields: detail.fields,\n routeSlugField: detail.routeSlugField ?? null,\n version: detail.version,\n };\n}\n\n/**\n * Converts an array of custom schema definitions into a record of Zod schemas,\n * keyed by schema name.\n *\n * @example\n * ```ts\n * const schemas = await fetchAllCustomSchemaFields(options);\n * const zodSchemas = buildZodSchemas(schemas);\n *\n * // Validate a blog post document\n * const result = zodSchemas['blog_post'].safeParse(data);\n * ```\n */\nexport function buildZodSchemas(\n schemas: CustomSchemaFields[]\n): Record<string, ZodObject<ZodRawShape>> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- avoids excessively deep type instantiation from Zod generics\n const result: Record<string, any> = {};\n\n for (const schema of schemas) {\n result[schema.name] = rehydrateSchema(schema.fields);\n }\n\n return result;\n}\n\n/**\n * Converts an array of custom schema definitions into a record of Zod source\n * code strings, keyed by schema name.\n *\n * @example\n * ```ts\n * const schemas = await fetchAllCustomSchemaFields(options);\n * const codeMap = buildZodSchemaCode(schemas);\n *\n * // Write blog_post schema to a file\n * fs.writeFileSync('blog-post.ts', codeMap['blog_post']);\n * ```\n */\nexport function buildZodSchemaCode(\n schemas: CustomSchemaFields[]\n): Record<string, string> {\n const result: Record<string, string> = {};\n\n for (const schema of schemas) {\n result[schema.name] = generateZodSchemaCode(schema.name, schema.fields);\n }\n\n return result;\n}\n\n/**\n * Generates combined Zod schema code from all custom schemas and writes it\n * to the specified file path.\n *\n * @param schemas - Array of custom schema definitions\n * @param filePath - Absolute or relative path to write the generated file\n */\nexport async function saveZodSchemaCode(\n schemas: CustomSchemaFields[],\n filePath: string\n): Promise<void> {\n if (schemas.length === 0) {\n console.warn('[saveZodSchemaCode] No schemas provided — skipping file write.');\n return;\n }\n\n const code = generateCombinedZodSchemaCode(schemas);\n\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, code, 'utf-8');\n}\n","/**\n * Document Schema Registry.\n *\n * Centralizes registration for all document schemas.\n * The CMS reads this registry to generate UI and validation.\n */\n\nimport { type ZodObject, type ZodRawShape, z } from 'zod';\nimport type { DocumentError } from '../db/document-types';\nimport { DocumentErrors } from '../db/document-types';\nimport type { TypedSupabaseClient } from '../db/types';\nimport type { Result } from '../types/errors';\nimport { err, ok } from '../types/errors';\n\n// =============================================================================\n// Validation Schemas\n// =============================================================================\n\n/**\n * Schema name validation - must be a non-empty string.\n */\nconst schemaNameValidator = z\n .string()\n .min(1, 'Schema name must be a non-empty string')\n .refine((name) => name.trim().length > 0, 'Schema name must not be only whitespace');\n\n/**\n * Runtime validator for document schema config.\n * Validates the config object structure at runtime.\n */\nconst documentSchemaConfigValidator = z.object({\n schema: z.custom<ZodObject<ZodRawShape>>(\n (val) => val !== null && typeof val === 'object' && '_def' in val,\n { message: 'schema must be a valid Zod schema' }\n ),\n titleField: z.string().optional(),\n displayName: z.string().optional(),\n description: z.string().optional(),\n validateContent: z.function().optional(),\n});\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Configuration for a registered document schema.\n */\nexport interface DocumentSchemaConfig<T extends ZodRawShape = ZodRawShape> {\n /** Zod schema for content validation */\n schema: ZodObject<T>;\n /** Field to extract for title (default: tries 'name', 'title', 'code') */\n titleField?: string;\n /** Display name for the schema in the UI */\n displayName?: string;\n /** Description of the document type */\n description?: string;\n /** Optional custom validation function for schema-specific rules */\n validateContent?: (content: unknown, supabase: TypedSupabaseClient) => Promise<void>;\n}\n\n/**\n * Registered schema with computed metadata.\n */\nexport interface RegisteredSchema<T extends ZodRawShape = ZodRawShape>\n extends DocumentSchemaConfig<T> {\n /** Schema name (registry key) */\n name: string;\n}\n\n// =============================================================================\n// Registry\n// =============================================================================\n\nconst documentRegistry = new Map<string, DocumentSchemaConfig>();\n\n/**\n * Register a document schema.\n *\n * @example\n * registerDocumentSchema('country', {\n * schema: CountrySchema,\n * titleField: 'name',\n * displayName: 'Country',\n * });\n *\n * @throws {Error} If schema name is empty or already registered\n */\nexport function registerDocumentSchema<T extends ZodRawShape>(\n name: string,\n config: DocumentSchemaConfig<T>\n): void {\n // Validate schema name using Zod\n const nameResult = schemaNameValidator.safeParse(name);\n if (!nameResult.success) {\n throw new Error(nameResult.error.issues.at(0)?.message ?? 'Invalid schema name');\n }\n\n // Validate config structure using Zod\n const configResult = documentSchemaConfigValidator.safeParse(config);\n if (!configResult.success) {\n throw new Error(\n `Invalid schema config: ${configResult.error.issues.at(0)?.message ?? 'Unknown error'}`\n );\n }\n\n // Check for duplicate registration\n if (documentRegistry.has(name)) {\n throw new Error(`Document schema \"${name}\" is already registered`);\n }\n\n documentRegistry.set(name, config as DocumentSchemaConfig);\n}\n\n/**\n * Get a document schema configuration by name.\n */\nexport function getDocumentSchema(name: string): DocumentSchemaConfig | undefined {\n return documentRegistry.get(name);\n}\n\n/**\n * Get all registered schema names.\n */\nexport function getRegisteredDocumentSchemas(): string[] {\n return Array.from(documentRegistry.keys());\n}\n\n/**\n * Get all registered schemas with their configurations.\n */\nexport function getAllDocumentSchemas(): RegisteredSchema[] {\n return Array.from(documentRegistry.entries()).map(([name, config]) => ({\n name,\n ...config,\n }));\n}\n\n/**\n * Clear the document registry (for testing).\n */\nexport function clearDocumentRegistry(): void {\n documentRegistry.clear();\n}\n\n// =============================================================================\n// Validation\n// =============================================================================\n\n/**\n * Validate document content against a registered schema.\n *\n * @returns Result with validated data or error\n */\nexport function validateDocumentContent<T>(\n schemaName: string,\n content: unknown\n): Result<T, DocumentError> {\n const config = documentRegistry.get(schemaName);\n\n if (!config) {\n return err(DocumentErrors.schemaNotFound(schemaName));\n }\n\n const result = config.schema.safeParse(content);\n\n if (!result.success) {\n const issues = result.error.issues.map((issue) => ({\n path: issue.path.filter((p): p is string | number => typeof p !== 'symbol'),\n message: issue.message,\n }));\n return err(DocumentErrors.validationError(issues));\n }\n\n return ok(result.data as T);\n}\n\n/**\n * Detailed validation result for UI display.\n */\nexport interface DocumentValidationResult<T> {\n valid: boolean;\n data?: T;\n issues?: Array<{ path: (string | number)[]; message: string }>;\n}\n\n/**\n * Validate document content with detailed error info for UI.\n */\nexport function validateDocumentContentDetailed<T>(\n schemaName: string,\n content: unknown\n): DocumentValidationResult<T> {\n const config = documentRegistry.get(schemaName);\n\n if (!config) {\n return {\n valid: false,\n issues: [{ path: [], message: `Document schema not found: ${schemaName}` }],\n };\n }\n\n const result = config.schema.safeParse(content);\n\n if (!result.success) {\n return {\n valid: false,\n issues: result.error.issues.map((issue) => ({\n path: issue.path.filter((p): p is string | number => typeof p !== 'symbol'),\n message: issue.message,\n })),\n };\n }\n\n return { valid: true, data: result.data as T };\n}\n\n// =============================================================================\n// Title Extraction\n// =============================================================================\n\n/**\n * Extract title from document content based on schema configuration.\n *\n * Tries in order:\n * 1. Schema's configured titleField\n * 2. 'title' field\n * 3. 'name' field\n * 4. 'code' field\n * 5. 'Untitled'\n */\nexport function extractDocumentTitle(schemaName: string, content: Record<string, unknown>): string {\n const config = documentRegistry.get(schemaName);\n\n // Try configured title field first\n if (config?.titleField && content[config.titleField] !== undefined) {\n return String(content[config.titleField]);\n }\n\n // Fall back to common title fields\n if (content.title !== undefined) return String(content.title);\n if (content.name !== undefined) return String(content.name);\n if (content.code !== undefined) return String(content.code);\n\n return 'Untitled';\n}\n\n// =============================================================================\n// Schema Introspection\n// =============================================================================\n\n/**\n * Get field information from a registered schema for dynamic form generation.\n */\nexport interface SchemaFieldInfo {\n name: string;\n type: string;\n isOptional: boolean;\n required: boolean;\n isArray: boolean;\n description?: string;\n /** For enum types, the available values */\n enumValues?: string[];\n /** For array types, the item type */\n itemType?: string;\n /** For reference types, the referenced schema */\n refSchema?: string;\n /** Default value if the field has one */\n defaultValue?: unknown;\n /** Whether this field has a default value */\n hasDefault?: boolean;\n}\n\n/**\n * Extract field info from a document schema for UI generation.\n */\nexport function getSchemaFields(schemaName: string): SchemaFieldInfo[] {\n const config = documentRegistry.get(schemaName);\n if (!config) return [];\n\n const shape = config.schema.shape;\n const fields: SchemaFieldInfo[] = [];\n\n for (const [name, zodType] of Object.entries(shape)) {\n const typeDef = zodType as z.ZodTypeAny;\n const isOptional = typeDef.isOptional();\n const fieldType = getFieldType(typeDef);\n const isArray = isArrayType(typeDef);\n const { value: defaultValue, hasDefault } = getDefaultValue(typeDef);\n\n const fieldInfo: SchemaFieldInfo = {\n name,\n type: fieldType,\n isOptional,\n required: !isOptional && !hasDefault, // Field is not required if it has a default\n isArray,\n description: typeDef.description,\n defaultValue,\n hasDefault,\n };\n\n // Extract enum values if this is an enum type\n // Also check if we can extract enum values even if type wasn't detected as enum\n const enumValues = getEnumValues(typeDef);\n if (enumValues.length > 0) {\n fieldInfo.enumValues = enumValues;\n // If we found enum values but type wasn't detected as enum, fix the type\n if (fieldType !== 'enum') {\n fieldInfo.type = 'enum';\n }\n }\n\n // Extract array item info\n if (isArray) {\n const arrayInfo = getArrayItemInfo(typeDef);\n fieldInfo.itemType = arrayInfo.itemType;\n fieldInfo.refSchema = arrayInfo.refSchema;\n }\n\n fields.push(fieldInfo);\n }\n\n return fields;\n}\n\nfunction getFieldType(zodType: z.ZodTypeAny): string {\n const def = zodType._def;\n if (!def) return 'unknown';\n\n // Unwrap default to get the inner type\n // ZodDefault wraps the inner type, so we need to unwrap it first\n if ('typeName' in def && def.typeName === 'ZodDefault') {\n // ZodDefault has an innerType property\n if ('innerType' in def) {\n return getFieldType(def.innerType as z.ZodTypeAny);\n }\n // Fallback: try to access _def.innerType directly\n const innerDef = (def as unknown as { innerType?: { _def?: unknown } }).innerType;\n if (innerDef?._def) {\n return getFieldType(innerDef as z.ZodTypeAny);\n }\n }\n\n // Unwrap optional/nullable (ZodOptional, ZodNullable)\n if ('innerType' in def) {\n return getFieldType(def.innerType as z.ZodTypeAny);\n }\n\n // Handle common types\n if ('typeName' in def) {\n const typeName = def.typeName as string;\n switch (typeName) {\n case 'ZodString':\n return 'string';\n case 'ZodNumber':\n return 'number';\n case 'ZodBoolean':\n return 'boolean';\n case 'ZodArray':\n return 'array';\n case 'ZodObject':\n return 'object';\n case 'ZodEnum':\n return 'enum';\n default:\n return typeName.replace('Zod', '').toLowerCase();\n }\n }\n\n return 'unknown';\n}\n\nfunction isArrayType(zodType: z.ZodTypeAny): boolean {\n const def = zodType._def;\n if (!def) return false;\n\n // Unwrap default to get the inner type\n if ('typeName' in def && def.typeName === 'ZodDefault' && 'innerType' in def) {\n return isArrayType(def.innerType as z.ZodTypeAny);\n }\n\n // Check for array type\n if ('typeName' in def && def.typeName === 'ZodArray') {\n return true;\n }\n\n // Check inside optional/nullable\n if ('innerType' in def) {\n return isArrayType(def.innerType as z.ZodTypeAny);\n }\n\n return false;\n}\n\n/**\n * Extract default value from a Zod type.\n */\nfunction getDefaultValue(zodType: z.ZodTypeAny): { value?: unknown; hasDefault: boolean } {\n const def = zodType._def;\n if (!def) return { hasDefault: false };\n\n // Check for default value in ZodDefault\n if ('typeName' in def && def.typeName === 'ZodDefault') {\n if ('defaultValue' in def) {\n const defaultValue = def.defaultValue;\n // Default value can be a function or a value\n if (typeof defaultValue === 'function') {\n try {\n return { value: defaultValue(), hasDefault: true };\n } catch {\n return { hasDefault: false };\n }\n }\n return { value: defaultValue, hasDefault: true };\n }\n }\n\n // Unwrap optional/nullable to check inner type\n if ('innerType' in def) {\n return getDefaultValue(def.innerType as z.ZodTypeAny);\n }\n\n return { hasDefault: false };\n}\n\n/**\n * Extract enum values from a Zod enum type.\n */\nfunction getEnumValues(zodType: z.ZodTypeAny): string[] {\n const def = zodType._def;\n if (!def) return [];\n\n // Unwrap default to get the inner type\n if ('typeName' in def && def.typeName === 'ZodDefault') {\n // Try to access innerType\n if ('innerType' in def) {\n return getEnumValues(def.innerType as z.ZodTypeAny);\n }\n // Fallback: try to access _def.innerType directly\n const innerDef = (def as unknown as { innerType?: z.ZodTypeAny }).innerType;\n if (innerDef) {\n return getEnumValues(innerDef);\n }\n }\n\n // Unwrap optional/nullable\n if ('innerType' in def) {\n return getEnumValues(def.innerType as z.ZodTypeAny);\n }\n\n // Get enum values from ZodEnum\n if ('typeName' in def && def.typeName === 'ZodEnum') {\n if ('values' in def && Array.isArray(def.values)) {\n return def.values as string[];\n }\n }\n\n // Also check for values property directly (some Zod versions)\n if ('values' in def && Array.isArray(def.values)) {\n return def.values as string[];\n }\n\n return [];\n}\n\n/**\n * Extract array item type information.\n */\nfunction getArrayItemInfo(zodType: z.ZodTypeAny): { itemType: string; refSchema?: string } {\n const def = zodType._def;\n if (!def) return { itemType: 'unknown' };\n\n // Unwrap optional/nullable\n if ('innerType' in def) {\n return getArrayItemInfo(def.innerType as z.ZodTypeAny);\n }\n\n // Get array element type\n if ('type' in def) {\n const itemType = def.type as unknown as z.ZodTypeAny;\n const itemDef = itemType._def as unknown as Record<string, unknown>;\n\n // Check if it's a reference object (has _type, _ref, _schema)\n if (itemDef && 'typeName' in itemDef && itemDef.typeName === 'ZodObject') {\n if ('shape' in itemDef && typeof itemDef.shape === 'function') {\n const shape = (itemDef.shape as () => Record<string, z.ZodTypeAny>)();\n if ('_type' in shape && '_ref' in shape && '_schema' in shape) {\n // This is a reference type - try to get the schema from literal\n const schemaField = shape._schema;\n const schemaDef = schemaField?._def as unknown as Record<string, unknown> | undefined;\n if (schemaDef && 'value' in schemaDef) {\n return { itemType: 'reference', refSchema: schemaDef.value as string };\n }\n return { itemType: 'reference' };\n }\n }\n }\n\n return { itemType: getFieldType(itemType) };\n }\n\n return { itemType: 'unknown' };\n}\n","/**\n * Country Document Schema.\n *\n * Defines the structure for country documents.\n * Countries have a list of supported language codes.\n */\n\nimport { z } from 'zod';\n\n// Reference to a language document (backward pass for now, I will remove this when we figure out how to handle languages)\nconst LanguageReferenceSchema = z.object({\n _type: z.literal('reference'),\n _ref: z.string().uuid('Language reference must be a valid UUID'),\n _schema: z.literal('language'),\n});\n\n/**\n * Country schema with validation rules.\n *\n * @example\n * {\n * code: 'us',\n * name: 'United States',\n * flag: '🇺🇸',\n * languages: ['en', 'es']\n * }\n *\n * @example\n * {\n * code: 'sa',\n * name: 'Saudi Arabia',\n * flag: '🇸🇦',\n * languages: ['ar', 'en']\n * }\n */\nexport const CountrySchema = z.object({\n /** 2-letter ISO 3166-1 alpha-2 country code */\n code: z.string().length(2, 'Country code must be 2 characters'),\n\n /** English name of the country */\n name: z.string().min(1, 'Country name required'),\n\n /** Flag emoji (optional but recommended) */\n flag: z.string().optional(),\n\n /**\n * List of supported languages (at least one required).\n * Supports either:\n * - Language codes (new format)\n * - Document references to languages (legacy format for backward compatibility)\n */\n languages: z\n .array(\n z.union([z.string().length(2, 'Language code must be 2 characters'), LanguageReferenceSchema])\n )\n .min(1, 'At least one language required'),\n});\n\n/** TypeScript type inferred from schema */\nexport type Country = z.infer<typeof CountrySchema>;\n\n/** Schema name constant */\nexport const COUNTRY_SCHEMA_NAME = 'country';\n\n/** Display name for UI */\nexport const COUNTRY_DISPLAY_NAME = 'Country';\n\n/** Title field for list display */\nexport const COUNTRY_TITLE_FIELD = 'name';\n\n/**\n * Create a default country object.\n */\nexport function createDefaultCountry(): Country {\n return {\n code: '',\n name: '',\n flag: '',\n languages: [],\n };\n}\n","/**\n * Language Document Schema.\n *\n * Defines the structure for language documents.\n */\n\nimport { z } from 'zod';\n\n/**\n * Language schema with validation rules.\n *\n * @example\n * {\n * code: 'en',\n * name: 'English',\n * nativeName: 'English'\n * }\n *\n * @example\n * {\n * code: 'ar',\n * name: 'Arabic',\n * nativeName: 'العربية'\n * }\n */\nexport const LanguageSchema = z.object({\n /** 2-letter ISO 639-1 language code */\n code: z.string().length(2, 'Language code must be 2 characters'),\n\n /** English name of the language */\n name: z.string().min(1, 'Language name required'),\n\n /** Name in the language itself (optional but recommended) */\n nativeName: z.string().optional(),\n});\n\n/** TypeScript type inferred from schema */\nexport type Language = z.infer<typeof LanguageSchema>;\n\n/** Schema name constant */\nexport const LANGUAGE_SCHEMA_NAME = 'language';\n\n/** Display name for UI */\nexport const LANGUAGE_DISPLAY_NAME = 'Language';\n\n/** Title field for list display */\nexport const LANGUAGE_TITLE_FIELD = 'name';\n\n/**\n * Create a default language object.\n */\nexport function createDefaultLanguage(): Language {\n return {\n code: '',\n name: '',\n nativeName: '',\n };\n}\n","/**\n * Unified Schema Registry\n *\n * Merges system schemas (hardcoded in TypeScript) with custom schemas (stored as JSON in database).\n * Both types of schemas are served through the same API, making them indistinguishable to consumers.\n *\n * System schemas take precedence over custom schemas with the same name.\n * Custom schemas are cached with a TTL and can be invalidated.\n */\n\nimport { type ZodObject, type ZodRawShape, z } from 'zod';\nimport type { TypedSupabaseClient } from '../db/types';\nimport { rehydrateSchema } from './rehydration';\nimport { createSchemaHash } from './schema-hash';\nimport type { FieldDefinition } from './schema-types';\n\n/** Source of a schema definition */\nexport type SchemaSource = 'system' | 'custom';\n\ntype TitleCandidateFieldType = FieldDefinition['type'];\n\nconst titleCandidateFieldTypes = new Set<TitleCandidateFieldType>([\n 'string',\n 'enum',\n 'url',\n 'email',\n 'date',\n 'datetime',\n]);\n\nfunction inferTitleFieldFromZodSchema(schema: ZodObject<ZodRawShape>): string {\n const shape = schema.shape ?? {};\n const keys = Object.keys(shape);\n if (keys.includes('title')) return 'title';\n if (keys.includes('name')) return 'name';\n if (keys.includes('code')) return 'code';\n return keys[0] ?? 'title';\n}\n\nfunction resolveTitleFieldFromFields(options: {\n fields: FieldDefinition[];\n titleField?: string | null;\n routeSlugField?: string | null;\n}): string | undefined {\n const { fields, titleField, routeSlugField } = options;\n\n if (titleField) {\n return titleField;\n }\n\n const fieldMap = new Map(fields.map((f) => [f.name, f] as const));\n\n if (routeSlugField) {\n const slugField = fieldMap.get(routeSlugField);\n if (slugField && titleCandidateFieldTypes.has(slugField.type)) {\n return routeSlugField;\n }\n }\n\n for (const preferredName of ['title', 'name', 'code'] as const) {\n const preferred = fieldMap.get(preferredName);\n if (preferred && titleCandidateFieldTypes.has(preferred.type)) {\n return preferredName;\n }\n }\n\n const firstCandidate = fields.find((f) => titleCandidateFieldTypes.has(f.type));\n return firstCandidate?.name;\n}\n\n/** Unified schema configuration that works for both system and custom schemas */\nexport interface UnifiedSchemaConfig {\n /** Database ID (only present for custom schemas) */\n id?: string;\n name: string;\n schema: ZodObject<ZodRawShape>;\n displayName: string;\n description?: string;\n titleField: string;\n /** Field name to use as URL routing slug. Value is auto-copied to content.code on document save. */\n routeSlugField?: string;\n icon?: string;\n source: SchemaSource;\n version?: number;\n\n /** Optional custom validation (system schemas only) */\n validateContent?: (content: unknown, supabase: TypedSupabaseClient) => Promise<void>;\n}\n\n/** Summary info for listing schemas (without full Zod schema) */\nexport interface SchemaSummary {\n /** Database ID (only present for custom schemas) */\n id?: string;\n name: string;\n displayName: string;\n description?: string;\n icon?: string;\n source: SchemaSource;\n version?: number;\n /** Field name used for URL routing - if not set, URL routing may not work */\n routeSlugField?: string;\n}\n\n// In-memory storage\nconst systemSchemas = new Map<string, UnifiedSchemaConfig>();\nconst customSchemaCacheByWebsite = new Map<string, Map<string, UnifiedSchemaConfig>>();\nconst customSchemasCacheTimeByWebsite = new Map<string, number>();\n\nfunction cacheKeyForWebsite(websiteId?: string): string {\n return websiteId ?? '__all__';\n}\n\n/** Cache TTL in milliseconds (30 seconds) */\nconst CACHE_TTL_MS = 30_000;\n\n/**\n * Registers a system schema. Called at application startup.\n * System schemas cannot be overwritten and take precedence over custom schemas.\n *\n * @param name - Unique schema identifier (e.g., 'country', 'language')\n * @param config - Schema configuration without name and source\n * @throws If schema with name already registered\n */\nexport function registerSystemSchema(\n name: string,\n config: Omit<UnifiedSchemaConfig, 'name' | 'source' | 'titleField'> & { titleField?: string }\n): void {\n if (systemSchemas.has(name)) {\n throw new Error(`System schema \"${name}\" is already registered`);\n }\n\n systemSchemas.set(name, {\n ...config,\n name,\n titleField: config.titleField ?? inferTitleFieldFromZodSchema(config.schema),\n source: 'system',\n });\n}\n\n/**\n * Gets a schema by name (system or custom).\n * System schemas are checked first, then custom schemas are loaded from cache/database.\n *\n * @param name - Schema name to look up\n * @param supabase - Database client for loading custom schemas\n * @returns Schema configuration or null if not found\n */\nexport async function getSchema(\n name: string,\n supabase: TypedSupabaseClient,\n websiteId?: string\n): Promise<UnifiedSchemaConfig | null> {\n // System schemas take precedence\n const systemSchema = systemSchemas.get(name);\n if (systemSchema) {\n return systemSchema;\n }\n\n // Load/refresh custom schemas if needed\n await loadCustomSchemas(supabase, websiteId);\n const scopedCache = customSchemaCacheByWebsite.get(cacheKeyForWebsite(websiteId));\n return scopedCache?.get(name) ?? null;\n}\n\n/**\n * Gets all registered schemas (system + active custom).\n *\n * @param supabase - Database client for loading custom schemas\n * @returns Array of all available schema configurations\n */\nexport async function getAllSchemas(\n supabase: TypedSupabaseClient,\n websiteId?: string\n): Promise<UnifiedSchemaConfig[]> {\n await loadCustomSchemas(supabase, websiteId);\n\n const scopedCache = customSchemaCacheByWebsite.get(cacheKeyForWebsite(websiteId));\n return [...systemSchemas.values(), ...(scopedCache?.values() ?? [])];\n}\n\n/**\n * Gets summary info for all schemas (without full Zod schemas).\n * Useful for sidebar/listing where full validation isn't needed.\n */\nexport async function getAllSchemaSummaries(\n supabase: TypedSupabaseClient,\n websiteId?: string\n): Promise<SchemaSummary[]> {\n const schemas = await getAllSchemas(supabase, websiteId);\n\n return schemas.map((s) => ({\n id: s.id,\n name: s.name,\n displayName: s.displayName,\n description: s.description,\n icon: s.icon,\n source: s.source,\n version: s.version,\n routeSlugField: s.routeSlugField,\n }));\n}\n\n/**\n * Loads custom schemas from database into cache.\n * Uses TTL-based caching to avoid excessive database queries.\n *\n * @param supabase - Database client\n * @param force - If true, bypasses cache TTL\n */\nasync function loadCustomSchemas(\n supabase: TypedSupabaseClient,\n websiteId?: string,\n force = false\n): Promise<void> {\n const now = Date.now();\n const key = cacheKeyForWebsite(websiteId);\n const cacheTime = customSchemasCacheTimeByWebsite.get(key) ?? null;\n\n // Use cache if valid and not forced\n if (!force && cacheTime && now - cacheTime < CACHE_TTL_MS) {\n return;\n }\n\n let query = supabase.from('custom_schemas').select('*').eq('state', 'active');\n if (websiteId) {\n query = query.eq('website_id', websiteId);\n }\n const { data, error } = await query;\n\n if (error) {\n console.error('Failed to load custom schemas:', error);\n // Keep stale cache on error rather than clearing\n return;\n }\n\n // Rebuild cache\n const scopedCache = new Map<string, UnifiedSchemaConfig>();\n\n for (const row of data ?? []) {\n try {\n const fields = row.fields as FieldDefinition[];\n const zodSchema = rehydrateSchema(fields);\n const resolvedTitleField = resolveTitleFieldFromFields({\n fields,\n titleField: row.title_field ?? undefined,\n routeSlugField: row.route_slug_field ?? undefined,\n });\n\n const hasExistingTitleField = fields.some((f) => f.name === 'title');\n const schemaWithResolvedTitle =\n resolvedTitleField === undefined && !hasExistingTitleField\n ? zodSchema.extend({ title: z.string().optional() })\n : zodSchema;\n\n const finalTitleField =\n resolvedTitleField ?? (hasExistingTitleField ? 'title' : (fields[0]?.name ?? 'title'));\n\n scopedCache.set(row.name, {\n id: row.id,\n name: row.name,\n schema: schemaWithResolvedTitle,\n displayName: row.display_name,\n description: row.description ?? undefined,\n titleField: finalTitleField,\n routeSlugField: row.route_slug_field ?? undefined,\n icon: row.icon ?? undefined,\n source: 'custom',\n version: row.version,\n });\n } catch (err) {\n // Log but don't fail - skip invalid schemas\n console.error(`Failed to rehydrate schema \"${row.name}\":`, err);\n }\n }\n\n customSchemaCacheByWebsite.set(key, scopedCache);\n customSchemasCacheTimeByWebsite.set(key, now);\n}\n\n/**\n * Invalidates the custom schema cache.\n * Call this after creating, updating, or deleting custom schemas.\n */\nexport function invalidateCustomSchemaCache(websiteId?: string): void {\n if (!websiteId) {\n customSchemasCacheTimeByWebsite.clear();\n customSchemaCacheByWebsite.clear();\n return;\n }\n\n const key = cacheKeyForWebsite(websiteId);\n customSchemasCacheTimeByWebsite.delete(key);\n customSchemaCacheByWebsite.delete(key);\n}\n\n/**\n * Forces a reload of custom schemas from database.\n */\nexport async function refreshCustomSchemas(supabase: TypedSupabaseClient): Promise<void> {\n await loadCustomSchemas(supabase, undefined, true);\n}\n\n/**\n * Checks if a schema name is reserved (used by a system schema).\n */\nexport function isSystemSchema(name: string): boolean {\n return systemSchemas.has(name);\n}\n\n/**\n * Gets all system schema names.\n */\nexport function getSystemSchemaNames(): string[] {\n return [...systemSchemas.keys()];\n}\n\n/**\n * Clears all registrations. FOR TESTING ONLY.\n */\nexport function clearUnifiedRegistry(): void {\n systemSchemas.clear();\n customSchemaCacheByWebsite.clear();\n customSchemasCacheTimeByWebsite.clear();\n}\n\n/**\n * Creates a hash for a custom schema from its fields.\n * Used for tracking schema versions in documents.\n */\nexport function createCustomSchemaHash(fields: FieldDefinition[]): string {\n const zodSchema = rehydrateSchema(fields);\n return createSchemaHash(zodSchema);\n}\n","/**\n * Zod Schema Rehydration\n *\n * Converts JSON field definitions (stored in database) into runtime Zod schemas.\n * This enables custom schemas to be validated identically to system schemas.\n *\n * @example\n * ```typescript\n * const fields: FieldDefinition[] = [\n * { name: 'title', type: 'string', required: true, constraints: { minLength: 1 } },\n * { name: 'price', type: 'number', required: true, constraints: { min: 0 } },\n * ];\n * const schema = rehydrateSchema(fields);\n * // Equivalent to: z.object({ title: z.string().min(1), price: z.number().min(0) })\n * ```\n */\n\nimport { type ZodObject, type ZodRawShape, type ZodTypeAny, z } from 'zod';\nimport { ImageReferenceSchema } from '../fields/complex/media';\nimport { validateSafeRegex } from '../utils/safe-regex';\nimport type { FieldConstraints, FieldDefinition, FieldType } from './schema-types';\n\n/** Error thrown when field definition cannot be rehydrated */\nexport class RehydrationError extends Error {\n constructor(\n message: string,\n public readonly fieldName?: string,\n public readonly fieldType?: FieldType\n ) {\n super(message);\n this.name = 'RehydrationError';\n }\n}\n\n/**\n * Rehydrates a single field definition into a Zod schema\n */\nexport function rehydrateField(field: FieldDefinition): ZodTypeAny {\n try {\n let schema = createBaseSchema(field.type, field.constraints);\n\n if (!field.required) {\n schema = schema.optional();\n }\n\n return schema;\n } catch (err) {\n throw new RehydrationError(\n `Failed to rehydrate field \"${field.name}\": ${err instanceof Error ? err.message : 'Unknown error'}`,\n field.name,\n field.type\n );\n }\n}\n\n/**\n * Creates the base Zod schema for a given field type\n */\nfunction createBaseSchema(type: FieldType, constraints?: FieldConstraints): ZodTypeAny {\n switch (type) {\n case 'string':\n return applyStringConstraints(z.string(), constraints);\n\n case 'number':\n return applyNumberConstraints(z.number(), constraints);\n\n case 'boolean':\n return z.boolean();\n\n case 'image':\n return ImageReferenceSchema;\n\n case 'date':\n return z.string().date('Invalid date format. Expected YYYY-MM-DD');\n\n case 'datetime':\n return z\n .string()\n .datetime({ offset: true, message: 'Invalid datetime format. Expected ISO 8601' });\n\n case 'url':\n return applyStringConstraints(z.string().url('Invalid URL format'), constraints);\n\n case 'email':\n return applyStringConstraints(z.string().email('Invalid email format'), constraints);\n\n case 'enum': {\n const values = constraints?.enumValues;\n if (!values || values.length === 0) {\n throw new Error('Enum field requires at least one enumValues in constraints');\n }\n return z.enum(values as [string, ...string[]]);\n }\n\n case 'reference':\n // Reference fields store inline objects (the referenced schema's field values)\n return z.record(z.string(), z.unknown());\n\n case 'array': {\n const itemType = constraints?.arrayItemType ?? 'string';\n const itemSchema = createPrimitiveSchema(itemType);\n return applyArrayConstraints(z.array(itemSchema), constraints);\n }\n\n default:\n throw new Error(`Unknown field type: ${type}`);\n }\n}\n\n/**\n * Creates a Zod schema for primitive array item types\n */\nfunction createPrimitiveSchema(type: 'string' | 'number' | 'boolean'): ZodTypeAny {\n switch (type) {\n case 'string':\n return z.string();\n case 'number':\n return z.number();\n case 'boolean':\n return z.boolean();\n }\n}\n\n/**\n * Applies string-specific constraints to a Zod string schema\n */\nfunction applyStringConstraints(schema: z.ZodString, constraints?: FieldConstraints): z.ZodString {\n if (!constraints) return schema;\n\n // Validate minLength <= maxLength when both are set\n if (\n constraints.minLength !== undefined &&\n constraints.maxLength !== undefined &&\n constraints.minLength > constraints.maxLength\n ) {\n throw new Error(\n `Invalid string constraints: minLength (${constraints.minLength}) cannot be greater than maxLength (${constraints.maxLength})`\n );\n }\n\n let result = schema;\n\n if (constraints.minLength !== undefined) {\n result = result.min(\n constraints.minLength,\n `Must be at least ${constraints.minLength} characters`\n );\n }\n if (constraints.maxLength !== undefined) {\n result = result.max(\n constraints.maxLength,\n `Must be at most ${constraints.maxLength} characters`\n );\n }\n if (constraints.pattern) {\n // Validate pattern is safe (prevents ReDoS attacks)\n const safetyError = validateSafeRegex(constraints.pattern);\n if (safetyError) {\n throw new Error(safetyError);\n }\n try {\n result = result.regex(new RegExp(constraints.pattern), 'Invalid format');\n } catch {\n throw new Error(`Invalid regex pattern: ${constraints.pattern}`);\n }\n }\n\n return result;\n}\n\n/**\n * Applies number-specific constraints to a Zod number schema\n */\nfunction applyNumberConstraints(schema: z.ZodNumber, constraints?: FieldConstraints): z.ZodNumber {\n if (!constraints) return schema;\n\n // Validate min <= max when both are set\n if (\n constraints.min !== undefined &&\n constraints.max !== undefined &&\n constraints.min > constraints.max\n ) {\n throw new Error(\n `Invalid number constraints: min (${constraints.min}) cannot be greater than max (${constraints.max})`\n );\n }\n\n let result = schema;\n\n if (constraints.min !== undefined) {\n result = result.min(constraints.min, `Must be at least ${constraints.min}`);\n }\n if (constraints.max !== undefined) {\n result = result.max(constraints.max, `Must be at most ${constraints.max}`);\n }\n if (constraints.integer) {\n result = result.int('Must be an integer');\n }\n\n return result;\n}\n\n/**\n * Applies array-specific constraints to a Zod array schema\n */\nfunction applyArrayConstraints(\n schema: z.ZodArray<ZodTypeAny>,\n constraints?: FieldConstraints\n): z.ZodArray<ZodTypeAny> {\n if (!constraints) return schema;\n\n // Validate minItems <= maxItems when both are set\n if (\n constraints.minItems !== undefined &&\n constraints.maxItems !== undefined &&\n constraints.minItems > constraints.maxItems\n ) {\n throw new Error(\n `Invalid array constraints: minItems (${constraints.minItems}) cannot be greater than maxItems (${constraints.maxItems})`\n );\n }\n\n let result = schema;\n\n if (constraints.minItems !== undefined) {\n result = result.min(constraints.minItems, `Must have at least ${constraints.minItems} items`);\n }\n if (constraints.maxItems !== undefined) {\n result = result.max(constraints.maxItems, `Must have at most ${constraints.maxItems} items`);\n }\n\n return result;\n}\n\n/**\n * Rehydrates a complete custom schema from field definitions into a Zod object schema\n *\n * @param fields - Array of field definitions from database\n * @returns Zod object schema that validates documents\n * @throws RehydrationError if any field cannot be rehydrated\n *\n * @example\n * ```typescript\n * const fields = [\n * { name: 'model', type: 'string', required: true },\n * { name: 'price', type: 'number', required: false },\n * ];\n * const schema = rehydrateSchema(fields);\n * schema.parse({ model: 'MacBook Pro' }); // Valid\n * schema.parse({ model: 'MacBook Pro', price: 1999 }); // Valid\n * schema.parse({ price: 1999 }); // Throws - model is required\n * ```\n */\nexport function rehydrateSchema(fields: FieldDefinition[]): ZodObject<ZodRawShape> {\n if (!Array.isArray(fields) || fields.length === 0) {\n throw new RehydrationError('Schema must have at least one field');\n }\n\n const shape: Record<string, ZodTypeAny> = {};\n const seenNames = new Set<string>();\n\n for (const field of fields) {\n // Validate field name uniqueness\n if (seenNames.has(field.name)) {\n throw new RehydrationError(`Duplicate field name: \"${field.name}\"`);\n }\n seenNames.add(field.name);\n\n // Validate field name format\n if (!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(field.name)) {\n throw new RehydrationError(\n `Invalid field name \"${field.name}\": must start with a letter and contain only alphanumeric characters and underscores`,\n field.name\n );\n }\n\n shape[field.name] = rehydrateField(field);\n }\n\n return z.object(shape);\n}\n\n/**\n * Validates that field definitions can be rehydrated without actually building the schema.\n * Useful for pre-validation before database insertion.\n *\n * @returns null if valid, error message if invalid\n */\nexport function validateFieldDefinitions(fields: FieldDefinition[]): string | null {\n try {\n rehydrateSchema(fields);\n return null;\n } catch (err) {\n return err instanceof Error ? err.message : 'Unknown validation error';\n }\n}\n","/**\n * Image and file field factories.\n *\n * The image() factory creates an ImageReference schema that:\n * - References an ImageAsset by ID\n * - Stores context-specific alt text (required for accessibility)\n * - Supports optional hotspot (focal point) and crop settings\n */\n\nimport { z } from 'zod';\n\nimport type { FieldMeta } from '../../types';\nimport {\n DimensionSchema,\n FileSizeSchema,\n MAX_DIMENSION,\n MAX_FILE_SIZE,\n MIN_DIMENSION,\n MimeTypeSchema,\n} from '../../validation/image';\n\n// =============================================================================\n// ImageAsset Schema (Public API type)\n// =============================================================================\n\n/**\n * Public API schema for image assets.\n *\n * This is the camelCase API representation. The database uses snake_case\n * (ImageAssetRow in db/image-asset-types.ts). Conversion between formats\n * should happen at the API boundary.\n *\n * Reuses validation schemas from validation/image.ts to ensure consistency.\n */\nexport const ImageAssetSchema = z.object({\n /** UUID primary key */\n id: z.uuid(),\n /** R2/S3 storage URL for the original file */\n url: z.url(),\n /** Image width in pixels */\n width: DimensionSchema,\n /** Image height in pixels */\n height: DimensionSchema,\n /** Original filename from upload */\n originalFilename: z.string().min(1).max(255),\n /** MIME type (only web-safe formats allowed) */\n mimeType: MimeTypeSchema,\n /** File size in bytes */\n fileSize: FileSizeSchema,\n /** Base64-encoded tiny preview for blur-up loading */\n lqip: z.string().optional(),\n});\n\nexport type ImageAsset = z.infer<typeof ImageAssetSchema>;\n\n// =============================================================================\n// ImageReference Schema (Asset-reference model)\n// =============================================================================\n\n/**\n * Hotspot defines the focal point of an image.\n * Coordinates are fractions (0-1) from top-left.\n */\nexport const HotspotSchema = z.object({\n x: z.number().min(0).max(1),\n y: z.number().min(0).max(1),\n});\n\nexport type Hotspot = z.infer<typeof HotspotSchema>;\n\n/**\n * Crop defines the region to extract from the image.\n * - x, y: Top-left coordinate of the crop region in pixels\n * - width, height: Size of the crop region in pixels\n * All values are positive integers representing pixel coordinates/dimensions.\n */\nexport const CropSchema = z.object({\n /** X coordinate of top-left corner in pixels */\n x: z.number().int().nonnegative(),\n /** Y coordinate of top-left corner in pixels */\n y: z.number().int().nonnegative(),\n /** Width of crop region in pixels (must be > 0) */\n width: z.number().int().positive(),\n /** Height of crop region in pixels (must be > 0) */\n height: z.number().int().positive(),\n});\n\nexport type Crop = z.infer<typeof CropSchema>;\n\n/**\n * ImageReference is what blocks store.\n * It points to an ImageAsset and adds context-specific metadata.\n */\nexport const ImageReferenceSchema = z.object({\n // Alt text is REQUIRED for accessibility\n alt: z.string().min(1, 'Alt text is required for accessibility'),\n\n // Optional metadata\n caption: z.string().max(500).optional(),\n attribution: z.string().max(255).optional(),\n\n // Reference to the ImageAsset with stored transformation\n _asset: z.object({\n id: z.uuid(),\n transformation: z.string().nullable().optional(),\n }),\n});\n\nexport type ImageReference = z.infer<typeof ImageReferenceSchema>;\n\n// =============================================================================\n// Image Field Factory\n// =============================================================================\n\nexport interface ImageFieldOptions {\n label: string;\n description?: string;\n required?: boolean;\n accept?: string;\n maxSize?: number;\n minWidth?: number;\n minHeight?: number;\n maxWidth?: number;\n maxHeight?: number;\n aspectRatio?: number;\n}\n\n/**\n * Create an image field with metadata.\n *\n * @example\n * const featuredImage = image({\n * label: 'Featured Image',\n * required: true,\n * accept: 'image/jpeg, image/png',\n * maxSize: 5 * 1024 * 1024,\n * });\n *\n * // Type of the value:\n * // {\n * // alt: string;\n * // caption?: string;\n * // attribution?: string;\n * // _asset: { id: string; transformation?: string | null };\n * // }\n */\nexport function image(options: ImageFieldOptions) {\n const meta: FieldMeta = {\n label: options.label,\n component: 'image-uploader',\n required: options.required,\n description: options.description,\n options: {\n accept: options.accept ?? 'image/jpeg, image/png, image/webp',\n maxSize: options.maxSize ?? MAX_FILE_SIZE, // 10MB default\n minWidth: options.minWidth ?? MIN_DIMENSION,\n minHeight: options.minHeight ?? MIN_DIMENSION,\n maxWidth: options.maxWidth ?? MAX_DIMENSION,\n maxHeight: options.maxHeight ?? MAX_DIMENSION,\n aspectRatio: options.aspectRatio,\n },\n };\n\n // Use the new ImageReferenceSchema instead of URL-only\n const result = options.required ? ImageReferenceSchema : ImageReferenceSchema.optional();\n\n return result.meta(meta);\n}\n\n// =============================================================================\n// File Field\n// =============================================================================\n\nexport interface FileFieldOptions {\n label: string;\n description?: string;\n required?: boolean;\n accept?: string;\n maxSize?: number;\n}\n\nconst fileSchema = z.object({\n url: z.url(),\n name: z.string(),\n size: z.number().int().positive(),\n type: z.string(),\n});\n\n/**\n * Create a file field with metadata.\n */\nexport function file(options: FileFieldOptions) {\n const meta: FieldMeta = {\n label: options.label,\n component: 'file-uploader',\n required: options.required,\n description: options.description,\n options: {\n accept: options.accept ?? '*/*',\n maxSize: options.maxSize,\n },\n };\n\n const result = options.required ? fileSchema : fileSchema.optional();\n return result.meta(meta);\n}\n","/**\n * Image Validation Utilities\n *\n * Provides validation for:\n * - File type (MIME type checking)\n * - File size (configurable limits)\n * - Image dimensions (width/height constraints)\n */\n\nimport { z } from 'zod';\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nexport const ALLOWED_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp'] as const;\nexport type ImageMimeType = (typeof ALLOWED_MIME_TYPES)[number];\n\nexport const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB\nexport const MIN_FILE_SIZE = 1024; // 1KB (avoid empty/corrupt files)\n\nexport const MAX_DIMENSION = 8192; // 8K resolution\nexport const MIN_DIMENSION = 10; // Minimum useful size\n\n// =============================================================================\n// Zod Schemas\n// =============================================================================\n\nexport const MimeTypeSchema = z.enum(ALLOWED_MIME_TYPES);\n\nexport const FileSizeSchema = z\n .number()\n .int()\n .min(MIN_FILE_SIZE, `File too small. Minimum: ${MIN_FILE_SIZE} bytes`)\n .max(MAX_FILE_SIZE, `File too large. Maximum: ${MAX_FILE_SIZE / 1024 / 1024}MB`);\n\nexport const DimensionSchema = z\n .number()\n .int()\n .min(MIN_DIMENSION, `Dimension too small. Minimum: ${MIN_DIMENSION}px`)\n .max(MAX_DIMENSION, `Dimension too large. Maximum: ${MAX_DIMENSION}px`);\n\n/**\n * Schema for upload request validation.\n */\nexport const UploadRequestSchema = z.object({\n filename: z\n .string()\n .min(1, 'Filename is required')\n .max(255, 'Filename too long')\n .regex(/^[^<>:\"/\\\\|?*]+$/, 'Filename contains invalid characters'),\n mimeType: MimeTypeSchema,\n fileSize: FileSizeSchema,\n});\n\nexport type UploadRequest = z.infer<typeof UploadRequestSchema>;\n\n/**\n * Schema for confirming upload with dimensions.\n * assetId is optional - if not provided, the server will generate a UUID.\n */\nexport const ConfirmUploadSchema = z.object({\n assetId: z.uuid().optional(),\n width: DimensionSchema,\n height: DimensionSchema,\n});\n\nexport type ConfirmUpload = z.infer<typeof ConfirmUploadSchema>;\n\n// =============================================================================\n// Validation Functions\n// =============================================================================\n\nexport interface ValidationResult {\n valid: boolean;\n error?: string;\n}\n\n/**\n * Validate file type by MIME type.\n */\nexport function validateMimeType(mimeType: string): ValidationResult {\n const result = MimeTypeSchema.safeParse(mimeType);\n if (result.success) {\n return { valid: true };\n }\n return {\n valid: false,\n error: `File type not supported. Use JPEG, PNG, or WebP.`,\n };\n}\n\n/**\n * Validate file size.\n */\nexport function validateFileSize(size: number): ValidationResult {\n if (size < MIN_FILE_SIZE) {\n return {\n valid: false,\n error: `File appears to be empty or corrupt.`,\n };\n }\n if (size > MAX_FILE_SIZE) {\n const sizeMB = (size / 1024 / 1024).toFixed(1);\n return {\n valid: false,\n error: `File too large (${sizeMB}MB). Maximum: 10 MB.`,\n };\n }\n return { valid: true };\n}\n\n/**\n * Validate image dimensions.\n */\nexport function validateDimensions(width: number, height: number): ValidationResult {\n if (width < MIN_DIMENSION || height < MIN_DIMENSION) {\n return {\n valid: false,\n error: `Image too small. Minimum: ${MIN_DIMENSION}x${MIN_DIMENSION}px.`,\n };\n }\n if (width > MAX_DIMENSION || height > MAX_DIMENSION) {\n return {\n valid: false,\n error: `Image too large. Maximum: ${MAX_DIMENSION}x${MAX_DIMENSION}px.`,\n };\n }\n return { valid: true };\n}\n\n/**\n * Validate complete upload request.\n */\nexport function validateUploadRequest(\n request: unknown\n): { valid: true; data: UploadRequest } | { valid: false; error: string } {\n const result = UploadRequestSchema.safeParse(request);\n if (result.success) {\n return { valid: true, data: result.data };\n }\n const firstIssue = result.error.issues[0];\n return {\n valid: false,\n error: firstIssue?.message ?? 'Invalid upload request',\n };\n}\n\n// =============================================================================\n// File Extension Utilities\n// =============================================================================\n\nconst MIME_TO_EXT: Record<ImageMimeType, string> = {\n 'image/jpeg': 'jpg',\n 'image/png': 'png',\n 'image/webp': 'webp',\n};\n\nconst EXT_TO_MIME: Record<string, ImageMimeType> = {\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n webp: 'image/webp',\n};\n\n/**\n * Get file extension from MIME type.\n */\nexport function getExtensionFromMime(mimeType: ImageMimeType | string): string {\n return MIME_TO_EXT[mimeType as ImageMimeType] ?? 'bin';\n}\n\n/**\n * Get MIME type from file extension.\n */\nexport function getMimeFromExtension(ext: string): ImageMimeType | undefined {\n return EXT_TO_MIME[ext.toLowerCase()];\n}\n\n/**\n * Extract extension from filename.\n */\nexport function getExtensionFromFilename(filename: string): string {\n const parts = filename.split('.');\n return parts.pop()?.toLowerCase?.() ?? '';\n}\n\n/**\n * Sanitize filename for storage.\n * Removes special characters, preserves extension.\n */\nexport function sanitizeFilename(filename: string): string {\n // Get extension\n const ext = getExtensionFromFilename(filename);\n\n // Get base name without extension\n const base = filename.slice(0, filename.length - ext.length - 1);\n\n // Sanitize: lowercase, replace spaces and special chars\n const sanitized = base\n .toLowerCase()\n .replace(/[^a-z0-9]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 50); // Limit length\n\n return ext ? `${sanitized}.${ext}` : sanitized;\n}\n","/**\n * Safe regex validation utilities.\n *\n * Prevents ReDoS (Regular Expression Denial of Service) attacks by\n * detecting potentially dangerous regex patterns.\n */\n\nimport safeRegex from 'safe-regex2';\n\n/**\n * Validates that a regex pattern is safe to use.\n * Uses safe-regex2 library to detect ReDoS vulnerabilities.\n *\n * @param pattern - The regex pattern to validate\n * @returns null if safe, error message if potentially dangerous\n */\nexport function validateSafeRegex(pattern: string): string | null {\n // Limit pattern length to prevent extremely long patterns\n if (pattern.length > 500) {\n return 'Regex pattern is too long (max 500 characters)';\n }\n\n // Use safe-regex2 to detect ReDoS vulnerabilities\n if (!safeRegex(pattern)) {\n return 'Regex pattern is potentially unsafe (ReDoS risk)';\n }\n\n // Try to compile the regex to ensure it's valid\n try {\n new RegExp(pattern);\n } catch (err) {\n return `Invalid regex: ${err instanceof Error ? err.message : 'Unknown'}`;\n }\n\n return null;\n}\n","/**\n * Schema hashing utility for document versioning.\n *\n * Creates a deterministic hash of a Zod schema's shape.\n * Used to detect when documents need migration after schema changes.\n */\n\nimport hash from 'object-hash';\nimport type { ZodObject, ZodRawShape, ZodTypeAny } from 'zod';\n\n/**\n * Unwraps optional, default, and nullable wrappers to get the inner type.\n */\nfunction unwrapZodType(zodType: ZodTypeAny): ZodTypeAny {\n const current = zodType;\n const def = current._def;\n\n // Unwrap optional/nullable/default wrappers\n if ('innerType' in def && def.innerType) {\n return unwrapZodType(def.innerType as ZodTypeAny);\n }\n\n return current;\n}\n\n/**\n * Gets the type name from a Zod type, unwrapping wrappers first.\n * In Zod v4, types are stored in _def.type (not typeName).\n */\nfunction getZodTypeName(zodType: ZodTypeAny): string {\n const unwrapped = unwrapZodType(zodType);\n const def = unwrapped._def;\n\n if (!def) return 'unknown';\n\n // Zod v4 uses _def.type for primitive types\n if ('type' in def && typeof def.type === 'string') {\n return def.type as string;\n }\n\n // Fallback: check for typeName (older Zod versions or complex types)\n if ('typeName' in def) {\n return def.typeName as string;\n }\n\n return 'unknown';\n}\n\n/**\n * Creates a deterministic hash of a Zod schema's shape.\n *\n * Uses object-hash library for canonical key ordering, ensuring\n * the same hash is produced regardless of property definition order.\n *\n * @param schema - A Zod object schema\n * @returns MD5 hash string of the schema shape\n */\nexport function createSchemaHash(schema: ZodObject<ZodRawShape>): string {\n const shape = schema.shape;\n\n // Create a serializable representation of the schema\n const schemaDefinition = Object.entries(shape).reduce(\n (acc, [key, zodType]) => {\n const typeName = getZodTypeName(zodType as ZodTypeAny);\n const unwrapped = unwrapZodType(zodType as ZodTypeAny);\n const unwrappedDef = unwrapped._def as unknown as Record<string, unknown>;\n\n // Check if optional (method exists on ZodTypeAny in Zod v4)\n const isOptional =\n 'isOptional' in zodType && typeof zodType.isOptional === 'function'\n ? zodType.isOptional()\n : false;\n\n acc[key] = {\n type: typeName,\n optional: isOptional,\n // Include nested shape for objects\n ...(typeName === 'object' &&\n 'shape' in unwrappedDef &&\n typeof unwrappedDef.shape === 'function' && {\n shape: Object.keys((unwrappedDef.shape as () => Record<string, unknown>)()),\n }),\n };\n return acc;\n },\n {} as Record<string, unknown>\n );\n\n return hash(schemaDefinition, {\n algorithm: 'md5',\n respectType: false,\n unorderedArrays: false,\n });\n}\n","/**\n * Country schema-specific validation.\n *\n * Validates that language codes exist in the database.\n */\n\nimport { TRPCError } from '@trpc/server';\nimport type { ReferenceValue } from '../../db/document-types';\nimport { isReference } from '../../db/document-types';\nimport type { TypedSupabaseClient } from '../../db/types';\n\n/**\n * Validate country content, specifically checking that language codes exist.\n *\n * @param content - Validated country content\n * @param supabase - Supabase client for database queries\n * @throws {TRPCError} If validation fails\n */\nexport async function validateCountryContent(\n content: unknown,\n supabase: TypedSupabaseClient\n): Promise<void> {\n const countryContent = content as {\n languages?: Array<string | ReferenceValue>;\n };\n const languages = Array.isArray(countryContent.languages) ? countryContent.languages : [];\n\n const languageCodes = languages.filter((lang): lang is string => typeof lang === 'string');\n const languageReferences = languages.filter(isReference);\n\n // Validate legacy reference format points to language schema\n const invalidReferences = languageReferences.filter((ref) => ref._schema !== 'language');\n if (invalidReferences.length > 0) {\n throw new TRPCError({\n code: 'BAD_REQUEST',\n message: 'Language references must target the language schema',\n });\n }\n\n // Only perform database check when using code-based languages\n if (languageCodes.length > 0) {\n const { data: allLanguages, error: langError } = await supabase\n .from('documents')\n .select('content')\n .eq('schema_name', 'language');\n\n if (langError) {\n throw new TRPCError({\n code: 'INTERNAL_SERVER_ERROR',\n message: 'Failed to validate language codes',\n cause: langError,\n });\n }\n\n const existingCodes = new Set(\n (allLanguages || [])\n .map((lang) => {\n const langContent = lang.content as { code?: string };\n return langContent?.code;\n })\n .filter((code): code is string => typeof code === 'string' && code.length > 0)\n );\n\n const missingCodes = languageCodes.filter((code) => !existingCodes.has(code));\n\n if (missingCodes.length > 0) {\n throw new TRPCError({\n code: 'BAD_REQUEST',\n message: `Language codes not found: ${missingCodes.join(', ')}. Please create language documents with these codes first.`,\n });\n }\n }\n}\n","/**\n * Zod Schema Code Generator\n *\n * Generates valid JavaScript/TypeScript Zod schema source code\n * from FieldDefinition[] (the same structure used by rehydration.ts at runtime).\n */\n\nimport type { FieldConstraints, FieldDefinition } from './schema-types';\n\n/**\n * Generates a complete Zod schema source code string from field definitions.\n *\n * @param schemaName - The schema name (used for the variable name)\n * @param fields - Array of field definitions\n * @returns Formatted Zod source code string\n */\nexport function generateZodSchemaCode(schemaName: string, fields: FieldDefinition[]): string {\n const lines: string[] = [];\n\n lines.push(`import { z } from 'zod';`);\n lines.push('');\n\n // Generate the ImageReference schema inline if any image fields exist\n const hasImageField = fields.some((f) => f.type === 'image');\n if (hasImageField) {\n appendImageReferenceSchema(lines);\n lines.push('');\n }\n\n appendSchemaBody(lines, schemaName, fields);\n\n return lines.join('\\n');\n}\n\n/**\n * Generates a single combined Zod schema source code file from multiple schema definitions.\n *\n * Produces one `import { z }`, one `ImageReferenceSchema` (if needed), then all schema exports.\n *\n * @param schemas - Array of schema definitions with name and fields\n * @returns Formatted Zod source code string for the combined file\n */\nexport function generateCombinedZodSchemaCode(\n schemas: Array<{ name: string; fields: FieldDefinition[] }>\n): string {\n const lines: string[] = [];\n\n lines.push(`import { z } from 'zod';`);\n lines.push('');\n\n // Emit ImageReferenceSchema once if any schema uses image fields\n const hasImageField = schemas.some((s) => s.fields.some((f) => f.type === 'image'));\n if (hasImageField) {\n appendImageReferenceSchema(lines);\n lines.push('');\n }\n\n for (let i = 0; i < schemas.length; i++) {\n const schema = schemas[i]!;\n if (i > 0) lines.push('');\n appendSchemaBody(lines, schema.name, schema.fields);\n }\n\n return lines.join('\\n');\n}\n\n/** Appends the z.object and type export lines for a single schema. */\nfunction appendSchemaBody(lines: string[], schemaName: string, fields: FieldDefinition[]): void {\n const varName = toCamelCase(schemaName) + 'Schema';\n\n lines.push(`export const ${varName} = z.object({`);\n\n for (const field of fields) {\n const fieldCode = generateFieldCode(field);\n if (field.description) {\n lines.push(` /** ${field.description} */`);\n }\n lines.push(` ${field.name}: ${fieldCode},`);\n }\n\n lines.push('});');\n lines.push('');\n lines.push(`export type ${toPascalCase(schemaName)} = z.infer<typeof ${varName}>;`);\n lines.push('');\n}\n\n/** Appends the ImageReferenceSchema constant. */\nfunction appendImageReferenceSchema(lines: string[]): void {\n lines.push('const ImageReferenceSchema = z.object({');\n lines.push(\" alt: z.string().min(1, 'Alt text is required for accessibility'),\");\n lines.push(' caption: z.string().max(500).optional(),');\n lines.push(' attribution: z.string().max(255).optional(),');\n lines.push(' _asset: z.object({');\n lines.push(' id: z.string().uuid(),');\n lines.push(' }),');\n lines.push('});');\n}\n\nfunction generateFieldCode(field: FieldDefinition): string {\n let code = generateBaseTypeCode(field.type, field.constraints);\n\n if (!field.required) {\n code += '.optional()';\n }\n\n return code;\n}\n\nfunction generateBaseTypeCode(type: FieldDefinition['type'], constraints?: FieldConstraints): string {\n switch (type) {\n case 'string':\n return applyStringConstraintCode('z.string()', constraints);\n\n case 'number':\n return applyNumberConstraintCode('z.number()', constraints);\n\n case 'boolean':\n return 'z.boolean()';\n\n case 'image':\n return 'ImageReferenceSchema';\n\n case 'date':\n return \"z.string().date('Invalid date format. Expected YYYY-MM-DD')\";\n\n case 'datetime':\n return \"z.string().datetime({ offset: true, message: 'Invalid datetime format. Expected ISO 8601' })\";\n\n case 'url':\n return applyStringConstraintCode(\"z.string().url('Invalid URL format')\", constraints);\n\n case 'email':\n return applyStringConstraintCode(\"z.string().email('Invalid email format')\", constraints);\n\n case 'enum': {\n const values = constraints?.enumValues;\n if (!values || values.length === 0) {\n return \"z.enum([''])\";\n }\n const formatted = values.map((v) => `'${escapeString(v)}'`).join(', ');\n return `z.enum([${formatted}])`;\n }\n\n case 'reference':\n return 'z.record(z.string(), z.unknown())';\n\n case 'array': {\n const itemType = constraints?.arrayItemType ?? 'string';\n const itemCode = generatePrimitiveCode(itemType);\n return applyArrayConstraintCode(`z.array(${itemCode})`, constraints);\n }\n\n default:\n return 'z.unknown()';\n }\n}\n\nfunction generatePrimitiveCode(type: 'string' | 'number' | 'boolean'): string {\n switch (type) {\n case 'string':\n return 'z.string()';\n case 'number':\n return 'z.number()';\n case 'boolean':\n return 'z.boolean()';\n }\n}\n\nfunction applyStringConstraintCode(base: string, constraints?: FieldConstraints): string {\n if (!constraints) return base;\n\n let code = base;\n if (constraints.minLength !== undefined) {\n code += `.min(${constraints.minLength}, 'Must be at least ${constraints.minLength} characters')`;\n }\n if (constraints.maxLength !== undefined) {\n code += `.max(${constraints.maxLength}, 'Must be at most ${constraints.maxLength} characters')`;\n }\n if (constraints.pattern) {\n code += `.regex(/${escapeRegex(constraints.pattern)}/, 'Invalid format')`;\n }\n return code;\n}\n\nfunction applyNumberConstraintCode(base: string, constraints?: FieldConstraints): string {\n if (!constraints) return base;\n\n let code = base;\n if (constraints.integer) {\n code += `.int('Must be an integer')`;\n }\n if (constraints.min !== undefined) {\n code += `.min(${constraints.min}, 'Must be at least ${constraints.min}')`;\n }\n if (constraints.max !== undefined) {\n code += `.max(${constraints.max}, 'Must be at most ${constraints.max}')`;\n }\n return code;\n}\n\nfunction applyArrayConstraintCode(base: string, constraints?: FieldConstraints): string {\n if (!constraints) return base;\n\n let code = base;\n if (constraints.minItems !== undefined) {\n code += `.min(${constraints.minItems}, 'Must have at least ${constraints.minItems} items')`;\n }\n if (constraints.maxItems !== undefined) {\n code += `.max(${constraints.maxItems}, 'Must have at most ${constraints.maxItems} items')`;\n }\n return code;\n}\n\nfunction escapeString(str: string): string {\n return str.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\nfunction escapeRegex(pattern: string): string {\n return pattern.replace(/\\//g, '\\\\/');\n}\n\nfunction toCamelCase(str: string): string {\n return str.replace(/_([a-z])/g, (_, c) => c.toUpperCase());\n}\n\nfunction toPascalCase(str: string): string {\n const camel = toCamelCase(str);\n return camel.charAt(0).toUpperCase() + camel.slice(1);\n}\n","/**\n * CMS API Client\n *\n * Creates an HTTP-based tRPC client for calling the CMS API.\n * Used in Server Components to fetch routes and blocks from the CMS.\n */\n\nimport type { AppRouter } from '@repo/cms-schema/trpc';\nimport { type CreateTRPCClient, createTRPCClient, httpBatchLink } from '@trpc/client';\nimport superjson from 'superjson';\n\n/** Type alias for the CMS API client */\ntype CmsClient = CreateTRPCClient<AppRouter>;\n\n/**\n * Get the CMS API URL from the provided base URL.\n */\nfunction getCmsApiUrl(cmsUrl: string): string {\n return new URL('/api/trpc', cmsUrl).toString();\n}\n\n/** Unified configuration for all CMS API access */\nexport interface CmsConfig {\n /** CMS API base URL (e.g., 'http://localhost:3000') */\n cmsUrl: string;\n /** API key for authentication */\n apiKey?: string;\n /** Website ID to scope API requests */\n websiteId?: string;\n}\n\n/**\n * Create a custom fetch function that appends API key as query parameter.\n */\nfunction createFetchWithApiKey(apiKey?: string, websiteId?: string) {\n return async (url: URL | RequestInfo, options?: RequestInit): Promise<Response> => {\n let finalUrl = url;\n\n const urlObj = new URL(url.toString());\n if (apiKey) {\n urlObj.searchParams.set('api_key', apiKey);\n }\n if (websiteId) {\n urlObj.searchParams.set('website_id', websiteId);\n }\n if (apiKey || websiteId) {\n finalUrl = urlObj.toString();\n }\n\n\n\n const response = await fetch(finalUrl, options);\n\n return response;\n };\n}\n\n/**\n * Create a tRPC client for the CMS API.\n */\nfunction createCmsClient(options: CmsConfig): CmsClient {\n const url = getCmsApiUrl(options.cmsUrl);\n\n return createTRPCClient<AppRouter>({\n links: [\n httpBatchLink({\n url,\n transformer: superjson,\n fetch: createFetchWithApiKey(options.apiKey, options.websiteId),\n }),\n ],\n });\n}\n\n/**\n * Get a CMS client for the specified CMS URL.\n */\nexport function getCmsClient(options: CmsConfig): CmsClient {\n return createCmsClient(options);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AACA,WAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAAA;AAAA;;;;;;;;ACD5D,QAAY;AAAZ,KAAA,SAAYA,QAAK;AACf,MAAAA,OAAAA,OAAA,MAAA,IAAA,CAAA,IAAA;AACA,MAAAA,OAAAA,OAAA,OAAA,IAAA,CAAA,IAAA;AACA,MAAAA,OAAAA,OAAA,UAAA,IAAA,CAAA,IAAA;AACA,MAAAA,OAAAA,OAAA,KAAA,IAAA,CAAA,IAAA;AACA,MAAAA,OAAAA,OAAA,OAAA,IAAA,CAAA,IAAA;AACA,MAAAA,OAAAA,OAAA,YAAA,IAAA,CAAA,IAAA;AACA,MAAAA,OAAAA,OAAA,WAAA,IAAA,CAAA,IAAA;AACA,MAAAA,OAAAA,OAAA,MAAA,IAAA,CAAA,IAAA;IACF,GATY,QAAA,QAAA,UAAA,QAAA,QAAK,CAAA,EAAA;;;;;ACAjB;AAAA;AAAA;AACA,WAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAAA;AAAA;;;;;;;;;;;;;;;;;;;ACD5D,iBAAA,kBAAA,OAAA;AACA,iBAAA,iBAAA,OAAA;AACA,iBAAA,sBAAA,OAAA;;;;;;;;;;ACFA,QAAA,UAAA;AAKA,QAAM,OAAiB,MAAM,CAAC,EAAE,MAAM,QAAA,MAAM,OAAO,MAAM,IAAI,IAAI,GAAE,CAAE;AAErE,QAAM,QAAkB,MAAM;MAC5B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,GAAE;MAC7B,EAAE,MAAM,QAAA,MAAM,OAAO,MAAM,IAAI,IAAI,IAAG;MACtC,EAAE,MAAM,QAAA,MAAM,OAAO,MAAM,IAAI,IAAI,GAAE;MACrC,EAAE,MAAM,QAAA,MAAM,OAAO,MAAM,IAAI,IAAI,GAAE;;AAGvC,QAAM,aAAuB,MAAM;MACjC,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,EAAC;MAC5B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,GAAE;MAC7B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,GAAE;MAC7B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,GAAE;MAC7B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,GAAE;MAC7B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,GAAE;MAC7B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,IAAG;MAC9B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,KAAI;MAC/B,EAAE,MAAM,QAAA,MAAM,OAAO,MAAM,MAAM,IAAI,KAAI;MACzC,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,KAAI;MAC/B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,KAAI;MAC/B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,KAAI;MAC/B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,KAAI;MAC/B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,MAAK;MAChC,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,MAAK;;AAGlC,QAAM,aAAuB,MAAM;MACjC,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,GAAE;MAC7B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,GAAE;MAC7B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,KAAI;MAC/B,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,KAAI;;AAIpB,YAAA,QAAiB,OAAO,EAAE,MAAM,QAAA,MAAM,KAAK,KAAK,MAAK,GAAI,KAAK,MAAK;AACnE,YAAA,WAAoB,OAAO,EAAE,MAAM,QAAA,MAAM,KAAK,KAAK,MAAK,GAAI,KAAK,KAAI;AACrE,YAAA,OAAgB,OAAO,EAAE,MAAM,QAAA,MAAM,KAAK,KAAK,KAAI,GAAI,KAAK,MAAK;AACjE,YAAA,UAAmB,OAAO,EAAE,MAAM,QAAA,MAAM,KAAK,KAAK,KAAI,GAAI,KAAK,KAAI;AACnE,YAAA,aAAsB,OAAO,EAAE,MAAM,QAAA,MAAM,KAAK,KAAK,WAAU,GAAI,KAAK,MAAK;AAC7E,YAAA,gBAAyB,OAAO,EAAE,MAAM,QAAA,MAAM,KAAK,KAAK,WAAU,GAAI,KAAK,KAAI;AAC/E,YAAA,UAAmB,OAAO,EAAE,MAAM,QAAA,MAAM,KAAK,KAAK,WAAU,GAAI,KAAK,KAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC9CtF,QAAA,UAAA;AACA,QAAA,OAAA,aAAA,cAAA;AAEA,QAAM,OAAO;AASA,YAAA,aAAa,CAAC,QAAuB;AAChD,YAAM,aAAa;AAEnB,aAAO,IAAI,QAAQ,YAAY,CAAC,GAAG,GAAG,KAAK,KAAK,KAAK,OAAO,UAAuB;AACjF,YAAI,KAAK;AACP,iBAAO;;AAGT,YAAI,OAAe,IAAI,IACrB,MAAM,SAAS,KAAK,EAAE,IACpB,MAAM,SAAS,KAAK,EAAE,IACpB,QAAQ,KAAK,QAAQ,KAAK,IAAI;UAC5B,GAAG;UACH,GAAG;UACH,GAAG;UACH,GAAG;UACH,GAAG;UACH,GAAG;UACH,KAAK;AAEb,YAAI,IAAI,OAAO,aAAa,IAAI;AAGhC,eAAO,mBAAmB,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK;MACjD,CAAC;IACH;AAWa,YAAA,gBAAgB,CAAC,KAAa,cAA0C;;AACnF,UAAI,SAAoB,CAAA,GAAI,IAAqB;AACjD,YAAM,SACN;AAEA,cAAQ,KAAK,OAAO,KAAK,GAAG,OAAO,MAAM;AACvC,cAAM,KAAC,MAAA,MAAA,MAAA,MAAA,MAAA,MAAA,KAAI,GAAG,CAAC,KAAK,KAAK,MAAK,OAAG,QAAA,OAAA,SAAA,KAC9B,GAAG,CAAC,KAAK,KAAK,KAAI,OAAG,QAAA,OAAA,SAAA,KACrB,GAAG,CAAC,KAAK,KAAK,WAAU,OAAG,QAAA,OAAA,SAAA,KAC3B,GAAG,CAAC,KAAK,KAAK,SAAQ,OAAG,QAAA,OAAA,SAAA,KACzB,GAAG,CAAC,KAAK,KAAK,QAAO,OAAG,QAAA,OAAA,SAAA,KACxB,GAAG,CAAC,KAAK,KAAK,cAAa,OAAG,QAAA,OAAA,SAAA,KAC9B,GAAG,CAAC,KAAK;UACR,MAAM,QAAA,MAAM;UACZ,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,WAAW,CAAC;UACnC,KAAK,IAAI,GAAG,EAAE,GAAG,WAAW,EAAE,SAAS,CAAC;eACxC,QAAA,OAAA,SAAA,MACA,IAAI,GAAG,EAAE,MAAM,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,EAAE,WAAW,CAAC,EAAC;AAE7D,YAAI,GAAG;AACL,iBAAO,KAAK,CAAC;eACR;AACL,iBAAO,CAAC,QAAQ,OAAO,SAAS;;;AAGpC,YAAM,IAAI,YAAY,gCAAgC,SAAS,iCAAiC;IAClG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1EA,QAAA,OAAA,aAAA,cAAA;AACA,QAAA,UAAA;AACA,QAAA,OAAA,aAAA,cAAA;AAOA,QAAM,wBAAwB;AAK9B,QAAM,oBAAoB;AAE1B,QAAM,QAAQ;AAQD,YAAA,YAAY,CAAC,cAA2B;AACnD,UAAI,IAAI,GAAG;AACX,UAAI,QAAc,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,CAAA,EAAE;AAG/C,UAAI,YAA0B;AAC9B,UAAI,OAAgB,MAAM;AAC1B,UAAI,aAA+B,CAAA;AAEnC,UAAI,iBAAiC,CAAA;AACrC,UAAI,aAAa;AAEjB,YAAM,YAAY,CAAC,QAAe;AAChC,cAAM,IAAI,YACR,gCACE,SACF,kCAAkC,MAAM,CAAC,EAAE;MAE/C;AAGA,UAAI,MAAM,KAAK,WAAW,SAAS;AAGnC,aAAO,IAAI,IAAI,QAAQ;AACrB,gBAAQ,IAAI,IAAI,GAAG,GAAG;;UAEpB,KAAK;AACH,gBAAI,MAAM,IAAI,QAAQ;AACpB,oBAAM,IAAI,YACR,gCACE,SACF,yBAAyB;;AAG7B,oBAAQ,IAAI,IAAI,GAAG,GAAG;cACpB,KAAK;AACH,qBAAK,KAAK,EAAE,MAAM,QAAA,MAAM,UAAU,OAAO,IAAG,CAAE;AAC9C;cAEF,KAAK;AACH,qBAAK,KAAK,EAAE,MAAM,QAAA,MAAM,UAAU,OAAO,IAAG,CAAE;AAC9C;cAEF,KAAK;AACH,qBAAK,KAAK,KAAK,MAAK,CAAE;AACtB;cAEF,KAAK;AACH,qBAAK,KAAK,KAAK,SAAQ,CAAE;AACzB;cAEF,KAAK;AACH,qBAAK,KAAK,KAAK,KAAI,CAAE;AACrB;cAEF,KAAK;AACH,qBAAK,KAAK,KAAK,QAAO,CAAE;AACxB;cAEF,KAAK;AACH,qBAAK,KAAK,KAAK,WAAU,CAAE;AAC3B;cAEF,KAAK;AACH,qBAAK,KAAK,KAAK,cAAa,CAAE;AAC9B;cAEF;AAGE,oBAAI,MAAM,KAAK,CAAC,GAAG;AACjB,sBAAI,SAAS;AAEb,yBAAO,IAAI,IAAI,UAAU,MAAM,KAAK,IAAI,CAAC,CAAC,GAAG;AAC3C,8BAAU,IAAI,GAAG;;AAGnB,sBAAI,QAAQ,SAAS,QAAQ,EAAE;AAC/B,wBAAM,YAAuB,EAAE,MAAM,QAAA,MAAM,WAAW,MAAK;AAE3D,uBAAK,KAAK,SAAS;AACnB,iCAAe,KAAK,EAAE,WAAW,OAAO,MAAM,OAAO,KAAK,SAAS,EAAC,CAAE;uBAGjE;AACL,uBAAK,KAAK,EAAE,MAAM,QAAA,MAAM,MAAM,OAAO,EAAE,WAAW,CAAC,EAAC,CAAE;;;AAI5D;;UAIF,KAAK;AACH,iBAAK,KAAK,EAAE,MAAM,QAAA,MAAM,UAAU,OAAO,IAAG,CAAE;AAC9C;UAEF,KAAK;AACH,iBAAK,KAAK,EAAE,MAAM,QAAA,MAAM,UAAU,OAAO,IAAG,CAAE;AAC9C;;UAIF,KAAK,KAAK;AAER,gBAAI;AACJ,gBAAI,IAAI,CAAC,MAAM,KAAK;AAClB,oBAAM;AACN;mBACK;AACL,oBAAM;;AAIR,gBAAI,cAAc,KAAK,cAAc,IAAI,MAAM,CAAC,GAAG,SAAS;AAG5D,iBAAK,YAAY,CAAC;AAClB,iBAAK,KAAK;cACR,MAAM,QAAA,MAAM;cACZ,KAAK,YAAY,CAAC;cAClB;aACD;AAED;;;UAKF,KAAK;AACH,iBAAK,KAAK,KAAK,QAAO,CAAE;AACxB;;UAIF,KAAK,KAAK;AAER,gBAAI,QAAe;cACjB,MAAM,QAAA,MAAM;cACZ,OAAO,CAAA;cACP,UAAU;;AAIZ,gBAAI,IAAI,CAAC,MAAM,KAAK;AAClB,kBAAI,IAAI,IAAI,CAAC;AACb,mBAAK;AAGL,kBAAI,MAAM,KAAK;AACb,sBAAM,aAAa;AACnB,sBAAM,WAAW;yBAGR,MAAM,KAAK;AACpB,sBAAM,gBAAgB;AACtB,sBAAM,WAAW;yBACR,MAAM,KAAK;AACpB,oBAAI,OAAO;AAEX,oBAAI,sBAAsB,KAAK,IAAI,CAAC,CAAC,GAAG;AACtC,0BAAQ,IAAI,CAAC;AACb;uBACK;AACL,wBAAM,IAAI,YACR,gCACE,SACF,6CAA6C,IAAI,CAAC,CAAC,yBAC3B,IAAI,CAAC,EAAE;;AAInC,uBAAO,IAAI,IAAI,UAAU,kBAAkB,KAAK,IAAI,CAAC,CAAC,GAAG;AACvD,0BAAQ,IAAI,CAAC;AACb;;AAGF,oBAAI,CAAC,MAAM;AACT,wBAAM,IAAI,YACR,gCACE,SACF,6CAA6C,IAAI,CAAC,CAAC,yBAC3B,IAAI,CAAC,EAAE;;AAInC,oBAAI,IAAI,CAAC,MAAM,KAAK;AAClB,wBAAM,IAAI,YACR,gCACE,SACF,wDACK,IAAI,CAAC,CAAC,eAAe,IAAI,CAAC,EAAE;;AAIrC,sBAAM,OAAO;AACb;yBACS,MAAM,KAAK;AACpB,sBAAM,WAAW;qBACZ;AACL,sBAAM,IAAI,YACR,gCACE,SACF,gCAAgC,CAAC,yBACT,IAAI,CAAC,EAAE;;mBAG9B;AACL,4BAAc;;AAIhB,iBAAK,KAAK,KAAK;AAGf,uBAAW,KAAK,SAAS;AAGzB,wBAAY;AACZ,mBAAO,MAAM;AAEb;;;UAKF,KAAK;AACH,gBAAI,WAAW,WAAW,GAAG;AAC3B,oBAAM,IAAI,YACR,gCACE,SACF,4BAA4B,IAAI,CAAC,EAAE;;AAGvC,wBAAY,WAAW,IAAG;AAI1B,mBAAO,UAAU,UACf,UAAU,QAAQ,UAAU,QAAQ,SAAS,CAAC,IAC9C,UAAU;AAEZ;;UAIF,KAAK,KAAK;AAGR,gBAAI,CAAC,UAAU,SAAS;AACtB,wBAAU,UAAU,CAAC,UAAU,KAAK;AACpC,qBAAO,UAAU;;AAGnB,gBAAI,QAAiB,CAAA;AACrB,sBAAU,QAAQ,KAAK,KAAK;AAC5B,mBAAO;AAEP;;;;;;;UASF,KAAK,KAAK;AACR,gBAAI,KAAK,qBAAqB,KAAK,IAAI,MAAM,CAAC,CAAC,GAAG,KAAK;AACvD,gBAAI,OAAO,MAAM;AACf,kBAAI,KAAK,WAAW,GAAG;AACrB,0BAAU,CAAC;;AAEb,oBAAM,SAAS,GAAG,CAAC,GAAG,EAAE;AACxB,oBAAM,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,GAAG,EAAE,IAAI,WAAW;AACvD,mBAAK,GAAG,CAAC,EAAE;AAEX,mBAAK,KAAK;gBACR,MAAM,QAAA,MAAM;gBACZ;gBACA;gBACA,OAAO,KAAK,IAAG;eAChB;mBACI;AACL,mBAAK,KAAK;gBACR,MAAM,QAAA,MAAM;gBACZ,OAAO;eACR;;AAGH;;UAGF,KAAK;AACH,gBAAI,KAAK,WAAW,GAAG;AACrB,wBAAU,CAAC;;AAEb,iBAAK,KAAK;cACR,MAAM,QAAA,MAAM;cACZ,KAAK;cACL,KAAK;cACL,OAAO,KAAK,IAAG;aAChB;AACD;UAEF,KAAK;AACH,gBAAI,KAAK,WAAW,GAAG;AACrB,wBAAU,CAAC;;AAEb,iBAAK,KAAK;cACR,MAAM,QAAA,MAAM;cACZ,KAAK;cACL,KAAK;cACL,OAAO,KAAK,IAAG;aAChB;AAED;UAEF,KAAK;AACH,gBAAI,KAAK,WAAW,GAAG;AACrB,wBAAU,CAAC;;AAEb,iBAAK,KAAK;cACR,MAAM,QAAA,MAAM;cACZ,KAAK;cACL,KAAK;cACL,OAAO,KAAK,IAAG;aAChB;AAED;;UAIF;AACE,iBAAK,KAAK;cACR,MAAM,QAAA,MAAM;cACZ,OAAO,EAAE,WAAW,CAAC;aACtB;;;AAKP,UAAI,WAAW,WAAW,GAAG;AAC3B,cAAM,IAAI,YACR,gCACE,SACF,uBAAuB;;AAI3B,uBAAiB,gBAAgB,UAAU;AAE3C,aAAO;IACT;AAWA,aAAS,iBAAiB,gBAAgC,YAAkB;AAI1E,iBAAW,QAAQ,eAAe,QAAO,GAAI;AAC3C,YAAI,aAAa,KAAK,UAAU,OAAO;AAErC,eAAK,UAAU,OAAO,QAAA,MAAM;AAE5B,gBAAM,cAAc,KAAK,UAAU,MAAM,SAAQ;AACjD,eAAK,UAAU,QAAQ,SAAS,aAAa,CAAC;AAG9C,cAAI,CAAC,WAAW,KAAK,WAAW,GAAG;AACjC,gBAAI,IAAI;AAER,mBAAO,YAAY,CAAC,MAAM,OAAO,YAAY,CAAC,MAAM,KAAK;AACvD,mBAAK;;AAGP,gBAAI,MAAM,GAAG;AAEX,mBAAK,UAAU,QAAQ,YAAY,WAAW,CAAC;AAC/C,mBAAK;mBACA;AAIL,mBAAK,UAAU,QAAQ,SAAS,YAAY,MAAM,GAAG,CAAC,GAAG,CAAC;;AAG5D,gBAAI,YAAY,SAAS,GAAG;AAC1B,oBAAM,OAAO,KAAK,MAAM,OAAO,KAAK,QAAQ,CAAC;AAE7C,yBAAW,QAAQ,YAAY,MAAM,CAAC,GAAG;AACvC,qBAAK,MAAM,KAAK;kBACd,MAAM,QAAA,MAAM;kBACZ,OAAO,KAAK,WAAW,CAAC;iBACzB;;AAEH,mBAAK,MAAM,KAAK,GAAG,IAAI;;;;;IAKjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AClbA,QAAA,OAAA,aAAA,cAAA;AACA,QAAA,UAAA;AAEA,aAAS,YAAY,QAAiB;AACpC,UAAI,SAA2C,CAAA;AAC/C,UAAI,MAAM;AACV,iBAAW,SAAS,QAAQ;AAC1B,YAAI,MAAM,SAAS,QAAA,MAAM,MAAM;AAC7B,iBAAO,MAAM,KAAK,IAAI;;AAOxB,YAAI,MAAM,SAAS,QAAA,MAAM,OAAO;AAC9B,iBAAO,GAAG,MAAM,IAAI,IAAI,MAAM,EAAE,EAAE,IAAI;;AAExC,eAAO;;AAET,aAAO;QACL,QAAQ,MAAM,OAAA,OAAA,CAAA,GAAM,MAAM;QAC1B;;IAEJ;AAEa,YAAA,OAAO,YAAY,KAAK,KAAI,EAAG,GAAG;AAClC,YAAA,QAAQ,YAAY,KAAK,MAAK,EAAG,GAAG;AACpC,YAAA,aAAa,YAAY,KAAK,WAAU,EAAG,GAAG;AAC9C,YAAA,aAAa,YAAY,KAAK,QAAO,EAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC7BxD,QAAA,UAAA;AACA,QAAA,OAAA,aAAA,qBAAA;AAQA,aAAgB,QAAQ,UAAgB;AACtC,aAAO,aAAa,KAAK,QACvB,aAAa,KAAK,SAChB,aAAa,KAAK,QAChB,aAAa,KAAK,QAChB,OAAO,aAAa,QAAQ;IACtC;AANA,YAAA,UAAA;AAcA,aAAS,UAAU,KAAgB,EAAE,QAAQ,IAAG,GAAa;AAG3D,UAAI,QAAQ,IAAI,QAAQ;AACtB,eAAO;;AAET,YAAM,MAAM,OAAM;AAClB,iBAAW,QAAQ,KAAK;AACtB,YAAI,KAAK,SAAS,QAAA,MAAM,KAAK;AAC3B,iBAAO;;AAET,cAAM,MAAM,KAAK,SAAS,QAAA,MAAM,OAAO,KAAK,QAAQ,GAAG,KAAK,IAAI,IAAI,KAAK,EAAE;AAC3E,YAAI,IAAI,GAAG,GAAG;AACZ,cAAI,GAAG,IAAI;eACN;AACL,iBAAO;;;AAGX,aAAO;IACT;AAQA,aAAgB,eAAe,KAAU,WAAW,OAAK;AACvD,UAAI,UAAU,IAAI,KAAK,KAAK,IAAI,GAAG;AACjC,eAAO,IAAI,MAAM,QAAQ;;AAE3B,UAAI,UAAU,IAAI,KAAK,KAAK,KAAK,GAAG;AAClC,eAAO,IAAI,MAAM,QAAQ;;AAG3B,UAAI,IAAI,OAAO,UAAU,IAAI,KAAK,KAAK,UAAU,GAAG;AAClD,eAAO;;AAET,UAAI,UAAU,IAAI,KAAK,KAAK,UAAU,GAAG;AACvC,eAAO,IAAI,MAAM,QAAQ;;AAE3B,UAAI,cAAc;AAClB,eAAS,IAAI,GAAG,IAAI,IAAI,IAAI,QAAQ,KAAK;AACvC,cAAM,SAAS,IAAI,IAAI,CAAC;AACxB,uBAAe,cAAc,MAAM;;AAErC,YAAM,WAAW,GAAG,IAAI,MAAM,MAAM,EAAE,GAAG,WAAW;AACpD,aAAO,WAAW,WAAW,IAAI,QAAQ;IAC3C;AArBA,YAAA,iBAAA;AA4BA,aAAS,cAAc,KAAuB;AAC5C,UAAI,IAAI,SAAS,QAAA,MAAM,MAAM;AAC3B,eAAO,QAAQ,IAAI,KAAK;iBACf,IAAI,SAAS,QAAA,MAAM,OAAO;AACnC,eAAO,GAAG,QAAQ,IAAI,IAAI,CAAC,IAAI,QAAQ,IAAI,EAAE,CAAC;;AAEhD,aAAO,eAAe,KAAK,IAAI;IACjC;;;;;;;;;;ACrFA,QAAA,UAAA;AACA,QAAA,qBAAA;AAEA,QAAM,cAAc,CAAC,UAA2B,MAAM,IAAI,QAAA,WAAW,EAAE,KAAK,EAAE;AAE9E,QAAM,kBAAkB,CAAC,UAA+B;AACtD,UAAI,aAAa,OAAO;AACtB,eAAO,MAAM,QAAQ,IAAI,WAAW,EAAE,KAAK,GAAG;iBACrC,WAAW,OAAO;AAC3B,eAAO,YAAY,MAAM,KAAK;aACzB;AACL,cAAM,IAAI,MAAM,8CAA8C;;IAElE;AAEa,YAAA,cAAc,CAAC,UAAyB;AACnD,cAAQ,MAAM,MAAM;QAClB,KAAK,QAAA,MAAM;AACT,iBAAO,gBAAgB,KAAK;QAC9B,KAAK,QAAA,MAAM,MAAM;AACf,gBAAM,IAAI,OAAO,aAAa,MAAM,KAAK;AAGzC,kBAAQ,mBAAmB,KAAK,CAAC,IAAI,OAAO,MAAM;;QAEpD,KAAK,QAAA,MAAM;AACT,cAAI,MAAM,UAAU,OAAO,MAAM,UAAU,KAAK;AAC9C,mBAAO,MAAM;iBACR;AACL,mBAAO,KAAK,MAAM,KAAK;;QAE3B,KAAK,QAAA,MAAM;AACT,iBAAO,KAAK,MAAM,KAAK;QACzB,KAAK,QAAA,MAAM;AACT,iBAAO,mBAAA,eAAe,KAAK;QAC7B,KAAK,QAAA,MAAM,OAAO;AAEhB,gBAAM,SACJ,MAAM,OAAO,KAAK,MAAM,IAAI,MAC1B,MAAM,WAAW,KACf,MAAM,aAAa,OACjB,MAAM,gBAAgB,OACpB;AACV,iBAAO,IAAI,MAAM,GAAG,gBAAgB,KAAK,CAAC;;QAE5C,KAAK,QAAA,MAAM,YAAY;AACrB,gBAAM,EAAE,KAAK,IAAG,IAAK;AACrB,cAAI;AACJ,cAAI,QAAQ,KAAK,QAAQ,GAAG;AAC1B,sBAAU;qBACD,QAAQ,KAAK,QAAQ,UAAU;AACxC,sBAAU;qBACD,QAAQ,KAAK,QAAQ,UAAU;AACxC,sBAAU;qBACD,QAAQ,UAAU;AAC3B,sBAAU,IAAI,GAAG;qBACR,QAAQ,KAAK;AACtB,sBAAU,IAAI,GAAG;iBACZ;AACL,sBAAU,IAAI,GAAG,IAAI,GAAG;;AAE1B,iBAAO,GAAG,QAAA,YAAY,MAAM,KAAK,CAAC,GAAG,OAAO;;QAE9C,KAAK,QAAA,MAAM;AACT,iBAAO,GAAG,mBAAA,QAAQ,MAAM,IAAI,CAAC,IAAI,mBAAA,QAAQ,MAAM,EAAE,CAAC;QACpD;AACE,gBAAM,IAAI,MAAM,sBAAsB,KAAK,EAAE;;IAEnD;;;;;;;;;;;;;;;;;;;;;;ACnEA,QAAA,UAAA;AAQS,WAAA,eAAA,SAAA,SAAA,EAAA,YAAA,MAAA,KAAA,WAAA;AAAA,aARA,QAAA;IAAK,EAAA,CAAA;AACd,iBAAA,qBAAA,OAAA;AACA,iBAAA,uBAAA,OAAA;AACA,QAAA,cAAA;AACA,QAAA,gBAAA;AACA,iBAAA,kBAAA,OAAA;AAEA,YAAA,UAAe,YAAA;AAGf,WAAO,UAAU,YAAA;AACjB,WAAO,QAAQ,QAAQ,QAAA;AACvB,WAAO,QAAQ,cAAc,cAAA;;;;;ACb7B;AAAA;AAAA;AAEA,QAAM,QAAQ;AACd,QAAM,QAAQ,MAAM;AAEpB,aAASC,WAAW,IAAI,MAAM;AAC5B,UAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,YAAM,WAAW,KAAK,UAAU,SAAY,KAAK,KAAK;AAGtD,UAAI,SAAS,EAAE,EAAG,MAAK,GAAG;AAAA,eACjB,OAAO,OAAO,SAAU,MAAK,OAAO,EAAE;AAE/C,UAAI;AAAE,aAAK,MAAM,EAAE;AAAA,MAAE,QAAQ;AAAE,eAAO;AAAA,MAAM;AAE5C,UAAI,OAAO;AACX,cAAQ,SAAS,KAAM,MAAM,YAAY;AACvC,YAAI;AACJ,YAAIC;AACJ,YAAI;AAEJ,YAAI,KAAK,SAAS,MAAM,YAAY;AAClC;AACA;AACA,cAAI,aAAa,EAAG,QAAO;AAC3B,cAAI,OAAO,SAAU,QAAO;AAAA,QAC9B;AAEA,YAAI,KAAK,SAAS;AAChB,eAAK,IAAI,GAAG,MAAM,KAAK,QAAQ,QAAQ,IAAI,KAAK,KAAK;AACnD,YAAAA,MAAK,KAAK,EAAE,OAAO,KAAK,QAAQ,CAAC,EAAE,GAAG,UAAU;AAChD,gBAAI,CAACA,IAAI,QAAO;AAAA,UAClB;AAAA,QACF;AACA,cAAM,QAAQ,KAAK,SAAS,KAAK,OAAO;AACxC,YAAI,CAAC,MAAO,QAAO;AAEnB,aAAK,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACjC,UAAAA,MAAK,KAAK,MAAM,CAAC,GAAG,UAAU;AAC9B,cAAI,CAACA,IAAI,QAAO;AAAA,QAClB;AAEA,eAAO;AAAA,MACT,GAAG,IAAI,CAAC;AAAA,IACV;AAEA,aAAS,SAAU,GAAG;AACpB,aAAO,CAAC,EAAE,SAAS,KAAK,CAAC,MAAM;AAAA,IACjC;AAEA,WAAO,UAAUD;AACjB,WAAO,QAAQ,UAAUA;AACzB,WAAO,QAAQ,YAAYA;AAAA;AAAA;;;ACrD3B;AAAA;AAAA;AAEA,QAAI,SAAS,UAAQ,QAAQ;AAyB7B,cAAU,OAAO,UAAU;AAE3B,aAAS,WAAW,QAAQ,SAAQ;AAClC,gBAAU,cAAc,QAAQ,OAAO;AAEvC,aAAOE,MAAK,QAAQ,OAAO;AAAA,IAC7B;AASA,YAAQ,OAAO,SAAS,QAAO;AAC7B,aAAO,WAAW,MAAM;AAAA,IAC1B;AACA,YAAQ,OAAO,SAAS,QAAO;AAC7B,aAAO,WAAW,QAAQ,EAAC,eAAe,MAAM,WAAW,QAAQ,UAAU,MAAK,CAAC;AAAA,IACrF;AACA,YAAQ,MAAM,SAAS,QAAO;AAC5B,aAAO,WAAW,QAAQ,EAAC,WAAW,OAAO,UAAU,MAAK,CAAC;AAAA,IAC/D;AACA,YAAQ,UAAU,SAAS,QAAO;AAChC,aAAO,WAAW,QAAQ,EAAC,WAAW,OAAO,UAAU,OAAO,eAAe,KAAI,CAAC;AAAA,IACpF;AAGA,QAAI,SAAS,OAAO,YAAY,OAAO,UAAU,EAAE,MAAM,IAAI,CAAC,QAAQ,KAAK;AAC3E,WAAO,KAAK,aAAa;AACzB,QAAI,YAAY,CAAC,UAAU,OAAO,UAAU,QAAQ;AAEpD,aAAS,cAAc,QAAQ,eAAc;AAC3C,sBAAgB,iBAAiB,CAAC;AAGlC,UAAI,UAAU,CAAC;AACf,cAAQ,YAAY,cAAc,aAAa;AAC/C,cAAQ,WAAW,cAAc,YAAY;AAC7C,cAAQ,gBAAgB,cAAc,gBAAgB,OAAO;AAC7D,cAAQ,YAAY,QAAQ,UAAU,YAAY;AAClD,cAAQ,WAAW,QAAQ,SAAS,YAAY;AAChD,cAAQ,gBAAgB,cAAc,kBAAkB,OAAO,QAAQ;AACvE,cAAQ,cAAc,cAAc,gBAAgB,QAAQ,QAAQ;AACpE,cAAQ,uBAAuB,cAAc,yBAAyB,QAAQ,QAAQ;AACtF,cAAQ,4BAA4B,cAAc,8BAA8B,QAAQ,QAAQ;AAChG,cAAQ,kBAAkB,cAAc,oBAAoB,OAAO,QAAQ;AAC3E,cAAQ,gBAAgB,cAAc,kBAAkB,QAAQ,QAAQ;AACxE,cAAQ,mBAAmB,cAAc,qBAAqB,QAAQ,QAAQ;AAC9E,cAAQ,WAAW,cAAc,YAAY;AAC7C,cAAQ,cAAc,cAAc,eAAe;AAEnD,UAAG,OAAO,WAAW,aAAa;AAChC,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AAIA,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,EAAE,GAAG;AACtC,YAAI,OAAO,CAAC,EAAE,YAAY,MAAM,QAAQ,UAAU,YAAY,GAAG;AAC/D,kBAAQ,YAAY,OAAO,CAAC;AAAA,QAC9B;AAAA,MACF;AAEA,UAAG,OAAO,QAAQ,QAAQ,SAAS,MAAM,IAAG;AAC1C,cAAM,IAAI,MAAM,gBAAgB,QAAQ,YAAY,yCAC3B,OAAO,KAAK,IAAI,CAAC;AAAA,MAC5C;AAEA,UAAG,UAAU,QAAQ,QAAQ,QAAQ,MAAM,MACxC,QAAQ,cAAc,eAAc;AACrC,cAAM,IAAI,MAAM,eAAe,QAAQ,WAAW,yCACzB,UAAU,KAAK,IAAI,CAAC;AAAA,MAC/C;AAEA,aAAO;AAAA,IACT;AAGA,aAAS,iBAAiB,GAAG;AAC3B,UAAK,OAAO,MAAO,YAAY;AAC7B,eAAO;AAAA,MACT;AACA,UAAI,MAAM;AACV,aAAO,IAAI,KAAK,SAAS,UAAU,SAAS,KAAK,CAAC,CAAC,KAAK;AAAA,IAC1D;AAEA,aAASA,MAAK,QAAQ,SAAS;AAC7B,UAAI;AAEJ,UAAI,QAAQ,cAAc,eAAe;AACvC,wBAAgB,OAAO,WAAW,QAAQ,SAAS;AAAA,MACrD,OAAO;AACL,wBAAgB,IAAI,YAAY;AAAA,MAClC;AAEA,UAAI,OAAO,cAAc,UAAU,aAAa;AAC9C,sBAAc,QAAQ,cAAc;AACpC,sBAAc,MAAQ,cAAc;AAAA,MACtC;AAEA,UAAI,SAAS,WAAW,SAAS,aAAa;AAC9C,aAAO,SAAS,MAAM;AACtB,UAAI,CAAC,cAAc,QAAQ;AACzB,sBAAc,IAAI,EAAE;AAAA,MACtB;AAEA,UAAI,cAAc,QAAQ;AACxB,eAAO,cAAc,OAAO,QAAQ,aAAa,WAAW,SAAY,QAAQ,QAAQ;AAAA,MAC1F;AAEA,UAAI,MAAM,cAAc,KAAK;AAC7B,UAAI,QAAQ,aAAa,UAAU;AACjC,eAAO;AAAA,MACT;AAEA,aAAO,IAAI,SAAS,QAAQ,QAAQ;AAAA,IACtC;AAUA,YAAQ,gBAAgB,SAAS,QAAQ,SAAS,QAAQ;AACxD,UAAI,OAAO,WAAW,aAAa;AACjC,iBAAS;AACT,kBAAU,CAAC;AAAA,MACb;AAEA,gBAAU,cAAc,QAAQ,OAAO;AAEvC,aAAO,WAAW,SAAS,MAAM,EAAE,SAAS,MAAM;AAAA,IACpD;AAEA,aAAS,WAAW,SAAS,SAAS,SAAQ;AAC5C,gBAAU,WAAW,CAAC;AACtB,UAAI,QAAQ,SAAS,KAAK;AACxB,YAAI,QAAQ,QAAQ;AAClB,iBAAO,QAAQ,OAAO,KAAK,MAAM;AAAA,QACnC,OAAO;AACL,iBAAO,QAAQ,MAAM,KAAK,MAAM;AAAA,QAClC;AAAA,MACF;AAEA,aAAO;AAAA,QACL,UAAU,SAAS,OAAM;AACvB,cAAI,QAAQ,UAAU;AACpB,oBAAQ,QAAQ,SAAS,KAAK;AAAA,UAChC;AAEA,cAAI,OAAO,OAAO;AAClB,cAAI,UAAU,MAAM;AAClB,mBAAO;AAAA,UACT;AAIA,iBAAO,KAAK,MAAM,IAAI,EAAE,KAAK;AAAA,QAC/B;AAAA,QACA,SAAS,SAAS,QAAQ;AACxB,cAAI,UAAW;AACf,cAAI,YAAY,OAAO,UAAU,SAAS,KAAK,MAAM;AACrD,cAAI,UAAU,QAAQ,KAAK,SAAS;AACpC,cAAI,CAAC,SAAS;AACZ,sBAAU,cAAc,YAAY;AAAA,UACtC,OAAO;AACL,sBAAU,QAAQ,CAAC;AAAA,UACrB;AAEA,oBAAU,QAAQ,YAAY;AAE9B,cAAI,eAAe;AAEnB,eAAK,eAAe,QAAQ,QAAQ,MAAM,MAAM,GAAG;AACjD,mBAAO,KAAK,SAAS,eAAe,eAAe,GAAG;AAAA,UACxD,OAAO;AACL,oBAAQ,KAAK,MAAM;AAAA,UACrB;AAEA,cAAI,OAAO,WAAW,eAAe,OAAO,YAAY,OAAO,SAAS,MAAM,GAAG;AAC/E,kBAAM,SAAS;AACf,mBAAO,MAAM,MAAM;AAAA,UACrB;AAEA,cAAG,YAAY,YAAY,YAAY,cAAc,YAAY,iBAAiB;AAChF,gBAAG,KAAK,MAAM,OAAO,GAAG;AACtB,mBAAK,MAAM,OAAO,EAAE,MAAM;AAAA,YAC5B,WAAW,QAAQ,eAAe;AAChC,qBAAO,MAAM,MAAM,UAAU,GAAG;AAAA,YAClC,OAAO;AACL,oBAAM,IAAI,MAAM,0BAA0B,UAAU,GAAG;AAAA,YACzD;AAAA,UACF,OAAK;AACH,gBAAI,OAAO,OAAO,KAAK,MAAM;AAC7B,gBAAI,QAAQ,kBAAkB;AAC5B,qBAAO,KAAK,KAAK;AAAA,YACnB;AAQA,gBAAI,QAAQ,gBAAgB,SAAS,CAAC,iBAAiB,MAAM,GAAG;AAC9D,mBAAK,OAAO,GAAG,GAAG,aAAa,aAAa,aAAa;AAAA,YAC3D;AAEA,gBAAI,QAAQ,aAAa;AACvB,qBAAO,KAAK,OAAO,SAAS,KAAK;AAAE,uBAAO,CAAC,QAAQ,YAAY,GAAG;AAAA,cAAG,CAAC;AAAA,YACxE;AAEA,kBAAM,YAAY,KAAK,SAAS,GAAG;AACnC,gBAAI,OAAO;AACX,mBAAO,KAAK,QAAQ,SAAS,KAAI;AAC/B,mBAAK,SAAS,GAAG;AACjB,oBAAM,GAAG;AACT,kBAAG,CAAC,QAAQ,eAAe;AACzB,qBAAK,SAAS,OAAO,GAAG,CAAC;AAAA,cAC3B;AACA,oBAAM,GAAG;AAAA,YACX,CAAC;AAAA,UACH;AAAA,QACF;AAAA,QACA,QAAQ,SAAS,KAAK,WAAU;AAC9B,sBAAY,OAAO,cAAc,cAAc,YAC7C,QAAQ,oBAAoB;AAE9B,cAAI,OAAO;AACX,gBAAM,WAAW,IAAI,SAAS,GAAG;AACjC,cAAI,CAAC,aAAa,IAAI,UAAU,GAAG;AACjC,mBAAO,IAAI,QAAQ,SAAS,OAAO;AACjC,qBAAO,KAAK,SAAS,KAAK;AAAA,YAC5B,CAAC;AAAA,UACH;AAWA,cAAI,mBAAmB,CAAC;AACxB,cAAI,UAAU,IAAI,IAAI,SAAS,OAAO;AACpC,gBAAI,OAAO,IAAI,YAAY;AAC3B,gBAAI,eAAe,QAAQ,MAAM;AACjC,gBAAI,SAAS,WAAW,SAAS,MAAM,YAAY;AACnD,mBAAO,SAAS,KAAK;AAErB,+BAAmB,iBAAiB,OAAO,aAAa,MAAM,QAAQ,MAAM,CAAC;AAC7E,mBAAO,KAAK,KAAK,EAAE,SAAS;AAAA,UAC9B,CAAC;AACD,oBAAU,QAAQ,OAAO,gBAAgB;AACzC,kBAAQ,KAAK;AACb,iBAAO,KAAK,OAAO,SAAS,KAAK;AAAA,QACnC;AAAA,QACA,OAAO,SAAS,MAAK;AACnB,iBAAO,MAAM,UAAU,KAAK,OAAO,CAAC;AAAA,QACtC;AAAA,QACA,SAAS,SAAS,KAAI;AACpB,iBAAO,MAAM,YAAY,IAAI,SAAS,CAAC;AAAA,QACzC;AAAA,QACA,QAAQ,SAASC,MAAI;AACnB,iBAAO,MAAM,WAAWA,KAAI,SAAS,CAAC;AAAA,QACxC;AAAA,QACA,UAAU,SAAS,MAAK;AACtB,iBAAO,MAAM,UAAU,KAAK,SAAS,CAAC;AAAA,QACxC;AAAA,QACA,SAAS,SAAS,QAAO;AACvB,gBAAM,YAAY,OAAO,SAAS,GAAG;AACrC,gBAAM,OAAO,SAAS,CAAC;AAAA,QACzB;AAAA,QACA,WAAW,SAAS,IAAG;AACrB,gBAAM,KAAK;AACX,cAAI,iBAAiB,EAAE,GAAG;AACxB,iBAAK,SAAS,UAAU;AAAA,UAC1B,OAAO;AACL,iBAAK,SAAS,GAAG,SAAS,CAAC;AAAA,UAC7B;AAEA,cAAI,QAAQ,yBAAyB,OAAO;AAI1C,iBAAK,SAAS,mBAAmB,OAAO,GAAG,IAAI,CAAC;AAAA,UAClD;AAEA,cAAI,QAAQ,2BAA2B;AACrC,iBAAK,QAAQ,EAAE;AAAA,UACjB;AAAA,QACF;AAAA,QACA,SAAS,SAAS,QAAO;AACvB,iBAAO,MAAM,YAAY,OAAO,SAAS,CAAC;AAAA,QAC5C;AAAA,QACA,MAAM,SAAS,KAAI;AACjB,iBAAO,MAAM,SAAS,IAAI,SAAS,CAAC;AAAA,QACtC;AAAA,QACA,OAAO,WAAW;AAChB,iBAAO,MAAM,MAAM;AAAA,QACrB;AAAA,QACA,YAAY,WAAW;AACrB,iBAAO,MAAM,WAAW;AAAA,QAC1B;AAAA,QACA,SAAS,SAAS,OAAM;AACtB,iBAAO,MAAM,WAAW,MAAM,SAAS,CAAC;AAAA,QAC1C;AAAA,QACA,aAAa,SAAS,KAAI;AACxB,gBAAM,aAAa;AACnB,iBAAO,KAAK,SAAS,MAAM,UAAU,MAAM,KAAK,GAAG,CAAC;AAAA,QACtD;AAAA,QACA,oBAAoB,SAAS,KAAI;AAC/B,gBAAM,oBAAoB;AAC1B,iBAAO,KAAK,SAAS,MAAM,UAAU,MAAM,KAAK,GAAG,CAAC;AAAA,QACtD;AAAA,QACA,YAAY,SAAS,KAAI;AACvB,gBAAM,YAAY;AAClB,iBAAO,KAAK,SAAS,MAAM,UAAU,MAAM,KAAK,GAAG,CAAC;AAAA,QACtD;AAAA,QACA,cAAc,SAAS,KAAI;AACzB,gBAAM,cAAc;AACpB,iBAAO,KAAK,SAAS,MAAM,UAAU,MAAM,KAAK,GAAG,CAAC;AAAA,QACtD;AAAA,QACA,aAAa,SAAS,KAAI;AACxB,gBAAM,aAAa;AACnB,iBAAO,KAAK,SAAS,MAAM,UAAU,MAAM,KAAK,GAAG,CAAC;AAAA,QACtD;AAAA,QACA,cAAc,SAAS,KAAI;AACzB,gBAAM,cAAc;AACpB,iBAAO,KAAK,SAAS,MAAM,UAAU,MAAM,KAAK,GAAG,CAAC;AAAA,QACtD;AAAA,QACA,aAAa,SAAS,KAAI;AACxB,gBAAM,aAAa;AACnB,iBAAO,KAAK,SAAS,MAAM,UAAU,MAAM,KAAK,GAAG,CAAC;AAAA,QACtD;AAAA,QACA,eAAe,SAAS,KAAI;AAC1B,gBAAM,eAAe;AACrB,iBAAO,KAAK,SAAS,MAAM,UAAU,MAAM,KAAK,GAAG,CAAC;AAAA,QACtD;AAAA,QACA,eAAe,SAAS,KAAI;AAC1B,gBAAM,eAAe;AACrB,iBAAO,KAAK,SAAS,MAAM,UAAU,MAAM,KAAK,GAAG,CAAC;AAAA,QACtD;AAAA,QACA,cAAc,SAAS,KAAI;AACzB,gBAAM,cAAc;AACpB,iBAAO,KAAK,SAAS,IAAI,WAAW,GAAG,CAAC;AAAA,QAC1C;AAAA,QACA,MAAM,SAAS,KAAK;AAClB,iBAAO,MAAM,SAAS,IAAI,SAAS,GAAG,MAAM;AAAA,QAC9C;AAAA,QACA,MAAM,SAAS,KAAK;AAClB,gBAAM,MAAM;AACZ,cAAI,MAAM,MAAM,KAAK,GAAG;AACxB,iBAAO,KAAK,OAAO,KAAK,QAAQ,kBAAkB,KAAK;AAAA,QACzD;AAAA,QACA,MAAM,SAAS,KAAK;AAClB,gBAAM,MAAM;AACZ,cAAI,MAAM,MAAM,KAAK,GAAG;AACxB,iBAAO,KAAK,OAAO,KAAK,QAAQ,kBAAkB,KAAK;AAAA,QACzD;AAAA,QACA,OAAO,SAAS,MAAM;AACpB,gBAAM,OAAO;AACb,iBAAO,KAAK,SAAS,CAAC,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,WAAW,CAAC;AAAA,QAC1E;AAAA,QACA,OAAO,WAAW;AAChB,cAAI,QAAQ,eAAe;AACzB,mBAAO,MAAM,QAAQ;AAAA,UACvB;AAEA,gBAAM,MAAM,6JAE2C;AAAA,QACzD;AAAA,QACA,YAAY,WAAW;AAAE,iBAAO,MAAM,WAAW;AAAA,QAAG;AAAA,QACpD,SAAS,SAAS,QAAO;AACvB,iBAAO,MAAM,YAAY,OAAO,SAAS,CAAC;AAAA,QAC5C;AAAA;AAAA,QAEA,UAAU,WAAW;AAAE,iBAAO,MAAM,SAAS;AAAA,QAAG;AAAA,QAChD,QAAQ,WAAW;AAAE,iBAAO,MAAM,OAAO;AAAA,QAAG;AAAA,QAC5C,OAAO,WAAW;AAAE,iBAAO,MAAM,MAAM;AAAA,QAAG;AAAA,QAC1C,MAAM,WAAW;AAAE,iBAAO,MAAM,KAAK;AAAA,QAAG;AAAA,QACxC,MAAM,WAAW;AAAE,iBAAO,MAAM,KAAK;AAAA,QAAG;AAAA,QACxC,MAAM,WAAW;AAAE,iBAAO,MAAM,KAAK;AAAA,QAAG;AAAA,QACxC,cAAc,WAAW;AAAE,iBAAO,MAAM,aAAa;AAAA,QAAG;AAAA,QACxD,gBAAgB,WAAW;AAAE,iBAAO,MAAM,eAAe;AAAA,QAAG;AAAA,QAC5D,aAAa,WAAW;AAAE,iBAAO,MAAM,YAAY;AAAA,QAAG;AAAA,QACtD,OAAO,WAAW;AAAE,iBAAO,MAAM,MAAM;AAAA,QAAG;AAAA,QAC1C,UAAU,WAAW;AAAE,iBAAO,MAAM,SAAS;AAAA,QAAG;AAAA,QAChD,aAAa,WAAW;AAAE,iBAAO,MAAM,YAAY;AAAA,QAAG;AAAA,QACtD,aAAa,WAAW;AAAE,iBAAO,MAAM,YAAY;AAAA,QAAG;AAAA,QACtD,WAAW,WAAW;AAAE,iBAAO,MAAM,UAAU;AAAA,QAAG;AAAA,QAClD,SAAS,WAAW;AAAE,iBAAO,MAAM,QAAQ;AAAA,QAAG;AAAA,QAC9C,UAAU,WAAW;AAAE,iBAAO,MAAM,SAAS;AAAA,QAAG;AAAA,QAChD,UAAU,WAAW;AAAE,iBAAO,MAAM,SAAS;AAAA,QAAG;AAAA,MAClD;AAAA,IACF;AAMA,aAAS,cAAc;AACrB,aAAO;AAAA,QACL,KAAK;AAAA,QAEL,OAAO,SAAS,GAAG;AACjB,eAAK,OAAO;AAAA,QACd;AAAA,QAEA,KAAK,SAAS,GAAG;AACf,eAAK,OAAO;AAAA,QACd;AAAA,QAEA,MAAM,WAAW;AACf,iBAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC7bA,SAAS,OAAO,iBAAiB;AACjC,SAAS,eAAe;;;ACDxB,SAA2C,SAAS;AAcpD,IAAM,sBAAsB,EACzB,OAAO,EACP,IAAI,GAAG,wCAAwC,EAC/C,OAAO,CAAC,SAAS,KAAK,KAAK,EAAE,SAAS,GAAG,yCAAyC;AAMrF,IAAM,gCAAgC,EAAE,OAAO;AAAA,EAC7C,QAAQ,EAAE;AAAA,IACR,CAAC,QAAQ,QAAQ,QAAQ,OAAO,QAAQ,YAAY,UAAU;AAAA,IAC9D,EAAE,SAAS,oCAAoC;AAAA,EACjD;AAAA,EACA,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,iBAAiB,EAAE,SAAS,EAAE,SAAS;AACzC,CAAC;;;AChCD,SAAS,KAAAC,UAAS;AAGlB,IAAM,0BAA0BA,GAAE,OAAO;AAAA,EACvC,OAAOA,GAAE,QAAQ,WAAW;AAAA,EAC5B,MAAMA,GAAE,OAAO,EAAE,KAAK,yCAAyC;AAAA,EAC/D,SAASA,GAAE,QAAQ,UAAU;AAC/B,CAAC;AAqBM,IAAM,gBAAgBA,GAAE,OAAO;AAAA;AAAA,EAEpC,MAAMA,GAAE,OAAO,EAAE,OAAO,GAAG,mCAAmC;AAAA;AAAA,EAG9D,MAAMA,GAAE,OAAO,EAAE,IAAI,GAAG,uBAAuB;AAAA;AAAA,EAG/C,MAAMA,GAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1B,WAAWA,GACR;AAAA,IACCA,GAAE,MAAM,CAACA,GAAE,OAAO,EAAE,OAAO,GAAG,oCAAoC,GAAG,uBAAuB,CAAC;AAAA,EAC/F,EACC,IAAI,GAAG,gCAAgC;AAC5C,CAAC;;;AClDD,SAAS,KAAAC,UAAS;AAmBX,IAAM,iBAAiBA,GAAE,OAAO;AAAA;AAAA,EAErC,MAAMA,GAAE,OAAO,EAAE,OAAO,GAAG,oCAAoC;AAAA;AAAA,EAG/D,MAAMA,GAAE,OAAO,EAAE,IAAI,GAAG,wBAAwB;AAAA;AAAA,EAGhD,YAAYA,GAAE,OAAO,EAAE,SAAS;AAClC,CAAC;;;ACxBD,SAA2C,KAAAC,UAAS;;;ACOpD,SAA4D,KAAAC,UAAS;;;ACRrE,SAAS,KAAAC,UAAS;;;ACAlB,SAAS,KAAAC,UAAS;AAMX,IAAM,qBAAqB,CAAC,cAAc,aAAa,YAAY;AAGnE,IAAM,gBAAgB,KAAK,OAAO;AAClC,IAAM,gBAAgB;AAEtB,IAAM,gBAAgB;AACtB,IAAM,gBAAgB;AAMtB,IAAM,iBAAiBA,GAAE,KAAK,kBAAkB;AAEhD,IAAM,iBAAiBA,GAC3B,OAAO,EACP,IAAI,EACJ,IAAI,eAAe,4BAA4B,aAAa,QAAQ,EACpE,IAAI,eAAe,4BAA4B,gBAAgB,OAAO,IAAI,IAAI;AAE1E,IAAM,kBAAkBA,GAC5B,OAAO,EACP,IAAI,EACJ,IAAI,eAAe,iCAAiC,aAAa,IAAI,EACrE,IAAI,eAAe,iCAAiC,aAAa,IAAI;AAKjE,IAAM,sBAAsBA,GAAE,OAAO;AAAA,EAC1C,UAAUA,GACP,OAAO,EACP,IAAI,GAAG,sBAAsB,EAC7B,IAAI,KAAK,mBAAmB,EAC5B,MAAM,oBAAoB,sCAAsC;AAAA,EACnE,UAAU;AAAA,EACV,UAAU;AACZ,CAAC;AAQM,IAAM,sBAAsBA,GAAE,OAAO;AAAA,EAC1C,SAASA,GAAE,KAAK,EAAE,SAAS;AAAA,EAC3B,OAAO;AAAA,EACP,QAAQ;AACV,CAAC;;;AD/BM,IAAM,mBAAmBC,GAAE,OAAO;AAAA;AAAA,EAEvC,IAAIA,GAAE,KAAK;AAAA;AAAA,EAEX,KAAKA,GAAE,IAAI;AAAA;AAAA,EAEX,OAAO;AAAA;AAAA,EAEP,QAAQ;AAAA;AAAA,EAER,kBAAkBA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA;AAAA,EAE3C,UAAU;AAAA;AAAA,EAEV,UAAU;AAAA;AAAA,EAEV,MAAMA,GAAE,OAAO,EAAE,SAAS;AAC5B,CAAC;AAYM,IAAM,gBAAgBA,GAAE,OAAO;AAAA,EACpC,GAAGA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC1B,GAAGA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAC5B,CAAC;AAUM,IAAM,aAAaA,GAAE,OAAO;AAAA;AAAA,EAEjC,GAAGA,GAAE,OAAO,EAAE,IAAI,EAAE,YAAY;AAAA;AAAA,EAEhC,GAAGA,GAAE,OAAO,EAAE,IAAI,EAAE,YAAY;AAAA;AAAA,EAEhC,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA;AAAA,EAEjC,QAAQA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AACpC,CAAC;AAQM,IAAM,uBAAuBA,GAAE,OAAO;AAAA;AAAA,EAE3C,KAAKA,GAAE,OAAO,EAAE,IAAI,GAAG,wCAAwC;AAAA;AAAA,EAG/D,SAASA,GAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EACtC,aAAaA,GAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA;AAAA,EAG1C,QAAQA,GAAE,OAAO;AAAA,IACf,IAAIA,GAAE,KAAK;AAAA,IACX,gBAAgBA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACjD,CAAC;AACH,CAAC;AA2ED,IAAM,aAAaC,GAAE,OAAO;AAAA,EAC1B,KAAKA,GAAE,IAAI;AAAA,EACX,MAAMA,GAAE,OAAO;AAAA,EACf,MAAMA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EAChC,MAAMA,GAAE,OAAO;AACjB,CAAC;;;AEnLD,yBAAsB;AASf,SAAS,kBAAkB,SAAgC;AAEhE,MAAI,QAAQ,SAAS,KAAK;AACxB,WAAO;AAAA,EACT;AAGA,MAAI,KAAC,mBAAAC,SAAU,OAAO,GAAG;AACvB,WAAO;AAAA,EACT;AAGA,MAAI;AACF,QAAI,OAAO,OAAO;AAAA,EACpB,SAASC,MAAK;AACZ,WAAO,kBAAkBA,gBAAe,QAAQA,KAAI,UAAU,SAAS;AAAA,EACzE;AAEA,SAAO;AACT;;;AHZO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1C,YACE,SACgB,WACA,WAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,SAAS,eAAe,OAAoC;AACjE,MAAI;AACF,QAAI,SAAS,iBAAiB,MAAM,MAAM,MAAM,WAAW;AAE3D,QAAI,CAAC,MAAM,UAAU;AACnB,eAAS,OAAO,SAAS;AAAA,IAC3B;AAEA,WAAO;AAAA,EACT,SAASC,MAAK;AACZ,UAAM,IAAI;AAAA,MACR,8BAA8B,MAAM,IAAI,MAAMA,gBAAe,QAAQA,KAAI,UAAU,eAAe;AAAA,MAClG,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAKA,SAAS,iBAAiB,MAAiB,aAA4C;AACrF,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,uBAAuBC,GAAE,OAAO,GAAG,WAAW;AAAA,IAEvD,KAAK;AACH,aAAO,uBAAuBA,GAAE,OAAO,GAAG,WAAW;AAAA,IAEvD,KAAK;AACH,aAAOA,GAAE,QAAQ;AAAA,IAEnB,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAOA,GAAE,OAAO,EAAE,KAAK,0CAA0C;AAAA,IAEnE,KAAK;AACH,aAAOA,GACJ,OAAO,EACP,SAAS,EAAE,QAAQ,MAAM,SAAS,6CAA6C,CAAC;AAAA,IAErF,KAAK;AACH,aAAO,uBAAuBA,GAAE,OAAO,EAAE,IAAI,oBAAoB,GAAG,WAAW;AAAA,IAEjF,KAAK;AACH,aAAO,uBAAuBA,GAAE,OAAO,EAAE,MAAM,sBAAsB,GAAG,WAAW;AAAA,IAErF,KAAK,QAAQ;AACX,YAAM,SAAS,aAAa;AAC5B,UAAI,CAAC,UAAU,OAAO,WAAW,GAAG;AAClC,cAAM,IAAI,MAAM,4DAA4D;AAAA,MAC9E;AACA,aAAOA,GAAE,KAAK,MAA+B;AAAA,IAC/C;AAAA,IAEA,KAAK;AAEH,aAAOA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,QAAQ,CAAC;AAAA,IAEzC,KAAK,SAAS;AACZ,YAAM,WAAW,aAAa,iBAAiB;AAC/C,YAAM,aAAa,sBAAsB,QAAQ;AACjD,aAAO,sBAAsBA,GAAE,MAAM,UAAU,GAAG,WAAW;AAAA,IAC/D;AAAA,IAEA;AACE,YAAM,IAAI,MAAM,uBAAuB,IAAI,EAAE;AAAA,EACjD;AACF;AAKA,SAAS,sBAAsB,MAAmD;AAChF,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAOA,GAAE,OAAO;AAAA,IAClB,KAAK;AACH,aAAOA,GAAE,OAAO;AAAA,IAClB,KAAK;AACH,aAAOA,GAAE,QAAQ;AAAA,EACrB;AACF;AAKA,SAAS,uBAAuB,QAAqB,aAA6C;AAChG,MAAI,CAAC,YAAa,QAAO;AAGzB,MACE,YAAY,cAAc,UAC1B,YAAY,cAAc,UAC1B,YAAY,YAAY,YAAY,WACpC;AACA,UAAM,IAAI;AAAA,MACR,0CAA0C,YAAY,SAAS,uCAAuC,YAAY,SAAS;AAAA,IAC7H;AAAA,EACF;AAEA,MAAI,SAAS;AAEb,MAAI,YAAY,cAAc,QAAW;AACvC,aAAS,OAAO;AAAA,MACd,YAAY;AAAA,MACZ,oBAAoB,YAAY,SAAS;AAAA,IAC3C;AAAA,EACF;AACA,MAAI,YAAY,cAAc,QAAW;AACvC,aAAS,OAAO;AAAA,MACd,YAAY;AAAA,MACZ,mBAAmB,YAAY,SAAS;AAAA,IAC1C;AAAA,EACF;AACA,MAAI,YAAY,SAAS;AAEvB,UAAM,cAAc,kBAAkB,YAAY,OAAO;AACzD,QAAI,aAAa;AACf,YAAM,IAAI,MAAM,WAAW;AAAA,IAC7B;AACA,QAAI;AACF,eAAS,OAAO,MAAM,IAAI,OAAO,YAAY,OAAO,GAAG,gBAAgB;AAAA,IACzE,QAAQ;AACN,YAAM,IAAI,MAAM,0BAA0B,YAAY,OAAO,EAAE;AAAA,IACjE;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,uBAAuB,QAAqB,aAA6C;AAChG,MAAI,CAAC,YAAa,QAAO;AAGzB,MACE,YAAY,QAAQ,UACpB,YAAY,QAAQ,UACpB,YAAY,MAAM,YAAY,KAC9B;AACA,UAAM,IAAI;AAAA,MACR,oCAAoC,YAAY,GAAG,iCAAiC,YAAY,GAAG;AAAA,IACrG;AAAA,EACF;AAEA,MAAI,SAAS;AAEb,MAAI,YAAY,QAAQ,QAAW;AACjC,aAAS,OAAO,IAAI,YAAY,KAAK,oBAAoB,YAAY,GAAG,EAAE;AAAA,EAC5E;AACA,MAAI,YAAY,QAAQ,QAAW;AACjC,aAAS,OAAO,IAAI,YAAY,KAAK,mBAAmB,YAAY,GAAG,EAAE;AAAA,EAC3E;AACA,MAAI,YAAY,SAAS;AACvB,aAAS,OAAO,IAAI,oBAAoB;AAAA,EAC1C;AAEA,SAAO;AACT;AAKA,SAAS,sBACP,QACA,aACwB;AACxB,MAAI,CAAC,YAAa,QAAO;AAGzB,MACE,YAAY,aAAa,UACzB,YAAY,aAAa,UACzB,YAAY,WAAW,YAAY,UACnC;AACA,UAAM,IAAI;AAAA,MACR,wCAAwC,YAAY,QAAQ,sCAAsC,YAAY,QAAQ;AAAA,IACxH;AAAA,EACF;AAEA,MAAI,SAAS;AAEb,MAAI,YAAY,aAAa,QAAW;AACtC,aAAS,OAAO,IAAI,YAAY,UAAU,sBAAsB,YAAY,QAAQ,QAAQ;AAAA,EAC9F;AACA,MAAI,YAAY,aAAa,QAAW;AACtC,aAAS,OAAO,IAAI,YAAY,UAAU,qBAAqB,YAAY,QAAQ,QAAQ;AAAA,EAC7F;AAEA,SAAO;AACT;AAqBO,SAAS,gBAAgB,QAAmD;AACjF,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,WAAW,GAAG;AACjD,UAAM,IAAI,iBAAiB,qCAAqC;AAAA,EAClE;AAEA,QAAM,QAAoC,CAAC;AAC3C,QAAM,YAAY,oBAAI,IAAY;AAElC,aAAW,SAAS,QAAQ;AAE1B,QAAI,UAAU,IAAI,MAAM,IAAI,GAAG;AAC7B,YAAM,IAAI,iBAAiB,0BAA0B,MAAM,IAAI,GAAG;AAAA,IACpE;AACA,cAAU,IAAI,MAAM,IAAI;AAGxB,QAAI,CAAC,0BAA0B,KAAK,MAAM,IAAI,GAAG;AAC/C,YAAM,IAAI;AAAA,QACR,uBAAuB,MAAM,IAAI;AAAA,QACjC,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,MAAM,IAAI,IAAI,eAAe,KAAK;AAAA,EAC1C;AAEA,SAAOA,GAAE,OAAO,KAAK;AACvB;;;AIjRA,yBAAiB;;;ACDjB,SAAS,iBAAiB;;;ACUnB,SAAS,sBAAsB,YAAoB,QAAmC;AAC3F,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,0BAA0B;AACrC,QAAM,KAAK,EAAE;AAGb,QAAM,gBAAgB,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO;AAC3D,MAAI,eAAe;AACjB,+BAA2B,KAAK;AAChC,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,mBAAiB,OAAO,YAAY,MAAM;AAE1C,SAAO,MAAM,KAAK,IAAI;AACxB;AAUO,SAAS,8BACd,SACQ;AACR,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,0BAA0B;AACrC,QAAM,KAAK,EAAE;AAGb,QAAM,gBAAgB,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,CAAC;AAClF,MAAI,eAAe;AACjB,+BAA2B,KAAK;AAChC,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,SAAS,QAAQ,CAAC;AACxB,QAAI,IAAI,EAAG,OAAM,KAAK,EAAE;AACxB,qBAAiB,OAAO,OAAO,MAAM,OAAO,MAAM;AAAA,EACpD;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGA,SAAS,iBAAiB,OAAiB,YAAoB,QAAiC;AAC9F,QAAM,UAAU,YAAY,UAAU,IAAI;AAE1C,QAAM,KAAK,gBAAgB,OAAO,eAAe;AAEjD,aAAW,SAAS,QAAQ;AAC1B,UAAM,YAAY,kBAAkB,KAAK;AACzC,QAAI,MAAM,aAAa;AACrB,YAAM,KAAK,SAAS,MAAM,WAAW,KAAK;AAAA,IAC5C;AACA,UAAM,KAAK,KAAK,MAAM,IAAI,KAAK,SAAS,GAAG;AAAA,EAC7C;AAEA,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,eAAe,aAAa,UAAU,CAAC,qBAAqB,OAAO,IAAI;AAClF,QAAM,KAAK,EAAE;AACf;AAGA,SAAS,2BAA2B,OAAuB;AACzD,QAAM,KAAK,yCAAyC;AACpD,QAAM,KAAK,qEAAqE;AAChF,QAAM,KAAK,4CAA4C;AACvD,QAAM,KAAK,gDAAgD;AAC3D,QAAM,KAAK,sBAAsB;AACjC,QAAM,KAAK,4BAA4B;AACvC,QAAM,KAAK,OAAO;AAClB,QAAM,KAAK,KAAK;AAClB;AAEA,SAAS,kBAAkB,OAAgC;AACzD,MAAI,OAAO,qBAAqB,MAAM,MAAM,MAAM,WAAW;AAE7D,MAAI,CAAC,MAAM,UAAU;AACnB,YAAQ;AAAA,EACV;AAEA,SAAO;AACT;AAEA,SAAS,qBAAqB,MAA+B,aAAwC;AACnG,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,0BAA0B,cAAc,WAAW;AAAA,IAE5D,KAAK;AACH,aAAO,0BAA0B,cAAc,WAAW;AAAA,IAE5D,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO,0BAA0B,wCAAwC,WAAW;AAAA,IAEtF,KAAK;AACH,aAAO,0BAA0B,4CAA4C,WAAW;AAAA,IAE1F,KAAK,QAAQ;AACX,YAAM,SAAS,aAAa;AAC5B,UAAI,CAAC,UAAU,OAAO,WAAW,GAAG;AAClC,eAAO;AAAA,MACT;AACA,YAAM,YAAY,OAAO,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC,CAAC,GAAG,EAAE,KAAK,IAAI;AACrE,aAAO,WAAW,SAAS;AAAA,IAC7B;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,IAET,KAAK,SAAS;AACZ,YAAM,WAAW,aAAa,iBAAiB;AAC/C,YAAM,WAAW,sBAAsB,QAAQ;AAC/C,aAAO,yBAAyB,WAAW,QAAQ,KAAK,WAAW;AAAA,IACrE;AAAA,IAEA;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,sBAAsB,MAA+C;AAC5E,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAEA,SAAS,0BAA0B,MAAc,aAAwC;AACvF,MAAI,CAAC,YAAa,QAAO;AAEzB,MAAI,OAAO;AACX,MAAI,YAAY,cAAc,QAAW;AACvC,YAAQ,QAAQ,YAAY,SAAS,uBAAuB,YAAY,SAAS;AAAA,EACnF;AACA,MAAI,YAAY,cAAc,QAAW;AACvC,YAAQ,QAAQ,YAAY,SAAS,sBAAsB,YAAY,SAAS;AAAA,EAClF;AACA,MAAI,YAAY,SAAS;AACvB,YAAQ,WAAW,YAAY,YAAY,OAAO,CAAC;AAAA,EACrD;AACA,SAAO;AACT;AAEA,SAAS,0BAA0B,MAAc,aAAwC;AACvF,MAAI,CAAC,YAAa,QAAO;AAEzB,MAAI,OAAO;AACX,MAAI,YAAY,SAAS;AACvB,YAAQ;AAAA,EACV;AACA,MAAI,YAAY,QAAQ,QAAW;AACjC,YAAQ,QAAQ,YAAY,GAAG,uBAAuB,YAAY,GAAG;AAAA,EACvE;AACA,MAAI,YAAY,QAAQ,QAAW;AACjC,YAAQ,QAAQ,YAAY,GAAG,sBAAsB,YAAY,GAAG;AAAA,EACtE;AACA,SAAO;AACT;AAEA,SAAS,yBAAyB,MAAc,aAAwC;AACtF,MAAI,CAAC,YAAa,QAAO;AAEzB,MAAI,OAAO;AACX,MAAI,YAAY,aAAa,QAAW;AACtC,YAAQ,QAAQ,YAAY,QAAQ,yBAAyB,YAAY,QAAQ;AAAA,EACnF;AACA,MAAI,YAAY,aAAa,QAAW;AACtC,YAAQ,QAAQ,YAAY,QAAQ,wBAAwB,YAAY,QAAQ;AAAA,EAClF;AACA,SAAO;AACT;AAEA,SAAS,aAAa,KAAqB;AACzC,SAAO,IAAI,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK;AACvD;AAEA,SAAS,YAAY,SAAyB;AAC5C,SAAO,QAAQ,QAAQ,OAAO,KAAK;AACrC;AAEA,SAAS,YAAY,KAAqB;AACxC,SAAO,IAAI,QAAQ,aAAa,CAAC,GAAG,MAAM,EAAE,YAAY,CAAC;AAC3D;AAEA,SAAS,aAAa,KAAqB;AACzC,QAAM,QAAQ,YAAY,GAAG;AAC7B,SAAO,MAAM,OAAO,CAAC,EAAE,YAAY,IAAI,MAAM,MAAM,CAAC;AACtD;;;AC5NA,SAAgC,kBAAkB,qBAAqB;AACvE,OAAO,eAAe;AAQtB,SAAS,aAAa,QAAwB;AAC5C,SAAO,IAAI,IAAI,aAAa,MAAM,EAAE,SAAS;AAC/C;AAeA,SAAS,sBAAsB,QAAiB,WAAoB;AAClE,SAAO,OAAO,KAAwB,YAA6C;AACjF,QAAI,WAAW;AAEf,UAAM,SAAS,IAAI,IAAI,IAAI,SAAS,CAAC;AACrC,QAAI,QAAQ;AACV,aAAO,aAAa,IAAI,WAAW,MAAM;AAAA,IAC3C;AACA,QAAI,WAAW;AACb,aAAO,aAAa,IAAI,cAAc,SAAS;AAAA,IACjD;AACA,QAAI,UAAU,WAAW;AACvB,iBAAW,OAAO,SAAS;AAAA,IAC7B;AAIA,UAAM,WAAW,MAAM,MAAM,UAAU,OAAO;AAE9C,WAAO;AAAA,EACT;AACF;AAKA,SAAS,gBAAgB,SAA+B;AACtD,QAAM,MAAM,aAAa,QAAQ,MAAM;AAEvC,SAAO,iBAA4B;AAAA,IACjC,OAAO;AAAA,MACL,cAAc;AAAA,QACZ;AAAA,QACA,aAAa;AAAA,QACb,OAAO,sBAAsB,QAAQ,QAAQ,QAAQ,SAAS;AAAA,MAChE,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAKO,SAAS,aAAa,SAA+B;AAC1D,SAAO,gBAAgB,OAAO;AAChC;;;AZtCA,eAAsB,2BACpB,SAC+B;AAC/B,QAAM,EAAE,UAAU,IAAI;AAEtB,QAAM,SAAS,aAAa,OAAO;AAGnC,QAAM,YAAY,MAAM,OAAO,aAAa,KAAK,MAAM;AAAA,IACrD;AAAA,IACA,eAAe;AAAA,EACjB,CAAC;AAGD,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,UAAU,IAAI,OAAO,YAAY;AAC/B,YAAM,SAAS,MAAM,OAAO,aAAa,UAAU,MAAM;AAAA,QACvD;AAAA,QACA,MAAM,QAAQ;AAAA,MAChB,CAAC;AAED,aAAO;AAAA,QACL,MAAM,OAAO;AAAA,QACb,aAAa,OAAO;AAAA,QACpB,aAAa,OAAO,eAAe;AAAA,QACnC,QAAQ,OAAO;AAAA,QACf,gBAAgB,OAAO,kBAAkB;AAAA,QACzC,SAAS,OAAO;AAAA,MAClB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAgBA,eAAsB,wBACpB,SACA,YAC6B;AAC7B,QAAM,EAAE,UAAU,IAAI;AACtB,QAAM,SAAS,aAAa,OAAO;AAEnC,QAAM,SAAS,MAAM,OAAO,aAAa,UAAU,MAAM;AAAA,IACvD;AAAA,IACA,MAAM;AAAA,EACR,CAAC;AAED,SAAO;AAAA,IACL,MAAM,OAAO;AAAA,IACb,aAAa,OAAO;AAAA,IACpB,aAAa,OAAO,eAAe;AAAA,IACnC,QAAQ,OAAO;AAAA,IACf,gBAAgB,OAAO,kBAAkB;AAAA,IACzC,SAAS,OAAO;AAAA,EAClB;AACF;AAeO,SAAS,gBACd,SACwC;AAExC,QAAM,SAA8B,CAAC;AAErC,aAAW,UAAU,SAAS;AAC5B,WAAO,OAAO,IAAI,IAAI,gBAAgB,OAAO,MAAM;AAAA,EACrD;AAEA,SAAO;AACT;AAeO,SAAS,mBACd,SACwB;AACxB,QAAM,SAAiC,CAAC;AAExC,aAAW,UAAU,SAAS;AAC5B,WAAO,OAAO,IAAI,IAAI,sBAAsB,OAAO,MAAM,OAAO,MAAM;AAAA,EACxE;AAEA,SAAO;AACT;AASA,eAAsB,kBACpB,SACA,UACe;AACf,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,KAAK,qEAAgE;AAC7E;AAAA,EACF;AAEA,QAAM,OAAO,8BAA8B,OAAO;AAElD,QAAM,MAAM,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,QAAM,UAAU,UAAU,MAAM,OAAO;AACzC;","names":["types","safeRegex","ok","hash","err","z","z","z","z","z","z","z","z","safeRegex","err","err","z"]}
@@ -1,22 +1,19 @@
1
1
  import * as React from 'react';
2
2
  import { Metadata } from 'next';
3
+ import { CmsConfig } from './cms-api.js';
3
4
  import { BlockComponentRegistry } from './types.js';
5
+ import '@repo/cms-schema/trpc';
6
+ import '@trpc/client';
4
7
  import '@repo/cms-schema/blocks';
5
8
 
6
- type PageProps = {
9
+ type PageProps = CmsConfig & {
7
10
  params: Promise<{
8
11
  slug: string[];
9
12
  }>;
10
13
  searchParams?: Promise<{
11
14
  [key: string]: string | string[] | undefined;
12
15
  }>;
13
- /** CMS API base URL (e.g., 'http://localhost:3000') */
14
- cmsUrl: string;
15
16
  registry?: Partial<BlockComponentRegistry>;
16
- /** API key for CMS API authentication */
17
- apiKey?: string;
18
- /** Website ID (required if not using env variables) */
19
- websiteId?: string;
20
17
  };
21
18
  /**
22
19
  * Force dynamic rendering to ensure routes are always fresh.
@@ -341,7 +341,12 @@ function renderToWalkableTree(node, keyPrefix = "") {
341
341
  }
342
342
  return node;
343
343
  }
344
- function BlockRenderer({ block, registry, disableEditable }) {
344
+ function BlockRenderer({
345
+ block,
346
+ registry,
347
+ disableEditable,
348
+ routeParams
349
+ }) {
345
350
  const Component = registry[block.type];
346
351
  if (!Component) {
347
352
  if (process.env.NODE_ENV === "development") {
@@ -349,7 +354,7 @@ function BlockRenderer({ block, registry, disableEditable }) {
349
354
  }
350
355
  return null;
351
356
  }
352
- const component = /* @__PURE__ */ jsx(Component, { content: block.content });
357
+ const component = /* @__PURE__ */ jsx(Component, { content: block.content, routeParams });
353
358
  if (disableEditable) {
354
359
  return component;
355
360
  }
@@ -574,14 +579,19 @@ function BlockRenderer({ block, registry, disableEditable }) {
574
579
  import { createTRPCClient, httpBatchLink } from "@trpc/client";
575
580
  import superjson from "superjson";
576
581
  function getCmsApiUrl(cmsUrl) {
577
- return `${cmsUrl}/api/trpc`;
582
+ return new URL("/api/trpc", cmsUrl).toString();
578
583
  }
579
- function createFetchWithApiKey(apiKey) {
584
+ function createFetchWithApiKey(apiKey, websiteId) {
580
585
  return async (url, options) => {
581
586
  let finalUrl = url;
587
+ const urlObj = new URL(url.toString());
582
588
  if (apiKey) {
583
- const urlObj = new URL(url.toString());
584
589
  urlObj.searchParams.set("api_key", apiKey);
590
+ }
591
+ if (websiteId) {
592
+ urlObj.searchParams.set("website_id", websiteId);
593
+ }
594
+ if (apiKey || websiteId) {
585
595
  finalUrl = urlObj.toString();
586
596
  }
587
597
  const response = await fetch(finalUrl, options);
@@ -590,13 +600,12 @@ function createFetchWithApiKey(apiKey) {
590
600
  }
591
601
  function createCmsClient(options) {
592
602
  const url = getCmsApiUrl(options.cmsUrl);
593
- console.log("[CMS API] Creating client with URL:", url);
594
603
  return createTRPCClient({
595
604
  links: [
596
605
  httpBatchLink({
597
606
  url,
598
607
  transformer: superjson,
599
- fetch: createFetchWithApiKey(options.apiKey)
608
+ fetch: createFetchWithApiKey(options.apiKey, options.websiteId)
600
609
  })
601
610
  ]
602
611
  });
@@ -652,7 +661,7 @@ async function ParametricRoutePage({
652
661
  const path = normalizePath(rawPath);
653
662
  const client = getCmsClient({ apiKey, cmsUrl });
654
663
  try {
655
- const { route } = await client.route.getByPath.query({ websiteId, path });
664
+ const { route, resolvedParams } = await client.route.getByPath.query({ websiteId, path });
656
665
  if (route.state !== "Live") {
657
666
  console.error(`Route found but not Live. Path: ${path}, State: ${route.state}`);
658
667
  notFound();
@@ -709,12 +718,28 @@ async function ParametricRoutePage({
709
718
  content
710
719
  });
711
720
  }
721
+ const routeParams = resolvedParams ? Object.fromEntries(
722
+ Object.entries(resolvedParams).map(([key, param]) => [
723
+ key,
724
+ {
725
+ value: param.value,
726
+ schemaName: param.schemaName,
727
+ document: {
728
+ id: param.document.id,
729
+ title: param.document.title,
730
+ content: param.document.content,
731
+ schema_name: param.document.schema_name
732
+ }
733
+ }
734
+ ])
735
+ ) : void 0;
712
736
  return /* @__PURE__ */ jsx2("main", { children: blocks.map((block) => /* @__PURE__ */ jsx2(
713
737
  BlockRenderer,
714
738
  {
715
739
  block,
716
740
  registry: registry ?? {},
717
- disableEditable: !editMode
741
+ disableEditable: !editMode,
742
+ routeParams
718
743
  },
719
744
  block.id
720
745
  )) });