@decoupla/sdk 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/modules/schema.ts","../src/modules/upload.ts","../src/modules/entry.ts","../src/modules/sync-api.ts","../src/modules/filters.ts","../src/utils/logger.ts","../src/types/generics.ts","../src/index.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type { ImageObject, TextObject } from \"../types\";\n\n// Utility functions for case conversion between snake_case and camelCase\nexport function snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n}\n\nexport function camelToSnake(str: string): string {\n // Convert camelCase or PascalCase to snake_case.\n // Preserve first-letter lowercase for single-word PascalCase (Title -> title)\n return str.replace(/([A-Z])/g, (match, _p1, offset) => {\n return offset === 0 ? match.toLowerCase() : `_${match.toLowerCase()}`;\n });\n}\n\nexport const initSchema = z.object({\n apiToken: z.string().min(1, \"API Token is required\"),\n workspace: z.string().min(1, \"Workspace is required\"),\n});\n\nexport type InitSchema = z.infer<typeof initSchema>;\n\nconst preloadType: z.ZodTypeAny = z.lazy(() =>\n z.array(\n z.union([\n z.string(),\n z.tuple([z.string(), preloadType])\n ])\n )\n);\n\nexport const requestSchema = z.object({\n type: z.string().optional(),\n op_type: z.enum(['get_entry', 'get_entries', 'inspect']),\n // Which API surface to target when fetching entries. Defaults to 'live' in the client.\n api_type: z.enum(['live', 'preview']).optional(),\n // entry_id is required for get_entry operations (top-level param)\n entry_id: z.string().optional(),\n filters: z.any().optional(),\n preload: preloadType.optional(),\n sort: z.array(z.tuple([z.string(), z.enum(['ASC', 'DESC'])])).optional(),\n limit: z.number().int().min(1).optional(),\n offset: z.number().int().min(0).optional(),\n})\n\nexport type RequestSchema = z.infer<typeof requestSchema>;\n\n// --- Content Type Schema Builder ---\n// Allows you to define content types with Zod and automatically infer TypeScript types\n\n// Base field types (non-reference)\nexport type FieldSchemaConfig =\n | { type: 'string'; required?: boolean; options?: readonly string[]; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'string[]'; required?: boolean; options?: readonly string[]; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'text'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'slug'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'int'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'int[]'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'float'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'float[]'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'boolean'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'boolean[]'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'date'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'time'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'datetime'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'json'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'image'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'image[]'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'video'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'video[]'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'reference'; required?: boolean; isLabel?: boolean; references?: readonly (string | Record<string, FieldSchemaConfig> | { __fields: Record<string, FieldSchemaConfig> })[]; schema?: z.ZodTypeAny }\n | { type: 'reference[]'; required?: boolean; isLabel?: boolean; references?: readonly (string | Record<string, FieldSchemaConfig> | { __fields: Record<string, FieldSchemaConfig> })[]; schema?: z.ZodTypeAny };\n\n// Helper type to extract all valid field type strings from FieldSchemaConfig\nexport type FieldType = FieldSchemaConfig extends { type: infer T } ? T : never;\n\n// Helper to infer type from a field config\n// This directly computes the TypeScript type without needing a separate registry\ntype InferFieldType<T extends FieldSchemaConfig> =\n T extends { type: 'string'; options: readonly (infer Opt)[] }\n ? Opt\n : T extends { type: 'string' }\n ? string\n : T extends { type: 'string[]'; options: readonly (infer Opt)[] }\n ? Opt[]\n : T extends { type: 'string[]' }\n ? string[]\n : T extends { type: 'text' } ? TextObject\n : T extends { type: 'slug' } ? string\n : T extends { type: 'int' } ? number\n : T extends { type: 'int[]' } ? number[]\n : T extends { type: 'float' } ? number\n : T extends { type: 'float[]' } ? number[]\n : T extends { type: 'boolean' } ? boolean\n : T extends { type: 'boolean[]' } ? boolean[]\n : T extends { type: 'date' } ? string // ISO 8601 date string\n : T extends { type: 'time' } ? string // ISO 8601 time string\n : T extends { type: 'datetime' } ? string // ISO 8601 datetime string\n : T extends { type: 'json' } ? unknown // Any valid JSON value\n : T extends { type: 'image' } ? ImageObject\n : T extends { type: 'image[]' } ? ImageObject[]\n : T extends { type: 'video' } ? string\n : T extends { type: 'video[]' } ? string[]\n : T extends { type: 'reference'; references: readonly (infer Ref)[] }\n ? Ref extends string\n ? string | Record<string, any> // String references resolve to generic types\n : Ref extends { __fields: infer Fields }\n ? Fields extends Record<string, FieldSchemaConfig>\n ? Omit<ContentTypeFromConfig<Fields>, never>\n : string | Record<string, any>\n : Ref extends Record<string, FieldSchemaConfig>\n ? Omit<ContentTypeFromConfig<Ref>, never>\n : string | Record<string, any>\n : T extends { type: 'reference[]'; references: readonly (infer Ref)[] }\n ? Ref extends string\n ? (string | Record<string, any>)[]\n : Ref extends { __fields: infer Fields }\n ? Fields extends Record<string, FieldSchemaConfig>\n ? Omit<ContentTypeFromConfig<Fields>, never>[]\n : (string | Record<string, any>)[]\n : Ref extends Record<string, FieldSchemaConfig>\n ? Omit<ContentTypeFromConfig<Ref>, never>[]\n : (string | Record<string, any>)[]\n : never;\n\n// Helper to determine if a field is required\ntype IsRequired<T extends FieldSchemaConfig> = T extends { required: true } ? true : false;\n\n// Helper to transform a single field into its proper type\ntype TransformField<T extends FieldSchemaConfig> =\n IsRequired<T> extends true\n ? InferFieldType<T>\n : InferFieldType<T> | undefined;\n\n// Main type transformer that builds an object type from field configs\nexport type ContentTypeFromConfig<T extends Record<string, FieldSchemaConfig>> = {\n [K in keyof T]: TransformField<T[K]>;\n};\n\n// Helper type to extract fields from a content type definition object\nexport type ExtractFields<T> = T extends { __fields: infer F } ? F : never;\n\n// Helper type to infer the TypeScript type from a content type definition object\n// Usage: type User = InferContentType<typeof userDefinition>;\nexport type InferContentType<T extends { __fields: Record<string, FieldSchemaConfig> }> = Omit<ContentTypeFromConfig<T['__fields']>, never>;\n\nexport type ContentTypeSchemaConfig = {\n fields: Record<string, FieldSchemaConfig>;\n};\n\n/**\n * Helper function to build a Zod schema for a field based on its config.\n * If a custom schema is provided, it uses that; otherwise, infers from the type.\n */\nexport const fieldSchemaBuilder = (config: FieldSchemaConfig): z.ZodTypeAny => {\n if (config.schema) {\n return config.required ? config.schema : config.schema.optional();\n }\n\n let baseSchema: z.ZodTypeAny;\n\n switch (config.type) {\n case 'string':\n baseSchema = (config as any).options ? z.enum((config as any).options as [string, ...string[]]) : z.string();\n break;\n case 'string[]':\n baseSchema = (config as any).options ? z.array(z.enum((config as any).options as [string, ...string[]])) : z.array(z.string());\n break;\n case 'text':\n baseSchema = z.string();\n break;\n case 'slug':\n baseSchema = z.string();\n break;\n case 'int':\n baseSchema = z.number().int();\n break;\n case 'int[]':\n baseSchema = z.array(z.number().int());\n break;\n case 'float':\n baseSchema = z.number();\n break;\n case 'float[]':\n baseSchema = z.array(z.number());\n break;\n case 'image':\n baseSchema = z.string(); // typically a URL or ID\n break;\n case 'image[]':\n baseSchema = z.array(z.string());\n break;\n case 'video':\n baseSchema = z.string();\n break;\n case 'video[]':\n baseSchema = z.array(z.string());\n break;\n case 'boolean':\n baseSchema = z.boolean();\n break;\n case 'boolean[]':\n baseSchema = z.array(z.boolean());\n break;\n case 'date':\n baseSchema = z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/, 'Invalid date format (YYYY-MM-DD)');\n break;\n case 'time':\n baseSchema = z.string().regex(/^\\d{2}:\\d{2}:\\d{2}$/, 'Invalid time format (HH:MM:SS)');\n break;\n case 'datetime':\n baseSchema = z.string().datetime('Invalid datetime format (ISO 8601)');\n break;\n case 'json':\n baseSchema = z.any(); // Accept any valid JSON value\n break;\n case 'reference':\n // reference fields typically contain an ID or object reference\n baseSchema = z.union([z.string(), z.record(z.string(), z.any())]);\n break;\n case 'reference[]':\n baseSchema = z.array(z.union([z.string(), z.record(z.string(), z.any())]));\n break;\n default:\n baseSchema = z.any();\n }\n\n return config.required ? baseSchema : baseSchema.optional();\n};\n\n/**\n * Build a Zod object schema from a content type config with proper type preservation.\n * \n * Usage:\n * type Author = Omit<ContentTypeFromConfig<typeof authorConfig>, never>;\n * type Article = Omit<ContentTypeFromConfig<typeof articleConfig>, never>;\n * \n * const authorSchema = createContentTypeSchema({ fields: authorConfig });\n * const articleSchema = createContentTypeSchema({ fields: articleConfig });\n */\nexport const createContentTypeSchema = <T extends Record<string, FieldSchemaConfig>>(\n config: { fields: T }\n): z.ZodType<ContentTypeFromConfig<T>> => {\n const fields: Record<string, z.ZodTypeAny> = {};\n\n for (const [fieldName, fieldConfig] of Object.entries(config.fields)) {\n fields[fieldName] = fieldSchemaBuilder(fieldConfig as FieldSchemaConfig);\n }\n\n return z.object(fields) as z.ZodType<ContentTypeFromConfig<T>>;\n};","/**\n * File Upload Types and Utilities\n * \n * Supports uploading images and videos to the Decoupla backend.\n */\n\nexport type ImageFile = {\n id: string;\n type: 'image';\n width: number;\n height: number;\n format: string;\n byte_size: number;\n};\n\nexport type VideoFile = {\n id: string;\n type: 'video';\n width: number;\n height: number;\n format: string;\n byte_size: number;\n duration: number;\n};\n\nexport type UploadedFile = ImageFile | VideoFile;\n\nexport type UploadFileRequest = {\n op_type: 'upload_file';\n};\n\nexport type UploadFileResponse = {\n data: {\n file: UploadedFile;\n };\n};\n\nexport type UploadError = {\n field: string;\n message: string;\n};\n\nexport type UploadErrorResponse = {\n errors: UploadError[];\n};\n\n/**\n * Check if a file is a supported image format\n */\nexport function isSupportedImageFormat(filename: string): boolean {\n const supportedFormats = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'tiff'];\n const ext = filename.split('.').pop()?.toLowerCase() || '';\n return supportedFormats.includes(ext);\n}\n\n/**\n * Check if a file is a supported video format\n */\nexport function isSupportedVideoFormat(filename: string): boolean {\n const supportedFormats = ['mp4', 'webm', 'ogv', 'mov', 'avi', 'mkv'];\n const ext = filename.split('.').pop()?.toLowerCase() || '';\n return supportedFormats.includes(ext);\n}\n\n/**\n * Check if a file is supported (image or video)\n */\nexport function isSupportedFileFormat(filename: string): boolean {\n return isSupportedImageFormat(filename) || isSupportedVideoFormat(filename);\n}\n\n/**\n * Validate file before upload\n */\nexport function validateFile(file: File): { valid: boolean; error?: string } {\n if (!file) {\n return { valid: false, error: 'No file provided' };\n }\n\n if (!isSupportedFileFormat(file.name)) {\n return {\n valid: false,\n error: `Unsupported file format: ${file.name}. Supported formats: images (JPG, PNG, GIF, WebP, etc.) and videos (MP4, WebM, OGV, etc.)`\n };\n }\n\n return { valid: true };\n}\n\n/**\n * Get file type from filename\n */\nexport function getFileType(filename: string): 'image' | 'video' | 'unknown' {\n if (isSupportedImageFormat(filename)) return 'image';\n if (isSupportedVideoFormat(filename)) return 'video';\n return 'unknown';\n}\n","/**\n * Entry Creation and Update Types\n * \n * Supports creating and updating entries (instances of content types)\n */\n\nexport type FieldValue =\n | string\n | number\n | boolean\n | null\n | FieldValue[]\n | Record<string, any>;\n\nexport type FieldValues = Record<string, FieldValue>;\n\nexport type CreateEntryRequest = {\n op_type: 'create_entry';\n field_values: FieldValues;\n published?: boolean;\n};\n\nexport type UpdateEntryRequest = {\n op_type: 'update_entry';\n entry_id: string;\n field_values: FieldValues;\n published?: boolean;\n};\n\nexport type EntryMetadata = {\n id: string;\n model_id: string;\n state: string;\n last_version: number;\n last_published_version: number | null;\n created_at: string;\n updated_at: string;\n};\n\n/**\n * Normalized version of EntryMetadata with camelCase field names\n */\nexport type NormalizedEntryMetadata = {\n id: string;\n modelId: string;\n state: string;\n lastVersion: number;\n lastPublishedVersion: number | null;\n createdAt: string;\n updatedAt: string;\n};\n\nexport type CreateEntryResponse = {\n data: {\n entry: EntryMetadata;\n };\n};\n\nexport type UpdateEntryResponse = CreateEntryResponse;\n\nexport type EntryError = {\n field: string;\n message: string;\n};\n\nexport type EntryErrorResponse = {\n errors: EntryError[];\n};\n\n/**\n * Validate entry ID (must be valid UUID)\n */\nexport function isValidUUID(id: string): boolean {\n const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n return uuidRegex.test(id);\n}\n\n/**\n * Validate field values before sending to API\n */\nexport function validateFieldValues(\n fieldValues: FieldValues,\n requiredFields?: string[]\n): { valid: boolean; error?: string; errors?: EntryError[] } {\n if (!fieldValues || typeof fieldValues !== 'object') {\n return {\n valid: false,\n error: 'Field values must be a non-null object'\n };\n }\n\n // Check required fields\n if (requiredFields && requiredFields.length > 0) {\n const missing = requiredFields.filter(field => {\n const value = fieldValues[field];\n return value === undefined || value === null || value === '';\n });\n\n if (missing.length > 0) {\n return {\n valid: false,\n errors: missing.map(field => ({\n field,\n message: \"can't be blank\"\n }))\n };\n }\n }\n\n return { valid: true };\n}\n\n/**\n * Convert field values for API (handle camelCase to snake_case conversion)\n */\nexport function normalizeFieldValues(fieldValues: FieldValues): FieldValues {\n const normalized: FieldValues = {};\n\n for (const [key, value] of Object.entries(fieldValues)) {\n // Keep the key as-is; API accepts both camelCase and snake_case\n normalized[key] = value;\n }\n\n return normalized;\n}\n\n/**\n * Format entry metadata for display\n */\nexport function formatEntryMetadata(entry: EntryMetadata): string {\n return `Entry #${entry.id} (v${entry.last_version}, ${entry.state})`;\n}\n","import type { FieldType, ContentTypeDefinition, FieldDefinition } from \"../types\";\n\n/**\n * API Request types for sync operations\n */\n\nexport type CreateContentTypeRequest = {\n op_type: 'create_content_type';\n name: string;\n description?: string;\n};\n\nexport type CreateFieldRequest = {\n op_type: 'create_field';\n content_type_id: string;\n name: string;\n type: string;\n control?: string;\n required?: boolean;\n description?: string;\n meta?: Record<string, any>;\n};\n\nexport type UpdateFieldRequest = {\n op_type: 'update_field';\n field_id: string;\n name?: string;\n required?: boolean;\n description?: string;\n meta?: Record<string, any>;\n};\n\nexport type DeleteFieldRequest = {\n op_type: 'delete_field';\n field_id: string;\n};\n\nexport type DeleteModelRequest = {\n op_type: 'delete_content_type';\n model_id: string;\n};\n\nexport type ModelRequest =\n | CreateContentTypeRequest\n | CreateFieldRequest\n | UpdateFieldRequest\n | DeleteFieldRequest\n | DeleteModelRequest;\n\n/**\n * API Response types for sync operations\n */\n\nexport type CreateContentTypeResponse = {\n data: {\n content_type: {\n id: string;\n name: string;\n slug: string;\n description?: string;\n localizable: boolean;\n project_id: string;\n inserted_at: string;\n updated_at: string;\n };\n };\n};\n\nexport type CreateFieldResponse = {\n data: {\n field: {\n id: string;\n name: string;\n slug: string;\n type: string;\n control: string;\n required: boolean;\n description?: string;\n model_id: string;\n order: number;\n is_label: boolean;\n inserted_at: string;\n updated_at: string;\n };\n };\n};\n\nexport type UpdateFieldResponse = {\n data: {\n field: {\n id: string;\n name: string;\n slug: string;\n type: string;\n control: string;\n required: boolean;\n description?: string;\n model_id: string;\n order: number;\n is_label: boolean;\n inserted_at: string;\n updated_at: string;\n };\n };\n};\n\nexport type DeleteFieldResponse = {\n data: {\n message: string;\n };\n};\n\nexport type DeleteModelResponse = {\n data: {\n message: string;\n };\n};\n\nexport type ModelResponse =\n | CreateContentTypeResponse\n | CreateFieldResponse\n | UpdateFieldResponse\n | DeleteFieldResponse\n | DeleteModelResponse\n | ErrorResponse;\n\nexport type ErrorResponse = {\n errors: Array<{\n field: string;\n message: string;\n valid_types?: string[];\n valid_controls?: string[];\n }>;\n};\n\n/**\n * Map our field types to backend field types\n */\nexport const fieldTypeMap: Record<FieldType, string> = {\n 'string': 'string',\n 'string[]': 'string[]',\n 'text': 'text',\n 'slug': 'slug',\n 'int': 'int',\n 'int[]': 'int[]',\n 'float': 'float',\n 'float[]': 'float[]',\n 'boolean': 'boolean',\n 'boolean[]': 'boolean[]',\n 'date': 'date',\n 'time': 'time',\n 'datetime': 'datetime',\n 'json': 'json',\n 'image': 'image',\n 'image[]': 'image[]',\n 'video': 'video',\n 'video[]': 'video[]',\n 'reference': 'reference',\n 'reference[]': 'reference[]',\n};\n\n/**\n * Reverse map backend field types to our field types\n */\nexport const reverseFieldTypeMap: Record<string, FieldType> = {\n 'string': 'string',\n 'string[]': 'string[]',\n 'text': 'text',\n 'slug': 'slug',\n 'id': 'string', // id fields are essentially strings\n 'int': 'int',\n 'int[]': 'int[]',\n 'float': 'float',\n 'float[]': 'float[]',\n 'boolean': 'boolean',\n 'date': 'date',\n 'time': 'time',\n 'datetime': 'datetime',\n 'json': 'json',\n 'image': 'image',\n 'image[]': 'image[]',\n 'video': 'video',\n 'video[]': 'video[]',\n 'reference': 'reference',\n 'reference[]': 'reference[]',\n};\n\n/**\n * Map control types (optional, defaults to 'default')\n */\nexport const controlTypeMap: Record<string, string> = {\n 'string': 'text',\n 'text': 'textarea',\n 'int': 'default',\n 'float': 'default',\n 'boolean': 'checkbox',\n 'date': 'default',\n 'datetime': 'default',\n 'time': 'default',\n 'image': 'default',\n 'video': 'default',\n 'reference': 'default',\n 'reference[]': 'default',\n};\n\n/**\n * Build a create field request from a field definition\n */\nexport function buildCreateFieldRequest(\n modelId: string,\n fieldName: string,\n fieldDef: FieldDefinition\n): CreateFieldRequest {\n const backendType = fieldTypeMap[fieldDef.type as FieldType] || 'string';\n const control = controlTypeMap[backendType] || 'default';\n\n // Build meta object. Start with any provided meta in settings, then attach reference_types\n const meta: Record<string, any> = { ...(fieldDef.settings?.meta || {}) };\n if (fieldDef.references && Array.isArray(fieldDef.references)) {\n // The sync layer is responsible for resolving reference targets to content-type IDs (UUIDs).\n // Here we place the provided identifiers directly into meta.reference_types so the backend\n // receives an array of content-type IDs as expected.\n meta.reference_types = fieldDef.references.map(ref => {\n if (typeof ref === 'string') return ref;\n // If a branded content type object is provided, prefer any explicit id property\n // (upstream code should already have resolved to IDs, but handle defensively).\n return (ref as any).__definition?.id || (ref as any).__definition?.name || ref;\n });\n }\n\n return {\n op_type: 'create_field',\n content_type_id: modelId,\n name: fieldName,\n type: backendType,\n control,\n required: fieldDef.required ?? false,\n description: fieldDef.settings?.description,\n meta: Object.keys(meta).length > 0 ? meta : undefined,\n };\n}\n\n/**\n * Build an update field request from differences\n */\nexport function buildUpdateFieldRequest(\n fieldId: string,\n changes: Record<string, any>\n): UpdateFieldRequest {\n const request: UpdateFieldRequest = {\n op_type: 'update_field',\n field_id: fieldId,\n };\n\n if (changes.required !== undefined) {\n request.required = changes.required;\n }\n if (changes.name !== undefined) {\n request.name = changes.name;\n }\n if (changes.description !== undefined) {\n request.description = changes.description;\n }\n // Support updating reference types via changes.references or changes.meta\n if (changes.references !== undefined) {\n request.meta = { ...(changes.meta || {}), reference_types: changes.references };\n } else if (changes.meta !== undefined) {\n request.meta = changes.meta;\n }\n\n return request;\n}\n\n/**\n * Build a create content type request from a content type definition\n */\nexport function buildCreateContentTypeRequest(ct: ContentTypeDefinition): CreateContentTypeRequest {\n return {\n op_type: 'create_content_type',\n name: ct.displayName || ct.name,\n description: ct.description,\n };\n}\n","/**\n * Type-safe filter system for content type queries\n * \n * Provides compile-time validation of filter operations based on field types.\n * Supports complex filters with and/or logic and list operations.\n * Supports polymorphic reference fields - can filter by any of the referenced types.\n * \n * Filter Structure:\n * - and: Filter[] - all conditions must be true\n * - or: Filter[] - any condition can be true\n * - Field filters: depend on field type\n * - string/slug: is_null, is_not_null, eq, not_eq, contains, not_contains, starts_with, not_starts_with, ends_with, not_ends_with, in, not_in\n * - text: same as string\n * - boolean: is_null, is_not_null, eq, not_eq\n * - id: eq, not_eq, in, not_in\n * - date/datetime/time: is_null, is_not_null, eq, not_eq, gt, gte, lt, lte, between, outside\n * - int/float: is_null, is_not_null, eq, not_eq, gt, gte, lt, lte, between, outside, in, not_in\n * - lists (except image[] and video[]): none<Filter>, any<Filter>, every<Filter>\n * - reference/reference[]: filters for each referenced type using {field}_{type}_filter naming\n * Can filter by any of the referenced content types or use union filter syntax\n */\n\nimport type { FieldDefinition, ContentTypeDefinition } from \"../types\";\n\n// Null check operations (valid for all field types)\ntype NullOperations = 'is_null' | 'is_not_null';\n\n// String/Slug/Text operations\ntype StringOperations = NullOperations | 'eq' | 'not_eq' | 'contains' | 'not_contains' | 'starts_with' | 'not_starts_with' | 'ends_with' | 'not_ends_with' | 'in' | 'not_in';\n\n// Boolean operations\ntype BooleanOperations = NullOperations | 'eq' | 'not_eq';\n\n// ID operations\ntype IdOperations = 'eq' | 'not_eq' | 'in' | 'not_in';\n\n// Numeric operations (int, float)\ntype NumericOperations = NullOperations | 'eq' | 'not_eq' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'outside' | 'in' | 'not_in';\n\n// Date/Time operations\ntype DateTimeOperations = NullOperations | 'eq' | 'not_eq' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'outside';\n\n// Reference operations\ntype ReferenceOperations = 'eq' | 'not_eq' | 'in' | 'not_in';\n\n// List operations - work on individual items in the list\ntype ListOperations<T extends Filter> = {\n none: T;\n any: T;\n every: T;\n};\n\n// Map field types to their allowed operations\ntype FieldTypeOperations = {\n 'id': IdOperations;\n 'string': StringOperations;\n 'text': StringOperations;\n 'slug': StringOperations;\n 'int': NumericOperations;\n 'float': NumericOperations;\n 'boolean': BooleanOperations;\n 'date': DateTimeOperations;\n 'time': DateTimeOperations;\n 'datetime': DateTimeOperations;\n 'reference': ReferenceOperations;\n 'string[]': ListOperations<Filter>;\n 'int[]': ListOperations<Filter>;\n 'float[]': ListOperations<Filter>;\n 'boolean[]': ListOperations<Filter>;\n 'date[]': ListOperations<Filter>;\n 'reference[]': ListOperations<Filter>;\n 'image': never; // Images cannot be filtered\n 'video': never; // Videos cannot be filtered\n 'image[]': never; // Image arrays cannot be filtered\n 'video[]': never; // Video arrays cannot be filtered\n 'json': never; // JSON cannot be filtered\n};\n\n// Value type for each field type\ntype FieldTypeValue = {\n 'id': string | string[];\n 'string': string | string[];\n 'text': string | string[];\n 'slug': string | string[];\n 'int': number | number[];\n 'float': number | number[];\n 'boolean': boolean;\n 'date': string | [string, string]; // ISO date string or [from, to] for between/outside\n 'time': string | [string, string];\n 'datetime': string | [string, string];\n 'reference': string | string[];\n 'string[]': never;\n 'int[]': never;\n 'float[]': never;\n 'boolean[]': never;\n 'date[]': never;\n 'reference[]': never;\n 'image': never;\n 'video': never;\n 'image[]': never;\n 'video[]': never;\n 'json': never;\n};\n\n// Forward declare Filter type for recursive definition\n/**\n * A filter object that can contain:\n * - and: Filter[] - all conditions must be true\n * - or: Filter[] - any condition can be true\n * - Field-specific filters: depends on the field type\n */\ntype Filter = {\n and?: Filter[];\n or?: Filter[];\n [fieldName: string]: any;\n};\n\n/**\n * Helper type to get the operations for a specific field type\n */\ntype OperationsForFieldType<TFieldType extends keyof FieldTypeOperations> =\n TFieldType extends keyof FieldTypeOperations\n ? FieldTypeOperations[TFieldType]\n : never;\n\n/**\n * Helper type to get the value for a specific field type\n */\ntype ValueForFieldType<TFieldType extends keyof FieldTypeValue> =\n TFieldType extends keyof FieldTypeValue\n ? FieldTypeValue[TFieldType]\n : never;\n\n/**\n * Build a field-specific filter based on field type\n * TFieldDef is optional and used for reference fields to provide type safety for nested filters\n */\ntype FieldFilter<TFieldType extends keyof FieldTypeOperations, TFieldDef extends FieldDefinition = any> =\n TFieldType extends 'string[]' | 'int[]' | 'float[]' | 'boolean[]' | 'date[]' | 'reference[]'\n ? {\n none?: ListItemFilter<TFieldType, TFieldDef>;\n any?: ListItemFilter<TFieldType, TFieldDef>;\n every?: ListItemFilter<TFieldType, TFieldDef>;\n }\n : TFieldType extends 'image' | 'video' | 'image[]' | 'video[]' | 'json'\n ? never\n : FieldTypeOperations[TFieldType] extends never\n ? never\n : TFieldType extends 'reference'\n ? (\n TFieldDef extends { type: 'reference'; references: readonly (infer TRef)[] }\n ? TRef extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition }\n ? ReferenceFieldOps<TRef['__definition']> | PolymorphicReferenceOps<TFieldDef['references']>\n : TRef extends ContentTypeDefinition\n ? ReferenceFieldOps<TRef> | PolymorphicReferenceOps<TFieldDef['references']>\n : Filter\n : Filter\n )\n : BuildFieldOperations<TFieldType>;\n\n/**\n * Helper type to build field operations as a union type\n */\ntype BuildFieldOperations<TFieldType extends keyof FieldTypeOperations> =\n TFieldType extends 'id'\n ? IdFieldOps\n : TFieldType extends 'string' | 'text' | 'slug'\n ? StringFieldOps\n : TFieldType extends 'boolean'\n ? BooleanFieldOps\n : TFieldType extends 'int' | 'float'\n ? NumericFieldOps\n : TFieldType extends 'date' | 'time' | 'datetime'\n ? DateTimeFieldOps\n : TFieldType extends 'reference'\n ? Filter // Shouldn't reach here as reference is handled above\n : never;\n\ntype IdFieldOps =\n | { eq: string }\n | { not_eq: string }\n | { in: string[] }\n | { not_in: string[] };\n\ntype StringFieldOps =\n | { is_null: boolean }\n | { is_not_null: boolean }\n | { eq: string }\n | { not_eq: string }\n | { contains: string }\n | { not_contains: string }\n | { starts_with: string }\n | { not_starts_with: string }\n | { ends_with: string }\n | { not_ends_with: string }\n | { in: string[] }\n | { not_in: string[] };\n\ntype BooleanFieldOps =\n | { is_null: boolean }\n | { is_not_null: boolean }\n | { eq: boolean }\n | { not_eq: boolean };\n\ntype NumericFieldOps =\n | { is_null: boolean }\n | { is_not_null: boolean }\n | { eq: number }\n | { not_eq: number }\n | { gt: number }\n | { gte: number }\n | { lt: number }\n | { lte: number }\n | { between: [number, number] }\n | { outside: [number, number] }\n | { in: number[] }\n | { not_in: number[] };\n\ntype DateTimeFieldOps =\n | { is_null: boolean }\n | { is_not_null: boolean }\n | { eq: string }\n | { not_eq: string }\n | { gt: string }\n | { gte: string }\n | { lt: string }\n | { lte: string }\n | { between: [string, string] }\n | { outside: [string, string] };\n\n/**\n * Helper type to extract the definition from a branded content type or return as-is if it's a definition\n */\ntype ExtractDefinition<T> =\n T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition }\n ? T['__definition']\n : T extends ContentTypeDefinition\n ? T\n : never;\n\n/**\n * Build filters for a specific content type schema\n * Includes the implicit 'id' field that all content types have\n */\ntype BuildReferenceFilters<TDef extends ContentTypeDefinition> = {\n and?: BuildReferenceFilters<TDef>[];\n or?: BuildReferenceFilters<TDef>[];\n id?: IdFieldOps; // Add implicit 'id' field that all content types have\n} & {\n [K in keyof TDef['fields']]?: FieldFilter<TDef['fields'][K]['type'], TDef['fields'][K]>;\n};\n\n/**\n * Reference field operations - nested filters for the referenced content type\n */\ntype ReferenceFieldOps<TRefDef extends ContentTypeDefinition | { __isContentTypeDefinition: true; __definition: ContentTypeDefinition }> =\n BuildReferenceFilters<ExtractDefinition<TRefDef>>;\n\n/**\n * Build union filters for polymorphic references\n * When a reference field can point to multiple content types, creates a union of filters for each type\n */\ntype PolymorphicReferenceOps<TRefs extends readonly any[]> =\n TRefs extends readonly [infer TFirst, ...infer TRest]\n ? (\n TFirst extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition }\n ? ReferenceFieldOps<TFirst['__definition']>\n : TFirst extends ContentTypeDefinition\n ? ReferenceFieldOps<TFirst>\n : never\n ) | PolymorphicReferenceOps<TRest>\n : never;\n\n/**\n * Build a filter for items within a reference array\n * For reference arrays, allow filters for any of the referenced types\n * Includes the implicit 'id' field that all references have\n */\ntype ListItemReferenceFilter<TRefs extends readonly any[]> =\n { id: IdFieldOps } | PolymorphicReferenceOps<TRefs>;\n\n/**\n * Build a filter for items within a list\n */\ntype ListItemFilter<TFieldType extends 'string[]' | 'int[]' | 'float[]' | 'boolean[]' | 'date[]' | 'reference[]', TFieldDef extends FieldDefinition = any> =\n TFieldType extends 'string[]'\n ? StringFieldOps\n : TFieldType extends 'int[]'\n ? NumericFieldOps\n : TFieldType extends 'float[]'\n ? NumericFieldOps\n : TFieldType extends 'boolean[]'\n ? BooleanFieldOps\n : TFieldType extends 'date[]'\n ? DateTimeFieldOps\n : TFieldType extends 'reference[]'\n ? (\n TFieldDef extends { type: 'reference[]'; references: readonly (infer TRef)[] }\n ? ListItemReferenceFilter<TFieldDef['references']>\n : Filter\n )\n : never;\n\n/**\n * Type helper for building filter inputs with field-specific operations\n */\nexport type BuildFiltersInput<\n T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }\n> = {\n and?: BuildFiltersInput<T>[];\n or?: BuildFiltersInput<T>[];\n} & {\n [K in keyof T['__fields']]?: FieldFilter<\n T['__definition']['fields'][K & string]['type'] & keyof FieldTypeOperations,\n T['__definition']['fields'][K & string]\n >;\n };\n\n/**\n * Type-safe filter builder for getEntry and getEntries\n * \n * This function validates that filters match the content type definition at compile time\n */\nexport type TypeSafeFilters<\n T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }\n> = BuildFiltersInput<T>;\n\n/**\n * Build a type-safe filter object for a specific content type\n * \n * Example:\n * ```ts\n * const filters = buildFilters(BlogPostContentType, {\n * Title: { eq: 'Hello' }, // ✅ Valid: string field with 'eq'\n * ViewCount: { gt: 10 }, // ✅ Valid: int field with 'gt'\n * Tags: { any: { contains: \"typescript\" } }, // ✅ Valid: string[] with any<contains>\n * // ViewCount: { contains: 'x' } // ❌ Error: 'contains' not valid for int\n * // FeaturedImage: { eq: '...' } // ❌ Error: cannot filter on image\n * });\n * ```\n */\nexport function buildFilters<\n T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }\n>(\n contentTypeDef: T,\n filters: BuildFiltersInput<T>\n): Filter {\n // Convert camelCase field names to snake_case\n const convertToSnakeCase = (str: string): string => {\n return str\n .replace(/([A-Z])/g, (letter) => `_${letter.toLowerCase()}`)\n .replace(/^_/, ''); // Remove leading underscore\n };\n\n // Recursively convert camelCase field names to snake_case for the backend\n const convertFilters = (obj: any): any => {\n if (!obj || typeof obj !== \"object\") {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(convertFilters);\n }\n\n const result: any = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (key === \"and\" || key === \"or\") {\n // These are special operators, keep as-is\n result[key] = Array.isArray(value) ? value.map(convertFilters) : convertFilters(value);\n } else {\n // Convert field name from camelCase to snake_case\n const snakeKey = convertToSnakeCase(key);\n if (value && typeof value === \"object\") {\n result[snakeKey] = convertFilters(value);\n } else {\n result[snakeKey] = value;\n }\n }\n }\n\n return result;\n };\n\n return convertFilters(filters);\n}","// Simple repo-only debug logger.\n// Enable by setting DECOUPLA_DEBUG=1 or DECOUPLA_DEBUG=true in your environment.\nconst ENABLED = (() => {\n const v = process.env.DECOUPLA_DEBUG || process.env.DEBUG || '';\n return v === '1' || v === 'true' || v.toLowerCase() === 'yes';\n})();\n\nexport function debug(...args: any[]) {\n if (!ENABLED) return;\n // eslint-disable-next-line no-console\n console.log(...args);\n}\n\nexport function info(...args: any[]) {\n // info is user-facing; keep visible\n // eslint-disable-next-line no-console\n console.log(...args);\n}\n\nexport function warn(...args: any[]) {\n // eslint-disable-next-line no-console\n console.warn(...args);\n}\n\nexport function error(...args: any[]) {\n // eslint-disable-next-line no-console\n console.error(...args);\n}\n\nexport default { debug, info, warn, error };\n","/**\n * Content Type Definition Utilities\n * \n * This module provides defineContentType and defineConfig utilities.\n * Type checking is done through the BrandedContentType returned by defineContentType,\n * rather than relying on generic type parameters in API functions.\n */\n\nimport type { FieldDefinition, ContentTypeDefinition } from './index';\n\n// ============================================\n// CONTENT TYPE DEFINITION\n// ============================================\n\n/**\n * Branded content type definition with field information\n * Used by defineContentType to preserve schema information that can be\n * extracted and used by API operations for type safety\n */\nexport type BrandedContentType<T extends Record<string, FieldDefinition> = Record<string, FieldDefinition>> = {\n __definition: ContentTypeDefinition;\n __fields: T;\n __isContentTypeDefinition: true;\n};\n\n/**\n * Extract field schema from content type\n */\nexport type ExtractFieldSchema<T extends BrandedContentType<any>> = T['__fields'];\n\n// ============================================\n// CONTENT TYPE DEFINITION HELPER\n// ============================================\n\n/**\n * Define a content type with full type safety and field preservation\n * \n * Used in config files to define content types. The returned object\n * carries type information that API operations can use for type checking.\n * \n * @example\n * export const AuthorContentType = defineContentType({\n * name: 'author',\n * displayName: 'Author',\n * description: 'Blog post authors',\n * fields: {\n * name: { type: 'string', required: true },\n * email: { type: 'string', required: false },\n * } as const,\n * });\n * \n * // Usage in API:\n * const author = await config.createEntry(AuthorContentType, {\n * name: 'John Doe',\n * email: 'john@example.com',\n * });\n */\nexport function defineContentType<T extends Record<string, FieldDefinition>>(config: {\n name: string;\n displayName?: string;\n description?: string;\n fields: T;\n}): BrandedContentType<T> {\n return {\n __definition: {\n name: config.name,\n displayName: config.displayName,\n description: config.description,\n fields: config.fields,\n },\n __fields: config.fields,\n __isContentTypeDefinition: true,\n };\n}\n\n// ============================================\n// CONFIG CREATION TYPE\n// ============================================\n\n/**\n * Type-safe configuration definition helper\n * Creates a config object that can be exported from decoupla.config.ts\n * The CLI tools will import and read this config to get credentials and content types\n * \n * @example\n * export default defineConfig({\n * workspace: 'my-workspace-id',\n * apiToken: 'my-api-token',\n * contentTypes: [BlogPostContentType, AuthorContentType],\n * });\n */\nexport function defineConfig(config: {\n workspace: string;\n apiToken: string;\n contentTypes: Array<BrandedContentType<any>>;\n}): typeof config {\n return config;\n}\n","/**\n * Decoupla TypeScript Client\n * \n * Type-safe API client for the Decoupla content management system.\n * \n * @module decoupla.js\n * \n * Main Exports:\n * - createClient() - Initialize the API client\n * - defineContentType() - Define content types with type safety\n * - defineConfig() - Create configuration with workspace and content types\n * \n * Type Exports:\n * - ContentTypeDefinition - Content type schema definition\n * - FieldDefinition - Field definition type\n * - TypeSafeFilters - Type-safe filter definitions\n * \n * Example:\n * import { createClient, defineContentType } from 'decoupla.js';\n * \n * const Author = defineContentType({\n * name: 'author',\n * fields: { Name: { type: 'string', required: true } }\n * });\n * \n * const client = createClient({\n * workspace: 'my-workspace',\n * apiToken: 'token'\n * });\n * \n * const entry = await client.createEntry('author', { Name: 'John' });\n */\n\nimport { initSchema, requestSchema, type InitSchema, type RequestSchema, snakeToCamel, camelToSnake } from \"./modules/schema\";\nimport type {\n EntryResponse,\n EntriesResponse,\n ErrorResponse,\n InspectResponse,\n ImageObject,\n TextObject,\n PreloadField,\n PreloadSpec,\n PrimitiveFieldType,\n ReferenceFieldType,\n FieldType,\n ReferenceTarget,\n FieldDefinition,\n ContentTypeDefinition,\n SyncOptions,\n SyncAction,\n SyncResult,\n FieldDiff,\n} from \"./types\";\nimport type {\n UploadedFile,\n ImageFile,\n VideoFile,\n UploadFileResponse,\n} from \"./modules/upload\";\nimport type {\n FieldValues,\n EntryMetadata,\n NormalizedEntryMetadata,\n CreateEntryResponse,\n UpdateEntryResponse,\n} from \"./modules/entry\";\nimport {\n validateFile,\n getFileType,\n isSupportedFileFormat,\n} from \"./modules/upload\";\nimport {\n validateFieldValues,\n isValidUUID,\n normalizeFieldValues,\n} from \"./modules/entry\";\nimport { buildCreateFieldRequest, buildUpdateFieldRequest, buildCreateContentTypeRequest } from \"./modules/sync-api\";\nimport type { TypeSafeFilters } from \"./modules/filters\";\nimport { buildFilters } from \"./modules/filters\";\nimport { debug } from './utils/logger';\n\nexport type {\n EntryResponse,\n EntriesResponse,\n ErrorResponse,\n InspectResponse,\n ImageObject,\n TextObject,\n PreloadField,\n PrimitiveFieldType,\n ReferenceFieldType,\n FieldType,\n ReferenceTarget,\n FieldDefinition,\n ContentTypeDefinition,\n SyncOptions,\n SyncAction,\n SyncResult,\n FieldDiff,\n UploadedFile,\n ImageFile,\n VideoFile,\n FieldValues,\n EntryMetadata,\n TypeSafeFilters,\n};\n\nconst {\n DECOUPLA_API_URL_BASE = \"https://api.decoupla.com/public/api/1.0/workspace/\",\n} = process.env;\n\nconst makeRequest = (options: InitSchema) => async <T>(request: RequestSchema): Promise<EntryResponse<T> | EntriesResponse<T> | InspectResponse> => {\n\n const { apiToken, workspace } = options;\n\n const {\n op_type,\n api_type,\n filters,\n type,\n preload,\n sort,\n limit,\n offset,\n } = requestSchema.parse(request);\n\n const sendSort = (sort || []).reduce((acc, [field, direction]) => {\n acc = acc || [];\n acc.push({ field, direction });\n return acc;\n }, undefined as {\n field: string;\n direction: \"ASC\" | \"DESC\";\n }[] | undefined);\n\n // Determine outgoing api_type: inspect doesn't require api_type and we default to 'live' for other ops\n const outgoingApiType = op_type === 'inspect' ? undefined : (api_type ?? 'live');\n\n const requestBody: any = {\n op_type,\n type,\n // pass through entry_id when present (used by get_entry)\n entry_id: (request as any).entry_id,\n filters,\n preload,\n sort: sendSort,\n limit,\n offset,\n };\n\n if (outgoingApiType) requestBody.api_type = outgoingApiType;\n\n const req = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n let respData;\n const responseText = await req.text();\n\n try {\n respData = JSON.parse(responseText);\n } catch (error) {\n console.error('Failed to parse JSON response:', error, 'Status:', req.status);\n console.error('Response body:', responseText);\n throw new Error(`Failed to parse JSON response (HTTP ${req.status}): ${error} | Response was: \"${responseText}\"`);\n }\n\n if ((respData as ErrorResponse).errors) {\n debug(respData);\n console.error('API Error:', (respData as ErrorResponse));\n const errorDetails = (respData as ErrorResponse).errors.map((e: any) => {\n let msg = `${e.field}: ${e.message}`;\n if (e.available_filters) {\n msg += ` | Available filters: ${JSON.stringify(e.available_filters)}`;\n }\n if (e.valid_filters) {\n msg += ` | Valid filters: ${JSON.stringify(e.valid_filters)}`;\n }\n return msg;\n }).join('\\n');\n throw new Error(`API Error:\\n${errorDetails}`);\n }\n\n return respData as EntriesResponse<T> | EntryResponse<T> | InspectResponse;\n}\n\ntype Request = ReturnType<typeof makeRequest>;\n\n/**\n * Helper type to convert a string to camelCase (only lowercase first letter for single words)\n */\ntype CamelCaseField<T extends string> = T extends `${infer First}${infer Rest}`\n ? `${Lowercase<First>}${Rest}`\n : T;\n\n/**\n * Convert PascalCase to camelCase: ViewCount -> viewCount\n */\ntype ToCamelCase<S extends string> =\n S extends `${infer First}${infer Rest}`\n ? `${Lowercase<First>}${Rest}`\n : S;\n\n/**\n * Helper type to build the entry data type from a content type definition\n * Maps field types to their TypeScript value types\n * Required fields are not nullable, optional fields are nullable/undefined\n * Field names are converted to camelCase (ViewCount -> viewCount, IsPublished -> isPublished)\n */\ntype BuildEntryType<TDef extends ContentTypeDefinition> = {\n id: string;\n} & {\n [K in keyof TDef['fields']as K extends string ? ToCamelCase<K> : never]:\n TDef['fields'][K] extends { type: 'string'; required: true }\n ? string\n : TDef['fields'][K] extends { type: 'string' }\n ? string | undefined\n : TDef['fields'][K] extends { type: 'text'; required: true }\n ? string\n : TDef['fields'][K] extends { type: 'text' }\n ? string | undefined\n : TDef['fields'][K] extends { type: 'slug'; required: true }\n ? string\n : TDef['fields'][K] extends { type: 'slug' }\n ? string | undefined\n : TDef['fields'][K] extends { type: 'int'; required: true }\n ? number\n : TDef['fields'][K] extends { type: 'int' }\n ? number | undefined\n : TDef['fields'][K] extends { type: 'float'; required: true }\n ? number\n : TDef['fields'][K] extends { type: 'float' }\n ? number | undefined\n : TDef['fields'][K] extends { type: 'boolean'; required: true }\n ? boolean\n : TDef['fields'][K] extends { type: 'boolean' }\n ? boolean | undefined\n : TDef['fields'][K] extends { type: 'date' | 'datetime' | 'time'; required: true }\n ? string\n : TDef['fields'][K] extends { type: 'date' | 'datetime' | 'time' }\n ? string | undefined\n : TDef['fields'][K] extends { type: 'reference'; required: true; references: infer R }\n ? RefToReturned<R>\n : TDef['fields'][K] extends { type: 'reference'; required: true }\n ? LightweightReference\n : TDef['fields'][K] extends { type: 'reference'; references: infer R }\n ? RefToReturned<R> | undefined\n : TDef['fields'][K] extends { type: 'reference' }\n ? LightweightReference | undefined\n : TDef['fields'][K] extends { type: 'reference[]'; required: true; references: infer R }\n ? RefToReturned<R>[]\n : TDef['fields'][K] extends { type: 'reference[]'; required: true }\n ? LightweightReference[]\n : TDef['fields'][K] extends { type: 'reference[]'; references: infer R }\n ? RefToReturned<R>[] | undefined\n : TDef['fields'][K] extends { type: 'reference[]' }\n ? LightweightReference[] | undefined\n : TDef['fields'][K] extends { type: 'string[]'; required: true }\n ? string[]\n : TDef['fields'][K] extends { type: 'string[]' }\n ? string[] | undefined\n : TDef['fields'][K] extends { type: 'int[]'; required: true }\n ? number[]\n : TDef['fields'][K] extends { type: 'int[]' }\n ? number[] | undefined\n : TDef['fields'][K] extends { type: 'float[]'; required: true }\n ? number[]\n : TDef['fields'][K] extends { type: 'float[]' }\n ? number[] | undefined\n : TDef['fields'][K] extends { type: 'boolean[]'; required: true }\n ? boolean[]\n : TDef['fields'][K] extends { type: 'boolean[]' }\n ? boolean[] | undefined\n : TDef['fields'][K] extends { type: 'date[]' | 'datetime[]' | 'time[]'; required: true }\n ? string[]\n : TDef['fields'][K] extends { type: 'date[]' | 'datetime[]' | 'time[]' }\n ? string[] | undefined\n : TDef['fields'][K] extends { type: 'image'; required: true }\n ? ImageObject\n : TDef['fields'][K] extends { type: 'image' }\n ? ImageObject | undefined\n : TDef['fields'][K] extends { type: 'image[]'; required: true }\n ? ImageObject[]\n : TDef['fields'][K] extends { type: 'image[]' }\n ? ImageObject[] | undefined\n : TDef['fields'][K] extends { type: 'video'; required: true }\n ? TextObject\n : TDef['fields'][K] extends { type: 'video' }\n ? TextObject | undefined\n : TDef['fields'][K] extends { type: 'video[]'; required: true }\n ? TextObject[]\n : TDef['fields'][K] extends { type: 'video[]' }\n ? TextObject[] | undefined\n : TDef['fields'][K] extends { type: 'json'; required: true }\n ? Record<string, any>\n : TDef['fields'][K] extends { type: 'json' }\n ? Record<string, any> | undefined\n : never;\n};\n\n// Helper types to map 'references' metadata (which may be branded content types)\ntype ExtractReferencedFields<R> =\n R extends readonly (infer U)[] ? (\n U extends { __isContentTypeDefinition: true; __fields: infer F } ? F : never\n ) : R extends { __isContentTypeDefinition: true; __fields: infer F } ? F : never;\n\ntype RefToReturned<R> =\n ExtractReferencedFields<R> extends Record<string, FieldDefinition>\n ? (BuildEntryFromFields<ExtractReferencedFields<R>> & { id: string }) | LightweightReference\n : LightweightReference;\n\n// Lightweight representation returned by the server when a reference is not loaded.\n// Previously we allowed plain string IDs in many places; switch to a structured\n// lightweight shape so callers can rely on stable metadata for \"not_loaded\" refs.\ntype LightweightReference = {\n id: string;\n __sys_content_type: 'reference';\n __sys_id: string;\n __sys_state: 'not_loaded';\n};\n\n/**\n * Build an entry type directly from the `fields` object (preserves literal field names/types\n * when content types are created with `defineContentType(... as const)` which stores the\n * fields in the branded `__fields` property).\n */\ntype BuildEntryFromFields<TFields extends Record<string, FieldDefinition>> = {\n id: string;\n} & {\n [K in keyof TFields as K extends string ? ToCamelCase<K> : never]:\n TFields[K] extends { type: 'string'; required: true }\n ? string\n : TFields[K] extends { type: 'string' }\n ? string | undefined\n : TFields[K] extends { type: 'text'; required: true }\n ? string\n : TFields[K] extends { type: 'text' }\n ? string | undefined\n : TFields[K] extends { type: 'slug'; required: true }\n ? string\n : TFields[K] extends { type: 'slug' }\n ? string | undefined\n : TFields[K] extends { type: 'int'; required: true }\n ? number\n : TFields[K] extends { type: 'int' }\n ? number | undefined\n : TFields[K] extends { type: 'float'; required: true }\n ? number\n : TFields[K] extends { type: 'float' }\n ? number | undefined\n : TFields[K] extends { type: 'boolean'; required: true }\n ? boolean\n : TFields[K] extends { type: 'boolean' }\n ? boolean | undefined\n : TFields[K] extends { type: 'date' | 'datetime' | 'time'; required: true }\n ? string\n : TFields[K] extends { type: 'date' | 'datetime' | 'time' }\n ? string | undefined\n : TFields[K] extends { type: 'reference'; required: true; references: infer R }\n ? RefToReturned<R>\n : TFields[K] extends { type: 'reference'; required: true }\n ? (LightweightReference | { id: string })\n : TFields[K] extends { type: 'reference'; references: infer R }\n ? RefToReturned<R> | undefined\n : TFields[K] extends { type: 'reference' }\n ? (LightweightReference | { id: string }) | undefined\n : TFields[K] extends { type: 'reference[]'; required: true; references: infer R }\n ? RefToReturned<R>[]\n : TFields[K] extends { type: 'reference[]'; required: true }\n ? (LightweightReference | { id: string })[]\n : TFields[K] extends { type: 'reference[]'; references: infer R }\n ? RefToReturned<R>[] | undefined\n : TFields[K] extends { type: 'reference[]' }\n ? (LightweightReference | { id: string })[] | undefined\n : TFields[K] extends { type: 'string[]'; required: true }\n ? string[]\n : TFields[K] extends { type: 'string[]' }\n ? string[] | undefined\n : TFields[K] extends { type: 'int[]'; required: true }\n ? number[]\n : TFields[K] extends { type: 'int[]' }\n ? number[] | undefined\n : TFields[K] extends { type: 'float[]'; required: true }\n ? number[]\n : TFields[K] extends { type: 'float[]' }\n ? number[] | undefined\n : TFields[K] extends { type: 'boolean[]'; required: true }\n ? boolean[]\n : TFields[K] extends { type: 'boolean[]' }\n ? boolean[] | undefined\n : TFields[K] extends { type: 'date[]' | 'datetime[]' | 'time[]'; required: true }\n ? string[]\n : TFields[K] extends { type: 'date[]' | 'datetime[]' | 'time[]' }\n ? string[] | undefined\n : TFields[K] extends { type: 'image'; required: true }\n ? ImageObject\n : TFields[K] extends { type: 'image' }\n ? ImageObject | undefined\n : TFields[K] extends { type: 'image[]'; required: true }\n ? ImageObject[]\n : TFields[K] extends { type: 'image[]' }\n ? ImageObject[] | undefined\n : TFields[K] extends { type: 'video'; required: true }\n ? TextObject\n : TFields[K] extends { type: 'video' }\n ? TextObject | undefined\n : TFields[K] extends { type: 'video[]'; required: true }\n ? TextObject[]\n : TFields[K] extends { type: 'video[]' }\n ? TextObject[] | undefined\n : TFields[K] extends { type: 'json'; required: true }\n ? Record<string, any>\n : TFields[K] extends { type: 'json' }\n ? Record<string, any> | undefined\n : never;\n};\n\n// ---------------------------\n// Preload-aware type helpers\n// ---------------------------\n\n// Convert a PreloadField item to a top-level camelCase key\ntype PreloadItemToKey<I> =\n I extends string ? ToCamelCase<I>\n : I extends [infer Key, any] ? Key extends string ? ToCamelCase<Key> : never\n : never;\n\n// Extract top-level preload keys from a PreloadField type P\ntype PreloadKeys<P> = [P] extends [undefined] ? never : (\n P extends Array<infer U> ? PreloadItemToKey<U> : never\n);\n\n// Extract the inner preload tuple for a specific top-level key.\n// If the preload contains the string 'Author' then the inner preload is `undefined`.\n// If the preload contains ['Author', [ ... ]] then the inner preload is that inner array type.\ntype ExtractPreloadForKey<P, Key extends string> = P extends Array<infer U> ? (\n U extends string ? (ToCamelCase<U> extends Key ? undefined : never)\n : U extends [infer Name, infer Inner] ? (Name extends string ? (ToCamelCase<Name> extends Key ? Inner : never) : never)\n : never\n) : never;\n\ntype PreloadForKey<K, P> = [K] extends [string] ? ExtractPreloadForKey<P, ToCamelCase<K & string>> : never;\n\n// Helper to test whether a mapped key K (from TFields) is present in the Preload keys\ntype IsPreloadedKey<K, P> = [PreloadForKey<K, P>] extends [never] ? false : true;\n\n// When a reference field is preloaded, prefer an expanded object (if we can resolve it at compile time)\ntype ExpandRefWhenPreloaded<R, PInner> =\n ExtractReferencedFields<R> extends Record<string, FieldDefinition>\n ? (BuildEntryFromFieldsWithPreload<ExtractReferencedFields<R>, PInner> & { id: string })\n : LightweightReference;\n\n// Build an entry type from fields but if a field name is present in PreloadKeys<P> then\n// reference/reference[] fields are expanded to their target shapes (or at least {id:string})\ntype BuildEntryFromFieldsWithPreload<\n TFields extends Record<string, FieldDefinition>,\n P\n> = {\n id: string;\n} & {\n [K in keyof TFields as K extends string ? ToCamelCase<K> : never]:\n // string\n TFields[K] extends { type: 'string'; required: true }\n ? string\n : TFields[K] extends { type: 'string' }\n ? string | undefined\n // text\n : TFields[K] extends { type: 'text'; required: true }\n ? string\n : TFields[K] extends { type: 'text' }\n ? string | undefined\n // slug\n : TFields[K] extends { type: 'slug'; required: true }\n ? string\n : TFields[K] extends { type: 'slug' }\n ? string | undefined\n // int\n : TFields[K] extends { type: 'int'; required: true }\n ? number\n : TFields[K] extends { type: 'int' }\n ? number | undefined\n // float\n : TFields[K] extends { type: 'float'; required: true }\n ? number\n : TFields[K] extends { type: 'float' }\n ? number | undefined\n // boolean\n : TFields[K] extends { type: 'boolean'; required: true }\n ? boolean\n : TFields[K] extends { type: 'boolean' }\n ? boolean | undefined\n // date/datetime/time\n : TFields[K] extends { type: 'date' | 'datetime' | 'time'; required: true }\n ? string\n : TFields[K] extends { type: 'date' | 'datetime' | 'time' }\n ? string | undefined\n // reference (single) - check preload\n : TFields[K] extends { type: 'reference'; required: true; references: infer R }\n ? IsPreloadedKey<K, P> extends true\n ? ExpandRefWhenPreloaded<R, PreloadForKey<K, P>>\n : RefToReturned<R>\n : TFields[K] extends { type: 'reference'; required: true }\n ? (LightweightReference | { id: string })\n : TFields[K] extends { type: 'reference'; references: infer R }\n ? IsPreloadedKey<K, P> extends true\n ? ExpandRefWhenPreloaded<R, PreloadForKey<K, P>> | undefined\n : (RefToReturned<R> | undefined)\n : TFields[K] extends { type: 'reference' }\n ? (LightweightReference | { id: string }) | undefined\n // reference[]\n : TFields[K] extends { type: 'reference[]'; required: true; references: infer R }\n ? IsPreloadedKey<K, P> extends true\n ? ExpandRefWhenPreloaded<R, PreloadForKey<K, P>>[]\n : RefToReturned<R>[]\n : TFields[K] extends { type: 'reference[]'; required: true }\n ? (LightweightReference | { id: string })[]\n : TFields[K] extends { type: 'reference[]'; references: infer R }\n ? IsPreloadedKey<K, P> extends true\n ? ExpandRefWhenPreloaded<R, PreloadForKey<K, P>>[] | undefined\n : (RefToReturned<R>[] | undefined)\n : TFields[K] extends { type: 'reference[]' }\n ? (LightweightReference | { id: string })[] | undefined\n // arrays and other primitives follow original mapping\n : TFields[K] extends { type: 'string[]'; required: true }\n ? string[]\n : TFields[K] extends { type: 'string[]' }\n ? string[] | undefined\n : TFields[K] extends { type: 'int[]'; required: true }\n ? number[]\n : TFields[K] extends { type: 'int[]' }\n ? number[] | undefined\n : TFields[K] extends { type: 'float[]'; required: true }\n ? number[]\n : TFields[K] extends { type: 'float[]' }\n ? number[] | undefined\n : TFields[K] extends { type: 'boolean[]'; required: true }\n ? boolean[]\n : TFields[K] extends { type: 'boolean[]' }\n ? boolean[] | undefined\n : TFields[K] extends { type: 'date[]' | 'datetime[]' | 'time[]'; required: true }\n ? string[]\n : TFields[K] extends { type: 'date[]' | 'datetime[]' | 'time[]' }\n ? string[] | undefined\n : TFields[K] extends { type: 'image'; required: true }\n ? ImageObject\n : TFields[K] extends { type: 'image' }\n ? ImageObject | undefined\n : TFields[K] extends { type: 'image[]'; required: true }\n ? ImageObject[]\n : TFields[K] extends { type: 'image[]' }\n ? ImageObject[] | undefined\n : TFields[K] extends { type: 'video'; required: true }\n ? TextObject\n : TFields[K] extends { type: 'video' }\n ? TextObject | undefined\n : TFields[K] extends { type: 'video[]'; required: true }\n ? TextObject[]\n : TFields[K] extends { type: 'video[]' }\n ? TextObject[] | undefined\n : TFields[K] extends { type: 'json'; required: true }\n ? Record<string, any>\n : TFields[K] extends { type: 'json' }\n ? Record<string, any> | undefined\n : never;\n };\n\nconst getEntry = (request: Request) =>\n async <T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }, const P extends PreloadSpec<T> | undefined = undefined>(\n contentTypeDef: T,\n entryId: string,\n options?: {\n preload?: P;\n /** Preferred client option name: selects which dataset (live vs preview) to read. */\n contentView?: 'live' | 'preview';\n }\n ): Promise<{ data: BuildEntryFromFieldsWithPreload<T['__fields'], P> & NormalizedEntryMetadata }> => {\n // For get_entry, entry_id is a top-level parameter, not in filters\n // Normalize preload shapes to the backend's nested-array grammar\n const normalizePreload = (p: any): any => {\n if (!Array.isArray(p)) return p;\n const out: any[] = [];\n for (const item of p) {\n if (typeof item === 'string') {\n out.push(camelToSnake(item));\n continue;\n }\n if (!Array.isArray(item)) {\n out.push(item);\n continue;\n }\n const [key, inner] = item;\n // If inner is null/undefined, treat as simple string preload\n if (inner == null) {\n out.push(camelToSnake(key));\n continue;\n }\n\n // Determine inner as an array of preload items.\n let innerArr: any[];\n if (typeof inner === 'string') {\n innerArr = [inner];\n } else if (Array.isArray(inner)) {\n // If inner looks like a single tuple [string, ...], treat it as one item and wrap it.\n if (inner.length === 2 && typeof inner[0] === 'string' && (Array.isArray(inner[1]) || inner[1] == null)) {\n innerArr = [inner];\n } else {\n innerArr = inner;\n }\n } else {\n innerArr = [inner];\n }\n\n out.push([camelToSnake(key), normalizePreload(innerArr)]);\n }\n return out;\n };\n\n const chosenApiType = options?.contentView ?? 'live';\n\n const reqBody = {\n op_type: 'get_entry',\n type: contentTypeDef.__definition.name,\n entry_id: entryId,\n preload: normalizePreload(options?.preload || []),\n api_type: chosenApiType,\n } as any;\n\n try { debug('[getEntry] request body:', JSON.stringify(reqBody)); } catch (e) { }\n\n // Use the shared request helper which already handles auth/errors/parsing\n const resp = await request(reqBody as any) as any;\n\n try { debug('[getEntry] raw response:', JSON.stringify(resp, null, 2)); } catch (e) { }\n\n const entry = resp?.data?.entry || resp?.data?.node;\n\n // Normalize snake_case field names to camelCase for the flat response\n const normalizedEntry: Record<string, any> = {};\n for (const [key, value] of Object.entries(entry || {})) {\n normalizedEntry[snakeToCamel(key)] = value;\n }\n\n return {\n data: normalizedEntry as BuildEntryFromFieldsWithPreload<T['__fields'], P> & NormalizedEntryMetadata,\n };\n }\n\nconst inspect = (request: Request) =>\n async () => {\n const resp = await request({\n op_type: 'inspect',\n });\n\n return resp as InspectResponse;\n }\n\nconst getEntries = (request: Request) =>\n async <T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }, const P extends PreloadSpec<T> | undefined = undefined>(\n contentTypeDef: T,\n options: {\n filters: TypeSafeFilters<T>;\n limit?: number;\n offset?: number;\n preload?: P;\n sort?: [string, \"ASC\" | \"DESC\"];\n contentView?: 'live' | 'preview';\n }\n ): Promise<EntriesResponse<BuildEntryFromFieldsWithPreload<T['__fields'], P>>> => {\n const {\n filters,\n limit,\n offset,\n preload = [] as any,\n sort = [],\n contentView: optContentView,\n } = options as any;\n\n const api_type = optContentView ?? 'live';\n\n // Normalize preload shapes to the backend's nested-array grammar (same as getEntry)\n const normalizePreload = (p: any): any => {\n if (!Array.isArray(p)) return p;\n const out: any[] = [];\n for (const item of p) {\n if (typeof item === 'string') {\n out.push(camelToSnake(item));\n continue;\n }\n if (!Array.isArray(item)) {\n out.push(item);\n continue;\n }\n const [key, inner] = item;\n if (inner == null) {\n out.push(camelToSnake(key));\n continue;\n }\n let innerArr: any[];\n if (typeof inner === 'string') {\n innerArr = [inner];\n } else if (Array.isArray(inner)) {\n if (inner.length === 2 && typeof inner[0] === 'string' && (Array.isArray(inner[1]) || inner[1] == null)) {\n innerArr = [inner];\n } else {\n innerArr = inner;\n }\n } else {\n innerArr = [inner];\n }\n out.push([camelToSnake(key), normalizePreload(innerArr)]);\n }\n return out;\n };\n\n // Convert camelCase field names to snake_case using buildFilters\n let backendFilters = buildFilters(contentTypeDef, filters);\n\n // Handle reference field naming: backend expects {fieldName}_{contentTypeName}_filter\n // First, get the inspect data to map UUIDs to content type names\n try {\n const inspectResult = await inspect(request)();\n\n // Build a mapping of reference type UUIDs to content type names/slugs\n const uuidToContentTypeName = new Map<string, string>();\n inspectResult.data.content_types.forEach((ct: any) => {\n // Use slug if available, otherwise fall back to id\n const contentTypeName = ct.slug || ct.id;\n uuidToContentTypeName.set(ct.id, contentTypeName);\n });\n\n // Build a mapping of field names to their reference content types\n // We'll use the backend's field metadata to determine the correct reference types\n const fieldReferenceMap = new Map<string, string[]>();\n\n // Find the current content type in the inspect response\n const currentCTMetadata = inspectResult.data.content_types.find((ct: any) =>\n ct.slug === contentTypeDef.__definition.name || ct.id === contentTypeDef.__definition.name\n );\n\n if (currentCTMetadata && currentCTMetadata.fields) {\n // Use the metadata from the backend to get the reference types\n currentCTMetadata.fields.forEach((field: any) => {\n if ((field.type === 'reference' || field.type === 'reference[]') && field.meta?.reference_types) {\n // Support polymorphic references - store ALL reference types for this field\n const contentTypeNames = field.meta.reference_types\n .map((refTypeId: string) => uuidToContentTypeName.get(refTypeId) || refTypeId);\n // field.slug is already in snake_case from the backend\n fieldReferenceMap.set(field.slug, contentTypeNames);\n }\n });\n }\n\n // Transform filter field names for reference fields\n // Reference filters are already in the correct nested structure from the user:\n // Author: { id: { eq: \"123\" } } or Author: { name: { starts_with: \"John\" } }\n // For polymorphic references, we can also filter by specific type:\n // Speakers: { Author: { id: { eq: \"123\" } } } filters speakers that are Authors\n // We rename the field from Author to author_author_filter or speakers_author_filter\n const transformReferenceFilters = (obj: any, referenceMap: Map<string, string[]>, depth = 0): any => {\n if (!obj || typeof obj !== \"object\") {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => transformReferenceFilters(item, referenceMap, depth + 1));\n }\n\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n if (key === \"and\" || key === \"or\") {\n // Logical operators: transform their contents\n result[key] = Array.isArray(value)\n ? (value as any[]).map(v => transformReferenceFilters(v, referenceMap, depth + 1))\n : transformReferenceFilters(value, referenceMap, depth + 1);\n } else if (referenceMap.has(key)) {\n // This is a reference field - rename it and pass through the nested structure as-is\n const contentTypeNames = referenceMap.get(key)!;\n const valueAsObj = value && typeof value === \"object\" ? (value as Record<string, any>) : {};\n const valueKeys = Object.keys(valueAsObj);\n\n // Check if value has list operators (any, none, every) for reference arrays\n const listOperator = valueKeys.find(vk => ['any', 'none', 'every'].includes(vk));\n\n if (listOperator) {\n // This is a reference array filter with list operator\n // Extract the inner filter that may have type-specific filters\n const innerFilter = valueAsObj[listOperator];\n const innerFilterObj = innerFilter && typeof innerFilter === \"object\" ? innerFilter as Record<string, any> : {};\n const innerKeys = Object.keys(innerFilterObj);\n // Handle both original case (Author) and snake_case (author) versions\n const innerSpecifiedType = innerKeys.find(ik =>\n contentTypeNames.includes(ik) || // Original case: Author, Product, etc.\n contentTypeNames.some(ct => snakeToCamel(ik) === ct) // Snake case: author -> Author\n );\n\n if (innerSpecifiedType && innerFilterObj[innerSpecifiedType]) {\n // Type-specific filter inside list operator\n // Normalize the type name to original case for the filter key\n const normalizedType = contentTypeNames.includes(innerSpecifiedType)\n ? innerSpecifiedType\n : snakeToCamel(innerSpecifiedType);\n const newKey = `${key}_${normalizedType}_filter`;\n const transformedInner = transformReferenceFilters(innerFilterObj[innerSpecifiedType], referenceMap, depth + 1);\n result[newKey] = {\n [listOperator]: transformedInner\n };\n } else {\n // No type specified, use first available type\n const contentTypeName = contentTypeNames[0];\n const newKey = `${key}_${contentTypeName}_filter`;\n const transformedInner = transformReferenceFilters(innerFilter, referenceMap, depth + 1);\n result[newKey] = {\n [listOperator]: transformedInner\n };\n }\n } else {\n // Regular reference filter (not an array)\n // Check if value is a type-specific filter\n // Need to handle both original case (Author) and snake_case (author) versions\n const specifiedType = valueKeys.find(vk =>\n contentTypeNames.includes(vk) || // Original case: Author, Product, etc.\n contentTypeNames.some(ct => snakeToCamel(vk) === ct) // Snake case: author -> Author\n );\n\n if (specifiedType && valueAsObj[specifiedType]) {\n // User specified a type-specific filter: field: { TypeName: { ... } } or { type_name: { ... } }\n // Normalize the type name to original case for the filter key\n const normalizedType = contentTypeNames.includes(specifiedType)\n ? specifiedType\n : snakeToCamel(specifiedType);\n const newKey = `${key}_${normalizedType}_filter`;\n result[newKey] = transformReferenceFilters(valueAsObj[specifiedType], referenceMap, depth + 1);\n } else {\n // No type specified, use first available type or treat as direct filter\n const contentTypeName = contentTypeNames[0];\n const newKey = `${key}_${contentTypeName}_filter`;\n result[newKey] = value && typeof value === \"object\"\n ? transformReferenceFilters(value, referenceMap, depth + 1)\n : value;\n }\n }\n } else {\n // Regular field\n result[key] = value && typeof value === \"object\"\n ? transformReferenceFilters(value, referenceMap, depth + 1)\n : value;\n }\n }\n return result;\n };\n\n backendFilters = transformReferenceFilters(backendFilters, fieldReferenceMap);\n } catch (error) {\n // If inspection fails, log but continue with the original filters\n console.warn('Failed to transform reference field filters:', error);\n }\n\n const reqBody: any = {\n type: contentTypeDef.__definition.name,\n op_type: 'get_entries',\n api_type,\n limit,\n offset,\n filters: backendFilters,\n preload: normalizePreload(preload),\n sort,\n };\n try { debug('[getEntries] request body:', JSON.stringify(reqBody, null, 2)); } catch (e) { }\n const resp = await request<any[]>(reqBody as any);\n\n try { debug('[getEntries] raw response:', JSON.stringify(resp, null, 2)); } catch (e) { }\n\n // Normalize field names from snake_case to camelCase\n let normalizedEntries = (resp as any).data?.map((entry: any) => {\n const normalized: Record<string, any> = { id: entry.id };\n for (const [key, value] of Object.entries(entry)) {\n if (key !== 'id') {\n normalized[snakeToCamel(key)] = value;\n }\n }\n return normalized;\n }) as Array<BuildEntryFromFieldsWithPreload<T['__fields'], P>>;\n\n // Rely on server-side preload expansion for get_entries responses. Client-side per-entry\n // expansion/fetching has been removed to avoid extra round-trips.\n\n return {\n ...resp,\n data: normalizedEntries\n } as EntriesResponse<BuildEntryFromFieldsWithPreload<T['__fields'], P>>;\n };\n\nconst sync = (request: Request) => {\n return async (\n contentTypes: (ContentTypeDefinition | { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> })[],\n options: SyncOptions = {}\n ): Promise<SyncResult> => {\n const {\n fetchRemote,\n createContentType,\n dryRun = true,\n createMissing = true,\n } = options;\n\n // Normalize content types: extract definition from branded types\n const normalizedContentTypes = contentTypes.map(ct => {\n if ('__definition' in ct) {\n return ct.__definition;\n }\n return ct;\n }) as ContentTypeDefinition[];\n\n try {\n debug('[syncWithFields] normalizedContentTypes:', normalizedContentTypes.map(ct => ct.name));\n } catch (e) {\n // ignore\n }\n\n // Inspect the remote to get current state\n let remoteInspect: InspectResponse | null = null;\n try {\n remoteInspect = await inspect(request)();\n } catch (e) {\n // if inspection fails, log but continue with empty state\n console.warn('Failed to inspect remote:', e);\n remoteInspect = null;\n }\n\n // Build remote content type map from inspect response\n // First, create a mapping of content type IDs to names\n const contentTypeIdToName = new Map<string, string>();\n const contentTypeNameToId = new Map<string, string>();\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n // Prefer the slug when available; fallback to id\n const name = (ct as any).slug || ct.id;\n contentTypeIdToName.set(ct.id, name);\n contentTypeNameToId.set(name, ct.id);\n });\n }\n\n const remoteMap = new Map<string, {\n id: string;\n fields: Map<string, {\n id: string;\n slug: string; // snake_case slug from remote\n type: FieldType;\n is_label: boolean;\n required: boolean;\n reference_types?: string[];\n }>;\n }>();\n\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n const fieldsMap = new Map<string, any>();\n ct.fields.forEach(f => {\n // Convert reference type IDs to names\n const referenceNames = (f.meta?.reference_types || [])\n .map(refId => contentTypeIdToName.get(refId) || refId)\n .filter(Boolean);\n\n // Use slug (in snake_case) as the key, as it comes from the remote\n fieldsMap.set(f.slug, {\n id: f.id,\n slug: f.slug,\n type: f.type,\n is_label: f.is_label,\n required: f.required,\n reference_types: referenceNames,\n });\n });\n const name = (ct as any).slug || ct.id;\n remoteMap.set(name, {\n id: ct.id,\n fields: fieldsMap,\n });\n });\n }\n\n const actions: SyncAction[] = [];\n\n for (const ct of normalizedContentTypes) {\n const remoteContentType = remoteMap.get(ct.name);\n\n if (!remoteContentType) {\n // Content type missing remotely\n if (createMissing && createContentType) {\n actions.push({ type: 'create', contentType: ct.name, detail: { reason: 'missing_content_type', contentType: ct } });\n if (!dryRun) {\n try {\n await createContentType(ct);\n } catch (e) {\n actions.push({ type: 'mismatch', contentType: ct.name, detail: { reason: 'create_failed', error: String(e) } });\n }\n }\n } else {\n actions.push({ type: 'skip', contentType: ct.name, detail: { reason: 'missing_content_type' } });\n }\n continue;\n }\n\n // Content type exists, check fields\n const fieldDiffs: any[] = [];\n const remoteFields = remoteContentType.fields;\n const desiredFields = ct.fields || {};\n\n // Check for missing fields in remote\n for (const [fname, fdef] of Object.entries(desiredFields)) {\n // Convert camelCase field name to snake_case to match remote slugs\n const remoteFieldSlug = camelToSnake(fname);\n const remoteField = remoteFields.get(remoteFieldSlug);\n\n if (!remoteField) {\n fieldDiffs.push({\n field: fname,\n reason: 'missing_field',\n desired: {\n type: fdef.type,\n required: fdef.required ?? false,\n isLabel: fdef.isLabel ?? false,\n }\n });\n continue;\n }\n\n // Field exists, check for changes\n const changes: any = {};\n\n // Check type mismatch\n if (remoteField.type !== fdef.type) {\n changes.type = {\n existing: remoteField.type,\n desired: fdef.type,\n };\n }\n\n // Check required mismatch\n const desiredRequired = fdef.required ?? false;\n if (remoteField.required !== desiredRequired) {\n changes.required = {\n existing: remoteField.required,\n desired: desiredRequired,\n };\n }\n\n // Check isLabel mismatch\n const desiredIsLabel = fdef.isLabel ?? false;\n if (remoteField.is_label !== desiredIsLabel) {\n changes.isLabel = {\n existing: remoteField.is_label,\n desired: desiredIsLabel,\n };\n }\n\n // Check references for reference types\n if ((fdef.type === 'reference' || fdef.type === 'reference[]') && fdef.references) {\n const desiredReferences = fdef.references\n .map(ref => typeof ref === 'string' ? ref : ref.__definition.name)\n .sort();\n const existingReferences = (remoteField.reference_types || []).sort();\n\n if (JSON.stringify(desiredReferences) !== JSON.stringify(existingReferences)) {\n changes.references = {\n existing: existingReferences,\n desired: desiredReferences,\n };\n }\n }\n\n if (Object.keys(changes).length > 0) {\n fieldDiffs.push({\n field: fname,\n reason: 'field_changes',\n changes,\n });\n }\n }\n\n // Check for extra fields in remote that aren't in desired\n for (const [remoteFieldSlug, remoteField] of remoteFields) {\n // Convert snake_case slug back to camelCase to check against local field names\n const camelCaseFieldName = snakeToCamel(remoteFieldSlug);\n if (!(camelCaseFieldName in desiredFields)) {\n fieldDiffs.push({\n field: remoteFieldSlug,\n reason: 'extra_field_remote',\n existing: {\n type: remoteField.type,\n required: remoteField.required,\n isLabel: remoteField.is_label,\n }\n });\n }\n }\n\n if (fieldDiffs.length === 0) {\n actions.push({ type: 'noop', contentType: ct.name });\n } else {\n actions.push({ type: 'mismatch', contentType: ct.name, detail: { fieldDiffs } });\n }\n }\n\n return { actions };\n }\n}\n\n/**\n * Enhanced sync function that can create, update, and delete fields in addition to content types.\n * This version works with the backend API and supports full field synchronization.\n */\nconst syncWithFields = (request: Request) => {\n return async (\n contentTypes: (ContentTypeDefinition | { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> })[],\n options: SyncOptions = {}\n ): Promise<SyncResult> => {\n const {\n createContentType,\n createField,\n updateField,\n deleteField,\n dryRun = true,\n createMissing = true,\n createMissingFields = true,\n updateFields = true,\n deleteExtraFields = false,\n } = options;\n\n // Normalize content types: extract definition from branded types\n const normalizedContentTypes = contentTypes.map(ct => {\n if ('__definition' in ct) {\n return ct.__definition;\n }\n return ct;\n }) as ContentTypeDefinition[];\n\n // Inspect the remote to get current state\n let remoteInspect: InspectResponse | null = null;\n try {\n remoteInspect = await inspect(request)();\n } catch (e) {\n console.warn('Failed to inspect remote:', e);\n remoteInspect = null;\n }\n\n // Build remote content type mappings\n const contentTypeIdToName = new Map<string, string>();\n const contentTypeNameToId = new Map<string, string>();\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n // Use slug when available, otherwise fall back to id.\n const name = (ct as any).slug || ct.id;\n contentTypeIdToName.set(ct.id, name);\n contentTypeNameToId.set(name, ct.id);\n });\n }\n\n const remoteMap = new Map<string, {\n id: string;\n fields: Map<string, {\n id: string;\n slug: string;\n type: FieldType;\n is_label: boolean;\n required: boolean;\n reference_types?: string[];\n }>;\n }>();\n\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n const fieldsMap = new Map<string, any>();\n ct.fields.forEach(f => {\n const referenceNames = (f.meta?.reference_types || [])\n .map(refId => contentTypeIdToName.get(refId) || refId)\n .filter(Boolean);\n\n fieldsMap.set(f.slug, {\n id: f.id,\n slug: f.slug,\n type: f.type,\n is_label: f.is_label,\n required: f.required,\n reference_types: referenceNames,\n });\n });\n\n const name = (ct as any).slug || ct.id;\n remoteMap.set(name, {\n id: ct.id,\n fields: fieldsMap,\n });\n });\n }\n\n try {\n debug('[syncWithFields] remoteMap keys:', Array.from(remoteMap.keys()));\n } catch (e) { }\n\n const actions: SyncAction[] = [];\n\n // ============================================\n // PHASE 1: Create all missing content types first\n // ============================================\n for (const ct of normalizedContentTypes) {\n const remoteContentType = remoteMap.get(ct.name);\n\n if (!remoteContentType) {\n // Content type missing remotely\n if (createMissing && createContentType) {\n actions.push({ type: 'create', contentType: ct.name, detail: { reason: 'missing_content_type' } });\n if (!dryRun) {\n try {\n await createContentType(ct);\n // After creating, add to our mapping so it's available for reference resolution\n contentTypeNameToId.set(ct.name, ct.name);\n } catch (e) {\n actions.push({ type: 'mismatch', contentType: ct.name, detail: { reason: 'create_failed', error: String(e) } });\n }\n }\n } else {\n actions.push({ type: 'skip', contentType: ct.name, detail: { reason: 'missing_content_type' } });\n }\n }\n }\n\n // ============================================\n // PHASE 2: Refresh inspect if we created content types\n // ============================================\n if (!dryRun) {\n try {\n remoteInspect = await inspect(request)();\n // Rebuild the mapping with fresh data\n contentTypeIdToName.clear();\n contentTypeNameToId.clear();\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n const name = (ct as any).slug || ct.id;\n contentTypeIdToName.set(ct.id, name);\n contentTypeNameToId.set(name, ct.id);\n });\n }\n // Rebuild remoteMap\n remoteMap.clear();\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n const fieldsMap = new Map<string, any>();\n ct.fields.forEach(f => {\n const referenceNames = (f.meta?.reference_types || [])\n .map(refId => contentTypeIdToName.get(refId) || refId)\n .filter(Boolean);\n\n fieldsMap.set(f.slug, {\n id: f.id,\n slug: f.slug,\n type: f.type,\n is_label: f.is_label,\n required: f.required,\n reference_types: referenceNames,\n });\n });\n\n const name = (ct as any).slug || ct.id;\n // Use the content type slug/name as the key so lookups by ct.name succeed\n remoteMap.set(name, {\n id: ct.id,\n fields: fieldsMap,\n });\n });\n }\n } catch (e) {\n console.warn('Failed to refresh inspect after creating content types:', e);\n }\n }\n\n // ============================================\n // PHASE 3: Now process fields with complete mapping\n // ============================================\n try {\n debug('[syncWithFields] starting field checks for', normalizedContentTypes.map(ct => ct.name));\n } catch (e) { }\n for (const ct of normalizedContentTypes) {\n try {\n const remote = remoteMap.get(ct.name);\n debug(`[syncWithFields] checking contentType=${String(ct.name)} (type=${typeof ct.name}, json=${JSON.stringify(ct.name)}) remoteHas=${remoteMap.has(ct.name)}`);\n } catch (e) { }\n const remoteContentType = remoteMap.get(ct.name);\n\n if (!remoteContentType) {\n // Content type still missing (wasn't created, was skipped)\n continue;\n }\n\n // Content type exists, check fields\n const fieldDiffs: FieldDiff[] = [];\n const remoteFields = remoteContentType.fields;\n const desiredFields = ct.fields || {};\n const fieldsToCreate: Array<{ name: string; def: FieldDefinition }> = [];\n const fieldsToUpdate: Array<{ id: string; name: string; changes: Record<string, any> }> = [];\n const fieldsToDelete: string[] = [];\n\n // Check for missing fields in remote\n for (const [fname, fdef] of Object.entries(desiredFields)) {\n const remoteFieldSlug = camelToSnake(fname);\n const remoteField = remoteFields.get(remoteFieldSlug);\n\n if (!remoteField) {\n fieldDiffs.push({\n field: fname,\n reason: 'missing_field',\n desired: {\n type: fdef.type,\n required: fdef.required ?? false,\n isLabel: fdef.isLabel ?? false,\n }\n });\n if (createMissingFields && createField) {\n fieldsToCreate.push({ name: fname, def: fdef });\n }\n continue;\n }\n\n // Field exists, check for changes\n const changes: any = {};\n\n if (remoteField.type !== fdef.type) {\n changes.type = {\n existing: remoteField.type,\n desired: fdef.type,\n };\n }\n\n const desiredRequired = fdef.required ?? false;\n if (remoteField.required !== desiredRequired) {\n changes.required = {\n existing: remoteField.required,\n desired: desiredRequired,\n };\n }\n\n const desiredIsLabel = fdef.isLabel ?? false;\n if (remoteField.is_label !== desiredIsLabel) {\n changes.isLabel = {\n existing: remoteField.is_label,\n desired: desiredIsLabel,\n };\n }\n\n if ((fdef.type === 'reference' || fdef.type === 'reference[]') && fdef.references) {\n const desiredReferences = fdef.references\n .map(ref => typeof ref === 'string' ? ref : ref.__definition.name)\n .sort();\n const existingReferences = (remoteField.reference_types || []).sort();\n\n if (JSON.stringify(desiredReferences) !== JSON.stringify(existingReferences)) {\n changes.references = {\n existing: existingReferences,\n desired: desiredReferences,\n };\n }\n }\n\n if (Object.keys(changes).length > 0) {\n fieldDiffs.push({\n field: fname,\n reason: 'field_changes',\n changes,\n });\n if (updateFields && updateField) {\n const updateChanges: any = {\n required: desiredRequired,\n description: fdef.settings?.description,\n };\n\n // Include reference types if the field is a reference type and references are defined\n if ((fdef.type === 'reference' || fdef.type === 'reference[]') && fdef.references && changes.references) {\n updateChanges.references = fdef.references\n .map(ref => typeof ref === 'string' ? ref : ref.__definition.name);\n }\n\n fieldsToUpdate.push({\n id: remoteField.id,\n name: fname,\n changes: updateChanges,\n });\n }\n }\n }\n\n // Check for extra fields in remote\n for (const [remoteFieldSlug, remoteField] of remoteFields) {\n const camelCaseFieldName = snakeToCamel(remoteFieldSlug);\n if (!(camelCaseFieldName in desiredFields)) {\n fieldDiffs.push({\n field: remoteFieldSlug,\n reason: 'extra_field_remote',\n existing: {\n type: remoteField.type,\n required: remoteField.required,\n isLabel: remoteField.is_label,\n }\n });\n if (deleteExtraFields && deleteField) {\n fieldsToDelete.push(remoteField.id);\n }\n }\n }\n\n // Execute field operations\n if (fieldsToCreate.length > 0 && !dryRun) {\n for (const { name, def } of fieldsToCreate) {\n try {\n // Resolve reference names to IDs for the callback\n const defWithResolvedReferences = { ...def };\n if ((def.type === 'reference' || def.type === 'reference[]') && def.references) {\n defWithResolvedReferences.references = def.references\n .map(ref => {\n const refName = typeof ref === 'string' ? ref : ref.__definition.name;\n return contentTypeNameToId.get(refName) || refName;\n })\n .filter(Boolean) as any[];\n }\n await createField!(remoteContentType.id, name, defWithResolvedReferences);\n } catch (e) {\n fieldDiffs.push({\n field: name,\n reason: 'missing_field',\n desired: {\n type: def.type,\n required: def.required ?? false,\n isLabel: def.isLabel ?? false,\n }\n });\n }\n }\n }\n\n if (fieldsToUpdate.length > 0 && !dryRun) {\n for (const { id, changes } of fieldsToUpdate) {\n try {\n // Resolve reference names to IDs if needed\n const resolvedChanges = { ...changes };\n if (resolvedChanges.references && Array.isArray(resolvedChanges.references)) {\n resolvedChanges.references = resolvedChanges.references\n .map(ref => contentTypeNameToId.get(ref) || ref)\n .filter(Boolean);\n }\n await updateField!(id, resolvedChanges);\n } catch (e) {\n console.warn(`Failed to update field ${id}:`, e);\n }\n }\n }\n\n if (fieldsToDelete.length > 0 && !dryRun) {\n for (const id of fieldsToDelete) {\n try {\n await deleteField!(id);\n } catch (e) {\n console.warn(`Failed to delete field ${id}:`, e);\n }\n }\n }\n\n // Determine action type\n if (fieldDiffs.length === 0) {\n actions.push({ type: 'noop', contentType: ct.name });\n } else if (fieldsToCreate.length > 0) {\n actions.push({ type: 'create_fields', contentType: ct.name, detail: { fieldDiffs, created: fieldsToCreate.length } });\n } else if (fieldsToUpdate.length > 0) {\n actions.push({ type: 'update_fields', contentType: ct.name, detail: { fieldDiffs, updated: fieldsToUpdate.length } });\n } else if (fieldsToDelete.length > 0) {\n actions.push({ type: 'delete_fields', contentType: ct.name, detail: { fieldDiffs, deleted: fieldsToDelete.length } });\n } else {\n actions.push({ type: 'mismatch', contentType: ct.name, detail: { fieldDiffs } });\n }\n }\n\n // Debug: when running a non-dry run from CLI show resolved actions for visibility\n try {\n if (actions && actions.length > 0) {\n debug('[syncWithFields] Resolved actions:', JSON.stringify(actions.map(a => ({ type: a.type, contentType: a.contentType, detail: a.detail })), null, 2));\n } else {\n debug('[syncWithFields] No actions resolved');\n }\n } catch (e) {\n // swallow JSON errors\n }\n\n return { actions };\n }\n}\n\n/**\n * Define a content type with full type safety and field preservation\n * \n * Creates a branded type that preserves field schema information for the CLI tools.\n * Can be used directly in config files or with the generic API methods.\n * \n * Example:\n * const Author = defineContentType({\n * name: 'author',\n * displayName: 'Author',\n * fields: {\n * id: { type: 'string', required: true },\n * name: { type: 'string', required: true },\n * status: { type: 'string', options: ['active', 'inactive'] },\n * }\n * });\n * \n * const Article = defineContentType({\n * name: 'article',\n * fields: {\n * author: { type: 'reference', references: [Author] }\n * }\n * });\n * \n * Usage:\n * - In config files: export default { contentTypes: [Author, Article] };\n * - Type checking done through the returned BrandedContentType\n */\n\n/**\n * Upload a file (image or video) to the backend\n */\nconst upload = (options: InitSchema) => async (file: File | Blob, filename?: string): Promise<UploadedFile> => {\n const { apiToken, workspace } = options;\n\n // If Blob is provided, we need a filename\n if (!(file instanceof File) && !filename) {\n throw new Error('Filename is required when uploading a Blob');\n }\n\n const fname = file instanceof File ? file.name : filename!;\n\n // Validate file format\n const validation = validateFile(new File([file], fname));\n if (!validation.valid) {\n throw new Error(validation.error);\n }\n\n // Create FormData\n const formData = new FormData();\n formData.append('op_type', 'upload_file');\n formData.append('file', file, fname);\n\n // Make the upload request\n const response = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: formData,\n });\n\n const respData = await response.json() as any;\n\n if ((respData as any).errors) {\n console.error('Upload Error:', respData);\n throw new Error(`Upload failed: ${(respData as any).errors.map((e: any) => e.message).join(', ')}`);\n }\n\n const uploadResponse = respData as UploadFileResponse;\n return uploadResponse.data.file;\n};\n\n/**\n * Normalize EntryMetadata field names from snake_case to camelCase\n */\nconst normalizeEntryMetadata = (entry: EntryMetadata): NormalizedEntryMetadata => ({\n id: entry.id,\n modelId: entry.model_id,\n state: entry.state,\n lastVersion: entry.last_version,\n lastPublishedVersion: entry.last_published_version,\n createdAt: entry.created_at,\n updatedAt: entry.updated_at,\n});\n\n/**\n * Create a new entry (instance of a content type)\n */\nconst createEntry = (options: InitSchema) => async <T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }, const P extends PreloadSpec<T> | undefined = undefined>(\n contentTypeDef: T,\n fieldValues: FieldValues,\n // Backwards-compatible: callers historically passed a boolean `published` as the 3rd arg.\n // New signature accepts an options object { published?, preload? }.\n optionsParam?: boolean | {\n published?: boolean;\n preload?: P;\n }\n): Promise<NormalizedEntryMetadata> => {\n const { apiToken, workspace } = options;\n // Normalize optionsParam to the object shape\n const opts = typeof optionsParam === 'boolean' ? { published: optionsParam } : (optionsParam || {});\n const published = opts.published ?? true;\n\n // Validate field values\n const validation = validateFieldValues(fieldValues);\n if (!validation.valid) {\n throw new Error(validation.error || 'Invalid field values');\n }\n\n // Normalize field values\n const normalizedFieldValues = normalizeFieldValues(fieldValues);\n\n // Normalize preload shapes to the backend's nested-array grammar (same as getEntry/getEntries)\n const normalizePreload = (p: any): any => {\n if (!Array.isArray(p)) return p;\n const out: any[] = [];\n for (const item of p) {\n if (typeof item === 'string') {\n out.push(camelToSnake(item));\n continue;\n }\n if (!Array.isArray(item)) {\n out.push(item);\n continue;\n }\n const [key, inner] = item;\n // If inner is null/undefined, treat as simple string preload\n if (inner == null) {\n out.push(camelToSnake(key));\n continue;\n }\n\n // Determine inner as an array of preload items.\n let innerArr: any[];\n if (typeof inner === 'string') {\n innerArr = [inner];\n } else if (Array.isArray(inner)) {\n // If inner looks like a single tuple [string, ...], treat it as one item and wrap it.\n if (inner.length === 2 && typeof inner[0] === 'string' && (Array.isArray(inner[1]) || inner[1] == null)) {\n innerArr = [inner];\n } else {\n innerArr = inner;\n }\n } else {\n innerArr = [inner];\n }\n\n out.push([camelToSnake(key), normalizePreload(innerArr)]);\n }\n return out;\n };\n\n // Build request\n const requestBody: any = {\n op_type: 'create_entry',\n type: contentTypeDef.__definition.name,\n field_values: normalizedFieldValues,\n published,\n };\n\n if ((opts as any).preload) {\n requestBody.preload = normalizePreload((opts as any).preload);\n }\n\n // Make the request\n const response = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n const respData = await response.json() as any;\n\n if ((respData as any).errors) {\n console.error('Create Entry Error:', respData);\n const errorMessages = (respData as any).errors\n .map((e: any) => `${e.field}: ${e.message}`)\n .join('; ');\n throw new Error(`Failed to create entry: ${errorMessages}`);\n }\n\n const createResponse = respData as CreateEntryResponse;\n const entry = createResponse.data?.entry;\n\n // Check if entry is null - this usually means the content type has no fields\n if (!entry) {\n throw new Error(\n `Failed to create entry: Content type \"${contentTypeDef.__definition.name}\" returned null. ` +\n `This typically means the content type has no fields defined. ` +\n `Please add at least one field to the content type before creating entries.`\n );\n }\n\n // If preload was requested, return the full normalized entry (snake_case -> camelCase)\n if ((opts as any).preload) {\n const normalized: Record<string, any> = { id: entry.id };\n for (const [key, value] of Object.entries(entry)) {\n if (key !== 'id') {\n normalized[snakeToCamel(key)] = value;\n }\n }\n return { data: normalized } as any;\n }\n\n return normalizeEntryMetadata(entry);\n};\n\n/**\n * Update an existing entry\n */\nconst updateEntry = (options: InitSchema) => async <T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }, const P extends PreloadSpec<T> | undefined = undefined>(\n contentTypeDef: T,\n entryId: string,\n fieldValues: FieldValues,\n // Backwards-compatible: callers historically passed a boolean `published` as the 4th arg.\n // New signature accepts an options object { published?, preload? }.\n optionsParam?: boolean | {\n published?: boolean;\n preload?: P;\n }\n): Promise<NormalizedEntryMetadata> => {\n const { apiToken, workspace } = options;\n\n // Validate entry ID\n if (!isValidUUID(entryId)) {\n throw new Error(`Invalid entry ID format: ${entryId}. Must be a valid UUID.`);\n }\n\n // Validate field values\n const validation = validateFieldValues(fieldValues);\n if (!validation.valid) {\n throw new Error(validation.error || 'Invalid field values');\n }\n\n // Normalize field values\n const normalizedFieldValues = normalizeFieldValues(fieldValues);\n\n // Build request\n const requestBody: any = {\n op_type: 'update_entry',\n entry_id: entryId,\n field_values: normalizedFieldValues,\n };\n\n // Normalize optionsParam to the object shape (back-compat boolean -> published)\n const opts = typeof optionsParam === 'boolean' ? { published: optionsParam } : (optionsParam || {});\n\n // Add published if specified\n if ((opts as any).published !== undefined) {\n requestBody.published = (opts as any).published;\n }\n\n // Normalize preload shapes to the backend's nested-array grammar (same as getEntry/getEntries)\n const normalizePreload = (p: any): any => {\n if (!Array.isArray(p)) return p;\n const out: any[] = [];\n for (const item of p) {\n if (typeof item === 'string') {\n out.push(camelToSnake(item));\n continue;\n }\n if (!Array.isArray(item)) {\n out.push(item);\n continue;\n }\n const [key, inner] = item;\n if (inner == null) {\n out.push(camelToSnake(key));\n continue;\n }\n let innerArr: any[];\n if (typeof inner === 'string') {\n innerArr = [inner];\n } else if (Array.isArray(inner)) {\n if (inner.length === 2 && typeof inner[0] === 'string' && (Array.isArray(inner[1]) || inner[1] == null)) {\n innerArr = [inner];\n } else {\n innerArr = inner;\n }\n } else {\n innerArr = [inner];\n }\n out.push([camelToSnake(key), normalizePreload(innerArr)]);\n }\n return out;\n };\n\n if ((opts as any).preload) {\n requestBody.preload = normalizePreload((opts as any).preload);\n }\n\n debug(`[DEBUG] Update Entry Request:`, JSON.stringify(requestBody, null, 2));\n\n // Make the request\n const response = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n const respData = await response.json() as any;\n\n if ((respData as any).errors) {\n console.error('Update Entry Error:', respData);\n const errorMessages = (respData as any).errors\n .map((e: any) => `${e.field}: ${e.message}`)\n .join('; ');\n throw new Error(`Failed to update entry: ${errorMessages}`);\n }\n\n const updateResponse = respData as UpdateEntryResponse;\n const entry = updateResponse.data?.entry;\n\n // Check if entry is null - this usually means the content type has no fields\n if (!entry) {\n throw new Error(\n `Failed to update entry: Entry ID \"${entryId}\" returned null. ` +\n `This typically means the content type has no fields defined. ` +\n `Please ensure the content type has at least one field.`\n );\n }\n\n return normalizeEntryMetadata(entry);\n};\n\n/**\n * Delete a content type by ID\n */\nconst deleteContentType = (options: InitSchema) => async (contentTypeId: string): Promise<void> => {\n const { apiToken, workspace } = options;\n\n // Validate content type ID\n if (!isValidUUID(contentTypeId)) {\n throw new Error(`Invalid content type ID format: ${contentTypeId}. Must be a valid UUID.`);\n }\n\n const requestBody = {\n op_type: 'delete_content_type',\n content_type_id: contentTypeId,\n };\n\n const response = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n const respData = await response.json() as any;\n\n if ((respData as any).errors) {\n console.error('Delete Content Type Error:', respData);\n const errorMessages = (respData as any).errors\n .map((e: any) => `${e.field}: ${e.message}`)\n .join('; ');\n throw new Error(`Failed to delete content type: ${errorMessages}`);\n }\n};\n\nexport const createClient = (config: InitSchema) => {\n const { apiToken, workspace } = initSchema.parse(config);\n const request = makeRequest({ apiToken, workspace });\n\n // Remote mutation helpers used by syncWithFields when invoked from the CLI.\n const createContentTypeRemote = async (ct: ContentTypeDefinition) => {\n const reqBody = buildCreateContentTypeRequest(ct);\n debug('[sync] createContentType request:', JSON.stringify(reqBody));\n const resp = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(reqBody),\n });\n const data = await resp.json().catch(() => null);\n debug('[sync] createContentType response:', JSON.stringify(data));\n if (!data || (data as any).errors) {\n throw new Error(`Failed to create content type ${ct.name}: ${JSON.stringify(data)}`);\n }\n return data;\n };\n\n const createFieldRemote = async (modelId: string, fieldName: string, fieldDef: FieldDefinition) => {\n const reqBody = buildCreateFieldRequest(modelId, fieldName, fieldDef);\n debug('[sync] createField request:', JSON.stringify(reqBody));\n const resp = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(reqBody),\n });\n const data = await resp.json().catch(() => null);\n debug('[sync] createField response for', fieldName, JSON.stringify(data));\n if (!data || (data as any).errors) {\n throw new Error(`Failed to create field ${fieldName} on ${modelId}: ${JSON.stringify(data)}`);\n }\n return data;\n };\n\n const updateFieldRemote = async (fieldId: string, changes: Record<string, any>) => {\n const reqBody = buildUpdateFieldRequest(fieldId, changes);\n debug('[sync] updateField request:', JSON.stringify(reqBody));\n const resp = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(reqBody),\n });\n const data = await resp.json().catch(() => null);\n debug('[sync] updateField response for', fieldId, JSON.stringify(data));\n if (!data || (data as any).errors) {\n throw new Error(`Failed to update field ${fieldId}: ${JSON.stringify(data)}`);\n }\n return data;\n };\n\n const deleteFieldRemote = async (fieldId: string) => {\n const reqBody = { op_type: 'delete_field', field_id: fieldId };\n const resp = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(reqBody),\n });\n const data = await resp.json().catch(() => null);\n if (!data || (data as any).errors) {\n throw new Error(`Failed to delete field ${fieldId}: ${JSON.stringify(data)}`);\n }\n return data;\n };\n\n // Bind syncWithFields so CLI callers get working remote mutation callbacks by default.\n const syncWithFieldsBound = async (\n contentTypes: Parameters<ReturnType<typeof syncWithFields>>[0],\n options: Parameters<ReturnType<typeof syncWithFields>>[1] = {}\n ) => {\n const defaults = {\n createContentType: createContentTypeRemote,\n createField: createFieldRemote,\n updateField: updateFieldRemote,\n deleteField: deleteFieldRemote,\n } as any;\n\n // Merge provided options over defaults so caller can override\n const merged = { ...defaults, ...options };\n\n return syncWithFields(request)(contentTypes as any, merged as any);\n };\n\n return {\n getEntry: getEntry(request),\n getEntries: getEntries(request),\n // Note: inline preload literal inference is supported by getEntries overloads.\n inspect: inspect(request),\n /**\n * Validate whether the current token can read the requested content view.\n * Returns true when the view is accessible, false when an authorization error is returned.\n * This helper inspects the remote for a content type and issues a harmless get_entries\n * against that content type using the requested view; it treats a structured\n * `{ errors: [{ field: 'authorization', ... }] }` as a permission failure.\n */\n validateContentView: async (view: 'live' | 'preview'): Promise<boolean> => {\n try {\n const inspectResp = await inspect(request)();\n const firstCT = inspectResp.data.content_types && inspectResp.data.content_types[0];\n if (!firstCT) return true; // nothing to check against\n const typeName = firstCT.slug || firstCT.id;\n // Call get_entries with limit 0/1 to avoid heavy payloads\n const resp = await request({ op_type: 'get_entries', type: typeName, limit: 1, api_type: view } as any).catch((err: any) => ({ __err: err }));\n if ((resp as any)?.__err) {\n // If the request failed at network/parse level, rethrow\n throw (resp as any).__err;\n }\n // If API responded with structured errors, detect authorization field\n if ((resp as any).errors || (resp as any).data?.errors) {\n const errors = (resp as any).errors || (resp as any).data?.errors || [];\n return !errors.some((e: any) => e.field === 'authorization');\n }\n return true;\n } catch (e: any) {\n // If we receive an API error shape, inspect it\n if (e && typeof e === 'object' && e.errors) {\n return !e.errors.some((er: any) => er.field === 'authorization');\n }\n throw e;\n }\n },\n sync: sync(request),\n syncWithFields: syncWithFieldsBound,\n upload: upload({ apiToken, workspace }),\n createEntry: createEntry({ apiToken, workspace }),\n updateEntry: updateEntry({ apiToken, workspace }),\n deleteContentType: deleteContentType({ apiToken, workspace }),\n };\n};\n\n/**\n * Utility: safely get an entry ID whether the field is a raw id string or an expanded object\n * Returns empty string for invalid inputs.\n */\nexport const getEntryId = (entry: unknown): string => {\n if (typeof entry === 'string') return entry;\n if (entry && typeof entry === 'object' && 'id' in (entry as any)) return (entry as any).id as string;\n return '';\n};\n\n/**\n * Type guard: true when the value is an expanded entry object with an `id` property\n */\nexport const isExpandedEntry = <T extends { id: string } = { id: string }>(value: unknown): value is T => {\n return !!(value && typeof value === 'object' && 'id' in (value as any));\n};\n\n// Re-export types and utilities\nexport { defineContentType, defineConfig } from './types';\n"],"mappings":"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","names":["_a","_b","_a"]}
1
+ {"version":3,"sources":["../src/modules/schema.ts","../src/modules/upload.ts","../src/modules/entry.ts","../src/modules/sync-api.ts","../src/modules/filters.ts","../src/utils/logger.ts","../src/types/generics.ts","../src/index.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type { ImageObject, TextObject } from \"../types\";\n\n// Utility functions for case conversion between snake_case and camelCase\nexport function snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n}\n\nexport function camelToSnake(str: string): string {\n // Convert camelCase or PascalCase to snake_case.\n // Preserve first-letter lowercase for single-word PascalCase (Title -> title)\n return str.replace(/([A-Z])/g, (match, _p1, offset) => {\n return offset === 0 ? match.toLowerCase() : `_${match.toLowerCase()}`;\n });\n}\n\nexport const initSchema = z.object({\n apiToken: z.string().min(1, \"API Token is required\"),\n workspace: z.string().min(1, \"Workspace is required\"),\n});\n\nexport type InitSchema = z.infer<typeof initSchema>;\n\nconst preloadType: z.ZodTypeAny = z.lazy(() =>\n z.array(\n z.union([\n z.string(),\n z.tuple([z.string(), preloadType])\n ])\n )\n);\n\nexport const requestSchema = z.object({\n type: z.string().optional(),\n op_type: z.enum(['get_entry', 'get_entries', 'inspect']),\n // Which API surface to target when fetching entries. Defaults to 'live' in the client.\n api_type: z.enum(['live', 'preview']).optional(),\n // entry_id is required for get_entry operations (top-level param)\n entry_id: z.string().optional(),\n filters: z.any().optional(),\n preload: preloadType.optional(),\n sort: z.array(z.tuple([z.string(), z.enum(['ASC', 'DESC'])])).optional(),\n limit: z.number().int().min(1).optional(),\n offset: z.number().int().min(0).optional(),\n})\n\nexport type RequestSchema = z.infer<typeof requestSchema>;\n\n// --- Content Type Schema Builder ---\n// Allows you to define content types with Zod and automatically infer TypeScript types\n\n// Base field types (non-reference)\nexport type FieldSchemaConfig =\n | { type: 'string'; required?: boolean; options?: readonly string[]; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'string[]'; required?: boolean; options?: readonly string[]; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'text'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'slug'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'int'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'int[]'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'float'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'float[]'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'boolean'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'boolean[]'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'date'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'time'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'datetime'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'json'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'image'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'image[]'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'video'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'video[]'; required?: boolean; isLabel?: boolean; schema?: z.ZodTypeAny }\n | { type: 'reference'; required?: boolean; isLabel?: boolean; references?: readonly (string | Record<string, FieldSchemaConfig> | { __fields: Record<string, FieldSchemaConfig> })[]; schema?: z.ZodTypeAny }\n | { type: 'reference[]'; required?: boolean; isLabel?: boolean; references?: readonly (string | Record<string, FieldSchemaConfig> | { __fields: Record<string, FieldSchemaConfig> })[]; schema?: z.ZodTypeAny };\n\n// Helper type to extract all valid field type strings from FieldSchemaConfig\nexport type FieldType = FieldSchemaConfig extends { type: infer T } ? T : never;\n\n// Helper to infer type from a field config\n// This directly computes the TypeScript type without needing a separate registry\ntype InferFieldType<T extends FieldSchemaConfig> =\n T extends { type: 'string'; options: readonly (infer Opt)[] }\n ? Opt\n : T extends { type: 'string' }\n ? string\n : T extends { type: 'string[]'; options: readonly (infer Opt)[] }\n ? Opt[]\n : T extends { type: 'string[]' }\n ? string[]\n : T extends { type: 'text' } ? TextObject\n : T extends { type: 'slug' } ? string\n : T extends { type: 'int' } ? number\n : T extends { type: 'int[]' } ? number[]\n : T extends { type: 'float' } ? number\n : T extends { type: 'float[]' } ? number[]\n : T extends { type: 'boolean' } ? boolean\n : T extends { type: 'boolean[]' } ? boolean[]\n : T extends { type: 'date' } ? string // ISO 8601 date string\n : T extends { type: 'time' } ? string // ISO 8601 time string\n : T extends { type: 'datetime' } ? string // ISO 8601 datetime string\n : T extends { type: 'json' } ? unknown // Any valid JSON value\n : T extends { type: 'image' } ? ImageObject\n : T extends { type: 'image[]' } ? ImageObject[]\n : T extends { type: 'video' } ? string\n : T extends { type: 'video[]' } ? string[]\n : T extends { type: 'reference'; references: readonly (infer Ref)[] }\n ? Ref extends string\n ? string | Record<string, any> // String references resolve to generic types\n : Ref extends { __fields: infer Fields }\n ? Fields extends Record<string, FieldSchemaConfig>\n ? Omit<ContentTypeFromConfig<Fields>, never>\n : string | Record<string, any>\n : Ref extends Record<string, FieldSchemaConfig>\n ? Omit<ContentTypeFromConfig<Ref>, never>\n : string | Record<string, any>\n : T extends { type: 'reference[]'; references: readonly (infer Ref)[] }\n ? Ref extends string\n ? (string | Record<string, any>)[]\n : Ref extends { __fields: infer Fields }\n ? Fields extends Record<string, FieldSchemaConfig>\n ? Omit<ContentTypeFromConfig<Fields>, never>[]\n : (string | Record<string, any>)[]\n : Ref extends Record<string, FieldSchemaConfig>\n ? Omit<ContentTypeFromConfig<Ref>, never>[]\n : (string | Record<string, any>)[]\n : never;\n\n// Helper to determine if a field is required\ntype IsRequired<T extends FieldSchemaConfig> = T extends { required: true } ? true : false;\n\n// Helper to transform a single field into its proper type\ntype TransformField<T extends FieldSchemaConfig> =\n IsRequired<T> extends true\n ? InferFieldType<T>\n : InferFieldType<T> | undefined;\n\n// Main type transformer that builds an object type from field configs\nexport type ContentTypeFromConfig<T extends Record<string, FieldSchemaConfig>> = {\n [K in keyof T]: TransformField<T[K]>;\n};\n\n// Helper type to extract fields from a content type definition object\nexport type ExtractFields<T> = T extends { __fields: infer F } ? F : never;\n\n// Helper type to infer the TypeScript type from a content type definition object\n// Usage: type User = InferContentType<typeof userDefinition>;\nexport type InferContentType<T extends { __fields: Record<string, FieldSchemaConfig> }> = Omit<ContentTypeFromConfig<T['__fields']>, never>;\n\nexport type ContentTypeSchemaConfig = {\n fields: Record<string, FieldSchemaConfig>;\n};\n\n/**\n * Helper function to build a Zod schema for a field based on its config.\n * If a custom schema is provided, it uses that; otherwise, infers from the type.\n */\nexport const fieldSchemaBuilder = (config: FieldSchemaConfig): z.ZodTypeAny => {\n if (config.schema) {\n return config.required ? config.schema : config.schema.optional();\n }\n\n let baseSchema: z.ZodTypeAny;\n\n switch (config.type) {\n case 'string':\n baseSchema = (config as any).options ? z.enum((config as any).options as [string, ...string[]]) : z.string();\n break;\n case 'string[]':\n baseSchema = (config as any).options ? z.array(z.enum((config as any).options as [string, ...string[]])) : z.array(z.string());\n break;\n case 'text':\n baseSchema = z.string();\n break;\n case 'slug':\n baseSchema = z.string();\n break;\n case 'int':\n baseSchema = z.number().int();\n break;\n case 'int[]':\n baseSchema = z.array(z.number().int());\n break;\n case 'float':\n baseSchema = z.number();\n break;\n case 'float[]':\n baseSchema = z.array(z.number());\n break;\n case 'image':\n baseSchema = z.string(); // typically a URL or ID\n break;\n case 'image[]':\n baseSchema = z.array(z.string());\n break;\n case 'video':\n baseSchema = z.string();\n break;\n case 'video[]':\n baseSchema = z.array(z.string());\n break;\n case 'boolean':\n baseSchema = z.boolean();\n break;\n case 'boolean[]':\n baseSchema = z.array(z.boolean());\n break;\n case 'date':\n baseSchema = z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/, 'Invalid date format (YYYY-MM-DD)');\n break;\n case 'time':\n baseSchema = z.string().regex(/^\\d{2}:\\d{2}:\\d{2}$/, 'Invalid time format (HH:MM:SS)');\n break;\n case 'datetime':\n baseSchema = z.string().datetime('Invalid datetime format (ISO 8601)');\n break;\n case 'json':\n baseSchema = z.any(); // Accept any valid JSON value\n break;\n case 'reference':\n // reference fields typically contain an ID or object reference\n baseSchema = z.union([z.string(), z.record(z.string(), z.any())]);\n break;\n case 'reference[]':\n baseSchema = z.array(z.union([z.string(), z.record(z.string(), z.any())]));\n break;\n default:\n baseSchema = z.any();\n }\n\n return config.required ? baseSchema : baseSchema.optional();\n};\n\n/**\n * Build a Zod object schema from a content type config with proper type preservation.\n * \n * Usage:\n * type Author = Omit<ContentTypeFromConfig<typeof authorConfig>, never>;\n * type Article = Omit<ContentTypeFromConfig<typeof articleConfig>, never>;\n * \n * const authorSchema = createContentTypeSchema({ fields: authorConfig });\n * const articleSchema = createContentTypeSchema({ fields: articleConfig });\n */\nexport const createContentTypeSchema = <T extends Record<string, FieldSchemaConfig>>(\n config: { fields: T }\n): z.ZodType<ContentTypeFromConfig<T>> => {\n const fields: Record<string, z.ZodTypeAny> = {};\n\n for (const [fieldName, fieldConfig] of Object.entries(config.fields)) {\n fields[fieldName] = fieldSchemaBuilder(fieldConfig as FieldSchemaConfig);\n }\n\n return z.object(fields) as z.ZodType<ContentTypeFromConfig<T>>;\n};","/**\n * File Upload Types and Utilities\n * \n * Supports uploading images and videos to the Decoupla backend.\n */\n\nexport type ImageFile = {\n id: string;\n type: 'image';\n width: number;\n height: number;\n format: string;\n byte_size: number;\n};\n\nexport type VideoFile = {\n id: string;\n type: 'video';\n width: number;\n height: number;\n format: string;\n byte_size: number;\n duration: number;\n};\n\nexport type UploadedFile = ImageFile | VideoFile;\n\nexport type UploadFileRequest = {\n op_type: 'upload_file';\n};\n\nexport type UploadFileResponse = {\n data: {\n file: UploadedFile;\n };\n};\n\nexport type UploadError = {\n field: string;\n message: string;\n};\n\nexport type UploadErrorResponse = {\n errors: UploadError[];\n};\n\n/**\n * Check if a file is a supported image format\n */\nexport function isSupportedImageFormat(filename: string): boolean {\n const supportedFormats = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'tiff'];\n const ext = filename.split('.').pop()?.toLowerCase() || '';\n return supportedFormats.includes(ext);\n}\n\n/**\n * Check if a file is a supported video format\n */\nexport function isSupportedVideoFormat(filename: string): boolean {\n const supportedFormats = ['mp4', 'webm', 'ogv', 'mov', 'avi', 'mkv'];\n const ext = filename.split('.').pop()?.toLowerCase() || '';\n return supportedFormats.includes(ext);\n}\n\n/**\n * Check if a file is supported (image or video)\n */\nexport function isSupportedFileFormat(filename: string): boolean {\n return isSupportedImageFormat(filename) || isSupportedVideoFormat(filename);\n}\n\n/**\n * Validate file before upload\n */\nexport function validateFile(file: File): { valid: boolean; error?: string } {\n if (!file) {\n return { valid: false, error: 'No file provided' };\n }\n\n if (!isSupportedFileFormat(file.name)) {\n return {\n valid: false,\n error: `Unsupported file format: ${file.name}. Supported formats: images (JPG, PNG, GIF, WebP, etc.) and videos (MP4, WebM, OGV, etc.)`\n };\n }\n\n return { valid: true };\n}\n\n/**\n * Get file type from filename\n */\nexport function getFileType(filename: string): 'image' | 'video' | 'unknown' {\n if (isSupportedImageFormat(filename)) return 'image';\n if (isSupportedVideoFormat(filename)) return 'video';\n return 'unknown';\n}\n","/**\n * Entry Creation and Update Types\n * \n * Supports creating and updating entries (instances of content types)\n */\n\nexport type FieldValue =\n | string\n | number\n | boolean\n | null\n | FieldValue[]\n | Record<string, any>;\n\nexport type FieldValues = Record<string, FieldValue>;\n\nexport type CreateEntryRequest = {\n op_type: 'create_entry';\n field_values: FieldValues;\n published?: boolean;\n};\n\nexport type UpdateEntryRequest = {\n op_type: 'update_entry';\n entry_id: string;\n field_values: FieldValues;\n published?: boolean;\n};\n\nexport type EntryMetadata = {\n id: string;\n model_id: string;\n state: string;\n last_version: number;\n last_published_version: number | null;\n created_at: string;\n updated_at: string;\n};\n\n/**\n * Normalized version of EntryMetadata with camelCase field names\n */\nexport type NormalizedEntryMetadata = {\n id: string;\n modelId: string;\n state: string;\n lastVersion: number;\n lastPublishedVersion: number | null;\n createdAt: string;\n updatedAt: string;\n};\n\nexport type CreateEntryResponse = {\n data: {\n entry: EntryMetadata;\n };\n};\n\nexport type UpdateEntryResponse = CreateEntryResponse;\n\nexport type EntryError = {\n field: string;\n message: string;\n};\n\nexport type EntryErrorResponse = {\n errors: EntryError[];\n};\n\n/**\n * Validate entry ID (must be valid UUID)\n */\nexport function isValidUUID(id: string): boolean {\n const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n return uuidRegex.test(id);\n}\n\n/**\n * Validate field values before sending to API\n */\nexport function validateFieldValues(\n fieldValues: FieldValues,\n requiredFields?: string[]\n): { valid: boolean; error?: string; errors?: EntryError[] } {\n if (!fieldValues || typeof fieldValues !== 'object') {\n return {\n valid: false,\n error: 'Field values must be a non-null object'\n };\n }\n\n // Check required fields\n if (requiredFields && requiredFields.length > 0) {\n const missing = requiredFields.filter(field => {\n const value = fieldValues[field];\n return value === undefined || value === null || value === '';\n });\n\n if (missing.length > 0) {\n return {\n valid: false,\n errors: missing.map(field => ({\n field,\n message: \"can't be blank\"\n }))\n };\n }\n }\n\n return { valid: true };\n}\n\n/**\n * Convert field values for API (handle camelCase to snake_case conversion)\n */\nexport function normalizeFieldValues(fieldValues: FieldValues): FieldValues {\n const normalized: FieldValues = {};\n\n for (const [key, value] of Object.entries(fieldValues)) {\n // Keep the key as-is; API accepts both camelCase and snake_case\n normalized[key] = value;\n }\n\n return normalized;\n}\n\n/**\n * Format entry metadata for display\n */\nexport function formatEntryMetadata(entry: EntryMetadata): string {\n return `Entry #${entry.id} (v${entry.last_version}, ${entry.state})`;\n}\n","import type { FieldType, ContentTypeDefinition, FieldDefinition } from \"../types\";\n\n/**\n * API Request types for sync operations\n */\n\nexport type CreateContentTypeRequest = {\n op_type: 'create_content_type';\n name: string;\n description?: string;\n};\n\nexport type CreateFieldRequest = {\n op_type: 'create_field';\n content_type_id: string;\n name: string;\n type: string;\n control?: string;\n required?: boolean;\n description?: string;\n is_label?: boolean;\n options?: string[];\n meta?: Record<string, any>;\n};\n\nexport type UpdateFieldRequest = {\n op_type: 'update_field';\n field_id: string;\n name?: string;\n required?: boolean;\n description?: string;\n is_label?: boolean;\n options?: string[] | null;\n meta?: Record<string, any>;\n};\n\nexport type DeleteFieldRequest = {\n op_type: 'delete_field';\n field_id: string;\n};\n\nexport type DeleteModelRequest = {\n op_type: 'delete_content_type';\n model_id: string;\n};\n\nexport type ModelRequest =\n | CreateContentTypeRequest\n | CreateFieldRequest\n | UpdateFieldRequest\n | DeleteFieldRequest\n | DeleteModelRequest;\n\n/**\n * API Response types for sync operations\n */\n\nexport type CreateContentTypeResponse = {\n data: {\n content_type: {\n id: string;\n name: string;\n slug: string;\n description?: string;\n localizable: boolean;\n project_id: string;\n inserted_at: string;\n updated_at: string;\n };\n };\n};\n\nexport type CreateFieldResponse = {\n data: {\n field: {\n id: string;\n name: string;\n slug: string;\n type: string;\n control: string;\n required: boolean;\n description?: string;\n model_id: string;\n order: number;\n is_label: boolean;\n inserted_at: string;\n updated_at: string;\n };\n };\n};\n\nexport type UpdateFieldResponse = {\n data: {\n field: {\n id: string;\n name: string;\n slug: string;\n type: string;\n control: string;\n required: boolean;\n description?: string;\n model_id: string;\n order: number;\n is_label: boolean;\n inserted_at: string;\n updated_at: string;\n };\n };\n};\n\nexport type DeleteFieldResponse = {\n data: {\n message: string;\n };\n};\n\nexport type DeleteModelResponse = {\n data: {\n message: string;\n };\n};\n\nexport type ModelResponse =\n | CreateContentTypeResponse\n | CreateFieldResponse\n | UpdateFieldResponse\n | DeleteFieldResponse\n | DeleteModelResponse\n | ErrorResponse;\n\nexport type ErrorResponse = {\n errors: Array<{\n field: string;\n message: string;\n valid_types?: string[];\n valid_controls?: string[];\n }>;\n};\n\n/**\n * Map our field types to backend field types\n */\nexport const fieldTypeMap: Record<FieldType, string> = {\n 'string': 'string',\n 'string[]': 'string[]',\n 'text': 'text',\n 'slug': 'slug',\n 'int': 'int',\n 'int[]': 'int[]',\n 'float': 'float',\n 'float[]': 'float[]',\n 'boolean': 'boolean',\n 'boolean[]': 'boolean[]',\n 'date': 'date',\n 'time': 'time',\n 'datetime': 'datetime',\n 'json': 'json',\n 'image': 'image',\n 'image[]': 'image[]',\n 'video': 'video',\n 'video[]': 'video[]',\n 'reference': 'reference',\n 'reference[]': 'reference[]',\n};\n\n/**\n * Reverse map backend field types to our field types\n */\nexport const reverseFieldTypeMap: Record<string, FieldType> = {\n 'string': 'string',\n 'string[]': 'string[]',\n 'text': 'text',\n 'slug': 'slug',\n 'id': 'string', // id fields are essentially strings\n 'int': 'int',\n 'int[]': 'int[]',\n 'float': 'float',\n 'float[]': 'float[]',\n 'boolean': 'boolean',\n 'date': 'date',\n 'time': 'time',\n 'datetime': 'datetime',\n 'json': 'json',\n 'image': 'image',\n 'image[]': 'image[]',\n 'video': 'video',\n 'video[]': 'video[]',\n 'reference': 'reference',\n 'reference[]': 'reference[]',\n};\n\n/**\n * Map control types (optional, defaults to 'default')\n */\nexport const controlTypeMap: Record<string, string> = {\n 'string': 'text',\n 'text': 'textarea',\n 'int': 'default',\n 'float': 'default',\n 'boolean': 'checkbox',\n 'date': 'default',\n 'datetime': 'default',\n 'time': 'default',\n 'image': 'default',\n 'video': 'default',\n 'reference': 'default',\n 'reference[]': 'default',\n};\n\n/**\n * Build a create field request from a field definition\n */\nexport function buildCreateFieldRequest(\n modelId: string,\n fieldName: string,\n fieldDef: FieldDefinition\n): CreateFieldRequest {\n const backendType = fieldTypeMap[fieldDef.type as FieldType] || 'string';\n const control = controlTypeMap[backendType] || 'default';\n\n // Build meta object. Start with any provided meta in settings, then attach reference_types\n const meta: Record<string, any> = { ...(fieldDef.settings?.meta || {}) };\n if (fieldDef.references && Array.isArray(fieldDef.references)) {\n // The sync layer is responsible for resolving reference targets to content-type IDs (UUIDs).\n // Here we place the provided identifiers directly into meta.reference_types so the backend\n // receives an array of content-type IDs as expected.\n meta.reference_types = fieldDef.references.map(ref => {\n if (typeof ref === 'string') return ref;\n // If a branded content type object is provided, prefer any explicit id property\n // (upstream code should already have resolved to IDs, but handle defensively).\n return (ref as any).__definition?.id || (ref as any).__definition?.name || ref;\n });\n }\n\n return {\n op_type: 'create_field',\n content_type_id: modelId,\n name: fieldName,\n type: backendType,\n control,\n required: fieldDef.required ?? false,\n description: fieldDef.settings?.description,\n is_label: fieldDef.isLabel ?? false,\n options: fieldDef.options,\n meta: Object.keys(meta).length > 0 ? meta : undefined,\n };\n}\n\n/**\n * Build an update field request from differences\n */\nexport function buildUpdateFieldRequest(\n fieldId: string,\n changes: Record<string, any>\n): UpdateFieldRequest {\n const request: UpdateFieldRequest = {\n op_type: 'update_field',\n field_id: fieldId,\n };\n\n if (changes.required !== undefined) {\n request.required = changes.required;\n }\n if (changes.name !== undefined) {\n request.name = changes.name;\n }\n if (changes.description !== undefined) {\n request.description = changes.description;\n }\n if (changes.isLabel !== undefined) {\n request.is_label = !!changes.isLabel;\n }\n // Support updating options for enum-like fields via changes.options (root-level)\n if (changes.options !== undefined) {\n request.options = changes.options as any; // allow explicit null to clear options\n }\n // Support updating reference types via changes.references or changes.meta\n if (changes.references !== undefined) {\n request.meta = { ...(changes.meta || {}), reference_types: changes.references };\n } else if (changes.meta !== undefined) {\n request.meta = changes.meta;\n }\n\n return request;\n}\n\n/**\n * Build a create content type request from a content type definition\n */\nexport function buildCreateContentTypeRequest(ct: ContentTypeDefinition): CreateContentTypeRequest {\n return {\n op_type: 'create_content_type',\n name: ct.displayName || ct.name,\n description: ct.description,\n };\n}\n","/**\n * Type-safe filter system for content type queries\n * \n * Provides compile-time validation of filter operations based on field types.\n * Supports complex filters with and/or logic and list operations.\n * Supports polymorphic reference fields - can filter by any of the referenced types.\n * \n * Filter Structure:\n * - and: Filter[] - all conditions must be true\n * - or: Filter[] - any condition can be true\n * - Field filters: depend on field type\n * - string/slug: is_null, is_not_null, eq, not_eq, contains, not_contains, starts_with, not_starts_with, ends_with, not_ends_with, in, not_in\n * - text: same as string\n * - boolean: is_null, is_not_null, eq, not_eq\n * - id: eq, not_eq, in, not_in\n * - date/datetime/time: is_null, is_not_null, eq, not_eq, gt, gte, lt, lte, between, outside\n * - int/float: is_null, is_not_null, eq, not_eq, gt, gte, lt, lte, between, outside, in, not_in\n * - lists (except image[] and video[]): none<Filter>, any<Filter>, every<Filter>\n * - reference/reference[]: filters for each referenced type using {field}_{type}_filter naming\n * Can filter by any of the referenced content types or use union filter syntax\n */\n\nimport type { FieldDefinition, ContentTypeDefinition } from \"../types\";\n\n// Null check operations (valid for all field types)\ntype NullOperations = 'is_null' | 'is_not_null';\n\n// String/Slug/Text operations\ntype StringOperations = NullOperations | 'eq' | 'not_eq' | 'contains' | 'not_contains' | 'starts_with' | 'not_starts_with' | 'ends_with' | 'not_ends_with' | 'in' | 'not_in';\n\n// Boolean operations\ntype BooleanOperations = NullOperations | 'eq' | 'not_eq';\n\n// ID operations\ntype IdOperations = 'eq' | 'not_eq' | 'in' | 'not_in';\n\n// Numeric operations (int, float)\ntype NumericOperations = NullOperations | 'eq' | 'not_eq' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'outside' | 'in' | 'not_in';\n\n// Date/Time operations\ntype DateTimeOperations = NullOperations | 'eq' | 'not_eq' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'outside';\n\n// Reference operations\ntype ReferenceOperations = 'eq' | 'not_eq' | 'in' | 'not_in';\n\n// List operations - work on individual items in the list\ntype ListOperations<T extends Filter> = {\n none: T;\n any: T;\n every: T;\n};\n\n// Map field types to their allowed operations\ntype FieldTypeOperations = {\n 'id': IdOperations;\n 'string': StringOperations;\n 'text': StringOperations;\n 'slug': StringOperations;\n 'int': NumericOperations;\n 'float': NumericOperations;\n 'boolean': BooleanOperations;\n 'date': DateTimeOperations;\n 'time': DateTimeOperations;\n 'datetime': DateTimeOperations;\n 'reference': ReferenceOperations;\n 'string[]': ListOperations<Filter>;\n 'int[]': ListOperations<Filter>;\n 'float[]': ListOperations<Filter>;\n 'boolean[]': ListOperations<Filter>;\n 'date[]': ListOperations<Filter>;\n 'reference[]': ListOperations<Filter>;\n 'image': never; // Images cannot be filtered\n 'video': never; // Videos cannot be filtered\n 'image[]': never; // Image arrays cannot be filtered\n 'video[]': never; // Video arrays cannot be filtered\n 'json': never; // JSON cannot be filtered\n};\n\n// Value type for each field type\ntype FieldTypeValue = {\n 'id': string | string[];\n 'string': string | string[];\n 'text': string | string[];\n 'slug': string | string[];\n 'int': number | number[];\n 'float': number | number[];\n 'boolean': boolean;\n 'date': string | [string, string]; // ISO date string or [from, to] for between/outside\n 'time': string | [string, string];\n 'datetime': string | [string, string];\n 'reference': string | string[];\n 'string[]': never;\n 'int[]': never;\n 'float[]': never;\n 'boolean[]': never;\n 'date[]': never;\n 'reference[]': never;\n 'image': never;\n 'video': never;\n 'image[]': never;\n 'video[]': never;\n 'json': never;\n};\n\n// Forward declare Filter type for recursive definition\n/**\n * A filter object that can contain:\n * - and: Filter[] - all conditions must be true\n * - or: Filter[] - any condition can be true\n * - Field-specific filters: depends on the field type\n */\ntype Filter = {\n and?: Filter[];\n or?: Filter[];\n [fieldName: string]: any;\n};\n\n/**\n * Helper type to get the operations for a specific field type\n */\ntype OperationsForFieldType<TFieldType extends keyof FieldTypeOperations> =\n TFieldType extends keyof FieldTypeOperations\n ? FieldTypeOperations[TFieldType]\n : never;\n\n/**\n * Helper type to get the value for a specific field type\n */\ntype ValueForFieldType<TFieldType extends keyof FieldTypeValue> =\n TFieldType extends keyof FieldTypeValue\n ? FieldTypeValue[TFieldType]\n : never;\n\n/**\n * Build a field-specific filter based on field type\n * TFieldDef is optional and used for reference fields to provide type safety for nested filters\n */\ntype FieldFilter<TFieldType extends keyof FieldTypeOperations, TFieldDef extends FieldDefinition = any> =\n TFieldType extends 'string[]' | 'int[]' | 'float[]' | 'boolean[]' | 'date[]' | 'reference[]'\n ? {\n none?: ListItemFilter<TFieldType, TFieldDef>;\n any?: ListItemFilter<TFieldType, TFieldDef>;\n every?: ListItemFilter<TFieldType, TFieldDef>;\n }\n : TFieldType extends 'image' | 'video' | 'image[]' | 'video[]' | 'json'\n ? never\n : FieldTypeOperations[TFieldType] extends never\n ? never\n : TFieldType extends 'reference'\n ? (\n TFieldDef extends { type: 'reference'; references: readonly (infer TRef)[] }\n ? TRef extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition }\n ? ReferenceFieldOps<TRef['__definition']> | PolymorphicReferenceOps<TFieldDef['references']>\n : TRef extends ContentTypeDefinition\n ? ReferenceFieldOps<TRef> | PolymorphicReferenceOps<TFieldDef['references']>\n : Filter\n : Filter\n )\n : BuildFieldOperations<TFieldType>;\n\n/**\n * Helper type to build field operations as a union type\n */\ntype BuildFieldOperations<TFieldType extends keyof FieldTypeOperations> =\n TFieldType extends 'id'\n ? IdFieldOps\n : TFieldType extends 'string' | 'text' | 'slug'\n ? StringFieldOps\n : TFieldType extends 'boolean'\n ? BooleanFieldOps\n : TFieldType extends 'int' | 'float'\n ? NumericFieldOps\n : TFieldType extends 'date' | 'time' | 'datetime'\n ? DateTimeFieldOps\n : TFieldType extends 'reference'\n ? Filter // Shouldn't reach here as reference is handled above\n : never;\n\ntype IdFieldOps =\n | { eq: string }\n | { not_eq: string }\n | { in: string[] }\n | { not_in: string[] };\n\ntype StringFieldOps =\n | { is_null: boolean }\n | { is_not_null: boolean }\n | { eq: string }\n | { not_eq: string }\n | { contains: string }\n | { not_contains: string }\n | { starts_with: string }\n | { not_starts_with: string }\n | { ends_with: string }\n | { not_ends_with: string }\n | { in: string[] }\n | { not_in: string[] };\n\ntype BooleanFieldOps =\n | { is_null: boolean }\n | { is_not_null: boolean }\n | { eq: boolean }\n | { not_eq: boolean };\n\ntype NumericFieldOps =\n | { is_null: boolean }\n | { is_not_null: boolean }\n | { eq: number }\n | { not_eq: number }\n | { gt: number }\n | { gte: number }\n | { lt: number }\n | { lte: number }\n | { between: [number, number] }\n | { outside: [number, number] }\n | { in: number[] }\n | { not_in: number[] };\n\ntype DateTimeFieldOps =\n | { is_null: boolean }\n | { is_not_null: boolean }\n | { eq: string }\n | { not_eq: string }\n | { gt: string }\n | { gte: string }\n | { lt: string }\n | { lte: string }\n | { between: [string, string] }\n | { outside: [string, string] };\n\n/**\n * Helper type to extract the definition from a branded content type or return as-is if it's a definition\n */\ntype ExtractDefinition<T> =\n T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition }\n ? T['__definition']\n : T extends ContentTypeDefinition\n ? T\n : never;\n\n/**\n * Build filters for a specific content type schema\n * Includes the implicit 'id' field that all content types have\n */\ntype BuildReferenceFilters<TDef extends ContentTypeDefinition> = {\n and?: BuildReferenceFilters<TDef>[];\n or?: BuildReferenceFilters<TDef>[];\n id?: IdFieldOps; // Add implicit 'id' field that all content types have\n} & {\n [K in keyof TDef['fields']]?: FieldFilter<TDef['fields'][K]['type'], TDef['fields'][K]>;\n};\n\n/**\n * Reference field operations - nested filters for the referenced content type\n */\ntype ReferenceFieldOps<TRefDef extends ContentTypeDefinition | { __isContentTypeDefinition: true; __definition: ContentTypeDefinition }> =\n BuildReferenceFilters<ExtractDefinition<TRefDef>>;\n\n/**\n * Build union filters for polymorphic references\n * When a reference field can point to multiple content types, creates a union of filters for each type\n */\ntype PolymorphicReferenceOps<TRefs extends readonly any[]> =\n TRefs extends readonly [infer TFirst, ...infer TRest]\n ? (\n TFirst extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition }\n ? ReferenceFieldOps<TFirst['__definition']>\n : TFirst extends ContentTypeDefinition\n ? ReferenceFieldOps<TFirst>\n : never\n ) | PolymorphicReferenceOps<TRest>\n : never;\n\n/**\n * Build a filter for items within a reference array\n * For reference arrays, allow filters for any of the referenced types\n * Includes the implicit 'id' field that all references have\n */\ntype ListItemReferenceFilter<TRefs extends readonly any[]> =\n { id: IdFieldOps } | PolymorphicReferenceOps<TRefs>;\n\n/**\n * Build a filter for items within a list\n */\ntype ListItemFilter<TFieldType extends 'string[]' | 'int[]' | 'float[]' | 'boolean[]' | 'date[]' | 'reference[]', TFieldDef extends FieldDefinition = any> =\n TFieldType extends 'string[]'\n ? StringFieldOps\n : TFieldType extends 'int[]'\n ? NumericFieldOps\n : TFieldType extends 'float[]'\n ? NumericFieldOps\n : TFieldType extends 'boolean[]'\n ? BooleanFieldOps\n : TFieldType extends 'date[]'\n ? DateTimeFieldOps\n : TFieldType extends 'reference[]'\n ? (\n TFieldDef extends { type: 'reference[]'; references: readonly (infer TRef)[] }\n ? ListItemReferenceFilter<TFieldDef['references']>\n : Filter\n )\n : never;\n\n/**\n * Type helper for building filter inputs with field-specific operations\n */\nexport type BuildFiltersInput<\n T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }\n> = {\n and?: BuildFiltersInput<T>[];\n or?: BuildFiltersInput<T>[];\n} & {\n [K in keyof T['__fields']]?: FieldFilter<\n T['__definition']['fields'][K & string]['type'] & keyof FieldTypeOperations,\n T['__definition']['fields'][K & string]\n >;\n };\n\n/**\n * Type-safe filter builder for getEntry and getEntries\n * \n * This function validates that filters match the content type definition at compile time\n */\nexport type TypeSafeFilters<\n T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }\n> = BuildFiltersInput<T>;\n\n/**\n * Build a type-safe filter object for a specific content type\n * \n * Example:\n * ```ts\n * const filters = buildFilters(BlogPostContentType, {\n * Title: { eq: 'Hello' }, // ✅ Valid: string field with 'eq'\n * ViewCount: { gt: 10 }, // ✅ Valid: int field with 'gt'\n * Tags: { any: { contains: \"typescript\" } }, // ✅ Valid: string[] with any<contains>\n * // ViewCount: { contains: 'x' } // ❌ Error: 'contains' not valid for int\n * // FeaturedImage: { eq: '...' } // ❌ Error: cannot filter on image\n * });\n * ```\n */\nexport function buildFilters<\n T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }\n>(\n contentTypeDef: T,\n filters: BuildFiltersInput<T>\n): Filter {\n // Convert camelCase field names to snake_case\n const convertToSnakeCase = (str: string): string => {\n return str\n .replace(/([A-Z])/g, (letter) => `_${letter.toLowerCase()}`)\n .replace(/^_/, ''); // Remove leading underscore\n };\n\n // Recursively convert camelCase field names to snake_case for the backend\n const convertFilters = (obj: any): any => {\n if (!obj || typeof obj !== \"object\") {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(convertFilters);\n }\n\n const result: any = {};\n\n for (const [key, value] of Object.entries(obj)) {\n if (key === \"and\" || key === \"or\") {\n // These are special operators, keep as-is\n result[key] = Array.isArray(value) ? value.map(convertFilters) : convertFilters(value);\n } else {\n // Convert field name from camelCase to snake_case\n const snakeKey = convertToSnakeCase(key);\n if (value && typeof value === \"object\") {\n result[snakeKey] = convertFilters(value);\n } else {\n result[snakeKey] = value;\n }\n }\n }\n\n return result;\n };\n\n return convertFilters(filters);\n}","// Simple repo-only debug logger.\n// Enable by setting DECOUPLA_DEBUG=1 or DECOUPLA_DEBUG=true in your environment.\nconst ENABLED = (() => {\n const v = process.env.DECOUPLA_DEBUG || process.env.DEBUG || '';\n return v === '1' || v === 'true' || v.toLowerCase() === 'yes';\n})();\n\nexport function debug(...args: any[]) {\n if (!ENABLED) return;\n // eslint-disable-next-line no-console\n console.log(...args);\n}\n\nexport function info(...args: any[]) {\n // info is user-facing; keep visible\n // eslint-disable-next-line no-console\n console.log(...args);\n}\n\nexport function warn(...args: any[]) {\n // eslint-disable-next-line no-console\n console.warn(...args);\n}\n\nexport function error(...args: any[]) {\n // eslint-disable-next-line no-console\n console.error(...args);\n}\n\nexport default { debug, info, warn, error };\n","/**\n * Content Type Definition Utilities\n * \n * This module provides defineContentType and defineConfig utilities.\n * Type checking is done through the BrandedContentType returned by defineContentType,\n * rather than relying on generic type parameters in API functions.\n */\n\nimport type { FieldDefinition, ContentTypeDefinition } from './index';\n\n// ============================================\n// CONTENT TYPE DEFINITION\n// ============================================\n\n/**\n * Branded content type definition with field information\n * Used by defineContentType to preserve schema information that can be\n * extracted and used by API operations for type safety\n */\nexport type BrandedContentType<T extends Record<string, FieldDefinition> = Record<string, FieldDefinition>> = {\n __definition: ContentTypeDefinition;\n __fields: T;\n __isContentTypeDefinition: true;\n};\n\n/**\n * Extract field schema from content type\n */\nexport type ExtractFieldSchema<T extends BrandedContentType<any>> = T['__fields'];\n\n// ============================================\n// CONTENT TYPE DEFINITION HELPER\n// ============================================\n\n/**\n * Define a content type with full type safety and field preservation\n * \n * Used in config files to define content types. The returned object\n * carries type information that API operations can use for type checking.\n * \n * @example\n * export const AuthorContentType = defineContentType({\n * name: 'author',\n * displayName: 'Author',\n * description: 'Blog post authors',\n * fields: {\n * name: { type: 'string', required: true },\n * email: { type: 'string', required: false },\n * } as const,\n * });\n * \n * // Usage in API:\n * const author = await config.createEntry(AuthorContentType, {\n * name: 'John Doe',\n * email: 'john@example.com',\n * });\n */\nexport function defineContentType<T extends Record<string, FieldDefinition>>(config: {\n name: string;\n displayName?: string;\n description?: string;\n fields: T;\n}): BrandedContentType<T> {\n return {\n __definition: {\n name: config.name,\n displayName: config.displayName,\n description: config.description,\n fields: config.fields,\n },\n __fields: config.fields,\n __isContentTypeDefinition: true,\n };\n}\n\n// ============================================\n// CONFIG CREATION TYPE\n// ============================================\n\n/**\n * Type-safe configuration definition helper\n * Creates a config object that can be exported from decoupla.config.ts\n * The CLI tools will import and read this config to get credentials and content types\n * \n * @example\n * export default defineConfig({\n * workspace: 'my-workspace-id',\n * apiToken: 'my-api-token',\n * contentTypes: [BlogPostContentType, AuthorContentType],\n * });\n */\nexport function defineConfig(config: {\n workspace: string;\n apiToken: string;\n contentTypes: Array<BrandedContentType<any>>;\n}): typeof config {\n return config;\n}\n","/**\n * Decoupla TypeScript Client\n * \n * Type-safe API client for the Decoupla content management system.\n * \n * @module decoupla.js\n * \n * Main Exports:\n * - createClient() - Initialize the API client\n * - defineContentType() - Define content types with type safety\n * - defineConfig() - Create configuration with workspace and content types\n * \n * Type Exports:\n * - ContentTypeDefinition - Content type schema definition\n * - FieldDefinition - Field definition type\n * - TypeSafeFilters - Type-safe filter definitions\n * \n * Example:\n * import { createClient, defineContentType } from 'decoupla.js';\n * \n * const Author = defineContentType({\n * name: 'author',\n * fields: { Name: { type: 'string', required: true } }\n * });\n * \n * const client = createClient({\n * workspace: 'my-workspace',\n * apiToken: 'token'\n * });\n * \n * const entry = await client.createEntry('author', { Name: 'John' });\n */\n\nimport { initSchema, requestSchema, type InitSchema, type RequestSchema, snakeToCamel, camelToSnake } from \"./modules/schema\";\nimport type {\n EntryResponse,\n EntriesResponse,\n ErrorResponse,\n InspectResponse,\n ImageObject,\n TextObject,\n PreloadField,\n PreloadSpec,\n PrimitiveFieldType,\n ReferenceFieldType,\n FieldType,\n ReferenceTarget,\n FieldDefinition,\n ContentTypeDefinition,\n SyncOptions,\n SyncAction,\n SyncResult,\n FieldDiff,\n} from \"./types\";\nimport type {\n UploadedFile,\n ImageFile,\n VideoFile,\n UploadFileResponse,\n} from \"./modules/upload\";\nimport type {\n FieldValues,\n EntryMetadata,\n NormalizedEntryMetadata,\n CreateEntryResponse,\n UpdateEntryResponse,\n} from \"./modules/entry\";\nimport {\n validateFile,\n getFileType,\n isSupportedFileFormat,\n} from \"./modules/upload\";\nimport {\n validateFieldValues,\n isValidUUID,\n normalizeFieldValues,\n} from \"./modules/entry\";\nimport { buildCreateFieldRequest, buildUpdateFieldRequest, buildCreateContentTypeRequest } from \"./modules/sync-api\";\nimport type { TypeSafeFilters } from \"./modules/filters\";\nimport { buildFilters } from \"./modules/filters\";\nimport { debug } from './utils/logger';\n\nexport type {\n EntryResponse,\n EntriesResponse,\n ErrorResponse,\n InspectResponse,\n ImageObject,\n TextObject,\n PreloadField,\n PrimitiveFieldType,\n ReferenceFieldType,\n FieldType,\n ReferenceTarget,\n FieldDefinition,\n ContentTypeDefinition,\n SyncOptions,\n SyncAction,\n SyncResult,\n FieldDiff,\n UploadedFile,\n ImageFile,\n VideoFile,\n FieldValues,\n EntryMetadata,\n TypeSafeFilters,\n};\n\nconst {\n DECOUPLA_API_URL_BASE = \"https://api.decoupla.com/public/api/1.0/workspace/\",\n} = process.env;\n\nconst makeRequest = (options: InitSchema) => async <T>(request: RequestSchema): Promise<EntryResponse<T> | EntriesResponse<T> | InspectResponse> => {\n\n const { apiToken, workspace } = options;\n\n const {\n op_type,\n api_type,\n filters,\n type,\n preload,\n sort,\n limit,\n offset,\n } = requestSchema.parse(request);\n\n const sendSort = (sort || []).reduce((acc, [field, direction]) => {\n acc = acc || [];\n acc.push({ field, direction });\n return acc;\n }, undefined as {\n field: string;\n direction: \"ASC\" | \"DESC\";\n }[] | undefined);\n\n // Determine outgoing api_type: inspect doesn't require api_type and we default to 'live' for other ops\n const outgoingApiType = op_type === 'inspect' ? undefined : (api_type ?? 'live');\n\n const requestBody: any = {\n op_type,\n type,\n // pass through entry_id when present (used by get_entry)\n entry_id: (request as any).entry_id,\n filters,\n preload,\n sort: sendSort,\n limit,\n offset,\n };\n\n if (outgoingApiType) requestBody.api_type = outgoingApiType;\n\n const req = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n let respData;\n const responseText = await req.text();\n\n try {\n respData = JSON.parse(responseText);\n } catch (error) {\n console.error('Failed to parse JSON response:', error, 'Status:', req.status);\n console.error('Response body:', responseText);\n throw new Error(`Failed to parse JSON response (HTTP ${req.status}): ${error} | Response was: \"${responseText}\"`);\n }\n\n if ((respData as ErrorResponse).errors) {\n debug(respData);\n console.error('API Error:', (respData as ErrorResponse));\n const errorDetails = (respData as ErrorResponse).errors.map((e: any) => {\n let msg = `${e.field}: ${e.message}`;\n if (e.available_filters) {\n msg += ` | Available filters: ${JSON.stringify(e.available_filters)}`;\n }\n if (e.valid_filters) {\n msg += ` | Valid filters: ${JSON.stringify(e.valid_filters)}`;\n }\n return msg;\n }).join('\\n');\n throw new Error(`API Error:\\n${errorDetails}`);\n }\n\n return respData as EntriesResponse<T> | EntryResponse<T> | InspectResponse;\n}\n\ntype Request = ReturnType<typeof makeRequest>;\n\n/**\n * Helper type to convert a string to camelCase (only lowercase first letter for single words)\n */\ntype CamelCaseField<T extends string> = T extends `${infer First}${infer Rest}`\n ? `${Lowercase<First>}${Rest}`\n : T;\n\n/**\n * Convert PascalCase to camelCase: ViewCount -> viewCount\n */\ntype ToCamelCase<S extends string> =\n S extends `${infer First}${infer Rest}`\n ? `${Lowercase<First>}${Rest}`\n : S;\n\n/**\n * Helper type to build the entry data type from a content type definition\n * Maps field types to their TypeScript value types\n * Required fields are not nullable, optional fields are nullable/undefined\n * Field names are converted to camelCase (ViewCount -> viewCount, IsPublished -> isPublished)\n */\ntype BuildEntryType<TDef extends ContentTypeDefinition> = {\n id: string;\n} & {\n [K in keyof TDef['fields']as K extends string ? ToCamelCase<K> : never]:\n TDef['fields'][K] extends { type: 'string'; required: true }\n ? string\n : TDef['fields'][K] extends { type: 'string' }\n ? string | undefined\n : TDef['fields'][K] extends { type: 'text'; required: true }\n ? string\n : TDef['fields'][K] extends { type: 'text' }\n ? string | undefined\n : TDef['fields'][K] extends { type: 'slug'; required: true }\n ? string\n : TDef['fields'][K] extends { type: 'slug' }\n ? string | undefined\n : TDef['fields'][K] extends { type: 'int'; required: true }\n ? number\n : TDef['fields'][K] extends { type: 'int' }\n ? number | undefined\n : TDef['fields'][K] extends { type: 'float'; required: true }\n ? number\n : TDef['fields'][K] extends { type: 'float' }\n ? number | undefined\n : TDef['fields'][K] extends { type: 'boolean'; required: true }\n ? boolean\n : TDef['fields'][K] extends { type: 'boolean' }\n ? boolean | undefined\n : TDef['fields'][K] extends { type: 'date' | 'datetime' | 'time'; required: true }\n ? string\n : TDef['fields'][K] extends { type: 'date' | 'datetime' | 'time' }\n ? string | undefined\n : TDef['fields'][K] extends { type: 'reference'; required: true; references: infer R }\n ? RefToReturned<R>\n : TDef['fields'][K] extends { type: 'reference'; required: true }\n ? LightweightReference\n : TDef['fields'][K] extends { type: 'reference'; references: infer R }\n ? RefToReturned<R> | undefined\n : TDef['fields'][K] extends { type: 'reference' }\n ? LightweightReference | undefined\n : TDef['fields'][K] extends { type: 'reference[]'; required: true; references: infer R }\n ? RefToReturned<R>[]\n : TDef['fields'][K] extends { type: 'reference[]'; required: true }\n ? LightweightReference[]\n : TDef['fields'][K] extends { type: 'reference[]'; references: infer R }\n ? RefToReturned<R>[] | undefined\n : TDef['fields'][K] extends { type: 'reference[]' }\n ? LightweightReference[] | undefined\n : TDef['fields'][K] extends { type: 'string[]'; required: true }\n ? string[]\n : TDef['fields'][K] extends { type: 'string[]' }\n ? string[] | undefined\n : TDef['fields'][K] extends { type: 'int[]'; required: true }\n ? number[]\n : TDef['fields'][K] extends { type: 'int[]' }\n ? number[] | undefined\n : TDef['fields'][K] extends { type: 'float[]'; required: true }\n ? number[]\n : TDef['fields'][K] extends { type: 'float[]' }\n ? number[] | undefined\n : TDef['fields'][K] extends { type: 'boolean[]'; required: true }\n ? boolean[]\n : TDef['fields'][K] extends { type: 'boolean[]' }\n ? boolean[] | undefined\n : TDef['fields'][K] extends { type: 'date[]' | 'datetime[]' | 'time[]'; required: true }\n ? string[]\n : TDef['fields'][K] extends { type: 'date[]' | 'datetime[]' | 'time[]' }\n ? string[] | undefined\n : TDef['fields'][K] extends { type: 'image'; required: true }\n ? ImageObject\n : TDef['fields'][K] extends { type: 'image' }\n ? ImageObject | undefined\n : TDef['fields'][K] extends { type: 'image[]'; required: true }\n ? ImageObject[]\n : TDef['fields'][K] extends { type: 'image[]' }\n ? ImageObject[] | undefined\n : TDef['fields'][K] extends { type: 'video'; required: true }\n ? TextObject\n : TDef['fields'][K] extends { type: 'video' }\n ? TextObject | undefined\n : TDef['fields'][K] extends { type: 'video[]'; required: true }\n ? TextObject[]\n : TDef['fields'][K] extends { type: 'video[]' }\n ? TextObject[] | undefined\n : TDef['fields'][K] extends { type: 'json'; required: true }\n ? Record<string, any>\n : TDef['fields'][K] extends { type: 'json' }\n ? Record<string, any> | undefined\n : never;\n};\n\n// Helper types to map 'references' metadata (which may be branded content types)\ntype ExtractReferencedFields<R> =\n R extends readonly (infer U)[] ? (\n U extends { __isContentTypeDefinition: true; __fields: infer F } ? F : never\n ) : R extends { __isContentTypeDefinition: true; __fields: infer F } ? F : never;\n\ntype RefToReturned<R> =\n ExtractReferencedFields<R> extends Record<string, FieldDefinition>\n ? (BuildEntryFromFields<ExtractReferencedFields<R>> & { id: string }) | LightweightReference\n : LightweightReference;\n\n// Lightweight representation returned by the server when a reference is not loaded.\n// Previously we allowed plain string IDs in many places; switch to a structured\n// lightweight shape so callers can rely on stable metadata for \"not_loaded\" refs.\ntype LightweightReference = {\n id: string;\n __sys_content_type: 'reference';\n __sys_id: string;\n __sys_state: 'not_loaded';\n};\n\n/**\n * Build an entry type directly from the `fields` object (preserves literal field names/types\n * when content types are created with `defineContentType(... as const)` which stores the\n * fields in the branded `__fields` property).\n */\ntype BuildEntryFromFields<TFields extends Record<string, FieldDefinition>> = {\n id: string;\n} & {\n [K in keyof TFields as K extends string ? ToCamelCase<K> : never]:\n TFields[K] extends { type: 'string'; required: true }\n ? string\n : TFields[K] extends { type: 'string' }\n ? string | undefined\n : TFields[K] extends { type: 'text'; required: true }\n ? string\n : TFields[K] extends { type: 'text' }\n ? string | undefined\n : TFields[K] extends { type: 'slug'; required: true }\n ? string\n : TFields[K] extends { type: 'slug' }\n ? string | undefined\n : TFields[K] extends { type: 'int'; required: true }\n ? number\n : TFields[K] extends { type: 'int' }\n ? number | undefined\n : TFields[K] extends { type: 'float'; required: true }\n ? number\n : TFields[K] extends { type: 'float' }\n ? number | undefined\n : TFields[K] extends { type: 'boolean'; required: true }\n ? boolean\n : TFields[K] extends { type: 'boolean' }\n ? boolean | undefined\n : TFields[K] extends { type: 'date' | 'datetime' | 'time'; required: true }\n ? string\n : TFields[K] extends { type: 'date' | 'datetime' | 'time' }\n ? string | undefined\n : TFields[K] extends { type: 'reference'; required: true; references: infer R }\n ? RefToReturned<R>\n : TFields[K] extends { type: 'reference'; required: true }\n ? (LightweightReference | { id: string })\n : TFields[K] extends { type: 'reference'; references: infer R }\n ? RefToReturned<R> | undefined\n : TFields[K] extends { type: 'reference' }\n ? (LightweightReference | { id: string }) | undefined\n : TFields[K] extends { type: 'reference[]'; required: true; references: infer R }\n ? RefToReturned<R>[]\n : TFields[K] extends { type: 'reference[]'; required: true }\n ? (LightweightReference | { id: string })[]\n : TFields[K] extends { type: 'reference[]'; references: infer R }\n ? RefToReturned<R>[] | undefined\n : TFields[K] extends { type: 'reference[]' }\n ? (LightweightReference | { id: string })[] | undefined\n : TFields[K] extends { type: 'string[]'; required: true }\n ? string[]\n : TFields[K] extends { type: 'string[]' }\n ? string[] | undefined\n : TFields[K] extends { type: 'int[]'; required: true }\n ? number[]\n : TFields[K] extends { type: 'int[]' }\n ? number[] | undefined\n : TFields[K] extends { type: 'float[]'; required: true }\n ? number[]\n : TFields[K] extends { type: 'float[]' }\n ? number[] | undefined\n : TFields[K] extends { type: 'boolean[]'; required: true }\n ? boolean[]\n : TFields[K] extends { type: 'boolean[]' }\n ? boolean[] | undefined\n : TFields[K] extends { type: 'date[]' | 'datetime[]' | 'time[]'; required: true }\n ? string[]\n : TFields[K] extends { type: 'date[]' | 'datetime[]' | 'time[]' }\n ? string[] | undefined\n : TFields[K] extends { type: 'image'; required: true }\n ? ImageObject\n : TFields[K] extends { type: 'image' }\n ? ImageObject | undefined\n : TFields[K] extends { type: 'image[]'; required: true }\n ? ImageObject[]\n : TFields[K] extends { type: 'image[]' }\n ? ImageObject[] | undefined\n : TFields[K] extends { type: 'video'; required: true }\n ? TextObject\n : TFields[K] extends { type: 'video' }\n ? TextObject | undefined\n : TFields[K] extends { type: 'video[]'; required: true }\n ? TextObject[]\n : TFields[K] extends { type: 'video[]' }\n ? TextObject[] | undefined\n : TFields[K] extends { type: 'json'; required: true }\n ? Record<string, any>\n : TFields[K] extends { type: 'json' }\n ? Record<string, any> | undefined\n : never;\n};\n\n// ---------------------------\n// Preload-aware type helpers\n// ---------------------------\n\n// Convert a PreloadField item to a top-level camelCase key\ntype PreloadItemToKey<I> =\n I extends string ? ToCamelCase<I>\n : I extends [infer Key, any] ? Key extends string ? ToCamelCase<Key> : never\n : never;\n\n// Extract top-level preload keys from a PreloadField type P\ntype PreloadKeys<P> = [P] extends [undefined] ? never : (\n P extends Array<infer U> ? PreloadItemToKey<U> : never\n);\n\n// Extract the inner preload tuple for a specific top-level key.\n// If the preload contains the string 'Author' then the inner preload is `undefined`.\n// If the preload contains ['Author', [ ... ]] then the inner preload is that inner array type.\ntype ExtractPreloadForKey<P, Key extends string> = P extends Array<infer U> ? (\n U extends string ? (ToCamelCase<U> extends Key ? undefined : never)\n : U extends [infer Name, infer Inner] ? (Name extends string ? (ToCamelCase<Name> extends Key ? Inner : never) : never)\n : never\n) : never;\n\ntype PreloadForKey<K, P> = [K] extends [string] ? ExtractPreloadForKey<P, ToCamelCase<K & string>> : never;\n\n// Helper to test whether a mapped key K (from TFields) is present in the Preload keys\ntype IsPreloadedKey<K, P> = [PreloadForKey<K, P>] extends [never] ? false : true;\n\n// When a reference field is preloaded, prefer an expanded object (if we can resolve it at compile time)\ntype ExpandRefWhenPreloaded<R, PInner> =\n ExtractReferencedFields<R> extends Record<string, FieldDefinition>\n ? (BuildEntryFromFieldsWithPreload<ExtractReferencedFields<R>, PInner> & { id: string })\n : LightweightReference;\n\n// Build an entry type from fields but if a field name is present in PreloadKeys<P> then\n// reference/reference[] fields are expanded to their target shapes (or at least {id:string})\ntype BuildEntryFromFieldsWithPreload<\n TFields extends Record<string, FieldDefinition>,\n P\n> = {\n id: string;\n} & {\n [K in keyof TFields as K extends string ? ToCamelCase<K> : never]:\n // string\n TFields[K] extends { type: 'string'; required: true }\n ? string\n : TFields[K] extends { type: 'string' }\n ? string | undefined\n // text\n : TFields[K] extends { type: 'text'; required: true }\n ? string\n : TFields[K] extends { type: 'text' }\n ? string | undefined\n // slug\n : TFields[K] extends { type: 'slug'; required: true }\n ? string\n : TFields[K] extends { type: 'slug' }\n ? string | undefined\n // int\n : TFields[K] extends { type: 'int'; required: true }\n ? number\n : TFields[K] extends { type: 'int' }\n ? number | undefined\n // float\n : TFields[K] extends { type: 'float'; required: true }\n ? number\n : TFields[K] extends { type: 'float' }\n ? number | undefined\n // boolean\n : TFields[K] extends { type: 'boolean'; required: true }\n ? boolean\n : TFields[K] extends { type: 'boolean' }\n ? boolean | undefined\n // date/datetime/time\n : TFields[K] extends { type: 'date' | 'datetime' | 'time'; required: true }\n ? string\n : TFields[K] extends { type: 'date' | 'datetime' | 'time' }\n ? string | undefined\n // reference (single) - check preload\n : TFields[K] extends { type: 'reference'; required: true; references: infer R }\n ? IsPreloadedKey<K, P> extends true\n ? ExpandRefWhenPreloaded<R, PreloadForKey<K, P>>\n : RefToReturned<R>\n : TFields[K] extends { type: 'reference'; required: true }\n ? (LightweightReference | { id: string })\n : TFields[K] extends { type: 'reference'; references: infer R }\n ? IsPreloadedKey<K, P> extends true\n ? ExpandRefWhenPreloaded<R, PreloadForKey<K, P>> | undefined\n : (RefToReturned<R> | undefined)\n : TFields[K] extends { type: 'reference' }\n ? (LightweightReference | { id: string }) | undefined\n // reference[]\n : TFields[K] extends { type: 'reference[]'; required: true; references: infer R }\n ? IsPreloadedKey<K, P> extends true\n ? ExpandRefWhenPreloaded<R, PreloadForKey<K, P>>[]\n : RefToReturned<R>[]\n : TFields[K] extends { type: 'reference[]'; required: true }\n ? (LightweightReference | { id: string })[]\n : TFields[K] extends { type: 'reference[]'; references: infer R }\n ? IsPreloadedKey<K, P> extends true\n ? ExpandRefWhenPreloaded<R, PreloadForKey<K, P>>[] | undefined\n : (RefToReturned<R>[] | undefined)\n : TFields[K] extends { type: 'reference[]' }\n ? (LightweightReference | { id: string })[] | undefined\n // arrays and other primitives follow original mapping\n : TFields[K] extends { type: 'string[]'; required: true }\n ? string[]\n : TFields[K] extends { type: 'string[]' }\n ? string[] | undefined\n : TFields[K] extends { type: 'int[]'; required: true }\n ? number[]\n : TFields[K] extends { type: 'int[]' }\n ? number[] | undefined\n : TFields[K] extends { type: 'float[]'; required: true }\n ? number[]\n : TFields[K] extends { type: 'float[]' }\n ? number[] | undefined\n : TFields[K] extends { type: 'boolean[]'; required: true }\n ? boolean[]\n : TFields[K] extends { type: 'boolean[]' }\n ? boolean[] | undefined\n : TFields[K] extends { type: 'date[]' | 'datetime[]' | 'time[]'; required: true }\n ? string[]\n : TFields[K] extends { type: 'date[]' | 'datetime[]' | 'time[]' }\n ? string[] | undefined\n : TFields[K] extends { type: 'image'; required: true }\n ? ImageObject\n : TFields[K] extends { type: 'image' }\n ? ImageObject | undefined\n : TFields[K] extends { type: 'image[]'; required: true }\n ? ImageObject[]\n : TFields[K] extends { type: 'image[]' }\n ? ImageObject[] | undefined\n : TFields[K] extends { type: 'video'; required: true }\n ? TextObject\n : TFields[K] extends { type: 'video' }\n ? TextObject | undefined\n : TFields[K] extends { type: 'video[]'; required: true }\n ? TextObject[]\n : TFields[K] extends { type: 'video[]' }\n ? TextObject[] | undefined\n : TFields[K] extends { type: 'json'; required: true }\n ? Record<string, any>\n : TFields[K] extends { type: 'json' }\n ? Record<string, any> | undefined\n : never;\n };\n\nconst getEntry = (request: Request) =>\n async <T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }, const P extends PreloadSpec<T> | undefined = undefined>(\n contentTypeDef: T,\n entryId: string,\n options?: {\n preload?: P;\n /** Preferred client option name: selects which dataset (live vs preview) to read. */\n contentView?: 'live' | 'preview';\n }\n ): Promise<{ data: BuildEntryFromFieldsWithPreload<T['__fields'], P> & NormalizedEntryMetadata }> => {\n // For get_entry, entry_id is a top-level parameter, not in filters\n // Normalize preload shapes to the backend's nested-array grammar\n const normalizePreload = (p: any): any => {\n if (!Array.isArray(p)) return p;\n const out: any[] = [];\n for (const item of p) {\n if (typeof item === 'string') {\n out.push(camelToSnake(item));\n continue;\n }\n if (!Array.isArray(item)) {\n out.push(item);\n continue;\n }\n const [key, inner] = item;\n // If inner is null/undefined, treat as simple string preload\n if (inner == null) {\n out.push(camelToSnake(key));\n continue;\n }\n\n // Determine inner as an array of preload items.\n let innerArr: any[];\n if (typeof inner === 'string') {\n innerArr = [inner];\n } else if (Array.isArray(inner)) {\n // If inner looks like a single tuple [string, ...], treat it as one item and wrap it.\n if (inner.length === 2 && typeof inner[0] === 'string' && (Array.isArray(inner[1]) || inner[1] == null)) {\n innerArr = [inner];\n } else {\n innerArr = inner;\n }\n } else {\n innerArr = [inner];\n }\n\n out.push([camelToSnake(key), normalizePreload(innerArr)]);\n }\n return out;\n };\n\n const chosenApiType = options?.contentView ?? 'live';\n\n const reqBody = {\n op_type: 'get_entry',\n type: contentTypeDef.__definition.name,\n entry_id: entryId,\n preload: normalizePreload(options?.preload || []),\n api_type: chosenApiType,\n } as any;\n\n try { debug('[getEntry] request body:', JSON.stringify(reqBody)); } catch (e) { }\n\n // Use the shared request helper which already handles auth/errors/parsing\n const resp = await request(reqBody as any) as any;\n\n try { debug('[getEntry] raw response:', JSON.stringify(resp, null, 2)); } catch (e) { }\n\n const entry = resp?.data?.entry || resp?.data?.node;\n\n // Normalize snake_case field names to camelCase for the flat response\n const normalizedEntry: Record<string, any> = {};\n for (const [key, value] of Object.entries(entry || {})) {\n normalizedEntry[snakeToCamel(key)] = value;\n }\n\n return {\n data: normalizedEntry as BuildEntryFromFieldsWithPreload<T['__fields'], P> & NormalizedEntryMetadata,\n };\n }\n\nconst inspect = (request: Request) =>\n async () => {\n const resp = await request({\n op_type: 'inspect',\n });\n\n return resp as InspectResponse;\n }\n\nconst getEntries = (request: Request) =>\n async <T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }, const P extends PreloadSpec<T> | undefined = undefined>(\n contentTypeDef: T,\n options: {\n filters: TypeSafeFilters<T>;\n limit?: number;\n offset?: number;\n preload?: P;\n sort?: [string, \"ASC\" | \"DESC\"];\n contentView?: 'live' | 'preview';\n }\n ): Promise<EntriesResponse<BuildEntryFromFieldsWithPreload<T['__fields'], P>>> => {\n const {\n filters,\n limit,\n offset,\n preload = [] as any,\n sort = [],\n contentView: optContentView,\n } = options as any;\n\n const api_type = optContentView ?? 'live';\n\n // Normalize preload shapes to the backend's nested-array grammar (same as getEntry)\n const normalizePreload = (p: any): any => {\n if (!Array.isArray(p)) return p;\n const out: any[] = [];\n for (const item of p) {\n if (typeof item === 'string') {\n out.push(camelToSnake(item));\n continue;\n }\n if (!Array.isArray(item)) {\n out.push(item);\n continue;\n }\n const [key, inner] = item;\n if (inner == null) {\n out.push(camelToSnake(key));\n continue;\n }\n let innerArr: any[];\n if (typeof inner === 'string') {\n innerArr = [inner];\n } else if (Array.isArray(inner)) {\n if (inner.length === 2 && typeof inner[0] === 'string' && (Array.isArray(inner[1]) || inner[1] == null)) {\n innerArr = [inner];\n } else {\n innerArr = inner;\n }\n } else {\n innerArr = [inner];\n }\n out.push([camelToSnake(key), normalizePreload(innerArr)]);\n }\n return out;\n };\n\n // Convert camelCase field names to snake_case using buildFilters\n let backendFilters = buildFilters(contentTypeDef, filters);\n\n // Handle reference field naming: backend expects {fieldName}_{contentTypeName}_filter\n // First, get the inspect data to map UUIDs to content type names\n try {\n const inspectResult = await inspect(request)();\n\n // Build a mapping of reference type UUIDs to content type names/slugs\n const uuidToContentTypeName = new Map<string, string>();\n inspectResult.data.content_types.forEach((ct: any) => {\n // Use slug if available, otherwise fall back to id\n const contentTypeName = ct.slug || ct.id;\n uuidToContentTypeName.set(ct.id, contentTypeName);\n });\n\n // Build a mapping of field names to their reference content types\n // We'll use the backend's field metadata to determine the correct reference types\n const fieldReferenceMap = new Map<string, string[]>();\n\n // Find the current content type in the inspect response\n const currentCTMetadata = inspectResult.data.content_types.find((ct: any) =>\n ct.slug === contentTypeDef.__definition.name || ct.id === contentTypeDef.__definition.name\n );\n\n if (currentCTMetadata && currentCTMetadata.fields) {\n // Use the metadata from the backend to get the reference types\n currentCTMetadata.fields.forEach((field: any) => {\n if ((field.type === 'reference' || field.type === 'reference[]') && field.meta?.reference_types) {\n // Support polymorphic references - store ALL reference types for this field\n const contentTypeNames = field.meta.reference_types\n .map((refTypeId: string) => uuidToContentTypeName.get(refTypeId) || refTypeId);\n // field.slug is already in snake_case from the backend\n fieldReferenceMap.set(field.slug, contentTypeNames);\n }\n });\n }\n\n // Transform filter field names for reference fields\n // Reference filters are already in the correct nested structure from the user:\n // Author: { id: { eq: \"123\" } } or Author: { name: { starts_with: \"John\" } }\n // For polymorphic references, we can also filter by specific type:\n // Speakers: { Author: { id: { eq: \"123\" } } } filters speakers that are Authors\n // We rename the field from Author to author_author_filter or speakers_author_filter\n const transformReferenceFilters = (obj: any, referenceMap: Map<string, string[]>, depth = 0): any => {\n if (!obj || typeof obj !== \"object\") {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => transformReferenceFilters(item, referenceMap, depth + 1));\n }\n\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n if (key === \"and\" || key === \"or\") {\n // Logical operators: transform their contents\n result[key] = Array.isArray(value)\n ? (value as any[]).map(v => transformReferenceFilters(v, referenceMap, depth + 1))\n : transformReferenceFilters(value, referenceMap, depth + 1);\n } else if (referenceMap.has(key)) {\n // This is a reference field - rename it and pass through the nested structure as-is\n const contentTypeNames = referenceMap.get(key)!;\n const valueAsObj = value && typeof value === \"object\" ? (value as Record<string, any>) : {};\n const valueKeys = Object.keys(valueAsObj);\n\n // Check if value has list operators (any, none, every) for reference arrays\n const listOperator = valueKeys.find(vk => ['any', 'none', 'every'].includes(vk));\n\n if (listOperator) {\n // This is a reference array filter with list operator\n // Extract the inner filter that may have type-specific filters\n const innerFilter = valueAsObj[listOperator];\n const innerFilterObj = innerFilter && typeof innerFilter === \"object\" ? innerFilter as Record<string, any> : {};\n const innerKeys = Object.keys(innerFilterObj);\n // Handle both original case (Author) and snake_case (author) versions\n const innerSpecifiedType = innerKeys.find(ik =>\n contentTypeNames.includes(ik) || // Original case: Author, Product, etc.\n contentTypeNames.some(ct => snakeToCamel(ik) === ct) // Snake case: author -> Author\n );\n\n if (innerSpecifiedType && innerFilterObj[innerSpecifiedType]) {\n // Type-specific filter inside list operator\n // Normalize the type name to original case for the filter key\n const normalizedType = contentTypeNames.includes(innerSpecifiedType)\n ? innerSpecifiedType\n : snakeToCamel(innerSpecifiedType);\n const newKey = `${key}_${normalizedType}_filter`;\n const transformedInner = transformReferenceFilters(innerFilterObj[innerSpecifiedType], referenceMap, depth + 1);\n result[newKey] = {\n [listOperator]: transformedInner\n };\n } else {\n // No type specified, use first available type\n const contentTypeName = contentTypeNames[0];\n const newKey = `${key}_${contentTypeName}_filter`;\n const transformedInner = transformReferenceFilters(innerFilter, referenceMap, depth + 1);\n result[newKey] = {\n [listOperator]: transformedInner\n };\n }\n } else {\n // Regular reference filter (not an array)\n // Check if value is a type-specific filter\n // Need to handle both original case (Author) and snake_case (author) versions\n const specifiedType = valueKeys.find(vk =>\n contentTypeNames.includes(vk) || // Original case: Author, Product, etc.\n contentTypeNames.some(ct => snakeToCamel(vk) === ct) // Snake case: author -> Author\n );\n\n if (specifiedType && valueAsObj[specifiedType]) {\n // User specified a type-specific filter: field: { TypeName: { ... } } or { type_name: { ... } }\n // Normalize the type name to original case for the filter key\n const normalizedType = contentTypeNames.includes(specifiedType)\n ? specifiedType\n : snakeToCamel(specifiedType);\n const newKey = `${key}_${normalizedType}_filter`;\n result[newKey] = transformReferenceFilters(valueAsObj[specifiedType], referenceMap, depth + 1);\n } else {\n // No type specified, use first available type or treat as direct filter\n const contentTypeName = contentTypeNames[0];\n const newKey = `${key}_${contentTypeName}_filter`;\n result[newKey] = value && typeof value === \"object\"\n ? transformReferenceFilters(value, referenceMap, depth + 1)\n : value;\n }\n }\n } else {\n // Regular field\n result[key] = value && typeof value === \"object\"\n ? transformReferenceFilters(value, referenceMap, depth + 1)\n : value;\n }\n }\n return result;\n };\n\n backendFilters = transformReferenceFilters(backendFilters, fieldReferenceMap);\n } catch (error) {\n // If inspection fails, log but continue with the original filters\n console.warn('Failed to transform reference field filters:', error);\n }\n\n const reqBody: any = {\n type: contentTypeDef.__definition.name,\n op_type: 'get_entries',\n api_type,\n limit,\n offset,\n filters: backendFilters,\n preload: normalizePreload(preload),\n sort,\n };\n try { debug('[getEntries] request body:', JSON.stringify(reqBody, null, 2)); } catch (e) { }\n const resp = await request<any[]>(reqBody as any);\n\n try { debug('[getEntries] raw response:', JSON.stringify(resp, null, 2)); } catch (e) { }\n\n // Normalize field names from snake_case to camelCase\n let normalizedEntries = (resp as any).data?.map((entry: any) => {\n const normalized: Record<string, any> = { id: entry.id };\n for (const [key, value] of Object.entries(entry)) {\n if (key !== 'id') {\n normalized[snakeToCamel(key)] = value;\n }\n }\n return normalized;\n }) as Array<BuildEntryFromFieldsWithPreload<T['__fields'], P>>;\n\n // Rely on server-side preload expansion for get_entries responses. Client-side per-entry\n // expansion/fetching has been removed to avoid extra round-trips.\n\n return {\n ...resp,\n data: normalizedEntries\n } as EntriesResponse<BuildEntryFromFieldsWithPreload<T['__fields'], P>>;\n };\n\nconst sync = (request: Request) => {\n return async (\n contentTypes: (ContentTypeDefinition | { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> })[],\n options: SyncOptions = {}\n ): Promise<SyncResult> => {\n const {\n fetchRemote,\n createContentType,\n dryRun = true,\n createMissing = true,\n } = options;\n\n // Normalize content types: extract definition from branded types\n const normalizedContentTypes = contentTypes.map(ct => {\n if ('__definition' in ct) {\n return ct.__definition;\n }\n return ct;\n }) as ContentTypeDefinition[];\n\n try {\n debug('[syncWithFields] normalizedContentTypes:', normalizedContentTypes.map(ct => ct.name));\n } catch (e) {\n // ignore\n }\n\n // Inspect the remote to get current state\n let remoteInspect: InspectResponse | null = null;\n try {\n remoteInspect = await inspect(request)();\n } catch (e) {\n // if inspection fails, log but continue with empty state\n console.warn('Failed to inspect remote:', e);\n remoteInspect = null;\n }\n\n // Build remote content type map from inspect response\n // First, create a mapping of content type IDs to names\n const contentTypeIdToName = new Map<string, string>();\n const contentTypeNameToId = new Map<string, string>();\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n // Prefer the slug when available; fallback to id\n const name = (ct as any).slug || ct.id;\n contentTypeIdToName.set(ct.id, name);\n contentTypeNameToId.set(name, ct.id);\n });\n }\n\n const remoteMap = new Map<string, {\n id: string;\n fields: Map<string, {\n id: string;\n slug: string; // snake_case slug from remote\n type: FieldType;\n is_label: boolean;\n required: boolean;\n reference_types?: string[];\n }>;\n }>();\n\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n const fieldsMap = new Map<string, any>();\n ct.fields.forEach(f => {\n // Convert reference type IDs to names\n const referenceNames = (f.meta?.reference_types || [])\n .map(refId => contentTypeIdToName.get(refId) || refId)\n .filter(Boolean);\n\n // Use slug (in snake_case) as the key, as it comes from the remote\n fieldsMap.set(f.slug, {\n id: f.id,\n slug: f.slug,\n type: f.type,\n is_label: f.is_label,\n required: f.required,\n reference_types: referenceNames,\n });\n });\n const name = (ct as any).slug || ct.id;\n remoteMap.set(name, {\n id: ct.id,\n fields: fieldsMap,\n });\n });\n }\n\n const actions: SyncAction[] = [];\n\n for (const ct of normalizedContentTypes) {\n const remoteContentType = remoteMap.get(ct.name);\n\n if (!remoteContentType) {\n // Content type missing remotely\n if (createMissing && createContentType) {\n actions.push({ type: 'create', contentType: ct.name, detail: { reason: 'missing_content_type', contentType: ct } });\n if (!dryRun) {\n try {\n await createContentType(ct);\n } catch (e) {\n actions.push({ type: 'mismatch', contentType: ct.name, detail: { reason: 'create_failed', error: String(e) } });\n }\n }\n } else {\n actions.push({ type: 'skip', contentType: ct.name, detail: { reason: 'missing_content_type' } });\n }\n continue;\n }\n\n // Content type exists, check fields\n const fieldDiffs: any[] = [];\n const remoteFields = remoteContentType.fields;\n const desiredFields = ct.fields || {};\n\n // Check for missing fields in remote\n for (const [fname, fdef] of Object.entries(desiredFields)) {\n // Convert camelCase field name to snake_case to match remote slugs\n const remoteFieldSlug = camelToSnake(fname);\n const remoteField = remoteFields.get(remoteFieldSlug);\n\n if (!remoteField) {\n fieldDiffs.push({\n field: fname,\n reason: 'missing_field',\n desired: {\n type: fdef.type,\n required: fdef.required ?? false,\n isLabel: fdef.isLabel ?? false,\n }\n });\n continue;\n }\n\n // Field exists, check for changes\n const changes: any = {};\n\n // Check type mismatch\n if (remoteField.type !== fdef.type) {\n changes.type = {\n existing: remoteField.type,\n desired: fdef.type,\n };\n }\n\n // Check required mismatch\n const desiredRequired = fdef.required ?? false;\n if (remoteField.required !== desiredRequired) {\n changes.required = {\n existing: remoteField.required,\n desired: desiredRequired,\n };\n }\n\n // Check isLabel mismatch\n const desiredIsLabel = fdef.isLabel ?? false;\n if (remoteField.is_label !== desiredIsLabel) {\n changes.isLabel = {\n existing: remoteField.is_label,\n desired: desiredIsLabel,\n };\n }\n\n // Check references for reference types\n if ((fdef.type === 'reference' || fdef.type === 'reference[]') && fdef.references) {\n const desiredReferences = fdef.references\n .map(ref => typeof ref === 'string' ? ref : ref.__definition.name)\n .sort();\n const existingReferences = (remoteField.reference_types || []).sort();\n\n if (JSON.stringify(desiredReferences) !== JSON.stringify(existingReferences)) {\n changes.references = {\n existing: existingReferences,\n desired: desiredReferences,\n };\n }\n }\n\n if (Object.keys(changes).length > 0) {\n fieldDiffs.push({\n field: fname,\n reason: 'field_changes',\n changes,\n });\n }\n }\n\n // Check for extra fields in remote that aren't in desired\n for (const [remoteFieldSlug, remoteField] of remoteFields) {\n // Convert snake_case slug back to camelCase to check against local field names\n const camelCaseFieldName = snakeToCamel(remoteFieldSlug);\n if (!(camelCaseFieldName in desiredFields)) {\n fieldDiffs.push({\n field: remoteFieldSlug,\n reason: 'extra_field_remote',\n existing: {\n type: remoteField.type,\n required: remoteField.required,\n isLabel: remoteField.is_label,\n }\n });\n }\n }\n\n if (fieldDiffs.length === 0) {\n actions.push({ type: 'noop', contentType: ct.name });\n } else {\n actions.push({ type: 'mismatch', contentType: ct.name, detail: { fieldDiffs } });\n }\n }\n\n return { actions };\n }\n}\n\n/**\n * Enhanced sync function that can create, update, and delete fields in addition to content types.\n * This version works with the backend API and supports full field synchronization.\n */\nconst syncWithFields = (request: Request) => {\n return async (\n contentTypes: (ContentTypeDefinition | { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> })[],\n options: SyncOptions = {}\n ): Promise<SyncResult> => {\n const {\n createContentType,\n createField,\n updateField,\n deleteField,\n dryRun = true,\n createMissing = true,\n createMissingFields = true,\n updateFields = true,\n deleteExtraFields = false,\n } = options;\n\n // Normalize content types: extract definition from branded types\n const normalizedContentTypes = contentTypes.map(ct => {\n if ('__definition' in ct) {\n return ct.__definition;\n }\n return ct;\n }) as ContentTypeDefinition[];\n\n // Inspect the remote to get current state\n let remoteInspect: InspectResponse | null = null;\n try {\n remoteInspect = await inspect(request)();\n } catch (e) {\n console.warn('Failed to inspect remote:', e);\n remoteInspect = null;\n }\n\n // Build remote content type mappings\n const contentTypeIdToName = new Map<string, string>();\n const contentTypeNameToId = new Map<string, string>();\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n // Use slug when available, otherwise fall back to id.\n const name = (ct as any).slug || ct.id;\n contentTypeIdToName.set(ct.id, name);\n contentTypeNameToId.set(name, ct.id);\n });\n }\n\n const remoteMap = new Map<string, {\n id: string;\n fields: Map<string, {\n id: string;\n slug: string;\n type: FieldType;\n is_label: boolean;\n required: boolean;\n reference_types?: string[];\n }>;\n }>();\n\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n const fieldsMap = new Map<string, any>();\n ct.fields.forEach(f => {\n const referenceNames = (f.meta?.reference_types || [])\n .map(refId => contentTypeIdToName.get(refId) || refId)\n .filter(Boolean);\n\n fieldsMap.set(f.slug, {\n id: f.id,\n slug: f.slug,\n type: f.type,\n is_label: f.is_label,\n required: f.required,\n reference_types: referenceNames,\n });\n });\n\n const name = (ct as any).slug || ct.id;\n remoteMap.set(name, {\n id: ct.id,\n fields: fieldsMap,\n });\n });\n }\n\n try {\n debug('[syncWithFields] remoteMap keys:', Array.from(remoteMap.keys()));\n } catch (e) { }\n\n const actions: SyncAction[] = [];\n\n // ============================================\n // PHASE 1: Create all missing content types first\n // ============================================\n for (const ct of normalizedContentTypes) {\n const remoteContentType = remoteMap.get(ct.name);\n\n if (!remoteContentType) {\n // Content type missing remotely\n if (createMissing && createContentType) {\n actions.push({ type: 'create', contentType: ct.name, detail: { reason: 'missing_content_type' } });\n if (!dryRun) {\n try {\n await createContentType(ct);\n // After creating, add to our mapping so it's available for reference resolution\n contentTypeNameToId.set(ct.name, ct.name);\n } catch (e) {\n actions.push({ type: 'mismatch', contentType: ct.name, detail: { reason: 'create_failed', error: String(e) } });\n }\n }\n } else {\n actions.push({ type: 'skip', contentType: ct.name, detail: { reason: 'missing_content_type' } });\n }\n }\n }\n\n // ============================================\n // PHASE 2: Refresh inspect if we created content types\n // ============================================\n if (!dryRun) {\n try {\n remoteInspect = await inspect(request)();\n // Rebuild the mapping with fresh data\n contentTypeIdToName.clear();\n contentTypeNameToId.clear();\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n const name = (ct as any).slug || ct.id;\n contentTypeIdToName.set(ct.id, name);\n contentTypeNameToId.set(name, ct.id);\n });\n }\n // Rebuild remoteMap\n remoteMap.clear();\n if (remoteInspect) {\n remoteInspect.data.content_types.forEach(ct => {\n const fieldsMap = new Map<string, any>();\n ct.fields.forEach(f => {\n const referenceNames = (f.meta?.reference_types || [])\n .map(refId => contentTypeIdToName.get(refId) || refId)\n .filter(Boolean);\n\n fieldsMap.set(f.slug, {\n id: f.id,\n slug: f.slug,\n type: f.type,\n is_label: f.is_label,\n required: f.required,\n reference_types: referenceNames,\n });\n });\n\n const name = (ct as any).slug || ct.id;\n // Use the content type slug/name as the key so lookups by ct.name succeed\n remoteMap.set(name, {\n id: ct.id,\n fields: fieldsMap,\n });\n });\n }\n } catch (e) {\n console.warn('Failed to refresh inspect after creating content types:', e);\n }\n }\n\n // ============================================\n // PHASE 3: Now process fields with complete mapping\n // ============================================\n try {\n debug('[syncWithFields] starting field checks for', normalizedContentTypes.map(ct => ct.name));\n } catch (e) { }\n for (const ct of normalizedContentTypes) {\n try {\n const remote = remoteMap.get(ct.name);\n debug(`[syncWithFields] checking contentType=${String(ct.name)} (type=${typeof ct.name}, json=${JSON.stringify(ct.name)}) remoteHas=${remoteMap.has(ct.name)}`);\n } catch (e) { }\n const remoteContentType = remoteMap.get(ct.name);\n\n if (!remoteContentType) {\n // Content type still missing (wasn't created, was skipped)\n continue;\n }\n\n // Content type exists, check fields\n const fieldDiffs: FieldDiff[] = [];\n const remoteFields = remoteContentType.fields;\n const desiredFields = ct.fields || {};\n const fieldsToCreate: Array<{ name: string; def: FieldDefinition }> = [];\n const fieldsToUpdate: Array<{ id: string; name: string; changes: Record<string, any> }> = [];\n const fieldsToDelete: string[] = [];\n\n // Check for missing fields in remote\n for (const [fname, fdef] of Object.entries(desiredFields)) {\n const remoteFieldSlug = camelToSnake(fname);\n const remoteField = remoteFields.get(remoteFieldSlug);\n\n if (!remoteField) {\n fieldDiffs.push({\n field: fname,\n reason: 'missing_field',\n desired: {\n type: fdef.type,\n required: fdef.required ?? false,\n isLabel: fdef.isLabel ?? false,\n }\n });\n if (createMissingFields && createField) {\n fieldsToCreate.push({ name: fname, def: fdef });\n }\n continue;\n }\n\n // Field exists, check for changes\n const changes: any = {};\n\n if (remoteField.type !== fdef.type) {\n changes.type = {\n existing: remoteField.type,\n desired: fdef.type,\n };\n }\n\n const desiredRequired = fdef.required ?? false;\n if (remoteField.required !== desiredRequired) {\n changes.required = {\n existing: remoteField.required,\n desired: desiredRequired,\n };\n }\n\n const desiredIsLabel = fdef.isLabel ?? false;\n if (remoteField.is_label !== desiredIsLabel) {\n changes.isLabel = {\n existing: remoteField.is_label,\n desired: desiredIsLabel,\n };\n }\n\n if ((fdef.type === 'reference' || fdef.type === 'reference[]') && fdef.references) {\n const desiredReferences = fdef.references\n .map(ref => typeof ref === 'string' ? ref : ref.__definition.name)\n .sort();\n const existingReferences = (remoteField.reference_types || []).sort();\n\n if (JSON.stringify(desiredReferences) !== JSON.stringify(existingReferences)) {\n changes.references = {\n existing: existingReferences,\n desired: desiredReferences,\n };\n }\n }\n\n if (Object.keys(changes).length > 0) {\n fieldDiffs.push({\n field: fname,\n reason: 'field_changes',\n changes,\n });\n if (updateFields && updateField) {\n const updateChanges: any = {\n required: desiredRequired,\n description: fdef.settings?.description,\n };\n\n // Include reference types if the field is a reference type and references are defined\n if ((fdef.type === 'reference' || fdef.type === 'reference[]') && fdef.references && changes.references) {\n updateChanges.references = fdef.references\n .map(ref => typeof ref === 'string' ? ref : ref.__definition.name);\n }\n\n fieldsToUpdate.push({\n id: remoteField.id,\n name: fname,\n changes: updateChanges,\n });\n }\n }\n }\n\n // Check for extra fields in remote\n for (const [remoteFieldSlug, remoteField] of remoteFields) {\n const camelCaseFieldName = snakeToCamel(remoteFieldSlug);\n if (!(camelCaseFieldName in desiredFields)) {\n fieldDiffs.push({\n field: remoteFieldSlug,\n reason: 'extra_field_remote',\n existing: {\n type: remoteField.type,\n required: remoteField.required,\n isLabel: remoteField.is_label,\n }\n });\n if (deleteExtraFields && deleteField) {\n fieldsToDelete.push(remoteField.id);\n }\n }\n }\n\n // Execute field operations\n if (fieldsToCreate.length > 0 && !dryRun) {\n for (const { name, def } of fieldsToCreate) {\n try {\n // Resolve reference names to IDs for the callback\n const defWithResolvedReferences = { ...def };\n if ((def.type === 'reference' || def.type === 'reference[]') && def.references) {\n defWithResolvedReferences.references = def.references\n .map(ref => {\n const refName = typeof ref === 'string' ? ref : ref.__definition.name;\n return contentTypeNameToId.get(refName) || refName;\n })\n .filter(Boolean) as any[];\n }\n await createField!(remoteContentType.id, name, defWithResolvedReferences);\n } catch (e) {\n fieldDiffs.push({\n field: name,\n reason: 'missing_field',\n desired: {\n type: def.type,\n required: def.required ?? false,\n isLabel: def.isLabel ?? false,\n }\n });\n }\n }\n }\n\n if (fieldsToUpdate.length > 0 && !dryRun) {\n for (const { id, changes } of fieldsToUpdate) {\n try {\n // Resolve reference names to IDs if needed\n const resolvedChanges = { ...changes };\n if (resolvedChanges.references && Array.isArray(resolvedChanges.references)) {\n resolvedChanges.references = resolvedChanges.references\n .map(ref => contentTypeNameToId.get(ref) || ref)\n .filter(Boolean);\n }\n await updateField!(id, resolvedChanges);\n } catch (e) {\n console.warn(`Failed to update field ${id}:`, e);\n }\n }\n }\n\n if (fieldsToDelete.length > 0 && !dryRun) {\n for (const id of fieldsToDelete) {\n try {\n await deleteField!(id);\n } catch (e) {\n console.warn(`Failed to delete field ${id}:`, e);\n }\n }\n }\n\n // Determine action type\n if (fieldDiffs.length === 0) {\n actions.push({ type: 'noop', contentType: ct.name });\n } else if (fieldsToCreate.length > 0) {\n actions.push({ type: 'create_fields', contentType: ct.name, detail: { fieldDiffs, created: fieldsToCreate.length } });\n } else if (fieldsToUpdate.length > 0) {\n actions.push({ type: 'update_fields', contentType: ct.name, detail: { fieldDiffs, updated: fieldsToUpdate.length } });\n } else if (fieldsToDelete.length > 0) {\n actions.push({ type: 'delete_fields', contentType: ct.name, detail: { fieldDiffs, deleted: fieldsToDelete.length } });\n } else {\n actions.push({ type: 'mismatch', contentType: ct.name, detail: { fieldDiffs } });\n }\n }\n\n // Debug: when running a non-dry run from CLI show resolved actions for visibility\n try {\n if (actions && actions.length > 0) {\n debug('[syncWithFields] Resolved actions:', JSON.stringify(actions.map(a => ({ type: a.type, contentType: a.contentType, detail: a.detail })), null, 2));\n } else {\n debug('[syncWithFields] No actions resolved');\n }\n } catch (e) {\n // swallow JSON errors\n }\n\n return { actions };\n }\n}\n\n/**\n * Define a content type with full type safety and field preservation\n * \n * Creates a branded type that preserves field schema information for the CLI tools.\n * Can be used directly in config files or with the generic API methods.\n * \n * Example:\n * const Author = defineContentType({\n * name: 'author',\n * displayName: 'Author',\n * fields: {\n * id: { type: 'string', required: true },\n * name: { type: 'string', required: true },\n * status: { type: 'string', options: ['active', 'inactive'] },\n * }\n * });\n * \n * const Article = defineContentType({\n * name: 'article',\n * fields: {\n * author: { type: 'reference', references: [Author] }\n * }\n * });\n * \n * Usage:\n * - In config files: export default { contentTypes: [Author, Article] };\n * - Type checking done through the returned BrandedContentType\n */\n\n/**\n * Upload a file (image or video) to the backend\n */\nconst upload = (options: InitSchema) => async (file: File | Blob, filename?: string): Promise<UploadedFile> => {\n const { apiToken, workspace } = options;\n\n // If Blob is provided, we need a filename\n if (!(file instanceof File) && !filename) {\n throw new Error('Filename is required when uploading a Blob');\n }\n\n const fname = file instanceof File ? file.name : filename!;\n\n // Validate file format\n const validation = validateFile(new File([file], fname));\n if (!validation.valid) {\n throw new Error(validation.error);\n }\n\n // Create FormData\n const formData = new FormData();\n formData.append('op_type', 'upload_file');\n formData.append('file', file, fname);\n\n // Make the upload request\n const response = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: formData,\n });\n\n const respData = await response.json() as any;\n\n if ((respData as any).errors) {\n console.error('Upload Error:', respData);\n throw new Error(`Upload failed: ${(respData as any).errors.map((e: any) => e.message).join(', ')}`);\n }\n\n const uploadResponse = respData as UploadFileResponse;\n return uploadResponse.data.file;\n};\n\n/**\n * Normalize EntryMetadata field names from snake_case to camelCase\n */\nconst normalizeEntryMetadata = (entry: EntryMetadata): NormalizedEntryMetadata => ({\n id: entry.id,\n modelId: entry.model_id,\n state: entry.state,\n lastVersion: entry.last_version,\n lastPublishedVersion: entry.last_published_version,\n createdAt: entry.created_at,\n updatedAt: entry.updated_at,\n});\n\n/**\n * Create a new entry (instance of a content type)\n */\nconst createEntry = (options: InitSchema) => async <T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }, const P extends PreloadSpec<T> | undefined = undefined>(\n contentTypeDef: T,\n fieldValues: FieldValues,\n // Backwards-compatible: callers historically passed a boolean `published` as the 3rd arg.\n // New signature accepts an options object { published?, preload? }.\n optionsParam?: boolean | {\n published?: boolean;\n preload?: P;\n }\n): Promise<NormalizedEntryMetadata> => {\n const { apiToken, workspace } = options;\n // Normalize optionsParam to the object shape\n const opts = typeof optionsParam === 'boolean' ? { published: optionsParam } : (optionsParam || {});\n const published = opts.published ?? true;\n\n // Validate field values\n const validation = validateFieldValues(fieldValues);\n if (!validation.valid) {\n throw new Error(validation.error || 'Invalid field values');\n }\n\n // Normalize field values\n const normalizedFieldValues = normalizeFieldValues(fieldValues);\n\n // Convert date fields to backend-expected date-only strings (YYYY-MM-DD).\n try {\n const fieldDefs = contentTypeDef.__definition?.fields || {};\n const keyMap = new Map<string, string>();\n for (const defKey of Object.keys(fieldDefs)) {\n keyMap.set(defKey, defKey);\n try { keyMap.set(camelToSnake(defKey), defKey); } catch (e) {}\n try { keyMap.set(snakeToCamel(camelToSnake(defKey)), defKey); } catch (e) {}\n }\n\n for (const [k, v] of Object.entries(normalizedFieldValues)) {\n const defKey = keyMap.get(k) || undefined;\n if (!defKey) continue;\n const fdef = fieldDefs[defKey];\n if (!fdef) continue;\n if (fdef.type === 'date') {\n const toDateOnly = (val: any) => {\n if (val instanceof Date) {\n const y = val.getFullYear();\n const m = String(val.getMonth() + 1).padStart(2, '0');\n const d = String(val.getDate()).padStart(2, '0');\n return `${y}-${m}-${d}`;\n }\n if (typeof val === 'string') {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(val)) return val;\n const parsed = new Date(val);\n if (!isNaN(parsed.getTime())) {\n const y = parsed.getFullYear();\n const m = String(parsed.getMonth() + 1).padStart(2, '0');\n const d = String(parsed.getDate()).padStart(2, '0');\n return `${y}-${m}-${d}`;\n }\n }\n return val;\n };\n normalizedFieldValues[k] = toDateOnly(v);\n }\n }\n } catch (e) {\n // swallow - non-fatal\n }\n\n // Convert date fields to backend-expected date-only strings (YYYY-MM-DD).\n // Backend expects `date` fields as a date string (not datetime). If callers pass\n // a JavaScript Date or an ISO datetime string, convert/truncate it to the date\n // in the user's local timezone. If the value is already a YYYY-MM-DD string,\n // leave it as-is.\n try {\n const fieldDefs = contentTypeDef.__definition?.fields || {};\n // build lookup mapping of possible keys -> canonical field key\n const keyMap = new Map<string, string>();\n for (const defKey of Object.keys(fieldDefs)) {\n keyMap.set(defKey, defKey);\n try { keyMap.set(camelToSnake(defKey), defKey); } catch (e) {}\n try { keyMap.set(snakeToCamel(camelToSnake(defKey)), defKey); } catch (e) {}\n }\n\n for (const [k, v] of Object.entries(normalizedFieldValues)) {\n const defKey = keyMap.get(k) || keyMap.get(k as string) || undefined;\n if (!defKey) continue;\n const fdef = fieldDefs[defKey];\n if (!fdef) continue;\n if (fdef.type === 'date') {\n const toDateOnly = (val: any) => {\n if (val instanceof Date) {\n const y = val.getFullYear();\n const m = String(val.getMonth() + 1).padStart(2, '0');\n const d = String(val.getDate()).padStart(2, '0');\n return `${y}-${m}-${d}`;\n }\n if (typeof val === 'string') {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(val)) return val;\n const parsed = new Date(val);\n if (!isNaN(parsed.getTime())) {\n const y = parsed.getFullYear();\n const m = String(parsed.getMonth() + 1).padStart(2, '0');\n const d = String(parsed.getDate()).padStart(2, '0');\n return `${y}-${m}-${d}`;\n }\n }\n return val;\n };\n normalizedFieldValues[k] = toDateOnly(v);\n }\n }\n } catch (e) {\n // non-fatal: if anything goes wrong here, keep original values\n }\n\n // Normalize preload shapes to the backend's nested-array grammar (same as getEntry/getEntries)\n const normalizePreload = (p: any): any => {\n if (!Array.isArray(p)) return p;\n const out: any[] = [];\n for (const item of p) {\n if (typeof item === 'string') {\n out.push(camelToSnake(item));\n continue;\n }\n if (!Array.isArray(item)) {\n out.push(item);\n continue;\n }\n const [key, inner] = item;\n // If inner is null/undefined, treat as simple string preload\n if (inner == null) {\n out.push(camelToSnake(key));\n continue;\n }\n\n // Determine inner as an array of preload items.\n let innerArr: any[];\n if (typeof inner === 'string') {\n innerArr = [inner];\n } else if (Array.isArray(inner)) {\n // If inner looks like a single tuple [string, ...], treat it as one item and wrap it.\n if (inner.length === 2 && typeof inner[0] === 'string' && (Array.isArray(inner[1]) || inner[1] == null)) {\n innerArr = [inner];\n } else {\n innerArr = inner;\n }\n } else {\n innerArr = [inner];\n }\n\n out.push([camelToSnake(key), normalizePreload(innerArr)]);\n }\n return out;\n };\n\n // Build request\n const requestBody: any = {\n op_type: 'create_entry',\n type: contentTypeDef.__definition.name,\n field_values: normalizedFieldValues,\n published,\n };\n\n if ((opts as any).preload) {\n requestBody.preload = normalizePreload((opts as any).preload);\n }\n\n // Make the request\n const response = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n const respData = await response.json() as any;\n\n if ((respData as any).errors) {\n console.error('Create Entry Error:', respData);\n const errorMessages = (respData as any).errors\n .map((e: any) => `${e.field}: ${e.message}`)\n .join('; ');\n throw new Error(`Failed to create entry: ${errorMessages}`);\n }\n\n const createResponse = respData as CreateEntryResponse;\n const entry = createResponse.data?.entry;\n\n // Check if entry is null - this usually means the content type has no fields\n if (!entry) {\n throw new Error(\n `Failed to create entry: Content type \"${contentTypeDef.__definition.name}\" returned null. ` +\n `This typically means the content type has no fields defined. ` +\n `Please add at least one field to the content type before creating entries.`\n );\n }\n\n // If preload was requested, return the full normalized entry (snake_case -> camelCase)\n if ((opts as any).preload) {\n const normalized: Record<string, any> = { id: entry.id };\n for (const [key, value] of Object.entries(entry)) {\n if (key !== 'id') {\n normalized[snakeToCamel(key)] = value;\n }\n }\n return { data: normalized } as any;\n }\n\n return normalizeEntryMetadata(entry);\n};\n\n/**\n * Update an existing entry\n */\nconst updateEntry = (options: InitSchema) => async <T extends { __isContentTypeDefinition: true; __definition: ContentTypeDefinition; __fields: Record<string, FieldDefinition> }, const P extends PreloadSpec<T> | undefined = undefined>(\n contentTypeDef: T,\n entryId: string,\n fieldValues: FieldValues,\n // Backwards-compatible: callers historically passed a boolean `published` as the 4th arg.\n // New signature accepts an options object { published?, preload? }.\n optionsParam?: boolean | {\n published?: boolean;\n preload?: P;\n }\n): Promise<NormalizedEntryMetadata> => {\n const { apiToken, workspace } = options;\n\n // Validate entry ID\n if (!isValidUUID(entryId)) {\n throw new Error(`Invalid entry ID format: ${entryId}. Must be a valid UUID.`);\n }\n\n // Validate field values\n const validation = validateFieldValues(fieldValues);\n if (!validation.valid) {\n throw new Error(validation.error || 'Invalid field values');\n }\n\n // Normalize field values\n const normalizedFieldValues = normalizeFieldValues(fieldValues);\n\n // Build request\n const requestBody: any = {\n op_type: 'update_entry',\n entry_id: entryId,\n field_values: normalizedFieldValues,\n };\n\n // Normalize optionsParam to the object shape (back-compat boolean -> published)\n const opts = typeof optionsParam === 'boolean' ? { published: optionsParam } : (optionsParam || {});\n\n // Add published if specified\n if ((opts as any).published !== undefined) {\n requestBody.published = (opts as any).published;\n }\n\n // Normalize preload shapes to the backend's nested-array grammar (same as getEntry/getEntries)\n const normalizePreload = (p: any): any => {\n if (!Array.isArray(p)) return p;\n const out: any[] = [];\n for (const item of p) {\n if (typeof item === 'string') {\n out.push(camelToSnake(item));\n continue;\n }\n if (!Array.isArray(item)) {\n out.push(item);\n continue;\n }\n const [key, inner] = item;\n if (inner == null) {\n out.push(camelToSnake(key));\n continue;\n }\n let innerArr: any[];\n if (typeof inner === 'string') {\n innerArr = [inner];\n } else if (Array.isArray(inner)) {\n if (inner.length === 2 && typeof inner[0] === 'string' && (Array.isArray(inner[1]) || inner[1] == null)) {\n innerArr = [inner];\n } else {\n innerArr = inner;\n }\n } else {\n innerArr = [inner];\n }\n out.push([camelToSnake(key), normalizePreload(innerArr)]);\n }\n return out;\n };\n\n if ((opts as any).preload) {\n requestBody.preload = normalizePreload((opts as any).preload);\n }\n\n debug(`[DEBUG] Update Entry Request:`, JSON.stringify(requestBody, null, 2));\n\n // Make the request\n const response = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n const respData = await response.json() as any;\n\n if ((respData as any).errors) {\n console.error('Update Entry Error:', respData);\n const errorMessages = (respData as any).errors\n .map((e: any) => `${e.field}: ${e.message}`)\n .join('; ');\n throw new Error(`Failed to update entry: ${errorMessages}`);\n }\n\n const updateResponse = respData as UpdateEntryResponse;\n const entry = updateResponse.data?.entry;\n\n // Check if entry is null - this usually means the content type has no fields\n if (!entry) {\n throw new Error(\n `Failed to update entry: Entry ID \"${entryId}\" returned null. ` +\n `This typically means the content type has no fields defined. ` +\n `Please ensure the content type has at least one field.`\n );\n }\n\n return normalizeEntryMetadata(entry);\n};\n\n/**\n * Delete a content type by ID\n */\nconst deleteContentType = (options: InitSchema) => async (contentTypeId: string): Promise<void> => {\n const { apiToken, workspace } = options;\n\n // Validate content type ID\n if (!isValidUUID(contentTypeId)) {\n throw new Error(`Invalid content type ID format: ${contentTypeId}. Must be a valid UUID.`);\n }\n\n const requestBody = {\n op_type: 'delete_content_type',\n content_type_id: contentTypeId,\n };\n\n const response = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(requestBody),\n });\n\n const respData = await response.json() as any;\n\n if ((respData as any).errors) {\n console.error('Delete Content Type Error:', respData);\n const errorMessages = (respData as any).errors\n .map((e: any) => `${e.field}: ${e.message}`)\n .join('; ');\n throw new Error(`Failed to delete content type: ${errorMessages}`);\n }\n};\n\nexport const createClient = (config: InitSchema) => {\n const { apiToken, workspace } = initSchema.parse(config);\n const request = makeRequest({ apiToken, workspace });\n\n // Remote mutation helpers used by syncWithFields when invoked from the CLI.\n const createContentTypeRemote = async (ct: ContentTypeDefinition) => {\n const reqBody = buildCreateContentTypeRequest(ct);\n debug('[sync] createContentType request:', JSON.stringify(reqBody));\n const resp = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(reqBody),\n });\n const data = await resp.json().catch(() => null);\n debug('[sync] createContentType response:', JSON.stringify(data));\n if (!data || (data as any).errors) {\n throw new Error(`Failed to create content type ${ct.name}: ${JSON.stringify(data)}`);\n }\n return data;\n };\n\n const createFieldRemote = async (modelId: string, fieldName: string, fieldDef: FieldDefinition) => {\n const reqBody = buildCreateFieldRequest(modelId, fieldName, fieldDef);\n debug('[sync] createField request:', JSON.stringify(reqBody));\n const resp = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(reqBody),\n });\n const data = await resp.json().catch(() => null);\n debug('[sync] createField response for', fieldName, JSON.stringify(data));\n if (!data || (data as any).errors) {\n throw new Error(`Failed to create field ${fieldName} on ${modelId}: ${JSON.stringify(data)}`);\n }\n return data;\n };\n\n const updateFieldRemote = async (fieldId: string, changes: Record<string, any>) => {\n const reqBody = buildUpdateFieldRequest(fieldId, changes);\n debug('[sync] updateField request:', JSON.stringify(reqBody));\n const resp = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(reqBody),\n });\n const data = await resp.json().catch(() => null);\n debug('[sync] updateField response for', fieldId, JSON.stringify(data));\n if (!data || (data as any).errors) {\n throw new Error(`Failed to update field ${fieldId}: ${JSON.stringify(data)}`);\n }\n return data;\n };\n\n const deleteFieldRemote = async (fieldId: string) => {\n const reqBody = { op_type: 'delete_field', field_id: fieldId };\n const resp = await fetch(`${DECOUPLA_API_URL_BASE}${workspace}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiToken}`,\n },\n body: JSON.stringify(reqBody),\n });\n const data = await resp.json().catch(() => null);\n if (!data || (data as any).errors) {\n throw new Error(`Failed to delete field ${fieldId}: ${JSON.stringify(data)}`);\n }\n return data;\n };\n\n // Bind syncWithFields so CLI callers get working remote mutation callbacks by default.\n const syncWithFieldsBound = async (\n contentTypes: Parameters<ReturnType<typeof syncWithFields>>[0],\n options: Parameters<ReturnType<typeof syncWithFields>>[1] = {}\n ) => {\n const defaults = {\n createContentType: createContentTypeRemote,\n createField: createFieldRemote,\n updateField: updateFieldRemote,\n deleteField: deleteFieldRemote,\n } as any;\n\n // Merge provided options over defaults so caller can override\n const merged = { ...defaults, ...options };\n\n return syncWithFields(request)(contentTypes as any, merged as any);\n };\n\n return {\n getEntry: getEntry(request),\n getEntries: getEntries(request),\n // Note: inline preload literal inference is supported by getEntries overloads.\n inspect: inspect(request),\n /**\n * Validate whether the current token can read the requested content view.\n * Returns true when the view is accessible, false when an authorization error is returned.\n * This helper inspects the remote for a content type and issues a harmless get_entries\n * against that content type using the requested view; it treats a structured\n * `{ errors: [{ field: 'authorization', ... }] }` as a permission failure.\n */\n validateContentView: async (view: 'live' | 'preview'): Promise<boolean> => {\n try {\n const inspectResp = await inspect(request)();\n const firstCT = inspectResp.data.content_types && inspectResp.data.content_types[0];\n if (!firstCT) return true; // nothing to check against\n const typeName = firstCT.slug || firstCT.id;\n // Call get_entries with limit 0/1 to avoid heavy payloads\n const resp = await request({ op_type: 'get_entries', type: typeName, limit: 1, api_type: view } as any).catch((err: any) => ({ __err: err }));\n if ((resp as any)?.__err) {\n // If the request failed at network/parse level, rethrow\n throw (resp as any).__err;\n }\n // If API responded with structured errors, detect authorization field\n if ((resp as any).errors || (resp as any).data?.errors) {\n const errors = (resp as any).errors || (resp as any).data?.errors || [];\n return !errors.some((e: any) => e.field === 'authorization');\n }\n return true;\n } catch (e: any) {\n // If we receive an API error shape, inspect it\n if (e && typeof e === 'object' && e.errors) {\n return !e.errors.some((er: any) => er.field === 'authorization');\n }\n throw e;\n }\n },\n sync: sync(request),\n syncWithFields: syncWithFieldsBound,\n upload: upload({ apiToken, workspace }),\n createEntry: createEntry({ apiToken, workspace }),\n updateEntry: updateEntry({ apiToken, workspace }),\n deleteContentType: deleteContentType({ apiToken, workspace }),\n };\n};\n\n/**\n * Utility: safely get an entry ID whether the field is a raw id string or an expanded object\n * Returns empty string for invalid inputs.\n */\nexport const getEntryId = (entry: unknown): string => {\n if (typeof entry === 'string') return entry;\n if (entry && typeof entry === 'object' && 'id' in (entry as any)) return (entry as any).id as string;\n return '';\n};\n\n/**\n * Type guard: true when the value is an expanded entry object with an `id` property\n */\nexport const isExpandedEntry = <T extends { id: string } = { id: string }>(value: unknown): value is T => {\n return !!(value && typeof value === 'object' && 'id' in (value as any));\n};\n\n// Re-export types and utilities\nexport { defineContentType, defineConfig } from './types';\n"],"mappings":";AAAA,SAAS,SAAS;AAIX,SAAS,aAAa,KAAqB;AAC9C,SAAO,IAAI,QAAQ,aAAa,CAAC,GAAG,WAAW,OAAO,YAAY,CAAC;AACvE;AAEO,SAAS,aAAa,KAAqB;AAG9C,SAAO,IAAI,QAAQ,YAAY,CAAC,OAAO,KAAK,WAAW;AACnD,WAAO,WAAW,IAAI,MAAM,YAAY,IAAI,IAAI,MAAM,YAAY;AAAA,EACtE,CAAC;AACL;AAEO,IAAM,aAAa,EAAE,OAAO;AAAA,EAC/B,UAAU,EAAE,OAAO,EAAE,IAAI,GAAG,uBAAuB;AAAA,EACnD,WAAW,EAAE,OAAO,EAAE,IAAI,GAAG,uBAAuB;AACxD,CAAC;AAID,IAAM,cAA4B,EAAE;AAAA,EAAK,MACrC,EAAE;AAAA,IACE,EAAE,MAAM;AAAA,MACJ,EAAE,OAAO;AAAA,MACT,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;AAAA,IACrC,CAAC;AAAA,EACL;AACJ;AAEO,IAAM,gBAAgB,EAAE,OAAO;AAAA,EAClC,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,SAAS,EAAE,KAAK,CAAC,aAAa,eAAe,SAAS,CAAC;AAAA;AAAA,EAEvD,UAAU,EAAE,KAAK,CAAC,QAAQ,SAAS,CAAC,EAAE,SAAS;AAAA;AAAA,EAE/C,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,SAAS,EAAE,IAAI,EAAE,SAAS;AAAA,EAC1B,SAAS,YAAY,SAAS;AAAA,EAC9B,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS;AAAA,EACvE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACxC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAC7C,CAAC;;;ACKM,SAAS,uBAAuB,UAA2B;AAjDlE;AAkDI,QAAM,mBAAmB,CAAC,OAAO,QAAQ,OAAO,OAAO,QAAQ,OAAO,MAAM;AAC5E,QAAM,QAAM,cAAS,MAAM,GAAG,EAAE,IAAI,MAAxB,mBAA2B,kBAAiB;AACxD,SAAO,iBAAiB,SAAS,GAAG;AACxC;AAKO,SAAS,uBAAuB,UAA2B;AA1DlE;AA2DI,QAAM,mBAAmB,CAAC,OAAO,QAAQ,OAAO,OAAO,OAAO,KAAK;AACnE,QAAM,QAAM,cAAS,MAAM,GAAG,EAAE,IAAI,MAAxB,mBAA2B,kBAAiB;AACxD,SAAO,iBAAiB,SAAS,GAAG;AACxC;AAKO,SAAS,sBAAsB,UAA2B;AAC7D,SAAO,uBAAuB,QAAQ,KAAK,uBAAuB,QAAQ;AAC9E;AAKO,SAAS,aAAa,MAAgD;AACzE,MAAI,CAAC,MAAM;AACP,WAAO,EAAE,OAAO,OAAO,OAAO,mBAAmB;AAAA,EACrD;AAEA,MAAI,CAAC,sBAAsB,KAAK,IAAI,GAAG;AACnC,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO,4BAA4B,KAAK;AAAA,IAC5C;AAAA,EACJ;AAEA,SAAO,EAAE,OAAO,KAAK;AACzB;;;ACfO,SAAS,YAAY,IAAqB;AAC7C,QAAM,YAAY;AAClB,SAAO,UAAU,KAAK,EAAE;AAC5B;AAKO,SAAS,oBACZ,aACA,gBACyD;AACzD,MAAI,CAAC,eAAe,OAAO,gBAAgB,UAAU;AACjD,WAAO;AAAA,MACH,OAAO;AAAA,MACP,OAAO;AAAA,IACX;AAAA,EACJ;AAGA,MAAI,kBAAkB,eAAe,SAAS,GAAG;AAC7C,UAAM,UAAU,eAAe,OAAO,WAAS;AAC3C,YAAM,QAAQ,YAAY,KAAK;AAC/B,aAAO,UAAU,UAAa,UAAU,QAAQ,UAAU;AAAA,IAC9D,CAAC;AAED,QAAI,QAAQ,SAAS,GAAG;AACpB,aAAO;AAAA,QACH,OAAO;AAAA,QACP,QAAQ,QAAQ,IAAI,YAAU;AAAA,UAC1B;AAAA,UACA,SAAS;AAAA,QACb,EAAE;AAAA,MACN;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO,EAAE,OAAO,KAAK;AACzB;AAKO,SAAS,qBAAqB,aAAuC;AACxE,QAAM,aAA0B,CAAC;AAEjC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,WAAW,GAAG;AAEpD,eAAW,GAAG,IAAI;AAAA,EACtB;AAEA,SAAO;AACX;;;ACkBO,IAAM,eAA0C;AAAA,EACnD,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,WAAW;AAAA,EACX,SAAS;AAAA,EACT,WAAW;AAAA,EACX,aAAa;AAAA,EACb,eAAe;AACnB;AA+BO,IAAM,iBAAyC;AAAA,EAClD,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,EACT,aAAa;AAAA,EACb,eAAe;AACnB;AAKO,SAAS,wBACZ,SACA,WACA,UACkB;AAxNtB;AAyNI,QAAM,cAAc,aAAa,SAAS,IAAiB,KAAK;AAChE,QAAM,UAAU,eAAe,WAAW,KAAK;AAG/C,QAAM,OAA4B,EAAE,KAAI,cAAS,aAAT,mBAAmB,SAAQ,CAAC,EAAG;AACvE,MAAI,SAAS,cAAc,MAAM,QAAQ,SAAS,UAAU,GAAG;AAI3D,SAAK,kBAAkB,SAAS,WAAW,IAAI,SAAO;AAlO9D,UAAAA,KAAAC;AAmOY,UAAI,OAAO,QAAQ;AAAU,eAAO;AAGpC,eAAQD,MAAA,IAAY,iBAAZ,gBAAAA,IAA0B,SAAOC,MAAA,IAAY,iBAAZ,gBAAAA,IAA0B,SAAQ;AAAA,IAC/E,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACH,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA,UAAU,SAAS,YAAY;AAAA,IAC/B,cAAa,cAAS,aAAT,mBAAmB;AAAA,IAChC,UAAU,SAAS,WAAW;AAAA,IAC9B,SAAS,SAAS;AAAA,IAClB,MAAM,OAAO,KAAK,IAAI,EAAE,SAAS,IAAI,OAAO;AAAA,EAChD;AACJ;AAKO,SAAS,wBACZ,SACA,SACkB;AAClB,QAAM,UAA8B;AAAA,IAChC,SAAS;AAAA,IACT,UAAU;AAAA,EACd;AAEA,MAAI,QAAQ,aAAa,QAAW;AAChC,YAAQ,WAAW,QAAQ;AAAA,EAC/B;AACA,MAAI,QAAQ,SAAS,QAAW;AAC5B,YAAQ,OAAO,QAAQ;AAAA,EAC3B;AACA,MAAI,QAAQ,gBAAgB,QAAW;AACnC,YAAQ,cAAc,QAAQ;AAAA,EAClC;AACA,MAAI,QAAQ,YAAY,QAAW;AAC/B,YAAQ,WAAW,CAAC,CAAC,QAAQ;AAAA,EACjC;AAEA,MAAI,QAAQ,YAAY,QAAW;AAC/B,YAAQ,UAAU,QAAQ;AAAA,EAC9B;AAEA,MAAI,QAAQ,eAAe,QAAW;AAClC,YAAQ,OAAO,EAAE,GAAI,QAAQ,QAAQ,CAAC,GAAI,iBAAiB,QAAQ,WAAW;AAAA,EAClF,WAAW,QAAQ,SAAS,QAAW;AACnC,YAAQ,OAAO,QAAQ;AAAA,EAC3B;AAEA,SAAO;AACX;AAKO,SAAS,8BAA8B,IAAqD;AAC/F,SAAO;AAAA,IACH,SAAS;AAAA,IACT,MAAM,GAAG,eAAe,GAAG;AAAA,IAC3B,aAAa,GAAG;AAAA,EACpB;AACJ;;;AC8CO,SAAS,aAGZ,gBACA,SACM;AAEN,QAAM,qBAAqB,CAAC,QAAwB;AAChD,WAAO,IACF,QAAQ,YAAY,CAAC,WAAW,IAAI,OAAO,YAAY,GAAG,EAC1D,QAAQ,MAAM,EAAE;AAAA,EACzB;AAGA,QAAM,iBAAiB,CAAC,QAAkB;AACtC,QAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACjC,aAAO;AAAA,IACX;AAEA,QAAI,MAAM,QAAQ,GAAG,GAAG;AACpB,aAAO,IAAI,IAAI,cAAc;AAAA,IACjC;AAEA,UAAM,SAAc,CAAC;AAErB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC5C,UAAI,QAAQ,SAAS,QAAQ,MAAM;AAE/B,eAAO,GAAG,IAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,IAAI,cAAc,IAAI,eAAe,KAAK;AAAA,MACzF,OAAO;AAEH,cAAM,WAAW,mBAAmB,GAAG;AACvC,YAAI,SAAS,OAAO,UAAU,UAAU;AACpC,iBAAO,QAAQ,IAAI,eAAe,KAAK;AAAA,QAC3C,OAAO;AACH,iBAAO,QAAQ,IAAI;AAAA,QACvB;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAEA,SAAO,eAAe,OAAO;AACjC;;;AC/XA,IAAM,WAAW,MAAM;AACrB,QAAM,IAAI,QAAQ,IAAI,kBAAkB,QAAQ,IAAI,SAAS;AAC7D,SAAO,MAAM,OAAO,MAAM,UAAU,EAAE,YAAY,MAAM;AAC1D,GAAG;AAEI,SAAS,SAAS,MAAa;AACpC,MAAI,CAAC;AAAS;AAEd,UAAQ,IAAI,GAAG,IAAI;AACrB;;;AC8CO,SAAS,kBAA6D,QAKnD;AACtB,SAAO;AAAA,IACH,cAAc;AAAA,MACV,MAAM,OAAO;AAAA,MACb,aAAa,OAAO;AAAA,MACpB,aAAa,OAAO;AAAA,MACpB,QAAQ,OAAO;AAAA,IACnB;AAAA,IACA,UAAU,OAAO;AAAA,IACjB,2BAA2B;AAAA,EAC/B;AACJ;AAkBO,SAAS,aAAa,QAIX;AACd,SAAO;AACX;;;ACWA,IAAM;AAAA,EACF,wBAAwB;AAC5B,IAAI,QAAQ;AAEZ,IAAM,cAAc,CAAC,YAAwB,OAAU,YAA6F;AAEhJ,QAAM,EAAE,UAAU,UAAU,IAAI;AAEhC,QAAM;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACJ,IAAI,cAAc,MAAM,OAAO;AAE/B,QAAM,YAAY,QAAQ,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,SAAS,MAAM;AAC9D,UAAM,OAAO,CAAC;AACd,QAAI,KAAK,EAAE,OAAO,UAAU,CAAC;AAC7B,WAAO;AAAA,EACX,GAAG,MAGY;AAGf,QAAM,kBAAkB,YAAY,YAAY,SAAa,YAAY;AAEzE,QAAM,cAAmB;AAAA,IACrB;AAAA,IACA;AAAA;AAAA,IAEA,UAAW,QAAgB;AAAA,IAC3B;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACJ;AAEA,MAAI;AAAiB,gBAAY,WAAW;AAE5C,QAAM,MAAM,MAAM,MAAM,GAAG,wBAAwB,aAAa;AAAA,IAC5D,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,gBAAgB;AAAA,MAChB,iBAAiB,UAAU;AAAA,IAC/B;AAAA,IACA,MAAM,KAAK,UAAU,WAAW;AAAA,EACpC,CAAC;AAED,MAAI;AACJ,QAAM,eAAe,MAAM,IAAI,KAAK;AAEpC,MAAI;AACA,eAAW,KAAK,MAAM,YAAY;AAAA,EACtC,SAAS,OAAP;AACE,YAAQ,MAAM,kCAAkC,OAAO,WAAW,IAAI,MAAM;AAC5E,YAAQ,MAAM,kBAAkB,YAAY;AAC5C,UAAM,IAAI,MAAM,uCAAuC,IAAI,YAAY,0BAA0B,eAAe;AAAA,EACpH;AAEA,MAAK,SAA2B,QAAQ;AACpC,UAAM,QAAQ;AACd,YAAQ,MAAM,cAAe,QAA0B;AACvD,UAAM,eAAgB,SAA2B,OAAO,IAAI,CAAC,MAAW;AACpE,UAAI,MAAM,GAAG,EAAE,UAAU,EAAE;AAC3B,UAAI,EAAE,mBAAmB;AACrB,eAAO,yBAAyB,KAAK,UAAU,EAAE,iBAAiB;AAAA,MACtE;AACA,UAAI,EAAE,eAAe;AACjB,eAAO,qBAAqB,KAAK,UAAU,EAAE,aAAa;AAAA,MAC9D;AACA,aAAO;AAAA,IACX,CAAC,EAAE,KAAK,IAAI;AACZ,UAAM,IAAI,MAAM;AAAA,EAAe,cAAc;AAAA,EACjD;AAEA,SAAO;AACX;AA8XA,IAAM,WAAW,CAAC,YACd,OACI,gBACA,SACA,YAKiG;AArkBzG;AAwkBQ,QAAM,mBAAmB,CAAC,MAAgB;AACtC,QAAI,CAAC,MAAM,QAAQ,CAAC;AAAG,aAAO;AAC9B,UAAM,MAAa,CAAC;AACpB,eAAW,QAAQ,GAAG;AAClB,UAAI,OAAO,SAAS,UAAU;AAC1B,YAAI,KAAK,aAAa,IAAI,CAAC;AAC3B;AAAA,MACJ;AACA,UAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACtB,YAAI,KAAK,IAAI;AACb;AAAA,MACJ;AACA,YAAM,CAAC,KAAK,KAAK,IAAI;AAErB,UAAI,SAAS,MAAM;AACf,YAAI,KAAK,aAAa,GAAG,CAAC;AAC1B;AAAA,MACJ;AAGA,UAAI;AACJ,UAAI,OAAO,UAAU,UAAU;AAC3B,mBAAW,CAAC,KAAK;AAAA,MACrB,WAAW,MAAM,QAAQ,KAAK,GAAG;AAE7B,YAAI,MAAM,WAAW,KAAK,OAAO,MAAM,CAAC,MAAM,aAAa,MAAM,QAAQ,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,OAAO;AACrG,qBAAW,CAAC,KAAK;AAAA,QACrB,OAAO;AACH,qBAAW;AAAA,QACf;AAAA,MACJ,OAAO;AACH,mBAAW,CAAC,KAAK;AAAA,MACrB;AAEA,UAAI,KAAK,CAAC,aAAa,GAAG,GAAG,iBAAiB,QAAQ,CAAC,CAAC;AAAA,IAC5D;AACA,WAAO;AAAA,EACX;AAEA,QAAM,iBAAgB,mCAAS,gBAAe;AAE9C,QAAM,UAAU;AAAA,IACZ,SAAS;AAAA,IACT,MAAM,eAAe,aAAa;AAAA,IAClC,UAAU;AAAA,IACV,SAAS,kBAAiB,mCAAS,YAAW,CAAC,CAAC;AAAA,IAChD,UAAU;AAAA,EACd;AAEA,MAAI;AAAE,UAAM,4BAA4B,KAAK,UAAU,OAAO,CAAC;AAAA,EAAG,SAAS,GAAP;AAAA,EAAY;AAGhF,QAAM,OAAO,MAAM,QAAQ,OAAc;AAEzC,MAAI;AAAE,UAAM,4BAA4B,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,EAAG,SAAS,GAAP;AAAA,EAAY;AAEtF,QAAM,UAAQ,kCAAM,SAAN,mBAAY,YAAS,kCAAM,SAAN,mBAAY;AAG/C,QAAM,kBAAuC,CAAC;AAC9C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,CAAC,CAAC,GAAG;AACpD,oBAAgB,aAAa,GAAG,CAAC,IAAI;AAAA,EACzC;AAEA,SAAO;AAAA,IACH,MAAM;AAAA,EACV;AACJ;AAEJ,IAAM,UAAU,CAAC,YACb,YAAY;AACR,QAAM,OAAO,MAAM,QAAQ;AAAA,IACvB,SAAS;AAAA,EACb,CAAC;AAED,SAAO;AACX;AAEJ,IAAM,aAAa,CAAC,YAChB,OACI,gBACA,YAQ8E;AAjqBtF;AAkqBQ,QAAM;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,CAAC;AAAA,IACX,OAAO,CAAC;AAAA,IACR,aAAa;AAAA,EACjB,IAAI;AAEJ,QAAM,WAAW,kBAAkB;AAGnC,QAAM,mBAAmB,CAAC,MAAgB;AACtC,QAAI,CAAC,MAAM,QAAQ,CAAC;AAAG,aAAO;AAC9B,UAAM,MAAa,CAAC;AACpB,eAAW,QAAQ,GAAG;AAClB,UAAI,OAAO,SAAS,UAAU;AAC1B,YAAI,KAAK,aAAa,IAAI,CAAC;AAC3B;AAAA,MACJ;AACA,UAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACtB,YAAI,KAAK,IAAI;AACb;AAAA,MACJ;AACA,YAAM,CAAC,KAAK,KAAK,IAAI;AACrB,UAAI,SAAS,MAAM;AACf,YAAI,KAAK,aAAa,GAAG,CAAC;AAC1B;AAAA,MACJ;AACA,UAAI;AACJ,UAAI,OAAO,UAAU,UAAU;AAC3B,mBAAW,CAAC,KAAK;AAAA,MACrB,WAAW,MAAM,QAAQ,KAAK,GAAG;AAC7B,YAAI,MAAM,WAAW,KAAK,OAAO,MAAM,CAAC,MAAM,aAAa,MAAM,QAAQ,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,OAAO;AACrG,qBAAW,CAAC,KAAK;AAAA,QACrB,OAAO;AACH,qBAAW;AAAA,QACf;AAAA,MACJ,OAAO;AACH,mBAAW,CAAC,KAAK;AAAA,MACrB;AACA,UAAI,KAAK,CAAC,aAAa,GAAG,GAAG,iBAAiB,QAAQ,CAAC,CAAC;AAAA,IAC5D;AACA,WAAO;AAAA,EACX;AAGA,MAAI,iBAAiB,aAAa,gBAAgB,OAAO;AAIzD,MAAI;AACA,UAAM,gBAAgB,MAAM,QAAQ,OAAO,EAAE;AAG7C,UAAM,wBAAwB,oBAAI,IAAoB;AACtD,kBAAc,KAAK,cAAc,QAAQ,CAAC,OAAY;AAElD,YAAM,kBAAkB,GAAG,QAAQ,GAAG;AACtC,4BAAsB,IAAI,GAAG,IAAI,eAAe;AAAA,IACpD,CAAC;AAID,UAAM,oBAAoB,oBAAI,IAAsB;AAGpD,UAAM,oBAAoB,cAAc,KAAK,cAAc;AAAA,MAAK,CAAC,OAC7D,GAAG,SAAS,eAAe,aAAa,QAAQ,GAAG,OAAO,eAAe,aAAa;AAAA,IAC1F;AAEA,QAAI,qBAAqB,kBAAkB,QAAQ;AAE/C,wBAAkB,OAAO,QAAQ,CAAC,UAAe;AA3uBjE,YAAAC;AA4uBoB,aAAK,MAAM,SAAS,eAAe,MAAM,SAAS,oBAAkBA,MAAA,MAAM,SAAN,gBAAAA,IAAY,kBAAiB;AAE7F,gBAAM,mBAAmB,MAAM,KAAK,gBAC/B,IAAI,CAAC,cAAsB,sBAAsB,IAAI,SAAS,KAAK,SAAS;AAEjF,4BAAkB,IAAI,MAAM,MAAM,gBAAgB;AAAA,QACtD;AAAA,MACJ,CAAC;AAAA,IACL;AAQA,UAAM,4BAA4B,CAAC,KAAU,cAAqC,QAAQ,MAAW;AACjG,UAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACjC,eAAO;AAAA,MACX;AAEA,UAAI,MAAM,QAAQ,GAAG,GAAG;AACpB,eAAO,IAAI,IAAI,UAAQ,0BAA0B,MAAM,cAAc,QAAQ,CAAC,CAAC;AAAA,MACnF;AAEA,YAAM,SAAc,CAAC;AACrB,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC5C,YAAI,QAAQ,SAAS,QAAQ,MAAM;AAE/B,iBAAO,GAAG,IAAI,MAAM,QAAQ,KAAK,IAC1B,MAAgB,IAAI,OAAK,0BAA0B,GAAG,cAAc,QAAQ,CAAC,CAAC,IAC/E,0BAA0B,OAAO,cAAc,QAAQ,CAAC;AAAA,QAClE,WAAW,aAAa,IAAI,GAAG,GAAG;AAE9B,gBAAM,mBAAmB,aAAa,IAAI,GAAG;AAC7C,gBAAM,aAAa,SAAS,OAAO,UAAU,WAAY,QAAgC,CAAC;AAC1F,gBAAM,YAAY,OAAO,KAAK,UAAU;AAGxC,gBAAM,eAAe,UAAU,KAAK,QAAM,CAAC,OAAO,QAAQ,OAAO,EAAE,SAAS,EAAE,CAAC;AAE/E,cAAI,cAAc;AAGd,kBAAM,cAAc,WAAW,YAAY;AAC3C,kBAAM,iBAAiB,eAAe,OAAO,gBAAgB,WAAW,cAAqC,CAAC;AAC9G,kBAAM,YAAY,OAAO,KAAK,cAAc;AAE5C,kBAAM,qBAAqB,UAAU;AAAA,cAAK,QACtC,iBAAiB,SAAS,EAAE;AAAA,cAC5B,iBAAiB,KAAK,QAAM,aAAa,EAAE,MAAM,EAAE;AAAA;AAAA,YACvD;AAEA,gBAAI,sBAAsB,eAAe,kBAAkB,GAAG;AAG1D,oBAAM,iBAAiB,iBAAiB,SAAS,kBAAkB,IAC7D,qBACA,aAAa,kBAAkB;AACrC,oBAAM,SAAS,GAAG,OAAO;AACzB,oBAAM,mBAAmB,0BAA0B,eAAe,kBAAkB,GAAG,cAAc,QAAQ,CAAC;AAC9G,qBAAO,MAAM,IAAI;AAAA,gBACb,CAAC,YAAY,GAAG;AAAA,cACpB;AAAA,YACJ,OAAO;AAEH,oBAAM,kBAAkB,iBAAiB,CAAC;AAC1C,oBAAM,SAAS,GAAG,OAAO;AACzB,oBAAM,mBAAmB,0BAA0B,aAAa,cAAc,QAAQ,CAAC;AACvF,qBAAO,MAAM,IAAI;AAAA,gBACb,CAAC,YAAY,GAAG;AAAA,cACpB;AAAA,YACJ;AAAA,UACJ,OAAO;AAIH,kBAAM,gBAAgB,UAAU;AAAA,cAAK,QACjC,iBAAiB,SAAS,EAAE;AAAA,cAC5B,iBAAiB,KAAK,QAAM,aAAa,EAAE,MAAM,EAAE;AAAA;AAAA,YACvD;AAEA,gBAAI,iBAAiB,WAAW,aAAa,GAAG;AAG5C,oBAAM,iBAAiB,iBAAiB,SAAS,aAAa,IACxD,gBACA,aAAa,aAAa;AAChC,oBAAM,SAAS,GAAG,OAAO;AACzB,qBAAO,MAAM,IAAI,0BAA0B,WAAW,aAAa,GAAG,cAAc,QAAQ,CAAC;AAAA,YACjG,OAAO;AAEH,oBAAM,kBAAkB,iBAAiB,CAAC;AAC1C,oBAAM,SAAS,GAAG,OAAO;AACzB,qBAAO,MAAM,IAAI,SAAS,OAAO,UAAU,WACrC,0BAA0B,OAAO,cAAc,QAAQ,CAAC,IACxD;AAAA,YACV;AAAA,UACJ;AAAA,QACJ,OAAO;AAEH,iBAAO,GAAG,IAAI,SAAS,OAAO,UAAU,WAClC,0BAA0B,OAAO,cAAc,QAAQ,CAAC,IACxD;AAAA,QACV;AAAA,MACJ;AACA,aAAO;AAAA,IACX;AAEA,qBAAiB,0BAA0B,gBAAgB,iBAAiB;AAAA,EAChF,SAAS,OAAP;AAEE,YAAQ,KAAK,gDAAgD,KAAK;AAAA,EACtE;AAEA,QAAM,UAAe;AAAA,IACjB,MAAM,eAAe,aAAa;AAAA,IAClC,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,SAAS,iBAAiB,OAAO;AAAA,IACjC;AAAA,EACJ;AACA,MAAI;AAAE,UAAM,8BAA8B,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,EAAG,SAAS,GAAP;AAAA,EAAY;AAC3F,QAAM,OAAO,MAAM,QAAe,OAAc;AAEhD,MAAI;AAAE,UAAM,8BAA8B,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,EAAG,SAAS,GAAP;AAAA,EAAY;AAGxF,MAAI,qBAAqB,UAAa,SAAb,mBAAmB,IAAI,CAAC,UAAe;AAC5D,UAAM,aAAkC,EAAE,IAAI,MAAM,GAAG;AACvD,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC9C,UAAI,QAAQ,MAAM;AACd,mBAAW,aAAa,GAAG,CAAC,IAAI;AAAA,MACpC;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAKA,SAAO;AAAA,IACH,GAAG;AAAA,IACH,MAAM;AAAA,EACV;AACJ;AAEJ,IAAM,OAAO,CAAC,YAAqB;AAC/B,SAAO,OACH,cACA,UAAuB,CAAC,MACF;AACtB,UAAM;AAAA,MACF;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,gBAAgB;AAAA,IACpB,IAAI;AAGJ,UAAM,yBAAyB,aAAa,IAAI,QAAM;AAClD,UAAI,kBAAkB,IAAI;AACtB,eAAO,GAAG;AAAA,MACd;AACA,aAAO;AAAA,IACX,CAAC;AAED,QAAI;AACA,YAAM,4CAA4C,uBAAuB,IAAI,QAAM,GAAG,IAAI,CAAC;AAAA,IAC/F,SAAS,GAAP;AAAA,IAEF;AAGA,QAAI,gBAAwC;AAC5C,QAAI;AACA,sBAAgB,MAAM,QAAQ,OAAO,EAAE;AAAA,IAC3C,SAAS,GAAP;AAEE,cAAQ,KAAK,6BAA6B,CAAC;AAC3C,sBAAgB;AAAA,IACpB;AAIA,UAAM,sBAAsB,oBAAI,IAAoB;AACpD,UAAM,sBAAsB,oBAAI,IAAoB;AACpD,QAAI,eAAe;AACf,oBAAc,KAAK,cAAc,QAAQ,QAAM;AAE3C,cAAM,OAAQ,GAAW,QAAQ,GAAG;AACpC,4BAAoB,IAAI,GAAG,IAAI,IAAI;AACnC,4BAAoB,IAAI,MAAM,GAAG,EAAE;AAAA,MACvC,CAAC;AAAA,IACL;AAEA,UAAM,YAAY,oBAAI,IAUnB;AAEH,QAAI,eAAe;AACf,oBAAc,KAAK,cAAc,QAAQ,QAAM;AAC3C,cAAM,YAAY,oBAAI,IAAiB;AACvC,WAAG,OAAO,QAAQ,OAAK;AAl8BvC;AAo8BoB,gBAAM,oBAAkB,OAAE,SAAF,mBAAQ,oBAAmB,CAAC,GAC/C,IAAI,WAAS,oBAAoB,IAAI,KAAK,KAAK,KAAK,EACpD,OAAO,OAAO;AAGnB,oBAAU,IAAI,EAAE,MAAM;AAAA,YAClB,IAAI,EAAE;AAAA,YACN,MAAM,EAAE;AAAA,YACR,MAAM,EAAE;AAAA,YACR,UAAU,EAAE;AAAA,YACZ,UAAU,EAAE;AAAA,YACZ,iBAAiB;AAAA,UACrB,CAAC;AAAA,QACL,CAAC;AACD,cAAM,OAAQ,GAAW,QAAQ,GAAG;AACpC,kBAAU,IAAI,MAAM;AAAA,UAChB,IAAI,GAAG;AAAA,UACP,QAAQ;AAAA,QACZ,CAAC;AAAA,MACL,CAAC;AAAA,IACL;AAEA,UAAM,UAAwB,CAAC;AAE/B,eAAW,MAAM,wBAAwB;AACrC,YAAM,oBAAoB,UAAU,IAAI,GAAG,IAAI;AAE/C,UAAI,CAAC,mBAAmB;AAEpB,YAAI,iBAAiB,mBAAmB;AACpC,kBAAQ,KAAK,EAAE,MAAM,UAAU,aAAa,GAAG,MAAM,QAAQ,EAAE,QAAQ,wBAAwB,aAAa,GAAG,EAAE,CAAC;AAClH,cAAI,CAAC,QAAQ;AACT,gBAAI;AACA,oBAAM,kBAAkB,EAAE;AAAA,YAC9B,SAAS,GAAP;AACE,sBAAQ,KAAK,EAAE,MAAM,YAAY,aAAa,GAAG,MAAM,QAAQ,EAAE,QAAQ,iBAAiB,OAAO,OAAO,CAAC,EAAE,EAAE,CAAC;AAAA,YAClH;AAAA,UACJ;AAAA,QACJ,OAAO;AACH,kBAAQ,KAAK,EAAE,MAAM,QAAQ,aAAa,GAAG,MAAM,QAAQ,EAAE,QAAQ,uBAAuB,EAAE,CAAC;AAAA,QACnG;AACA;AAAA,MACJ;AAGA,YAAM,aAAoB,CAAC;AAC3B,YAAM,eAAe,kBAAkB;AACvC,YAAM,gBAAgB,GAAG,UAAU,CAAC;AAGpC,iBAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,aAAa,GAAG;AAEvD,cAAM,kBAAkB,aAAa,KAAK;AAC1C,cAAM,cAAc,aAAa,IAAI,eAAe;AAEpD,YAAI,CAAC,aAAa;AACd,qBAAW,KAAK;AAAA,YACZ,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,SAAS;AAAA,cACL,MAAM,KAAK;AAAA,cACX,UAAU,KAAK,YAAY;AAAA,cAC3B,SAAS,KAAK,WAAW;AAAA,YAC7B;AAAA,UACJ,CAAC;AACD;AAAA,QACJ;AAGA,cAAM,UAAe,CAAC;AAGtB,YAAI,YAAY,SAAS,KAAK,MAAM;AAChC,kBAAQ,OAAO;AAAA,YACX,UAAU,YAAY;AAAA,YACtB,SAAS,KAAK;AAAA,UAClB;AAAA,QACJ;AAGA,cAAM,kBAAkB,KAAK,YAAY;AACzC,YAAI,YAAY,aAAa,iBAAiB;AAC1C,kBAAQ,WAAW;AAAA,YACf,UAAU,YAAY;AAAA,YACtB,SAAS;AAAA,UACb;AAAA,QACJ;AAGA,cAAM,iBAAiB,KAAK,WAAW;AACvC,YAAI,YAAY,aAAa,gBAAgB;AACzC,kBAAQ,UAAU;AAAA,YACd,UAAU,YAAY;AAAA,YACtB,SAAS;AAAA,UACb;AAAA,QACJ;AAGA,aAAK,KAAK,SAAS,eAAe,KAAK,SAAS,kBAAkB,KAAK,YAAY;AAC/E,gBAAM,oBAAoB,KAAK,WAC1B,IAAI,SAAO,OAAO,QAAQ,WAAW,MAAM,IAAI,aAAa,IAAI,EAChE,KAAK;AACV,gBAAM,sBAAsB,YAAY,mBAAmB,CAAC,GAAG,KAAK;AAEpE,cAAI,KAAK,UAAU,iBAAiB,MAAM,KAAK,UAAU,kBAAkB,GAAG;AAC1E,oBAAQ,aAAa;AAAA,cACjB,UAAU;AAAA,cACV,SAAS;AAAA,YACb;AAAA,UACJ;AAAA,QACJ;AAEA,YAAI,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AACjC,qBAAW,KAAK;AAAA,YACZ,OAAO;AAAA,YACP,QAAQ;AAAA,YACR;AAAA,UACJ,CAAC;AAAA,QACL;AAAA,MACJ;AAGA,iBAAW,CAAC,iBAAiB,WAAW,KAAK,cAAc;AAEvD,cAAM,qBAAqB,aAAa,eAAe;AACvD,YAAI,EAAE,sBAAsB,gBAAgB;AACxC,qBAAW,KAAK;AAAA,YACZ,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,UAAU;AAAA,cACN,MAAM,YAAY;AAAA,cAClB,UAAU,YAAY;AAAA,cACtB,SAAS,YAAY;AAAA,YACzB;AAAA,UACJ,CAAC;AAAA,QACL;AAAA,MACJ;AAEA,UAAI,WAAW,WAAW,GAAG;AACzB,gBAAQ,KAAK,EAAE,MAAM,QAAQ,aAAa,GAAG,KAAK,CAAC;AAAA,MACvD,OAAO;AACH,gBAAQ,KAAK,EAAE,MAAM,YAAY,aAAa,GAAG,MAAM,QAAQ,EAAE,WAAW,EAAE,CAAC;AAAA,MACnF;AAAA,IACJ;AAEA,WAAO,EAAE,QAAQ;AAAA,EACrB;AACJ;AAMA,IAAM,iBAAiB,CAAC,YAAqB;AACzC,SAAO,OACH,cACA,UAAuB,CAAC,MACF;AAjmC9B;AAkmCQ,UAAM;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB,sBAAsB;AAAA,MACtB,eAAe;AAAA,MACf,oBAAoB;AAAA,IACxB,IAAI;AAGJ,UAAM,yBAAyB,aAAa,IAAI,QAAM;AAClD,UAAI,kBAAkB,IAAI;AACtB,eAAO,GAAG;AAAA,MACd;AACA,aAAO;AAAA,IACX,CAAC;AAGD,QAAI,gBAAwC;AAC5C,QAAI;AACA,sBAAgB,MAAM,QAAQ,OAAO,EAAE;AAAA,IAC3C,SAAS,GAAP;AACE,cAAQ,KAAK,6BAA6B,CAAC;AAC3C,sBAAgB;AAAA,IACpB;AAGA,UAAM,sBAAsB,oBAAI,IAAoB;AACpD,UAAM,sBAAsB,oBAAI,IAAoB;AACpD,QAAI,eAAe;AACf,oBAAc,KAAK,cAAc,QAAQ,QAAM;AAE3C,cAAM,OAAQ,GAAW,QAAQ,GAAG;AACpC,4BAAoB,IAAI,GAAG,IAAI,IAAI;AACnC,4BAAoB,IAAI,MAAM,GAAG,EAAE;AAAA,MACvC,CAAC;AAAA,IACL;AAEA,UAAM,YAAY,oBAAI,IAUnB;AAEH,QAAI,eAAe;AACf,oBAAc,KAAK,cAAc,QAAQ,QAAM;AAC3C,cAAM,YAAY,oBAAI,IAAiB;AACvC,WAAG,OAAO,QAAQ,OAAK;AA1pCvC,cAAAA;AA2pCoB,gBAAM,oBAAkBA,MAAA,EAAE,SAAF,gBAAAA,IAAQ,oBAAmB,CAAC,GAC/C,IAAI,WAAS,oBAAoB,IAAI,KAAK,KAAK,KAAK,EACpD,OAAO,OAAO;AAEnB,oBAAU,IAAI,EAAE,MAAM;AAAA,YAClB,IAAI,EAAE;AAAA,YACN,MAAM,EAAE;AAAA,YACR,MAAM,EAAE;AAAA,YACR,UAAU,EAAE;AAAA,YACZ,UAAU,EAAE;AAAA,YACZ,iBAAiB;AAAA,UACrB,CAAC;AAAA,QACL,CAAC;AAED,cAAM,OAAQ,GAAW,QAAQ,GAAG;AACpC,kBAAU,IAAI,MAAM;AAAA,UAChB,IAAI,GAAG;AAAA,UACP,QAAQ;AAAA,QACZ,CAAC;AAAA,MACL,CAAC;AAAA,IACL;AAEA,QAAI;AACA,YAAM,oCAAoC,MAAM,KAAK,UAAU,KAAK,CAAC,CAAC;AAAA,IAC1E,SAAS,GAAP;AAAA,IAAY;AAEd,UAAM,UAAwB,CAAC;AAK/B,eAAW,MAAM,wBAAwB;AACrC,YAAM,oBAAoB,UAAU,IAAI,GAAG,IAAI;AAE/C,UAAI,CAAC,mBAAmB;AAEpB,YAAI,iBAAiB,mBAAmB;AACpC,kBAAQ,KAAK,EAAE,MAAM,UAAU,aAAa,GAAG,MAAM,QAAQ,EAAE,QAAQ,uBAAuB,EAAE,CAAC;AACjG,cAAI,CAAC,QAAQ;AACT,gBAAI;AACA,oBAAM,kBAAkB,EAAE;AAE1B,kCAAoB,IAAI,GAAG,MAAM,GAAG,IAAI;AAAA,YAC5C,SAAS,GAAP;AACE,sBAAQ,KAAK,EAAE,MAAM,YAAY,aAAa,GAAG,MAAM,QAAQ,EAAE,QAAQ,iBAAiB,OAAO,OAAO,CAAC,EAAE,EAAE,CAAC;AAAA,YAClH;AAAA,UACJ;AAAA,QACJ,OAAO;AACH,kBAAQ,KAAK,EAAE,MAAM,QAAQ,aAAa,GAAG,MAAM,QAAQ,EAAE,QAAQ,uBAAuB,EAAE,CAAC;AAAA,QACnG;AAAA,MACJ;AAAA,IACJ;AAKA,QAAI,CAAC,QAAQ;AACT,UAAI;AACA,wBAAgB,MAAM,QAAQ,OAAO,EAAE;AAEvC,4BAAoB,MAAM;AAC1B,4BAAoB,MAAM;AAC1B,YAAI,eAAe;AACf,wBAAc,KAAK,cAAc,QAAQ,QAAM;AAC3C,kBAAM,OAAQ,GAAW,QAAQ,GAAG;AACpC,gCAAoB,IAAI,GAAG,IAAI,IAAI;AACnC,gCAAoB,IAAI,MAAM,GAAG,EAAE;AAAA,UACvC,CAAC;AAAA,QACL;AAEA,kBAAU,MAAM;AAChB,YAAI,eAAe;AACf,wBAAc,KAAK,cAAc,QAAQ,QAAM;AAC3C,kBAAM,YAAY,oBAAI,IAAiB;AACvC,eAAG,OAAO,QAAQ,OAAK;AAruC/C,kBAAAA;AAsuC4B,oBAAM,oBAAkBA,MAAA,EAAE,SAAF,gBAAAA,IAAQ,oBAAmB,CAAC,GAC/C,IAAI,WAAS,oBAAoB,IAAI,KAAK,KAAK,KAAK,EACpD,OAAO,OAAO;AAEnB,wBAAU,IAAI,EAAE,MAAM;AAAA,gBAClB,IAAI,EAAE;AAAA,gBACN,MAAM,EAAE;AAAA,gBACR,MAAM,EAAE;AAAA,gBACR,UAAU,EAAE;AAAA,gBACZ,UAAU,EAAE;AAAA,gBACZ,iBAAiB;AAAA,cACrB,CAAC;AAAA,YACL,CAAC;AAED,kBAAM,OAAQ,GAAW,QAAQ,GAAG;AAEpC,sBAAU,IAAI,MAAM;AAAA,cAChB,IAAI,GAAG;AAAA,cACP,QAAQ;AAAA,YACZ,CAAC;AAAA,UACL,CAAC;AAAA,QACL;AAAA,MACJ,SAAS,GAAP;AACE,gBAAQ,KAAK,2DAA2D,CAAC;AAAA,MAC7E;AAAA,IACJ;AAKA,QAAI;AACA,YAAM,8CAA8C,uBAAuB,IAAI,QAAM,GAAG,IAAI,CAAC;AAAA,IACjG,SAAS,GAAP;AAAA,IAAY;AACd,eAAW,MAAM,wBAAwB;AACrC,UAAI;AACA,cAAM,SAAS,UAAU,IAAI,GAAG,IAAI;AACpC,cAAM,yCAAyC,OAAO,GAAG,IAAI,WAAW,OAAO,GAAG,cAAc,KAAK,UAAU,GAAG,IAAI,gBAAgB,UAAU,IAAI,GAAG,IAAI,GAAG;AAAA,MAClK,SAAS,GAAP;AAAA,MAAY;AACd,YAAM,oBAAoB,UAAU,IAAI,GAAG,IAAI;AAE/C,UAAI,CAAC,mBAAmB;AAEpB;AAAA,MACJ;AAGA,YAAM,aAA0B,CAAC;AACjC,YAAM,eAAe,kBAAkB;AACvC,YAAM,gBAAgB,GAAG,UAAU,CAAC;AACpC,YAAM,iBAAgE,CAAC;AACvE,YAAM,iBAAoF,CAAC;AAC3F,YAAM,iBAA2B,CAAC;AAGlC,iBAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,aAAa,GAAG;AACvD,cAAM,kBAAkB,aAAa,KAAK;AAC1C,cAAM,cAAc,aAAa,IAAI,eAAe;AAEpD,YAAI,CAAC,aAAa;AACd,qBAAW,KAAK;AAAA,YACZ,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,SAAS;AAAA,cACL,MAAM,KAAK;AAAA,cACX,UAAU,KAAK,YAAY;AAAA,cAC3B,SAAS,KAAK,WAAW;AAAA,YAC7B;AAAA,UACJ,CAAC;AACD,cAAI,uBAAuB,aAAa;AACpC,2BAAe,KAAK,EAAE,MAAM,OAAO,KAAK,KAAK,CAAC;AAAA,UAClD;AACA;AAAA,QACJ;AAGA,cAAM,UAAe,CAAC;AAEtB,YAAI,YAAY,SAAS,KAAK,MAAM;AAChC,kBAAQ,OAAO;AAAA,YACX,UAAU,YAAY;AAAA,YACtB,SAAS,KAAK;AAAA,UAClB;AAAA,QACJ;AAEA,cAAM,kBAAkB,KAAK,YAAY;AACzC,YAAI,YAAY,aAAa,iBAAiB;AAC1C,kBAAQ,WAAW;AAAA,YACf,UAAU,YAAY;AAAA,YACtB,SAAS;AAAA,UACb;AAAA,QACJ;AAEA,cAAM,iBAAiB,KAAK,WAAW;AACvC,YAAI,YAAY,aAAa,gBAAgB;AACzC,kBAAQ,UAAU;AAAA,YACd,UAAU,YAAY;AAAA,YACtB,SAAS;AAAA,UACb;AAAA,QACJ;AAEA,aAAK,KAAK,SAAS,eAAe,KAAK,SAAS,kBAAkB,KAAK,YAAY;AAC/E,gBAAM,oBAAoB,KAAK,WAC1B,IAAI,SAAO,OAAO,QAAQ,WAAW,MAAM,IAAI,aAAa,IAAI,EAChE,KAAK;AACV,gBAAM,sBAAsB,YAAY,mBAAmB,CAAC,GAAG,KAAK;AAEpE,cAAI,KAAK,UAAU,iBAAiB,MAAM,KAAK,UAAU,kBAAkB,GAAG;AAC1E,oBAAQ,aAAa;AAAA,cACjB,UAAU;AAAA,cACV,SAAS;AAAA,YACb;AAAA,UACJ;AAAA,QACJ;AAEA,YAAI,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AACjC,qBAAW,KAAK;AAAA,YACZ,OAAO;AAAA,YACP,QAAQ;AAAA,YACR;AAAA,UACJ,CAAC;AACD,cAAI,gBAAgB,aAAa;AAC7B,kBAAM,gBAAqB;AAAA,cACvB,UAAU;AAAA,cACV,cAAa,UAAK,aAAL,mBAAe;AAAA,YAChC;AAGA,iBAAK,KAAK,SAAS,eAAe,KAAK,SAAS,kBAAkB,KAAK,cAAc,QAAQ,YAAY;AACrG,4BAAc,aAAa,KAAK,WAC3B,IAAI,SAAO,OAAO,QAAQ,WAAW,MAAM,IAAI,aAAa,IAAI;AAAA,YACzE;AAEA,2BAAe,KAAK;AAAA,cAChB,IAAI,YAAY;AAAA,cAChB,MAAM;AAAA,cACN,SAAS;AAAA,YACb,CAAC;AAAA,UACL;AAAA,QACJ;AAAA,MACJ;AAGA,iBAAW,CAAC,iBAAiB,WAAW,KAAK,cAAc;AACvD,cAAM,qBAAqB,aAAa,eAAe;AACvD,YAAI,EAAE,sBAAsB,gBAAgB;AACxC,qBAAW,KAAK;AAAA,YACZ,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,UAAU;AAAA,cACN,MAAM,YAAY;AAAA,cAClB,UAAU,YAAY;AAAA,cACtB,SAAS,YAAY;AAAA,YACzB;AAAA,UACJ,CAAC;AACD,cAAI,qBAAqB,aAAa;AAClC,2BAAe,KAAK,YAAY,EAAE;AAAA,UACtC;AAAA,QACJ;AAAA,MACJ;AAGA,UAAI,eAAe,SAAS,KAAK,CAAC,QAAQ;AACtC,mBAAW,EAAE,MAAM,IAAI,KAAK,gBAAgB;AACxC,cAAI;AAEA,kBAAM,4BAA4B,EAAE,GAAG,IAAI;AAC3C,iBAAK,IAAI,SAAS,eAAe,IAAI,SAAS,kBAAkB,IAAI,YAAY;AAC5E,wCAA0B,aAAa,IAAI,WACtC,IAAI,SAAO;AACR,sBAAM,UAAU,OAAO,QAAQ,WAAW,MAAM,IAAI,aAAa;AACjE,uBAAO,oBAAoB,IAAI,OAAO,KAAK;AAAA,cAC/C,CAAC,EACA,OAAO,OAAO;AAAA,YACvB;AACA,kBAAM,YAAa,kBAAkB,IAAI,MAAM,yBAAyB;AAAA,UAC5E,SAAS,GAAP;AACE,uBAAW,KAAK;AAAA,cACZ,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,SAAS;AAAA,gBACL,MAAM,IAAI;AAAA,gBACV,UAAU,IAAI,YAAY;AAAA,gBAC1B,SAAS,IAAI,WAAW;AAAA,cAC5B;AAAA,YACJ,CAAC;AAAA,UACL;AAAA,QACJ;AAAA,MACJ;AAEA,UAAI,eAAe,SAAS,KAAK,CAAC,QAAQ;AACtC,mBAAW,EAAE,IAAI,QAAQ,KAAK,gBAAgB;AAC1C,cAAI;AAEA,kBAAM,kBAAkB,EAAE,GAAG,QAAQ;AACrC,gBAAI,gBAAgB,cAAc,MAAM,QAAQ,gBAAgB,UAAU,GAAG;AACzE,8BAAgB,aAAa,gBAAgB,WACxC,IAAI,SAAO,oBAAoB,IAAI,GAAG,KAAK,GAAG,EAC9C,OAAO,OAAO;AAAA,YACvB;AACA,kBAAM,YAAa,IAAI,eAAe;AAAA,UAC1C,SAAS,GAAP;AACE,oBAAQ,KAAK,0BAA0B,OAAO,CAAC;AAAA,UACnD;AAAA,QACJ;AAAA,MACJ;AAEA,UAAI,eAAe,SAAS,KAAK,CAAC,QAAQ;AACtC,mBAAW,MAAM,gBAAgB;AAC7B,cAAI;AACA,kBAAM,YAAa,EAAE;AAAA,UACzB,SAAS,GAAP;AACE,oBAAQ,KAAK,0BAA0B,OAAO,CAAC;AAAA,UACnD;AAAA,QACJ;AAAA,MACJ;AAGA,UAAI,WAAW,WAAW,GAAG;AACzB,gBAAQ,KAAK,EAAE,MAAM,QAAQ,aAAa,GAAG,KAAK,CAAC;AAAA,MACvD,WAAW,eAAe,SAAS,GAAG;AAClC,gBAAQ,KAAK,EAAE,MAAM,iBAAiB,aAAa,GAAG,MAAM,QAAQ,EAAE,YAAY,SAAS,eAAe,OAAO,EAAE,CAAC;AAAA,MACxH,WAAW,eAAe,SAAS,GAAG;AAClC,gBAAQ,KAAK,EAAE,MAAM,iBAAiB,aAAa,GAAG,MAAM,QAAQ,EAAE,YAAY,SAAS,eAAe,OAAO,EAAE,CAAC;AAAA,MACxH,WAAW,eAAe,SAAS,GAAG;AAClC,gBAAQ,KAAK,EAAE,MAAM,iBAAiB,aAAa,GAAG,MAAM,QAAQ,EAAE,YAAY,SAAS,eAAe,OAAO,EAAE,CAAC;AAAA,MACxH,OAAO;AACH,gBAAQ,KAAK,EAAE,MAAM,YAAY,aAAa,GAAG,MAAM,QAAQ,EAAE,WAAW,EAAE,CAAC;AAAA,MACnF;AAAA,IACJ;AAGA,QAAI;AACA,UAAI,WAAW,QAAQ,SAAS,GAAG;AAC/B,cAAM,sCAAsC,KAAK,UAAU,QAAQ,IAAI,QAAM,EAAE,MAAM,EAAE,MAAM,aAAa,EAAE,aAAa,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC;AAAA,MAC3J,OAAO;AACH,cAAM,sCAAsC;AAAA,MAChD;AAAA,IACJ,SAAS,GAAP;AAAA,IAEF;AAEA,WAAO,EAAE,QAAQ;AAAA,EACrB;AACJ;AAkCA,IAAM,SAAS,CAAC,YAAwB,OAAO,MAAmB,aAA6C;AAC3G,QAAM,EAAE,UAAU,UAAU,IAAI;AAGhC,MAAI,EAAE,gBAAgB,SAAS,CAAC,UAAU;AACtC,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAChE;AAEA,QAAM,QAAQ,gBAAgB,OAAO,KAAK,OAAO;AAGjD,QAAM,aAAa,aAAa,IAAI,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;AACvD,MAAI,CAAC,WAAW,OAAO;AACnB,UAAM,IAAI,MAAM,WAAW,KAAK;AAAA,EACpC;AAGA,QAAM,WAAW,IAAI,SAAS;AAC9B,WAAS,OAAO,WAAW,aAAa;AACxC,WAAS,OAAO,QAAQ,MAAM,KAAK;AAGnC,QAAM,WAAW,MAAM,MAAM,GAAG,wBAAwB,aAAa;AAAA,IACjE,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,iBAAiB,UAAU;AAAA,IAC/B;AAAA,IACA,MAAM;AAAA,EACV,CAAC;AAED,QAAM,WAAW,MAAM,SAAS,KAAK;AAErC,MAAK,SAAiB,QAAQ;AAC1B,YAAQ,MAAM,iBAAiB,QAAQ;AACvC,UAAM,IAAI,MAAM,kBAAmB,SAAiB,OAAO,IAAI,CAAC,MAAW,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG;AAAA,EACtG;AAEA,QAAM,iBAAiB;AACvB,SAAO,eAAe,KAAK;AAC/B;AAKA,IAAM,yBAAyB,CAAC,WAAmD;AAAA,EAC/E,IAAI,MAAM;AAAA,EACV,SAAS,MAAM;AAAA,EACf,OAAO,MAAM;AAAA,EACb,aAAa,MAAM;AAAA,EACnB,sBAAsB,MAAM;AAAA,EAC5B,WAAW,MAAM;AAAA,EACjB,WAAW,MAAM;AACrB;AAKA,IAAM,cAAc,CAAC,YAAwB,OACzC,gBACA,aAGA,iBAImC;AA7jDvC;AA8jDI,QAAM,EAAE,UAAU,UAAU,IAAI;AAEhC,QAAM,OAAO,OAAO,iBAAiB,YAAY,EAAE,WAAW,aAAa,IAAK,gBAAgB,CAAC;AACjG,QAAM,YAAY,KAAK,aAAa;AAGpC,QAAM,aAAa,oBAAoB,WAAW;AAClD,MAAI,CAAC,WAAW,OAAO;AACnB,UAAM,IAAI,MAAM,WAAW,SAAS,sBAAsB;AAAA,EAC9D;AAGA,QAAM,wBAAwB,qBAAqB,WAAW;AAG9D,MAAI;AACA,UAAM,cAAY,oBAAe,iBAAf,mBAA6B,WAAU,CAAC;AAC1D,UAAM,SAAS,oBAAI,IAAoB;AACvC,eAAW,UAAU,OAAO,KAAK,SAAS,GAAG;AACzC,aAAO,IAAI,QAAQ,MAAM;AACzB,UAAI;AAAE,eAAO,IAAI,aAAa,MAAM,GAAG,MAAM;AAAA,MAAG,SAAS,GAAP;AAAA,MAAW;AAC7D,UAAI;AAAE,eAAO,IAAI,aAAa,aAAa,MAAM,CAAC,GAAG,MAAM;AAAA,MAAG,SAAS,GAAP;AAAA,MAAW;AAAA,IAC/E;AAEA,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,qBAAqB,GAAG;AACxD,YAAM,SAAS,OAAO,IAAI,CAAC,KAAK;AAChC,UAAI,CAAC;AAAQ;AACb,YAAM,OAAO,UAAU,MAAM;AAC7B,UAAI,CAAC;AAAM;AACX,UAAI,KAAK,SAAS,QAAQ;AACtB,cAAM,aAAa,CAAC,QAAa;AAC7B,cAAI,eAAe,MAAM;AACrB,kBAAM,IAAI,IAAI,YAAY;AAC1B,kBAAM,IAAI,OAAO,IAAI,SAAS,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AACpD,kBAAM,IAAI,OAAO,IAAI,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG;AAC/C,mBAAO,GAAG,KAAK,KAAK;AAAA,UACxB;AACA,cAAI,OAAO,QAAQ,UAAU;AACzB,gBAAI,sBAAsB,KAAK,GAAG;AAAG,qBAAO;AAC5C,kBAAM,SAAS,IAAI,KAAK,GAAG;AAC3B,gBAAI,CAAC,MAAM,OAAO,QAAQ,CAAC,GAAG;AAC1B,oBAAM,IAAI,OAAO,YAAY;AAC7B,oBAAM,IAAI,OAAO,OAAO,SAAS,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AACvD,oBAAM,IAAI,OAAO,OAAO,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG;AAClD,qBAAO,GAAG,KAAK,KAAK;AAAA,YACxB;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AACA,8BAAsB,CAAC,IAAI,WAAW,CAAC;AAAA,MAC3C;AAAA,IACJ;AAAA,EACJ,SAAS,GAAP;AAAA,EAEF;AAOA,MAAI;AACA,UAAM,cAAY,oBAAe,iBAAf,mBAA6B,WAAU,CAAC;AAE1D,UAAM,SAAS,oBAAI,IAAoB;AACvC,eAAW,UAAU,OAAO,KAAK,SAAS,GAAG;AACzC,aAAO,IAAI,QAAQ,MAAM;AACzB,UAAI;AAAE,eAAO,IAAI,aAAa,MAAM,GAAG,MAAM;AAAA,MAAG,SAAS,GAAP;AAAA,MAAW;AAC7D,UAAI;AAAE,eAAO,IAAI,aAAa,aAAa,MAAM,CAAC,GAAG,MAAM;AAAA,MAAG,SAAS,GAAP;AAAA,MAAW;AAAA,IAC/E;AAEA,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,qBAAqB,GAAG;AACxD,YAAM,SAAS,OAAO,IAAI,CAAC,KAAK,OAAO,IAAI,CAAW,KAAK;AAC3D,UAAI,CAAC;AAAQ;AACb,YAAM,OAAO,UAAU,MAAM;AAC7B,UAAI,CAAC;AAAM;AACX,UAAI,KAAK,SAAS,QAAQ;AACtB,cAAM,aAAa,CAAC,QAAa;AAC7B,cAAI,eAAe,MAAM;AACrB,kBAAM,IAAI,IAAI,YAAY;AAC1B,kBAAM,IAAI,OAAO,IAAI,SAAS,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AACpD,kBAAM,IAAI,OAAO,IAAI,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG;AAC/C,mBAAO,GAAG,KAAK,KAAK;AAAA,UACxB;AACA,cAAI,OAAO,QAAQ,UAAU;AACzB,gBAAI,sBAAsB,KAAK,GAAG;AAAG,qBAAO;AAC5C,kBAAM,SAAS,IAAI,KAAK,GAAG;AAC3B,gBAAI,CAAC,MAAM,OAAO,QAAQ,CAAC,GAAG;AAC1B,oBAAM,IAAI,OAAO,YAAY;AAC7B,oBAAM,IAAI,OAAO,OAAO,SAAS,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AACvD,oBAAM,IAAI,OAAO,OAAO,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG;AAClD,qBAAO,GAAG,KAAK,KAAK;AAAA,YACxB;AAAA,UACJ;AACA,iBAAO;AAAA,QACX;AACA,8BAAsB,CAAC,IAAI,WAAW,CAAC;AAAA,MAC3C;AAAA,IACJ;AAAA,EACJ,SAAS,GAAP;AAAA,EAEF;AAGA,QAAM,mBAAmB,CAAC,MAAgB;AACtC,QAAI,CAAC,MAAM,QAAQ,CAAC;AAAG,aAAO;AAC9B,UAAM,MAAa,CAAC;AACpB,eAAW,QAAQ,GAAG;AAClB,UAAI,OAAO,SAAS,UAAU;AAC1B,YAAI,KAAK,aAAa,IAAI,CAAC;AAC3B;AAAA,MACJ;AACA,UAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACtB,YAAI,KAAK,IAAI;AACb;AAAA,MACJ;AACA,YAAM,CAAC,KAAK,KAAK,IAAI;AAErB,UAAI,SAAS,MAAM;AACf,YAAI,KAAK,aAAa,GAAG,CAAC;AAC1B;AAAA,MACJ;AAGA,UAAI;AACJ,UAAI,OAAO,UAAU,UAAU;AAC3B,mBAAW,CAAC,KAAK;AAAA,MACrB,WAAW,MAAM,QAAQ,KAAK,GAAG;AAE7B,YAAI,MAAM,WAAW,KAAK,OAAO,MAAM,CAAC,MAAM,aAAa,MAAM,QAAQ,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,OAAO;AACrG,qBAAW,CAAC,KAAK;AAAA,QACrB,OAAO;AACH,qBAAW;AAAA,QACf;AAAA,MACJ,OAAO;AACH,mBAAW,CAAC,KAAK;AAAA,MACrB;AAEA,UAAI,KAAK,CAAC,aAAa,GAAG,GAAG,iBAAiB,QAAQ,CAAC,CAAC;AAAA,IAC5D;AACA,WAAO;AAAA,EACX;AAGA,QAAM,cAAmB;AAAA,IACrB,SAAS;AAAA,IACT,MAAM,eAAe,aAAa;AAAA,IAClC,cAAc;AAAA,IACd;AAAA,EACJ;AAEA,MAAK,KAAa,SAAS;AACvB,gBAAY,UAAU,iBAAkB,KAAa,OAAO;AAAA,EAChE;AAGA,QAAM,WAAW,MAAM,MAAM,GAAG,wBAAwB,aAAa;AAAA,IACjE,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,gBAAgB;AAAA,MAChB,iBAAiB,UAAU;AAAA,IAC/B;AAAA,IACA,MAAM,KAAK,UAAU,WAAW;AAAA,EACpC,CAAC;AAED,QAAM,WAAW,MAAM,SAAS,KAAK;AAErC,MAAK,SAAiB,QAAQ;AAC1B,YAAQ,MAAM,uBAAuB,QAAQ;AAC7C,UAAM,gBAAiB,SAAiB,OACnC,IAAI,CAAC,MAAW,GAAG,EAAE,UAAU,EAAE,SAAS,EAC1C,KAAK,IAAI;AACd,UAAM,IAAI,MAAM,2BAA2B,eAAe;AAAA,EAC9D;AAEA,QAAM,iBAAiB;AACvB,QAAM,SAAQ,oBAAe,SAAf,mBAAqB;AAGnC,MAAI,CAAC,OAAO;AACR,UAAM,IAAI;AAAA,MACN,yCAAyC,eAAe,aAAa;AAAA,IAGzE;AAAA,EACJ;AAGA,MAAK,KAAa,SAAS;AACvB,UAAM,aAAkC,EAAE,IAAI,MAAM,GAAG;AACvD,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC9C,UAAI,QAAQ,MAAM;AACd,mBAAW,aAAa,GAAG,CAAC,IAAI;AAAA,MACpC;AAAA,IACJ;AACA,WAAO,EAAE,MAAM,WAAW;AAAA,EAC9B;AAEA,SAAO,uBAAuB,KAAK;AACvC;AAKA,IAAM,cAAc,CAAC,YAAwB,OACzC,gBACA,SACA,aAGA,iBAImC;AApxDvC;AAqxDI,QAAM,EAAE,UAAU,UAAU,IAAI;AAGhC,MAAI,CAAC,YAAY,OAAO,GAAG;AACvB,UAAM,IAAI,MAAM,4BAA4B,gCAAgC;AAAA,EAChF;AAGA,QAAM,aAAa,oBAAoB,WAAW;AAClD,MAAI,CAAC,WAAW,OAAO;AACnB,UAAM,IAAI,MAAM,WAAW,SAAS,sBAAsB;AAAA,EAC9D;AAGA,QAAM,wBAAwB,qBAAqB,WAAW;AAG9D,QAAM,cAAmB;AAAA,IACrB,SAAS;AAAA,IACT,UAAU;AAAA,IACV,cAAc;AAAA,EAClB;AAGA,QAAM,OAAO,OAAO,iBAAiB,YAAY,EAAE,WAAW,aAAa,IAAK,gBAAgB,CAAC;AAGjG,MAAK,KAAa,cAAc,QAAW;AACvC,gBAAY,YAAa,KAAa;AAAA,EAC1C;AAGA,QAAM,mBAAmB,CAAC,MAAgB;AACtC,QAAI,CAAC,MAAM,QAAQ,CAAC;AAAG,aAAO;AAC9B,UAAM,MAAa,CAAC;AACpB,eAAW,QAAQ,GAAG;AAClB,UAAI,OAAO,SAAS,UAAU;AAC1B,YAAI,KAAK,aAAa,IAAI,CAAC;AAC3B;AAAA,MACJ;AACA,UAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACtB,YAAI,KAAK,IAAI;AACb;AAAA,MACJ;AACA,YAAM,CAAC,KAAK,KAAK,IAAI;AACrB,UAAI,SAAS,MAAM;AACf,YAAI,KAAK,aAAa,GAAG,CAAC;AAC1B;AAAA,MACJ;AACA,UAAI;AACJ,UAAI,OAAO,UAAU,UAAU;AAC3B,mBAAW,CAAC,KAAK;AAAA,MACrB,WAAW,MAAM,QAAQ,KAAK,GAAG;AAC7B,YAAI,MAAM,WAAW,KAAK,OAAO,MAAM,CAAC,MAAM,aAAa,MAAM,QAAQ,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,OAAO;AACrG,qBAAW,CAAC,KAAK;AAAA,QACrB,OAAO;AACH,qBAAW;AAAA,QACf;AAAA,MACJ,OAAO;AACH,mBAAW,CAAC,KAAK;AAAA,MACrB;AACA,UAAI,KAAK,CAAC,aAAa,GAAG,GAAG,iBAAiB,QAAQ,CAAC,CAAC;AAAA,IAC5D;AACA,WAAO;AAAA,EACX;AAEA,MAAK,KAAa,SAAS;AACvB,gBAAY,UAAU,iBAAkB,KAAa,OAAO;AAAA,EAChE;AAEA,QAAM,iCAAiC,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;AAG3E,QAAM,WAAW,MAAM,MAAM,GAAG,wBAAwB,aAAa;AAAA,IACjE,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,gBAAgB;AAAA,MAChB,iBAAiB,UAAU;AAAA,IAC/B;AAAA,IACA,MAAM,KAAK,UAAU,WAAW;AAAA,EACpC,CAAC;AAED,QAAM,WAAW,MAAM,SAAS,KAAK;AAErC,MAAK,SAAiB,QAAQ;AAC1B,YAAQ,MAAM,uBAAuB,QAAQ;AAC7C,UAAM,gBAAiB,SAAiB,OACnC,IAAI,CAAC,MAAW,GAAG,EAAE,UAAU,EAAE,SAAS,EAC1C,KAAK,IAAI;AACd,UAAM,IAAI,MAAM,2BAA2B,eAAe;AAAA,EAC9D;AAEA,QAAM,iBAAiB;AACvB,QAAM,SAAQ,oBAAe,SAAf,mBAAqB;AAGnC,MAAI,CAAC,OAAO;AACR,UAAM,IAAI;AAAA,MACN,qCAAqC;AAAA,IAGzC;AAAA,EACJ;AAEA,SAAO,uBAAuB,KAAK;AACvC;AAKA,IAAM,oBAAoB,CAAC,YAAwB,OAAO,kBAAyC;AAC/F,QAAM,EAAE,UAAU,UAAU,IAAI;AAGhC,MAAI,CAAC,YAAY,aAAa,GAAG;AAC7B,UAAM,IAAI,MAAM,mCAAmC,sCAAsC;AAAA,EAC7F;AAEA,QAAM,cAAc;AAAA,IAChB,SAAS;AAAA,IACT,iBAAiB;AAAA,EACrB;AAEA,QAAM,WAAW,MAAM,MAAM,GAAG,wBAAwB,aAAa;AAAA,IACjE,QAAQ;AAAA,IACR,SAAS;AAAA,MACL,gBAAgB;AAAA,MAChB,iBAAiB,UAAU;AAAA,IAC/B;AAAA,IACA,MAAM,KAAK,UAAU,WAAW;AAAA,EACpC,CAAC;AAED,QAAM,WAAW,MAAM,SAAS,KAAK;AAErC,MAAK,SAAiB,QAAQ;AAC1B,YAAQ,MAAM,8BAA8B,QAAQ;AACpD,UAAM,gBAAiB,SAAiB,OACnC,IAAI,CAAC,MAAW,GAAG,EAAE,UAAU,EAAE,SAAS,EAC1C,KAAK,IAAI;AACd,UAAM,IAAI,MAAM,kCAAkC,eAAe;AAAA,EACrE;AACJ;AAEO,IAAM,eAAe,CAAC,WAAuB;AAChD,QAAM,EAAE,UAAU,UAAU,IAAI,WAAW,MAAM,MAAM;AACvD,QAAM,UAAU,YAAY,EAAE,UAAU,UAAU,CAAC;AAGnD,QAAM,0BAA0B,OAAO,OAA8B;AACjE,UAAM,UAAU,8BAA8B,EAAE;AAChD,UAAM,qCAAqC,KAAK,UAAU,OAAO,CAAC;AAClE,UAAM,OAAO,MAAM,MAAM,GAAG,wBAAwB,aAAa;AAAA,MAC7D,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,QAChB,iBAAiB,UAAU;AAAA,MAC/B;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,IAChC,CAAC;AACD,UAAM,OAAO,MAAM,KAAK,KAAK,EAAE,MAAM,MAAM,IAAI;AAC/C,UAAM,sCAAsC,KAAK,UAAU,IAAI,CAAC;AAChE,QAAI,CAAC,QAAS,KAAa,QAAQ;AAC/B,YAAM,IAAI,MAAM,iCAAiC,GAAG,SAAS,KAAK,UAAU,IAAI,GAAG;AAAA,IACvF;AACA,WAAO;AAAA,EACX;AAEA,QAAM,oBAAoB,OAAO,SAAiB,WAAmB,aAA8B;AAC/F,UAAM,UAAU,wBAAwB,SAAS,WAAW,QAAQ;AACpE,UAAM,+BAA+B,KAAK,UAAU,OAAO,CAAC;AAC5D,UAAM,OAAO,MAAM,MAAM,GAAG,wBAAwB,aAAa;AAAA,MAC7D,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,QAChB,iBAAiB,UAAU;AAAA,MAC/B;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,IAChC,CAAC;AACD,UAAM,OAAO,MAAM,KAAK,KAAK,EAAE,MAAM,MAAM,IAAI;AAC/C,UAAM,mCAAmC,WAAW,KAAK,UAAU,IAAI,CAAC;AACxE,QAAI,CAAC,QAAS,KAAa,QAAQ;AAC/B,YAAM,IAAI,MAAM,0BAA0B,gBAAgB,YAAY,KAAK,UAAU,IAAI,GAAG;AAAA,IAChG;AACA,WAAO;AAAA,EACX;AAEA,QAAM,oBAAoB,OAAO,SAAiB,YAAiC;AAC/E,UAAM,UAAU,wBAAwB,SAAS,OAAO;AACxD,UAAM,+BAA+B,KAAK,UAAU,OAAO,CAAC;AAC5D,UAAM,OAAO,MAAM,MAAM,GAAG,wBAAwB,aAAa;AAAA,MAC7D,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,QAChB,iBAAiB,UAAU;AAAA,MAC/B;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,IAChC,CAAC;AACD,UAAM,OAAO,MAAM,KAAK,KAAK,EAAE,MAAM,MAAM,IAAI;AAC/C,UAAM,mCAAmC,SAAS,KAAK,UAAU,IAAI,CAAC;AACtE,QAAI,CAAC,QAAS,KAAa,QAAQ;AAC/B,YAAM,IAAI,MAAM,0BAA0B,YAAY,KAAK,UAAU,IAAI,GAAG;AAAA,IAChF;AACA,WAAO;AAAA,EACX;AAEA,QAAM,oBAAoB,OAAO,YAAoB;AACjD,UAAM,UAAU,EAAE,SAAS,gBAAgB,UAAU,QAAQ;AAC7D,UAAM,OAAO,MAAM,MAAM,GAAG,wBAAwB,aAAa;AAAA,MAC7D,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,QAChB,iBAAiB,UAAU;AAAA,MAC/B;AAAA,MACA,MAAM,KAAK,UAAU,OAAO;AAAA,IAChC,CAAC;AACD,UAAM,OAAO,MAAM,KAAK,KAAK,EAAE,MAAM,MAAM,IAAI;AAC/C,QAAI,CAAC,QAAS,KAAa,QAAQ;AAC/B,YAAM,IAAI,MAAM,0BAA0B,YAAY,KAAK,UAAU,IAAI,GAAG;AAAA,IAChF;AACA,WAAO;AAAA,EACX;AAGA,QAAM,sBAAsB,OACxB,cACA,UAA4D,CAAC,MAC5D;AACD,UAAM,WAAW;AAAA,MACb,mBAAmB;AAAA,MACnB,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa;AAAA,IACjB;AAGA,UAAM,SAAS,EAAE,GAAG,UAAU,GAAG,QAAQ;AAEzC,WAAO,eAAe,OAAO,EAAE,cAAqB,MAAa;AAAA,EACrE;AAEA,SAAO;AAAA,IACH,UAAU,SAAS,OAAO;AAAA,IAC1B,YAAY,WAAW,OAAO;AAAA;AAAA,IAE9B,SAAS,QAAQ,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQxB,qBAAqB,OAAO,SAA+C;AAjhEnF;AAkhEY,UAAI;AACA,cAAM,cAAc,MAAM,QAAQ,OAAO,EAAE;AAC3C,cAAM,UAAU,YAAY,KAAK,iBAAiB,YAAY,KAAK,cAAc,CAAC;AAClF,YAAI,CAAC;AAAS,iBAAO;AACrB,cAAM,WAAW,QAAQ,QAAQ,QAAQ;AAEzC,cAAM,OAAO,MAAM,QAAQ,EAAE,SAAS,eAAe,MAAM,UAAU,OAAO,GAAG,UAAU,KAAK,CAAQ,EAAE,MAAM,CAAC,SAAc,EAAE,OAAO,IAAI,EAAE;AAC5I,YAAK,6BAAc,OAAO;AAEtB,gBAAO,KAAa;AAAA,QACxB;AAEA,YAAK,KAAa,YAAW,UAAa,SAAb,mBAAmB,SAAQ;AACpD,gBAAM,SAAU,KAAa,YAAW,UAAa,SAAb,mBAAmB,WAAU,CAAC;AACtE,iBAAO,CAAC,OAAO,KAAK,CAAC,MAAW,EAAE,UAAU,eAAe;AAAA,QAC/D;AACA,eAAO;AAAA,MACX,SAAS,GAAP;AAEE,YAAI,KAAK,OAAO,MAAM,YAAY,EAAE,QAAQ;AACxC,iBAAO,CAAC,EAAE,OAAO,KAAK,CAAC,OAAY,GAAG,UAAU,eAAe;AAAA,QACnE;AACA,cAAM;AAAA,MACV;AAAA,IACJ;AAAA,IACA,MAAM,KAAK,OAAO;AAAA,IAClB,gBAAgB;AAAA,IAChB,QAAQ,OAAO,EAAE,UAAU,UAAU,CAAC;AAAA,IACtC,aAAa,YAAY,EAAE,UAAU,UAAU,CAAC;AAAA,IAChD,aAAa,YAAY,EAAE,UAAU,UAAU,CAAC;AAAA,IAChD,mBAAmB,kBAAkB,EAAE,UAAU,UAAU,CAAC;AAAA,EAChE;AACJ;AAMO,IAAM,aAAa,CAAC,UAA2B;AAClD,MAAI,OAAO,UAAU;AAAU,WAAO;AACtC,MAAI,SAAS,OAAO,UAAU,YAAY,QAAS;AAAe,WAAQ,MAAc;AACxF,SAAO;AACX;AAKO,IAAM,kBAAkB,CAA4C,UAA+B;AACtG,SAAO,CAAC,EAAE,SAAS,OAAO,UAAU,YAAY,QAAS;AAC7D;","names":["_a","_b","_a"]}