db4ai 0.3.2 → 0.3.3
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 +5 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -296,6 +296,9 @@ function parseStateConfig(config) {
|
|
|
296
296
|
};
|
|
297
297
|
}
|
|
298
298
|
function extractCountFromDescription(description) {
|
|
299
|
+
if (typeof description !== "string") {
|
|
300
|
+
return void 0;
|
|
301
|
+
}
|
|
299
302
|
const rangeMatch = description.match(/\b(\d+)-(\d+)\b/);
|
|
300
303
|
if (rangeMatch) {
|
|
301
304
|
return { min: parseInt(rangeMatch[1], 10), max: parseInt(rangeMatch[2], 10) };
|
|
@@ -320,7 +323,8 @@ function parseFieldType(value) {
|
|
|
320
323
|
};
|
|
321
324
|
}
|
|
322
325
|
if (Array.isArray(value)) {
|
|
323
|
-
const
|
|
326
|
+
const rawDesc = value[0];
|
|
327
|
+
const desc = typeof rawDesc === "string" ? rawDesc : "";
|
|
324
328
|
const count = extractCountFromDescription(desc);
|
|
325
329
|
const backRefMatch = desc.match(/^<-(\w+)$/);
|
|
326
330
|
if (backRefMatch) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts"],"sourcesContent":["import type { ComponentType } from 'react'\n// Import and re-export shared handler types\nexport {\n SerializedFunction,\n serializeFunction,\n type EntityHandlerType,\n type SchemaHandlerType,\n type LifecycleHandlerType,\n type StateHandlerType,\n type HandlerExecutionResult,\n type HandlerLogEntry,\n} from './handlers'\nimport { serializeFunction, type SerializedFunction } from './handlers'\n\n// Type declaration for Node.js process global (may not exist in browser)\ndeclare const process: { env?: Record<string, string | undefined> } | undefined\n\n// ============================================================================\n// Custom Error Classes\n// ============================================================================\n\n/**\n * Error codes for schema validation errors.\n */\nexport type SchemaValidationErrorCode = 'MISSING_CONTEXT' | 'MISSING_NAMESPACE' | 'INVALID_FIELD_TYPE'\n\n/**\n * Error thrown when schema validation fails.\n *\n * @example\n * try {\n * DB({ User: { name: 'User name' } }) // Missing $id or $context\n * } catch (error) {\n * if (error instanceof SchemaValidationError) {\n * console.log(error.code) // 'MISSING_CONTEXT'\n * }\n * }\n */\nexport class SchemaValidationError extends Error {\n code: SchemaValidationErrorCode\n\n constructor(code: SchemaValidationErrorCode, message: string) {\n super(message)\n this.name = 'SchemaValidationError'\n this.code = code\n }\n}\n\n/**\n * Error codes for API errors.\n */\nexport type APIErrorCode = 'REGISTRATION_FAILED' | 'GENERATION_FAILED' | 'REFERENCE_RESOLUTION_FAILED'\n\n/**\n * Error thrown when API operations fail.\n *\n * @example\n * try {\n * await db.User('john-doe')\n * } catch (error) {\n * if (error instanceof APIError) {\n * console.log(error.code) // 'GENERATION_FAILED'\n * console.log(error.statusCode) // 404\n * }\n * }\n */\nexport class APIError extends Error {\n code: APIErrorCode\n statusCode?: number\n\n constructor(code: APIErrorCode, message: string, statusCode?: number) {\n super(message)\n this.name = 'APIError'\n this.code = code\n this.statusCode = statusCode\n }\n}\n\nexport type Components = {\n App: ComponentType\n List: ComponentType\n ListItem: ComponentType\n View: ComponentType\n Edit: ComponentType\n Chat: ComponentType\n}\n\nexport function UI(components: Components) {\n return components\n}\n\n/**\n * Parse namespace from a $id URL.\n *\n * @example\n * parseNamespaceFromId('https://db.sb/sales') // 'sales' (from path)\n * parseNamespaceFromId('https://db4.ai/startups') // 'startups' (from path)\n * parseNamespaceFromId('https://db.sb/org/team') // 'org/team' (from path)\n * parseNamespaceFromId('https://startup.db.sb') // 'startup' (from subdomain)\n * parseNamespaceFromId('https://startups.db.sb') // 'startups' (from subdomain)\n * parseNamespaceFromId('https://db.sb/') // null\n * parseNamespaceFromId('invalid') // null\n */\nexport function parseNamespaceFromId(id: string): string | null {\n try {\n const url = new URL(id)\n // Remove leading slash and trailing slash\n const path = url.pathname.replace(/^\\//, '').replace(/\\/$/, '')\n if (path) return path\n\n // No path - try to extract namespace from subdomain\n // e.g., 'startup.db.sb' -> 'startup', 'startups.db4.ai' -> 'startups'\n const hostParts = url.hostname.split('.')\n // Need at least 3 parts for subdomain (e.g., 'startup.db.sb' or 'startups.db4.ai')\n if (hostParts.length >= 3) {\n const subdomain = hostParts[0]\n // Exclude common non-namespace subdomains\n if (subdomain && subdomain !== 'www' && subdomain !== 'api') {\n return subdomain\n }\n }\n return null\n } catch {\n return null\n }\n}\n\n// Schema Types\n\n/**\n * Computed field - a function that derives a value from the entity.\n */\nexport type ComputedFieldFn<E = any, R = any> = (entity: E, $?: any) => R\n\n/**\n * Nested object field value - used for complex structures like StoryBrand.hero.wants\n */\nexport interface NestedFieldValue {\n [key: string]: string | string[] | boolean | NestedFieldValue | ComputedFieldFn\n}\n\n/**\n * Field value in an entity definition.\n * - `string` - Prompt for AI generation or JSONPath ($.field)\n * - `string[]` - Array generation\n * - `NestedFieldValue` - Nested object structure\n * - `boolean` - Relationship marker (e.g., '->Entity[]': true)\n * - `Function` - Computed field\n */\nexport type FieldValue =\n | string\n | string[]\n | boolean\n | NestedFieldValue\n | ComputedFieldFn\n\n/**\n * Entity lifecycle handler.\n */\nexport type EntityHandler<E = any> = (entity: E, $: any) => void | Promise<void>\n\n/**\n * Entity update handler with previous state.\n */\nexport type EntityUpdateHandler<E = any> = (entity: E, previous: E, $: any) => void | Promise<void>\n\n/**\n * Schema lifecycle handler.\n */\nexport type SchemaHandler = ($: any) => void | Promise<void>\n\n/**\n * Schema error handler.\n */\nexport type SchemaErrorHandler = (error: Error, $: any) => void | Promise<void>\n\n/**\n * Input state machine configuration for entity definitions.\n * This is the raw format before parsing - use RawStateConfig from state machine types.\n */\nexport type InputStateConfig = {\n $initial: string\n} & Record<string, unknown>\n\n/**\n * Evaluation definition stub.\n */\nexport type EvalDefinition = Record<string, unknown>\n\n/**\n * Schema experiment definition stub.\n */\nexport type SchemaExperiment = Record<string, unknown>\n\n/**\n * Schema analytics configuration stub.\n */\nexport type SchemaAnalytics = Record<string, unknown>\n\n// Schema metadata fields (prefixed with $)\nexport interface SchemaMetadata {\n /** Unique identifier/URL for this schema */\n $id?: string\n /** Shared namespace for composing multiple DB() schemas */\n $context?: string\n /** Schema version */\n $version?: string\n /** Schema-level functions */\n $fn?: Record<string, (...args: any[]) => any>\n /** Handler called after all seeds complete */\n $seeded?: SchemaHandler\n /** Handler called when database is fully initialized */\n $ready?: SchemaHandler\n /** Global error handler */\n $error?: SchemaErrorHandler\n /** Reusable evaluation definitions */\n $eval?: Record<string, EvalDefinition>\n /** Schema-level experiments */\n $experiment?: Record<string, SchemaExperiment>\n /** Analytics provider configuration */\n $analytics?: SchemaAnalytics\n /** Event handlers (deprecated) */\n $on?: Record<string, (...args: any[]) => void | Promise<void>>\n}\n\n/**\n * Entity-level directives that can appear in type definitions.\n */\nexport interface EntityDirectives {\n /** Seed data source URL */\n $seed?: string\n /** JSONPath or transform for entity ID from seed data (e.g., '$.slug', 'PascalCase($.name)') */\n $id?: string\n /** Entity type discriminator */\n $type?: string\n /** Handler called when entity is created */\n $created?: EntityHandler\n /** Handler called when entity is updated */\n $updated?: EntityUpdateHandler\n /** Handler called when entity is deleted */\n $deleted?: EntityHandler\n /** State machine configuration */\n $state?: InputStateConfig\n /** Inline experiment */\n $experiment?: Record<string, unknown>\n /** Inline eval */\n $eval?: EvalDefinition | EvalDefinition[]\n /** Image generation config */\n $image?: Record<string, unknown>\n /** Speech generation config */\n $speech?: Record<string, unknown>\n /** Diagram generation config */\n $diagram?: Record<string, unknown>\n /** Code generation config */\n $code?: Record<string, unknown>\n}\n\n/**\n * Type definition: entity directives + field definitions.\n * Allows any string key for fields and relationship markers.\n */\nexport type TypeDefinition = EntityDirectives & Record<string, FieldValue | undefined>\n\n/**\n * Schema: metadata + type definitions.\n * Allows entity type definitions with all directives and field types.\n */\nexport type SchemaDefinition = SchemaMetadata & Record<string, TypeDefinition | string | undefined>\n\nexport interface StringField {\n type: 'string'\n description: string\n optional?: boolean\n}\n\n// ============================================================================\n// Reference Operator Constants\n// ============================================================================\n\n/**\n * Reference operators used in the schema DSL.\n *\n * - `->` (FORWARD_EXACT): Forward exact reference - resolves by ID\n * - `~>` (FORWARD_FUZZY): Forward fuzzy reference - resolves by semantic matching\n * - `<-` (BACKWARD_EXACT): Backward exact reference - reverse lookup by ID\n * - `<~` (BACKWARD_FUZZY): Backward fuzzy reference - reverse lookup by semantic matching\n *\n * @example\n * // Forward references (existing)\n * { author: '->User' } // Exact forward ref\n * { avatar: '~>Image' } // Fuzzy forward ref\n *\n * // Backward references (new)\n * { posts: '<-Post' } // Find Posts that reference this entity\n * { related: '<~Article' } // Find semantically related Articles\n */\nexport const OPERATORS = {\n /** Forward exact reference: `->Type` - resolves to exact ID match */\n FORWARD_EXACT: '->',\n /** Forward fuzzy reference: `~>Type` - resolves by semantic similarity */\n FORWARD_FUZZY: '~>',\n /** Backward exact reference: `<-Type` - finds entities referencing this one */\n BACKWARD_EXACT: '<-',\n /** Backward fuzzy reference: `<~Type` - finds semantically related entities */\n BACKWARD_FUZZY: '<~',\n} as const\n\n/** Type for all valid reference operators */\nexport type ReferenceOperator = (typeof OPERATORS)[keyof typeof OPERATORS]\n\n/** Parsed operator information returned by parseOperator */\nexport type ParsedOperator =\n | { direction: 'forward'; fuzzy: boolean }\n | { direction: 'backward'; mode: 'exact' | 'fuzzy' }\n\n/**\n * Parse a reference operator prefix into its direction and mode/fuzzy properties.\n *\n * This helper function converts the two-character operator prefix into structured\n * properties for building ReferenceField objects.\n *\n * @param prefix - The operator prefix (`->`, `~>`, `<-`, or `<~`)\n * @returns Parsed operator with direction and either fuzzy (forward) or mode (backward)\n *\n * @example\n * parseOperator('->') // { direction: 'forward', fuzzy: false }\n * parseOperator('~>') // { direction: 'forward', fuzzy: true }\n * parseOperator('<-') // { direction: 'backward', mode: 'exact' }\n * parseOperator('<~') // { direction: 'backward', mode: 'fuzzy' }\n */\nexport function parseOperator(prefix: string): ParsedOperator {\n switch (prefix) {\n case OPERATORS.FORWARD_EXACT:\n return { direction: 'forward', fuzzy: false }\n case OPERATORS.FORWARD_FUZZY:\n return { direction: 'forward', fuzzy: true }\n case OPERATORS.BACKWARD_EXACT:\n return { direction: 'backward', mode: 'exact' }\n case OPERATORS.BACKWARD_FUZZY:\n return { direction: 'backward', mode: 'fuzzy' }\n default:\n // Default to forward exact for unknown operators\n return { direction: 'forward', fuzzy: false }\n }\n}\n\n/**\n * Parsed reference field from the schema DSL.\n *\n * The `direction` and `mode` properties are used for backward references (`<-`, `<~`),\n * while the `fuzzy` property is used for forward references (`->`, `~>`) for\n * backward compatibility.\n *\n * ## Forward References (direction omitted)\n * - `->Type` produces `{ fuzzy: false, ... }` - exact ID lookup\n * - `~>Type` produces `{ fuzzy: true, ... }` - semantic matching\n *\n * ## Backward References\n * - `<-Type` produces `{ direction: 'backward', mode: 'exact', ... }` - find by ID\n * - `<~Type` produces `{ direction: 'backward', mode: 'fuzzy', ... }` - find by semantics\n *\n * @example\n * // Forward exact reference\n * parseFieldType('->User')\n * // { type: 'reference', ref: 'User', isArray: false, optional: false, fuzzy: false }\n *\n * // Backward fuzzy array reference\n * parseFieldType('<~Post[]')\n * // { type: 'reference', ref: 'Post', isArray: true, optional: false, direction: 'backward', mode: 'fuzzy' }\n */\nexport interface ReferenceField {\n type: 'reference'\n /** Single reference target type (mutually exclusive with `refs`) */\n ref?: string\n /** Union type reference targets (mutually exclusive with `ref`) */\n refs?: string[]\n /** Whether this is an array of references (e.g., `->Type[]`) */\n isArray: boolean\n /** Whether the reference is optional (e.g., `->Type?`) */\n optional?: boolean\n /** For forward references: true if fuzzy (`~>`), false if exact (`->`) */\n fuzzy?: boolean\n /** For backward references: always 'backward' when present */\n direction?: 'forward' | 'backward'\n /** For backward references: 'exact' (`<-`) or 'fuzzy' (`<~`) */\n mode?: 'exact' | 'fuzzy'\n}\n\nexport interface ArrayField {\n type: 'array'\n items: { type: 'string' }\n description: string\n optional?: boolean\n refs?: string[] // Inline references: ['... ->Type']\n backRef?: string // Back references: ['<-Type']\n count?: number | { min: number; max: number } // Extracted count from description\n}\n\nexport interface ObjectField {\n type: 'object'\n properties: Record<string, StringField>\n optional?: boolean\n}\n\nexport interface EmbeddedField {\n type: 'embedded'\n embeddedType: string\n isArray?: boolean\n optional?: boolean\n}\n\nexport interface JSONPathField {\n type: 'jsonpath'\n path: string\n transform?: string\n}\n\nexport interface JSONPathEmbeddedField {\n type: 'jsonpath-embedded'\n path: string\n embeddedType: string\n isArray: boolean\n optional?: boolean\n}\n\nexport interface ComputedField {\n type: 'computed'\n source: string\n}\n\nexport interface PromptField {\n type: 'prompt'\n prompt: string\n}\n\nexport type ParsedField = StringField | ReferenceField | ArrayField | ObjectField | EmbeddedField | JSONPathField | JSONPathEmbeddedField | ComputedField | PromptField\n\nexport interface TypeReference {\n field: string\n ref: string\n refs?: string[]\n isArray: boolean\n optional?: boolean\n fuzzy?: boolean\n backRef?: boolean // True if this is a back reference (read-only, not generated)\n}\n\nexport interface SeedConfig {\n url: string\n format?: 'tsv' | 'csv' | 'json'\n idField?: string // Which column to use as the ID (defaults to first column)\n id?: string // JSONPath to use as the ID (e.g., '$.slug')\n idTransform?: string // Transform function to apply to ID (e.g., 'PascalCase')\n next?: string // JSONPath to next page URL for pagination\n data?: string // JSONPath to data array in response\n}\n\n/**\n * Parse $id field which can be:\n * - Simple JSONPath: $.slug\n * - Transform with path: PascalCase($.example)\n * - Column name (legacy): slug\n *\n * @example\n * parseIdConfig('$.slug') // { path: '$.slug' }\n * parseIdConfig('PascalCase($.example)') // { path: '$.example', transform: 'PascalCase' }\n * parseIdConfig('kebab-case($.title)') // { path: '$.title', transform: 'kebab-case' }\n * parseIdConfig('slug') // { path: 'slug' }\n */\nexport function parseIdConfig(idField: string): { path: string; transform?: string } {\n // Check for transform pattern: Transform($.path)\n // Supports transforms like PascalCase, camelCase, kebab-case, UPPERCASE, lowercase\n const transformMatch = idField.match(/^([A-Za-z][A-Za-z0-9-]*)\\((\\$\\..+)\\)$/)\n if (transformMatch) {\n const [, transform, path] = transformMatch\n return { path, transform }\n }\n // Plain JSONPath or column name\n return { path: idField }\n}\n\n// ============================================================================\n// JSONPath Validation\n// ============================================================================\n\n/**\n * Validates that a string is a valid JSONPath expression.\n *\n * A valid JSONPath must:\n * - Start with `$.` (root reference)\n * - Contain valid property names, array indices, or bracket notation\n *\n * Supported patterns:\n * - `$.field` - Simple property access\n * - `$.nested.field` - Nested property access\n * - `$.array[0]` - Array index access\n * - `$.array[*]` - Array wildcard\n * - `$.items[?(@.active)]` - Filter expressions\n *\n * @example\n * isValidJSONPath('$.title') // true\n * isValidJSONPath('$.data.items[0]') // true\n * isValidJSONPath('$.tags[*]') // true\n * isValidJSONPath('title') // false (missing $.)\n * isValidJSONPath('$50 price') // false (not a valid path)\n */\nexport function isValidJSONPath(path: string): boolean {\n // Must start with $.\n if (!path.startsWith('$.')) {\n return false\n }\n\n // Basic validation regex for common JSONPath patterns:\n // - Property access: .propertyName or ['property name']\n // - Array access: [0], [*], [?(@.condition)]\n // - Nested paths: $.a.b.c\n const jsonPathPattern = /^\\$\\.[\\w\\[\\].*@?()'\"=!<>|&\\s-]+$/\n\n return jsonPathPattern.test(path)\n}\n\n// ============================================================================\n// Type Guards for ParsedField\n// ============================================================================\n\n/**\n * Type guard to check if a ParsedField is a JSONPathField.\n *\n * @example\n * const field = parseFieldType('$.title')\n * if (isJSONPathField(field)) {\n * console.log(field.path) // TypeScript knows field.path exists\n * }\n */\nexport function isJSONPathField(field: ParsedField): field is JSONPathField {\n return field.type === 'jsonpath'\n}\n\n/**\n * Type guard to check if a ParsedField is a JSONPathEmbeddedField.\n *\n * @example\n * const field = parseFieldType('$.author ->Author')\n * if (isJSONPathEmbeddedField(field)) {\n * console.log(field.embeddedType) // TypeScript knows field.embeddedType exists\n * }\n */\nexport function isJSONPathEmbeddedField(field: ParsedField): field is JSONPathEmbeddedField {\n return field.type === 'jsonpath-embedded'\n}\n\n/**\n * Type guard to check if a ParsedField is a PromptField.\n *\n * @example\n * const field = parsed.types.Task.fields.description\n * if (isPromptField(field)) {\n * console.log(field.prompt) // TypeScript knows field.prompt exists\n * }\n */\nexport function isPromptField(field: ParsedField): field is PromptField {\n return field.type === 'prompt'\n}\n\n/**\n * Type guard to check if a ParsedField is a StringField.\n */\nexport function isStringField(field: ParsedField): field is StringField {\n return field.type === 'string'\n}\n\n// ============================================================================\n// Function Serialization Types\n// ============================================================================\n// NOTE: SerializedFunction, serializeFunction, and related handler types are now\n// imported from ./handlers and re-exported at the top of this file.\n\n// ============================================================================\n// Data Source Configuration Types\n// ============================================================================\n\nexport interface OAuthConfig {\n tokenUrl: string\n clientId: string\n clientSecret: string\n}\n\nexport interface AsyncConfig {\n start: string\n result: string\n}\n\nexport interface SourceConfig {\n $api: string\n $apiKey?: string\n $bearer?: string\n $oauth?: OAuthConfig\n $data?: string\n $async?: AsyncConfig\n}\n\nexport type SourceInput = Record<string, 'string' | 'string?'>\n\n// ============================================================================\n// Generative Format Configuration Types\n// ============================================================================\n\nexport interface ImageConfig {\n aspectRatio?: string\n style?: string\n}\n\nexport interface SpeechConfig {\n voice?: string\n speed?: number\n format?: string\n}\n\nexport interface DiagramConfig {\n type?: string\n direction?: string\n format?: string\n}\n\nexport interface ConventionsConfig {\n nodes?: string\n edges?: string\n events?: string\n}\n\nexport interface CodeConfig {\n language?: string\n runtime?: string\n framework?: string\n}\n\n// ============================================================================\n// State Machine Types\n// ============================================================================\n\n/** Transition configuration - simple string or complex object */\nexport interface TransitionConfig {\n to: string | null\n if?: SerializedFunction\n do?: SerializedFunction\n}\n\n/** State configuration with transitions */\nexport interface StateConfig {\n transitions: Record<string, TransitionConfig>\n $entry?: SerializedFunction\n $exit?: SerializedFunction\n}\n\n/** Parsed state machine configuration */\nexport interface ParsedStateConfig {\n $initial: string\n states: Record<string, StateConfig>\n}\n\n/** Raw state config - input format before parsing */\nexport type RawStateConfig = {\n $initial: string\n} & Record<string, unknown>\n\n/** State validation error */\nexport interface StateValidationError {\n code: string\n message: string\n state?: string\n event?: string\n transition?: string\n}\n\n/** State validation result */\nexport interface StateValidationResult {\n valid: boolean\n errors: StateValidationError[]\n}\n\n/**\n * Validate a raw state machine configuration.\n * Checks for: valid $initial, reachable states, no orphan states, valid transitions.\n */\nexport function validateStateConfig(config: RawStateConfig): StateValidationResult {\n const errors: StateValidationError[] = []\n\n // Extract state names (exclude $ prefixed keys like $initial, $version, etc.)\n const stateNames = Object.keys(config).filter((k) => !k.startsWith('$'))\n\n // Check if $initial is missing or empty\n if (!('$initial' in config) || config.$initial === undefined) {\n errors.push({\n code: 'MISSING_INITIAL_STATE',\n message: 'State machine configuration is missing $initial',\n })\n } else if (config.$initial === '' || !stateNames.includes(config.$initial)) {\n // $initial is present but invalid (empty string or references non-existent state)\n errors.push({\n code: 'INVALID_INITIAL_STATE',\n message: `Initial state '${config.$initial}' is not a valid state`,\n })\n }\n\n // Helper to get transition target from a transition value\n const getTransitionTarget = (value: unknown): string | null => {\n if (typeof value === 'string') return value\n if (value && typeof value === 'object' && 'to' in value && typeof (value as Record<string, unknown>).to === 'string') {\n return (value as Record<string, unknown>).to as string\n }\n return null\n }\n\n // Check all transition targets exist and have valid syntax\n for (const stateName of stateNames) {\n const stateConfig = config[stateName]\n\n // null means terminal state - valid\n if (stateConfig === null) continue\n\n // Empty object means terminal state - valid\n if (typeof stateConfig === 'object' && Object.keys(stateConfig as object).length === 0) continue\n\n if (typeof stateConfig !== 'object') {\n errors.push({\n code: 'INVALID_STATE_CONFIG',\n message: `State '${stateName}' has invalid configuration`,\n state: stateName,\n })\n continue\n }\n\n // Check each transition\n for (const [eventName, transitionValue] of Object.entries(stateConfig as object)) {\n // Skip handler functions ($entry, $exit)\n if (eventName.startsWith('$')) continue\n\n // Check transition syntax\n if (Array.isArray(transitionValue)) {\n errors.push({\n code: 'INVALID_TRANSITION_SYNTAX',\n message: `Transition '${eventName}' in state '${stateName}' cannot be an array`,\n state: stateName,\n event: eventName,\n })\n continue\n }\n\n // String transition: { submit: 'pending' }\n if (typeof transitionValue === 'string') {\n if (!stateNames.includes(transitionValue)) {\n errors.push({\n code: 'INVALID_TRANSITION_TARGET',\n message: `Transition '${eventName}' in state '${stateName}' targets unknown state '${transitionValue}'`,\n state: stateName,\n event: eventName,\n })\n }\n continue\n }\n\n // null transition: terminal (goes nowhere, like archive/delete)\n if (transitionValue === null) continue\n\n // Object transition: { submit: { to: 'pending', if: ..., do: ... } }\n if (typeof transitionValue === 'object') {\n const tv = transitionValue as Record<string, unknown>\n // Must have 'to' property\n if (!('to' in tv)) {\n errors.push({\n code: 'INVALID_TRANSITION_SYNTAX',\n message: `Transition '${eventName}' in state '${stateName}' is missing 'to' property`,\n state: stateName,\n event: eventName,\n })\n continue\n }\n // Check target exists if 'to' is specified\n if (typeof tv.to === 'string' && !stateNames.includes(tv.to)) {\n errors.push({\n code: 'INVALID_TRANSITION_TARGET',\n message: `Transition '${eventName}' in state '${stateName}' targets unknown state '${tv.to}'`,\n state: stateName,\n event: eventName,\n })\n }\n continue\n }\n\n // Unknown transition format (e.g., number)\n errors.push({\n code: 'INVALID_TRANSITION_SYNTAX',\n message: `Transition '${eventName}' in state '${stateName}' has invalid format`,\n state: stateName,\n event: eventName,\n })\n }\n }\n\n // Check for orphan states (states not reachable from $initial)\n // Only do this check if we have a valid $initial state\n if (config.$initial && stateNames.includes(config.$initial)) {\n const reachable = new Set<string>()\n const toVisit = [config.$initial]\n\n while (toVisit.length > 0) {\n const current = toVisit.pop()!\n if (reachable.has(current)) continue\n reachable.add(current)\n\n // Find all states reachable from current\n const stateConfig = config[current]\n if (stateConfig === null || typeof stateConfig !== 'object') continue\n\n for (const [eventName, transitionValue] of Object.entries(stateConfig as object)) {\n if (eventName.startsWith('$')) continue\n const target = getTransitionTarget(transitionValue)\n if (target && stateNames.includes(target) && !reachable.has(target)) {\n toVisit.push(target)\n }\n }\n }\n\n // Any state not in reachable set is an orphan\n for (const stateName of stateNames) {\n if (!reachable.has(stateName)) {\n errors.push({\n code: 'ORPHAN_STATE',\n message: `State '${stateName}' is not reachable from initial state '${config.$initial}'`,\n state: stateName,\n })\n }\n }\n }\n\n return { valid: errors.length === 0, errors }\n}\n\n/**\n * Parse a raw state machine configuration into the normalized format.\n * Converts string functions to SerializedFunction objects.\n *\n * @param config - Raw state machine config from schema\n * @returns Parsed state machine configuration\n *\n * @example\n * const parsed = parseStateConfig({\n * $initial: 'draft',\n * draft: {\n * submit: 'pending',\n * $entry: (entity) => { console.log('entered draft') }\n * },\n * pending: {\n * approve: { to: 'approved', if: (e) => e.score >= 80 }\n * },\n * approved: null // terminal state\n * })\n */\nexport function parseStateConfig(config: RawStateConfig): ParsedStateConfig {\n const states: Record<string, StateConfig> = {}\n\n for (const [stateName, stateValue] of Object.entries(config)) {\n // Skip $initial - it's not a state\n if (stateName === '$initial') continue\n\n // Terminal state (null or empty object)\n if (stateValue === null || (typeof stateValue === 'object' && Object.keys(stateValue).length === 0)) {\n states[stateName] = { transitions: {} }\n continue\n }\n\n if (typeof stateValue !== 'object') {\n continue // Skip invalid state configs\n }\n\n const stateConfig: StateConfig = { transitions: {} }\n const stateObj = stateValue as Record<string, unknown>\n\n for (const [key, value] of Object.entries(stateObj)) {\n // Handle $entry handler\n if (key === '$entry') {\n if (typeof value === 'function') {\n stateConfig.$entry = serializeFunction('$entry', value)\n } else if (typeof value === 'string') {\n // String function body - parse it\n stateConfig.$entry = {\n name: '$entry',\n body: value,\n params: ['entity'],\n async: value.includes('await'),\n }\n }\n continue\n }\n\n // Handle $exit handler\n if (key === '$exit') {\n if (typeof value === 'function') {\n stateConfig.$exit = serializeFunction('$exit', value)\n } else if (typeof value === 'string') {\n stateConfig.$exit = {\n name: '$exit',\n body: value,\n params: ['entity'],\n async: value.includes('await'),\n }\n }\n continue\n }\n\n // Handle transitions\n const transitionName = key\n\n // Simple string transition: { submit: 'pending' }\n if (typeof value === 'string') {\n stateConfig.transitions[transitionName] = { to: value }\n continue\n }\n\n // null transition (shouldn't happen, but handle it)\n if (value === null) {\n stateConfig.transitions[transitionName] = { to: null }\n continue\n }\n\n // Complex transition with to/if/do: { approve: { to: 'approved', if: ..., do: ... } }\n if (typeof value === 'object') {\n const transObj = value as Record<string, unknown>\n const transitionConfig: TransitionConfig = {\n to: (transObj.to as string) ?? null,\n }\n\n // Parse 'if' guard\n if (transObj.if) {\n if (typeof transObj.if === 'function') {\n transitionConfig.if = serializeFunction('if', transObj.if)\n } else if (typeof transObj.if === 'string') {\n transitionConfig.if = {\n name: 'if',\n body: transObj.if,\n params: ['entity'],\n async: (transObj.if as string).includes('await'),\n }\n }\n }\n\n // Parse 'do' action\n if (transObj.do) {\n if (typeof transObj.do === 'function') {\n transitionConfig.do = serializeFunction('do', transObj.do)\n } else if (typeof transObj.do === 'string') {\n transitionConfig.do = {\n name: 'do',\n body: transObj.do,\n params: ['entity'],\n async: (transObj.do as string).includes('await'),\n }\n }\n }\n\n stateConfig.transitions[transitionName] = transitionConfig\n }\n }\n\n states[stateName] = stateConfig\n }\n\n return {\n $initial: config.$initial,\n states,\n }\n}\n\n// ============================================================================\n// Parsed Types\n// ============================================================================\n\nexport interface ParsedType {\n name: string\n fields: Record<string, ParsedField>\n references: TypeReference[]\n seed?: SeedConfig\n icon?: string\n group?: string\n // Entity lifecycle handlers (direct access)\n $created?: SerializedFunction\n $updated?: SerializedFunction\n $deleted?: SerializedFunction\n // Entity lifecycle handlers (grouped - deprecated, use direct access)\n handlers?: Record<string, SerializedFunction>\n // State machine configuration\n $state?: ParsedStateConfig\n // Data source configurations\n source?: SourceConfig\n input?: SourceInput\n from?: string[]\n cache?: string\n isSourceFunction?: boolean\n // Generative format configurations\n image?: ImageConfig\n speech?: SpeechConfig\n diagram?: DiagramConfig\n conventions?: ConventionsConfig\n code?: CodeConfig\n isGenerative?: boolean\n // Entity-level eval and experiment\n eval?: Record<string, EvalDefinition>\n experiment?: SchemaExperiment\n}\n\nexport interface SchemaSettings {\n iconLibrary?: string\n}\n\nexport interface ParsedSchema {\n types: Record<string, ParsedType>\n hash: string\n settings?: SchemaSettings\n // Schema-level directives\n fn?: Record<string, SerializedFunction>\n on?: Record<string, SerializedFunction>\n eval?: Record<string, EvalDefinition>\n experiment?: Record<string, SchemaExperiment>\n analytics?: SchemaAnalytics\n // Schema-level lifecycle handlers ($seeded, $ready, $error)\n handlers?: Record<string, SerializedFunction>\n}\n\nexport interface JSONSchemaProperty {\n type: string\n description?: string\n items?: { type: string; properties?: Record<string, JSONSchemaProperty>; required?: string[]; additionalProperties?: boolean }\n properties?: Record<string, JSONSchemaProperty>\n required?: string[]\n additionalProperties?: boolean\n minItems?: number\n maxItems?: number\n}\n\nexport interface JSONSchema {\n type: 'object'\n properties: Record<string, JSONSchemaProperty>\n required: string[]\n additionalProperties: boolean\n}\n\n// Extract count from array description\n// Supports patterns like:\n// - \"List 5 items\" -> 5\n// - \"Generate 10 samples\" -> 10\n// - \"Create exactly 7 categories\" -> 7\n// - \"List 3-5 keywords\" -> { min: 3, max: 5 }\nexport function extractCountFromDescription(description: string): number | { min: number; max: number } | undefined {\n // First check for range pattern: N-M (e.g., \"3-5\")\n const rangeMatch = description.match(/\\b(\\d+)-(\\d+)\\b/)\n if (rangeMatch) {\n return { min: parseInt(rangeMatch[1], 10), max: parseInt(rangeMatch[2], 10) }\n }\n\n // Check for patterns like \"List N\", \"Generate N\", \"Create exactly N\"\n // Match word followed by optional \"exactly\" and a number\n const countMatch = description.match(/\\b(?:List|Generate|Create)\\s+(?:exactly\\s+)?(\\d+)\\b/i)\n if (countMatch) {\n return parseInt(countMatch[1], 10)\n }\n\n return undefined\n}\n\n/**\n * Parse a field value into its structured field type representation.\n *\n * Converts the shorthand field notation used in schema definitions into\n * a fully parsed field object with type information, references, and options.\n *\n * ## Reference Operators\n *\n * This function parses all four reference operators defined in {@link OPERATORS}:\n *\n * | Operator | Direction | Mode | Description |\n * |----------|-----------|-------|--------------------------------|\n * | `->` | forward | exact | Resolves to exact ID match |\n * | `~>` | forward | fuzzy | Resolves by semantic similarity|\n * | `<-` | backward | exact | Finds entities referencing this|\n * | `<~` | backward | fuzzy | Finds semantically related |\n *\n * @param value - The field value to parse. Can be:\n * - `string` - A field description or reference pattern (e.g., `'User name'`, `'->User'`, `'~>Image?'`, `'<-Post[]'`)\n * - `string[]` - An array field with description (e.g., `['Tag labels']`, `['<-Post']`)\n * - `Record<string, string>` - A nested object with field descriptions\n * - `Function` - A computed field\n *\n * @returns A ParsedField object representing the field type:\n * - `StringField` - Plain text field with description\n * - `ReferenceField` - Reference to another type (forward or backward)\n * - `ArrayField` - Array of strings or references\n * - `ObjectField` - Nested object with properties\n * - `EmbeddedField` - Embedded type (detected in second pass)\n * - `JSONPathField` - JSONPath expression for data mapping\n * - `ComputedField` - Field computed from a function\n *\n * @example\n * // String field\n * parseFieldType('User name')\n * // { type: 'string', description: 'User name' }\n *\n * @example\n * // Forward exact reference\n * parseFieldType('->User')\n * // { type: 'reference', ref: 'User', isArray: false, optional: false, fuzzy: false }\n *\n * @example\n * // Forward fuzzy reference (optional)\n * parseFieldType('~>Image?')\n * // { type: 'reference', ref: 'Image', isArray: false, optional: true, fuzzy: true }\n *\n * @example\n * // Forward array reference\n * parseFieldType('->Tag[]')\n * // { type: 'reference', ref: 'Tag', isArray: true, optional: false, fuzzy: false }\n *\n * @example\n * // Backward exact reference - finds Posts that reference this entity\n * parseFieldType('<-Post')\n * // { type: 'reference', ref: 'Post', isArray: false, optional: false, direction: 'backward', mode: 'exact' }\n *\n * @example\n * // Backward fuzzy reference array - finds semantically related Articles\n * parseFieldType('<~Article[]')\n * // { type: 'reference', ref: 'Article', isArray: true, optional: false, direction: 'backward', mode: 'fuzzy' }\n *\n * @example\n * // Union type reference\n * parseFieldType('->User|Organization')\n * // { type: 'reference', refs: ['User', 'Organization'], isArray: false, optional: false, fuzzy: false }\n *\n * @example\n * // String array with count hint\n * parseFieldType(['List 5 keywords'])\n * // { type: 'array', items: { type: 'string' }, description: 'List 5 keywords', count: 5 }\n *\n * @example\n * // Nested object\n * parseFieldType({ street: 'Street address', city: 'City name' })\n * // { type: 'object', properties: { street: {...}, city: {...} } }\n */\nexport function parseFieldType(value: FieldValue | Function): ParsedField {\n // Handle boolean markers (e.g., '->ICP[]': true)\n // These are relationship triggers where the field key contains the reference pattern\n if (typeof value === 'boolean') {\n return {\n type: 'string',\n description: '',\n }\n }\n\n // Handle computed fields (functions)\n if (typeof value === 'function') {\n return {\n type: 'computed',\n source: value.toString(),\n }\n }\n\n // Handle array descriptions: ['description'], ['... ->Type'], ['<-Type']\n if (Array.isArray(value)) {\n const desc = value[0] || ''\n const count = extractCountFromDescription(desc)\n\n // Check for back reference: ['<-Type']\n const backRefMatch = desc.match(/^<-(\\w+)$/)\n if (backRefMatch) {\n const result: ArrayField = {\n type: 'array',\n items: { type: 'string' },\n description: desc,\n backRef: backRefMatch[1],\n }\n if (count !== undefined) result.count = count\n return result\n }\n\n // Check for inline references: ['... ->Type'] or ['... ->Type1 ->Type2']\n const inlineRefMatches = desc.match(/->(\\w+)/g)\n if (inlineRefMatches) {\n const refs = inlineRefMatches.map((m) => m.slice(2)) // Remove '->' prefix\n const result: ArrayField = {\n type: 'array',\n items: { type: 'string' },\n description: desc,\n refs,\n }\n if (count !== undefined) result.count = count\n return result\n }\n\n const result: ArrayField = {\n type: 'array',\n items: { type: 'string' },\n description: desc,\n }\n if (count !== undefined) result.count = count\n return result\n }\n\n // Handle nested objects: { field: 'description', ... }\n if (typeof value === 'object' && value !== null) {\n const properties: Record<string, StringField> = {}\n for (const [key, desc] of Object.entries(value)) {\n // Only include string descriptions, skip booleans and nested objects\n if (typeof desc === 'string') {\n properties[key] = { type: 'string', description: desc }\n }\n }\n return {\n type: 'object',\n properties,\n }\n }\n\n // Handle non-string values that weren't caught above (null, undefined, numbers, etc.)\n if (typeof value !== 'string') {\n return null as unknown as ParsedField\n }\n\n // Handle string patterns\n const str = value\n\n // Check for JSONPath with transform: Transform($.path)\n // Supports transforms like PascalCase, camelCase, kebab-case, UPPERCASE, lowercase\n const transformMatch = str.match(/^([A-Za-z][A-Za-z0-9-]*)\\((\\$\\..+)\\)$/)\n if (transformMatch) {\n const [, transform, path] = transformMatch\n return {\n type: 'jsonpath',\n path,\n transform,\n }\n }\n\n // Check for JSONPath embedded pattern: $.path ->Type or $.path ->Type?\n // Must check this BEFORE plain JSONPath to properly detect embedded mappings\n // Pattern: JSONPath followed by optional whitespace, ->, optional whitespace, TypeName, optional ?\n const jsonpathEmbeddedMatch = str.match(/^(\\$\\.[^\\s]+?)\\s*->\\s*([A-Za-z][A-Za-z0-9]*)(\\?)?$/)\n if (jsonpathEmbeddedMatch) {\n const [, path, embeddedType, optionalMarker] = jsonpathEmbeddedMatch\n // Determine if it's an array based on path containing [*] or [?(...)]\n const isArray = /\\[\\*\\]|\\[\\?/.test(path)\n return {\n type: 'jsonpath-embedded',\n path,\n embeddedType,\n isArray,\n ...(optionalMarker && { optional: true }),\n }\n }\n\n // Check for JSONPath pattern: $.xxx (must start with $. to avoid matching \"$50 price\")\n if (str.startsWith('$.')) {\n return {\n type: 'jsonpath',\n path: str,\n }\n }\n\n // Check for reference pattern: ->Type, ~>Type, <-Type, <~Type, with optional [], ?, and unions\n // Pattern: (<-|<~|->|~>)Type1|Type2|...[]?\n const refMatch = str.match(/^(<-|<~|->|~>)(.+?)(\\[\\])?(\\?)?$/)\n\n if (refMatch) {\n const [, prefix, typesPart, arrayMarker, optionalMarker] = refMatch\n const isArray = !!arrayMarker\n const optional = !!optionalMarker\n\n // Check for union types (Type1|Type2|...)\n const types = typesPart.split('|').map((t) => t.trim())\n\n // Parse the operator to get direction and mode/fuzzy\n const parsedOp = parseOperator(prefix)\n\n if (parsedOp.direction === 'backward') {\n // Backward references use direction/mode properties\n const baseRef = {\n type: 'reference' as const,\n isArray,\n optional,\n direction: parsedOp.direction,\n mode: parsedOp.mode,\n }\n\n return types.length > 1 ? { ...baseRef, refs: types } : { ...baseRef, ref: types[0] }\n } else {\n // Forward references use fuzzy property (backward compatibility)\n const baseRef = {\n type: 'reference' as const,\n isArray,\n optional,\n fuzzy: parsedOp.fuzzy,\n }\n\n return types.length > 1 ? { ...baseRef, refs: types } : { ...baseRef, ref: types[0] }\n }\n }\n\n // Plain string field\n return {\n type: 'string',\n description: str,\n }\n}\n\n// ============================================================================\n// Reference Parsing Utilities for Two-Phase Generation\n// ============================================================================\n\n/**\n * Parsed reference field info for generation.\n * Used by the two-phase generation pipeline to understand reference fields.\n */\nexport interface ParsedGenerationReference {\n /** Reference mode: exact (->) or fuzzy (~>) */\n mode: 'exact' | 'fuzzy'\n /** Target type name (or first type for union types) */\n targetType: string\n /** All target types for union types */\n targetTypes?: string[]\n /** Whether this reference is optional */\n isOptional: boolean\n /** Whether this is an array reference */\n isArray: boolean\n}\n\n/**\n * Parse a reference field definition for generation.\n *\n * Handles patterns like:\n * - `->Person` - exact reference\n * - `~>Industry` - fuzzy reference\n * - `->Type[]` - array of exact references\n * - `~>Type?` - optional fuzzy reference\n * - `->User|Organization` - union type reference\n *\n * @param fieldDef - The field definition string (e.g., '->Person', '~>Industry?')\n * @returns ParsedGenerationReference or null if not a reference field\n *\n * @example\n * parseGenerationReference('->Person')\n * // { mode: 'exact', targetType: 'Person', isOptional: false, isArray: false }\n *\n * @example\n * parseGenerationReference('~>Industry?')\n * // { mode: 'fuzzy', targetType: 'Industry', isOptional: true, isArray: false }\n *\n * @example\n * parseGenerationReference('->User|Organization')\n * // { mode: 'exact', targetType: 'User', targetTypes: ['User', 'Organization'], isOptional: false, isArray: false }\n */\nexport function parseGenerationReference(fieldDef: string): ParsedGenerationReference | null {\n // Match reference patterns: ->, ~>, with optional ? and []\n // Pattern supports union types: ->Type1|Type2|Type3\n const match = fieldDef.match(/^(->|~>)([A-Za-z][A-Za-z0-9]*(?:\\|[A-Za-z][A-Za-z0-9]*)*)(\\[\\])?(\\?)?$/)\n if (!match) return null\n\n const [, operator, typesPart, arrayMarker, optionalMarker] = match\n const types = typesPart.split('|').map(t => t.trim())\n\n return {\n mode: operator === '->' ? 'exact' : 'fuzzy',\n targetType: types[0],\n ...(types.length > 1 && { targetTypes: types }),\n isOptional: optionalMarker === '?',\n isArray: arrayMarker === '[]',\n }\n}\n\n/**\n * Parse array field definition for generation.\n *\n * Handles array shorthand like `['~>Investor']` or `['->Person']`.\n *\n * @param fieldDef - The field definition array (e.g., ['~>Investor'])\n * @returns ParsedGenerationReference or null if not a reference array\n *\n * @example\n * parseGenerationArrayReference(['~>Investor'])\n * // { mode: 'fuzzy', targetType: 'Investor', isOptional: false, isArray: true }\n */\nexport function parseGenerationArrayReference(fieldDef: string[]): ParsedGenerationReference | null {\n if (!Array.isArray(fieldDef) || fieldDef.length !== 1) return null\n const inner = fieldDef[0]\n if (typeof inner !== 'string') return null\n\n const parsed = parseGenerationReference(inner)\n if (!parsed) return null\n\n return {\n ...parsed,\n isArray: true,\n }\n}\n\n/**\n * Check if a field definition is a reference field.\n *\n * @param fieldDef - The field definition (string or array)\n * @returns true if this is a reference field\n *\n * @example\n * isReferenceField('->User') // true\n * isReferenceField('~>Industry?') // true\n * isReferenceField(['~>Investor']) // true\n * isReferenceField('User name') // false\n * isReferenceField(['tags']) // false\n */\nexport function isReferenceField(fieldDef: string | string[]): boolean {\n if (typeof fieldDef === 'string') {\n return parseGenerationReference(fieldDef) !== null\n }\n if (Array.isArray(fieldDef)) {\n return parseGenerationArrayReference(fieldDef) !== null\n }\n return false\n}\n\n/**\n * Extract reference mode from a field definition.\n *\n * @param fieldDef - The field definition\n * @returns 'exact' | 'fuzzy' | null\n */\nexport function getReferenceMode(fieldDef: string | string[]): 'exact' | 'fuzzy' | null {\n if (typeof fieldDef === 'string') {\n return parseGenerationReference(fieldDef)?.mode ?? null\n }\n if (Array.isArray(fieldDef)) {\n return parseGenerationArrayReference(fieldDef)?.mode ?? null\n }\n return null\n}\n\n/**\n * Extract target type(s) from a reference field.\n *\n * @param fieldDef - The field definition\n * @returns Target type string, array of types for unions, or null if not a reference\n */\nexport function getReferenceTargetType(fieldDef: string | string[]): string | string[] | null {\n let parsed: ParsedGenerationReference | null = null\n\n if (typeof fieldDef === 'string') {\n parsed = parseGenerationReference(fieldDef)\n } else if (Array.isArray(fieldDef)) {\n parsed = parseGenerationArrayReference(fieldDef)\n }\n\n if (!parsed) return null\n return parsed.targetTypes ?? parsed.targetType\n}\n\n/**\n * Parse seed configuration from a schema type's `$seed` field.\n *\n * Seed configuration tells the system where to fetch initial data for a type,\n * supporting TSV, CSV, and JSON formats with pagination support.\n *\n * @param value - The seed configuration. Can be:\n * - `string` - A URL (format inferred from extension: `.csv`, `.json`, or default `.tsv`)\n * - `Record<string, string>` - Object with explicit options\n *\n * @returns A SeedConfig object with:\n * - `url` - The data source URL\n * - `format` - Data format ('tsv', 'csv', or 'json')\n * - `idField` - Optional field to use as entity ID\n * - `next` - Optional JSONPath to pagination URL\n * - `data` - Optional JSONPath to data array in response\n *\n * @example\n * // Simple URL (format inferred)\n * parseSeedConfig('https://example.com/data.csv')\n * // { url: 'https://example.com/data.csv', format: 'csv' }\n *\n * @example\n * // URL with TSV default\n * parseSeedConfig('https://example.com/data')\n * // { url: 'https://example.com/data', format: 'tsv' }\n *\n * @example\n * // Object config with pagination\n * parseSeedConfig({\n * url: 'https://api.example.com/items',\n * format: 'json',\n * data: '$.items',\n * next: '$.pagination.next'\n * })\n * // { url: '...', format: 'json', data: '$.items', next: '$.pagination.next' }\n */\nexport function parseSeedConfig(value: string | Record<string, string>): SeedConfig {\n if (typeof value === 'string') {\n // Infer format from URL extension\n const url = value\n let format: 'tsv' | 'csv' | 'json' = 'tsv'\n if (url.endsWith('.csv')) format = 'csv'\n else if (url.endsWith('.json')) format = 'json'\n return { url, format }\n }\n // Object config with explicit options\n const config: SeedConfig = {\n url: value.url || value.$seed,\n format: (value.format as 'tsv' | 'csv' | 'json') || 'tsv',\n }\n if (value.idField) config.idField = value.idField\n if (value.next) config.next = value.next\n if (value.data) config.data = value.data\n return config\n}\n\n/**\n * Converts string fields to prompt fields in a seeded type's field map.\n *\n * In seeded schemas, plain string values represent prompts for AI generation\n * rather than simple field descriptions. This function performs the conversion\n * after initial field parsing, ensuring that JSONPath fields and reference\n * fields remain unchanged while string fields become prompt fields.\n *\n * @param fields - The parsed fields map from parseFieldType calls\n * @returns A new fields map with string fields converted to prompt fields\n *\n * @example\n * // Input: fields from a seeded type\n * const fields = {\n * title: { type: 'string', description: 'Some title' },\n * jsonField: { type: 'jsonpath', path: '$.name' },\n * ref: { type: 'reference', ref: 'Other', isArray: false },\n * }\n *\n * // Output: string -> prompt, others unchanged\n * const converted = convertStringsToPromptsInSeededType(fields)\n * // converted.title = { type: 'prompt', prompt: 'Some title' }\n * // converted.jsonField = { type: 'jsonpath', path: '$.name' }\n * // converted.ref = { type: 'reference', ref: 'Other', isArray: false }\n *\n * @remarks\n * This function is called during parseSchema when a type has `$seed` defined.\n * Only StringField types are converted; all other field types pass through unchanged.\n */\nexport function convertStringsToPromptsInSeededType(\n fields: Record<string, ParsedField>\n): Record<string, ParsedField> {\n const result: Record<string, ParsedField> = {}\n\n for (const [fieldName, field] of Object.entries(fields)) {\n if (isStringField(field)) {\n result[fieldName] = {\n type: 'prompt',\n prompt: field.description,\n }\n } else {\n result[fieldName] = field\n }\n }\n\n return result\n}\n\n/**\n * Parse an entire schema definition into a structured ParsedSchema.\n *\n * This is the main parsing function that takes a schema definition object and\n * produces a fully parsed representation with all types, fields, references,\n * and metadata resolved.\n *\n * @param schema - The schema definition object containing type definitions and metadata.\n * Metadata fields are prefixed with `$` (e.g., `$id`, `$context`, `$settings`).\n * All other keys are treated as type definitions.\n *\n * @returns A ParsedSchema object containing:\n * - `types` - Record of parsed type definitions with fields and references\n * - `hash` - Deterministic hash of the schema for versioning\n * - `settings` - Optional schema-level settings (e.g., iconLibrary)\n *\n * @example\n * const schema = parseSchema({\n * $id: 'https://db.sb/blog',\n * Post: {\n * title: 'Post title',\n * content: 'Main content',\n * author: '->User',\n * tags: ['Tag labels']\n * },\n * User: {\n * name: 'User name',\n * email: 'Email address',\n * posts: '->Post[]'\n * }\n * })\n *\n * // schema.types.Post.fields.title\n * // { type: 'string', description: 'Post title' }\n *\n * // schema.types.Post.references\n * // [{ field: 'author', ref: 'User', isArray: false }]\n *\n * @example\n * // Schema with seed configuration and icons\n * const schema = parseSchema({\n * $context: 'startups',\n * $settings: { iconLibrary: 'lucide' },\n * Company: {\n * $icon: 'building',\n * $seed: 'https://api.example.com/companies.json',\n * name: 'Company name',\n * website: 'Website URL'\n * }\n * })\n *\n * // schema.types.Company.icon === 'building'\n * // schema.types.Company.seed.url === 'https://api.example.com/companies.json'\n */\nexport function parseSchema(schema: SchemaDefinition): ParsedSchema {\n const types: Record<string, ParsedType> = {}\n\n // Extract schema-level $settings\n let settings: SchemaSettings | undefined\n const settingsValue = (schema as Record<string, unknown>).$settings\n if (settingsValue && typeof settingsValue === 'object' && settingsValue !== null) {\n const settingsObj = settingsValue as Record<string, unknown>\n if (settingsObj.iconLibrary || Object.keys(settingsObj).length > 0) {\n settings = {}\n if (typeof settingsObj.iconLibrary === 'string') {\n settings.iconLibrary = settingsObj.iconLibrary\n }\n }\n }\n\n // First pass: parse all types\n for (const [typeName, fields] of Object.entries(schema)) {\n // Skip metadata fields ($ prefixed)\n if (typeName.startsWith('$')) continue\n // Skip if not an object (metadata string values)\n if (typeof fields !== 'object' || fields === null) continue\n\n const parsedFields: Record<string, ParsedField> = {}\n const references: TypeReference[] = []\n let seed: SeedConfig | undefined\n let icon: string | undefined\n let group: string | undefined\n let seedNext: string | undefined\n let seedData: string | undefined\n let seedId: string | undefined\n let seedIdTransform: string | undefined\n // Entity lifecycle handlers\n const entityHandlers: Record<string, SerializedFunction> = {}\n // State machine configuration\n let parsedState: ParsedStateConfig | undefined\n // Data source configurations\n let source: SourceConfig | undefined\n let input: SourceInput | undefined\n let from: string[] | undefined\n let cache: string | undefined\n // Generative format configurations\n let image: ImageConfig | undefined\n let speech: SpeechConfig | undefined\n let diagram: DiagramConfig | undefined\n let conventions: ConventionsConfig | undefined\n let code: CodeConfig | undefined\n // Entity-level eval and experiment\n let entityEval: Record<string, EvalDefinition> | undefined\n let entityExperiment: SchemaExperiment | undefined\n\n for (const [fieldName, fieldValue] of Object.entries(fields)) {\n // Handle $seed metadata\n if (fieldName === '$seed') {\n seed = parseSeedConfig(fieldValue as string | Record<string, string>)\n continue\n }\n\n // Handle $next metadata (JSONPath to next page URL)\n if (fieldName === '$next') {\n if (typeof fieldValue === 'string') {\n seedNext = fieldValue\n }\n continue\n }\n\n // Handle $data metadata (JSONPath to data array)\n if (fieldName === '$data') {\n if (typeof fieldValue === 'string') {\n seedData = fieldValue\n }\n continue\n }\n\n // Handle $id metadata (JSONPath or transform for ID field)\n // Supports: '$.taskID', 'PascalCase($.example)', etc.\n if (fieldName === '$id') {\n if (typeof fieldValue === 'string') {\n const idConfig = parseIdConfig(fieldValue)\n seedId = idConfig.path\n seedIdTransform = idConfig.transform\n }\n continue\n }\n\n // Handle $icon metadata\n if (fieldName === '$icon') {\n if (typeof fieldValue === 'string') {\n icon = fieldValue\n }\n continue\n }\n\n // Handle $group metadata\n if (fieldName === '$group') {\n if (typeof fieldValue === 'string') {\n group = fieldValue\n }\n continue\n }\n\n // Handle entity lifecycle handlers ($created, $updated, $deleted)\n if (fieldName === '$created' || fieldName === '$updated' || fieldName === '$deleted') {\n if (typeof fieldValue === 'function') {\n entityHandlers[fieldName] = serializeFunction(fieldName, fieldValue)\n }\n continue\n }\n\n // Handle $state (state machine definition)\n if (fieldName === '$state') {\n if (typeof fieldValue === 'object' && fieldValue !== null && '$initial' in (fieldValue as object)) {\n parsedState = parseStateConfig(fieldValue as RawStateConfig)\n }\n continue\n }\n\n // Handle $source (external API source configuration)\n if (fieldName === '$source') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n source = fieldValue as unknown as SourceConfig\n }\n continue\n }\n\n // Handle $input (input parameters for source)\n if (fieldName === '$input') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n input = fieldValue as unknown as SourceInput\n }\n continue\n }\n\n // Handle $from (multi-source aggregation)\n if (fieldName === '$from') {\n if (Array.isArray(fieldValue)) {\n from = fieldValue as string[]\n }\n continue\n }\n\n // Handle $cache (cache duration)\n if (fieldName === '$cache') {\n if (typeof fieldValue === 'string') {\n cache = fieldValue\n }\n continue\n }\n\n // Handle $image (image generation configuration)\n if (fieldName === '$image') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n image = fieldValue as unknown as ImageConfig\n }\n continue\n }\n\n // Handle $speech (speech/TTS generation configuration)\n if (fieldName === '$speech') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n speech = fieldValue as unknown as SpeechConfig\n }\n continue\n }\n\n // Handle $diagram (diagram generation configuration)\n if (fieldName === '$diagram') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n diagram = fieldValue as unknown as DiagramConfig\n }\n continue\n }\n\n // Handle $code (code generation configuration)\n if (fieldName === '$code') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n code = fieldValue as unknown as CodeConfig\n }\n continue\n }\n\n // Handle $conventions (naming conventions)\n if (fieldName === '$conventions') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n conventions = fieldValue as unknown as ConventionsConfig\n }\n continue\n }\n\n // Handle $eval (entity-level evaluation definitions)\n if (fieldName === '$eval') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n entityEval = fieldValue as unknown as Record<string, EvalDefinition>\n }\n continue\n }\n\n // Handle $experiment (entity-level experiment definition)\n if (fieldName === '$experiment') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n entityExperiment = fieldValue as unknown as SchemaExperiment\n }\n continue\n }\n\n // Skip undefined field values\n if (fieldValue === undefined) continue\n\n const parsed = parseFieldType(fieldValue)\n parsedFields[fieldName] = parsed\n\n if (parsed.type === 'reference') {\n const refField = parsed as ReferenceField\n references.push({\n field: fieldName,\n ref: refField.ref || refField.refs?.[0] || '',\n refs: refField.refs,\n isArray: refField.isArray,\n optional: refField.optional,\n fuzzy: refField.fuzzy,\n })\n } else if (parsed.type === 'array') {\n const arrField = parsed as ArrayField\n // Track inline references from arrays\n if (arrField.refs) {\n for (const ref of arrField.refs) {\n references.push({\n field: fieldName,\n ref,\n isArray: true,\n optional: true, // Inline refs are always optional\n })\n }\n }\n // Track back references (for schema completeness, but these are read-only)\n if (arrField.backRef) {\n references.push({\n field: fieldName,\n ref: arrField.backRef,\n isArray: true,\n optional: true, // Back refs are collections\n backRef: true, // Mark as back reference - should not trigger generation\n })\n }\n }\n }\n\n // Merge $next, $data, $id into seed config if present\n if (seed) {\n if (seedNext) seed.next = seedNext\n if (seedData) seed.data = seedData\n if (seedId) seed.id = seedId\n if (seedIdTransform) seed.idTransform = seedIdTransform\n }\n\n // Post-process fields for seeded types: convert string fields to prompt fields\n // In seeded schemas, plain strings are prompts for AI generation, not string descriptions\n if (seed) {\n for (const [fieldName, field] of Object.entries(parsedFields)) {\n if (field.type === 'string') {\n const stringField = field as StringField\n parsedFields[fieldName] = {\n type: 'prompt',\n prompt: stringField.description,\n } as PromptField\n }\n }\n }\n\n // Determine if this is a source function type (provider:Type pattern)\n const isSourceFunction = typeName.includes(':') && !!source\n\n // Determine if this is a generative type\n const isGenerative = !!(image || speech || diagram || code)\n\n types[typeName] = {\n name: typeName,\n fields: parsedFields,\n references,\n ...(seed && { seed }),\n ...(icon && { icon }),\n ...(group && { group }),\n // Direct lifecycle handler access\n ...(entityHandlers['$created'] && { $created: entityHandlers['$created'] }),\n ...(entityHandlers['$updated'] && { $updated: entityHandlers['$updated'] }),\n ...(entityHandlers['$deleted'] && { $deleted: entityHandlers['$deleted'] }),\n // Grouped handlers (deprecated)\n ...(Object.keys(entityHandlers).length > 0 && { handlers: entityHandlers }),\n // State machine configuration\n ...(parsedState && { $state: parsedState }),\n // Data source configurations\n ...(source && { source }),\n ...(input && { input }),\n ...(from && { from }),\n ...(cache && { cache }),\n ...(isSourceFunction && { isSourceFunction }),\n // Generative format configurations\n ...(image && { image }),\n ...(speech && { speech }),\n ...(diagram && { diagram }),\n ...(code && { code }),\n ...(conventions && { conventions }),\n ...(isGenerative && { isGenerative }),\n // Entity-level eval and experiment\n ...(entityEval && { eval: entityEval }),\n ...(entityExperiment && { experiment: entityExperiment }),\n }\n }\n\n // Second pass: validate references (warn but don't crash on undefined types)\n for (const type of Object.values(types)) {\n for (const ref of type.references) {\n // Check all refs in union types\n const refsToCheck = ref.refs || [ref.ref]\n for (const refType of refsToCheck) {\n if (refType && !types[refType]) {\n // Warn instead of throwing - allows app to load with schema errors\n console.warn(`Reference to undefined type: ${refType} (in type ${type.name})`)\n }\n }\n }\n\n // Also validate jsonpath-embedded fields\n for (const [fieldName, field] of Object.entries(type.fields)) {\n if (field.type === 'jsonpath-embedded') {\n const embeddedType = (field as JSONPathEmbeddedField).embeddedType\n if (!types[embeddedType]) {\n console.warn(`JSONPath embedded reference to undefined type: ${embeddedType} (in type ${type.name}.${fieldName})`)\n }\n }\n }\n }\n\n // Third pass: detect embedded types (string fields that exactly match a type name)\n for (const type of Object.values(types)) {\n for (const [fieldName, field] of Object.entries(type.fields)) {\n if (field.type === 'string') {\n const desc = field.description\n\n // Check for embedded type pattern: TypeName, TypeName?, TypeName[]\n // Only match if the entire string is a type name (possibly with ? or [] suffix)\n const embeddedMatch = desc.match(/^(\\w+)(\\[\\])?(\\?)?$/)\n if (embeddedMatch) {\n const [, typeName, arrayMarker, optionalMarker] = embeddedMatch\n // Check if the type name exists in our schema\n if (types[typeName]) {\n // Convert to embedded field\n const embeddedField: EmbeddedField = {\n type: 'embedded',\n embeddedType: typeName,\n isArray: !!arrayMarker,\n optional: !!optionalMarker,\n }\n type.fields[fieldName] = embeddedField\n }\n }\n }\n }\n }\n\n // Parse schema-level directives\n let fn: Record<string, SerializedFunction> | undefined\n let on: Record<string, SerializedFunction> | undefined\n let evalDefs: Record<string, EvalDefinition> | undefined\n let experiment: Record<string, SchemaExperiment> | undefined\n let analytics: SchemaAnalytics | undefined\n\n const schemaObj = schema as Record<string, unknown>\n\n // Parse $fn - schema-level functions\n if (schemaObj.$fn && typeof schemaObj.$fn === 'object') {\n fn = {}\n for (const [name, func] of Object.entries(schemaObj.$fn)) {\n if (typeof func === 'function') {\n fn[name] = serializeFunction(name, func)\n }\n }\n }\n\n // Parse $on - schema-level event handlers\n if (schemaObj.$on && typeof schemaObj.$on === 'object') {\n on = {}\n for (const [name, func] of Object.entries(schemaObj.$on)) {\n if (typeof func === 'function') {\n on[name] = serializeFunction(name, func)\n }\n }\n }\n\n // Parse $eval - evaluation definitions\n if (schemaObj.$eval && typeof schemaObj.$eval === 'object') {\n evalDefs = schemaObj.$eval as Record<string, EvalDefinition>\n }\n\n // Parse $experiment - experiment definitions\n if (schemaObj.$experiment && typeof schemaObj.$experiment === 'object') {\n experiment = schemaObj.$experiment as Record<string, SchemaExperiment>\n }\n\n // Parse $analytics - analytics configuration\n if (schemaObj.$analytics && typeof schemaObj.$analytics === 'object') {\n analytics = schemaObj.$analytics as SchemaAnalytics\n }\n\n // Parse schema-level lifecycle handlers ($seeded, $ready, $error)\n const schemaHandlers: Record<string, SerializedFunction> = {}\n for (const key of ['$seeded', '$ready', '$error']) {\n if (typeof schemaObj[key] === 'function') {\n schemaHandlers[key] = serializeFunction(key, schemaObj[key] as Function)\n }\n }\n\n return {\n types,\n hash: schemaHash(schema),\n ...(settings && { settings }),\n ...(fn && { fn }),\n ...(on && { on }),\n ...(evalDefs && { eval: evalDefs }),\n ...(experiment && { experiment }),\n ...(analytics && { analytics }),\n ...(Object.keys(schemaHandlers).length > 0 && { handlers: schemaHandlers }),\n }\n}\n\n/**\n * Convert a parsed type definition to a JSON Schema representation.\n *\n * Transforms the internal ParsedType format into a standard JSON Schema object\n * that can be used for validation, documentation, or AI generation prompts.\n *\n * @param parsedType - The parsed type definition to convert\n * @param parsedSchema - Optional full schema for resolving embedded types.\n * When provided, embedded types (e.g., `Address` in `address: 'Address'`) are\n * recursively expanded into their full JSON Schema representation.\n * @param seen - Internal set for tracking visited types to prevent infinite recursion\n * in circular reference scenarios. Do not pass this parameter manually.\n *\n * @returns A JSON Schema object with:\n * - `type: 'object'` - Always an object schema\n * - `properties` - Map of field names to their JSON Schema definitions\n * - `required` - Array of required field names (non-optional fields)\n * - `additionalProperties: false` - Strict schema, no extra fields allowed\n *\n * @example\n * const parsed = parseSchema({\n * $context: 'blog',\n * Post: {\n * title: 'Post title',\n * author: '->User',\n * tags: ['List 3-5 keywords']\n * }\n * })\n *\n * const jsonSchema = toJSONSchema(parsed.types.Post, parsed)\n * // {\n * // type: 'object',\n * // properties: {\n * // title: { type: 'string', description: 'Post title' },\n * // author: { type: 'string', description: 'Reference to User (ID)' },\n * // tags: { type: 'array', items: { type: 'string' }, minItems: 3, maxItems: 5 }\n * // },\n * // required: ['title', 'author', 'tags'],\n * // additionalProperties: false\n * // }\n *\n * @example\n * // With embedded types expanded\n * const schema = parseSchema({\n * $context: 'app',\n * User: {\n * name: 'User name',\n * address: 'Address' // Embedded type\n * },\n * Address: {\n * street: 'Street',\n * city: 'City'\n * }\n * })\n *\n * const jsonSchema = toJSONSchema(schema.types.User, schema)\n * // properties.address will contain the full Address schema inline\n */\nexport function toJSONSchema(\n parsedType: ParsedType,\n parsedSchemaOrIncludeRefs?: ParsedSchema | boolean,\n seen: Set<string> = new Set()\n): JSONSchema {\n // Support both old API (boolean for includeReferences) and new API (ParsedSchema)\n const parsedSchema = typeof parsedSchemaOrIncludeRefs === 'object' ? parsedSchemaOrIncludeRefs : undefined\n const includeReferences = typeof parsedSchemaOrIncludeRefs === 'boolean' ? parsedSchemaOrIncludeRefs : true\n\n const properties: Record<string, JSONSchemaProperty> = {}\n const required: string[] = []\n\n for (const [fieldName, field] of Object.entries(parsedType.fields)) {\n // Skip computed fields - they're derived, not generated\n if (field.type === 'computed') {\n continue\n }\n\n const isOptional = 'optional' in field && field.optional\n\n if (field.type === 'string') {\n properties[fieldName] = {\n type: 'string',\n description: field.description,\n }\n } else if (field.type === 'reference' && includeReferences) {\n const refName = field.refs ? field.refs.join(' | ') : field.ref\n if (field.isArray) {\n properties[fieldName] = {\n type: 'array',\n items: { type: 'string' },\n description: `Array of ${refName} references (IDs)`,\n }\n } else {\n properties[fieldName] = {\n type: 'string',\n description: `Reference to ${refName} (ID)`,\n }\n }\n } else if (field.type === 'array') {\n const arrayProp: JSONSchemaProperty = {\n type: 'array',\n items: { type: 'string' },\n description: field.description,\n }\n // Wire up minItems/maxItems from parsed count\n if (field.count !== undefined) {\n if (typeof field.count === 'number') {\n arrayProp.minItems = field.count\n arrayProp.maxItems = field.count\n } else {\n arrayProp.minItems = field.count.min\n arrayProp.maxItems = field.count.max\n }\n }\n properties[fieldName] = arrayProp\n } else if (field.type === 'object') {\n const nestedProps: Record<string, JSONSchemaProperty> = {}\n const nestedRequired: string[] = []\n for (const [propName, propField] of Object.entries(field.properties)) {\n nestedProps[propName] = {\n type: 'string',\n description: propField.description,\n }\n nestedRequired.push(propName)\n }\n properties[fieldName] = {\n type: 'object',\n properties: nestedProps,\n required: nestedRequired,\n }\n } else if (field.type === 'embedded' && parsedSchema) {\n // Recursively embed the referenced type's JSON schema\n const embeddedTypeName = field.embeddedType\n const embeddedType = parsedSchema.types[embeddedTypeName]\n\n if (embeddedType) {\n // Determine if we're in a circular reference situation\n const isCircular = seen.has(embeddedTypeName)\n\n // Get the embedded type's JSON schema\n // For circular refs, stop recursion by not passing parsedSchema\n // For normal refs, continue with updated seen set\n const newSeen = isCircular ? seen : new Set([...seen, embeddedTypeName])\n const embeddedSchema = toJSONSchema(embeddedType, isCircular ? undefined : parsedSchema, newSeen)\n\n // Build the embedded object schema\n const embeddedObjectSchema = {\n type: 'object' as const,\n properties: embeddedSchema.properties,\n required: embeddedSchema.required,\n additionalProperties: false,\n }\n\n if (field.isArray) {\n properties[fieldName] = {\n type: 'array',\n items: embeddedObjectSchema,\n }\n } else {\n properties[fieldName] = embeddedObjectSchema\n }\n }\n } else if (field.type === 'embedded') {\n // If no parsedSchema provided, fall back to string representation\n properties[fieldName] = {\n type: 'string',\n description: field.embeddedType,\n }\n }\n\n // Only add to required if:\n // - not optional AND\n // - (not a reference OR includeReferences is true)\n const isReference = field.type === 'reference'\n if (!isOptional && (!isReference || includeReferences)) {\n required.push(fieldName)\n }\n }\n\n return {\n type: 'object',\n properties,\n required,\n additionalProperties: false,\n }\n}\n\n/**\n * Generate a deterministic hash for a schema definition.\n *\n * Creates a consistent 8-character hexadecimal hash that uniquely identifies\n * a schema's structure. The hash is computed using the FNV-1a algorithm on\n * the JSON-serialized schema with sorted keys, ensuring the same schema\n * always produces the same hash regardless of property order.\n *\n * @param schema - The schema definition to hash\n *\n * @returns An 8-character hexadecimal hash string\n *\n * @example\n * const hash1 = schemaHash({\n * $context: 'blog',\n * Post: { title: 'Title' }\n * })\n * // e.g., 'a1b2c3d4'\n *\n * // Same schema, different property order = same hash\n * const hash2 = schemaHash({\n * Post: { title: 'Title' },\n * $context: 'blog'\n * })\n * // hash1 === hash2\n *\n * @example\n * // Used for schema versioning\n * const schema = parseSchema({ $context: 'app', User: { name: 'Name' } })\n * console.log(schema.hash)\n * // The hash can be used to detect schema changes and trigger migrations\n */\nexport function schemaHash(schema: SchemaDefinition): string {\n // Sort keys recursively for consistent hashing\n const sortedSchema = sortObject(schema)\n const json = JSON.stringify(sortedSchema)\n\n // Simple hash function (FNV-1a)\n let hash = 2166136261\n for (let i = 0; i < json.length; i++) {\n hash ^= json.charCodeAt(i)\n hash = (hash * 16777619) >>> 0\n }\n return hash.toString(16).padStart(8, '0')\n}\n\nfunction sortObject(obj: Record<string, unknown>): Record<string, unknown> {\n if (typeof obj !== 'object' || obj === null) {\n return obj\n }\n\n if (Array.isArray(obj)) {\n return obj.map(sortObject) as unknown as Record<string, unknown>\n }\n\n const sorted: Record<string, unknown> = {}\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = sortObject(obj[key] as Record<string, unknown>)\n }\n return sorted\n}\n\n// ============================================================================\n// SDK Configuration\n// ============================================================================\n\n/**\n * Get the default API base URL. Reads environment variable dynamically\n * to support test mocking.\n */\nfunction getDefaultApiBase(): string {\n return (typeof process !== 'undefined' && process.env?.DB4AI_API_BASE) || 'https://db4ai.dev'\n}\n\n// ============================================================================\n// Job: Tracking async operations\n// ============================================================================\n\nexport type JobStatus = 'queued' | 'running' | 'completed' | 'failed'\n\nexport interface Job<T = void> {\n id: string\n status: JobStatus\n result?: T\n error?: Error\n}\n\nfunction createJob<T>(): Job<T> {\n return {\n id: `job_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`,\n status: 'queued',\n }\n}\n\n// ============================================================================\n// EntityCollection: Callable, iterable collection of entities\n// ============================================================================\n\n/**\n * EntityCollection is both a factory function and an iterable collection.\n * - As factory: `await db.Idea('id', { concept: '...' })`\n * - As collection: `for (const idea of db.Idea) { ... }`\n */\n/** Options for listing entities */\nexport interface ListOptions {\n /** Maximum number of entities to return */\n limit?: number\n /** Number of entities to skip */\n offset?: number\n /** Filter criteria */\n filter?: Record<string, unknown>\n}\n\nexport interface EntityCollection<T extends Record<string, unknown> = Record<string, unknown>> extends Iterable<T> {\n /** The type name of entities in this collection */\n readonly $type: string\n\n /** Current count of entities in the local collection */\n readonly $count: number\n\n /** Execute a function for each entity, returns a Job for tracking */\n forEach(fn: (item: T) => void): Job<void>\n\n /** Transform each entity, returns a Combinable for chaining */\n map<R>(fn: (item: T) => R): Combinable<R>\n\n /** Filter entities by predicate, returns a Combinable for chaining */\n where(predicate: (item: T) => boolean): Combinable<T>\n\n /** Fetch all entities from API and populate collection */\n fetchAll(): Promise<T[]>\n\n /** List entities with optional limit, offset, and filter */\n list(options?: ListOptions): Promise<T[]>\n\n /** Get a single entity by ID */\n get(id: string): Promise<T | undefined>\n\n /** Create a new entity with the given data */\n create(data: Partial<T>): Promise<T>\n\n /** Factory function signature - call the collection to generate/fetch an entity */\n (id: string, context?: Record<string, unknown>): Promise<T>\n}\n\n/**\n * Internal class for managing entity collection state\n */\nclass EntityCollectionImpl<T extends Record<string, unknown>> {\n readonly $type: string\n private _items: T[] = []\n private _baseUrl: string\n private _namespace: string\n private _registerSchema: () => Promise<void>\n\n constructor(typeName: string, baseUrl: string, namespace: string, registerSchema: () => Promise<void>) {\n this.$type = typeName\n this._baseUrl = baseUrl\n this._namespace = namespace\n this._registerSchema = registerSchema\n }\n\n get $count(): number {\n return this._items.length\n }\n\n _addItem(item: T): void {\n this._items.push(item)\n }\n\n _setItems(items: T[]): void {\n this._items = items\n }\n\n _getItems(): T[] {\n return this._items\n }\n\n [Symbol.iterator](): Iterator<T> {\n return this._items[Symbol.iterator]()\n }\n\n forEach(fn: (item: T) => void): Job<void> {\n const job = createJob<void>()\n job.status = 'running'\n try {\n for (const item of this._items) {\n fn(item)\n }\n job.status = 'completed'\n } catch (error) {\n job.status = 'failed'\n job.error = error instanceof Error ? error : new Error(String(error))\n }\n return job\n }\n\n map<R>(fn: (item: T) => R): Combinable<R> {\n const items = this._items\n return new Combinable(function* () {\n for (const item of items) {\n yield fn(item)\n }\n })\n }\n\n where(predicate: (item: T) => boolean): Combinable<T> {\n const items = this._items\n return new Combinable(function* () {\n for (const item of items) {\n if (predicate(item)) {\n yield item\n }\n }\n })\n }\n\n async fetchAll(): Promise<T[]> {\n await this._registerSchema()\n const url = `${this._baseUrl}/api/${this._namespace}/${this.$type}`\n const res = await fetch(url)\n if (!res.ok) {\n throw new APIError('GENERATION_FAILED', `Failed to fetch ${this.$type}: ${await res.text()}`, res.status)\n }\n const data = await res.json()\n const items = Array.isArray(data) ? data : data.items || []\n this._setItems(items)\n return items\n }\n\n async list(options: ListOptions = {}): Promise<T[]> {\n await this._registerSchema()\n const params = new URLSearchParams()\n if (options.limit !== undefined) params.set('limit', String(options.limit))\n if (options.offset !== undefined) params.set('offset', String(options.offset))\n if (options.filter) {\n for (const [key, value] of Object.entries(options.filter)) {\n if (value !== undefined && value !== null) {\n params.set(key, String(value))\n }\n }\n }\n const queryString = params.toString()\n const url = `${this._baseUrl}/api/${this._namespace}/${this.$type}${queryString ? `?${queryString}` : ''}`\n const res = await fetch(url)\n if (!res.ok) {\n throw new APIError('GENERATION_FAILED', `Failed to list ${this.$type}: ${await res.text()}`, res.status)\n }\n const data = await res.json()\n const items = Array.isArray(data) ? data : data.items || []\n this._setItems(items)\n return items\n }\n\n async get(id: string): Promise<T | undefined> {\n await this._registerSchema()\n const url = `${this._baseUrl}/api/${this._namespace}/${this.$type}/${id}`\n const res = await fetch(url)\n if (res.status === 404) {\n return undefined\n }\n if (!res.ok) {\n throw new APIError('GENERATION_FAILED', `Failed to get ${this.$type}/${id}: ${await res.text()}`, res.status)\n }\n return await res.json()\n }\n\n async create(data: Partial<T>): Promise<T> {\n await this._registerSchema()\n const url = `${this._baseUrl}/api/${this._namespace}/${this.$type}`\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n })\n if (!res.ok) {\n throw new APIError('GENERATION_FAILED', `Failed to create ${this.$type}: ${await res.text()}`, res.status)\n }\n const created = await res.json()\n this._addItem(created)\n return created\n }\n}\n\n/**\n * Create a callable EntityCollection using a Proxy.\n * The returned object is both a function (factory) and has collection methods/properties.\n */\nfunction createEntityCollection<T extends Record<string, unknown>>(\n typeName: string,\n baseUrl: string,\n namespace: string,\n registerSchema: () => Promise<void>,\n factory: (id: string, context?: Record<string, unknown>) => Promise<T>\n): EntityCollection<T> {\n const collection = new EntityCollectionImpl<T>(typeName, baseUrl, namespace, registerSchema)\n\n // Create a proxy around the factory function\n return new Proxy(factory, {\n get(target, prop) {\n // Handle Symbol.iterator for iteration\n if (prop === Symbol.iterator) {\n return () => collection[Symbol.iterator]()\n }\n\n // Return collection properties and methods\n if (prop === '$type') return collection.$type\n if (prop === '$count') return collection.$count\n if (prop === 'forEach') return collection.forEach.bind(collection)\n if (prop === 'map') return collection.map.bind(collection)\n if (prop === 'where') return collection.where.bind(collection)\n if (prop === 'fetchAll') return collection.fetchAll.bind(collection)\n if (prop === 'list') return collection.list.bind(collection)\n if (prop === 'get') return collection.get.bind(collection)\n if (prop === 'create') return collection.create.bind(collection)\n\n // Internal methods for testing/manipulation\n if (prop === '_addItem') return collection._addItem.bind(collection)\n if (prop === '_setItems') return collection._setItems.bind(collection)\n if (prop === '_getItems') return collection._getItems.bind(collection)\n\n return undefined\n },\n apply(target, thisArg, args) {\n // When called as a function, invoke the factory\n return factory(args[0] as string, args[1] as Record<string, unknown> | undefined)\n },\n }) as EntityCollection<T>\n}\n\n// Instance type for generated objects\nexport interface DBInstance<T = Record<string, unknown>> {\n id: string\n type: string\n data: T\n}\n\n// Generated object with all fields resolved\nexport type GeneratedObject = Record<string, unknown>\n\n// Factory function type - async for API-based generation\nexport type TypeFactory = (id: string, context?: Record<string, unknown>) => Promise<GeneratedObject>\n\n// Base properties of DBResult (non-dynamic)\nexport interface DBResultBase {\n schema: SchemaDefinition\n types: Record<string, ParsedType>\n hash: string\n id?: string // Full $id if specified\n context?: string // Shared context/namespace (from $context or parsed from $id)\n namespace: string // The resolved namespace (always present)\n baseUrl: string // API base URL (from $id or default)\n instances: DBInstance[] // Collected instances defined with this schema\n toJSONSchema: (typeName: string) => JSONSchema\n registerSchema: () => Promise<void> // Manually register schema with API\n}\n\n// Return type for DB function\n// Dynamic type accessor - generates objects via API\n// Usage: await db.Blog('my-blog', { topic: '...' }) -> GeneratedObject\n// Also works as collection: for (const blog of db.Blog) { ... }\nexport type DBResult = DBResultBase & Record<string, EntityCollection>\n\n/**\n * Extract API base URL from $id\n * @example\n * getApiBaseFromId('https://db.sb/blogs') // 'https://db.sb'\n * getApiBaseFromId('https://startups.db.sb') // 'https://startups.db.sb'\n * getApiBaseFromId('my-namespace') // undefined (use default)\n */\nfunction getApiBaseFromId(id: string): string | undefined {\n // If it's not a URL, return undefined to use default\n if (!id.startsWith('http://') && !id.startsWith('https://')) {\n return undefined\n }\n try {\n const url = new URL(id)\n return `${url.protocol}//${url.host}`\n } catch {\n return undefined\n }\n}\n\n/**\n * Parse namespace from $id - supports both full URLs and plain namespace strings\n * @example\n * parseIdNamespace('https://db.sb/blogs') // 'blogs'\n * parseIdNamespace('my-namespace') // 'my-namespace'\n * parseIdNamespace('https://db.sb/') // null\n */\nfunction parseIdNamespace(id: string): string | null {\n // If it's not a URL, treat the whole string as the namespace\n if (!id.startsWith('http://') && !id.startsWith('https://')) {\n const trimmed = id.trim()\n return trimmed || null\n }\n // Otherwise parse as URL\n return parseNamespaceFromId(id)\n}\n\n/**\n * Resolve all references in a generated object recursively\n */\nasync function resolveReferences(\n obj: GeneratedObject,\n typeName: string,\n parsed: ParsedSchema,\n baseUrl: string,\n namespace: string,\n cache: Map<string, GeneratedObject>\n): Promise<GeneratedObject> {\n const type = parsed.types[typeName]\n if (!type) return obj\n\n const resolved: GeneratedObject = { ...obj }\n\n for (const [fieldName, field] of Object.entries(type.fields)) {\n const value = obj[fieldName]\n if (value === undefined || value === null) continue\n\n if (field.type === 'array' && field.refs && Array.isArray(value)) {\n // Inline references: ['... ->Type'] - resolve each ID to full object\n const refType = field.refs[0]\n const resolvedItems = await Promise.all(\n (value as string[]).map(async (refId) => {\n const cacheKey = `${refType}:${refId}`\n if (cache.has(cacheKey)) return cache.get(cacheKey)!\n\n // If refId is already a URL, use it directly; otherwise construct URL\n const refUrl = refId.startsWith('http://') || refId.startsWith('https://')\n ? refId\n : `${baseUrl}/api/${namespace}/${refType}/${refId}`\n const refRes = await fetch(refUrl)\n if (!refRes.ok) return { id: refId, _error: 'Failed to resolve' }\n\n const refObj = await refRes.json()\n cache.set(cacheKey, refObj)\n\n // Recursively resolve nested references\n return resolveReferences(refObj, refType, parsed, baseUrl, namespace, cache)\n })\n )\n resolved[fieldName] = resolvedItems\n } else if (field.type === 'reference' && !field.isArray && typeof value === 'string') {\n // Single reference: ->Type - resolve to full object\n const refType = field.ref || field.refs?.[0]\n if (refType) {\n const cacheKey = `${refType}:${value}`\n if (cache.has(cacheKey)) {\n resolved[fieldName] = cache.get(cacheKey)!\n } else {\n // If value is already a URL, use it directly; otherwise construct URL\n const refUrl = value.startsWith('http://') || value.startsWith('https://')\n ? value\n : `${baseUrl}/api/${namespace}/${refType}/${value}`\n const refRes = await fetch(refUrl)\n if (refRes.ok) {\n const refObj = await refRes.json()\n cache.set(cacheKey, refObj)\n resolved[fieldName] = await resolveReferences(refObj, refType, parsed, baseUrl, namespace, cache)\n }\n }\n }\n } else if (field.type === 'reference' && field.isArray && Array.isArray(value)) {\n // Array reference: ->Type[] - resolve each ID to full object\n const refType = field.ref || field.refs?.[0]\n if (refType) {\n const resolvedItems = await Promise.all(\n (value as string[]).map(async (refId) => {\n const cacheKey = `${refType}:${refId}`\n if (cache.has(cacheKey)) return cache.get(cacheKey)!\n\n // If refId is already a URL, use it directly; otherwise construct URL\n const refUrl = refId.startsWith('http://') || refId.startsWith('https://')\n ? refId\n : `${baseUrl}/api/${namespace}/${refType}/${refId}`\n const refRes = await fetch(refUrl)\n if (!refRes.ok) return { id: refId, _error: 'Failed to resolve' }\n\n const refObj = await refRes.json()\n cache.set(cacheKey, refObj)\n return resolveReferences(refObj, refType, parsed, baseUrl, namespace, cache)\n })\n )\n resolved[fieldName] = resolvedItems\n }\n }\n // Back references (['<-Type']) are populated by the API, no client-side resolution needed\n }\n\n return resolved\n}\n\n/**\n * Create a database instance from a schema definition.\n *\n * This is the main entry point for defining and working with a db4.ai schema.\n * It parses the schema, registers it with the API, and returns a typed object\n * that provides access to all defined types as EntityCollections.\n *\n * ## API Base URL Configuration\n *\n * The SDK determines the API base URL in the following priority order:\n * 1. Host from `$id` if it's a full URL (e.g., `'https://custom.api.com/myapp'`)\n * 2. `DB4AI_API_BASE` environment variable\n * 3. Default: `'https://db4ai.dev'`\n *\n * @param schema - The schema definition object. Must include either:\n * - `$id` - A URL or namespace identifier (e.g., `'https://db.sb/blog'` or `'blog'`)\n * - `$context` - A namespace string (e.g., `'my-app'`)\n *\n * Type definitions are records where keys are type names and values define fields.\n *\n * @returns A DBResult object providing:\n * - `schema` - The original schema definition\n * - `types` - Parsed type definitions\n * - `hash` - Schema version hash\n * - `namespace` - The resolved namespace\n * - `baseUrl` - API base URL\n * - `toJSONSchema(typeName)` - Convert a type to JSON Schema\n * - `registerSchema()` - Manually register the schema with the API\n * - Dynamic type accessors (e.g., `db.Post`, `db.User`) as EntityCollections\n *\n * @throws Error if neither `$id` nor `$context` is provided\n *\n * @example\n * // Define a blog schema\n * const db = DB({\n * $context: 'blog',\n * Post: {\n * title: 'Post title',\n * content: 'Main content',\n * author: '->User',\n * tags: ['List 3-5 keywords']\n * },\n * User: {\n * name: 'User name',\n * email: 'Email address'\n * }\n * })\n *\n * @example\n * // Generate a new post\n * const post = await db.Post('my-first-post', { topic: 'AI' })\n * console.log(post.title, post.content)\n *\n * @example\n * // Fetch all posts and iterate\n * await db.Post.fetchAll()\n * for (const post of db.Post) {\n * console.log(post.title)\n * }\n *\n * @example\n * // Use with full URL\n * const db = DB({\n * $id: 'https://db.sb/startups',\n * Company: {\n * name: 'Company name',\n * description: 'Company description'\n * }\n * })\n */\nexport function DB(schema: SchemaDefinition) {\n const parsed = parseSchema(schema)\n const metadata = schema as SchemaMetadata\n const schemaId = metadata.$id\n const schemaContext = metadata.$context\n\n // Either $id or $context is required\n if (!schemaId && !schemaContext) {\n throw new SchemaValidationError('MISSING_CONTEXT', 'Schema must have $id or $context set (e.g., $context: \"my-app\" or $id: \"https://db4ai.dev/my-app\")')\n }\n\n // Parse namespace from $id (URL or plain string) or use $context directly\n let namespace: string | null = null\n let baseUrl: string = getDefaultApiBase()\n\n if (schemaContext) {\n // $context is always just a namespace, uses default base URL\n namespace = schemaContext.trim() || null\n }\n\n if (schemaId) {\n // $id can be a full URL or plain namespace\n namespace = parseIdNamespace(schemaId)\n // Use $id's host if it's a URL (overrides default/env var)\n const idBaseUrl = getApiBaseFromId(schemaId)\n if (idBaseUrl) {\n baseUrl = idBaseUrl\n }\n }\n\n if (!namespace) {\n throw new SchemaValidationError('MISSING_NAMESPACE', 'Schema must specify a namespace via $context or $id (e.g., $context: \"my-app\")')\n }\n\n const instances: DBInstance[] = []\n\n // Track schema registration state\n let schemaRegistered = false\n let schemaRegistrationPromise: Promise<void> | null = null\n\n // Register schema with API (idempotent, cached)\n async function registerSchema(): Promise<void> {\n if (schemaRegistered) return\n if (schemaRegistrationPromise) return schemaRegistrationPromise\n\n schemaRegistrationPromise = (async () => {\n const res = await fetch(`${baseUrl}/api/${namespace}/schema`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(schema),\n })\n\n if (!res.ok) {\n const error = await res.text()\n throw new APIError('REGISTRATION_FAILED', `Failed to register schema: ${error}`, res.status)\n }\n\n schemaRegistered = true\n })()\n\n return schemaRegistrationPromise\n }\n\n // Create base result object\n const base = {\n schema,\n types: parsed.types,\n hash: parsed.hash,\n id: schemaId,\n context: schemaContext,\n namespace,\n baseUrl,\n instances,\n registerSchema,\n toJSONSchema: (typeName: string) => {\n const type = parsed.types[typeName]\n if (!type) throw new SchemaValidationError('INVALID_FIELD_TYPE', `Unknown type: ${typeName}`)\n return toJSONSchema(type, parsed)\n },\n }\n\n // Cache EntityCollections so the same instance is returned each time\n const collectionCache = new Map<string, EntityCollection>()\n\n // Create a proxy that handles dynamic type access\n return new Proxy(base, {\n get(target, prop) {\n // Return known properties directly\n if (prop in target) {\n return target[prop as keyof typeof target]\n }\n\n // For type names, return an EntityCollection (cached)\n const typeName = String(prop)\n if (parsed.types[typeName]) {\n // Return cached collection if exists\n if (collectionCache.has(typeName)) {\n return collectionCache.get(typeName)!\n }\n\n // Create factory function for this type\n const factory = async (id: string, context?: Record<string, unknown>): Promise<GeneratedObject> => {\n // Ensure schema is registered\n await registerSchema()\n\n // Build URL with context as query params if provided\n let url = `${baseUrl}/api/${namespace}/${typeName}/${id}`\n if (context && Object.keys(context).length > 0) {\n const params = new URLSearchParams()\n for (const [key, value] of Object.entries(context)) {\n if (value !== undefined && value !== null) {\n params.set(key, String(value))\n }\n }\n url += `?${params.toString()}`\n }\n\n // Fetch/generate the object with extended timeout for long-running generations\n // Default Node.js undici timeout is 300s, but Blog generation can take 80-150s\n // We use 10 minutes to handle complex hierarchies with AI latency variance\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), 600000) // 10 minute timeout\n try {\n const res = await fetch(url, { signal: controller.signal })\n clearTimeout(timeoutId)\n if (!res.ok) {\n const error = await res.text()\n throw new APIError('GENERATION_FAILED', `Failed to generate ${typeName}/${id}: ${error}`, res.status)\n }\n\n const obj = await res.json()\n\n // Resolve all references recursively\n const cache = new Map<string, GeneratedObject>()\n return resolveReferences(obj, typeName, parsed, baseUrl, namespace, cache)\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n // Create and cache the EntityCollection\n const collection = createEntityCollection(typeName, baseUrl, namespace, registerSchema, factory)\n collectionCache.set(typeName, collection)\n return collection\n }\n return undefined\n },\n }) as DBResult\n}\n\n// ============================================================================\n// Combinable: Lazy cartesian product pipeline builder\n// ============================================================================\n\n/**\n * A lazy pipeline builder for cartesian products and collection transformations.\n *\n * Combinable provides a fluent API for building transformation pipelines where\n * no computation happens until a terminal operation is invoked. This enables\n * efficient processing of large datasets and cartesian products.\n *\n * Key features:\n * - Lazy evaluation: transformations are only applied when results are consumed\n * - Chainable: all intermediate operations return new Combinable instances\n * - Iterable: works with for...of loops and spread operator\n *\n * Intermediate operations (return Combinable):\n * - `where(predicate)` - Filter items by predicate\n * - `map(fn)` - Transform each item\n * - `take(n)` - Limit to first n items\n * - `skip(n)` - Skip first n items\n *\n * Terminal operations (trigger evaluation):\n * - `all()` - Collect all results into an array\n * - `first()` - Get the first result or undefined\n * - `count()` - Count total results\n * - Iteration via for...of or spread\n *\n * @example\n * // Basic cartesian product\n * const pairs = combine([1, 2, 3], ['a', 'b']).all()\n * // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b'], [3, 'a'], [3, 'b']]\n *\n * @example\n * // Chained transformations\n * const result = combine([1, 2, 3], [10, 20, 30])\n * .where(([a, b]) => a + b > 15)\n * .map(([a, b]) => a * b)\n * .take(3)\n * .all()\n * // [20, 30, 40]\n *\n * @example\n * // Lazy evaluation with for...of\n * for (const [x, y] of combine(range(1000), range(1000)).take(10)) {\n * console.log(x, y) // Only computes first 10 pairs\n * }\n *\n * @example\n * // From EntityCollection\n * await db.User.fetchAll()\n * const activeUsers = db.User\n * .where(user => user.isActive)\n * .map(user => user.email)\n * .all()\n */\nexport class Combinable<T> implements Iterable<T> {\n private readonly source: () => Generator<T>\n\n constructor(source: () => Generator<T>) {\n this.source = source\n }\n\n /**\n * Filter combinations by predicate\n */\n where(predicate: (item: T) => boolean): Combinable<T> {\n const source = this.source\n return new Combinable(function* () {\n for (const item of source()) {\n if (predicate(item)) {\n yield item\n }\n }\n })\n }\n\n /**\n * Transform each combination\n */\n map<R>(fn: (item: T) => R): Combinable<R> {\n const source = this.source\n return new Combinable(function* () {\n for (const item of source()) {\n yield fn(item)\n }\n })\n }\n\n /**\n * Limit to first n items\n */\n take(n: number): Combinable<T> {\n const source = this.source\n return new Combinable(function* () {\n let count = 0\n for (const item of source()) {\n if (count >= n) break\n yield item\n count++\n }\n })\n }\n\n /**\n * Skip first n items\n */\n skip(n: number): Combinable<T> {\n const source = this.source\n return new Combinable(function* () {\n let count = 0\n for (const item of source()) {\n if (count >= n) {\n yield item\n }\n count++\n }\n })\n }\n\n /**\n * Collect all results into an array (terminal operation)\n */\n all(): T[] {\n return [...this.source()]\n }\n\n /**\n * Get the first result or undefined (terminal operation)\n */\n first(): T | undefined {\n const iterator = this.source()\n const result = iterator.next()\n return result.done ? undefined : result.value\n }\n\n /**\n * Count total results (terminal operation)\n */\n count(): number {\n let count = 0\n for (const _ of this.source()) {\n count++\n }\n return count\n }\n\n /**\n * Make Combinable iterable with for...of and spread operator\n */\n [Symbol.iterator](): Iterator<T> {\n return this.source()\n }\n}\n\n// Overloaded combine function signatures for type inference\nexport function combine<A, B>(a: Iterable<A>, b: Iterable<B>): Combinable<[A, B]>\nexport function combine<A, B, C>(a: Iterable<A>, b: Iterable<B>, c: Iterable<C>): Combinable<[A, B, C]>\nexport function combine<A, B, C, D>(a: Iterable<A>, b: Iterable<B>, c: Iterable<C>, d: Iterable<D>): Combinable<[A, B, C, D]>\nexport function combine<A, B, C, D, E>(a: Iterable<A>, b: Iterable<B>, c: Iterable<C>, d: Iterable<D>, e: Iterable<E>): Combinable<[A, B, C, D, E]>\n\n/**\n * Create cartesian product of multiple iterables.\n * Returns a lazy Combinable that only computes when iterated or terminal operation is called.\n *\n * @example\n * const result = combine([1, 2], ['a', 'b']).all()\n * // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]\n *\n * @example\n * const filtered = combine([1, 2, 3], [10, 20])\n * .where(([a, b]) => a + b > 20)\n * .map(([a, b]) => a * b)\n * .all()\n */\nexport function combine(...iterables: Iterable<unknown>[]): Combinable<unknown[]> {\n // Convert iterables to arrays lazily (we need to iterate multiple times)\n // This is done inside the generator to maintain laziness\n return new Combinable(function* () {\n if (iterables.length === 0) return\n\n // Convert to arrays (required for cartesian product - need multiple passes)\n const arrays = iterables.map((it) => [...it])\n\n // Check for empty arrays - cartesian product with empty set is empty\n if (arrays.some((arr) => arr.length === 0)) return\n\n // Generate cartesian product using indices\n const indices = new Array(arrays.length).fill(0)\n const maxIndices = arrays.map((arr) => arr.length)\n\n while (true) {\n // Yield current combination\n yield indices.map((i, j) => arrays[j][i])\n\n // Increment indices (like counting in mixed radix)\n let carry = true\n for (let i = indices.length - 1; i >= 0 && carry; i--) {\n indices[i]++\n if (indices[i] >= maxIndices[i]) {\n indices[i] = 0\n } else {\n carry = false\n }\n }\n\n // If we carried all the way, we're done\n if (carry) break\n }\n })\n}\n\n// ============================================================================\n// MDX Frontmatter Parser\n// ============================================================================\n\n/**\n * Result of parsing MDX frontmatter\n */\nexport interface ParseMDXResult {\n /** Parsed schema definition from YAML frontmatter */\n schema: SchemaDefinition\n /** Remaining MDX body after frontmatter */\n body: string\n}\n\n/**\n * Simple YAML parser for frontmatter\n * Handles the subset of YAML commonly used in MDX frontmatter:\n * - Key-value pairs (string values)\n * - Nested objects (indentation-based)\n * - Arrays with bracket notation [item1, item2]\n * - Comments (# ...)\n * - Multiline strings with | and >\n */\nfunction parseYAML(yaml: string): Record<string, unknown> {\n // Normalize line endings to LF\n const normalized = yaml.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n')\n const lines = normalized.split('\\n')\n const result: Record<string, unknown> = {}\n\n // Stack for tracking nested objects: [{ obj, indent }]\n const stack: { obj: Record<string, unknown>; indent: number }[] = [{ obj: result, indent: -1 }]\n\n // State for multiline strings\n let multilineKey: string | null = null\n let multilineIndent = 0\n let multilineLines: string[] = []\n let multilineStyle: '|' | '>' | null = null\n\n for (let lineNum = 0; lineNum < lines.length; lineNum++) {\n const rawLine = lines[lineNum]\n\n // Handle multiline string continuation\n if (multilineKey !== null) {\n // Check if this line continues the multiline string\n const lineIndent = rawLine.match(/^(\\s*)/)?.[1].length ?? 0\n if (lineIndent >= multilineIndent && (rawLine.trim() !== '' || multilineLines.length > 0)) {\n // This is a continuation of the multiline string\n multilineLines.push(rawLine.slice(multilineIndent))\n continue\n } else {\n // End of multiline string - set the value\n const current = stack[stack.length - 1]\n if (multilineStyle === '|') {\n // Literal block - preserve newlines\n current.obj[multilineKey] = multilineLines.join('\\n')\n } else {\n // Folded block - join with spaces (single newlines become spaces)\n current.obj[multilineKey] = multilineLines.join(' ').replace(/\\s+/g, ' ').trim()\n }\n multilineKey = null\n multilineLines = []\n multilineStyle = null\n }\n }\n\n // Remove comments (but not inside quoted strings)\n let line = rawLine\n // Simple comment removal - find # that's not inside quotes\n const hashIndex = line.indexOf('#')\n if (hashIndex !== -1) {\n // Check if it's inside quotes by counting quotes before it\n const beforeHash = line.slice(0, hashIndex)\n const singleQuotes = (beforeHash.match(/'/g) || []).length\n const doubleQuotes = (beforeHash.match(/\"/g) || []).length\n if (singleQuotes % 2 === 0 && doubleQuotes % 2 === 0) {\n line = line.slice(0, hashIndex)\n }\n }\n\n // Skip empty lines\n if (line.trim() === '') continue\n\n // Calculate indentation\n const indentMatch = line.match(/^(\\s*)/)\n const indent = indentMatch ? indentMatch[1].length : 0\n const content = line.trim()\n\n // Pop stack back to appropriate level\n while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {\n stack.pop()\n }\n\n // Parse key-value pair\n const colonIndex = content.indexOf(':')\n if (colonIndex === -1) {\n throw new Error(`Invalid YAML at line ${lineNum + 1}: expected key-value pair, got \"${content}\"`)\n }\n\n const key = content.slice(0, colonIndex).trim()\n let value = content.slice(colonIndex + 1).trim()\n\n // Validate key\n if (!key) {\n throw new Error(`Invalid YAML at line ${lineNum + 1}: empty key`)\n }\n\n const current = stack[stack.length - 1]\n\n // Handle multiline string indicators\n if (value === '|' || value === '>') {\n multilineKey = key\n multilineStyle = value as '|' | '>'\n multilineIndent = indent + 2 // Expect content indented from the key\n multilineLines = []\n continue\n }\n\n if (value === '') {\n // No value - this is a nested object\n const nested: Record<string, unknown> = {}\n current.obj[key] = nested\n stack.push({ obj: nested, indent })\n } else if (value.startsWith('[') && !value.endsWith(']')) {\n // Unclosed array bracket\n throw new Error(`Invalid YAML at line ${lineNum + 1}: unclosed array bracket in \"${content}\"`)\n } else if (value.startsWith('[') && value.endsWith(']')) {\n // Array notation: [item1, item2, ...]\n const arrayContent = value.slice(1, -1).trim()\n if (arrayContent === '') {\n current.obj[key] = []\n } else {\n // Parse array items - handle quoted strings and unquoted values\n const items: string[] = []\n let currentItem = ''\n let inQuote: string | null = null\n for (let i = 0; i < arrayContent.length; i++) {\n const char = arrayContent[i]\n if (inQuote) {\n if (char === inQuote) {\n inQuote = null\n } else {\n currentItem += char\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char\n } else if (char === ',') {\n items.push(currentItem.trim())\n currentItem = ''\n } else {\n currentItem += char\n }\n }\n if (currentItem.trim()) {\n items.push(currentItem.trim())\n }\n current.obj[key] = items\n }\n } else {\n // String value - remove surrounding quotes if present\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1)\n }\n current.obj[key] = value\n }\n }\n\n // Handle any remaining multiline string\n if (multilineKey !== null) {\n const current = stack[stack.length - 1]\n if (multilineStyle === '|') {\n current.obj[multilineKey] = multilineLines.join('\\n')\n } else {\n current.obj[multilineKey] = multilineLines.join(' ').replace(/\\s+/g, ' ').trim()\n }\n }\n\n return result\n}\n\n/**\n * Parse MDX frontmatter and extract schema definition.\n *\n * @param mdx - The MDX content with optional YAML frontmatter\n * @returns Object with parsed schema and remaining body\n * @throws Error if YAML syntax is invalid\n *\n * @example\n * const mdx = `---\n * $context: https://db.sb\n * Idea:\n * concept: What is the concept?\n * ---\n *\n * <App>content</App>`\n *\n * const { schema, body } = parseMDX(mdx)\n * // schema = { $context: 'https://db.sb', Idea: { concept: 'What is the concept?' } }\n * // body = '\\n<App>content</App>'\n */\nexport function parseMDX(mdx: string): ParseMDXResult {\n // Normalize line endings\n const normalized = mdx.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n')\n\n // Check if MDX starts with frontmatter delimiter\n if (!normalized.startsWith('---')) {\n // No frontmatter - return empty schema and full content as body\n return {\n schema: {},\n body: mdx,\n }\n }\n\n // Find the closing frontmatter delimiter\n // Start searching after the first ---\n const startIndex = 3 // Length of '---'\n let endIndex = -1\n\n // Look for --- at the start of a line (after a newline)\n let searchStart = startIndex\n while (searchStart < normalized.length) {\n const newlineIndex = normalized.indexOf('\\n', searchStart)\n if (newlineIndex === -1) break\n\n // Check if the next line starts with ---\n if (normalized.slice(newlineIndex + 1, newlineIndex + 4) === '---') {\n // Verify it's actually the closing delimiter (followed by newline or EOF)\n const afterDash = normalized[newlineIndex + 4]\n if (afterDash === undefined || afterDash === '\\n' || afterDash === '\\r') {\n endIndex = newlineIndex + 1\n break\n }\n }\n searchStart = newlineIndex + 1\n }\n\n if (endIndex === -1) {\n throw new Error('Invalid MDX: unclosed frontmatter (missing closing ---)')\n }\n\n // Extract frontmatter YAML (between the two --- markers)\n const frontmatter = normalized.slice(startIndex, endIndex).trim()\n\n // Extract body (everything after the closing ---)\n const bodyStart = endIndex + 3 // Skip past ---\n let body = normalized.slice(bodyStart)\n\n // Remove leading newline from body if present (but preserve rest of whitespace)\n if (body.startsWith('\\n')) {\n body = body.slice(1)\n }\n\n // Parse YAML frontmatter\n let schema: SchemaDefinition\n if (frontmatter === '') {\n // Empty frontmatter\n schema = {}\n } else {\n try {\n schema = parseYAML(frontmatter) as SchemaDefinition\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Invalid YAML in frontmatter: ${error.message}`)\n }\n throw error\n }\n }\n\n return { schema, body }\n}\n\n// ============================================================================\n// JSX UI Specification Parser\n// ============================================================================\n\nimport { parse as babelParse } from '@babel/parser'\nimport type {\n JSXElement,\n JSXFragment,\n JSXText,\n JSXExpressionContainer,\n JSXSpreadChild,\n JSXMemberExpression,\n Expression,\n ObjectExpression,\n ArrayExpression,\n SpreadElement,\n StringLiteral,\n NumericLiteral,\n BooleanLiteral,\n NullLiteral,\n Identifier,\n ArrowFunctionExpression,\n FunctionExpression,\n ObjectProperty,\n Node,\n} from '@babel/types'\n\n/**\n * Hook context passed to entity hooks\n */\nexport interface HookContext {\n generate: (types: string | string[]) => Promise<void>\n changed?: Record<string, boolean>\n}\n\n/**\n * Entity lifecycle hooks\n */\nexport interface EntityHooks {\n onCreate?: (entity: unknown, ctx: HookContext) => Promise<void>\n onUpdate?: (entity: unknown, ctx: HookContext) => Promise<void>\n onDelete?: (entity: unknown) => Promise<void>\n}\n\n/**\n * Navigation group in the sidebar\n */\nexport interface NavigationGroup {\n name: string\n icon?: string\n children: (NavigationGroup | string)[] // string = collection name\n}\n\n/**\n * Field configuration from <Field> elements\n */\nexport interface FieldConfig {\n name: string\n lines?: number\n placeholder?: string\n display?: 'card' | 'link' | 'inline'\n allowCreate?: boolean\n searchable?: boolean\n preview?: string[]\n collapsed?: boolean\n readOnly?: boolean\n required?: boolean\n min?: number\n max?: number\n span?: number\n autoFocus?: boolean\n}\n\n/**\n * Section configuration from <Section> elements\n */\nexport interface SectionConfig {\n label: string\n collapsed?: boolean\n children?: (FieldConfig | SectionConfig)[]\n}\n\n/**\n * Search configuration from <Search> elements\n */\nexport interface SearchConfig {\n fields?: string[]\n}\n\n/**\n * Filter configuration from <Filter> elements\n */\nexport interface FilterConfig {\n field: string\n exists?: boolean\n}\n\n/**\n * Action configuration for generate/built-in actions\n */\nexport interface ActionConfig {\n type: 'generate' | 'delete' | 'duplicate' | 'export' | 'import'\n entity?: string // For generate actions\n context?: string[] // For generate actions\n confirm?: string // For delete\n formats?: string[] // For export\n}\n\n/**\n * Role-based permission configuration\n */\nexport interface RoleConfig {\n name: string\n actions: string[]\n}\n\n/**\n * Template configuration for Cards/Detail views\n */\nexport interface TemplateConfig {\n jsx: string // Preserved JSX string for runtime rendering\n}\n\n/**\n * Form configuration from <Form> elements\n */\nexport interface FormConfig {\n layout?: 'stack' | 'grid'\n fields?: string[] // Quick form with just field names\n children?: (FieldConfig | SectionConfig)[]\n}\n\n/**\n * Display component configuration\n */\nexport interface DisplayConfig {\n type: 'table' | 'grid' | 'cards'\n columns?: string[]\n sortable?: boolean\n template?: TemplateConfig\n}\n\n/**\n * View configuration (List, Detail, Edit, Create)\n */\nexport interface ViewConfig {\n search?: SearchConfig\n filters?: FilterConfig[]\n display?: DisplayConfig\n form?: FormConfig\n template?: TemplateConfig\n editor?: { language: string }\n}\n\n/**\n * Collection configuration for a schema type\n */\nexport interface CollectionConfig {\n view?: 'table' | 'cards' | 'grid'\n columns?: string[]\n searchable?: boolean\n path?: string\n slug?: string\n list?: ViewConfig\n detail?: ViewConfig\n edit?: ViewConfig\n create?: ViewConfig\n actions?: ActionConfig[]\n permissions?: RoleConfig[]\n hooks?: EntityHooks\n}\n\n/**\n * Complete UI configuration parsed from JSX\n */\nexport interface UIConfig {\n hooks: Record<string, EntityHooks>\n navigation: NavigationGroup[]\n collections: Record<string, CollectionConfig>\n}\n\n// Babel type guard helpers\ntype JSXChild = JSXElement | JSXFragment | JSXText | JSXExpressionContainer | JSXSpreadChild\n\nfunction isJSXElement(node: Node | null | undefined): node is JSXElement {\n return node?.type === 'JSXElement'\n}\n\nfunction isObjectExpression(node: Node | null | undefined): node is ObjectExpression {\n return node?.type === 'ObjectExpression'\n}\n\nfunction isArrayExpression(node: Node | null | undefined): node is ArrayExpression {\n return node?.type === 'ArrayExpression'\n}\n\nfunction isStringLiteral(node: Node | null | undefined): node is StringLiteral {\n return node?.type === 'StringLiteral'\n}\n\nfunction isNumericLiteral(node: Node | null | undefined): node is NumericLiteral {\n return node?.type === 'NumericLiteral'\n}\n\nfunction isBooleanLiteral(node: Node | null | undefined): node is BooleanLiteral {\n return node?.type === 'BooleanLiteral'\n}\n\nfunction isNullLiteral(node: Node | null | undefined): node is NullLiteral {\n return node?.type === 'NullLiteral'\n}\n\nfunction isIdentifier(node: Node | null | undefined): node is Identifier {\n return node?.type === 'Identifier'\n}\n\nfunction isArrowFunctionExpression(node: Node | null | undefined): node is ArrowFunctionExpression {\n return node?.type === 'ArrowFunctionExpression'\n}\n\nfunction isFunctionExpression(node: Node | null | undefined): node is FunctionExpression {\n return node?.type === 'FunctionExpression'\n}\n\nfunction isObjectProperty(node: Node | null | undefined): node is ObjectProperty {\n return node?.type === 'ObjectProperty'\n}\n\n/**\n * Get the element name from a JSX element\n */\nfunction getElementName(element: JSXElement): string {\n const name = element.openingElement.name\n if (name.type === 'JSXIdentifier') {\n return name.name\n }\n if (name.type === 'JSXMemberExpression') {\n // Handle Member.Expression style names\n const parts: string[] = []\n let current: JSXMemberExpression['object'] = name\n while (current.type === 'JSXMemberExpression') {\n parts.unshift(current.property.name)\n current = current.object\n }\n if (current.type === 'JSXIdentifier') {\n parts.unshift(current.name)\n }\n return parts.join('.')\n }\n return ''\n}\n\n/**\n * Extract props from a JSX element\n */\nfunction extractProps(element: JSXElement, sourceCode: string): Record<string, unknown> {\n const props: Record<string, unknown> = {}\n\n for (const attr of element.openingElement.attributes) {\n if (attr.type === 'JSXAttribute') {\n const name = attr.name.type === 'JSXIdentifier' ? attr.name.name : String(attr.name.name)\n const value = attr.value\n\n if (value === null || value === undefined) {\n // Boolean prop: <Field searchable />\n props[name] = true\n } else if (value.type === 'StringLiteral') {\n props[name] = value.value\n } else if (value.type === 'JSXExpressionContainer') {\n props[name] = evaluateExpression(value.expression, sourceCode)\n }\n } else if (attr.type === 'JSXSpreadAttribute') {\n // Handle spread attributes if needed\n const spreadValue = evaluateExpression(attr.argument, sourceCode)\n if (typeof spreadValue === 'object' && spreadValue !== null) {\n Object.assign(props, spreadValue)\n }\n }\n }\n\n return props\n}\n\n/**\n * Evaluate a JSX expression to a JavaScript value\n */\nfunction evaluateExpression(\n expr: Expression | JSXExpressionContainer['expression'],\n sourceCode: string\n): unknown {\n if (expr.type === 'JSXEmptyExpression') {\n return undefined\n }\n\n if (isStringLiteral(expr)) {\n return expr.value\n }\n\n if (isNumericLiteral(expr)) {\n return expr.value\n }\n\n if (isBooleanLiteral(expr)) {\n return expr.value\n }\n\n if (isNullLiteral(expr)) {\n return null\n }\n\n if (isIdentifier(expr)) {\n // Handle special identifiers\n if (expr.name === 'undefined') return undefined\n if (expr.name === 'true') return true\n if (expr.name === 'false') return false\n // Return identifier name as string (for field references)\n return expr.name\n }\n\n if (isArrayExpression(expr)) {\n return expr.elements.map((el: Expression | SpreadElement | null) => {\n if (el === null) return null\n if (el.type === 'SpreadElement') {\n return evaluateExpression(el.argument, sourceCode)\n }\n return evaluateExpression(el, sourceCode)\n })\n }\n\n if (isObjectExpression(expr)) {\n const obj: Record<string, unknown> = {}\n for (const prop of expr.properties) {\n if (isObjectProperty(prop)) {\n const key = isIdentifier(prop.key)\n ? prop.key.name\n : isStringLiteral(prop.key)\n ? prop.key.value\n : String(prop.key)\n obj[key] = evaluateExpression(prop.value as Expression, sourceCode)\n }\n // ObjectMethod handling for hooks\n if (prop.type === 'ObjectMethod') {\n const key = isIdentifier(prop.key)\n ? prop.key.name\n : isStringLiteral(prop.key)\n ? prop.key.value\n : String(prop.key)\n // Preserve function as source code string\n if (prop.start !== null && prop.end !== null) {\n obj[key] = sourceCode.slice(prop.start, prop.end)\n }\n }\n }\n return obj\n }\n\n if (isArrowFunctionExpression(expr) || isFunctionExpression(expr)) {\n // Preserve function source for hooks\n if (expr.start !== null && expr.end !== null) {\n return sourceCode.slice(expr.start, expr.end)\n }\n return '[Function]'\n }\n\n // For complex expressions, preserve as string\n if (expr.start !== null && expr.end !== null) {\n return sourceCode.slice(expr.start, expr.end)\n }\n\n return undefined\n}\n\n/**\n * Get child elements of a JSX element, filtering out whitespace-only text\n */\nfunction getChildElements(element: JSXElement): JSXElement[] {\n return element.children.filter((child: JSXChild): child is JSXElement => {\n if (!isJSXElement(child)) return false\n return true\n })\n}\n\n/**\n * Parse Field configuration from a JSX element\n */\nfunction parseFieldConfig(element: JSXElement, sourceCode: string): FieldConfig {\n const props = extractProps(element, sourceCode)\n const config: FieldConfig = {\n name: String(props.name || ''),\n }\n\n if (typeof props.lines === 'number') config.lines = props.lines\n if (typeof props.placeholder === 'string') config.placeholder = props.placeholder\n if (typeof props.display === 'string') config.display = props.display as FieldConfig['display']\n if (props.allowCreate === true) config.allowCreate = true\n if (props.searchable === true) config.searchable = true\n if (Array.isArray(props.preview)) config.preview = props.preview as string[]\n if (props.collapsed === true) config.collapsed = true\n if (props.readOnly === true) config.readOnly = true\n if (props.required === true) config.required = true\n if (typeof props.min === 'number') config.min = props.min\n if (typeof props.max === 'number') config.max = props.max\n if (typeof props.span === 'number') config.span = props.span\n if (props.autoFocus === true) config.autoFocus = true\n\n return config\n}\n\n/**\n * Parse Section configuration from a JSX element\n */\nfunction parseSectionConfig(element: JSXElement, sourceCode: string): SectionConfig {\n const props = extractProps(element, sourceCode)\n const config: SectionConfig = {\n label: String(props.label || ''),\n }\n\n if (props.collapsed === true) config.collapsed = true\n\n // Parse child fields and sections\n const children: (FieldConfig | SectionConfig)[] = []\n for (const child of getChildElements(element)) {\n const childName = getElementName(child)\n if (childName === 'Field') {\n children.push(parseFieldConfig(child, sourceCode))\n } else if (childName === 'Section') {\n children.push(parseSectionConfig(child, sourceCode))\n }\n }\n if (children.length > 0) {\n config.children = children\n }\n\n return config\n}\n\n/**\n * Parse Form configuration from a JSX element\n */\nfunction parseFormConfig(element: JSXElement, sourceCode: string): FormConfig {\n const props = extractProps(element, sourceCode)\n const config: FormConfig = {}\n\n if (typeof props.layout === 'string') config.layout = props.layout as 'stack' | 'grid'\n if (Array.isArray(props.fields)) config.fields = props.fields as string[]\n\n // Parse child fields and sections\n const children: (FieldConfig | SectionConfig)[] = []\n for (const child of getChildElements(element)) {\n const childName = getElementName(child)\n if (childName === 'Field') {\n children.push(parseFieldConfig(child, sourceCode))\n } else if (childName === 'Section') {\n children.push(parseSectionConfig(child, sourceCode))\n }\n }\n if (children.length > 0) {\n config.children = children\n }\n\n return config\n}\n\n/**\n * Parse Template configuration, preserving JSX for runtime\n */\nfunction parseTemplateConfig(element: JSXElement, sourceCode: string): TemplateConfig {\n // Preserve the entire template JSX as a string\n if (element.start !== null && element.end !== null) {\n // Get just the children content\n const openingEnd = element.openingElement.end ?? element.start\n const closingStart = element.closingElement?.start ?? element.end\n const jsx = sourceCode.slice(openingEnd, closingStart).trim()\n return { jsx }\n }\n return { jsx: '' }\n}\n\n/**\n * Parse display component (Table, Grid, Cards)\n */\nfunction parseDisplayConfig(element: JSXElement, sourceCode: string): DisplayConfig {\n const name = getElementName(element)\n const props = extractProps(element, sourceCode)\n const config: DisplayConfig = {\n type: name.toLowerCase() as 'table' | 'grid' | 'cards',\n }\n\n if (Array.isArray(props.columns)) config.columns = props.columns as string[]\n if (props.sortable === true) config.sortable = true\n\n // Look for Template child\n for (const child of getChildElements(element)) {\n if (getElementName(child) === 'Template') {\n config.template = parseTemplateConfig(child, sourceCode)\n break\n }\n }\n\n return config\n}\n\n/**\n * Parse Search configuration\n */\nfunction parseSearchConfig(element: JSXElement, sourceCode: string): SearchConfig {\n const props = extractProps(element, sourceCode)\n const config: SearchConfig = {}\n\n if (Array.isArray(props.fields)) config.fields = props.fields as string[]\n\n return config\n}\n\n/**\n * Parse Filter configuration\n */\nfunction parseFilterConfig(element: JSXElement, sourceCode: string): FilterConfig {\n const props = extractProps(element, sourceCode)\n return {\n field: String(props.field || ''),\n exists: props.exists === true ? true : undefined,\n }\n}\n\n/**\n * Parse view configuration (List, Detail, Edit, Create)\n */\nfunction parseViewConfig(element: JSXElement, sourceCode: string): ViewConfig {\n const config: ViewConfig = {}\n\n for (const child of getChildElements(element)) {\n const childName = getElementName(child)\n\n switch (childName) {\n case 'Search':\n config.search = parseSearchConfig(child, sourceCode)\n break\n case 'Filters': {\n config.filters = []\n for (const filterChild of getChildElements(child)) {\n if (getElementName(filterChild) === 'Filter') {\n config.filters.push(parseFilterConfig(filterChild, sourceCode))\n }\n }\n break\n }\n case 'Table':\n case 'Grid':\n case 'Cards':\n config.display = parseDisplayConfig(child, sourceCode)\n break\n case 'Form':\n config.form = parseFormConfig(child, sourceCode)\n break\n case 'Template':\n config.template = parseTemplateConfig(child, sourceCode)\n break\n case 'Editor': {\n const props = extractProps(child, sourceCode)\n config.editor = { language: String(props.language || 'yaml') }\n break\n }\n }\n }\n\n return config\n}\n\n/**\n * Parse Actions container\n */\nfunction parseActionsConfig(\n element: JSXElement,\n schemaTypes: Set<string>,\n sourceCode: string\n): ActionConfig[] {\n const actions: ActionConfig[] = []\n\n for (const child of getChildElements(element)) {\n const childName = getElementName(child)\n const props = extractProps(child, sourceCode)\n\n if (childName === 'Delete') {\n actions.push({\n type: 'delete',\n confirm: typeof props.confirm === 'string' ? props.confirm : undefined,\n })\n } else if (childName === 'Duplicate') {\n actions.push({ type: 'duplicate' })\n } else if (childName === 'Export') {\n actions.push({\n type: 'export',\n formats: Array.isArray(props.formats) ? (props.formats as string[]) : undefined,\n })\n } else if (childName === 'Import') {\n actions.push({ type: 'import' })\n } else if (schemaTypes.has(childName)) {\n // Entity reference = generate action\n actions.push({\n type: 'generate',\n entity: childName,\n context: Array.isArray(props.context) ? (props.context as string[]) : undefined,\n })\n }\n }\n\n return actions\n}\n\n/**\n * Parse Permissions container\n */\nfunction parsePermissionsConfig(element: JSXElement, sourceCode: string): RoleConfig[] {\n const roles: RoleConfig[] = []\n\n for (const child of getChildElements(element)) {\n if (getElementName(child) === 'Role') {\n const props = extractProps(child, sourceCode)\n roles.push({\n name: String(props.name || ''),\n actions: Array.isArray(props.actions) ? (props.actions as string[]) : [],\n })\n }\n }\n\n return roles\n}\n\n/**\n * Parse a collection element (schema type)\n */\nfunction parseCollectionConfig(\n element: JSXElement,\n schemaTypes: Set<string>,\n sourceCode: string\n): CollectionConfig {\n const props = extractProps(element, sourceCode)\n const config: CollectionConfig = {}\n\n // Top-level collection props\n if (typeof props.view === 'string') config.view = props.view as 'table' | 'cards' | 'grid'\n if (Array.isArray(props.columns)) config.columns = props.columns as string[]\n if (props.searchable === true) config.searchable = true\n if (typeof props.path === 'string') config.path = props.path\n if (typeof props.slug === 'string') config.slug = props.slug\n\n // Parse child views and configurations\n for (const child of getChildElements(element)) {\n const childName = getElementName(child)\n\n switch (childName) {\n case 'List':\n config.list = parseViewConfig(child, sourceCode)\n break\n case 'Detail':\n config.detail = parseViewConfig(child, sourceCode)\n break\n case 'Edit':\n config.edit = parseViewConfig(child, sourceCode)\n break\n case 'Create':\n config.create = parseViewConfig(child, sourceCode)\n break\n case 'Actions':\n config.actions = parseActionsConfig(child, schemaTypes, sourceCode)\n break\n case 'Permissions':\n config.permissions = parsePermissionsConfig(child, sourceCode)\n break\n }\n }\n\n return config\n}\n\n/**\n * Parse navigation structure, distinguishing between groups and collections\n */\nfunction parseNavigationElement(\n element: JSXElement,\n schemaTypes: Set<string>,\n collections: Record<string, CollectionConfig>,\n sourceCode: string\n): NavigationGroup | string {\n const name = getElementName(element)\n const props = extractProps(element, sourceCode)\n\n // If this is a schema type, it's a collection\n if (schemaTypes.has(name)) {\n // Parse and store collection config\n collections[name] = parseCollectionConfig(element, schemaTypes, sourceCode)\n return name\n }\n\n // Otherwise it's a navigation group\n const group: NavigationGroup = {\n name,\n children: [],\n }\n\n if (typeof props.icon === 'string') {\n group.icon = props.icon\n }\n\n // Parse children\n for (const child of getChildElements(element)) {\n const childResult = parseNavigationElement(child, schemaTypes, collections, sourceCode)\n group.children.push(childResult)\n }\n\n return group\n}\n\n/**\n * Parse hooks from the App element's hooks prop\n */\nfunction parseHooksFromProp(\n hooksProp: unknown,\n sourceCode: string\n): Record<string, EntityHooks> {\n const hooks: Record<string, EntityHooks> = {}\n\n if (typeof hooksProp !== 'object' || hooksProp === null) {\n return hooks\n }\n\n for (const [typeName, typeHooks] of Object.entries(hooksProp as Record<string, unknown>)) {\n if (typeof typeHooks !== 'object' || typeHooks === null) continue\n\n const entityHooks: EntityHooks = {}\n const hooksObj = typeHooks as Record<string, unknown>\n\n // Preserve hooks as function source strings\n if (hooksObj.onCreate !== undefined) {\n entityHooks.onCreate = hooksObj.onCreate as EntityHooks['onCreate']\n }\n if (hooksObj.onUpdate !== undefined) {\n entityHooks.onUpdate = hooksObj.onUpdate as EntityHooks['onUpdate']\n }\n if (hooksObj.onDelete !== undefined) {\n entityHooks.onDelete = hooksObj.onDelete as EntityHooks['onDelete']\n }\n\n if (Object.keys(entityHooks).length > 0) {\n hooks[typeName] = entityHooks\n }\n }\n\n return hooks\n}\n\n/**\n * Parse JSX UI specification into UIConfig\n *\n * @param jsx - The JSX string to parse\n * @param schema - The parsed schema to determine which elements are collections\n * @returns Parsed UI configuration\n * @throws Error if JSX syntax is invalid or no App root element\n *\n * @example\n * const jsx = `\n * <App hooks={{ Startup: { onCreate: async () => {} } }}>\n * <Planning icon=\"lightbulb\">\n * <Idea view=\"cards\" />\n * </Planning>\n * </App>\n * `\n * const config = parseJSXUI(jsx, schema)\n * // config.hooks = { Startup: { onCreate: ... } }\n * // config.navigation = [{ name: 'Planning', icon: 'lightbulb', children: ['Idea'] }]\n * // config.collections = { Idea: { view: 'cards' } }\n */\nexport function parseJSXUI(jsx: string, schema: ParsedSchema): UIConfig {\n // Parse JSX using Babel\n let ast\n try {\n ast = babelParse(jsx, {\n plugins: ['jsx'],\n sourceType: 'module',\n })\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Invalid JSX syntax: ${error.message}`)\n }\n throw new Error('Invalid JSX syntax')\n }\n\n // Get schema type names for distinguishing collections from groups\n const schemaTypes = new Set(Object.keys(schema.types))\n\n // Find the root App element\n let appElement: JSXElement | null = null\n\n // Walk the AST to find JSX elements\n function findApp(node: Node): void {\n if (isJSXElement(node)) {\n if (getElementName(node) === 'App') {\n appElement = node\n return\n }\n // Check children\n for (const child of node.children) {\n findApp(child)\n }\n }\n // Handle ExpressionStatement wrapping JSX\n if (node.type === 'ExpressionStatement' && isJSXElement(node.expression)) {\n findApp(node.expression)\n }\n // Handle Program body\n if (node.type === 'Program') {\n for (const stmt of node.body) {\n findApp(stmt)\n }\n }\n // Handle File\n if (node.type === 'File') {\n findApp(node.program)\n }\n }\n\n findApp(ast)\n\n if (!appElement) {\n throw new Error('No <App> root element found in JSX')\n }\n\n // Initialize result\n const result: UIConfig = {\n hooks: {},\n navigation: [],\n collections: {},\n }\n\n // Extract hooks from App props\n const appProps = extractProps(appElement, jsx)\n if (appProps.hooks) {\n result.hooks = parseHooksFromProp(appProps.hooks, jsx)\n }\n\n // Parse children of App as navigation/collections\n for (const child of getChildElements(appElement)) {\n const parsed = parseNavigationElement(child, schemaTypes, result.collections, jsx)\n if (typeof parsed === 'string') {\n // Top-level collection (unusual but possible)\n result.navigation.push({\n name: parsed,\n children: [],\n })\n } else {\n result.navigation.push(parsed)\n }\n }\n\n return result\n}\n\n/**\n * Result of processing an MDX file\n */\nexport interface ProcessMDXResult {\n /** Raw YAML schema definition */\n schema: SchemaDefinition\n /** Parsed schema with types, fields, and references */\n parsedSchema: ParsedSchema\n /** Parsed JSX UI configuration */\n uiConfig: UIConfig\n /** Original JSX body (after frontmatter) */\n rawBody: string\n}\n\n/**\n * Process an MDX file and return all parsed components.\n */\nexport function processMDX(mdx: string): ProcessMDXResult {\n const { schema, body } = parseMDX(mdx)\n const parsedSchema = parseSchema(schema)\n const uiConfig = parseJSXUI(body, parsedSchema)\n return { schema, parsedSchema, uiConfig, rawBody: body }\n}\n"],"mappings":"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","names":["result","current"]}
|
|
1
|
+
{"version":3,"sources":["../index.ts"],"sourcesContent":["import type { ComponentType } from 'react'\n// Import and re-export shared handler types\nexport {\n SerializedFunction,\n serializeFunction,\n type EntityHandlerType,\n type SchemaHandlerType,\n type LifecycleHandlerType,\n type StateHandlerType,\n type HandlerExecutionResult,\n type HandlerLogEntry,\n} from './handlers'\nimport { serializeFunction, type SerializedFunction } from './handlers'\n\n// Type declaration for Node.js process global (may not exist in browser)\ndeclare const process: { env?: Record<string, string | undefined> } | undefined\n\n// ============================================================================\n// Custom Error Classes\n// ============================================================================\n\n/**\n * Error codes for schema validation errors.\n */\nexport type SchemaValidationErrorCode = 'MISSING_CONTEXT' | 'MISSING_NAMESPACE' | 'INVALID_FIELD_TYPE'\n\n/**\n * Error thrown when schema validation fails.\n *\n * @example\n * try {\n * DB({ User: { name: 'User name' } }) // Missing $id or $context\n * } catch (error) {\n * if (error instanceof SchemaValidationError) {\n * console.log(error.code) // 'MISSING_CONTEXT'\n * }\n * }\n */\nexport class SchemaValidationError extends Error {\n code: SchemaValidationErrorCode\n\n constructor(code: SchemaValidationErrorCode, message: string) {\n super(message)\n this.name = 'SchemaValidationError'\n this.code = code\n }\n}\n\n/**\n * Error codes for API errors.\n */\nexport type APIErrorCode = 'REGISTRATION_FAILED' | 'GENERATION_FAILED' | 'REFERENCE_RESOLUTION_FAILED'\n\n/**\n * Error thrown when API operations fail.\n *\n * @example\n * try {\n * await db.User('john-doe')\n * } catch (error) {\n * if (error instanceof APIError) {\n * console.log(error.code) // 'GENERATION_FAILED'\n * console.log(error.statusCode) // 404\n * }\n * }\n */\nexport class APIError extends Error {\n code: APIErrorCode\n statusCode?: number\n\n constructor(code: APIErrorCode, message: string, statusCode?: number) {\n super(message)\n this.name = 'APIError'\n this.code = code\n this.statusCode = statusCode\n }\n}\n\nexport type Components = {\n App: ComponentType\n List: ComponentType\n ListItem: ComponentType\n View: ComponentType\n Edit: ComponentType\n Chat: ComponentType\n}\n\nexport function UI(components: Components) {\n return components\n}\n\n/**\n * Parse namespace from a $id URL.\n *\n * @example\n * parseNamespaceFromId('https://db.sb/sales') // 'sales' (from path)\n * parseNamespaceFromId('https://db4.ai/startups') // 'startups' (from path)\n * parseNamespaceFromId('https://db.sb/org/team') // 'org/team' (from path)\n * parseNamespaceFromId('https://startup.db.sb') // 'startup' (from subdomain)\n * parseNamespaceFromId('https://startups.db.sb') // 'startups' (from subdomain)\n * parseNamespaceFromId('https://db.sb/') // null\n * parseNamespaceFromId('invalid') // null\n */\nexport function parseNamespaceFromId(id: string): string | null {\n try {\n const url = new URL(id)\n // Remove leading slash and trailing slash\n const path = url.pathname.replace(/^\\//, '').replace(/\\/$/, '')\n if (path) return path\n\n // No path - try to extract namespace from subdomain\n // e.g., 'startup.db.sb' -> 'startup', 'startups.db4.ai' -> 'startups'\n const hostParts = url.hostname.split('.')\n // Need at least 3 parts for subdomain (e.g., 'startup.db.sb' or 'startups.db4.ai')\n if (hostParts.length >= 3) {\n const subdomain = hostParts[0]\n // Exclude common non-namespace subdomains\n if (subdomain && subdomain !== 'www' && subdomain !== 'api') {\n return subdomain\n }\n }\n return null\n } catch {\n return null\n }\n}\n\n// Schema Types\n\n/**\n * Computed field - a function that derives a value from the entity.\n */\nexport type ComputedFieldFn<E = any, R = any> = (entity: E, $?: any) => R\n\n/**\n * Nested object field value - used for complex structures like StoryBrand.hero.wants\n */\nexport interface NestedFieldValue {\n [key: string]: string | string[] | boolean | NestedFieldValue | ComputedFieldFn\n}\n\n/**\n * Field value in an entity definition.\n * - `string` - Prompt for AI generation or JSONPath ($.field)\n * - `string[]` - Array generation\n * - `NestedFieldValue` - Nested object structure\n * - `boolean` - Relationship marker (e.g., '->Entity[]': true)\n * - `Function` - Computed field\n */\nexport type FieldValue =\n | string\n | string[]\n | boolean\n | NestedFieldValue\n | ComputedFieldFn\n\n/**\n * Entity lifecycle handler.\n */\nexport type EntityHandler<E = any> = (entity: E, $: any) => void | Promise<void>\n\n/**\n * Entity update handler with previous state.\n */\nexport type EntityUpdateHandler<E = any> = (entity: E, previous: E, $: any) => void | Promise<void>\n\n/**\n * Schema lifecycle handler.\n */\nexport type SchemaHandler = ($: any) => void | Promise<void>\n\n/**\n * Schema error handler.\n */\nexport type SchemaErrorHandler = (error: Error, $: any) => void | Promise<void>\n\n/**\n * Input state machine configuration for entity definitions.\n * This is the raw format before parsing - use RawStateConfig from state machine types.\n */\nexport type InputStateConfig = {\n $initial: string\n} & Record<string, unknown>\n\n/**\n * Evaluation definition stub.\n */\nexport type EvalDefinition = Record<string, unknown>\n\n/**\n * Schema experiment definition stub.\n */\nexport type SchemaExperiment = Record<string, unknown>\n\n/**\n * Schema analytics configuration stub.\n */\nexport type SchemaAnalytics = Record<string, unknown>\n\n// Schema metadata fields (prefixed with $)\nexport interface SchemaMetadata {\n /** Unique identifier/URL for this schema */\n $id?: string\n /** Shared namespace for composing multiple DB() schemas */\n $context?: string\n /** Schema version */\n $version?: string\n /** Schema-level functions */\n $fn?: Record<string, (...args: any[]) => any>\n /** Handler called after all seeds complete */\n $seeded?: SchemaHandler\n /** Handler called when database is fully initialized */\n $ready?: SchemaHandler\n /** Global error handler */\n $error?: SchemaErrorHandler\n /** Reusable evaluation definitions */\n $eval?: Record<string, EvalDefinition>\n /** Schema-level experiments */\n $experiment?: Record<string, SchemaExperiment>\n /** Analytics provider configuration */\n $analytics?: SchemaAnalytics\n /** Event handlers (deprecated) */\n $on?: Record<string, (...args: any[]) => void | Promise<void>>\n}\n\n/**\n * Entity-level directives that can appear in type definitions.\n */\nexport interface EntityDirectives {\n /** Seed data source URL */\n $seed?: string\n /** JSONPath or transform for entity ID from seed data (e.g., '$.slug', 'PascalCase($.name)') */\n $id?: string\n /** Entity type discriminator */\n $type?: string\n /** Handler called when entity is created */\n $created?: EntityHandler\n /** Handler called when entity is updated */\n $updated?: EntityUpdateHandler\n /** Handler called when entity is deleted */\n $deleted?: EntityHandler\n /** State machine configuration */\n $state?: InputStateConfig\n /** Inline experiment */\n $experiment?: Record<string, unknown>\n /** Inline eval */\n $eval?: EvalDefinition | EvalDefinition[]\n /** Image generation config */\n $image?: Record<string, unknown>\n /** Speech generation config */\n $speech?: Record<string, unknown>\n /** Diagram generation config */\n $diagram?: Record<string, unknown>\n /** Code generation config */\n $code?: Record<string, unknown>\n}\n\n/**\n * Type definition: entity directives + field definitions.\n * Allows any string key for fields and relationship markers.\n */\nexport type TypeDefinition = EntityDirectives & Record<string, FieldValue | undefined>\n\n/**\n * Schema: metadata + type definitions.\n * Allows entity type definitions with all directives and field types.\n */\nexport type SchemaDefinition = SchemaMetadata & Record<string, TypeDefinition | string | undefined>\n\nexport interface StringField {\n type: 'string'\n description: string\n optional?: boolean\n}\n\n// ============================================================================\n// Reference Operator Constants\n// ============================================================================\n\n/**\n * Reference operators used in the schema DSL.\n *\n * - `->` (FORWARD_EXACT): Forward exact reference - resolves by ID\n * - `~>` (FORWARD_FUZZY): Forward fuzzy reference - resolves by semantic matching\n * - `<-` (BACKWARD_EXACT): Backward exact reference - reverse lookup by ID\n * - `<~` (BACKWARD_FUZZY): Backward fuzzy reference - reverse lookup by semantic matching\n *\n * @example\n * // Forward references (existing)\n * { author: '->User' } // Exact forward ref\n * { avatar: '~>Image' } // Fuzzy forward ref\n *\n * // Backward references (new)\n * { posts: '<-Post' } // Find Posts that reference this entity\n * { related: '<~Article' } // Find semantically related Articles\n */\nexport const OPERATORS = {\n /** Forward exact reference: `->Type` - resolves to exact ID match */\n FORWARD_EXACT: '->',\n /** Forward fuzzy reference: `~>Type` - resolves by semantic similarity */\n FORWARD_FUZZY: '~>',\n /** Backward exact reference: `<-Type` - finds entities referencing this one */\n BACKWARD_EXACT: '<-',\n /** Backward fuzzy reference: `<~Type` - finds semantically related entities */\n BACKWARD_FUZZY: '<~',\n} as const\n\n/** Type for all valid reference operators */\nexport type ReferenceOperator = (typeof OPERATORS)[keyof typeof OPERATORS]\n\n/** Parsed operator information returned by parseOperator */\nexport type ParsedOperator =\n | { direction: 'forward'; fuzzy: boolean }\n | { direction: 'backward'; mode: 'exact' | 'fuzzy' }\n\n/**\n * Parse a reference operator prefix into its direction and mode/fuzzy properties.\n *\n * This helper function converts the two-character operator prefix into structured\n * properties for building ReferenceField objects.\n *\n * @param prefix - The operator prefix (`->`, `~>`, `<-`, or `<~`)\n * @returns Parsed operator with direction and either fuzzy (forward) or mode (backward)\n *\n * @example\n * parseOperator('->') // { direction: 'forward', fuzzy: false }\n * parseOperator('~>') // { direction: 'forward', fuzzy: true }\n * parseOperator('<-') // { direction: 'backward', mode: 'exact' }\n * parseOperator('<~') // { direction: 'backward', mode: 'fuzzy' }\n */\nexport function parseOperator(prefix: string): ParsedOperator {\n switch (prefix) {\n case OPERATORS.FORWARD_EXACT:\n return { direction: 'forward', fuzzy: false }\n case OPERATORS.FORWARD_FUZZY:\n return { direction: 'forward', fuzzy: true }\n case OPERATORS.BACKWARD_EXACT:\n return { direction: 'backward', mode: 'exact' }\n case OPERATORS.BACKWARD_FUZZY:\n return { direction: 'backward', mode: 'fuzzy' }\n default:\n // Default to forward exact for unknown operators\n return { direction: 'forward', fuzzy: false }\n }\n}\n\n/**\n * Parsed reference field from the schema DSL.\n *\n * The `direction` and `mode` properties are used for backward references (`<-`, `<~`),\n * while the `fuzzy` property is used for forward references (`->`, `~>`) for\n * backward compatibility.\n *\n * ## Forward References (direction omitted)\n * - `->Type` produces `{ fuzzy: false, ... }` - exact ID lookup\n * - `~>Type` produces `{ fuzzy: true, ... }` - semantic matching\n *\n * ## Backward References\n * - `<-Type` produces `{ direction: 'backward', mode: 'exact', ... }` - find by ID\n * - `<~Type` produces `{ direction: 'backward', mode: 'fuzzy', ... }` - find by semantics\n *\n * @example\n * // Forward exact reference\n * parseFieldType('->User')\n * // { type: 'reference', ref: 'User', isArray: false, optional: false, fuzzy: false }\n *\n * // Backward fuzzy array reference\n * parseFieldType('<~Post[]')\n * // { type: 'reference', ref: 'Post', isArray: true, optional: false, direction: 'backward', mode: 'fuzzy' }\n */\nexport interface ReferenceField {\n type: 'reference'\n /** Single reference target type (mutually exclusive with `refs`) */\n ref?: string\n /** Union type reference targets (mutually exclusive with `ref`) */\n refs?: string[]\n /** Whether this is an array of references (e.g., `->Type[]`) */\n isArray: boolean\n /** Whether the reference is optional (e.g., `->Type?`) */\n optional?: boolean\n /** For forward references: true if fuzzy (`~>`), false if exact (`->`) */\n fuzzy?: boolean\n /** For backward references: always 'backward' when present */\n direction?: 'forward' | 'backward'\n /** For backward references: 'exact' (`<-`) or 'fuzzy' (`<~`) */\n mode?: 'exact' | 'fuzzy'\n}\n\nexport interface ArrayField {\n type: 'array'\n items: { type: 'string' }\n description: string\n optional?: boolean\n refs?: string[] // Inline references: ['... ->Type']\n backRef?: string // Back references: ['<-Type']\n count?: number | { min: number; max: number } // Extracted count from description\n}\n\nexport interface ObjectField {\n type: 'object'\n properties: Record<string, StringField>\n optional?: boolean\n}\n\nexport interface EmbeddedField {\n type: 'embedded'\n embeddedType: string\n isArray?: boolean\n optional?: boolean\n}\n\nexport interface JSONPathField {\n type: 'jsonpath'\n path: string\n transform?: string\n}\n\nexport interface JSONPathEmbeddedField {\n type: 'jsonpath-embedded'\n path: string\n embeddedType: string\n isArray: boolean\n optional?: boolean\n}\n\nexport interface ComputedField {\n type: 'computed'\n source: string\n}\n\nexport interface PromptField {\n type: 'prompt'\n prompt: string\n}\n\nexport type ParsedField = StringField | ReferenceField | ArrayField | ObjectField | EmbeddedField | JSONPathField | JSONPathEmbeddedField | ComputedField | PromptField\n\nexport interface TypeReference {\n field: string\n ref: string\n refs?: string[]\n isArray: boolean\n optional?: boolean\n fuzzy?: boolean\n backRef?: boolean // True if this is a back reference (read-only, not generated)\n}\n\nexport interface SeedConfig {\n url: string\n format?: 'tsv' | 'csv' | 'json'\n idField?: string // Which column to use as the ID (defaults to first column)\n id?: string // JSONPath to use as the ID (e.g., '$.slug')\n idTransform?: string // Transform function to apply to ID (e.g., 'PascalCase')\n next?: string // JSONPath to next page URL for pagination\n data?: string // JSONPath to data array in response\n}\n\n/**\n * Parse $id field which can be:\n * - Simple JSONPath: $.slug\n * - Transform with path: PascalCase($.example)\n * - Column name (legacy): slug\n *\n * @example\n * parseIdConfig('$.slug') // { path: '$.slug' }\n * parseIdConfig('PascalCase($.example)') // { path: '$.example', transform: 'PascalCase' }\n * parseIdConfig('kebab-case($.title)') // { path: '$.title', transform: 'kebab-case' }\n * parseIdConfig('slug') // { path: 'slug' }\n */\nexport function parseIdConfig(idField: string): { path: string; transform?: string } {\n // Check for transform pattern: Transform($.path)\n // Supports transforms like PascalCase, camelCase, kebab-case, UPPERCASE, lowercase\n const transformMatch = idField.match(/^([A-Za-z][A-Za-z0-9-]*)\\((\\$\\..+)\\)$/)\n if (transformMatch) {\n const [, transform, path] = transformMatch\n return { path, transform }\n }\n // Plain JSONPath or column name\n return { path: idField }\n}\n\n// ============================================================================\n// JSONPath Validation\n// ============================================================================\n\n/**\n * Validates that a string is a valid JSONPath expression.\n *\n * A valid JSONPath must:\n * - Start with `$.` (root reference)\n * - Contain valid property names, array indices, or bracket notation\n *\n * Supported patterns:\n * - `$.field` - Simple property access\n * - `$.nested.field` - Nested property access\n * - `$.array[0]` - Array index access\n * - `$.array[*]` - Array wildcard\n * - `$.items[?(@.active)]` - Filter expressions\n *\n * @example\n * isValidJSONPath('$.title') // true\n * isValidJSONPath('$.data.items[0]') // true\n * isValidJSONPath('$.tags[*]') // true\n * isValidJSONPath('title') // false (missing $.)\n * isValidJSONPath('$50 price') // false (not a valid path)\n */\nexport function isValidJSONPath(path: string): boolean {\n // Must start with $.\n if (!path.startsWith('$.')) {\n return false\n }\n\n // Basic validation regex for common JSONPath patterns:\n // - Property access: .propertyName or ['property name']\n // - Array access: [0], [*], [?(@.condition)]\n // - Nested paths: $.a.b.c\n const jsonPathPattern = /^\\$\\.[\\w\\[\\].*@?()'\"=!<>|&\\s-]+$/\n\n return jsonPathPattern.test(path)\n}\n\n// ============================================================================\n// Type Guards for ParsedField\n// ============================================================================\n\n/**\n * Type guard to check if a ParsedField is a JSONPathField.\n *\n * @example\n * const field = parseFieldType('$.title')\n * if (isJSONPathField(field)) {\n * console.log(field.path) // TypeScript knows field.path exists\n * }\n */\nexport function isJSONPathField(field: ParsedField): field is JSONPathField {\n return field.type === 'jsonpath'\n}\n\n/**\n * Type guard to check if a ParsedField is a JSONPathEmbeddedField.\n *\n * @example\n * const field = parseFieldType('$.author ->Author')\n * if (isJSONPathEmbeddedField(field)) {\n * console.log(field.embeddedType) // TypeScript knows field.embeddedType exists\n * }\n */\nexport function isJSONPathEmbeddedField(field: ParsedField): field is JSONPathEmbeddedField {\n return field.type === 'jsonpath-embedded'\n}\n\n/**\n * Type guard to check if a ParsedField is a PromptField.\n *\n * @example\n * const field = parsed.types.Task.fields.description\n * if (isPromptField(field)) {\n * console.log(field.prompt) // TypeScript knows field.prompt exists\n * }\n */\nexport function isPromptField(field: ParsedField): field is PromptField {\n return field.type === 'prompt'\n}\n\n/**\n * Type guard to check if a ParsedField is a StringField.\n */\nexport function isStringField(field: ParsedField): field is StringField {\n return field.type === 'string'\n}\n\n// ============================================================================\n// Function Serialization Types\n// ============================================================================\n// NOTE: SerializedFunction, serializeFunction, and related handler types are now\n// imported from ./handlers and re-exported at the top of this file.\n\n// ============================================================================\n// Data Source Configuration Types\n// ============================================================================\n\nexport interface OAuthConfig {\n tokenUrl: string\n clientId: string\n clientSecret: string\n}\n\nexport interface AsyncConfig {\n start: string\n result: string\n}\n\nexport interface SourceConfig {\n $api: string\n $apiKey?: string\n $bearer?: string\n $oauth?: OAuthConfig\n $data?: string\n $async?: AsyncConfig\n}\n\nexport type SourceInput = Record<string, 'string' | 'string?'>\n\n// ============================================================================\n// Generative Format Configuration Types\n// ============================================================================\n\nexport interface ImageConfig {\n aspectRatio?: string\n style?: string\n}\n\nexport interface SpeechConfig {\n voice?: string\n speed?: number\n format?: string\n}\n\nexport interface DiagramConfig {\n type?: string\n direction?: string\n format?: string\n}\n\nexport interface ConventionsConfig {\n nodes?: string\n edges?: string\n events?: string\n}\n\nexport interface CodeConfig {\n language?: string\n runtime?: string\n framework?: string\n}\n\n// ============================================================================\n// State Machine Types\n// ============================================================================\n\n/** Transition configuration - simple string or complex object */\nexport interface TransitionConfig {\n to: string | null\n if?: SerializedFunction\n do?: SerializedFunction\n}\n\n/** State configuration with transitions */\nexport interface StateConfig {\n transitions: Record<string, TransitionConfig>\n $entry?: SerializedFunction\n $exit?: SerializedFunction\n}\n\n/** Parsed state machine configuration */\nexport interface ParsedStateConfig {\n $initial: string\n states: Record<string, StateConfig>\n}\n\n/** Raw state config - input format before parsing */\nexport type RawStateConfig = {\n $initial: string\n} & Record<string, unknown>\n\n/** State validation error */\nexport interface StateValidationError {\n code: string\n message: string\n state?: string\n event?: string\n transition?: string\n}\n\n/** State validation result */\nexport interface StateValidationResult {\n valid: boolean\n errors: StateValidationError[]\n}\n\n/**\n * Validate a raw state machine configuration.\n * Checks for: valid $initial, reachable states, no orphan states, valid transitions.\n */\nexport function validateStateConfig(config: RawStateConfig): StateValidationResult {\n const errors: StateValidationError[] = []\n\n // Extract state names (exclude $ prefixed keys like $initial, $version, etc.)\n const stateNames = Object.keys(config).filter((k) => !k.startsWith('$'))\n\n // Check if $initial is missing or empty\n if (!('$initial' in config) || config.$initial === undefined) {\n errors.push({\n code: 'MISSING_INITIAL_STATE',\n message: 'State machine configuration is missing $initial',\n })\n } else if (config.$initial === '' || !stateNames.includes(config.$initial)) {\n // $initial is present but invalid (empty string or references non-existent state)\n errors.push({\n code: 'INVALID_INITIAL_STATE',\n message: `Initial state '${config.$initial}' is not a valid state`,\n })\n }\n\n // Helper to get transition target from a transition value\n const getTransitionTarget = (value: unknown): string | null => {\n if (typeof value === 'string') return value\n if (value && typeof value === 'object' && 'to' in value && typeof (value as Record<string, unknown>).to === 'string') {\n return (value as Record<string, unknown>).to as string\n }\n return null\n }\n\n // Check all transition targets exist and have valid syntax\n for (const stateName of stateNames) {\n const stateConfig = config[stateName]\n\n // null means terminal state - valid\n if (stateConfig === null) continue\n\n // Empty object means terminal state - valid\n if (typeof stateConfig === 'object' && Object.keys(stateConfig as object).length === 0) continue\n\n if (typeof stateConfig !== 'object') {\n errors.push({\n code: 'INVALID_STATE_CONFIG',\n message: `State '${stateName}' has invalid configuration`,\n state: stateName,\n })\n continue\n }\n\n // Check each transition\n for (const [eventName, transitionValue] of Object.entries(stateConfig as object)) {\n // Skip handler functions ($entry, $exit)\n if (eventName.startsWith('$')) continue\n\n // Check transition syntax\n if (Array.isArray(transitionValue)) {\n errors.push({\n code: 'INVALID_TRANSITION_SYNTAX',\n message: `Transition '${eventName}' in state '${stateName}' cannot be an array`,\n state: stateName,\n event: eventName,\n })\n continue\n }\n\n // String transition: { submit: 'pending' }\n if (typeof transitionValue === 'string') {\n if (!stateNames.includes(transitionValue)) {\n errors.push({\n code: 'INVALID_TRANSITION_TARGET',\n message: `Transition '${eventName}' in state '${stateName}' targets unknown state '${transitionValue}'`,\n state: stateName,\n event: eventName,\n })\n }\n continue\n }\n\n // null transition: terminal (goes nowhere, like archive/delete)\n if (transitionValue === null) continue\n\n // Object transition: { submit: { to: 'pending', if: ..., do: ... } }\n if (typeof transitionValue === 'object') {\n const tv = transitionValue as Record<string, unknown>\n // Must have 'to' property\n if (!('to' in tv)) {\n errors.push({\n code: 'INVALID_TRANSITION_SYNTAX',\n message: `Transition '${eventName}' in state '${stateName}' is missing 'to' property`,\n state: stateName,\n event: eventName,\n })\n continue\n }\n // Check target exists if 'to' is specified\n if (typeof tv.to === 'string' && !stateNames.includes(tv.to)) {\n errors.push({\n code: 'INVALID_TRANSITION_TARGET',\n message: `Transition '${eventName}' in state '${stateName}' targets unknown state '${tv.to}'`,\n state: stateName,\n event: eventName,\n })\n }\n continue\n }\n\n // Unknown transition format (e.g., number)\n errors.push({\n code: 'INVALID_TRANSITION_SYNTAX',\n message: `Transition '${eventName}' in state '${stateName}' has invalid format`,\n state: stateName,\n event: eventName,\n })\n }\n }\n\n // Check for orphan states (states not reachable from $initial)\n // Only do this check if we have a valid $initial state\n if (config.$initial && stateNames.includes(config.$initial)) {\n const reachable = new Set<string>()\n const toVisit = [config.$initial]\n\n while (toVisit.length > 0) {\n const current = toVisit.pop()!\n if (reachable.has(current)) continue\n reachable.add(current)\n\n // Find all states reachable from current\n const stateConfig = config[current]\n if (stateConfig === null || typeof stateConfig !== 'object') continue\n\n for (const [eventName, transitionValue] of Object.entries(stateConfig as object)) {\n if (eventName.startsWith('$')) continue\n const target = getTransitionTarget(transitionValue)\n if (target && stateNames.includes(target) && !reachable.has(target)) {\n toVisit.push(target)\n }\n }\n }\n\n // Any state not in reachable set is an orphan\n for (const stateName of stateNames) {\n if (!reachable.has(stateName)) {\n errors.push({\n code: 'ORPHAN_STATE',\n message: `State '${stateName}' is not reachable from initial state '${config.$initial}'`,\n state: stateName,\n })\n }\n }\n }\n\n return { valid: errors.length === 0, errors }\n}\n\n/**\n * Parse a raw state machine configuration into the normalized format.\n * Converts string functions to SerializedFunction objects.\n *\n * @param config - Raw state machine config from schema\n * @returns Parsed state machine configuration\n *\n * @example\n * const parsed = parseStateConfig({\n * $initial: 'draft',\n * draft: {\n * submit: 'pending',\n * $entry: (entity) => { console.log('entered draft') }\n * },\n * pending: {\n * approve: { to: 'approved', if: (e) => e.score >= 80 }\n * },\n * approved: null // terminal state\n * })\n */\nexport function parseStateConfig(config: RawStateConfig): ParsedStateConfig {\n const states: Record<string, StateConfig> = {}\n\n for (const [stateName, stateValue] of Object.entries(config)) {\n // Skip $initial - it's not a state\n if (stateName === '$initial') continue\n\n // Terminal state (null or empty object)\n if (stateValue === null || (typeof stateValue === 'object' && Object.keys(stateValue).length === 0)) {\n states[stateName] = { transitions: {} }\n continue\n }\n\n if (typeof stateValue !== 'object') {\n continue // Skip invalid state configs\n }\n\n const stateConfig: StateConfig = { transitions: {} }\n const stateObj = stateValue as Record<string, unknown>\n\n for (const [key, value] of Object.entries(stateObj)) {\n // Handle $entry handler\n if (key === '$entry') {\n if (typeof value === 'function') {\n stateConfig.$entry = serializeFunction('$entry', value)\n } else if (typeof value === 'string') {\n // String function body - parse it\n stateConfig.$entry = {\n name: '$entry',\n body: value,\n params: ['entity'],\n async: value.includes('await'),\n }\n }\n continue\n }\n\n // Handle $exit handler\n if (key === '$exit') {\n if (typeof value === 'function') {\n stateConfig.$exit = serializeFunction('$exit', value)\n } else if (typeof value === 'string') {\n stateConfig.$exit = {\n name: '$exit',\n body: value,\n params: ['entity'],\n async: value.includes('await'),\n }\n }\n continue\n }\n\n // Handle transitions\n const transitionName = key\n\n // Simple string transition: { submit: 'pending' }\n if (typeof value === 'string') {\n stateConfig.transitions[transitionName] = { to: value }\n continue\n }\n\n // null transition (shouldn't happen, but handle it)\n if (value === null) {\n stateConfig.transitions[transitionName] = { to: null }\n continue\n }\n\n // Complex transition with to/if/do: { approve: { to: 'approved', if: ..., do: ... } }\n if (typeof value === 'object') {\n const transObj = value as Record<string, unknown>\n const transitionConfig: TransitionConfig = {\n to: (transObj.to as string) ?? null,\n }\n\n // Parse 'if' guard\n if (transObj.if) {\n if (typeof transObj.if === 'function') {\n transitionConfig.if = serializeFunction('if', transObj.if)\n } else if (typeof transObj.if === 'string') {\n transitionConfig.if = {\n name: 'if',\n body: transObj.if,\n params: ['entity'],\n async: (transObj.if as string).includes('await'),\n }\n }\n }\n\n // Parse 'do' action\n if (transObj.do) {\n if (typeof transObj.do === 'function') {\n transitionConfig.do = serializeFunction('do', transObj.do)\n } else if (typeof transObj.do === 'string') {\n transitionConfig.do = {\n name: 'do',\n body: transObj.do,\n params: ['entity'],\n async: (transObj.do as string).includes('await'),\n }\n }\n }\n\n stateConfig.transitions[transitionName] = transitionConfig\n }\n }\n\n states[stateName] = stateConfig\n }\n\n return {\n $initial: config.$initial,\n states,\n }\n}\n\n// ============================================================================\n// Parsed Types\n// ============================================================================\n\nexport interface ParsedType {\n name: string\n fields: Record<string, ParsedField>\n references: TypeReference[]\n seed?: SeedConfig\n icon?: string\n group?: string\n // Entity lifecycle handlers (direct access)\n $created?: SerializedFunction\n $updated?: SerializedFunction\n $deleted?: SerializedFunction\n // Entity lifecycle handlers (grouped - deprecated, use direct access)\n handlers?: Record<string, SerializedFunction>\n // State machine configuration\n $state?: ParsedStateConfig\n // Data source configurations\n source?: SourceConfig\n input?: SourceInput\n from?: string[]\n cache?: string\n isSourceFunction?: boolean\n // Generative format configurations\n image?: ImageConfig\n speech?: SpeechConfig\n diagram?: DiagramConfig\n conventions?: ConventionsConfig\n code?: CodeConfig\n isGenerative?: boolean\n // Entity-level eval and experiment\n eval?: Record<string, EvalDefinition>\n experiment?: SchemaExperiment\n}\n\nexport interface SchemaSettings {\n iconLibrary?: string\n}\n\nexport interface ParsedSchema {\n types: Record<string, ParsedType>\n hash: string\n settings?: SchemaSettings\n // Schema-level directives\n fn?: Record<string, SerializedFunction>\n on?: Record<string, SerializedFunction>\n eval?: Record<string, EvalDefinition>\n experiment?: Record<string, SchemaExperiment>\n analytics?: SchemaAnalytics\n // Schema-level lifecycle handlers ($seeded, $ready, $error)\n handlers?: Record<string, SerializedFunction>\n}\n\nexport interface JSONSchemaProperty {\n type: string\n description?: string\n items?: { type: string; properties?: Record<string, JSONSchemaProperty>; required?: string[]; additionalProperties?: boolean }\n properties?: Record<string, JSONSchemaProperty>\n required?: string[]\n additionalProperties?: boolean\n minItems?: number\n maxItems?: number\n}\n\nexport interface JSONSchema {\n type: 'object'\n properties: Record<string, JSONSchemaProperty>\n required: string[]\n additionalProperties: boolean\n}\n\n// Extract count from array description\n// Supports patterns like:\n// - \"List 5 items\" -> 5\n// - \"Generate 10 samples\" -> 10\n// - \"Create exactly 7 categories\" -> 7\n// - \"List 3-5 keywords\" -> { min: 3, max: 5 }\nexport function extractCountFromDescription(description: string): number | { min: number; max: number } | undefined {\n // Guard against non-string input\n if (typeof description !== 'string') {\n return undefined\n }\n\n // First check for range pattern: N-M (e.g., \"3-5\")\n const rangeMatch = description.match(/\\b(\\d+)-(\\d+)\\b/)\n if (rangeMatch) {\n return { min: parseInt(rangeMatch[1], 10), max: parseInt(rangeMatch[2], 10) }\n }\n\n // Check for patterns like \"List N\", \"Generate N\", \"Create exactly N\"\n // Match word followed by optional \"exactly\" and a number\n const countMatch = description.match(/\\b(?:List|Generate|Create)\\s+(?:exactly\\s+)?(\\d+)\\b/i)\n if (countMatch) {\n return parseInt(countMatch[1], 10)\n }\n\n return undefined\n}\n\n/**\n * Parse a field value into its structured field type representation.\n *\n * Converts the shorthand field notation used in schema definitions into\n * a fully parsed field object with type information, references, and options.\n *\n * ## Reference Operators\n *\n * This function parses all four reference operators defined in {@link OPERATORS}:\n *\n * | Operator | Direction | Mode | Description |\n * |----------|-----------|-------|--------------------------------|\n * | `->` | forward | exact | Resolves to exact ID match |\n * | `~>` | forward | fuzzy | Resolves by semantic similarity|\n * | `<-` | backward | exact | Finds entities referencing this|\n * | `<~` | backward | fuzzy | Finds semantically related |\n *\n * @param value - The field value to parse. Can be:\n * - `string` - A field description or reference pattern (e.g., `'User name'`, `'->User'`, `'~>Image?'`, `'<-Post[]'`)\n * - `string[]` - An array field with description (e.g., `['Tag labels']`, `['<-Post']`)\n * - `Record<string, string>` - A nested object with field descriptions\n * - `Function` - A computed field\n *\n * @returns A ParsedField object representing the field type:\n * - `StringField` - Plain text field with description\n * - `ReferenceField` - Reference to another type (forward or backward)\n * - `ArrayField` - Array of strings or references\n * - `ObjectField` - Nested object with properties\n * - `EmbeddedField` - Embedded type (detected in second pass)\n * - `JSONPathField` - JSONPath expression for data mapping\n * - `ComputedField` - Field computed from a function\n *\n * @example\n * // String field\n * parseFieldType('User name')\n * // { type: 'string', description: 'User name' }\n *\n * @example\n * // Forward exact reference\n * parseFieldType('->User')\n * // { type: 'reference', ref: 'User', isArray: false, optional: false, fuzzy: false }\n *\n * @example\n * // Forward fuzzy reference (optional)\n * parseFieldType('~>Image?')\n * // { type: 'reference', ref: 'Image', isArray: false, optional: true, fuzzy: true }\n *\n * @example\n * // Forward array reference\n * parseFieldType('->Tag[]')\n * // { type: 'reference', ref: 'Tag', isArray: true, optional: false, fuzzy: false }\n *\n * @example\n * // Backward exact reference - finds Posts that reference this entity\n * parseFieldType('<-Post')\n * // { type: 'reference', ref: 'Post', isArray: false, optional: false, direction: 'backward', mode: 'exact' }\n *\n * @example\n * // Backward fuzzy reference array - finds semantically related Articles\n * parseFieldType('<~Article[]')\n * // { type: 'reference', ref: 'Article', isArray: true, optional: false, direction: 'backward', mode: 'fuzzy' }\n *\n * @example\n * // Union type reference\n * parseFieldType('->User|Organization')\n * // { type: 'reference', refs: ['User', 'Organization'], isArray: false, optional: false, fuzzy: false }\n *\n * @example\n * // String array with count hint\n * parseFieldType(['List 5 keywords'])\n * // { type: 'array', items: { type: 'string' }, description: 'List 5 keywords', count: 5 }\n *\n * @example\n * // Nested object\n * parseFieldType({ street: 'Street address', city: 'City name' })\n * // { type: 'object', properties: { street: {...}, city: {...} } }\n */\nexport function parseFieldType(value: FieldValue | Function): ParsedField {\n // Handle boolean markers (e.g., '->ICP[]': true)\n // These are relationship triggers where the field key contains the reference pattern\n if (typeof value === 'boolean') {\n return {\n type: 'string',\n description: '',\n }\n }\n\n // Handle computed fields (functions)\n if (typeof value === 'function') {\n return {\n type: 'computed',\n source: value.toString(),\n }\n }\n\n // Handle array descriptions: ['description'], ['... ->Type'], ['<-Type']\n if (Array.isArray(value)) {\n const rawDesc = value[0]\n // Ensure desc is a string for all subsequent operations\n const desc = typeof rawDesc === 'string' ? rawDesc : ''\n const count = extractCountFromDescription(desc)\n\n // Check for back reference: ['<-Type']\n const backRefMatch = desc.match(/^<-(\\w+)$/)\n if (backRefMatch) {\n const result: ArrayField = {\n type: 'array',\n items: { type: 'string' },\n description: desc,\n backRef: backRefMatch[1],\n }\n if (count !== undefined) result.count = count\n return result\n }\n\n // Check for inline references: ['... ->Type'] or ['... ->Type1 ->Type2']\n const inlineRefMatches = desc.match(/->(\\w+)/g)\n if (inlineRefMatches) {\n const refs = inlineRefMatches.map((m) => m.slice(2)) // Remove '->' prefix\n const result: ArrayField = {\n type: 'array',\n items: { type: 'string' },\n description: desc,\n refs,\n }\n if (count !== undefined) result.count = count\n return result\n }\n\n const result: ArrayField = {\n type: 'array',\n items: { type: 'string' },\n description: desc,\n }\n if (count !== undefined) result.count = count\n return result\n }\n\n // Handle nested objects: { field: 'description', ... }\n if (typeof value === 'object' && value !== null) {\n const properties: Record<string, StringField> = {}\n for (const [key, desc] of Object.entries(value)) {\n // Only include string descriptions, skip booleans and nested objects\n if (typeof desc === 'string') {\n properties[key] = { type: 'string', description: desc }\n }\n }\n return {\n type: 'object',\n properties,\n }\n }\n\n // Handle non-string values that weren't caught above (null, undefined, numbers, etc.)\n if (typeof value !== 'string') {\n return null as unknown as ParsedField\n }\n\n // Handle string patterns\n const str = value\n\n // Check for JSONPath with transform: Transform($.path)\n // Supports transforms like PascalCase, camelCase, kebab-case, UPPERCASE, lowercase\n const transformMatch = str.match(/^([A-Za-z][A-Za-z0-9-]*)\\((\\$\\..+)\\)$/)\n if (transformMatch) {\n const [, transform, path] = transformMatch\n return {\n type: 'jsonpath',\n path,\n transform,\n }\n }\n\n // Check for JSONPath embedded pattern: $.path ->Type or $.path ->Type?\n // Must check this BEFORE plain JSONPath to properly detect embedded mappings\n // Pattern: JSONPath followed by optional whitespace, ->, optional whitespace, TypeName, optional ?\n const jsonpathEmbeddedMatch = str.match(/^(\\$\\.[^\\s]+?)\\s*->\\s*([A-Za-z][A-Za-z0-9]*)(\\?)?$/)\n if (jsonpathEmbeddedMatch) {\n const [, path, embeddedType, optionalMarker] = jsonpathEmbeddedMatch\n // Determine if it's an array based on path containing [*] or [?(...)]\n const isArray = /\\[\\*\\]|\\[\\?/.test(path)\n return {\n type: 'jsonpath-embedded',\n path,\n embeddedType,\n isArray,\n ...(optionalMarker && { optional: true }),\n }\n }\n\n // Check for JSONPath pattern: $.xxx (must start with $. to avoid matching \"$50 price\")\n if (str.startsWith('$.')) {\n return {\n type: 'jsonpath',\n path: str,\n }\n }\n\n // Check for reference pattern: ->Type, ~>Type, <-Type, <~Type, with optional [], ?, and unions\n // Pattern: (<-|<~|->|~>)Type1|Type2|...[]?\n const refMatch = str.match(/^(<-|<~|->|~>)(.+?)(\\[\\])?(\\?)?$/)\n\n if (refMatch) {\n const [, prefix, typesPart, arrayMarker, optionalMarker] = refMatch\n const isArray = !!arrayMarker\n const optional = !!optionalMarker\n\n // Check for union types (Type1|Type2|...)\n const types = typesPart.split('|').map((t) => t.trim())\n\n // Parse the operator to get direction and mode/fuzzy\n const parsedOp = parseOperator(prefix)\n\n if (parsedOp.direction === 'backward') {\n // Backward references use direction/mode properties\n const baseRef = {\n type: 'reference' as const,\n isArray,\n optional,\n direction: parsedOp.direction,\n mode: parsedOp.mode,\n }\n\n return types.length > 1 ? { ...baseRef, refs: types } : { ...baseRef, ref: types[0] }\n } else {\n // Forward references use fuzzy property (backward compatibility)\n const baseRef = {\n type: 'reference' as const,\n isArray,\n optional,\n fuzzy: parsedOp.fuzzy,\n }\n\n return types.length > 1 ? { ...baseRef, refs: types } : { ...baseRef, ref: types[0] }\n }\n }\n\n // Plain string field\n return {\n type: 'string',\n description: str,\n }\n}\n\n// ============================================================================\n// Reference Parsing Utilities for Two-Phase Generation\n// ============================================================================\n\n/**\n * Parsed reference field info for generation.\n * Used by the two-phase generation pipeline to understand reference fields.\n */\nexport interface ParsedGenerationReference {\n /** Reference mode: exact (->) or fuzzy (~>) */\n mode: 'exact' | 'fuzzy'\n /** Target type name (or first type for union types) */\n targetType: string\n /** All target types for union types */\n targetTypes?: string[]\n /** Whether this reference is optional */\n isOptional: boolean\n /** Whether this is an array reference */\n isArray: boolean\n}\n\n/**\n * Parse a reference field definition for generation.\n *\n * Handles patterns like:\n * - `->Person` - exact reference\n * - `~>Industry` - fuzzy reference\n * - `->Type[]` - array of exact references\n * - `~>Type?` - optional fuzzy reference\n * - `->User|Organization` - union type reference\n *\n * @param fieldDef - The field definition string (e.g., '->Person', '~>Industry?')\n * @returns ParsedGenerationReference or null if not a reference field\n *\n * @example\n * parseGenerationReference('->Person')\n * // { mode: 'exact', targetType: 'Person', isOptional: false, isArray: false }\n *\n * @example\n * parseGenerationReference('~>Industry?')\n * // { mode: 'fuzzy', targetType: 'Industry', isOptional: true, isArray: false }\n *\n * @example\n * parseGenerationReference('->User|Organization')\n * // { mode: 'exact', targetType: 'User', targetTypes: ['User', 'Organization'], isOptional: false, isArray: false }\n */\nexport function parseGenerationReference(fieldDef: string): ParsedGenerationReference | null {\n // Match reference patterns: ->, ~>, with optional ? and []\n // Pattern supports union types: ->Type1|Type2|Type3\n const match = fieldDef.match(/^(->|~>)([A-Za-z][A-Za-z0-9]*(?:\\|[A-Za-z][A-Za-z0-9]*)*)(\\[\\])?(\\?)?$/)\n if (!match) return null\n\n const [, operator, typesPart, arrayMarker, optionalMarker] = match\n const types = typesPart.split('|').map(t => t.trim())\n\n return {\n mode: operator === '->' ? 'exact' : 'fuzzy',\n targetType: types[0],\n ...(types.length > 1 && { targetTypes: types }),\n isOptional: optionalMarker === '?',\n isArray: arrayMarker === '[]',\n }\n}\n\n/**\n * Parse array field definition for generation.\n *\n * Handles array shorthand like `['~>Investor']` or `['->Person']`.\n *\n * @param fieldDef - The field definition array (e.g., ['~>Investor'])\n * @returns ParsedGenerationReference or null if not a reference array\n *\n * @example\n * parseGenerationArrayReference(['~>Investor'])\n * // { mode: 'fuzzy', targetType: 'Investor', isOptional: false, isArray: true }\n */\nexport function parseGenerationArrayReference(fieldDef: string[]): ParsedGenerationReference | null {\n if (!Array.isArray(fieldDef) || fieldDef.length !== 1) return null\n const inner = fieldDef[0]\n if (typeof inner !== 'string') return null\n\n const parsed = parseGenerationReference(inner)\n if (!parsed) return null\n\n return {\n ...parsed,\n isArray: true,\n }\n}\n\n/**\n * Check if a field definition is a reference field.\n *\n * @param fieldDef - The field definition (string or array)\n * @returns true if this is a reference field\n *\n * @example\n * isReferenceField('->User') // true\n * isReferenceField('~>Industry?') // true\n * isReferenceField(['~>Investor']) // true\n * isReferenceField('User name') // false\n * isReferenceField(['tags']) // false\n */\nexport function isReferenceField(fieldDef: string | string[]): boolean {\n if (typeof fieldDef === 'string') {\n return parseGenerationReference(fieldDef) !== null\n }\n if (Array.isArray(fieldDef)) {\n return parseGenerationArrayReference(fieldDef) !== null\n }\n return false\n}\n\n/**\n * Extract reference mode from a field definition.\n *\n * @param fieldDef - The field definition\n * @returns 'exact' | 'fuzzy' | null\n */\nexport function getReferenceMode(fieldDef: string | string[]): 'exact' | 'fuzzy' | null {\n if (typeof fieldDef === 'string') {\n return parseGenerationReference(fieldDef)?.mode ?? null\n }\n if (Array.isArray(fieldDef)) {\n return parseGenerationArrayReference(fieldDef)?.mode ?? null\n }\n return null\n}\n\n/**\n * Extract target type(s) from a reference field.\n *\n * @param fieldDef - The field definition\n * @returns Target type string, array of types for unions, or null if not a reference\n */\nexport function getReferenceTargetType(fieldDef: string | string[]): string | string[] | null {\n let parsed: ParsedGenerationReference | null = null\n\n if (typeof fieldDef === 'string') {\n parsed = parseGenerationReference(fieldDef)\n } else if (Array.isArray(fieldDef)) {\n parsed = parseGenerationArrayReference(fieldDef)\n }\n\n if (!parsed) return null\n return parsed.targetTypes ?? parsed.targetType\n}\n\n/**\n * Parse seed configuration from a schema type's `$seed` field.\n *\n * Seed configuration tells the system where to fetch initial data for a type,\n * supporting TSV, CSV, and JSON formats with pagination support.\n *\n * @param value - The seed configuration. Can be:\n * - `string` - A URL (format inferred from extension: `.csv`, `.json`, or default `.tsv`)\n * - `Record<string, string>` - Object with explicit options\n *\n * @returns A SeedConfig object with:\n * - `url` - The data source URL\n * - `format` - Data format ('tsv', 'csv', or 'json')\n * - `idField` - Optional field to use as entity ID\n * - `next` - Optional JSONPath to pagination URL\n * - `data` - Optional JSONPath to data array in response\n *\n * @example\n * // Simple URL (format inferred)\n * parseSeedConfig('https://example.com/data.csv')\n * // { url: 'https://example.com/data.csv', format: 'csv' }\n *\n * @example\n * // URL with TSV default\n * parseSeedConfig('https://example.com/data')\n * // { url: 'https://example.com/data', format: 'tsv' }\n *\n * @example\n * // Object config with pagination\n * parseSeedConfig({\n * url: 'https://api.example.com/items',\n * format: 'json',\n * data: '$.items',\n * next: '$.pagination.next'\n * })\n * // { url: '...', format: 'json', data: '$.items', next: '$.pagination.next' }\n */\nexport function parseSeedConfig(value: string | Record<string, string>): SeedConfig {\n if (typeof value === 'string') {\n // Infer format from URL extension\n const url = value\n let format: 'tsv' | 'csv' | 'json' = 'tsv'\n if (url.endsWith('.csv')) format = 'csv'\n else if (url.endsWith('.json')) format = 'json'\n return { url, format }\n }\n // Object config with explicit options\n const config: SeedConfig = {\n url: value.url || value.$seed,\n format: (value.format as 'tsv' | 'csv' | 'json') || 'tsv',\n }\n if (value.idField) config.idField = value.idField\n if (value.next) config.next = value.next\n if (value.data) config.data = value.data\n return config\n}\n\n/**\n * Converts string fields to prompt fields in a seeded type's field map.\n *\n * In seeded schemas, plain string values represent prompts for AI generation\n * rather than simple field descriptions. This function performs the conversion\n * after initial field parsing, ensuring that JSONPath fields and reference\n * fields remain unchanged while string fields become prompt fields.\n *\n * @param fields - The parsed fields map from parseFieldType calls\n * @returns A new fields map with string fields converted to prompt fields\n *\n * @example\n * // Input: fields from a seeded type\n * const fields = {\n * title: { type: 'string', description: 'Some title' },\n * jsonField: { type: 'jsonpath', path: '$.name' },\n * ref: { type: 'reference', ref: 'Other', isArray: false },\n * }\n *\n * // Output: string -> prompt, others unchanged\n * const converted = convertStringsToPromptsInSeededType(fields)\n * // converted.title = { type: 'prompt', prompt: 'Some title' }\n * // converted.jsonField = { type: 'jsonpath', path: '$.name' }\n * // converted.ref = { type: 'reference', ref: 'Other', isArray: false }\n *\n * @remarks\n * This function is called during parseSchema when a type has `$seed` defined.\n * Only StringField types are converted; all other field types pass through unchanged.\n */\nexport function convertStringsToPromptsInSeededType(\n fields: Record<string, ParsedField>\n): Record<string, ParsedField> {\n const result: Record<string, ParsedField> = {}\n\n for (const [fieldName, field] of Object.entries(fields)) {\n if (isStringField(field)) {\n result[fieldName] = {\n type: 'prompt',\n prompt: field.description,\n }\n } else {\n result[fieldName] = field\n }\n }\n\n return result\n}\n\n/**\n * Parse an entire schema definition into a structured ParsedSchema.\n *\n * This is the main parsing function that takes a schema definition object and\n * produces a fully parsed representation with all types, fields, references,\n * and metadata resolved.\n *\n * @param schema - The schema definition object containing type definitions and metadata.\n * Metadata fields are prefixed with `$` (e.g., `$id`, `$context`, `$settings`).\n * All other keys are treated as type definitions.\n *\n * @returns A ParsedSchema object containing:\n * - `types` - Record of parsed type definitions with fields and references\n * - `hash` - Deterministic hash of the schema for versioning\n * - `settings` - Optional schema-level settings (e.g., iconLibrary)\n *\n * @example\n * const schema = parseSchema({\n * $id: 'https://db.sb/blog',\n * Post: {\n * title: 'Post title',\n * content: 'Main content',\n * author: '->User',\n * tags: ['Tag labels']\n * },\n * User: {\n * name: 'User name',\n * email: 'Email address',\n * posts: '->Post[]'\n * }\n * })\n *\n * // schema.types.Post.fields.title\n * // { type: 'string', description: 'Post title' }\n *\n * // schema.types.Post.references\n * // [{ field: 'author', ref: 'User', isArray: false }]\n *\n * @example\n * // Schema with seed configuration and icons\n * const schema = parseSchema({\n * $context: 'startups',\n * $settings: { iconLibrary: 'lucide' },\n * Company: {\n * $icon: 'building',\n * $seed: 'https://api.example.com/companies.json',\n * name: 'Company name',\n * website: 'Website URL'\n * }\n * })\n *\n * // schema.types.Company.icon === 'building'\n * // schema.types.Company.seed.url === 'https://api.example.com/companies.json'\n */\nexport function parseSchema(schema: SchemaDefinition): ParsedSchema {\n const types: Record<string, ParsedType> = {}\n\n // Extract schema-level $settings\n let settings: SchemaSettings | undefined\n const settingsValue = (schema as Record<string, unknown>).$settings\n if (settingsValue && typeof settingsValue === 'object' && settingsValue !== null) {\n const settingsObj = settingsValue as Record<string, unknown>\n if (settingsObj.iconLibrary || Object.keys(settingsObj).length > 0) {\n settings = {}\n if (typeof settingsObj.iconLibrary === 'string') {\n settings.iconLibrary = settingsObj.iconLibrary\n }\n }\n }\n\n // First pass: parse all types\n for (const [typeName, fields] of Object.entries(schema)) {\n // Skip metadata fields ($ prefixed)\n if (typeName.startsWith('$')) continue\n // Skip if not an object (metadata string values)\n if (typeof fields !== 'object' || fields === null) continue\n\n const parsedFields: Record<string, ParsedField> = {}\n const references: TypeReference[] = []\n let seed: SeedConfig | undefined\n let icon: string | undefined\n let group: string | undefined\n let seedNext: string | undefined\n let seedData: string | undefined\n let seedId: string | undefined\n let seedIdTransform: string | undefined\n // Entity lifecycle handlers\n const entityHandlers: Record<string, SerializedFunction> = {}\n // State machine configuration\n let parsedState: ParsedStateConfig | undefined\n // Data source configurations\n let source: SourceConfig | undefined\n let input: SourceInput | undefined\n let from: string[] | undefined\n let cache: string | undefined\n // Generative format configurations\n let image: ImageConfig | undefined\n let speech: SpeechConfig | undefined\n let diagram: DiagramConfig | undefined\n let conventions: ConventionsConfig | undefined\n let code: CodeConfig | undefined\n // Entity-level eval and experiment\n let entityEval: Record<string, EvalDefinition> | undefined\n let entityExperiment: SchemaExperiment | undefined\n\n for (const [fieldName, fieldValue] of Object.entries(fields)) {\n // Handle $seed metadata\n if (fieldName === '$seed') {\n seed = parseSeedConfig(fieldValue as string | Record<string, string>)\n continue\n }\n\n // Handle $next metadata (JSONPath to next page URL)\n if (fieldName === '$next') {\n if (typeof fieldValue === 'string') {\n seedNext = fieldValue\n }\n continue\n }\n\n // Handle $data metadata (JSONPath to data array)\n if (fieldName === '$data') {\n if (typeof fieldValue === 'string') {\n seedData = fieldValue\n }\n continue\n }\n\n // Handle $id metadata (JSONPath or transform for ID field)\n // Supports: '$.taskID', 'PascalCase($.example)', etc.\n if (fieldName === '$id') {\n if (typeof fieldValue === 'string') {\n const idConfig = parseIdConfig(fieldValue)\n seedId = idConfig.path\n seedIdTransform = idConfig.transform\n }\n continue\n }\n\n // Handle $icon metadata\n if (fieldName === '$icon') {\n if (typeof fieldValue === 'string') {\n icon = fieldValue\n }\n continue\n }\n\n // Handle $group metadata\n if (fieldName === '$group') {\n if (typeof fieldValue === 'string') {\n group = fieldValue\n }\n continue\n }\n\n // Handle entity lifecycle handlers ($created, $updated, $deleted)\n if (fieldName === '$created' || fieldName === '$updated' || fieldName === '$deleted') {\n if (typeof fieldValue === 'function') {\n entityHandlers[fieldName] = serializeFunction(fieldName, fieldValue)\n }\n continue\n }\n\n // Handle $state (state machine definition)\n if (fieldName === '$state') {\n if (typeof fieldValue === 'object' && fieldValue !== null && '$initial' in (fieldValue as object)) {\n parsedState = parseStateConfig(fieldValue as RawStateConfig)\n }\n continue\n }\n\n // Handle $source (external API source configuration)\n if (fieldName === '$source') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n source = fieldValue as unknown as SourceConfig\n }\n continue\n }\n\n // Handle $input (input parameters for source)\n if (fieldName === '$input') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n input = fieldValue as unknown as SourceInput\n }\n continue\n }\n\n // Handle $from (multi-source aggregation)\n if (fieldName === '$from') {\n if (Array.isArray(fieldValue)) {\n from = fieldValue as string[]\n }\n continue\n }\n\n // Handle $cache (cache duration)\n if (fieldName === '$cache') {\n if (typeof fieldValue === 'string') {\n cache = fieldValue\n }\n continue\n }\n\n // Handle $image (image generation configuration)\n if (fieldName === '$image') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n image = fieldValue as unknown as ImageConfig\n }\n continue\n }\n\n // Handle $speech (speech/TTS generation configuration)\n if (fieldName === '$speech') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n speech = fieldValue as unknown as SpeechConfig\n }\n continue\n }\n\n // Handle $diagram (diagram generation configuration)\n if (fieldName === '$diagram') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n diagram = fieldValue as unknown as DiagramConfig\n }\n continue\n }\n\n // Handle $code (code generation configuration)\n if (fieldName === '$code') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n code = fieldValue as unknown as CodeConfig\n }\n continue\n }\n\n // Handle $conventions (naming conventions)\n if (fieldName === '$conventions') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n conventions = fieldValue as unknown as ConventionsConfig\n }\n continue\n }\n\n // Handle $eval (entity-level evaluation definitions)\n if (fieldName === '$eval') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n entityEval = fieldValue as unknown as Record<string, EvalDefinition>\n }\n continue\n }\n\n // Handle $experiment (entity-level experiment definition)\n if (fieldName === '$experiment') {\n if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {\n entityExperiment = fieldValue as unknown as SchemaExperiment\n }\n continue\n }\n\n // Skip undefined field values\n if (fieldValue === undefined) continue\n\n const parsed = parseFieldType(fieldValue)\n parsedFields[fieldName] = parsed\n\n if (parsed.type === 'reference') {\n const refField = parsed as ReferenceField\n references.push({\n field: fieldName,\n ref: refField.ref || refField.refs?.[0] || '',\n refs: refField.refs,\n isArray: refField.isArray,\n optional: refField.optional,\n fuzzy: refField.fuzzy,\n })\n } else if (parsed.type === 'array') {\n const arrField = parsed as ArrayField\n // Track inline references from arrays\n if (arrField.refs) {\n for (const ref of arrField.refs) {\n references.push({\n field: fieldName,\n ref,\n isArray: true,\n optional: true, // Inline refs are always optional\n })\n }\n }\n // Track back references (for schema completeness, but these are read-only)\n if (arrField.backRef) {\n references.push({\n field: fieldName,\n ref: arrField.backRef,\n isArray: true,\n optional: true, // Back refs are collections\n backRef: true, // Mark as back reference - should not trigger generation\n })\n }\n }\n }\n\n // Merge $next, $data, $id into seed config if present\n if (seed) {\n if (seedNext) seed.next = seedNext\n if (seedData) seed.data = seedData\n if (seedId) seed.id = seedId\n if (seedIdTransform) seed.idTransform = seedIdTransform\n }\n\n // Post-process fields for seeded types: convert string fields to prompt fields\n // In seeded schemas, plain strings are prompts for AI generation, not string descriptions\n if (seed) {\n for (const [fieldName, field] of Object.entries(parsedFields)) {\n if (field.type === 'string') {\n const stringField = field as StringField\n parsedFields[fieldName] = {\n type: 'prompt',\n prompt: stringField.description,\n } as PromptField\n }\n }\n }\n\n // Determine if this is a source function type (provider:Type pattern)\n const isSourceFunction = typeName.includes(':') && !!source\n\n // Determine if this is a generative type\n const isGenerative = !!(image || speech || diagram || code)\n\n types[typeName] = {\n name: typeName,\n fields: parsedFields,\n references,\n ...(seed && { seed }),\n ...(icon && { icon }),\n ...(group && { group }),\n // Direct lifecycle handler access\n ...(entityHandlers['$created'] && { $created: entityHandlers['$created'] }),\n ...(entityHandlers['$updated'] && { $updated: entityHandlers['$updated'] }),\n ...(entityHandlers['$deleted'] && { $deleted: entityHandlers['$deleted'] }),\n // Grouped handlers (deprecated)\n ...(Object.keys(entityHandlers).length > 0 && { handlers: entityHandlers }),\n // State machine configuration\n ...(parsedState && { $state: parsedState }),\n // Data source configurations\n ...(source && { source }),\n ...(input && { input }),\n ...(from && { from }),\n ...(cache && { cache }),\n ...(isSourceFunction && { isSourceFunction }),\n // Generative format configurations\n ...(image && { image }),\n ...(speech && { speech }),\n ...(diagram && { diagram }),\n ...(code && { code }),\n ...(conventions && { conventions }),\n ...(isGenerative && { isGenerative }),\n // Entity-level eval and experiment\n ...(entityEval && { eval: entityEval }),\n ...(entityExperiment && { experiment: entityExperiment }),\n }\n }\n\n // Second pass: validate references (warn but don't crash on undefined types)\n for (const type of Object.values(types)) {\n for (const ref of type.references) {\n // Check all refs in union types\n const refsToCheck = ref.refs || [ref.ref]\n for (const refType of refsToCheck) {\n if (refType && !types[refType]) {\n // Warn instead of throwing - allows app to load with schema errors\n console.warn(`Reference to undefined type: ${refType} (in type ${type.name})`)\n }\n }\n }\n\n // Also validate jsonpath-embedded fields\n for (const [fieldName, field] of Object.entries(type.fields)) {\n if (field.type === 'jsonpath-embedded') {\n const embeddedType = (field as JSONPathEmbeddedField).embeddedType\n if (!types[embeddedType]) {\n console.warn(`JSONPath embedded reference to undefined type: ${embeddedType} (in type ${type.name}.${fieldName})`)\n }\n }\n }\n }\n\n // Third pass: detect embedded types (string fields that exactly match a type name)\n for (const type of Object.values(types)) {\n for (const [fieldName, field] of Object.entries(type.fields)) {\n if (field.type === 'string') {\n const desc = field.description\n\n // Check for embedded type pattern: TypeName, TypeName?, TypeName[]\n // Only match if the entire string is a type name (possibly with ? or [] suffix)\n const embeddedMatch = desc.match(/^(\\w+)(\\[\\])?(\\?)?$/)\n if (embeddedMatch) {\n const [, typeName, arrayMarker, optionalMarker] = embeddedMatch\n // Check if the type name exists in our schema\n if (types[typeName]) {\n // Convert to embedded field\n const embeddedField: EmbeddedField = {\n type: 'embedded',\n embeddedType: typeName,\n isArray: !!arrayMarker,\n optional: !!optionalMarker,\n }\n type.fields[fieldName] = embeddedField\n }\n }\n }\n }\n }\n\n // Parse schema-level directives\n let fn: Record<string, SerializedFunction> | undefined\n let on: Record<string, SerializedFunction> | undefined\n let evalDefs: Record<string, EvalDefinition> | undefined\n let experiment: Record<string, SchemaExperiment> | undefined\n let analytics: SchemaAnalytics | undefined\n\n const schemaObj = schema as Record<string, unknown>\n\n // Parse $fn - schema-level functions\n if (schemaObj.$fn && typeof schemaObj.$fn === 'object') {\n fn = {}\n for (const [name, func] of Object.entries(schemaObj.$fn)) {\n if (typeof func === 'function') {\n fn[name] = serializeFunction(name, func)\n }\n }\n }\n\n // Parse $on - schema-level event handlers\n if (schemaObj.$on && typeof schemaObj.$on === 'object') {\n on = {}\n for (const [name, func] of Object.entries(schemaObj.$on)) {\n if (typeof func === 'function') {\n on[name] = serializeFunction(name, func)\n }\n }\n }\n\n // Parse $eval - evaluation definitions\n if (schemaObj.$eval && typeof schemaObj.$eval === 'object') {\n evalDefs = schemaObj.$eval as Record<string, EvalDefinition>\n }\n\n // Parse $experiment - experiment definitions\n if (schemaObj.$experiment && typeof schemaObj.$experiment === 'object') {\n experiment = schemaObj.$experiment as Record<string, SchemaExperiment>\n }\n\n // Parse $analytics - analytics configuration\n if (schemaObj.$analytics && typeof schemaObj.$analytics === 'object') {\n analytics = schemaObj.$analytics as SchemaAnalytics\n }\n\n // Parse schema-level lifecycle handlers ($seeded, $ready, $error)\n const schemaHandlers: Record<string, SerializedFunction> = {}\n for (const key of ['$seeded', '$ready', '$error']) {\n if (typeof schemaObj[key] === 'function') {\n schemaHandlers[key] = serializeFunction(key, schemaObj[key] as Function)\n }\n }\n\n return {\n types,\n hash: schemaHash(schema),\n ...(settings && { settings }),\n ...(fn && { fn }),\n ...(on && { on }),\n ...(evalDefs && { eval: evalDefs }),\n ...(experiment && { experiment }),\n ...(analytics && { analytics }),\n ...(Object.keys(schemaHandlers).length > 0 && { handlers: schemaHandlers }),\n }\n}\n\n/**\n * Convert a parsed type definition to a JSON Schema representation.\n *\n * Transforms the internal ParsedType format into a standard JSON Schema object\n * that can be used for validation, documentation, or AI generation prompts.\n *\n * @param parsedType - The parsed type definition to convert\n * @param parsedSchema - Optional full schema for resolving embedded types.\n * When provided, embedded types (e.g., `Address` in `address: 'Address'`) are\n * recursively expanded into their full JSON Schema representation.\n * @param seen - Internal set for tracking visited types to prevent infinite recursion\n * in circular reference scenarios. Do not pass this parameter manually.\n *\n * @returns A JSON Schema object with:\n * - `type: 'object'` - Always an object schema\n * - `properties` - Map of field names to their JSON Schema definitions\n * - `required` - Array of required field names (non-optional fields)\n * - `additionalProperties: false` - Strict schema, no extra fields allowed\n *\n * @example\n * const parsed = parseSchema({\n * $context: 'blog',\n * Post: {\n * title: 'Post title',\n * author: '->User',\n * tags: ['List 3-5 keywords']\n * }\n * })\n *\n * const jsonSchema = toJSONSchema(parsed.types.Post, parsed)\n * // {\n * // type: 'object',\n * // properties: {\n * // title: { type: 'string', description: 'Post title' },\n * // author: { type: 'string', description: 'Reference to User (ID)' },\n * // tags: { type: 'array', items: { type: 'string' }, minItems: 3, maxItems: 5 }\n * // },\n * // required: ['title', 'author', 'tags'],\n * // additionalProperties: false\n * // }\n *\n * @example\n * // With embedded types expanded\n * const schema = parseSchema({\n * $context: 'app',\n * User: {\n * name: 'User name',\n * address: 'Address' // Embedded type\n * },\n * Address: {\n * street: 'Street',\n * city: 'City'\n * }\n * })\n *\n * const jsonSchema = toJSONSchema(schema.types.User, schema)\n * // properties.address will contain the full Address schema inline\n */\nexport function toJSONSchema(\n parsedType: ParsedType,\n parsedSchemaOrIncludeRefs?: ParsedSchema | boolean,\n seen: Set<string> = new Set()\n): JSONSchema {\n // Support both old API (boolean for includeReferences) and new API (ParsedSchema)\n const parsedSchema = typeof parsedSchemaOrIncludeRefs === 'object' ? parsedSchemaOrIncludeRefs : undefined\n const includeReferences = typeof parsedSchemaOrIncludeRefs === 'boolean' ? parsedSchemaOrIncludeRefs : true\n\n const properties: Record<string, JSONSchemaProperty> = {}\n const required: string[] = []\n\n for (const [fieldName, field] of Object.entries(parsedType.fields)) {\n // Skip computed fields - they're derived, not generated\n if (field.type === 'computed') {\n continue\n }\n\n const isOptional = 'optional' in field && field.optional\n\n if (field.type === 'string') {\n properties[fieldName] = {\n type: 'string',\n description: field.description,\n }\n } else if (field.type === 'reference' && includeReferences) {\n const refName = field.refs ? field.refs.join(' | ') : field.ref\n if (field.isArray) {\n properties[fieldName] = {\n type: 'array',\n items: { type: 'string' },\n description: `Array of ${refName} references (IDs)`,\n }\n } else {\n properties[fieldName] = {\n type: 'string',\n description: `Reference to ${refName} (ID)`,\n }\n }\n } else if (field.type === 'array') {\n const arrayProp: JSONSchemaProperty = {\n type: 'array',\n items: { type: 'string' },\n description: field.description,\n }\n // Wire up minItems/maxItems from parsed count\n if (field.count !== undefined) {\n if (typeof field.count === 'number') {\n arrayProp.minItems = field.count\n arrayProp.maxItems = field.count\n } else {\n arrayProp.minItems = field.count.min\n arrayProp.maxItems = field.count.max\n }\n }\n properties[fieldName] = arrayProp\n } else if (field.type === 'object') {\n const nestedProps: Record<string, JSONSchemaProperty> = {}\n const nestedRequired: string[] = []\n for (const [propName, propField] of Object.entries(field.properties)) {\n nestedProps[propName] = {\n type: 'string',\n description: propField.description,\n }\n nestedRequired.push(propName)\n }\n properties[fieldName] = {\n type: 'object',\n properties: nestedProps,\n required: nestedRequired,\n }\n } else if (field.type === 'embedded' && parsedSchema) {\n // Recursively embed the referenced type's JSON schema\n const embeddedTypeName = field.embeddedType\n const embeddedType = parsedSchema.types[embeddedTypeName]\n\n if (embeddedType) {\n // Determine if we're in a circular reference situation\n const isCircular = seen.has(embeddedTypeName)\n\n // Get the embedded type's JSON schema\n // For circular refs, stop recursion by not passing parsedSchema\n // For normal refs, continue with updated seen set\n const newSeen = isCircular ? seen : new Set([...seen, embeddedTypeName])\n const embeddedSchema = toJSONSchema(embeddedType, isCircular ? undefined : parsedSchema, newSeen)\n\n // Build the embedded object schema\n const embeddedObjectSchema = {\n type: 'object' as const,\n properties: embeddedSchema.properties,\n required: embeddedSchema.required,\n additionalProperties: false,\n }\n\n if (field.isArray) {\n properties[fieldName] = {\n type: 'array',\n items: embeddedObjectSchema,\n }\n } else {\n properties[fieldName] = embeddedObjectSchema\n }\n }\n } else if (field.type === 'embedded') {\n // If no parsedSchema provided, fall back to string representation\n properties[fieldName] = {\n type: 'string',\n description: field.embeddedType,\n }\n }\n\n // Only add to required if:\n // - not optional AND\n // - (not a reference OR includeReferences is true)\n const isReference = field.type === 'reference'\n if (!isOptional && (!isReference || includeReferences)) {\n required.push(fieldName)\n }\n }\n\n return {\n type: 'object',\n properties,\n required,\n additionalProperties: false,\n }\n}\n\n/**\n * Generate a deterministic hash for a schema definition.\n *\n * Creates a consistent 8-character hexadecimal hash that uniquely identifies\n * a schema's structure. The hash is computed using the FNV-1a algorithm on\n * the JSON-serialized schema with sorted keys, ensuring the same schema\n * always produces the same hash regardless of property order.\n *\n * @param schema - The schema definition to hash\n *\n * @returns An 8-character hexadecimal hash string\n *\n * @example\n * const hash1 = schemaHash({\n * $context: 'blog',\n * Post: { title: 'Title' }\n * })\n * // e.g., 'a1b2c3d4'\n *\n * // Same schema, different property order = same hash\n * const hash2 = schemaHash({\n * Post: { title: 'Title' },\n * $context: 'blog'\n * })\n * // hash1 === hash2\n *\n * @example\n * // Used for schema versioning\n * const schema = parseSchema({ $context: 'app', User: { name: 'Name' } })\n * console.log(schema.hash)\n * // The hash can be used to detect schema changes and trigger migrations\n */\nexport function schemaHash(schema: SchemaDefinition): string {\n // Sort keys recursively for consistent hashing\n const sortedSchema = sortObject(schema)\n const json = JSON.stringify(sortedSchema)\n\n // Simple hash function (FNV-1a)\n let hash = 2166136261\n for (let i = 0; i < json.length; i++) {\n hash ^= json.charCodeAt(i)\n hash = (hash * 16777619) >>> 0\n }\n return hash.toString(16).padStart(8, '0')\n}\n\nfunction sortObject(obj: Record<string, unknown>): Record<string, unknown> {\n if (typeof obj !== 'object' || obj === null) {\n return obj\n }\n\n if (Array.isArray(obj)) {\n return obj.map(sortObject) as unknown as Record<string, unknown>\n }\n\n const sorted: Record<string, unknown> = {}\n for (const key of Object.keys(obj).sort()) {\n sorted[key] = sortObject(obj[key] as Record<string, unknown>)\n }\n return sorted\n}\n\n// ============================================================================\n// SDK Configuration\n// ============================================================================\n\n/**\n * Get the default API base URL. Reads environment variable dynamically\n * to support test mocking.\n */\nfunction getDefaultApiBase(): string {\n return (typeof process !== 'undefined' && process.env?.DB4AI_API_BASE) || 'https://db4ai.dev'\n}\n\n// ============================================================================\n// Job: Tracking async operations\n// ============================================================================\n\nexport type JobStatus = 'queued' | 'running' | 'completed' | 'failed'\n\nexport interface Job<T = void> {\n id: string\n status: JobStatus\n result?: T\n error?: Error\n}\n\nfunction createJob<T>(): Job<T> {\n return {\n id: `job_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`,\n status: 'queued',\n }\n}\n\n// ============================================================================\n// EntityCollection: Callable, iterable collection of entities\n// ============================================================================\n\n/**\n * EntityCollection is both a factory function and an iterable collection.\n * - As factory: `await db.Idea('id', { concept: '...' })`\n * - As collection: `for (const idea of db.Idea) { ... }`\n */\n/** Options for listing entities */\nexport interface ListOptions {\n /** Maximum number of entities to return */\n limit?: number\n /** Number of entities to skip */\n offset?: number\n /** Filter criteria */\n filter?: Record<string, unknown>\n}\n\nexport interface EntityCollection<T extends Record<string, unknown> = Record<string, unknown>> extends Iterable<T> {\n /** The type name of entities in this collection */\n readonly $type: string\n\n /** Current count of entities in the local collection */\n readonly $count: number\n\n /** Execute a function for each entity, returns a Job for tracking */\n forEach(fn: (item: T) => void): Job<void>\n\n /** Transform each entity, returns a Combinable for chaining */\n map<R>(fn: (item: T) => R): Combinable<R>\n\n /** Filter entities by predicate, returns a Combinable for chaining */\n where(predicate: (item: T) => boolean): Combinable<T>\n\n /** Fetch all entities from API and populate collection */\n fetchAll(): Promise<T[]>\n\n /** List entities with optional limit, offset, and filter */\n list(options?: ListOptions): Promise<T[]>\n\n /** Get a single entity by ID */\n get(id: string): Promise<T | undefined>\n\n /** Create a new entity with the given data */\n create(data: Partial<T>): Promise<T>\n\n /** Factory function signature - call the collection to generate/fetch an entity */\n (id: string, context?: Record<string, unknown>): Promise<T>\n}\n\n/**\n * Internal class for managing entity collection state\n */\nclass EntityCollectionImpl<T extends Record<string, unknown>> {\n readonly $type: string\n private _items: T[] = []\n private _baseUrl: string\n private _namespace: string\n private _registerSchema: () => Promise<void>\n\n constructor(typeName: string, baseUrl: string, namespace: string, registerSchema: () => Promise<void>) {\n this.$type = typeName\n this._baseUrl = baseUrl\n this._namespace = namespace\n this._registerSchema = registerSchema\n }\n\n get $count(): number {\n return this._items.length\n }\n\n _addItem(item: T): void {\n this._items.push(item)\n }\n\n _setItems(items: T[]): void {\n this._items = items\n }\n\n _getItems(): T[] {\n return this._items\n }\n\n [Symbol.iterator](): Iterator<T> {\n return this._items[Symbol.iterator]()\n }\n\n forEach(fn: (item: T) => void): Job<void> {\n const job = createJob<void>()\n job.status = 'running'\n try {\n for (const item of this._items) {\n fn(item)\n }\n job.status = 'completed'\n } catch (error) {\n job.status = 'failed'\n job.error = error instanceof Error ? error : new Error(String(error))\n }\n return job\n }\n\n map<R>(fn: (item: T) => R): Combinable<R> {\n const items = this._items\n return new Combinable(function* () {\n for (const item of items) {\n yield fn(item)\n }\n })\n }\n\n where(predicate: (item: T) => boolean): Combinable<T> {\n const items = this._items\n return new Combinable(function* () {\n for (const item of items) {\n if (predicate(item)) {\n yield item\n }\n }\n })\n }\n\n async fetchAll(): Promise<T[]> {\n await this._registerSchema()\n const url = `${this._baseUrl}/api/${this._namespace}/${this.$type}`\n const res = await fetch(url)\n if (!res.ok) {\n throw new APIError('GENERATION_FAILED', `Failed to fetch ${this.$type}: ${await res.text()}`, res.status)\n }\n const data = await res.json()\n const items = Array.isArray(data) ? data : data.items || []\n this._setItems(items)\n return items\n }\n\n async list(options: ListOptions = {}): Promise<T[]> {\n await this._registerSchema()\n const params = new URLSearchParams()\n if (options.limit !== undefined) params.set('limit', String(options.limit))\n if (options.offset !== undefined) params.set('offset', String(options.offset))\n if (options.filter) {\n for (const [key, value] of Object.entries(options.filter)) {\n if (value !== undefined && value !== null) {\n params.set(key, String(value))\n }\n }\n }\n const queryString = params.toString()\n const url = `${this._baseUrl}/api/${this._namespace}/${this.$type}${queryString ? `?${queryString}` : ''}`\n const res = await fetch(url)\n if (!res.ok) {\n throw new APIError('GENERATION_FAILED', `Failed to list ${this.$type}: ${await res.text()}`, res.status)\n }\n const data = await res.json()\n const items = Array.isArray(data) ? data : data.items || []\n this._setItems(items)\n return items\n }\n\n async get(id: string): Promise<T | undefined> {\n await this._registerSchema()\n const url = `${this._baseUrl}/api/${this._namespace}/${this.$type}/${id}`\n const res = await fetch(url)\n if (res.status === 404) {\n return undefined\n }\n if (!res.ok) {\n throw new APIError('GENERATION_FAILED', `Failed to get ${this.$type}/${id}: ${await res.text()}`, res.status)\n }\n return await res.json()\n }\n\n async create(data: Partial<T>): Promise<T> {\n await this._registerSchema()\n const url = `${this._baseUrl}/api/${this._namespace}/${this.$type}`\n const res = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n })\n if (!res.ok) {\n throw new APIError('GENERATION_FAILED', `Failed to create ${this.$type}: ${await res.text()}`, res.status)\n }\n const created = await res.json()\n this._addItem(created)\n return created\n }\n}\n\n/**\n * Create a callable EntityCollection using a Proxy.\n * The returned object is both a function (factory) and has collection methods/properties.\n */\nfunction createEntityCollection<T extends Record<string, unknown>>(\n typeName: string,\n baseUrl: string,\n namespace: string,\n registerSchema: () => Promise<void>,\n factory: (id: string, context?: Record<string, unknown>) => Promise<T>\n): EntityCollection<T> {\n const collection = new EntityCollectionImpl<T>(typeName, baseUrl, namespace, registerSchema)\n\n // Create a proxy around the factory function\n return new Proxy(factory, {\n get(target, prop) {\n // Handle Symbol.iterator for iteration\n if (prop === Symbol.iterator) {\n return () => collection[Symbol.iterator]()\n }\n\n // Return collection properties and methods\n if (prop === '$type') return collection.$type\n if (prop === '$count') return collection.$count\n if (prop === 'forEach') return collection.forEach.bind(collection)\n if (prop === 'map') return collection.map.bind(collection)\n if (prop === 'where') return collection.where.bind(collection)\n if (prop === 'fetchAll') return collection.fetchAll.bind(collection)\n if (prop === 'list') return collection.list.bind(collection)\n if (prop === 'get') return collection.get.bind(collection)\n if (prop === 'create') return collection.create.bind(collection)\n\n // Internal methods for testing/manipulation\n if (prop === '_addItem') return collection._addItem.bind(collection)\n if (prop === '_setItems') return collection._setItems.bind(collection)\n if (prop === '_getItems') return collection._getItems.bind(collection)\n\n return undefined\n },\n apply(target, thisArg, args) {\n // When called as a function, invoke the factory\n return factory(args[0] as string, args[1] as Record<string, unknown> | undefined)\n },\n }) as EntityCollection<T>\n}\n\n// Instance type for generated objects\nexport interface DBInstance<T = Record<string, unknown>> {\n id: string\n type: string\n data: T\n}\n\n// Generated object with all fields resolved\nexport type GeneratedObject = Record<string, unknown>\n\n// Factory function type - async for API-based generation\nexport type TypeFactory = (id: string, context?: Record<string, unknown>) => Promise<GeneratedObject>\n\n// Base properties of DBResult (non-dynamic)\nexport interface DBResultBase {\n schema: SchemaDefinition\n types: Record<string, ParsedType>\n hash: string\n id?: string // Full $id if specified\n context?: string // Shared context/namespace (from $context or parsed from $id)\n namespace: string // The resolved namespace (always present)\n baseUrl: string // API base URL (from $id or default)\n instances: DBInstance[] // Collected instances defined with this schema\n toJSONSchema: (typeName: string) => JSONSchema\n registerSchema: () => Promise<void> // Manually register schema with API\n}\n\n// Return type for DB function\n// Dynamic type accessor - generates objects via API\n// Usage: await db.Blog('my-blog', { topic: '...' }) -> GeneratedObject\n// Also works as collection: for (const blog of db.Blog) { ... }\nexport type DBResult = DBResultBase & Record<string, EntityCollection>\n\n/**\n * Extract API base URL from $id\n * @example\n * getApiBaseFromId('https://db.sb/blogs') // 'https://db.sb'\n * getApiBaseFromId('https://startups.db.sb') // 'https://startups.db.sb'\n * getApiBaseFromId('my-namespace') // undefined (use default)\n */\nfunction getApiBaseFromId(id: string): string | undefined {\n // If it's not a URL, return undefined to use default\n if (!id.startsWith('http://') && !id.startsWith('https://')) {\n return undefined\n }\n try {\n const url = new URL(id)\n return `${url.protocol}//${url.host}`\n } catch {\n return undefined\n }\n}\n\n/**\n * Parse namespace from $id - supports both full URLs and plain namespace strings\n * @example\n * parseIdNamespace('https://db.sb/blogs') // 'blogs'\n * parseIdNamespace('my-namespace') // 'my-namespace'\n * parseIdNamespace('https://db.sb/') // null\n */\nfunction parseIdNamespace(id: string): string | null {\n // If it's not a URL, treat the whole string as the namespace\n if (!id.startsWith('http://') && !id.startsWith('https://')) {\n const trimmed = id.trim()\n return trimmed || null\n }\n // Otherwise parse as URL\n return parseNamespaceFromId(id)\n}\n\n/**\n * Resolve all references in a generated object recursively\n */\nasync function resolveReferences(\n obj: GeneratedObject,\n typeName: string,\n parsed: ParsedSchema,\n baseUrl: string,\n namespace: string,\n cache: Map<string, GeneratedObject>\n): Promise<GeneratedObject> {\n const type = parsed.types[typeName]\n if (!type) return obj\n\n const resolved: GeneratedObject = { ...obj }\n\n for (const [fieldName, field] of Object.entries(type.fields)) {\n const value = obj[fieldName]\n if (value === undefined || value === null) continue\n\n if (field.type === 'array' && field.refs && Array.isArray(value)) {\n // Inline references: ['... ->Type'] - resolve each ID to full object\n const refType = field.refs[0]\n const resolvedItems = await Promise.all(\n (value as string[]).map(async (refId) => {\n const cacheKey = `${refType}:${refId}`\n if (cache.has(cacheKey)) return cache.get(cacheKey)!\n\n // If refId is already a URL, use it directly; otherwise construct URL\n const refUrl = refId.startsWith('http://') || refId.startsWith('https://')\n ? refId\n : `${baseUrl}/api/${namespace}/${refType}/${refId}`\n const refRes = await fetch(refUrl)\n if (!refRes.ok) return { id: refId, _error: 'Failed to resolve' }\n\n const refObj = await refRes.json()\n cache.set(cacheKey, refObj)\n\n // Recursively resolve nested references\n return resolveReferences(refObj, refType, parsed, baseUrl, namespace, cache)\n })\n )\n resolved[fieldName] = resolvedItems\n } else if (field.type === 'reference' && !field.isArray && typeof value === 'string') {\n // Single reference: ->Type - resolve to full object\n const refType = field.ref || field.refs?.[0]\n if (refType) {\n const cacheKey = `${refType}:${value}`\n if (cache.has(cacheKey)) {\n resolved[fieldName] = cache.get(cacheKey)!\n } else {\n // If value is already a URL, use it directly; otherwise construct URL\n const refUrl = value.startsWith('http://') || value.startsWith('https://')\n ? value\n : `${baseUrl}/api/${namespace}/${refType}/${value}`\n const refRes = await fetch(refUrl)\n if (refRes.ok) {\n const refObj = await refRes.json()\n cache.set(cacheKey, refObj)\n resolved[fieldName] = await resolveReferences(refObj, refType, parsed, baseUrl, namespace, cache)\n }\n }\n }\n } else if (field.type === 'reference' && field.isArray && Array.isArray(value)) {\n // Array reference: ->Type[] - resolve each ID to full object\n const refType = field.ref || field.refs?.[0]\n if (refType) {\n const resolvedItems = await Promise.all(\n (value as string[]).map(async (refId) => {\n const cacheKey = `${refType}:${refId}`\n if (cache.has(cacheKey)) return cache.get(cacheKey)!\n\n // If refId is already a URL, use it directly; otherwise construct URL\n const refUrl = refId.startsWith('http://') || refId.startsWith('https://')\n ? refId\n : `${baseUrl}/api/${namespace}/${refType}/${refId}`\n const refRes = await fetch(refUrl)\n if (!refRes.ok) return { id: refId, _error: 'Failed to resolve' }\n\n const refObj = await refRes.json()\n cache.set(cacheKey, refObj)\n return resolveReferences(refObj, refType, parsed, baseUrl, namespace, cache)\n })\n )\n resolved[fieldName] = resolvedItems\n }\n }\n // Back references (['<-Type']) are populated by the API, no client-side resolution needed\n }\n\n return resolved\n}\n\n/**\n * Create a database instance from a schema definition.\n *\n * This is the main entry point for defining and working with a db4.ai schema.\n * It parses the schema, registers it with the API, and returns a typed object\n * that provides access to all defined types as EntityCollections.\n *\n * ## API Base URL Configuration\n *\n * The SDK determines the API base URL in the following priority order:\n * 1. Host from `$id` if it's a full URL (e.g., `'https://custom.api.com/myapp'`)\n * 2. `DB4AI_API_BASE` environment variable\n * 3. Default: `'https://db4ai.dev'`\n *\n * @param schema - The schema definition object. Must include either:\n * - `$id` - A URL or namespace identifier (e.g., `'https://db.sb/blog'` or `'blog'`)\n * - `$context` - A namespace string (e.g., `'my-app'`)\n *\n * Type definitions are records where keys are type names and values define fields.\n *\n * @returns A DBResult object providing:\n * - `schema` - The original schema definition\n * - `types` - Parsed type definitions\n * - `hash` - Schema version hash\n * - `namespace` - The resolved namespace\n * - `baseUrl` - API base URL\n * - `toJSONSchema(typeName)` - Convert a type to JSON Schema\n * - `registerSchema()` - Manually register the schema with the API\n * - Dynamic type accessors (e.g., `db.Post`, `db.User`) as EntityCollections\n *\n * @throws Error if neither `$id` nor `$context` is provided\n *\n * @example\n * // Define a blog schema\n * const db = DB({\n * $context: 'blog',\n * Post: {\n * title: 'Post title',\n * content: 'Main content',\n * author: '->User',\n * tags: ['List 3-5 keywords']\n * },\n * User: {\n * name: 'User name',\n * email: 'Email address'\n * }\n * })\n *\n * @example\n * // Generate a new post\n * const post = await db.Post('my-first-post', { topic: 'AI' })\n * console.log(post.title, post.content)\n *\n * @example\n * // Fetch all posts and iterate\n * await db.Post.fetchAll()\n * for (const post of db.Post) {\n * console.log(post.title)\n * }\n *\n * @example\n * // Use with full URL\n * const db = DB({\n * $id: 'https://db.sb/startups',\n * Company: {\n * name: 'Company name',\n * description: 'Company description'\n * }\n * })\n */\nexport function DB(schema: SchemaDefinition) {\n const parsed = parseSchema(schema)\n const metadata = schema as SchemaMetadata\n const schemaId = metadata.$id\n const schemaContext = metadata.$context\n\n // Either $id or $context is required\n if (!schemaId && !schemaContext) {\n throw new SchemaValidationError('MISSING_CONTEXT', 'Schema must have $id or $context set (e.g., $context: \"my-app\" or $id: \"https://db4ai.dev/my-app\")')\n }\n\n // Parse namespace from $id (URL or plain string) or use $context directly\n let namespace: string | null = null\n let baseUrl: string = getDefaultApiBase()\n\n if (schemaContext) {\n // $context is always just a namespace, uses default base URL\n namespace = schemaContext.trim() || null\n }\n\n if (schemaId) {\n // $id can be a full URL or plain namespace\n namespace = parseIdNamespace(schemaId)\n // Use $id's host if it's a URL (overrides default/env var)\n const idBaseUrl = getApiBaseFromId(schemaId)\n if (idBaseUrl) {\n baseUrl = idBaseUrl\n }\n }\n\n if (!namespace) {\n throw new SchemaValidationError('MISSING_NAMESPACE', 'Schema must specify a namespace via $context or $id (e.g., $context: \"my-app\")')\n }\n\n const instances: DBInstance[] = []\n\n // Track schema registration state\n let schemaRegistered = false\n let schemaRegistrationPromise: Promise<void> | null = null\n\n // Register schema with API (idempotent, cached)\n async function registerSchema(): Promise<void> {\n if (schemaRegistered) return\n if (schemaRegistrationPromise) return schemaRegistrationPromise\n\n schemaRegistrationPromise = (async () => {\n const res = await fetch(`${baseUrl}/api/${namespace}/schema`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(schema),\n })\n\n if (!res.ok) {\n const error = await res.text()\n throw new APIError('REGISTRATION_FAILED', `Failed to register schema: ${error}`, res.status)\n }\n\n schemaRegistered = true\n })()\n\n return schemaRegistrationPromise\n }\n\n // Create base result object\n const base = {\n schema,\n types: parsed.types,\n hash: parsed.hash,\n id: schemaId,\n context: schemaContext,\n namespace,\n baseUrl,\n instances,\n registerSchema,\n toJSONSchema: (typeName: string) => {\n const type = parsed.types[typeName]\n if (!type) throw new SchemaValidationError('INVALID_FIELD_TYPE', `Unknown type: ${typeName}`)\n return toJSONSchema(type, parsed)\n },\n }\n\n // Cache EntityCollections so the same instance is returned each time\n const collectionCache = new Map<string, EntityCollection>()\n\n // Create a proxy that handles dynamic type access\n return new Proxy(base, {\n get(target, prop) {\n // Return known properties directly\n if (prop in target) {\n return target[prop as keyof typeof target]\n }\n\n // For type names, return an EntityCollection (cached)\n const typeName = String(prop)\n if (parsed.types[typeName]) {\n // Return cached collection if exists\n if (collectionCache.has(typeName)) {\n return collectionCache.get(typeName)!\n }\n\n // Create factory function for this type\n const factory = async (id: string, context?: Record<string, unknown>): Promise<GeneratedObject> => {\n // Ensure schema is registered\n await registerSchema()\n\n // Build URL with context as query params if provided\n let url = `${baseUrl}/api/${namespace}/${typeName}/${id}`\n if (context && Object.keys(context).length > 0) {\n const params = new URLSearchParams()\n for (const [key, value] of Object.entries(context)) {\n if (value !== undefined && value !== null) {\n params.set(key, String(value))\n }\n }\n url += `?${params.toString()}`\n }\n\n // Fetch/generate the object with extended timeout for long-running generations\n // Default Node.js undici timeout is 300s, but Blog generation can take 80-150s\n // We use 10 minutes to handle complex hierarchies with AI latency variance\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), 600000) // 10 minute timeout\n try {\n const res = await fetch(url, { signal: controller.signal })\n clearTimeout(timeoutId)\n if (!res.ok) {\n const error = await res.text()\n throw new APIError('GENERATION_FAILED', `Failed to generate ${typeName}/${id}: ${error}`, res.status)\n }\n\n const obj = await res.json()\n\n // Resolve all references recursively\n const cache = new Map<string, GeneratedObject>()\n return resolveReferences(obj, typeName, parsed, baseUrl, namespace, cache)\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n // Create and cache the EntityCollection\n const collection = createEntityCollection(typeName, baseUrl, namespace, registerSchema, factory)\n collectionCache.set(typeName, collection)\n return collection\n }\n return undefined\n },\n }) as DBResult\n}\n\n// ============================================================================\n// Combinable: Lazy cartesian product pipeline builder\n// ============================================================================\n\n/**\n * A lazy pipeline builder for cartesian products and collection transformations.\n *\n * Combinable provides a fluent API for building transformation pipelines where\n * no computation happens until a terminal operation is invoked. This enables\n * efficient processing of large datasets and cartesian products.\n *\n * Key features:\n * - Lazy evaluation: transformations are only applied when results are consumed\n * - Chainable: all intermediate operations return new Combinable instances\n * - Iterable: works with for...of loops and spread operator\n *\n * Intermediate operations (return Combinable):\n * - `where(predicate)` - Filter items by predicate\n * - `map(fn)` - Transform each item\n * - `take(n)` - Limit to first n items\n * - `skip(n)` - Skip first n items\n *\n * Terminal operations (trigger evaluation):\n * - `all()` - Collect all results into an array\n * - `first()` - Get the first result or undefined\n * - `count()` - Count total results\n * - Iteration via for...of or spread\n *\n * @example\n * // Basic cartesian product\n * const pairs = combine([1, 2, 3], ['a', 'b']).all()\n * // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b'], [3, 'a'], [3, 'b']]\n *\n * @example\n * // Chained transformations\n * const result = combine([1, 2, 3], [10, 20, 30])\n * .where(([a, b]) => a + b > 15)\n * .map(([a, b]) => a * b)\n * .take(3)\n * .all()\n * // [20, 30, 40]\n *\n * @example\n * // Lazy evaluation with for...of\n * for (const [x, y] of combine(range(1000), range(1000)).take(10)) {\n * console.log(x, y) // Only computes first 10 pairs\n * }\n *\n * @example\n * // From EntityCollection\n * await db.User.fetchAll()\n * const activeUsers = db.User\n * .where(user => user.isActive)\n * .map(user => user.email)\n * .all()\n */\nexport class Combinable<T> implements Iterable<T> {\n private readonly source: () => Generator<T>\n\n constructor(source: () => Generator<T>) {\n this.source = source\n }\n\n /**\n * Filter combinations by predicate\n */\n where(predicate: (item: T) => boolean): Combinable<T> {\n const source = this.source\n return new Combinable(function* () {\n for (const item of source()) {\n if (predicate(item)) {\n yield item\n }\n }\n })\n }\n\n /**\n * Transform each combination\n */\n map<R>(fn: (item: T) => R): Combinable<R> {\n const source = this.source\n return new Combinable(function* () {\n for (const item of source()) {\n yield fn(item)\n }\n })\n }\n\n /**\n * Limit to first n items\n */\n take(n: number): Combinable<T> {\n const source = this.source\n return new Combinable(function* () {\n let count = 0\n for (const item of source()) {\n if (count >= n) break\n yield item\n count++\n }\n })\n }\n\n /**\n * Skip first n items\n */\n skip(n: number): Combinable<T> {\n const source = this.source\n return new Combinable(function* () {\n let count = 0\n for (const item of source()) {\n if (count >= n) {\n yield item\n }\n count++\n }\n })\n }\n\n /**\n * Collect all results into an array (terminal operation)\n */\n all(): T[] {\n return [...this.source()]\n }\n\n /**\n * Get the first result or undefined (terminal operation)\n */\n first(): T | undefined {\n const iterator = this.source()\n const result = iterator.next()\n return result.done ? undefined : result.value\n }\n\n /**\n * Count total results (terminal operation)\n */\n count(): number {\n let count = 0\n for (const _ of this.source()) {\n count++\n }\n return count\n }\n\n /**\n * Make Combinable iterable with for...of and spread operator\n */\n [Symbol.iterator](): Iterator<T> {\n return this.source()\n }\n}\n\n// Overloaded combine function signatures for type inference\nexport function combine<A, B>(a: Iterable<A>, b: Iterable<B>): Combinable<[A, B]>\nexport function combine<A, B, C>(a: Iterable<A>, b: Iterable<B>, c: Iterable<C>): Combinable<[A, B, C]>\nexport function combine<A, B, C, D>(a: Iterable<A>, b: Iterable<B>, c: Iterable<C>, d: Iterable<D>): Combinable<[A, B, C, D]>\nexport function combine<A, B, C, D, E>(a: Iterable<A>, b: Iterable<B>, c: Iterable<C>, d: Iterable<D>, e: Iterable<E>): Combinable<[A, B, C, D, E]>\n\n/**\n * Create cartesian product of multiple iterables.\n * Returns a lazy Combinable that only computes when iterated or terminal operation is called.\n *\n * @example\n * const result = combine([1, 2], ['a', 'b']).all()\n * // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]\n *\n * @example\n * const filtered = combine([1, 2, 3], [10, 20])\n * .where(([a, b]) => a + b > 20)\n * .map(([a, b]) => a * b)\n * .all()\n */\nexport function combine(...iterables: Iterable<unknown>[]): Combinable<unknown[]> {\n // Convert iterables to arrays lazily (we need to iterate multiple times)\n // This is done inside the generator to maintain laziness\n return new Combinable(function* () {\n if (iterables.length === 0) return\n\n // Convert to arrays (required for cartesian product - need multiple passes)\n const arrays = iterables.map((it) => [...it])\n\n // Check for empty arrays - cartesian product with empty set is empty\n if (arrays.some((arr) => arr.length === 0)) return\n\n // Generate cartesian product using indices\n const indices = new Array(arrays.length).fill(0)\n const maxIndices = arrays.map((arr) => arr.length)\n\n while (true) {\n // Yield current combination\n yield indices.map((i, j) => arrays[j][i])\n\n // Increment indices (like counting in mixed radix)\n let carry = true\n for (let i = indices.length - 1; i >= 0 && carry; i--) {\n indices[i]++\n if (indices[i] >= maxIndices[i]) {\n indices[i] = 0\n } else {\n carry = false\n }\n }\n\n // If we carried all the way, we're done\n if (carry) break\n }\n })\n}\n\n// ============================================================================\n// MDX Frontmatter Parser\n// ============================================================================\n\n/**\n * Result of parsing MDX frontmatter\n */\nexport interface ParseMDXResult {\n /** Parsed schema definition from YAML frontmatter */\n schema: SchemaDefinition\n /** Remaining MDX body after frontmatter */\n body: string\n}\n\n/**\n * Simple YAML parser for frontmatter\n * Handles the subset of YAML commonly used in MDX frontmatter:\n * - Key-value pairs (string values)\n * - Nested objects (indentation-based)\n * - Arrays with bracket notation [item1, item2]\n * - Comments (# ...)\n * - Multiline strings with | and >\n */\nfunction parseYAML(yaml: string): Record<string, unknown> {\n // Normalize line endings to LF\n const normalized = yaml.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n')\n const lines = normalized.split('\\n')\n const result: Record<string, unknown> = {}\n\n // Stack for tracking nested objects: [{ obj, indent }]\n const stack: { obj: Record<string, unknown>; indent: number }[] = [{ obj: result, indent: -1 }]\n\n // State for multiline strings\n let multilineKey: string | null = null\n let multilineIndent = 0\n let multilineLines: string[] = []\n let multilineStyle: '|' | '>' | null = null\n\n for (let lineNum = 0; lineNum < lines.length; lineNum++) {\n const rawLine = lines[lineNum]\n\n // Handle multiline string continuation\n if (multilineKey !== null) {\n // Check if this line continues the multiline string\n const lineIndent = rawLine.match(/^(\\s*)/)?.[1].length ?? 0\n if (lineIndent >= multilineIndent && (rawLine.trim() !== '' || multilineLines.length > 0)) {\n // This is a continuation of the multiline string\n multilineLines.push(rawLine.slice(multilineIndent))\n continue\n } else {\n // End of multiline string - set the value\n const current = stack[stack.length - 1]\n if (multilineStyle === '|') {\n // Literal block - preserve newlines\n current.obj[multilineKey] = multilineLines.join('\\n')\n } else {\n // Folded block - join with spaces (single newlines become spaces)\n current.obj[multilineKey] = multilineLines.join(' ').replace(/\\s+/g, ' ').trim()\n }\n multilineKey = null\n multilineLines = []\n multilineStyle = null\n }\n }\n\n // Remove comments (but not inside quoted strings)\n let line = rawLine\n // Simple comment removal - find # that's not inside quotes\n const hashIndex = line.indexOf('#')\n if (hashIndex !== -1) {\n // Check if it's inside quotes by counting quotes before it\n const beforeHash = line.slice(0, hashIndex)\n const singleQuotes = (beforeHash.match(/'/g) || []).length\n const doubleQuotes = (beforeHash.match(/\"/g) || []).length\n if (singleQuotes % 2 === 0 && doubleQuotes % 2 === 0) {\n line = line.slice(0, hashIndex)\n }\n }\n\n // Skip empty lines\n if (line.trim() === '') continue\n\n // Calculate indentation\n const indentMatch = line.match(/^(\\s*)/)\n const indent = indentMatch ? indentMatch[1].length : 0\n const content = line.trim()\n\n // Pop stack back to appropriate level\n while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {\n stack.pop()\n }\n\n // Parse key-value pair\n const colonIndex = content.indexOf(':')\n if (colonIndex === -1) {\n throw new Error(`Invalid YAML at line ${lineNum + 1}: expected key-value pair, got \"${content}\"`)\n }\n\n const key = content.slice(0, colonIndex).trim()\n let value = content.slice(colonIndex + 1).trim()\n\n // Validate key\n if (!key) {\n throw new Error(`Invalid YAML at line ${lineNum + 1}: empty key`)\n }\n\n const current = stack[stack.length - 1]\n\n // Handle multiline string indicators\n if (value === '|' || value === '>') {\n multilineKey = key\n multilineStyle = value as '|' | '>'\n multilineIndent = indent + 2 // Expect content indented from the key\n multilineLines = []\n continue\n }\n\n if (value === '') {\n // No value - this is a nested object\n const nested: Record<string, unknown> = {}\n current.obj[key] = nested\n stack.push({ obj: nested, indent })\n } else if (value.startsWith('[') && !value.endsWith(']')) {\n // Unclosed array bracket\n throw new Error(`Invalid YAML at line ${lineNum + 1}: unclosed array bracket in \"${content}\"`)\n } else if (value.startsWith('[') && value.endsWith(']')) {\n // Array notation: [item1, item2, ...]\n const arrayContent = value.slice(1, -1).trim()\n if (arrayContent === '') {\n current.obj[key] = []\n } else {\n // Parse array items - handle quoted strings and unquoted values\n const items: string[] = []\n let currentItem = ''\n let inQuote: string | null = null\n for (let i = 0; i < arrayContent.length; i++) {\n const char = arrayContent[i]\n if (inQuote) {\n if (char === inQuote) {\n inQuote = null\n } else {\n currentItem += char\n }\n } else if (char === '\"' || char === \"'\") {\n inQuote = char\n } else if (char === ',') {\n items.push(currentItem.trim())\n currentItem = ''\n } else {\n currentItem += char\n }\n }\n if (currentItem.trim()) {\n items.push(currentItem.trim())\n }\n current.obj[key] = items\n }\n } else {\n // String value - remove surrounding quotes if present\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1)\n }\n current.obj[key] = value\n }\n }\n\n // Handle any remaining multiline string\n if (multilineKey !== null) {\n const current = stack[stack.length - 1]\n if (multilineStyle === '|') {\n current.obj[multilineKey] = multilineLines.join('\\n')\n } else {\n current.obj[multilineKey] = multilineLines.join(' ').replace(/\\s+/g, ' ').trim()\n }\n }\n\n return result\n}\n\n/**\n * Parse MDX frontmatter and extract schema definition.\n *\n * @param mdx - The MDX content with optional YAML frontmatter\n * @returns Object with parsed schema and remaining body\n * @throws Error if YAML syntax is invalid\n *\n * @example\n * const mdx = `---\n * $context: https://db.sb\n * Idea:\n * concept: What is the concept?\n * ---\n *\n * <App>content</App>`\n *\n * const { schema, body } = parseMDX(mdx)\n * // schema = { $context: 'https://db.sb', Idea: { concept: 'What is the concept?' } }\n * // body = '\\n<App>content</App>'\n */\nexport function parseMDX(mdx: string): ParseMDXResult {\n // Normalize line endings\n const normalized = mdx.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n')\n\n // Check if MDX starts with frontmatter delimiter\n if (!normalized.startsWith('---')) {\n // No frontmatter - return empty schema and full content as body\n return {\n schema: {},\n body: mdx,\n }\n }\n\n // Find the closing frontmatter delimiter\n // Start searching after the first ---\n const startIndex = 3 // Length of '---'\n let endIndex = -1\n\n // Look for --- at the start of a line (after a newline)\n let searchStart = startIndex\n while (searchStart < normalized.length) {\n const newlineIndex = normalized.indexOf('\\n', searchStart)\n if (newlineIndex === -1) break\n\n // Check if the next line starts with ---\n if (normalized.slice(newlineIndex + 1, newlineIndex + 4) === '---') {\n // Verify it's actually the closing delimiter (followed by newline or EOF)\n const afterDash = normalized[newlineIndex + 4]\n if (afterDash === undefined || afterDash === '\\n' || afterDash === '\\r') {\n endIndex = newlineIndex + 1\n break\n }\n }\n searchStart = newlineIndex + 1\n }\n\n if (endIndex === -1) {\n throw new Error('Invalid MDX: unclosed frontmatter (missing closing ---)')\n }\n\n // Extract frontmatter YAML (between the two --- markers)\n const frontmatter = normalized.slice(startIndex, endIndex).trim()\n\n // Extract body (everything after the closing ---)\n const bodyStart = endIndex + 3 // Skip past ---\n let body = normalized.slice(bodyStart)\n\n // Remove leading newline from body if present (but preserve rest of whitespace)\n if (body.startsWith('\\n')) {\n body = body.slice(1)\n }\n\n // Parse YAML frontmatter\n let schema: SchemaDefinition\n if (frontmatter === '') {\n // Empty frontmatter\n schema = {}\n } else {\n try {\n schema = parseYAML(frontmatter) as SchemaDefinition\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Invalid YAML in frontmatter: ${error.message}`)\n }\n throw error\n }\n }\n\n return { schema, body }\n}\n\n// ============================================================================\n// JSX UI Specification Parser\n// ============================================================================\n\nimport { parse as babelParse } from '@babel/parser'\nimport type {\n JSXElement,\n JSXFragment,\n JSXText,\n JSXExpressionContainer,\n JSXSpreadChild,\n JSXMemberExpression,\n Expression,\n ObjectExpression,\n ArrayExpression,\n SpreadElement,\n StringLiteral,\n NumericLiteral,\n BooleanLiteral,\n NullLiteral,\n Identifier,\n ArrowFunctionExpression,\n FunctionExpression,\n ObjectProperty,\n Node,\n} from '@babel/types'\n\n/**\n * Hook context passed to entity hooks\n */\nexport interface HookContext {\n generate: (types: string | string[]) => Promise<void>\n changed?: Record<string, boolean>\n}\n\n/**\n * Entity lifecycle hooks\n */\nexport interface EntityHooks {\n onCreate?: (entity: unknown, ctx: HookContext) => Promise<void>\n onUpdate?: (entity: unknown, ctx: HookContext) => Promise<void>\n onDelete?: (entity: unknown) => Promise<void>\n}\n\n/**\n * Navigation group in the sidebar\n */\nexport interface NavigationGroup {\n name: string\n icon?: string\n children: (NavigationGroup | string)[] // string = collection name\n}\n\n/**\n * Field configuration from <Field> elements\n */\nexport interface FieldConfig {\n name: string\n lines?: number\n placeholder?: string\n display?: 'card' | 'link' | 'inline'\n allowCreate?: boolean\n searchable?: boolean\n preview?: string[]\n collapsed?: boolean\n readOnly?: boolean\n required?: boolean\n min?: number\n max?: number\n span?: number\n autoFocus?: boolean\n}\n\n/**\n * Section configuration from <Section> elements\n */\nexport interface SectionConfig {\n label: string\n collapsed?: boolean\n children?: (FieldConfig | SectionConfig)[]\n}\n\n/**\n * Search configuration from <Search> elements\n */\nexport interface SearchConfig {\n fields?: string[]\n}\n\n/**\n * Filter configuration from <Filter> elements\n */\nexport interface FilterConfig {\n field: string\n exists?: boolean\n}\n\n/**\n * Action configuration for generate/built-in actions\n */\nexport interface ActionConfig {\n type: 'generate' | 'delete' | 'duplicate' | 'export' | 'import'\n entity?: string // For generate actions\n context?: string[] // For generate actions\n confirm?: string // For delete\n formats?: string[] // For export\n}\n\n/**\n * Role-based permission configuration\n */\nexport interface RoleConfig {\n name: string\n actions: string[]\n}\n\n/**\n * Template configuration for Cards/Detail views\n */\nexport interface TemplateConfig {\n jsx: string // Preserved JSX string for runtime rendering\n}\n\n/**\n * Form configuration from <Form> elements\n */\nexport interface FormConfig {\n layout?: 'stack' | 'grid'\n fields?: string[] // Quick form with just field names\n children?: (FieldConfig | SectionConfig)[]\n}\n\n/**\n * Display component configuration\n */\nexport interface DisplayConfig {\n type: 'table' | 'grid' | 'cards'\n columns?: string[]\n sortable?: boolean\n template?: TemplateConfig\n}\n\n/**\n * View configuration (List, Detail, Edit, Create)\n */\nexport interface ViewConfig {\n search?: SearchConfig\n filters?: FilterConfig[]\n display?: DisplayConfig\n form?: FormConfig\n template?: TemplateConfig\n editor?: { language: string }\n}\n\n/**\n * Collection configuration for a schema type\n */\nexport interface CollectionConfig {\n view?: 'table' | 'cards' | 'grid'\n columns?: string[]\n searchable?: boolean\n path?: string\n slug?: string\n list?: ViewConfig\n detail?: ViewConfig\n edit?: ViewConfig\n create?: ViewConfig\n actions?: ActionConfig[]\n permissions?: RoleConfig[]\n hooks?: EntityHooks\n}\n\n/**\n * Complete UI configuration parsed from JSX\n */\nexport interface UIConfig {\n hooks: Record<string, EntityHooks>\n navigation: NavigationGroup[]\n collections: Record<string, CollectionConfig>\n}\n\n// Babel type guard helpers\ntype JSXChild = JSXElement | JSXFragment | JSXText | JSXExpressionContainer | JSXSpreadChild\n\nfunction isJSXElement(node: Node | null | undefined): node is JSXElement {\n return node?.type === 'JSXElement'\n}\n\nfunction isObjectExpression(node: Node | null | undefined): node is ObjectExpression {\n return node?.type === 'ObjectExpression'\n}\n\nfunction isArrayExpression(node: Node | null | undefined): node is ArrayExpression {\n return node?.type === 'ArrayExpression'\n}\n\nfunction isStringLiteral(node: Node | null | undefined): node is StringLiteral {\n return node?.type === 'StringLiteral'\n}\n\nfunction isNumericLiteral(node: Node | null | undefined): node is NumericLiteral {\n return node?.type === 'NumericLiteral'\n}\n\nfunction isBooleanLiteral(node: Node | null | undefined): node is BooleanLiteral {\n return node?.type === 'BooleanLiteral'\n}\n\nfunction isNullLiteral(node: Node | null | undefined): node is NullLiteral {\n return node?.type === 'NullLiteral'\n}\n\nfunction isIdentifier(node: Node | null | undefined): node is Identifier {\n return node?.type === 'Identifier'\n}\n\nfunction isArrowFunctionExpression(node: Node | null | undefined): node is ArrowFunctionExpression {\n return node?.type === 'ArrowFunctionExpression'\n}\n\nfunction isFunctionExpression(node: Node | null | undefined): node is FunctionExpression {\n return node?.type === 'FunctionExpression'\n}\n\nfunction isObjectProperty(node: Node | null | undefined): node is ObjectProperty {\n return node?.type === 'ObjectProperty'\n}\n\n/**\n * Get the element name from a JSX element\n */\nfunction getElementName(element: JSXElement): string {\n const name = element.openingElement.name\n if (name.type === 'JSXIdentifier') {\n return name.name\n }\n if (name.type === 'JSXMemberExpression') {\n // Handle Member.Expression style names\n const parts: string[] = []\n let current: JSXMemberExpression['object'] = name\n while (current.type === 'JSXMemberExpression') {\n parts.unshift(current.property.name)\n current = current.object\n }\n if (current.type === 'JSXIdentifier') {\n parts.unshift(current.name)\n }\n return parts.join('.')\n }\n return ''\n}\n\n/**\n * Extract props from a JSX element\n */\nfunction extractProps(element: JSXElement, sourceCode: string): Record<string, unknown> {\n const props: Record<string, unknown> = {}\n\n for (const attr of element.openingElement.attributes) {\n if (attr.type === 'JSXAttribute') {\n const name = attr.name.type === 'JSXIdentifier' ? attr.name.name : String(attr.name.name)\n const value = attr.value\n\n if (value === null || value === undefined) {\n // Boolean prop: <Field searchable />\n props[name] = true\n } else if (value.type === 'StringLiteral') {\n props[name] = value.value\n } else if (value.type === 'JSXExpressionContainer') {\n props[name] = evaluateExpression(value.expression, sourceCode)\n }\n } else if (attr.type === 'JSXSpreadAttribute') {\n // Handle spread attributes if needed\n const spreadValue = evaluateExpression(attr.argument, sourceCode)\n if (typeof spreadValue === 'object' && spreadValue !== null) {\n Object.assign(props, spreadValue)\n }\n }\n }\n\n return props\n}\n\n/**\n * Evaluate a JSX expression to a JavaScript value\n */\nfunction evaluateExpression(\n expr: Expression | JSXExpressionContainer['expression'],\n sourceCode: string\n): unknown {\n if (expr.type === 'JSXEmptyExpression') {\n return undefined\n }\n\n if (isStringLiteral(expr)) {\n return expr.value\n }\n\n if (isNumericLiteral(expr)) {\n return expr.value\n }\n\n if (isBooleanLiteral(expr)) {\n return expr.value\n }\n\n if (isNullLiteral(expr)) {\n return null\n }\n\n if (isIdentifier(expr)) {\n // Handle special identifiers\n if (expr.name === 'undefined') return undefined\n if (expr.name === 'true') return true\n if (expr.name === 'false') return false\n // Return identifier name as string (for field references)\n return expr.name\n }\n\n if (isArrayExpression(expr)) {\n return expr.elements.map((el: Expression | SpreadElement | null) => {\n if (el === null) return null\n if (el.type === 'SpreadElement') {\n return evaluateExpression(el.argument, sourceCode)\n }\n return evaluateExpression(el, sourceCode)\n })\n }\n\n if (isObjectExpression(expr)) {\n const obj: Record<string, unknown> = {}\n for (const prop of expr.properties) {\n if (isObjectProperty(prop)) {\n const key = isIdentifier(prop.key)\n ? prop.key.name\n : isStringLiteral(prop.key)\n ? prop.key.value\n : String(prop.key)\n obj[key] = evaluateExpression(prop.value as Expression, sourceCode)\n }\n // ObjectMethod handling for hooks\n if (prop.type === 'ObjectMethod') {\n const key = isIdentifier(prop.key)\n ? prop.key.name\n : isStringLiteral(prop.key)\n ? prop.key.value\n : String(prop.key)\n // Preserve function as source code string\n if (prop.start !== null && prop.end !== null) {\n obj[key] = sourceCode.slice(prop.start, prop.end)\n }\n }\n }\n return obj\n }\n\n if (isArrowFunctionExpression(expr) || isFunctionExpression(expr)) {\n // Preserve function source for hooks\n if (expr.start !== null && expr.end !== null) {\n return sourceCode.slice(expr.start, expr.end)\n }\n return '[Function]'\n }\n\n // For complex expressions, preserve as string\n if (expr.start !== null && expr.end !== null) {\n return sourceCode.slice(expr.start, expr.end)\n }\n\n return undefined\n}\n\n/**\n * Get child elements of a JSX element, filtering out whitespace-only text\n */\nfunction getChildElements(element: JSXElement): JSXElement[] {\n return element.children.filter((child: JSXChild): child is JSXElement => {\n if (!isJSXElement(child)) return false\n return true\n })\n}\n\n/**\n * Parse Field configuration from a JSX element\n */\nfunction parseFieldConfig(element: JSXElement, sourceCode: string): FieldConfig {\n const props = extractProps(element, sourceCode)\n const config: FieldConfig = {\n name: String(props.name || ''),\n }\n\n if (typeof props.lines === 'number') config.lines = props.lines\n if (typeof props.placeholder === 'string') config.placeholder = props.placeholder\n if (typeof props.display === 'string') config.display = props.display as FieldConfig['display']\n if (props.allowCreate === true) config.allowCreate = true\n if (props.searchable === true) config.searchable = true\n if (Array.isArray(props.preview)) config.preview = props.preview as string[]\n if (props.collapsed === true) config.collapsed = true\n if (props.readOnly === true) config.readOnly = true\n if (props.required === true) config.required = true\n if (typeof props.min === 'number') config.min = props.min\n if (typeof props.max === 'number') config.max = props.max\n if (typeof props.span === 'number') config.span = props.span\n if (props.autoFocus === true) config.autoFocus = true\n\n return config\n}\n\n/**\n * Parse Section configuration from a JSX element\n */\nfunction parseSectionConfig(element: JSXElement, sourceCode: string): SectionConfig {\n const props = extractProps(element, sourceCode)\n const config: SectionConfig = {\n label: String(props.label || ''),\n }\n\n if (props.collapsed === true) config.collapsed = true\n\n // Parse child fields and sections\n const children: (FieldConfig | SectionConfig)[] = []\n for (const child of getChildElements(element)) {\n const childName = getElementName(child)\n if (childName === 'Field') {\n children.push(parseFieldConfig(child, sourceCode))\n } else if (childName === 'Section') {\n children.push(parseSectionConfig(child, sourceCode))\n }\n }\n if (children.length > 0) {\n config.children = children\n }\n\n return config\n}\n\n/**\n * Parse Form configuration from a JSX element\n */\nfunction parseFormConfig(element: JSXElement, sourceCode: string): FormConfig {\n const props = extractProps(element, sourceCode)\n const config: FormConfig = {}\n\n if (typeof props.layout === 'string') config.layout = props.layout as 'stack' | 'grid'\n if (Array.isArray(props.fields)) config.fields = props.fields as string[]\n\n // Parse child fields and sections\n const children: (FieldConfig | SectionConfig)[] = []\n for (const child of getChildElements(element)) {\n const childName = getElementName(child)\n if (childName === 'Field') {\n children.push(parseFieldConfig(child, sourceCode))\n } else if (childName === 'Section') {\n children.push(parseSectionConfig(child, sourceCode))\n }\n }\n if (children.length > 0) {\n config.children = children\n }\n\n return config\n}\n\n/**\n * Parse Template configuration, preserving JSX for runtime\n */\nfunction parseTemplateConfig(element: JSXElement, sourceCode: string): TemplateConfig {\n // Preserve the entire template JSX as a string\n if (element.start !== null && element.end !== null) {\n // Get just the children content\n const openingEnd = element.openingElement.end ?? element.start\n const closingStart = element.closingElement?.start ?? element.end\n const jsx = sourceCode.slice(openingEnd, closingStart).trim()\n return { jsx }\n }\n return { jsx: '' }\n}\n\n/**\n * Parse display component (Table, Grid, Cards)\n */\nfunction parseDisplayConfig(element: JSXElement, sourceCode: string): DisplayConfig {\n const name = getElementName(element)\n const props = extractProps(element, sourceCode)\n const config: DisplayConfig = {\n type: name.toLowerCase() as 'table' | 'grid' | 'cards',\n }\n\n if (Array.isArray(props.columns)) config.columns = props.columns as string[]\n if (props.sortable === true) config.sortable = true\n\n // Look for Template child\n for (const child of getChildElements(element)) {\n if (getElementName(child) === 'Template') {\n config.template = parseTemplateConfig(child, sourceCode)\n break\n }\n }\n\n return config\n}\n\n/**\n * Parse Search configuration\n */\nfunction parseSearchConfig(element: JSXElement, sourceCode: string): SearchConfig {\n const props = extractProps(element, sourceCode)\n const config: SearchConfig = {}\n\n if (Array.isArray(props.fields)) config.fields = props.fields as string[]\n\n return config\n}\n\n/**\n * Parse Filter configuration\n */\nfunction parseFilterConfig(element: JSXElement, sourceCode: string): FilterConfig {\n const props = extractProps(element, sourceCode)\n return {\n field: String(props.field || ''),\n exists: props.exists === true ? true : undefined,\n }\n}\n\n/**\n * Parse view configuration (List, Detail, Edit, Create)\n */\nfunction parseViewConfig(element: JSXElement, sourceCode: string): ViewConfig {\n const config: ViewConfig = {}\n\n for (const child of getChildElements(element)) {\n const childName = getElementName(child)\n\n switch (childName) {\n case 'Search':\n config.search = parseSearchConfig(child, sourceCode)\n break\n case 'Filters': {\n config.filters = []\n for (const filterChild of getChildElements(child)) {\n if (getElementName(filterChild) === 'Filter') {\n config.filters.push(parseFilterConfig(filterChild, sourceCode))\n }\n }\n break\n }\n case 'Table':\n case 'Grid':\n case 'Cards':\n config.display = parseDisplayConfig(child, sourceCode)\n break\n case 'Form':\n config.form = parseFormConfig(child, sourceCode)\n break\n case 'Template':\n config.template = parseTemplateConfig(child, sourceCode)\n break\n case 'Editor': {\n const props = extractProps(child, sourceCode)\n config.editor = { language: String(props.language || 'yaml') }\n break\n }\n }\n }\n\n return config\n}\n\n/**\n * Parse Actions container\n */\nfunction parseActionsConfig(\n element: JSXElement,\n schemaTypes: Set<string>,\n sourceCode: string\n): ActionConfig[] {\n const actions: ActionConfig[] = []\n\n for (const child of getChildElements(element)) {\n const childName = getElementName(child)\n const props = extractProps(child, sourceCode)\n\n if (childName === 'Delete') {\n actions.push({\n type: 'delete',\n confirm: typeof props.confirm === 'string' ? props.confirm : undefined,\n })\n } else if (childName === 'Duplicate') {\n actions.push({ type: 'duplicate' })\n } else if (childName === 'Export') {\n actions.push({\n type: 'export',\n formats: Array.isArray(props.formats) ? (props.formats as string[]) : undefined,\n })\n } else if (childName === 'Import') {\n actions.push({ type: 'import' })\n } else if (schemaTypes.has(childName)) {\n // Entity reference = generate action\n actions.push({\n type: 'generate',\n entity: childName,\n context: Array.isArray(props.context) ? (props.context as string[]) : undefined,\n })\n }\n }\n\n return actions\n}\n\n/**\n * Parse Permissions container\n */\nfunction parsePermissionsConfig(element: JSXElement, sourceCode: string): RoleConfig[] {\n const roles: RoleConfig[] = []\n\n for (const child of getChildElements(element)) {\n if (getElementName(child) === 'Role') {\n const props = extractProps(child, sourceCode)\n roles.push({\n name: String(props.name || ''),\n actions: Array.isArray(props.actions) ? (props.actions as string[]) : [],\n })\n }\n }\n\n return roles\n}\n\n/**\n * Parse a collection element (schema type)\n */\nfunction parseCollectionConfig(\n element: JSXElement,\n schemaTypes: Set<string>,\n sourceCode: string\n): CollectionConfig {\n const props = extractProps(element, sourceCode)\n const config: CollectionConfig = {}\n\n // Top-level collection props\n if (typeof props.view === 'string') config.view = props.view as 'table' | 'cards' | 'grid'\n if (Array.isArray(props.columns)) config.columns = props.columns as string[]\n if (props.searchable === true) config.searchable = true\n if (typeof props.path === 'string') config.path = props.path\n if (typeof props.slug === 'string') config.slug = props.slug\n\n // Parse child views and configurations\n for (const child of getChildElements(element)) {\n const childName = getElementName(child)\n\n switch (childName) {\n case 'List':\n config.list = parseViewConfig(child, sourceCode)\n break\n case 'Detail':\n config.detail = parseViewConfig(child, sourceCode)\n break\n case 'Edit':\n config.edit = parseViewConfig(child, sourceCode)\n break\n case 'Create':\n config.create = parseViewConfig(child, sourceCode)\n break\n case 'Actions':\n config.actions = parseActionsConfig(child, schemaTypes, sourceCode)\n break\n case 'Permissions':\n config.permissions = parsePermissionsConfig(child, sourceCode)\n break\n }\n }\n\n return config\n}\n\n/**\n * Parse navigation structure, distinguishing between groups and collections\n */\nfunction parseNavigationElement(\n element: JSXElement,\n schemaTypes: Set<string>,\n collections: Record<string, CollectionConfig>,\n sourceCode: string\n): NavigationGroup | string {\n const name = getElementName(element)\n const props = extractProps(element, sourceCode)\n\n // If this is a schema type, it's a collection\n if (schemaTypes.has(name)) {\n // Parse and store collection config\n collections[name] = parseCollectionConfig(element, schemaTypes, sourceCode)\n return name\n }\n\n // Otherwise it's a navigation group\n const group: NavigationGroup = {\n name,\n children: [],\n }\n\n if (typeof props.icon === 'string') {\n group.icon = props.icon\n }\n\n // Parse children\n for (const child of getChildElements(element)) {\n const childResult = parseNavigationElement(child, schemaTypes, collections, sourceCode)\n group.children.push(childResult)\n }\n\n return group\n}\n\n/**\n * Parse hooks from the App element's hooks prop\n */\nfunction parseHooksFromProp(\n hooksProp: unknown,\n sourceCode: string\n): Record<string, EntityHooks> {\n const hooks: Record<string, EntityHooks> = {}\n\n if (typeof hooksProp !== 'object' || hooksProp === null) {\n return hooks\n }\n\n for (const [typeName, typeHooks] of Object.entries(hooksProp as Record<string, unknown>)) {\n if (typeof typeHooks !== 'object' || typeHooks === null) continue\n\n const entityHooks: EntityHooks = {}\n const hooksObj = typeHooks as Record<string, unknown>\n\n // Preserve hooks as function source strings\n if (hooksObj.onCreate !== undefined) {\n entityHooks.onCreate = hooksObj.onCreate as EntityHooks['onCreate']\n }\n if (hooksObj.onUpdate !== undefined) {\n entityHooks.onUpdate = hooksObj.onUpdate as EntityHooks['onUpdate']\n }\n if (hooksObj.onDelete !== undefined) {\n entityHooks.onDelete = hooksObj.onDelete as EntityHooks['onDelete']\n }\n\n if (Object.keys(entityHooks).length > 0) {\n hooks[typeName] = entityHooks\n }\n }\n\n return hooks\n}\n\n/**\n * Parse JSX UI specification into UIConfig\n *\n * @param jsx - The JSX string to parse\n * @param schema - The parsed schema to determine which elements are collections\n * @returns Parsed UI configuration\n * @throws Error if JSX syntax is invalid or no App root element\n *\n * @example\n * const jsx = `\n * <App hooks={{ Startup: { onCreate: async () => {} } }}>\n * <Planning icon=\"lightbulb\">\n * <Idea view=\"cards\" />\n * </Planning>\n * </App>\n * `\n * const config = parseJSXUI(jsx, schema)\n * // config.hooks = { Startup: { onCreate: ... } }\n * // config.navigation = [{ name: 'Planning', icon: 'lightbulb', children: ['Idea'] }]\n * // config.collections = { Idea: { view: 'cards' } }\n */\nexport function parseJSXUI(jsx: string, schema: ParsedSchema): UIConfig {\n // Parse JSX using Babel\n let ast\n try {\n ast = babelParse(jsx, {\n plugins: ['jsx'],\n sourceType: 'module',\n })\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Invalid JSX syntax: ${error.message}`)\n }\n throw new Error('Invalid JSX syntax')\n }\n\n // Get schema type names for distinguishing collections from groups\n const schemaTypes = new Set(Object.keys(schema.types))\n\n // Find the root App element\n let appElement: JSXElement | null = null\n\n // Walk the AST to find JSX elements\n function findApp(node: Node): void {\n if (isJSXElement(node)) {\n if (getElementName(node) === 'App') {\n appElement = node\n return\n }\n // Check children\n for (const child of node.children) {\n findApp(child)\n }\n }\n // Handle ExpressionStatement wrapping JSX\n if (node.type === 'ExpressionStatement' && isJSXElement(node.expression)) {\n findApp(node.expression)\n }\n // Handle Program body\n if (node.type === 'Program') {\n for (const stmt of node.body) {\n findApp(stmt)\n }\n }\n // Handle File\n if (node.type === 'File') {\n findApp(node.program)\n }\n }\n\n findApp(ast)\n\n if (!appElement) {\n throw new Error('No <App> root element found in JSX')\n }\n\n // Initialize result\n const result: UIConfig = {\n hooks: {},\n navigation: [],\n collections: {},\n }\n\n // Extract hooks from App props\n const appProps = extractProps(appElement, jsx)\n if (appProps.hooks) {\n result.hooks = parseHooksFromProp(appProps.hooks, jsx)\n }\n\n // Parse children of App as navigation/collections\n for (const child of getChildElements(appElement)) {\n const parsed = parseNavigationElement(child, schemaTypes, result.collections, jsx)\n if (typeof parsed === 'string') {\n // Top-level collection (unusual but possible)\n result.navigation.push({\n name: parsed,\n children: [],\n })\n } else {\n result.navigation.push(parsed)\n }\n }\n\n return result\n}\n\n/**\n * Result of processing an MDX file\n */\nexport interface ProcessMDXResult {\n /** Raw YAML schema definition */\n schema: SchemaDefinition\n /** Parsed schema with types, fields, and references */\n parsedSchema: ParsedSchema\n /** Parsed JSX UI configuration */\n uiConfig: UIConfig\n /** Original JSX body (after frontmatter) */\n rawBody: string\n}\n\n/**\n * Process an MDX file and return all parsed components.\n */\nexport function processMDX(mdx: string): ProcessMDXResult {\n const { schema, body } = parseMDX(mdx)\n const parsedSchema = parseSchema(schema)\n const uiConfig = parseJSXUI(body, parsedSchema)\n return { schema, parsedSchema, uiConfig, rawBody: body }\n}\n"],"mappings":"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","names":["result","current"]}
|