@objectstack/objectql 3.3.0 → 3.3.1

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/registry.ts","../src/protocol.ts","../src/engine.ts","../src/metadata-facade.ts","../src/plugin.ts","../src/kernel-factory.ts","../src/util.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ServiceObject, ObjectSchema, ObjectOwnership } from '@objectstack/spec/data';\nimport { ObjectStackManifest, ManifestSchema, InstalledPackage, InstalledPackageSchema } from '@objectstack/spec/kernel';\nimport { AppSchema } from '@objectstack/spec/ui';\n\n/**\n * Reserved namespaces that do not get FQN prefix applied.\n * Objects in these namespaces keep their short names (e.g., \"user\" not \"base__user\").\n */\nexport const RESERVED_NAMESPACES = new Set(['base', 'system']);\n\n/**\n * Default priorities for ownership types.\n */\nexport const DEFAULT_OWNER_PRIORITY = 100;\nexport const DEFAULT_EXTENDER_PRIORITY = 200;\n\n/**\n * Contributor Record\n * Tracks how a package contributes to an object (own or extend).\n */\nexport interface ObjectContributor {\n packageId: string;\n namespace: string;\n ownership: ObjectOwnership;\n priority: number;\n definition: ServiceObject;\n}\n\n/**\n * Compute Fully Qualified Name (FQN) for an object.\n * \n * @param namespace - The package namespace (e.g., \"crm\", \"todo\")\n * @param shortName - The object's short name (e.g., \"task\", \"account\")\n * @returns FQN string (e.g., \"crm__task\") or just shortName for reserved namespaces\n * \n * @example\n * computeFQN('crm', 'account') // => 'crm__account'\n * computeFQN('base', 'user') // => 'user' (reserved, no prefix)\n * computeFQN(undefined, 'task') // => 'task' (legacy, no namespace)\n */\nexport function computeFQN(namespace: string | undefined, shortName: string): string {\n if (!namespace || RESERVED_NAMESPACES.has(namespace)) {\n return shortName;\n }\n return `${namespace}__${shortName}`;\n}\n\n/**\n * Parse FQN back to namespace and short name.\n * \n * @param fqn - Fully qualified name (e.g., \"crm__account\" or \"user\")\n * @returns { namespace, shortName } - namespace is undefined for unprefixed names\n */\nexport function parseFQN(fqn: string): { namespace: string | undefined; shortName: string } {\n const idx = fqn.indexOf('__');\n if (idx === -1) {\n return { namespace: undefined, shortName: fqn };\n }\n return {\n namespace: fqn.slice(0, idx),\n shortName: fqn.slice(idx + 2),\n };\n}\n\n/**\n * Deep merge two ServiceObject definitions.\n * Fields are merged additively. Other props: later value wins.\n */\nfunction mergeObjectDefinitions(base: ServiceObject, extension: Partial<ServiceObject>): ServiceObject {\n const merged = { ...base };\n\n // Merge fields additively\n if (extension.fields) {\n merged.fields = { ...base.fields, ...extension.fields };\n }\n\n // Merge validations additively\n if (extension.validations) {\n merged.validations = [...(base.validations || []), ...extension.validations];\n }\n\n // Merge indexes additively\n if (extension.indexes) {\n merged.indexes = [...(base.indexes || []), ...extension.indexes];\n }\n\n // Override scalar props (last writer wins)\n if (extension.label !== undefined) merged.label = extension.label;\n if (extension.pluralLabel !== undefined) merged.pluralLabel = extension.pluralLabel;\n if (extension.description !== undefined) merged.description = extension.description;\n\n return merged;\n}\n\n/**\n * Global Schema Registry\n * Unified storage for all metadata types (Objects, Apps, Flows, Layouts, etc.)\n * \n * ## Namespace & Ownership Model\n * \n * Objects use a namespace-based FQN system:\n * - `namespace`: Short identifier from package manifest (e.g., \"crm\", \"todo\")\n * - `FQN`: `{namespace}__{short_name}` (e.g., \"crm__account\")\n * - Reserved namespaces (`base`, `system`) don't get prefixed\n * \n * Ownership modes:\n * - `own`: One package owns the object (creates the table, defines base schema)\n * - `extend`: Multiple packages can extend an object (add fields, merge by priority)\n * \n * ## Package vs App Distinction\n * - **Package**: The unit of installation, stored under type 'package'.\n * Each InstalledPackage wraps a ManifestSchema with lifecycle state.\n * - **App**: A UI navigation shell (AppSchema), registered under type 'apps'.\n * Apps are extracted from packages during registration.\n * - A package may contain 0, 1, or many apps.\n */\nexport type RegistryLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\n\nexport class SchemaRegistry {\n // ==========================================\n // Logging control\n // ==========================================\n\n /** Controls verbosity of registry console messages. Default: 'info'. */\n private static _logLevel: RegistryLogLevel = 'info';\n\n static get logLevel(): RegistryLogLevel { return this._logLevel; }\n static set logLevel(level: RegistryLogLevel) { this._logLevel = level; }\n\n private static log(msg: string): void {\n if (this._logLevel === 'silent' || this._logLevel === 'error' || this._logLevel === 'warn') return;\n console.log(msg);\n }\n\n // ==========================================\n // Object-specific storage (Ownership Model)\n // ==========================================\n \n /** FQN → Contributor[] (all packages that own/extend this object) */\n private static objectContributors = new Map<string, ObjectContributor[]>();\n \n /** FQN → Merged ServiceObject (cached, invalidated on changes) */\n private static mergedObjectCache = new Map<string, ServiceObject>();\n \n /** Namespace → PackageId (ensures namespace uniqueness) */\n private static namespaceRegistry = new Map<string, string>();\n\n // ==========================================\n // Generic metadata storage (non-object types)\n // ==========================================\n \n /** Type → Name/ID → MetadataItem */\n private static metadata = new Map<string, Map<string, any>>();\n\n // ==========================================\n // Namespace Management\n // ==========================================\n\n /**\n * Register a namespace for a package.\n * Enforces namespace uniqueness within the instance.\n * \n * @throws Error if namespace is already registered to a different package\n */\n static registerNamespace(namespace: string, packageId: string): void {\n if (!namespace) return;\n \n const existing = this.namespaceRegistry.get(namespace);\n if (existing && existing !== packageId) {\n throw new Error(\n `Namespace \"${namespace}\" is already registered to package \"${existing}\". ` +\n `Package \"${packageId}\" cannot use the same namespace.`\n );\n }\n \n this.namespaceRegistry.set(namespace, packageId);\n this.log(`[Registry] Registered namespace: ${namespace} → ${packageId}`);\n }\n\n /**\n * Unregister a namespace when a package is uninstalled.\n */\n static unregisterNamespace(namespace: string, packageId: string): void {\n const existing = this.namespaceRegistry.get(namespace);\n if (existing === packageId) {\n this.namespaceRegistry.delete(namespace);\n this.log(`[Registry] Unregistered namespace: ${namespace}`);\n }\n }\n\n /**\n * Get the package that owns a namespace.\n */\n static getNamespaceOwner(namespace: string): string | undefined {\n return this.namespaceRegistry.get(namespace);\n }\n\n // ==========================================\n // Object Registration (Ownership Model)\n // ==========================================\n\n /**\n * Register an object with ownership semantics.\n * \n * @param schema - The object definition\n * @param packageId - The owning package ID\n * @param namespace - The package namespace (for FQN computation)\n * @param ownership - 'own' (single owner) or 'extend' (additive merge)\n * @param priority - Merge priority (lower applied first, higher wins on conflict)\n * \n * @throws Error if trying to 'own' an object that already has an owner\n */\n static registerObject(\n schema: ServiceObject,\n packageId: string,\n namespace?: string,\n ownership: ObjectOwnership = 'own',\n priority: number = ownership === 'own' ? DEFAULT_OWNER_PRIORITY : DEFAULT_EXTENDER_PRIORITY\n ): string {\n const shortName = schema.name;\n const fqn = computeFQN(namespace, shortName);\n\n // Ensure namespace is registered\n if (namespace) {\n this.registerNamespace(namespace, packageId);\n }\n\n // Get or create contributor list\n let contributors = this.objectContributors.get(fqn);\n if (!contributors) {\n contributors = [];\n this.objectContributors.set(fqn, contributors);\n }\n\n // Validate ownership rules\n if (ownership === 'own') {\n const existingOwner = contributors.find(c => c.ownership === 'own');\n if (existingOwner && existingOwner.packageId !== packageId) {\n throw new Error(\n `Object \"${fqn}\" is already owned by package \"${existingOwner.packageId}\". ` +\n `Package \"${packageId}\" cannot claim ownership. Use 'extend' to add fields.`\n );\n }\n // Remove existing owner contribution from same package (re-registration)\n const idx = contributors.findIndex(c => c.packageId === packageId && c.ownership === 'own');\n if (idx !== -1) {\n contributors.splice(idx, 1);\n console.warn(`[Registry] Re-registering owned object: ${fqn} from ${packageId}`);\n }\n } else {\n // extend mode: remove existing extension from same package\n const idx = contributors.findIndex(c => c.packageId === packageId && c.ownership === 'extend');\n if (idx !== -1) {\n contributors.splice(idx, 1);\n }\n }\n\n // Add new contributor\n const contributor: ObjectContributor = {\n packageId,\n namespace: namespace || '',\n ownership,\n priority,\n definition: { ...schema, name: fqn }, // Store with FQN as name\n };\n contributors.push(contributor);\n\n // Sort by priority (ascending: lower priority applied first)\n contributors.sort((a, b) => a.priority - b.priority);\n\n // Invalidate merge cache\n this.mergedObjectCache.delete(fqn);\n\n this.log(`[Registry] Registered object: ${fqn} (${ownership}, priority=${priority}) from ${packageId}`);\n return fqn;\n }\n\n /**\n * Resolve an object by FQN, merging all contributions.\n * Returns the merged object or undefined if not found.\n */\n static resolveObject(fqn: string): ServiceObject | undefined {\n // Check cache first\n const cached = this.mergedObjectCache.get(fqn);\n if (cached) return cached;\n\n const contributors = this.objectContributors.get(fqn);\n if (!contributors || contributors.length === 0) {\n return undefined;\n }\n\n // Find owner (must exist for a valid object)\n const ownerContrib = contributors.find(c => c.ownership === 'own');\n if (!ownerContrib) {\n console.warn(`[Registry] Object \"${fqn}\" has extenders but no owner. Skipping.`);\n return undefined;\n }\n\n // Start with owner's definition\n let merged = { ...ownerContrib.definition };\n\n // Apply extensions in priority order (already sorted)\n for (const contrib of contributors) {\n if (contrib.ownership === 'extend') {\n merged = mergeObjectDefinitions(merged, contrib.definition);\n }\n }\n\n // Cache the result\n this.mergedObjectCache.set(fqn, merged);\n return merged;\n }\n\n /**\n * Get object by name (FQN, short name, or physical table name).\n *\n * Resolution order:\n * 1. Exact FQN match (e.g., 'crm__account')\n * 2. Short name fallback (e.g., 'account' → 'crm__account')\n * 3. Physical table name match (e.g., 'sys_user' → 'sys__user')\n * ObjectSchema.create() auto-derives tableName as {namespace}_{name},\n * which uses a single underscore — different from the FQN double underscore.\n */\n static getObject(name: string): ServiceObject | undefined {\n // Direct FQN lookup\n const direct = this.resolveObject(name);\n if (direct) return direct;\n\n // Fallback: scan for objects ending with the short name\n // This handles legacy code that doesn't use FQN\n for (const fqn of this.objectContributors.keys()) {\n const { shortName } = parseFQN(fqn);\n if (shortName === name) {\n return this.resolveObject(fqn);\n }\n }\n\n // Fallback: match by physical table name (e.g., 'sys_user' → FQN 'sys__user')\n // This bridges the gap between protocol names (SystemObjectName) and FQN.\n for (const fqn of this.objectContributors.keys()) {\n const resolved = this.resolveObject(fqn);\n if (resolved?.tableName === name) {\n return resolved;\n }\n }\n\n return undefined;\n }\n\n /**\n * Get all registered objects (merged).\n * \n * @param packageId - Optional filter: only objects contributed by this package\n */\n static getAllObjects(packageId?: string): ServiceObject[] {\n const results: ServiceObject[] = [];\n\n for (const fqn of this.objectContributors.keys()) {\n // If filtering by package, check if this package contributes\n if (packageId) {\n const contributors = this.objectContributors.get(fqn);\n const hasContribution = contributors?.some(c => c.packageId === packageId);\n if (!hasContribution) continue;\n }\n\n const merged = this.resolveObject(fqn);\n if (merged) {\n // Tag with contributor info for UI\n (merged as any)._packageId = this.getObjectOwner(fqn)?.packageId;\n results.push(merged);\n }\n }\n\n return results;\n }\n\n /**\n * Get all contributors for an object.\n */\n static getObjectContributors(fqn: string): ObjectContributor[] {\n return this.objectContributors.get(fqn) || [];\n }\n\n /**\n * Get the owner contributor for an object.\n */\n static getObjectOwner(fqn: string): ObjectContributor | undefined {\n const contributors = this.objectContributors.get(fqn);\n return contributors?.find(c => c.ownership === 'own');\n }\n\n /**\n * Unregister all objects contributed by a package.\n * \n * @throws Error if trying to uninstall an owner that has extenders\n */\n static unregisterObjectsByPackage(packageId: string, force: boolean = false): void {\n for (const [fqn, contributors] of this.objectContributors.entries()) {\n // Find this package's contributions\n const packageContribs = contributors.filter(c => c.packageId === packageId);\n \n for (const contrib of packageContribs) {\n if (contrib.ownership === 'own' && !force) {\n // Check if there are extenders from other packages\n const otherExtenders = contributors.filter(\n c => c.packageId !== packageId && c.ownership === 'extend'\n );\n if (otherExtenders.length > 0) {\n throw new Error(\n `Cannot uninstall package \"${packageId}\": object \"${fqn}\" is extended by ` +\n `${otherExtenders.map(c => c.packageId).join(', ')}. Uninstall extenders first.`\n );\n }\n }\n\n // Remove contribution\n const idx = contributors.indexOf(contrib);\n if (idx !== -1) {\n contributors.splice(idx, 1);\n this.log(`[Registry] Removed ${contrib.ownership} contribution to ${fqn} from ${packageId}`);\n }\n }\n\n // Clean up empty contributor lists\n if (contributors.length === 0) {\n this.objectContributors.delete(fqn);\n }\n\n // Invalidate cache\n this.mergedObjectCache.delete(fqn);\n }\n }\n\n // ==========================================\n // Generic Metadata (Non-Object Types)\n // ==========================================\n\n /**\n * Universal Register Method for non-object metadata.\n */\n static registerItem<T>(type: string, item: T, keyField: keyof T = 'name' as keyof T, packageId?: string) {\n if (!this.metadata.has(type)) {\n this.metadata.set(type, new Map());\n }\n const collection = this.metadata.get(type)!;\n const baseName = String(item[keyField]);\n \n // Tag item with owning package for scoped queries\n if (packageId) {\n (item as any)._packageId = packageId;\n }\n\n // Validation Hook\n try {\n this.validate(type, item);\n } catch (e: any) {\n console.error(`[Registry] Validation failed for ${type} ${baseName}: ${e.message}`);\n }\n\n // Use composite key (packageId:name) when packageId is provided\n const storageKey = packageId ? `${packageId}:${baseName}` : baseName;\n\n if (collection.has(storageKey)) {\n console.warn(`[Registry] Overwriting ${type}: ${storageKey}`);\n }\n collection.set(storageKey, item);\n this.log(`[Registry] Registered ${type}: ${storageKey}`);\n }\n\n /**\n * Validate Metadata against Spec Zod Schemas\n */\n static validate(type: string, item: any) {\n if (type === 'object') {\n return ObjectSchema.parse(item);\n }\n if (type === 'apps') {\n return AppSchema.parse(item);\n }\n if (type === 'package') {\n return InstalledPackageSchema.parse(item);\n }\n if (type === 'plugin') {\n return ManifestSchema.parse(item);\n }\n return true;\n }\n\n /**\n * Universal Unregister Method\n */\n static unregisterItem(type: string, name: string) {\n const collection = this.metadata.get(type);\n if (!collection) {\n console.warn(`[Registry] Attempted to unregister non-existent ${type}: ${name}`);\n return;\n }\n if (collection.has(name)) {\n collection.delete(name);\n this.log(`[Registry] Unregistered ${type}: ${name}`);\n return;\n }\n // Scan composite keys\n for (const key of collection.keys()) {\n if (key.endsWith(`:${name}`)) {\n collection.delete(key);\n this.log(`[Registry] Unregistered ${type}: ${key}`);\n return;\n }\n }\n console.warn(`[Registry] Attempted to unregister non-existent ${type}: ${name}`);\n }\n\n /**\n * Universal Get Method\n */\n static getItem<T>(type: string, name: string): T | undefined {\n // Special handling for 'object' and 'objects' types - use objectContributors\n if (type === 'object' || type === 'objects') {\n return this.getObject(name) as unknown as T | undefined;\n }\n \n const collection = this.metadata.get(type);\n if (!collection) return undefined;\n const direct = collection.get(name);\n if (direct) return direct as T;\n // Scan for composite keys\n for (const [key, item] of collection) {\n if (key.endsWith(`:${name}`)) return item as T;\n }\n return undefined;\n }\n\n /**\n * Universal List Method\n */\n static listItems<T>(type: string, packageId?: string): T[] {\n // Special handling for 'object' and 'objects' types - use objectContributors\n if (type === 'object' || type === 'objects') {\n return this.getAllObjects(packageId) as unknown as T[];\n }\n \n const items = Array.from(this.metadata.get(type)?.values() || []) as T[];\n if (packageId) {\n return items.filter((item: any) => item._packageId === packageId);\n }\n return items;\n }\n\n /**\n * Get all registered metadata types (Kinds)\n */\n static getRegisteredTypes(): string[] {\n const types = Array.from(this.metadata.keys());\n // Always include 'object' even if stored separately\n if (!types.includes('object') && this.objectContributors.size > 0) {\n types.push('object');\n }\n return types;\n }\n\n // ==========================================\n // Package Management\n // ==========================================\n\n static installPackage(manifest: ObjectStackManifest, settings?: Record<string, any>): InstalledPackage {\n const now = new Date().toISOString();\n const pkg: InstalledPackage = {\n manifest,\n status: 'installed',\n enabled: true,\n installedAt: now,\n updatedAt: now,\n settings,\n };\n \n // Register namespace if present\n if (manifest.namespace) {\n this.registerNamespace(manifest.namespace, manifest.id);\n }\n \n if (!this.metadata.has('package')) {\n this.metadata.set('package', new Map());\n }\n const collection = this.metadata.get('package')!;\n if (collection.has(manifest.id)) {\n console.warn(`[Registry] Overwriting package: ${manifest.id}`);\n }\n collection.set(manifest.id, pkg);\n this.log(`[Registry] Installed package: ${manifest.id} (${manifest.name})`);\n return pkg;\n }\n\n static uninstallPackage(id: string): boolean {\n const pkg = this.getPackage(id);\n if (!pkg) {\n console.warn(`[Registry] Package not found for uninstall: ${id}`);\n return false;\n }\n\n // Unregister namespace\n if (pkg.manifest.namespace) {\n this.unregisterNamespace(pkg.manifest.namespace, id);\n }\n\n // Unregister objects (will throw if extenders exist)\n this.unregisterObjectsByPackage(id);\n\n // Remove package record\n const collection = this.metadata.get('package');\n if (collection) {\n collection.delete(id);\n this.log(`[Registry] Uninstalled package: ${id}`);\n return true;\n }\n return false;\n }\n\n static getPackage(id: string): InstalledPackage | undefined {\n return this.metadata.get('package')?.get(id) as InstalledPackage | undefined;\n }\n\n static getAllPackages(): InstalledPackage[] {\n return this.listItems<InstalledPackage>('package');\n }\n\n static enablePackage(id: string): InstalledPackage | undefined {\n const pkg = this.getPackage(id);\n if (pkg) {\n pkg.enabled = true;\n pkg.status = 'installed';\n pkg.statusChangedAt = new Date().toISOString();\n pkg.updatedAt = new Date().toISOString();\n this.log(`[Registry] Enabled package: ${id}`);\n }\n return pkg;\n }\n\n static disablePackage(id: string): InstalledPackage | undefined {\n const pkg = this.getPackage(id);\n if (pkg) {\n pkg.enabled = false;\n pkg.status = 'disabled';\n pkg.statusChangedAt = new Date().toISOString();\n pkg.updatedAt = new Date().toISOString();\n this.log(`[Registry] Disabled package: ${id}`);\n }\n return pkg;\n }\n\n // ==========================================\n // App Helpers\n // ==========================================\n\n static registerApp(app: any, packageId?: string) {\n this.registerItem('apps', app, 'name', packageId);\n }\n\n static getApp(name: string): any {\n return this.getItem('apps', name);\n }\n\n static getAllApps(): any[] {\n return this.listItems('apps');\n }\n\n // ==========================================\n // Plugin Helpers\n // ==========================================\n\n static registerPlugin(manifest: ObjectStackManifest) {\n this.registerItem('plugin', manifest, 'id');\n }\n\n static getAllPlugins(): ObjectStackManifest[] {\n return this.listItems<ObjectStackManifest>('plugin');\n }\n\n // ==========================================\n // Kind Helpers\n // ==========================================\n\n static registerKind(kind: { id: string, globs: string[] }) {\n this.registerItem('kind', kind, 'id');\n }\n \n static getAllKinds(): { id: string, globs: string[] }[] {\n return this.listItems('kind');\n }\n\n // ==========================================\n // Reset (for testing)\n // ==========================================\n\n /**\n * Clear all registry state. Use only for testing.\n */\n static reset(): void {\n this.objectContributors.clear();\n this.mergedObjectCache.clear();\n this.namespaceRegistry.clear();\n this.metadata.clear();\n this.log('[Registry] Reset complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { IDataEngine } from '@objectstack/core';\nimport type { \n BatchUpdateRequest, \n BatchUpdateResponse, \n UpdateManyDataRequest,\n DeleteManyDataRequest\n} from '@objectstack/spec/api';\nimport type { MetadataCacheRequest, MetadataCacheResponse, ServiceInfo, ApiRoutes, WellKnownCapabilities } from '@objectstack/spec/api';\nimport type { IFeedService } from '@objectstack/spec/contracts';\nimport { parseFilterAST, isFilterAST } from '@objectstack/spec/data';\n\n// We import SchemaRegistry directly since this class lives in the same package\nimport { SchemaRegistry } from './registry.js';\n\n/**\n * Simple hash function for ETag generation (browser-compatible)\n * Uses a basic hash algorithm instead of crypto.createHash\n */\nfunction simpleHash(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return Math.abs(hash).toString(16);\n}\n\n/**\n * Service Configuration for Discovery\n * Maps service names to their routes and plugin providers\n */\nconst SERVICE_CONFIG: Record<string, { route: string; plugin: string }> = {\n auth: { route: '/api/v1/auth', plugin: 'plugin-auth' },\n automation: { route: '/api/v1/automation', plugin: 'plugin-automation' },\n cache: { route: '/api/v1/cache', plugin: 'plugin-redis' },\n queue: { route: '/api/v1/queue', plugin: 'plugin-bullmq' },\n job: { route: '/api/v1/jobs', plugin: 'job-scheduler' },\n ui: { route: '/api/v1/ui', plugin: 'ui-plugin' },\n workflow: { route: '/api/v1/workflow', plugin: 'plugin-workflow' },\n realtime: { route: '/api/v1/realtime', plugin: 'plugin-realtime' },\n notification: { route: '/api/v1/notifications', plugin: 'plugin-notifications' },\n ai: { route: '/api/v1/ai', plugin: 'plugin-ai' },\n i18n: { route: '/api/v1/i18n', plugin: 'service-i18n' },\n graphql: { route: '/graphql', plugin: 'plugin-graphql' }, // GraphQL uses /graphql by convention (not versioned REST)\n 'file-storage': { route: '/api/v1/storage', plugin: 'plugin-storage' },\n search: { route: '/api/v1/search', plugin: 'plugin-search' },\n};\n\nexport class ObjectStackProtocolImplementation implements ObjectStackProtocol {\n private engine: IDataEngine;\n private getServicesRegistry?: () => Map<string, any>;\n private getFeedService?: () => IFeedService | undefined;\n\n constructor(engine: IDataEngine, getServicesRegistry?: () => Map<string, any>, getFeedService?: () => IFeedService | undefined) {\n this.engine = engine;\n this.getServicesRegistry = getServicesRegistry;\n this.getFeedService = getFeedService;\n }\n\n private requireFeedService(): IFeedService {\n const svc = this.getFeedService?.();\n if (!svc) {\n throw new Error('Feed service not available. Install and register service-feed to enable feed operations.');\n }\n return svc;\n }\n\n async getDiscovery() {\n // Get registered services from kernel if available\n const registeredServices = this.getServicesRegistry ? this.getServicesRegistry() : new Map();\n \n // Build dynamic service info with proper typing\n const services: Record<string, ServiceInfo> = {\n // --- Kernel-provided (objectql is an example kernel implementation) ---\n metadata: { enabled: true, status: 'degraded' as const, route: '/api/v1/meta', provider: 'objectql', message: 'In-memory registry only; DB persistence not yet implemented' },\n data: { enabled: true, status: 'available' as const, route: '/api/v1/data', provider: 'objectql' },\n analytics: { enabled: true, status: 'available' as const, route: '/api/v1/analytics', provider: 'objectql' },\n };\n\n // Check which services are actually registered\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n // Service is registered and available\n services[serviceName] = {\n enabled: true,\n status: 'available' as const,\n route: config.route,\n provider: config.plugin,\n };\n } else {\n // Service is not registered\n services[serviceName] = {\n enabled: false,\n status: 'unavailable' as const,\n message: `Install ${config.plugin} to enable`,\n };\n }\n }\n\n // Build routes from services — a flat convenience map for client routing\n const serviceToRouteKey: Record<string, keyof ApiRoutes> = {\n auth: 'auth',\n automation: 'automation',\n ui: 'ui',\n workflow: 'workflow',\n realtime: 'realtime',\n notification: 'notifications',\n ai: 'ai',\n i18n: 'i18n',\n graphql: 'graphql',\n 'file-storage': 'storage',\n };\n\n const optionalRoutes: Partial<ApiRoutes> = {\n analytics: '/api/v1/analytics',\n };\n\n // Add routes for available plugin services\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n const routeKey = serviceToRouteKey[serviceName];\n if (routeKey) {\n optionalRoutes[routeKey] = config.route;\n }\n }\n }\n\n // Add feed service status\n if (registeredServices.has('feed')) {\n services['feed'] = {\n enabled: true,\n status: 'available' as const,\n route: '/api/v1/data',\n provider: 'service-feed',\n };\n } else {\n services['feed'] = {\n enabled: false,\n status: 'unavailable' as const,\n message: 'Install service-feed to enable',\n };\n }\n\n const routes: ApiRoutes = {\n data: '/api/v1/data',\n metadata: '/api/v1/meta',\n ...optionalRoutes,\n };\n\n // Build well-known capabilities from registered services\n const capabilities: WellKnownCapabilities = {\n feed: registeredServices.has('feed'),\n comments: registeredServices.has('feed'),\n automation: registeredServices.has('automation'),\n cron: registeredServices.has('job'),\n search: registeredServices.has('search'),\n export: registeredServices.has('automation') || registeredServices.has('queue'),\n chunkedUpload: registeredServices.has('file-storage'),\n };\n\n return {\n version: '1.0',\n apiName: 'ObjectStack API',\n routes,\n services,\n capabilities,\n };\n }\n\n async getMetaTypes() {\n return {\n types: SchemaRegistry.getRegisteredTypes()\n };\n }\n\n async getMetaItems(request: { type: string }) {\n let items = SchemaRegistry.listItems(request.type);\n // Normalize singular/plural: REST uses singular ('app') but registry may store as plural ('apps')\n if (items.length === 0) {\n const alt = request.type.endsWith('s') ? request.type.slice(0, -1) : request.type + 's';\n items = SchemaRegistry.listItems(alt);\n }\n return {\n type: request.type,\n items\n };\n }\n\n async getMetaItem(request: { type: string, name: string }) {\n let item = SchemaRegistry.getItem(request.type, request.name);\n // Normalize singular/plural\n if (item === undefined) {\n const alt = request.type.endsWith('s') ? request.type.slice(0, -1) : request.type + 's';\n item = SchemaRegistry.getItem(alt, request.name);\n }\n return {\n type: request.type,\n name: request.name,\n item\n };\n }\n\n async getUiView(request: { object: string, type: 'list' | 'form' }) {\n const schema = SchemaRegistry.getObject(request.object);\n if (!schema) throw new Error(`Object ${request.object} not found`);\n\n const fields = schema.fields || {};\n const fieldKeys = Object.keys(fields);\n\n if (request.type === 'list') {\n // Intelligent Column Selection\n // 1. Always include 'name' or name-like fields\n // 2. Limit to 6 columns by default\n const priorityFields = ['name', 'title', 'label', 'subject', 'email', 'status', 'type', 'category', 'created_at'];\n \n let columns = fieldKeys.filter(k => priorityFields.includes(k));\n \n // If few priority fields, add others until 5\n if (columns.length < 5) {\n const remaining = fieldKeys.filter(k => !columns.includes(k) && k !== 'id' && !fields[k].hidden);\n columns = [...columns, ...remaining.slice(0, 5 - columns.length)];\n }\n \n // Sort columns by priority then alphabet or schema order\n // For now, just keep them roughly in order they appear in schema or priority list\n \n return {\n list: {\n type: 'grid' as const,\n object: request.object,\n label: schema.label || schema.name,\n columns: columns.map(f => ({\n field: f,\n label: fields[f]?.label || f,\n sortable: true\n })),\n sort: fields['created_at'] ? ([{ field: 'created_at', order: 'desc' }] as any) : undefined,\n searchableFields: columns.slice(0, 3) // Make first few textual columns searchable\n }\n };\n } else {\n // Form View Generation\n // Simple single-section layout for now\n const formFields = fieldKeys\n .filter(k => k !== 'id' && k !== 'created_at' && k !== 'updated_at' && !fields[k].hidden)\n .map(f => ({\n field: f,\n label: fields[f]?.label,\n required: fields[f]?.required,\n readonly: fields[f]?.readonly,\n type: fields[f]?.type,\n // Default to 2 columns for most, 1 for textareas\n colSpan: (fields[f]?.type === 'textarea' || fields[f]?.type === 'html') ? 2 : 1\n }));\n\n return {\n form: {\n type: 'simple' as const,\n object: request.object,\n label: `Edit ${schema.label || schema.name}`,\n sections: [\n {\n label: 'General Information',\n columns: 2 as const,\n collapsible: false,\n collapsed: false,\n fields: formFields\n }\n ]\n }\n };\n }\n }\n\n async findData(request: { object: string, query?: any }) {\n const options: any = { ...request.query };\n\n // Numeric fields\n if (options.top != null) options.top = Number(options.top);\n if (options.skip != null) options.skip = Number(options.skip);\n if (options.limit != null) options.limit = Number(options.limit);\n\n // Select: comma-separated string → array\n if (typeof options.select === 'string') {\n options.select = options.select.split(',').map((s: string) => s.trim()).filter(Boolean);\n }\n\n // Sort/orderBy: string → sort array (e.g. \"name asc,created_at desc\" or \"name,-created_at\")\n const sortValue = options.orderBy ?? options.sort;\n if (typeof sortValue === 'string') {\n const parsed = sortValue.split(',').map((part: string) => {\n const trimmed = part.trim();\n if (trimmed.startsWith('-')) {\n return { field: trimmed.slice(1), order: 'desc' as const };\n }\n const [field, order] = trimmed.split(/\\s+/);\n return { field, order: (order?.toLowerCase() === 'desc' ? 'desc' : 'asc') as 'asc' | 'desc' };\n }).filter((s: any) => s.field);\n options.sort = parsed;\n delete options.orderBy;\n }\n\n // Filter: normalize `filter`/`filters` (plural) → `filter` (singular, canonical)\n // Accept both `filter` and `filters` for backward compatibility.\n if (options.filters !== undefined && options.filter === undefined) {\n options.filter = options.filters;\n }\n delete options.filters;\n\n // Filter: JSON string → object\n if (typeof options.filter === 'string') {\n try { options.filter = JSON.parse(options.filter); } catch { /* keep as-is */ }\n }\n\n // Filter AST array → FilterCondition object\n // Converts [\"and\", [\"field\", \"=\", \"val\"], ...] to { $and: [{ field: \"val\" }, ...] }\n if (isFilterAST(options.filter)) {\n options.filter = parseFilterAST(options.filter);\n }\n\n // Populate: comma-separated string → array\n if (typeof options.populate === 'string') {\n options.populate = options.populate.split(',').map((s: string) => s.trim()).filter(Boolean);\n }\n\n // Expand → Populate: normalize $expand/expand to populate array\n // Supports OData $expand, REST expand, and JSON-RPC expand parameters\n const expandValue = options.$expand ?? options.expand;\n if (expandValue && !options.populate) {\n if (typeof expandValue === 'string') {\n options.populate = expandValue.split(',').map((s: string) => s.trim()).filter(Boolean);\n } else if (Array.isArray(expandValue)) {\n options.populate = expandValue;\n }\n }\n delete options.$expand;\n delete options.expand;\n\n // Boolean fields\n for (const key of ['distinct', 'count']) {\n if (options[key] === 'true') options[key] = true;\n else if (options[key] === 'false') options[key] = false;\n }\n \n // Flat field filters: REST-style query params like ?id=abc&status=open\n // After extracting all known query parameters, any remaining keys are\n // treated as implicit field-level equality filters. This is the standard\n // REST convention used by the client when serializing simple filter maps\n // (e.g. `{ filters: { id: \"...\" } }` → `?id=...`).\n const knownParams = new Set([\n 'top', 'skip', 'limit', 'offset',\n 'sort', 'orderBy',\n 'select', 'fields',\n 'filter', 'filters', '$filter',\n 'populate', 'expand', '$expand',\n 'distinct', 'count',\n 'aggregations', 'groupBy',\n 'search', 'context',\n ]);\n if (!options.filter) {\n const implicitFilters: Record<string, unknown> = {};\n for (const key of Object.keys(options)) {\n if (!knownParams.has(key)) {\n implicitFilters[key] = options[key];\n delete options[key];\n }\n }\n if (Object.keys(implicitFilters).length > 0) {\n options.filter = implicitFilters;\n }\n }\n \n const records = await this.engine.find(request.object, options);\n return {\n object: request.object,\n value: records, // OData compaibility\n records, // Legacy\n total: records.length,\n hasMore: false\n };\n }\n\n async getData(request: { object: string, id: string, expand?: string | string[], select?: string | string[] }) {\n const queryOptions: any = {\n filter: { id: request.id }\n };\n\n // Support select for single-record retrieval\n if (request.select) {\n queryOptions.select = typeof request.select === 'string'\n ? request.select.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.select;\n }\n\n // Support expand for single-record retrieval\n if (request.expand) {\n queryOptions.populate = typeof request.expand === 'string'\n ? request.expand.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.expand;\n }\n\n const result = await this.engine.findOne(request.object, queryOptions);\n if (result) {\n return {\n object: request.object,\n id: request.id,\n record: result\n };\n }\n throw new Error(`Record ${request.id} not found in ${request.object}`);\n }\n\n async createData(request: { object: string, data: any }) {\n const result = await this.engine.insert(request.object, request.data);\n return {\n object: request.object,\n id: result.id,\n record: result\n };\n }\n\n async updateData(request: { object: string, id: string, data: any }) {\n // Adapt: update(obj, id, data) -> update(obj, data, options)\n const result = await this.engine.update(request.object, request.data, { filter: { id: request.id } });\n return {\n object: request.object,\n id: request.id,\n record: result\n };\n }\n\n async deleteData(request: { object: string, id: string }) {\n // Adapt: delete(obj, id) -> delete(obj, options)\n await this.engine.delete(request.object, { filter: { id: request.id } });\n return {\n object: request.object,\n id: request.id,\n success: true\n };\n }\n\n // ==========================================\n // Metadata Caching\n // ==========================================\n\n async getMetaItemCached(request: { type: string, name: string, cacheRequest?: MetadataCacheRequest }): Promise<MetadataCacheResponse> {\n try {\n const item = SchemaRegistry.getItem(request.type, request.name);\n if (!item) {\n throw new Error(`Metadata item ${request.type}/${request.name} not found`);\n }\n\n // Calculate ETag (simple hash of the stringified metadata)\n const content = JSON.stringify(item);\n const hash = simpleHash(content);\n const etag = { value: hash, weak: false };\n\n // Check If-None-Match header\n if (request.cacheRequest?.ifNoneMatch) {\n const clientEtag = request.cacheRequest.ifNoneMatch.replace(/^\"(.*)\"$/, '$1').replace(/^W\\/\"(.*)\"$/, '$1');\n if (clientEtag === hash) {\n // Return 304 Not Modified\n return {\n notModified: true,\n etag,\n };\n }\n }\n\n // Return full metadata with cache headers\n return {\n data: item,\n etag,\n lastModified: new Date().toISOString(),\n cacheControl: {\n directives: ['public', 'max-age'],\n maxAge: 3600, // 1 hour\n },\n notModified: false,\n };\n } catch (error: any) {\n throw error;\n }\n }\n\n // ==========================================\n // Batch Operations\n // ==========================================\n\n async batchData(request: { object: string, request: BatchUpdateRequest }): Promise<BatchUpdateResponse> {\n const { object, request: batchReq } = request;\n const { operation, records, options } = batchReq;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n switch (operation) {\n case 'create': {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n succeeded++;\n break;\n }\n case 'update': {\n if (!record.id) throw new Error('Record id is required for update');\n const updated = await this.engine.update(object, record.data || {}, { filter: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n break;\n }\n case 'upsert': {\n // Try update first, then create if not found\n if (record.id) {\n try {\n const existing = await this.engine.findOne(object, { filter: { id: record.id } });\n if (existing) {\n const updated = await this.engine.update(object, record.data || {}, { filter: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n } else {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } catch {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } else {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n }\n succeeded++;\n break;\n }\n case 'delete': {\n if (!record.id) throw new Error('Record id is required for delete');\n await this.engine.delete(object, { filter: { id: record.id } });\n results.push({ id: record.id, success: true });\n succeeded++;\n break;\n }\n default:\n results.push({ id: record.id, success: false, error: `Unknown operation: ${operation}` });\n failed++;\n }\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (options?.atomic) {\n // Abort remaining operations on first failure in atomic mode\n break;\n }\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation,\n total: records.length,\n succeeded,\n failed,\n results: options?.returnRecords !== false ? results : results.map(r => ({ id: r.id, success: r.success, error: r.error })),\n } as BatchUpdateResponse;\n }\n \n async createManyData(request: { object: string, records: any[] }): Promise<any> {\n const records = await this.engine.insert(request.object, request.records);\n return {\n object: request.object,\n records,\n count: records.length\n };\n }\n \n async updateManyData(request: UpdateManyDataRequest): Promise<BatchUpdateResponse> {\n const { object, records, options } = request;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n const updated = await this.engine.update(object, record.data, { filter: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation: 'update',\n total: records.length,\n succeeded,\n failed,\n results,\n } as BatchUpdateResponse;\n }\n\n async analyticsQuery(request: any): Promise<any> {\n // Map AnalyticsQuery (cube-style) to engine aggregation.\n // cube name maps to object name; measures → aggregations; dimensions → groupBy.\n const { query, cube } = request;\n const object = cube;\n\n // Build groupBy from dimensions\n const groupBy = query.dimensions || [];\n\n // Build aggregations from measures\n // Measures can be simple field names like \"count\" or \"field_name.sum\"\n // Or cube-defined measure names. We support: field.function or just function(field).\n const aggregations: Array<{ field: string; method: string; alias: string }> = [];\n if (query.measures) {\n for (const measure of query.measures) {\n // Support formats: \"count\", \"amount.sum\", \"revenue.avg\"\n if (measure === 'count' || measure === 'count_all') {\n aggregations.push({ field: '*', method: 'count', alias: 'count' });\n } else if (measure.includes('.')) {\n const [field, method] = measure.split('.');\n aggregations.push({ field, method, alias: `${field}_${method}` });\n } else {\n // Treat as count of the field\n aggregations.push({ field: measure, method: 'sum', alias: measure });\n }\n }\n }\n\n // Build filter from analytics filters\n let filter: any = undefined;\n if (query.filters && query.filters.length > 0) {\n const conditions: any[] = query.filters.map((f: any) => {\n const op = this.mapAnalyticsOperator(f.operator);\n if (f.values && f.values.length === 1) {\n return { [f.member]: { [op]: f.values[0] } };\n } else if (f.values && f.values.length > 1) {\n return { [f.member]: { $in: f.values } };\n }\n return { [f.member]: { [op]: true } };\n });\n filter = conditions.length === 1 ? conditions[0] : { $and: conditions };\n }\n\n // Execute via engine.aggregate (which delegates to driver.find with groupBy/aggregations)\n const rows = await this.engine.aggregate(object, {\n filter,\n groupBy: groupBy.length > 0 ? groupBy : undefined,\n aggregations: aggregations.length > 0\n ? aggregations.map(a => ({ field: a.field, method: a.method as any, alias: a.alias }))\n : [{ field: '*', method: 'count' as any, alias: 'count' }],\n });\n\n // Build field metadata\n const fields = [\n ...groupBy.map((d: string) => ({ name: d, type: 'string' })),\n ...aggregations.map(a => ({ name: a.alias, type: 'number' })),\n ];\n\n return {\n success: true,\n data: {\n rows,\n fields,\n },\n };\n }\n\n async getAnalyticsMeta(request: any): Promise<any> {\n // Auto-generate cube metadata from registered objects in SchemaRegistry.\n // Each object becomes a cube; number fields → measures; other fields → dimensions.\n const objects = SchemaRegistry.listItems('object');\n const cubeFilter = request?.cube;\n\n const cubes: any[] = [];\n for (const obj of objects) {\n const schema = obj as any;\n if (cubeFilter && schema.name !== cubeFilter) continue;\n\n const measures: Record<string, any> = {};\n const dimensions: Record<string, any> = {};\n const fields = schema.fields || {};\n\n // Always add a count measure\n measures['count'] = {\n name: 'count',\n label: 'Count',\n type: 'count',\n sql: '*',\n };\n\n for (const [fieldName, fieldDef] of Object.entries(fields)) {\n const fd = fieldDef as any;\n const fieldType = fd.type || 'text';\n\n if (['number', 'currency', 'percent'].includes(fieldType)) {\n // Numeric fields become both measures and dimensions\n measures[`${fieldName}_sum`] = {\n name: `${fieldName}_sum`,\n label: `${fd.label || fieldName} (Sum)`,\n type: 'sum',\n sql: fieldName,\n };\n measures[`${fieldName}_avg`] = {\n name: `${fieldName}_avg`,\n label: `${fd.label || fieldName} (Avg)`,\n type: 'avg',\n sql: fieldName,\n };\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'number',\n sql: fieldName,\n };\n } else if (['date', 'datetime'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'time',\n sql: fieldName,\n granularities: ['day', 'week', 'month', 'quarter', 'year'],\n };\n } else if (['boolean'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'boolean',\n sql: fieldName,\n };\n } else {\n // text, select, lookup, etc. → dimension\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'string',\n sql: fieldName,\n };\n }\n }\n\n cubes.push({\n name: schema.name,\n title: schema.label || schema.name,\n description: schema.description,\n sql: schema.name,\n measures,\n dimensions,\n public: true,\n });\n }\n\n return {\n success: true,\n data: { cubes },\n };\n }\n\n private mapAnalyticsOperator(op: string): string {\n const map: Record<string, string> = {\n equals: '$eq',\n notEquals: '$ne',\n contains: '$contains',\n notContains: '$notContains',\n gt: '$gt',\n gte: '$gte',\n lt: '$lt',\n lte: '$lte',\n set: '$ne',\n notSet: '$eq',\n };\n return map[op] || '$eq';\n }\n\n async triggerAutomation(_request: any): Promise<any> {\n throw new Error('triggerAutomation requires plugin-automation service. Install and register a plugin that provides the \"automation\" service.');\n }\n\n async deleteManyData(request: DeleteManyDataRequest): Promise<any> {\n // This expects deleting by IDs.\n return this.engine.delete(request.object, {\n filter: { id: { $in: request.ids } },\n ...request.options\n });\n }\n\n async saveMetaItem(request: { type: string, name: string, item?: any }) {\n if (!request.item) {\n throw new Error('Item data is required');\n }\n // Default implementation saves to Memory Registry\n SchemaRegistry.registerItem(request.type, request.item, 'name');\n return {\n success: true,\n message: 'Saved to memory registry'\n };\n }\n\n // ==========================================\n // Feed Operations\n // ==========================================\n\n async listFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n return { success: true, data: result };\n }\n\n async createFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.createFeedItem({\n object: request.object,\n recordId: request.recordId,\n type: request.type,\n actor: { type: 'user', id: 'current_user' },\n body: request.body,\n mentions: request.mentions,\n parentId: request.parentId,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async updateFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.updateFeedItem(request.feedId, {\n body: request.body,\n mentions: request.mentions,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async deleteFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n await svc.deleteFeedItem(request.feedId);\n return { success: true, data: { feedId: request.feedId } };\n }\n\n async addReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.addReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async removeReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.removeReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async pinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated pin/unpin — use updateFeedItem to persist pin state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: true, pinnedAt: new Date().toISOString() } };\n }\n\n async unpinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: false } };\n }\n\n async starFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated star/unstar — verify item exists then return state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: true, starredAt: new Date().toISOString() } };\n }\n\n async unstarFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: false } };\n }\n\n async searchFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Search delegates to listFeed with filter since IFeedService doesn't have a dedicated search\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n // Filter by query text in body\n const queryLower = (request.query || '').toLowerCase();\n const filtered = result.items.filter((item: any) =>\n item.body?.toLowerCase().includes(queryLower)\n );\n return { success: true, data: { items: filtered, total: filtered.length, hasMore: false } };\n }\n\n async getChangelog(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Changelog retrieves field_change type feed items\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: 'changes_only',\n limit: request.limit,\n cursor: request.cursor,\n });\n const entries = result.items.map((item: any) => ({\n id: item.id,\n object: item.object,\n recordId: item.recordId,\n actor: item.actor,\n changes: item.changes || [],\n timestamp: item.createdAt,\n source: item.source,\n }));\n return { success: true, data: { entries, total: result.total, nextCursor: result.nextCursor, hasMore: result.hasMore } };\n }\n\n async feedSubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const subscription = await svc.subscribe({\n object: request.object,\n recordId: request.recordId,\n userId: 'current_user',\n events: request.events,\n channels: request.channels,\n });\n return { success: true, data: subscription };\n }\n\n async feedUnsubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const unsubscribed = await svc.unsubscribe(request.object, request.recordId, 'current_user');\n return { success: true, data: { object: request.object, recordId: request.recordId, unsubscribed } };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { QueryAST, HookContext, ServiceObject } from '@objectstack/spec/data';\nimport { \n DataEngineQueryOptions, \n DataEngineInsertOptions, \n DataEngineUpdateOptions, \n DataEngineDeleteOptions,\n DataEngineAggregateOptions,\n DataEngineCountOptions \n} from '@objectstack/spec/data';\nimport { ExecutionContext, ExecutionContextSchema } from '@objectstack/spec/kernel';\nimport { DriverInterface, IDataEngine, Logger, createLogger } from '@objectstack/core';\nimport { CoreServiceName } from '@objectstack/spec/system';\nimport { SchemaRegistry } from './registry.js';\n\nexport type HookHandler = (context: HookContext) => Promise<void> | void;\n\n/**\n * Per-object hook entry with priority support\n */\nexport interface HookEntry {\n handler: HookHandler;\n object?: string | string[]; // undefined = global hook\n priority: number;\n packageId?: string;\n}\n\n/**\n * Operation Context for Middleware Chain\n */\nexport interface OperationContext {\n object: string;\n operation: 'find' | 'findOne' | 'insert' | 'update' | 'delete' | 'count' | 'aggregate';\n ast?: QueryAST;\n data?: any;\n options?: any;\n context?: ExecutionContext;\n result?: any;\n}\n\n/**\n * Engine Middleware (Onion model)\n */\nexport type EngineMiddleware = (\n ctx: OperationContext,\n next: () => Promise<void>\n) => Promise<void>;\n\n/**\n * Host Context provided to plugins (Internal ObjectQL Plugin System)\n */\nexport interface ObjectQLHostContext {\n ql: ObjectQL;\n logger: Logger;\n // Extensible map for host-specific globals (like HTTP Router, etc.)\n [key: string]: any;\n}\n\n/**\n * ObjectQL Engine\n * \n * Implements the IDataEngine interface for data persistence.\n * Acts as the reference implementation for:\n * - CoreServiceName.data (CRUD)\n * - CoreServiceName.metadata (Schema Registry)\n */\nexport class ObjectQL implements IDataEngine {\n private drivers = new Map<string, DriverInterface>();\n private defaultDriver: string | null = null;\n private logger: Logger;\n \n // Per-object hooks with priority support\n private hooks: Map<string, HookEntry[]> = new Map([\n ['beforeFind', []], ['afterFind', []],\n ['beforeInsert', []], ['afterInsert', []],\n ['beforeUpdate', []], ['afterUpdate', []],\n ['beforeDelete', []], ['afterDelete', []],\n ]);\n\n // Middleware chain (onion model)\n private middlewares: Array<{\n fn: EngineMiddleware;\n object?: string;\n }> = [];\n\n // Action registry: key = \"objectName:actionName\"\n private actions = new Map<string, { handler: (ctx: any) => Promise<any> | any; package?: string }>();\n \n // Host provided context additions (e.g. Server router)\n private hostContext: Record<string, any> = {};\n\n constructor(hostContext: Record<string, any> = {}) {\n this.hostContext = hostContext;\n // Use provided logger or create a new one\n this.logger = hostContext.logger || createLogger({ level: 'info', format: 'pretty' });\n this.logger.info('ObjectQL Engine Instance Created');\n }\n\n /**\n * Service Status Report\n * Used by Kernel to verify health and capabilities.\n */\n getStatus() {\n return {\n name: CoreServiceName.enum.data,\n status: 'running',\n version: '0.9.0',\n features: ['crud', 'query', 'aggregate', 'transactions', 'metadata']\n };\n }\n\n /**\n * Expose the SchemaRegistry for plugins to register metadata\n */\n get registry() {\n return SchemaRegistry;\n }\n\n /**\n * Load and Register a Plugin\n */\n async use(manifestPart: any, runtimePart?: any) {\n this.logger.debug('Loading plugin', { \n hasManifest: !!manifestPart, \n hasRuntime: !!runtimePart \n });\n\n // 1. Validate / Register Manifest\n if (manifestPart) {\n this.registerApp(manifestPart);\n }\n\n // 2. Execute Runtime\n if (runtimePart) {\n const pluginDef = (runtimePart as any).default || runtimePart;\n if (pluginDef.onEnable) {\n this.logger.debug('Executing plugin runtime onEnable');\n \n const context: ObjectQLHostContext = {\n ql: this,\n logger: this.logger,\n // Expose the driver registry helper explicitly if needed\n drivers: {\n register: (driver: DriverInterface) => this.registerDriver(driver)\n },\n ...this.hostContext\n };\n \n await pluginDef.onEnable(context);\n this.logger.debug('Plugin runtime onEnable completed');\n }\n }\n }\n\n /**\n * Register a hook\n * @param event The event name (e.g. 'beforeFind', 'afterInsert')\n * @param handler The handler function\n * @param options Optional: target object(s) and priority\n */\n registerHook(event: string, handler: HookHandler, options?: {\n object?: string | string[];\n priority?: number;\n packageId?: string;\n }) {\n if (!this.hooks.has(event)) {\n this.hooks.set(event, []);\n }\n const entries = this.hooks.get(event)!;\n entries.push({\n handler,\n object: options?.object,\n priority: options?.priority ?? 100,\n packageId: options?.packageId,\n });\n // Sort by priority (lower runs first)\n entries.sort((a, b) => a.priority - b.priority);\n this.logger.debug('Registered hook', { event, object: options?.object, priority: options?.priority ?? 100, totalHandlers: entries.length });\n }\n\n public async triggerHooks(event: string, context: HookContext) {\n const entries = this.hooks.get(event) || [];\n \n if (entries.length === 0) {\n this.logger.debug('No hooks registered for event', { event });\n return;\n }\n\n this.logger.debug('Triggering hooks', { event, count: entries.length });\n \n for (const entry of entries) {\n // Per-object matching\n if (entry.object) {\n const targets = Array.isArray(entry.object) ? entry.object : [entry.object];\n if (!targets.includes('*') && !targets.includes(context.object)) {\n continue; // Skip non-matching hooks\n }\n }\n await entry.handler(context);\n }\n }\n\n // ========================================\n // Action System\n // ========================================\n\n /**\n * Register a named action on an object.\n * Actions are custom business logic callable via `repo.execute(actionName, params)`.\n *\n * @param objectName Target object\n * @param actionName Unique action name within the object\n * @param handler Handler function\n * @param packageName Optional package owner (for cleanup)\n */\n registerAction(objectName: string, actionName: string, handler: (ctx: any) => Promise<any> | any, packageName?: string): void {\n const key = `${objectName}:${actionName}`;\n this.actions.set(key, { handler, package: packageName });\n this.logger.debug('Registered action', { objectName, actionName, package: packageName });\n }\n\n /**\n * Execute a named action on an object.\n */\n async executeAction(objectName: string, actionName: string, ctx: any): Promise<any> {\n const entry = this.actions.get(`${objectName}:${actionName}`);\n if (!entry) {\n throw new Error(`Action '${actionName}' on object '${objectName}' not found`);\n }\n return entry.handler(ctx);\n }\n\n /**\n * Remove all actions registered by a specific package.\n */\n removeActionsByPackage(packageName: string): void {\n for (const [key, entry] of this.actions.entries()) {\n if (entry.package === packageName) {\n this.actions.delete(key);\n }\n }\n }\n\n /**\n * Register a middleware function\n * Middlewares execute in onion model around every data operation.\n * @param fn The middleware function\n * @param options Optional: target object filter\n */\n registerMiddleware(fn: EngineMiddleware, options?: { object?: string }): void {\n this.middlewares.push({ fn, object: options?.object });\n this.logger.debug('Registered middleware', { object: options?.object, total: this.middlewares.length });\n }\n\n /**\n * Execute an operation through the middleware chain\n */\n private async executeWithMiddleware(ctx: OperationContext, executor: () => Promise<any>): Promise<any> {\n const applicable = this.middlewares.filter(m =>\n !m.object || m.object === '*' || m.object === ctx.object\n );\n\n let index = 0;\n const next = async (): Promise<void> => {\n if (index < applicable.length) {\n const mw = applicable[index++];\n await mw.fn(ctx, next);\n } else {\n ctx.result = await executor();\n }\n };\n\n await next();\n return ctx.result;\n }\n\n /**\n * Build a HookContext.session from ExecutionContext\n */\n private buildSession(execCtx?: ExecutionContext): HookContext['session'] {\n if (!execCtx) return undefined;\n return {\n userId: execCtx.userId,\n tenantId: execCtx.tenantId,\n roles: execCtx.roles,\n accessToken: execCtx.accessToken,\n };\n }\n\n /**\n * Register contribution (Manifest)\n * \n * Installs the manifest as a Package (the unit of installation),\n * then decomposes it into individual metadata items (objects, apps, actions, etc.)\n * and registers each into the SchemaRegistry.\n * \n * Key: Package ≠ App. The manifest is the package. The apps[] array inside\n * the manifest contains UI navigation definitions (AppSchema).\n */\n registerApp(manifest: any) {\n const id = manifest.id || manifest.name;\n const namespace = manifest.namespace as string | undefined;\n this.logger.debug('Registering package manifest', { id, namespace });\n\n // 1. Register the Package (manifest + lifecycle state)\n SchemaRegistry.installPackage(manifest);\n this.logger.debug('Installed Package', { id: manifest.id, name: manifest.name, namespace });\n\n // 2. Register owned objects\n if (manifest.objects) {\n if (Array.isArray(manifest.objects)) {\n this.logger.debug('Registering objects from manifest (Array)', { id, objectCount: manifest.objects.length });\n for (const objDef of manifest.objects) {\n const fqn = SchemaRegistry.registerObject(objDef, id, namespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: id });\n }\n } else {\n this.logger.debug('Registering objects from manifest (Map)', { id, objectCount: Object.keys(manifest.objects).length });\n for (const [name, objDef] of Object.entries(manifest.objects)) {\n // Ensure name in definition matches key\n (objDef as any).name = name;\n const fqn = SchemaRegistry.registerObject(objDef as any, id, namespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: id });\n }\n }\n }\n\n // 2b. Register object extensions (fields added to objects owned by other packages)\n if (Array.isArray(manifest.objectExtensions) && manifest.objectExtensions.length > 0) {\n this.logger.debug('Registering object extensions', { id, count: manifest.objectExtensions.length });\n for (const ext of manifest.objectExtensions) {\n const targetFqn = ext.extend;\n const priority = ext.priority ?? 200;\n // Create a partial object definition for the extension\n const extDef = {\n name: targetFqn, // Use the target FQN as name\n fields: ext.fields,\n label: ext.label,\n pluralLabel: ext.pluralLabel,\n description: ext.description,\n validations: ext.validations,\n indexes: ext.indexes,\n };\n // Register as extension (namespace is undefined since we're targeting by FQN)\n SchemaRegistry.registerObject(extDef as any, id, undefined, 'extend', priority);\n this.logger.debug('Registered Object Extension', { target: targetFqn, priority, from: id });\n }\n }\n\n // 3. Register apps (UI navigation definitions) as their own metadata type\n if (Array.isArray(manifest.apps) && manifest.apps.length > 0) {\n this.logger.debug('Registering apps from manifest', { id, count: manifest.apps.length });\n for (const app of manifest.apps) {\n const appName = app.name || app.id;\n if (appName) {\n SchemaRegistry.registerApp(app, id);\n this.logger.debug('Registered App', { app: appName, from: id });\n }\n }\n }\n\n // 4. If manifest itself looks like an App (has navigation), also register as app\n // This handles the case where the manifest IS the app definition (legacy/simple packages)\n if (manifest.name && manifest.navigation && !manifest.apps?.length) {\n SchemaRegistry.registerApp(manifest, id);\n this.logger.debug('Registered manifest-as-app', { app: manifest.name, from: id });\n }\n\n // 5. Register all other metadata types generically\n const metadataArrayKeys = [\n // UI Protocol\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'themes',\n // Automation Protocol\n 'flows', 'workflows', 'approvals', 'webhooks',\n // Security Protocol\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n // AI Protocol\n 'agents', 'ragPipelines',\n // API Protocol\n 'apis',\n // Data Extensions\n 'hooks', 'mappings', 'analyticsCubes',\n // Integration Protocol\n 'connectors',\n ];\n for (const key of metadataArrayKeys) {\n const items = (manifest as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n this.logger.debug(`Registering ${key} from manifest`, { id, count: items.length });\n for (const item of items) {\n const itemName = item.name || item.id;\n if (itemName) {\n SchemaRegistry.registerItem(key, item, 'name' as any, id);\n }\n }\n }\n }\n\n // 6. Register seed data as metadata (keyed by target object name)\n const seedData = (manifest as any).data;\n if (Array.isArray(seedData) && seedData.length > 0) {\n this.logger.debug('Registering seed data datasets', { id, count: seedData.length });\n for (const dataset of seedData) {\n if (dataset.object) {\n SchemaRegistry.registerItem('data', dataset, 'object' as any, id);\n }\n }\n }\n\n // 6. Register contributions\n if (manifest.contributes?.kinds) {\n this.logger.debug('Registering kinds from manifest', { id, kindCount: manifest.contributes.kinds.length });\n for (const kind of manifest.contributes.kinds) {\n SchemaRegistry.registerKind(kind);\n this.logger.debug('Registered Kind', { kind: kind.name || kind.type, from: id });\n }\n }\n\n // 7. Recursively register nested plugins\n if (Array.isArray(manifest.plugins) && manifest.plugins.length > 0) {\n this.logger.debug('Processing nested plugins', { id, count: manifest.plugins.length });\n for (const plugin of manifest.plugins) {\n if (plugin && typeof plugin === 'object') {\n const pluginName = plugin.name || plugin.id || 'unnamed-plugin';\n this.logger.debug('Registering nested plugin', { pluginName, parentId: id });\n this.registerPlugin(plugin, id, namespace);\n }\n }\n }\n }\n\n /**\n * Register a nested plugin's metadata (objects, actions, views, etc.)\n *\n * Unlike registerApp(), this does NOT call SchemaRegistry.installPackage()\n * because plugins are not formal manifests — they are lightweight config\n * bundles with objects, actions, triggers, and navigation.\n *\n * @param plugin - The plugin config object\n * @param parentId - The parent package ID (for ownership tracking)\n * @param parentNamespace - The parent package's namespace (for FQN resolution)\n */\n private registerPlugin(plugin: any, parentId: string, parentNamespace?: string) {\n const pluginName = plugin.name || plugin.id || 'unnamed';\n const pluginNamespace = plugin.namespace || parentNamespace;\n\n // Use parentId as the owning package for namespace consistency.\n // The parent package already claimed the namespace — nested plugins\n // contribute objects UNDER the parent's ownership.\n const ownerId = parentId;\n\n // Register objects (supports both Array and Map formats)\n if (plugin.objects) {\n try {\n if (Array.isArray(plugin.objects)) {\n this.logger.debug('Registering plugin objects (Array)', { pluginName, count: plugin.objects.length });\n for (const objDef of plugin.objects) {\n const fqn = SchemaRegistry.registerObject(objDef, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n } else {\n const entries = Object.entries(plugin.objects);\n this.logger.debug('Registering plugin objects (Map)', { pluginName, count: entries.length });\n for (const [name, objDef] of entries) {\n (objDef as any).name = name;\n const fqn = SchemaRegistry.registerObject(objDef as any, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n }\n } catch (err: any) {\n this.logger.warn('Failed to register plugin objects', { pluginName, error: err.message });\n }\n }\n\n // Register plugin as app if it has navigation (for sidebar display)\n if (plugin.name && plugin.navigation) {\n try {\n SchemaRegistry.registerApp(plugin, ownerId);\n this.logger.debug('Registered plugin-as-app', { app: plugin.name, from: pluginName });\n } catch (err: any) {\n this.logger.warn('Failed to register plugin as app', { pluginName, error: err.message });\n }\n }\n\n // Register metadata arrays (actions, views, triggers, etc.)\n const metadataArrayKeys = [\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'themes',\n 'flows', 'workflows', 'approvals', 'webhooks',\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n 'agents', 'ragPipelines', 'apis',\n 'hooks', 'mappings', 'analyticsCubes', 'connectors',\n ];\n for (const key of metadataArrayKeys) {\n const items = (plugin as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n for (const item of items) {\n const itemName = item.name || item.id;\n if (itemName) {\n SchemaRegistry.registerItem(key, item, 'name' as any, ownerId);\n }\n }\n }\n }\n }\n\n /**\n * Register a new storage driver\n */\n registerDriver(driver: DriverInterface, isDefault: boolean = false) {\n if (this.drivers.has(driver.name)) {\n this.logger.warn('Driver already registered, skipping', { driverName: driver.name });\n return;\n }\n\n this.drivers.set(driver.name, driver);\n this.logger.info('Registered driver', { \n driverName: driver.name, \n version: driver.version\n });\n\n if (isDefault || this.drivers.size === 1) {\n this.defaultDriver = driver.name;\n this.logger.info('Set default driver', { driverName: driver.name });\n }\n }\n\n /**\n * Helper to get object definition\n */\n getSchema(objectName: string): ServiceObject | undefined {\n return SchemaRegistry.getObject(objectName);\n }\n\n /**\n * Resolve an object name to its Fully Qualified Name (FQN).\n * \n * Short names like 'task' are resolved to FQN like 'todo__task'\n * via SchemaRegistry lookup. If no match is found, the name is\n * returned as-is (for ad-hoc / unregistered objects).\n * \n * This ensures that all driver operations use a consistent key\n * regardless of whether the caller uses the short name or FQN.\n */\n private resolveObjectName(name: string): string {\n const schema = SchemaRegistry.getObject(name);\n if (schema) {\n // Prefer the physical table name (e.g., 'sys_user') over the FQN\n // (e.g., 'sys__user'). ObjectSchema.create() auto-derives tableName\n // as {namespace}_{name} which matches the storage convention.\n return schema.tableName || schema.name;\n }\n return name; // Ad-hoc object, keep as-is\n }\n\n /**\n * Helper to get the target driver\n */\n private getDriver(objectName: string): DriverInterface {\n const object = SchemaRegistry.getObject(objectName);\n \n // 1. If object definition exists, check for explicit datasource\n if (object) {\n const datasourceName = object.datasource || 'default';\n \n // If configured for 'default', try to find the default driver\n if (datasourceName === 'default') {\n if (this.defaultDriver && this.drivers.has(this.defaultDriver)) {\n return this.drivers.get(this.defaultDriver)!;\n }\n } else {\n // Specific datasource requested\n if (this.drivers.has(datasourceName)) {\n return this.drivers.get(datasourceName)!;\n }\n throw new Error(`[ObjectQL] Datasource '${datasourceName}' configured for object '${objectName}' is not registered.`);\n }\n }\n\n // 2. Fallback for ad-hoc objects or missing definitions\n if (this.defaultDriver) {\n return this.drivers.get(this.defaultDriver)!;\n }\n\n throw new Error(`[ObjectQL] No driver available for object '${objectName}'`);\n }\n\n /**\n * Initialize the engine and all registered drivers\n */\n async init() {\n this.logger.info('Initializing ObjectQL engine', { \n driverCount: this.drivers.size,\n drivers: Array.from(this.drivers.keys())\n });\n \n for (const [name, driver] of this.drivers) {\n try {\n await driver.connect();\n this.logger.info('Driver connected successfully', { driverName: name });\n } catch (e) {\n this.logger.error('Failed to connect driver', e as Error, { driverName: name });\n }\n }\n \n this.logger.info('ObjectQL engine initialization complete');\n }\n\n async destroy() {\n this.logger.info('Destroying ObjectQL engine', { driverCount: this.drivers.size });\n \n for (const [name, driver] of this.drivers.entries()) {\n try {\n await driver.disconnect();\n } catch (e) {\n this.logger.error('Error disconnecting driver', e as Error, { driverName: name });\n }\n }\n \n this.logger.info('ObjectQL engine destroyed');\n }\n\n // ============================================\n // Helper: Expand Related Records\n // ============================================\n\n /** Maximum depth for recursive expand to prevent infinite loops */\n private static readonly MAX_EXPAND_DEPTH = 3;\n\n /**\n * Post-process expand: resolve lookup/master_detail fields by batch-loading related records.\n * \n * This is a driver-agnostic implementation that uses secondary queries ($in batches)\n * to load related records, then injects them into the result set.\n * \n * @param objectName - The source object name\n * @param records - The records returned by the driver\n * @param expand - The expand map from QueryAST (field name → nested QueryAST)\n * @param depth - Current recursion depth (0-based)\n * @returns Records with expanded lookup fields (IDs replaced by full objects)\n */\n private async expandRelatedRecords(\n objectName: string,\n records: any[],\n expand: Record<string, QueryAST>,\n depth: number = 0,\n ): Promise<any[]> {\n if (!records || records.length === 0) return records;\n if (depth >= ObjectQL.MAX_EXPAND_DEPTH) return records;\n\n const objectSchema = SchemaRegistry.getObject(objectName);\n // If no schema registered, skip expand — return raw data\n if (!objectSchema || !objectSchema.fields) return records;\n\n for (const [fieldName, nestedAST] of Object.entries(expand)) {\n const fieldDef = objectSchema.fields[fieldName];\n\n // Skip if field not found or not a relationship type\n if (!fieldDef || !fieldDef.reference) continue;\n if (fieldDef.type !== 'lookup' && fieldDef.type !== 'master_detail') continue;\n\n const referenceObject = fieldDef.reference;\n\n // Collect all foreign key IDs from records (handle both single and multiple values)\n const allIds: any[] = [];\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n if (Array.isArray(val)) {\n allIds.push(...val.filter((id: any) => id != null));\n } else if (typeof val === 'object') {\n // Already expanded — skip\n continue;\n } else {\n allIds.push(val);\n }\n }\n\n // De-duplicate IDs\n const uniqueIds = [...new Set(allIds)];\n if (uniqueIds.length === 0) continue;\n\n // Batch-load related records using $in query\n try {\n const relatedQuery: QueryAST = {\n object: referenceObject,\n where: { id: { $in: uniqueIds } },\n ...(nestedAST.fields ? { fields: nestedAST.fields } : {}),\n ...(nestedAST.orderBy ? { orderBy: nestedAST.orderBy } : {}),\n };\n\n const driver = this.getDriver(referenceObject);\n const relatedRecords = await driver.find(referenceObject, relatedQuery) ?? [];\n\n // Build a lookup map: id → record\n const recordMap = new Map<string, any>();\n for (const rec of relatedRecords) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n\n // Recursively expand nested relations if present\n if (nestedAST.expand && Object.keys(nestedAST.expand).length > 0) {\n const expandedRelated = await this.expandRelatedRecords(\n referenceObject,\n relatedRecords,\n nestedAST.expand,\n depth + 1,\n );\n // Rebuild map with expanded records\n recordMap.clear();\n for (const rec of expandedRelated) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n }\n\n // Inject expanded records back into the original result set\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n\n if (Array.isArray(val)) {\n record[fieldName] = val.map((id: any) => recordMap.get(String(id)) ?? id);\n } else if (typeof val !== 'object') {\n record[fieldName] = recordMap.get(String(val)) ?? val;\n }\n // If val is already an object, leave it as-is\n }\n } catch (e) {\n // Graceful degradation: if expand fails, keep original IDs\n this.logger.warn('Failed to expand relationship field; retaining foreign key IDs', {\n object: objectName,\n field: fieldName,\n reference: referenceObject,\n error: (e as Error).message,\n });\n }\n }\n\n return records;\n }\n\n // ============================================\n // Helper: Query Conversion\n // ============================================\n\n private toQueryAST(object: string, options?: DataEngineQueryOptions): QueryAST {\n const ast: QueryAST = { object };\n if (!options) return ast;\n\n if (options.filter) {\n ast.where = options.filter;\n }\n if (options.select) {\n ast.fields = options.select;\n }\n if (options.sort) {\n // Support DataEngineSortSchema variant\n if (Array.isArray(options.sort)) {\n // [{ field: 'a', order: 'asc' }]\n ast.orderBy = options.sort; \n } else {\n // Record<string, 'asc' | 'desc' | 1 | -1>\n ast.orderBy = Object.entries(options.sort).map(([field, order]) => ({\n field,\n order: (order === -1 || order === 'desc') ? 'desc' : 'asc'\n }));\n }\n }\n \n if (options.top !== undefined) ast.limit = options.top;\n else if (options.limit !== undefined) ast.limit = options.limit;\n \n if (options.skip !== undefined) ast.offset = options.skip;\n\n // Map populate (relationship field names) to QueryAST expand entries\n if (options.populate && options.populate.length > 0) {\n ast.expand = {};\n for (const rel of options.populate) {\n ast.expand[rel] = { object: rel };\n }\n }\n\n return ast;\n }\n\n // ============================================\n // Data Access Methods (IDataEngine Interface)\n // ============================================\n\n async find(object: string, query?: DataEngineQueryOptions): Promise<any[]> {\n object = this.resolveObjectName(object);\n this.logger.debug('Find operation starting', { object, query });\n const driver = this.getDriver(object);\n const ast = this.toQueryAST(object, query);\n\n const opCtx: OperationContext = {\n object,\n operation: 'find',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeFind',\n input: { ast: opCtx.ast, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeFind', hookContext);\n\n try {\n let result = await driver.find(object, hookContext.input.ast as QueryAST, hookContext.input.options as any);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && Array.isArray(result)) {\n result = await this.expandRelatedRecords(object, result, ast.expand, 0);\n }\n \n hookContext.event = 'afterFind';\n hookContext.result = result;\n await this.triggerHooks('afterFind', hookContext);\n \n return hookContext.result;\n } catch (e) {\n this.logger.error('Find operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result as any[];\n }\n\n async findOne(objectName: string, query?: DataEngineQueryOptions): Promise<any> {\n objectName = this.resolveObjectName(objectName);\n this.logger.debug('FindOne operation', { objectName });\n const driver = this.getDriver(objectName);\n const ast = this.toQueryAST(objectName, query);\n ast.limit = 1;\n\n const opCtx: OperationContext = {\n object: objectName,\n operation: 'findOne',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n let result = await driver.findOne(objectName, opCtx.ast as QueryAST);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && result != null) {\n const expanded = await this.expandRelatedRecords(objectName, [result], ast.expand, 0);\n result = expanded[0];\n }\n\n return result;\n });\n\n return opCtx.result;\n }\n\n async insert(object: string, data: any | any[], options?: DataEngineInsertOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Insert operation starting', { object, isBatch: Array.isArray(data) });\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'insert',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeInsert',\n input: { data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeInsert', hookContext);\n\n try {\n let result;\n if (Array.isArray(hookContext.input.data)) {\n // Bulk Create\n if (driver.bulkCreate) {\n result = await driver.bulkCreate(object, hookContext.input.data as any[], hookContext.input.options as any);\n } else {\n // Fallback loop\n result = await Promise.all((hookContext.input.data as any[]).map((item: any) => driver.create(object, item, hookContext.input.options as any)));\n }\n } else {\n result = await driver.create(object, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n }\n\n hookContext.event = 'afterInsert';\n hookContext.result = result;\n await this.triggerHooks('afterInsert', hookContext);\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Insert operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async update(object: string, data: any, options?: DataEngineUpdateOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Update operation starting', { object });\n const driver = this.getDriver(object);\n \n // 1. Extract ID from data or filter if it's a single update by ID\n let id = data.id;\n if (!id && options?.filter) {\n if (typeof options.filter === 'string') id = options.filter;\n else if (options.filter.id) id = options.filter.id;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'update',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeUpdate',\n input: { id, data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeUpdate', hookContext);\n\n try {\n let result;\n if (hookContext.input.id) {\n result = await driver.update(object, hookContext.input.id as string, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else if (options?.multi && driver.updateMany) {\n const ast = this.toQueryAST(object, { filter: options.filter });\n result = await driver.updateMany(object, ast, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else {\n throw new Error('Update requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterUpdate';\n hookContext.result = result;\n await this.triggerHooks('afterUpdate', hookContext);\n return hookContext.result;\n } catch (e) {\n this.logger.error('Update operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async delete(object: string, options?: DataEngineDeleteOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Delete operation starting', { object });\n const driver = this.getDriver(object);\n\n // Extract ID logic similar to update\n let id: any = undefined;\n if (options?.filter) {\n if (typeof options.filter === 'string') id = options.filter;\n else if (options.filter.id) id = options.filter.id;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'delete',\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeDelete',\n input: { id, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeDelete', hookContext);\n\n try {\n let result;\n if (hookContext.input.id) {\n result = await driver.delete(object, hookContext.input.id as string, hookContext.input.options as any);\n } else if (options?.multi && driver.deleteMany) {\n const ast = this.toQueryAST(object, { filter: options.filter });\n result = await driver.deleteMany(object, ast, hookContext.input.options as any);\n } else {\n throw new Error('Delete requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterDelete';\n hookContext.result = result;\n await this.triggerHooks('afterDelete', hookContext);\n return hookContext.result;\n } catch (e) {\n this.logger.error('Delete operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async count(object: string, query?: DataEngineCountOptions): Promise<number> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'count',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n if (driver.count) {\n const ast = this.toQueryAST(object, { filter: query?.filter });\n return driver.count(object, ast);\n }\n // Fallback to find().length\n const res = await this.find(object, { filter: query?.filter, select: ['id'] });\n return res.length;\n });\n\n return opCtx.result as number;\n }\n\n async aggregate(object: string, query: DataEngineAggregateOptions): Promise<any[]> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n this.logger.debug(`Aggregate on ${object} using ${driver.name}`, query);\n\n const opCtx: OperationContext = {\n object,\n operation: 'aggregate',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const ast: QueryAST = {\n object,\n where: query.filter,\n groupBy: query.groupBy,\n aggregations: query.aggregations?.map(agg => ({\n function: agg.method,\n field: agg.field,\n alias: agg.alias || `${agg.method}_${agg.field || 'all'}`,\n })),\n };\n\n return driver.find(object, ast);\n });\n\n return opCtx.result as any[];\n }\n \n async execute(command: any, options?: Record<string, any>): Promise<any> {\n // Direct pass-through implies we know which driver to use?\n // Usually execute is tied to a specific object context OR we need a way to select driver.\n // If command has 'object', we use that.\n if (options?.object) {\n const driver = this.getDriver(options.object);\n if (driver.execute) {\n return driver.execute(command, undefined, options);\n }\n }\n throw new Error('Execute requires options.object to select driver');\n }\n\n // ============================================\n // Compatibility / Convenience API\n // ============================================\n // These methods provide a higher-level API matching the @objectql/core\n // ObjectQL interface, enabling painless migration from the legacy layer.\n\n /**\n * Register a single object definition.\n * \n * Proxies to SchemaRegistry.registerObject() with sensible defaults.\n * Fields without a `name` property are auto-assigned from their key.\n */\n registerObject(\n schema: ServiceObject,\n packageId: string = '__runtime__',\n namespace?: string\n ): string {\n // Auto-assign field names from keys\n if (schema.fields) {\n for (const [key, field] of Object.entries(schema.fields)) {\n if (field && typeof field === 'object' && !('name' in field)) {\n (field as any).name = key;\n }\n }\n }\n return SchemaRegistry.registerObject(schema, packageId, namespace);\n }\n\n /**\n * Unregister a single object by name.\n */\n unregisterObject(name: string, packageId?: string): void {\n if (packageId) {\n SchemaRegistry.unregisterObjectsByPackage(packageId);\n } else {\n // Remove from generic metadata as fallback\n SchemaRegistry.unregisterItem('object', name);\n }\n }\n\n /**\n * Get an object definition by name.\n * Alias for getSchema() — matches @objectql/core API.\n */\n getObject(name: string): ServiceObject | undefined {\n return this.getSchema(name);\n }\n\n /**\n * Get all registered object configs as a name→config map.\n * Matches @objectql/core getConfigs() API.\n */\n getConfigs(): Record<string, ServiceObject> {\n const result: Record<string, ServiceObject> = {};\n const objects = SchemaRegistry.getAllObjects();\n for (const obj of objects) {\n if (obj.name) {\n result[obj.name] = obj;\n }\n }\n return result;\n }\n\n /**\n * Get a registered driver by datasource name.\n * \n * Unlike the private getDriver() (which resolves by object name),\n * this method directly looks up a driver by its registered name.\n */\n getDriverByName(name: string): DriverInterface | undefined {\n return this.drivers.get(name);\n }\n\n /**\n * Get the driver responsible for the given object.\n *\n * Resolves datasource binding from the object's schema definition,\n * falling back to the default driver. This is a public version of\n * the internal getDriver() used by CRUD operations.\n *\n * @param objectName - FQN or short name of the registered object.\n * @returns The resolved DriverInterface, or undefined if no driver is available.\n */\n getDriverForObject(objectName: string): DriverInterface | undefined {\n try {\n return this.getDriver(objectName);\n } catch {\n return undefined;\n }\n }\n\n /**\n * Get a registered driver by datasource name.\n * Alias matching @objectql/core datasource() API.\n * \n * @throws Error if the datasource is not found\n */\n datasource(name: string): DriverInterface {\n const driver = this.drivers.get(name);\n if (!driver) {\n throw new Error(`[ObjectQL] Datasource '${name}' not found`);\n }\n return driver;\n }\n\n /**\n * Register a hook handler.\n * Convenience alias for registerHook() matching @objectql/core on() API.\n * \n * Usage:\n * ql.on('beforeInsert', 'user', async (ctx) => { ... });\n */\n on(\n event: string,\n objectName: string,\n handler: (ctx: HookContext) => Promise<void> | void,\n packageId?: string\n ): void {\n this.registerHook(event, handler, { object: objectName, packageId });\n }\n\n /**\n * Remove all hooks, actions, and objects contributed by a package.\n */\n removePackage(packageId: string): void {\n // Remove hooks\n for (const [key, handlers] of this.hooks.entries()) {\n const filtered = handlers.filter(h => h.packageId !== packageId);\n if (filtered.length !== handlers.length) {\n this.hooks.set(key, filtered);\n }\n }\n // Remove actions\n this.removeActionsByPackage(packageId);\n // Remove objects\n SchemaRegistry.unregisterObjectsByPackage(packageId, true);\n }\n\n /**\n * Gracefully shut down the engine, disconnecting all drivers.\n * Alias for destroy() — matches @objectql/core close() API.\n */\n async close(): Promise<void> {\n return this.destroy();\n }\n\n /**\n * Create a scoped execution context bound to this engine.\n * \n * Usage:\n * const ctx = engine.createContext({ userId: '...', tenantId: '...' });\n * const users = ctx.object('user');\n * await users.find({ filter: { status: 'active' } });\n */\n createContext(ctx: Partial<ExecutionContext>): ScopedContext {\n return new ScopedContext(\n ExecutionContextSchema.parse(ctx),\n this\n );\n }\n\n /**\n * Static factory: create a fully configured ObjectQL instance.\n * \n * Matches @objectql/core's `new ObjectQL(config)` pattern but also\n * registers drivers and objects, then calls init().\n * \n * Usage:\n * const ql = await ObjectQL.create({\n * datasources: { default: myDriver },\n * objects: { user: { name: 'user', fields: { ... } } }\n * });\n */\n static async create(config: {\n datasources?: Record<string, DriverInterface>;\n objects?: Record<string, ServiceObject>;\n hooks?: Array<{ event: string; object: string; handler: (ctx: HookContext) => Promise<void> | void }>;\n }): Promise<ObjectQL> {\n const ql = new ObjectQL();\n\n // Register drivers\n if (config.datasources) {\n for (const [name, driver] of Object.entries(config.datasources)) {\n // Set driver name if not already set\n if (!driver.name) {\n (driver as any).name = name;\n }\n ql.registerDriver(driver, name === 'default');\n }\n }\n\n // Register objects\n if (config.objects) {\n for (const [_key, schema] of Object.entries(config.objects)) {\n ql.registerObject(schema);\n }\n }\n\n // Register hooks\n if (config.hooks) {\n for (const hook of config.hooks) {\n ql.on(hook.event, hook.object, hook.handler);\n }\n }\n\n // Initialize (connect drivers)\n await ql.init();\n\n return ql;\n }\n}\n\n/**\n * Repository scoped to a single object, bound to an execution context.\n *\n * Provides both IDataEngine-style methods (find, insert, update, delete)\n * and convenience aliases (create, updateById, deleteById) matching\n * the @objectql/core ObjectRepository API.\n */\nexport class ObjectRepository {\n constructor(\n private objectName: string,\n private context: ExecutionContext,\n private engine: IDataEngine & { executeAction?: (o: string, a: string, c: any) => Promise<any> }\n ) {}\n\n async find(query: any = {}): Promise<any[]> {\n return this.engine.find(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async findOne(query: any = {}): Promise<any> {\n return this.engine.findOne(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async insert(data: any): Promise<any> {\n return this.engine.insert(this.objectName, data, {\n context: this.context,\n });\n }\n\n /** Alias for insert() — matches @objectql/core convention */\n async create(data: any): Promise<any> {\n return this.insert(data);\n }\n\n async update(data: any, options: any = {}): Promise<any> {\n return this.engine.update(this.objectName, data, {\n ...options,\n context: this.context,\n });\n }\n\n /** Update a single record by ID */\n async updateById(id: string | number, data: any): Promise<any> {\n return this.engine.update(this.objectName, { ...data, id: id }, {\n filter: { id: id },\n context: this.context,\n });\n }\n\n async delete(options: any = {}): Promise<any> {\n return this.engine.delete(this.objectName, {\n ...options,\n context: this.context,\n });\n }\n\n /** Delete a single record by ID */\n async deleteById(id: string | number): Promise<any> {\n return this.engine.delete(this.objectName, {\n filter: { id: id },\n context: this.context,\n });\n }\n\n async count(query: any = {}): Promise<number> {\n return this.engine.count(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Aggregate query */\n async aggregate(query: any = {}): Promise<any[]> {\n return this.engine.aggregate(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Execute a named action registered on this object */\n async execute(actionName: string, params?: any): Promise<any> {\n if (this.engine.executeAction) {\n return this.engine.executeAction(this.objectName, actionName, {\n ...params,\n userId: this.context.userId,\n tenantId: this.context.tenantId,\n roles: this.context.roles,\n });\n }\n throw new Error(`Actions not supported by engine`);\n }\n}\n\n/**\n * Scoped execution context with object() accessor.\n * \n * Provides identity (userId, tenantId/spaceId, roles),\n * repository access via object(), privilege escalation via sudo(),\n * and transactional execution via transaction().\n */\nexport class ScopedContext {\n constructor(\n private executionContext: ExecutionContext,\n private engine: IDataEngine\n ) {}\n\n /** Get a repository scoped to this context */\n object(name: string): ObjectRepository {\n return new ObjectRepository(name, this.executionContext, this.engine as any);\n }\n\n /** Create an elevated (system) context */\n sudo(): ScopedContext {\n return new ScopedContext(\n { ...this.executionContext, isSystem: true },\n this.engine\n );\n }\n\n /**\n * Execute a callback within a database transaction.\n *\n * The callback receives a new ScopedContext whose operations\n * share the same transaction handle. If the callback throws,\n * the transaction is rolled back; otherwise it is committed.\n *\n * Falls back to non-transactional execution if the driver\n * does not support transactions.\n */\n async transaction(callback: (trxCtx: ScopedContext) => Promise<any>): Promise<any> {\n const engine = this.engine as any;\n\n // Find the default driver for transaction support\n const driver = engine.defaultDriver\n ? engine.drivers?.get(engine.defaultDriver)\n : undefined;\n\n if (!driver?.beginTransaction) {\n // No transaction support — execute directly\n return callback(this);\n }\n\n const trx = await driver.beginTransaction();\n const trxCtx = new ScopedContext(\n { ...this.executionContext, transaction: trx },\n this.engine\n );\n\n try {\n const result = await callback(trxCtx);\n if (driver.commit) await driver.commit(trx);\n else if (driver.commitTransaction) await driver.commitTransaction(trx);\n return result;\n } catch (error) {\n if (driver.rollback) await driver.rollback(trx);\n else if (driver.rollbackTransaction) await driver.rollbackTransaction(trx);\n throw error;\n }\n }\n\n get userId() { return this.executionContext.userId; }\n get tenantId() { return this.executionContext.tenantId; }\n /** Alias for tenantId — matches ObjectQLContext.spaceId convention */\n get spaceId() { return this.executionContext.tenantId; }\n get roles() { return this.executionContext.roles; }\n get isSystem() { return this.executionContext.isSystem; }\n\n /** Internal: expose the transaction handle for driver-level access */\n get transactionHandle() { return this.executionContext.transaction; }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { SchemaRegistry } from './registry.js';\n\n/**\n * MetadataFacade\n * \n * Provides a clean, injectable interface over SchemaRegistry.\n * Registered as the 'metadata' kernel service to eliminate\n * downstream packages needing to manually wrap SchemaRegistry.\n * \n * Implements the async IMetadataService interface.\n * Internally delegates to SchemaRegistry (in-memory) with Promise wrappers.\n */\nexport class MetadataFacade {\n /**\n * Register a metadata item\n */\n async register(type: string, name: string, data: any): Promise<void> {\n const definition = typeof data === 'object' && data !== null\n ? { ...data, name: data.name ?? name }\n : data;\n if (type === 'object') {\n SchemaRegistry.registerItem(type, definition, 'name' as any);\n } else {\n SchemaRegistry.registerItem(type, definition, definition.id ? 'id' as any : 'name' as any);\n }\n }\n\n /**\n * Get a metadata item by type and name\n */\n async get(type: string, name: string): Promise<any> {\n const item = SchemaRegistry.getItem(type, name) as any;\n return item?.content ?? item;\n }\n\n /**\n * Get the raw entry (with metadata wrapper)\n */\n getEntry(type: string, name: string): any {\n return SchemaRegistry.getItem(type, name);\n }\n\n /**\n * List all items of a type\n */\n async list(type: string): Promise<any[]> {\n const items = SchemaRegistry.listItems(type);\n return items.map((item: any) => item?.content ?? item);\n }\n\n /**\n * Unregister a metadata item\n */\n async unregister(type: string, name: string): Promise<void> {\n SchemaRegistry.unregisterItem(type, name);\n }\n\n /**\n * Check if a metadata item exists\n */\n async exists(type: string, name: string): Promise<boolean> {\n const item = SchemaRegistry.getItem(type, name);\n return item !== undefined && item !== null;\n }\n\n /**\n * List all names of metadata items of a given type\n */\n async listNames(type: string): Promise<string[]> {\n const items = SchemaRegistry.listItems(type);\n return items.map((item: any) => item?.name ?? item?.content?.name ?? '').filter(Boolean);\n }\n\n /**\n * Unregister all metadata from a package\n */\n async unregisterPackage(packageName: string): Promise<void> {\n SchemaRegistry.unregisterObjectsByPackage(packageName);\n }\n\n /**\n * Convenience: get object definition\n */\n async getObject(name: string): Promise<any> {\n return SchemaRegistry.getObject(name);\n }\n\n /**\n * Convenience: list all objects\n */\n async listObjects(): Promise<any[]> {\n return SchemaRegistry.getAllObjects();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectQL } from './engine.js';\nimport { MetadataFacade } from './metadata-facade.js';\nimport { ObjectStackProtocolImplementation } from './protocol.js';\nimport { Plugin, PluginContext } from '@objectstack/core';\n\nexport type { Plugin, PluginContext };\n\nexport class ObjectQLPlugin implements Plugin {\n name = 'com.objectstack.engine.objectql';\n type = 'objectql';\n version = '1.0.0';\n \n private ql: ObjectQL | undefined;\n private hostContext?: Record<string, any>;\n\n constructor(ql?: ObjectQL, hostContext?: Record<string, any>) {\n if (ql) {\n this.ql = ql;\n } else {\n this.hostContext = hostContext;\n // Lazily created in init\n }\n }\n\n init = async (ctx: PluginContext) => {\n if (!this.ql) {\n // Pass kernel logger to engine to avoid creating a separate pino instance\n const hostCtx = { ...this.hostContext, logger: ctx.logger };\n this.ql = new ObjectQL(hostCtx);\n }\n \n // Register as provider for Core Kernel Services\n ctx.registerService('objectql', this.ql);\n \n // Register MetadataFacade as metadata service (unless external service exists)\n let hasMetadata = false;\n let metadataProvider = 'objectql';\n try {\n if (ctx.getService('metadata')) {\n hasMetadata = true;\n metadataProvider = 'external';\n }\n } catch (e: any) {\n // Ignore errors during check (e.g. \"Service is async\")\n }\n\n if (!hasMetadata) {\n try {\n const metadataFacade = new MetadataFacade();\n ctx.registerService('metadata', metadataFacade);\n ctx.logger.info('MetadataFacade registered as metadata service', {\n mode: 'in-memory',\n features: ['registry', 'fast-lookup']\n });\n } catch (e: any) {\n // Ignore if already registered (race condition or async mis-detection)\n if (!e.message?.includes('already registered')) {\n throw e;\n }\n }\n } else {\n ctx.logger.info('External metadata service detected', {\n provider: metadataProvider,\n mode: 'will-sync-in-start-phase'\n });\n }\n \n ctx.registerService('data', this.ql); // ObjectQL implements IDataEngine\n \n ctx.logger.info('ObjectQL engine registered', { \n services: ['objectql', 'data'],\n metadataProvider: metadataProvider\n });\n\n // Register Protocol Implementation\n const protocolShim = new ObjectStackProtocolImplementation(\n this.ql, \n () => ctx.getServices ? ctx.getServices() : new Map()\n );\n\n ctx.registerService('protocol', protocolShim);\n ctx.logger.info('Protocol service registered');\n }\n\n start = async (ctx: PluginContext) => {\n ctx.logger.info('ObjectQL engine starting...');\n \n // Check if we should load from external metadata service\n try {\n const metadataService = ctx.getService('metadata') as any;\n // Only sync if metadata service is external (not our own MetadataFacade)\n if (metadataService && !(metadataService instanceof MetadataFacade) && this.ql) {\n await this.loadMetadataFromService(metadataService, ctx);\n }\n } catch (e: any) {\n // No external metadata service or error accessing it\n ctx.logger.debug('No external metadata service to sync from');\n }\n \n // Discover features from Kernel Services\n if (ctx.getServices && this.ql) {\n const services = ctx.getServices();\n for (const [name, service] of services.entries()) {\n if (name.startsWith('driver.')) {\n // Register Driver\n this.ql.registerDriver(service);\n ctx.logger.debug('Discovered and registered driver service', { serviceName: name });\n }\n if (name.startsWith('app.')) {\n // Register App\n this.ql.registerApp(service); // service is Manifest\n ctx.logger.debug('Discovered and registered app service', { serviceName: name });\n }\n }\n }\n\n // Initialize drivers (calls driver.connect() which sets up persistence)\n await this.ql?.init();\n\n // Sync all registered object schemas to database\n // This ensures tables/collections are created or updated for every\n // object registered by plugins (e.g., sys_user from plugin-auth).\n await this.syncRegisteredSchemas(ctx);\n\n // Register built-in audit hooks\n this.registerAuditHooks(ctx);\n\n // Register tenant isolation middleware\n this.registerTenantMiddleware(ctx);\n \n ctx.logger.info('ObjectQL engine started', {\n driversRegistered: this.ql?.['drivers']?.size || 0,\n objectsRegistered: this.ql?.registry?.getAllObjects?.()?.length || 0\n });\n }\n\n /**\n * Register built-in audit hooks for auto-stamping created_by/updated_by\n * and fetching previousData for update/delete operations.\n */\n private registerAuditHooks(ctx: PluginContext) {\n if (!this.ql) return;\n\n // Auto-stamp created_by/updated_by on insert\n this.ql.registerHook('beforeInsert', async (hookCtx) => {\n if (hookCtx.session?.userId && hookCtx.input?.data) {\n const data = hookCtx.input.data as Record<string, any>;\n if (typeof data === 'object' && data !== null) {\n data.created_by = data.created_by ?? hookCtx.session.userId;\n data.updated_by = hookCtx.session.userId;\n data.created_at = data.created_at ?? new Date().toISOString();\n data.updated_at = new Date().toISOString();\n if (hookCtx.session.tenantId) {\n data.tenant_id = data.tenant_id ?? hookCtx.session.tenantId;\n }\n }\n }\n }, { object: '*', priority: 10 });\n\n // Auto-stamp updated_by on update\n this.ql.registerHook('beforeUpdate', async (hookCtx) => {\n if (hookCtx.session?.userId && hookCtx.input?.data) {\n const data = hookCtx.input.data as Record<string, any>;\n if (typeof data === 'object' && data !== null) {\n data.updated_by = hookCtx.session.userId;\n data.updated_at = new Date().toISOString();\n }\n }\n }, { object: '*', priority: 10 });\n\n // Auto-fetch previousData for update hooks\n this.ql.registerHook('beforeUpdate', async (hookCtx) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n filter: { id: hookCtx.input.id }\n });\n if (existing) {\n hookCtx.previous = existing;\n }\n } catch (_e) {\n // Non-fatal: some objects may not support findOne\n }\n }\n }, { object: '*', priority: 5 });\n\n // Auto-fetch previousData for delete hooks\n this.ql.registerHook('beforeDelete', async (hookCtx) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n filter: { id: hookCtx.input.id }\n });\n if (existing) {\n hookCtx.previous = existing;\n }\n } catch (_e) {\n // Non-fatal\n }\n }\n }, { object: '*', priority: 5 });\n\n ctx.logger.debug('Audit hooks registered (created_by/updated_by, previousData)');\n }\n\n /**\n * Register tenant isolation middleware that auto-injects tenant_id filter\n * for multi-tenant operations.\n */\n private registerTenantMiddleware(ctx: PluginContext) {\n if (!this.ql) return;\n\n this.ql.registerMiddleware(async (opCtx, next) => {\n // Only apply to operations with tenantId that are not system-level\n if (!opCtx.context?.tenantId || opCtx.context?.isSystem) {\n return next();\n }\n\n // Read operations: inject tenant_id filter into AST\n if (['find', 'findOne', 'count', 'aggregate'].includes(opCtx.operation)) {\n if (opCtx.ast) {\n const tenantFilter = { tenant_id: opCtx.context.tenantId };\n if (opCtx.ast.where) {\n opCtx.ast.where = { $and: [opCtx.ast.where, tenantFilter] };\n } else {\n opCtx.ast.where = tenantFilter;\n }\n }\n }\n\n await next();\n });\n\n ctx.logger.debug('Tenant isolation middleware registered');\n }\n\n /**\n * Synchronize all registered object schemas to the database.\n *\n * Iterates every object in the SchemaRegistry and calls the\n * responsible driver's `syncSchema()` for each one. This is\n * idempotent — drivers must tolerate repeated calls without\n * duplicating tables or erroring out.\n *\n * Drivers that do not implement `syncSchema` are silently skipped.\n */\n private async syncRegisteredSchemas(ctx: PluginContext) {\n if (!this.ql) return;\n\n const allObjects = this.ql.registry?.getAllObjects?.() ?? [];\n if (allObjects.length === 0) return;\n\n let synced = 0;\n let skipped = 0;\n\n for (const obj of allObjects) {\n const driver = this.ql.getDriverForObject(obj.name);\n if (!driver) {\n ctx.logger.debug('No driver available for object, skipping schema sync', {\n object: obj.name,\n });\n skipped++;\n continue;\n }\n\n if (typeof driver.syncSchema !== 'function') {\n ctx.logger.debug('Driver does not support syncSchema, skipping', {\n object: obj.name,\n driver: driver.name,\n });\n skipped++;\n continue;\n }\n\n // Use the physical table name (e.g., 'sys_user') for DDL operations\n // instead of the FQN (e.g., 'sys__user'). ObjectSchema.create()\n // auto-derives tableName as {namespace}_{name}.\n const tableName = obj.tableName || obj.name;\n\n try {\n await driver.syncSchema(tableName, obj);\n synced++;\n } catch (e: unknown) {\n ctx.logger.warn('Failed to sync schema for object', {\n object: obj.name,\n tableName,\n driver: driver.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n if (synced > 0 || skipped > 0) {\n ctx.logger.info('Schema sync complete', { synced, skipped, total: allObjects.length });\n }\n }\n\n /**\n * Load metadata from external metadata service into ObjectQL registry\n * This enables ObjectQL to use file-based or remote metadata\n */\n private async loadMetadataFromService(metadataService: any, ctx: PluginContext) {\n ctx.logger.info('Syncing metadata from external service into ObjectQL registry...');\n \n // Metadata types to sync\n const metadataTypes = ['object', 'view', 'app', 'flow', 'workflow', 'function'];\n let totalLoaded = 0;\n \n for (const type of metadataTypes) {\n try {\n // Check if service has loadMany method\n if (typeof metadataService.loadMany === 'function') {\n const items = await metadataService.loadMany(type);\n \n if (items && items.length > 0) {\n items.forEach((item: any) => {\n // Determine key field (usually 'name' or 'id')\n const keyField = item.id ? 'id' : 'name';\n \n // For objects, use the ownership-aware registration\n if (type === 'object' && this.ql) {\n // Objects are registered differently (ownership model)\n // Skip for now - handled by app registration\n return;\n }\n \n // Register other types in the registry\n if (this.ql?.registry?.registerItem) {\n this.ql.registry.registerItem(type, item, keyField);\n }\n });\n \n totalLoaded += items.length;\n ctx.logger.info(`Synced ${items.length} ${type}(s) from metadata service`);\n }\n }\n } catch (e: any) {\n // Type might not exist in metadata service - that's ok\n ctx.logger.debug(`No ${type} metadata found or error loading`, { \n error: e.message \n });\n }\n }\n \n if (totalLoaded > 0) {\n ctx.logger.info(`Metadata sync complete: ${totalLoaded} items loaded into ObjectQL registry`);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectKernel } from '@objectstack/core';\nimport { ObjectQLPlugin } from './plugin.js';\nimport type { Plugin } from '@objectstack/core';\n\n/**\n * Options for creating an ObjectQL Kernel.\n */\nexport interface ObjectQLKernelOptions {\n /**\n * Additional plugins to register with the kernel.\n */\n plugins?: Plugin[];\n}\n\n/**\n * Convenience factory for creating an ObjectQL-ready kernel.\n *\n * Creates an ObjectKernel pre-configured with the ObjectQLPlugin\n * (data engine, schema registry, protocol implementation) plus any\n * additional plugins provided.\n *\n * @example\n * ```typescript\n * import { createObjectQLKernel } from '@objectstack/objectql';\n *\n * const kernel = createObjectQLKernel({\n * plugins: [myDriverPlugin, myAuthPlugin],\n * });\n * await kernel.bootstrap();\n * ```\n */\nexport async function createObjectQLKernel(options: ObjectQLKernelOptions = {}): Promise<ObjectKernel> {\n const kernel = new ObjectKernel();\n\n // Register the core ObjectQLPlugin first\n await kernel.use(new ObjectQLPlugin());\n\n // Register any additional plugins\n if (options.plugins) {\n for (const plugin of options.plugins) {\n await kernel.use(plugin);\n }\n }\n\n return kernel;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ServiceObject } from '@objectstack/spec/data';\n\n// ── Introspection Types ──────────────────────────────────────────────────────\n\n/**\n * Column metadata from database introspection.\n */\nexport interface IntrospectedColumn {\n /** Column name */\n name: string;\n /** Native database type (e.g., 'varchar', 'integer', 'timestamp') */\n type: string;\n /** Whether the column is nullable */\n nullable: boolean;\n /** Default value if any */\n defaultValue?: unknown;\n /** Whether this is a primary key */\n isPrimary?: boolean;\n /** Whether this column has a unique constraint */\n isUnique?: boolean;\n /** Maximum length for string types */\n maxLength?: number;\n}\n\n/**\n * Foreign key relationship metadata.\n */\nexport interface IntrospectedForeignKey {\n /** Column name in the source table */\n columnName: string;\n /** Referenced table name */\n referencedTable: string;\n /** Referenced column name */\n referencedColumn: string;\n /** Constraint name */\n constraintName?: string;\n}\n\n/**\n * Table metadata from database introspection.\n */\nexport interface IntrospectedTable {\n /** Table name */\n name: string;\n /** List of columns */\n columns: IntrospectedColumn[];\n /** List of foreign key relationships */\n foreignKeys: IntrospectedForeignKey[];\n /** Primary key columns */\n primaryKeys: string[];\n}\n\n/**\n * Complete database schema introspection result.\n */\nexport interface IntrospectedSchema {\n /** Map of table name to table metadata */\n tables: Record<string, IntrospectedTable>;\n}\n\n// ── Utility Functions ────────────────────────────────────────────────────────\n\n/**\n * Convert a snake_case or plain string to Title Case.\n *\n * @example\n * toTitleCase('first_name') // => 'First Name'\n * toTitleCase('project_task') // => 'Project Task'\n */\nexport function toTitleCase(str: string): string {\n return str\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n/**\n * Map a native database column type to an ObjectStack FieldType.\n */\nfunction mapDatabaseTypeToFieldType(\n dbType: string\n): 'text' | 'textarea' | 'number' | 'boolean' | 'datetime' | 'date' | 'time' | 'json' {\n const type = dbType.toLowerCase();\n\n // Text types\n if (type.includes('char') || type.includes('varchar') || type.includes('text')) {\n if (type.includes('text')) return 'textarea';\n return 'text';\n }\n\n // Numeric types\n if (\n type.includes('int') || type === 'integer' || type === 'bigint' || type === 'smallint'\n ) {\n return 'number';\n }\n if (\n type.includes('float') || type.includes('double') || type.includes('decimal') ||\n type.includes('numeric') || type === 'real'\n ) {\n return 'number';\n }\n\n // Boolean\n if (type.includes('bool')) {\n return 'boolean';\n }\n\n // Date / Time types\n if (type.includes('timestamp') || type === 'datetime') {\n return 'datetime';\n }\n if (type === 'date') {\n return 'date';\n }\n if (type === 'time') {\n return 'time';\n }\n\n // JSON types\n if (type === 'json' || type === 'jsonb') {\n return 'json';\n }\n\n // Default to text\n return 'text';\n}\n\n/**\n * Convert an introspected database schema to ObjectStack object definitions.\n *\n * This allows using existing database tables without manually defining metadata.\n *\n * @param introspectedSchema - The schema returned from driver.introspectSchema()\n * @param options - Optional filtering / conversion settings\n * @returns Array of ServiceObject definitions that can be registered with ObjectQL\n *\n * @example\n * ```typescript\n * const schema = await driver.introspectSchema();\n * const objects = convertIntrospectedSchemaToObjects(schema);\n * for (const obj of objects) {\n * engine.registerObject(obj);\n * }\n * ```\n */\nexport function convertIntrospectedSchemaToObjects(\n introspectedSchema: IntrospectedSchema,\n options?: {\n /** Tables to exclude from conversion */\n excludeTables?: string[];\n /** Tables to include (if specified, only these will be converted) */\n includeTables?: string[];\n /** Whether to skip system columns like id, created_at, updated_at (default: true) */\n skipSystemColumns?: boolean;\n }\n): ServiceObject[] {\n const objects: ServiceObject[] = [];\n const excludeTables = options?.excludeTables || [];\n const includeTables = options?.includeTables;\n const skipSystemColumns = options?.skipSystemColumns !== false;\n\n for (const [tableName, table] of Object.entries(introspectedSchema.tables)) {\n if (excludeTables.includes(tableName)) continue;\n if (includeTables && !includeTables.includes(tableName)) continue;\n\n const fields: Record<string, any> = {};\n\n for (const column of table.columns) {\n // Skip system columns if requested\n if (skipSystemColumns && ['id', 'created_at', 'updated_at'].includes(column.name)) {\n continue;\n }\n\n // Check for foreign key → lookup field\n const foreignKey = table.foreignKeys.find((fk) => fk.columnName === column.name);\n\n if (foreignKey) {\n fields[column.name] = {\n name: column.name,\n type: 'lookup' as const,\n reference: foreignKey.referencedTable,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n } else {\n const fieldType = mapDatabaseTypeToFieldType(column.type);\n\n const field: Record<string, any> = {\n name: column.name,\n type: fieldType,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n\n if (column.isUnique) {\n field.unique = true;\n }\n if (column.maxLength && (fieldType === 'text' || fieldType === 'textarea')) {\n field.maxLength = column.maxLength;\n }\n if (column.defaultValue != null) {\n field.defaultValue = column.defaultValue;\n }\n\n fields[column.name] = field;\n }\n }\n\n objects.push({\n name: tableName,\n label: toTitleCase(tableName),\n fields,\n } as ServiceObject);\n }\n\n return objects;\n}\n"],"mappings":";AAEA,SAAwB,oBAAqC;AAC7D,SAA8B,gBAAkC,8BAA8B;AAC9F,SAAS,iBAAiB;AAMnB,IAAM,sBAAsB,oBAAI,IAAI,CAAC,QAAQ,QAAQ,CAAC;AAKtD,IAAM,yBAAyB;AAC/B,IAAM,4BAA4B;AA0BlC,SAAS,WAAW,WAA+B,WAA2B;AACnF,MAAI,CAAC,aAAa,oBAAoB,IAAI,SAAS,GAAG;AACpD,WAAO;AAAA,EACT;AACA,SAAO,GAAG,SAAS,KAAK,SAAS;AACnC;AAQO,SAAS,SAAS,KAAmE;AAC1F,QAAM,MAAM,IAAI,QAAQ,IAAI;AAC5B,MAAI,QAAQ,IAAI;AACd,WAAO,EAAE,WAAW,QAAW,WAAW,IAAI;AAAA,EAChD;AACA,SAAO;AAAA,IACL,WAAW,IAAI,MAAM,GAAG,GAAG;AAAA,IAC3B,WAAW,IAAI,MAAM,MAAM,CAAC;AAAA,EAC9B;AACF;AAMA,SAAS,uBAAuB,MAAqB,WAAkD;AACrG,QAAM,SAAS,EAAE,GAAG,KAAK;AAGzB,MAAI,UAAU,QAAQ;AACpB,WAAO,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAG,UAAU,OAAO;AAAA,EACxD;AAGA,MAAI,UAAU,aAAa;AACzB,WAAO,cAAc,CAAC,GAAI,KAAK,eAAe,CAAC,GAAI,GAAG,UAAU,WAAW;AAAA,EAC7E;AAGA,MAAI,UAAU,SAAS;AACrB,WAAO,UAAU,CAAC,GAAI,KAAK,WAAW,CAAC,GAAI,GAAG,UAAU,OAAO;AAAA,EACjE;AAGA,MAAI,UAAU,UAAU,OAAW,QAAO,QAAQ,UAAU;AAC5D,MAAI,UAAU,gBAAgB,OAAW,QAAO,cAAc,UAAU;AACxE,MAAI,UAAU,gBAAgB,OAAW,QAAO,cAAc,UAAU;AAExE,SAAO;AACT;AA0BO,IAAM,iBAAN,MAAqB;AAAA,EAQ1B,WAAW,WAA6B;AAAE,WAAO,KAAK;AAAA,EAAW;AAAA,EACjE,WAAW,SAAS,OAAyB;AAAE,SAAK,YAAY;AAAA,EAAO;AAAA,EAEvE,OAAe,IAAI,KAAmB;AACpC,QAAI,KAAK,cAAc,YAAY,KAAK,cAAc,WAAW,KAAK,cAAc,OAAQ;AAC5F,YAAQ,IAAI,GAAG;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,OAAO,kBAAkB,WAAmB,WAAyB;AACnE,QAAI,CAAC,UAAW;AAEhB,UAAM,WAAW,KAAK,kBAAkB,IAAI,SAAS;AACrD,QAAI,YAAY,aAAa,WAAW;AACtC,YAAM,IAAI;AAAA,QACR,cAAc,SAAS,uCAAuC,QAAQ,eAC1D,SAAS;AAAA,MACvB;AAAA,IACF;AAEA,SAAK,kBAAkB,IAAI,WAAW,SAAS;AAC/C,SAAK,IAAI,oCAAoC,SAAS,WAAM,SAAS,EAAE;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,oBAAoB,WAAmB,WAAyB;AACrE,UAAM,WAAW,KAAK,kBAAkB,IAAI,SAAS;AACrD,QAAI,aAAa,WAAW;AAC1B,WAAK,kBAAkB,OAAO,SAAS;AACvC,WAAK,IAAI,sCAAsC,SAAS,EAAE;AAAA,IAC5D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,kBAAkB,WAAuC;AAC9D,WAAO,KAAK,kBAAkB,IAAI,SAAS;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,OAAO,eACL,QACA,WACA,WACA,YAA6B,OAC7B,WAAmB,cAAc,QAAQ,yBAAyB,2BAC1D;AACR,UAAM,YAAY,OAAO;AACzB,UAAM,MAAM,WAAW,WAAW,SAAS;AAG3C,QAAI,WAAW;AACb,WAAK,kBAAkB,WAAW,SAAS;AAAA,IAC7C;AAGA,QAAI,eAAe,KAAK,mBAAmB,IAAI,GAAG;AAClD,QAAI,CAAC,cAAc;AACjB,qBAAe,CAAC;AAChB,WAAK,mBAAmB,IAAI,KAAK,YAAY;AAAA,IAC/C;AAGA,QAAI,cAAc,OAAO;AACvB,YAAM,gBAAgB,aAAa,KAAK,OAAK,EAAE,cAAc,KAAK;AAClE,UAAI,iBAAiB,cAAc,cAAc,WAAW;AAC1D,cAAM,IAAI;AAAA,UACR,WAAW,GAAG,kCAAkC,cAAc,SAAS,eAC3D,SAAS;AAAA,QACvB;AAAA,MACF;AAEA,YAAM,MAAM,aAAa,UAAU,OAAK,EAAE,cAAc,aAAa,EAAE,cAAc,KAAK;AAC1F,UAAI,QAAQ,IAAI;AACd,qBAAa,OAAO,KAAK,CAAC;AAC1B,gBAAQ,KAAK,2CAA2C,GAAG,SAAS,SAAS,EAAE;AAAA,MACjF;AAAA,IACF,OAAO;AAEL,YAAM,MAAM,aAAa,UAAU,OAAK,EAAE,cAAc,aAAa,EAAE,cAAc,QAAQ;AAC7F,UAAI,QAAQ,IAAI;AACd,qBAAa,OAAO,KAAK,CAAC;AAAA,MAC5B;AAAA,IACF;AAGA,UAAM,cAAiC;AAAA,MACrC;AAAA,MACA,WAAW,aAAa;AAAA,MACxB;AAAA,MACA;AAAA,MACA,YAAY,EAAE,GAAG,QAAQ,MAAM,IAAI;AAAA;AAAA,IACrC;AACA,iBAAa,KAAK,WAAW;AAG7B,iBAAa,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAGnD,SAAK,kBAAkB,OAAO,GAAG;AAEjC,SAAK,IAAI,iCAAiC,GAAG,KAAK,SAAS,cAAc,QAAQ,UAAU,SAAS,EAAE;AACtG,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,cAAc,KAAwC;AAE3D,UAAM,SAAS,KAAK,kBAAkB,IAAI,GAAG;AAC7C,QAAI,OAAQ,QAAO;AAEnB,UAAM,eAAe,KAAK,mBAAmB,IAAI,GAAG;AACpD,QAAI,CAAC,gBAAgB,aAAa,WAAW,GAAG;AAC9C,aAAO;AAAA,IACT;AAGA,UAAM,eAAe,aAAa,KAAK,OAAK,EAAE,cAAc,KAAK;AACjE,QAAI,CAAC,cAAc;AACjB,cAAQ,KAAK,sBAAsB,GAAG,yCAAyC;AAC/E,aAAO;AAAA,IACT;AAGA,QAAI,SAAS,EAAE,GAAG,aAAa,WAAW;AAG1C,eAAW,WAAW,cAAc;AAClC,UAAI,QAAQ,cAAc,UAAU;AAClC,iBAAS,uBAAuB,QAAQ,QAAQ,UAAU;AAAA,MAC5D;AAAA,IACF;AAGA,SAAK,kBAAkB,IAAI,KAAK,MAAM;AACtC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAO,UAAU,MAAyC;AAExD,UAAM,SAAS,KAAK,cAAc,IAAI;AACtC,QAAI,OAAQ,QAAO;AAInB,eAAW,OAAO,KAAK,mBAAmB,KAAK,GAAG;AAChD,YAAM,EAAE,UAAU,IAAI,SAAS,GAAG;AAClC,UAAI,cAAc,MAAM;AACtB,eAAO,KAAK,cAAc,GAAG;AAAA,MAC/B;AAAA,IACF;AAIA,eAAW,OAAO,KAAK,mBAAmB,KAAK,GAAG;AAChD,YAAM,WAAW,KAAK,cAAc,GAAG;AACvC,UAAI,UAAU,cAAc,MAAM;AAChC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,cAAc,WAAqC;AACxD,UAAM,UAA2B,CAAC;AAElC,eAAW,OAAO,KAAK,mBAAmB,KAAK,GAAG;AAEhD,UAAI,WAAW;AACb,cAAM,eAAe,KAAK,mBAAmB,IAAI,GAAG;AACpD,cAAM,kBAAkB,cAAc,KAAK,OAAK,EAAE,cAAc,SAAS;AACzE,YAAI,CAAC,gBAAiB;AAAA,MACxB;AAEA,YAAM,SAAS,KAAK,cAAc,GAAG;AACrC,UAAI,QAAQ;AAEV,QAAC,OAAe,aAAa,KAAK,eAAe,GAAG,GAAG;AACvD,gBAAQ,KAAK,MAAM;AAAA,MACrB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,sBAAsB,KAAkC;AAC7D,WAAO,KAAK,mBAAmB,IAAI,GAAG,KAAK,CAAC;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,eAAe,KAA4C;AAChE,UAAM,eAAe,KAAK,mBAAmB,IAAI,GAAG;AACpD,WAAO,cAAc,KAAK,OAAK,EAAE,cAAc,KAAK;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,2BAA2B,WAAmB,QAAiB,OAAa;AACjF,eAAW,CAAC,KAAK,YAAY,KAAK,KAAK,mBAAmB,QAAQ,GAAG;AAEnE,YAAM,kBAAkB,aAAa,OAAO,OAAK,EAAE,cAAc,SAAS;AAE1E,iBAAW,WAAW,iBAAiB;AACrC,YAAI,QAAQ,cAAc,SAAS,CAAC,OAAO;AAEzC,gBAAM,iBAAiB,aAAa;AAAA,YAClC,OAAK,EAAE,cAAc,aAAa,EAAE,cAAc;AAAA,UACpD;AACA,cAAI,eAAe,SAAS,GAAG;AAC7B,kBAAM,IAAI;AAAA,cACR,6BAA6B,SAAS,cAAc,GAAG,oBACpD,eAAe,IAAI,OAAK,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;AAAA,YACpD;AAAA,UACF;AAAA,QACF;AAGA,cAAM,MAAM,aAAa,QAAQ,OAAO;AACxC,YAAI,QAAQ,IAAI;AACd,uBAAa,OAAO,KAAK,CAAC;AAC1B,eAAK,IAAI,sBAAsB,QAAQ,SAAS,oBAAoB,GAAG,SAAS,SAAS,EAAE;AAAA,QAC7F;AAAA,MACF;AAGA,UAAI,aAAa,WAAW,GAAG;AAC7B,aAAK,mBAAmB,OAAO,GAAG;AAAA,MACpC;AAGA,WAAK,kBAAkB,OAAO,GAAG;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,aAAgB,MAAc,MAAS,WAAoB,QAAmB,WAAoB;AACvG,QAAI,CAAC,KAAK,SAAS,IAAI,IAAI,GAAG;AAC5B,WAAK,SAAS,IAAI,MAAM,oBAAI,IAAI,CAAC;AAAA,IACnC;AACA,UAAM,aAAa,KAAK,SAAS,IAAI,IAAI;AACzC,UAAM,WAAW,OAAO,KAAK,QAAQ,CAAC;AAGtC,QAAI,WAAW;AACb,MAAC,KAAa,aAAa;AAAA,IAC7B;AAGA,QAAI;AACF,WAAK,SAAS,MAAM,IAAI;AAAA,IAC1B,SAAS,GAAQ;AACf,cAAQ,MAAM,oCAAoC,IAAI,IAAI,QAAQ,KAAK,EAAE,OAAO,EAAE;AAAA,IACpF;AAGA,UAAM,aAAa,YAAY,GAAG,SAAS,IAAI,QAAQ,KAAK;AAE5D,QAAI,WAAW,IAAI,UAAU,GAAG;AAC9B,cAAQ,KAAK,0BAA0B,IAAI,KAAK,UAAU,EAAE;AAAA,IAC9D;AACA,eAAW,IAAI,YAAY,IAAI;AAC/B,SAAK,IAAI,yBAAyB,IAAI,KAAK,UAAU,EAAE;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,SAAS,MAAc,MAAW;AACvC,QAAI,SAAS,UAAU;AACrB,aAAO,aAAa,MAAM,IAAI;AAAA,IAChC;AACA,QAAI,SAAS,QAAQ;AACnB,aAAO,UAAU,MAAM,IAAI;AAAA,IAC7B;AACA,QAAI,SAAS,WAAW;AACtB,aAAO,uBAAuB,MAAM,IAAI;AAAA,IAC1C;AACA,QAAI,SAAS,UAAU;AACrB,aAAO,eAAe,MAAM,IAAI;AAAA,IAClC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,eAAe,MAAc,MAAc;AAChD,UAAM,aAAa,KAAK,SAAS,IAAI,IAAI;AACzC,QAAI,CAAC,YAAY;AACf,cAAQ,KAAK,mDAAmD,IAAI,KAAK,IAAI,EAAE;AAC/E;AAAA,IACF;AACA,QAAI,WAAW,IAAI,IAAI,GAAG;AACxB,iBAAW,OAAO,IAAI;AACtB,WAAK,IAAI,2BAA2B,IAAI,KAAK,IAAI,EAAE;AACnD;AAAA,IACF;AAEA,eAAW,OAAO,WAAW,KAAK,GAAG;AACnC,UAAI,IAAI,SAAS,IAAI,IAAI,EAAE,GAAG;AAC5B,mBAAW,OAAO,GAAG;AACrB,aAAK,IAAI,2BAA2B,IAAI,KAAK,GAAG,EAAE;AAClD;AAAA,MACF;AAAA,IACF;AACA,YAAQ,KAAK,mDAAmD,IAAI,KAAK,IAAI,EAAE;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,QAAW,MAAc,MAA6B;AAE3D,QAAI,SAAS,YAAY,SAAS,WAAW;AAC3C,aAAO,KAAK,UAAU,IAAI;AAAA,IAC5B;AAEA,UAAM,aAAa,KAAK,SAAS,IAAI,IAAI;AACzC,QAAI,CAAC,WAAY,QAAO;AACxB,UAAM,SAAS,WAAW,IAAI,IAAI;AAClC,QAAI,OAAQ,QAAO;AAEnB,eAAW,CAAC,KAAK,IAAI,KAAK,YAAY;AACpC,UAAI,IAAI,SAAS,IAAI,IAAI,EAAE,EAAG,QAAO;AAAA,IACvC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,UAAa,MAAc,WAAyB;AAEzD,QAAI,SAAS,YAAY,SAAS,WAAW;AAC3C,aAAO,KAAK,cAAc,SAAS;AAAA,IACrC;AAEA,UAAM,QAAQ,MAAM,KAAK,KAAK,SAAS,IAAI,IAAI,GAAG,OAAO,KAAK,CAAC,CAAC;AAChE,QAAI,WAAW;AACb,aAAO,MAAM,OAAO,CAAC,SAAc,KAAK,eAAe,SAAS;AAAA,IAClE;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,qBAA+B;AACpC,UAAM,QAAQ,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC;AAE7C,QAAI,CAAC,MAAM,SAAS,QAAQ,KAAK,KAAK,mBAAmB,OAAO,GAAG;AACjE,YAAM,KAAK,QAAQ;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,eAAe,UAA+B,UAAkD;AACrG,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAM,MAAwB;AAAA,MAC5B;AAAA,MACA,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW;AAAA,MACX;AAAA,IACF;AAGA,QAAI,SAAS,WAAW;AACtB,WAAK,kBAAkB,SAAS,WAAW,SAAS,EAAE;AAAA,IACxD;AAEA,QAAI,CAAC,KAAK,SAAS,IAAI,SAAS,GAAG;AACjC,WAAK,SAAS,IAAI,WAAW,oBAAI,IAAI,CAAC;AAAA,IACxC;AACA,UAAM,aAAa,KAAK,SAAS,IAAI,SAAS;AAC9C,QAAI,WAAW,IAAI,SAAS,EAAE,GAAG;AAC/B,cAAQ,KAAK,mCAAmC,SAAS,EAAE,EAAE;AAAA,IAC/D;AACA,eAAW,IAAI,SAAS,IAAI,GAAG;AAC/B,SAAK,IAAI,iCAAiC,SAAS,EAAE,KAAK,SAAS,IAAI,GAAG;AAC1E,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,iBAAiB,IAAqB;AAC3C,UAAM,MAAM,KAAK,WAAW,EAAE;AAC9B,QAAI,CAAC,KAAK;AACR,cAAQ,KAAK,+CAA+C,EAAE,EAAE;AAChE,aAAO;AAAA,IACT;AAGA,QAAI,IAAI,SAAS,WAAW;AAC1B,WAAK,oBAAoB,IAAI,SAAS,WAAW,EAAE;AAAA,IACrD;AAGA,SAAK,2BAA2B,EAAE;AAGlC,UAAM,aAAa,KAAK,SAAS,IAAI,SAAS;AAC9C,QAAI,YAAY;AACd,iBAAW,OAAO,EAAE;AACpB,WAAK,IAAI,mCAAmC,EAAE,EAAE;AAChD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,WAAW,IAA0C;AAC1D,WAAO,KAAK,SAAS,IAAI,SAAS,GAAG,IAAI,EAAE;AAAA,EAC7C;AAAA,EAEA,OAAO,iBAAqC;AAC1C,WAAO,KAAK,UAA4B,SAAS;AAAA,EACnD;AAAA,EAEA,OAAO,cAAc,IAA0C;AAC7D,UAAM,MAAM,KAAK,WAAW,EAAE;AAC9B,QAAI,KAAK;AACP,UAAI,UAAU;AACd,UAAI,SAAS;AACb,UAAI,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAC7C,UAAI,aAAY,oBAAI,KAAK,GAAE,YAAY;AACvC,WAAK,IAAI,+BAA+B,EAAE,EAAE;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,eAAe,IAA0C;AAC9D,UAAM,MAAM,KAAK,WAAW,EAAE;AAC9B,QAAI,KAAK;AACP,UAAI,UAAU;AACd,UAAI,SAAS;AACb,UAAI,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAC7C,UAAI,aAAY,oBAAI,KAAK,GAAE,YAAY;AACvC,WAAK,IAAI,gCAAgC,EAAE,EAAE;AAAA,IAC/C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,YAAY,KAAU,WAAoB;AAC/C,SAAK,aAAa,QAAQ,KAAK,QAAQ,SAAS;AAAA,EAClD;AAAA,EAEA,OAAO,OAAO,MAAmB;AAC/B,WAAO,KAAK,QAAQ,QAAQ,IAAI;AAAA,EAClC;AAAA,EAEA,OAAO,aAAoB;AACzB,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,eAAe,UAA+B;AACnD,SAAK,aAAa,UAAU,UAAU,IAAI;AAAA,EAC5C;AAAA,EAEA,OAAO,gBAAuC;AAC5C,WAAO,KAAK,UAA+B,QAAQ;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,aAAa,MAAuC;AACzD,SAAK,aAAa,QAAQ,MAAM,IAAI;AAAA,EACtC;AAAA,EAEA,OAAO,cAAiD;AACtD,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,QAAc;AACnB,SAAK,mBAAmB,MAAM;AAC9B,SAAK,kBAAkB,MAAM;AAC7B,SAAK,kBAAkB,MAAM;AAC7B,SAAK,SAAS,MAAM;AACpB,SAAK,IAAI,2BAA2B;AAAA,EACtC;AACF;AAAA;AAAA;AAAA;AAAA;AA1kBa,eAMI,YAA8B;AAAA;AAAA;AAAA;AAAA;AANlC,eAqBI,qBAAqB,oBAAI,IAAiC;AAAA;AArB9D,eAwBI,oBAAoB,oBAAI,IAA2B;AAAA;AAxBvD,eA2BI,oBAAoB,oBAAI,IAAoB;AAAA;AAAA;AAAA;AAAA;AA3BhD,eAkCI,WAAW,oBAAI,IAA8B;;;AC9I9D,SAAS,gBAAgB,mBAAmB;AAS5C,SAAS,WAAW,KAAqB;AACrC,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACjC,UAAM,OAAO,IAAI,WAAW,CAAC;AAC7B,YAAS,QAAQ,KAAK,OAAQ;AAC9B,WAAO,OAAO;AAAA,EAClB;AACA,SAAO,KAAK,IAAI,IAAI,EAAE,SAAS,EAAE;AACrC;AAMA,IAAM,iBAAoE;AAAA,EACtE,MAAc,EAAE,OAAO,gBAAgB,QAAQ,cAAc;AAAA,EAC7D,YAAc,EAAE,OAAO,sBAAsB,QAAQ,oBAAoB;AAAA,EACzE,OAAc,EAAE,OAAO,iBAAiB,QAAQ,eAAe;AAAA,EAC/D,OAAc,EAAE,OAAO,iBAAiB,QAAQ,gBAAgB;AAAA,EAChE,KAAc,EAAE,OAAO,gBAAgB,QAAQ,gBAAgB;AAAA,EAC/D,IAAc,EAAE,OAAO,cAAc,QAAQ,YAAY;AAAA,EACzD,UAAc,EAAE,OAAO,oBAAoB,QAAQ,kBAAkB;AAAA,EACrE,UAAc,EAAE,OAAO,oBAAoB,QAAQ,kBAAkB;AAAA,EACrE,cAAc,EAAE,OAAO,yBAAyB,QAAQ,uBAAuB;AAAA,EAC/E,IAAc,EAAE,OAAO,cAAc,QAAQ,YAAY;AAAA,EACzD,MAAc,EAAE,OAAO,gBAAgB,QAAQ,eAAe;AAAA,EAC9D,SAAc,EAAE,OAAO,YAAY,QAAQ,iBAAiB;AAAA;AAAA,EAC5D,gBAAgB,EAAE,OAAO,mBAAmB,QAAQ,iBAAiB;AAAA,EACrE,QAAc,EAAE,OAAO,kBAAkB,QAAQ,gBAAgB;AACrE;AAEO,IAAM,oCAAN,MAAuE;AAAA,EAK1E,YAAY,QAAqB,qBAA8C,gBAAiD;AAC5H,SAAK,SAAS;AACd,SAAK,sBAAsB;AAC3B,SAAK,iBAAiB;AAAA,EAC1B;AAAA,EAEQ,qBAAmC;AACvC,UAAM,MAAM,KAAK,iBAAiB;AAClC,QAAI,CAAC,KAAK;AACN,YAAM,IAAI,MAAM,0FAA0F;AAAA,IAC9G;AACA,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,eAAe;AAEjB,UAAM,qBAAqB,KAAK,sBAAsB,KAAK,oBAAoB,IAAI,oBAAI,IAAI;AAG3F,UAAM,WAAwC;AAAA;AAAA,MAE1C,UAAW,EAAE,SAAS,MAAM,QAAQ,YAAqB,OAAO,gBAAgB,UAAU,YAAY,SAAS,8DAA8D;AAAA,MAC7K,MAAW,EAAE,SAAS,MAAM,QAAQ,aAAsB,OAAO,gBAAgB,UAAU,WAAW;AAAA,MACtG,WAAW,EAAE,SAAS,MAAM,QAAQ,aAAsB,OAAO,qBAAqB,UAAU,WAAW;AAAA,IAC/G;AAGA,eAAW,CAAC,aAAa,MAAM,KAAK,OAAO,QAAQ,cAAc,GAAG;AAChE,UAAI,mBAAmB,IAAI,WAAW,GAAG;AAErC,iBAAS,WAAW,IAAI;AAAA,UACpB,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,QACrB;AAAA,MACJ,OAAO;AAEH,iBAAS,WAAW,IAAI;AAAA,UACpB,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,SAAS,WAAW,OAAO,MAAM;AAAA,QACrC;AAAA,MACJ;AAAA,IACJ;AAGA,UAAM,oBAAqD;AAAA,MACvD,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,UAAU;AAAA,MACV,cAAc;AAAA,MACd,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,gBAAgB;AAAA,IACpB;AAEA,UAAM,iBAAqC;AAAA,MACvC,WAAW;AAAA,IACf;AAGA,eAAW,CAAC,aAAa,MAAM,KAAK,OAAO,QAAQ,cAAc,GAAG;AAChE,UAAI,mBAAmB,IAAI,WAAW,GAAG;AACrC,cAAM,WAAW,kBAAkB,WAAW;AAC9C,YAAI,UAAU;AACV,yBAAe,QAAQ,IAAI,OAAO;AAAA,QACtC;AAAA,MACJ;AAAA,IACJ;AAGA,QAAI,mBAAmB,IAAI,MAAM,GAAG;AAChC,eAAS,MAAM,IAAI;AAAA,QACf,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,UAAU;AAAA,MACd;AAAA,IACJ,OAAO;AACH,eAAS,MAAM,IAAI;AAAA,QACf,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,SAAS;AAAA,MACb;AAAA,IACJ;AAEA,UAAM,SAAoB;AAAA,MACtB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,GAAG;AAAA,IACP;AAGA,UAAM,eAAsC;AAAA,MACxC,MAAM,mBAAmB,IAAI,MAAM;AAAA,MACnC,UAAU,mBAAmB,IAAI,MAAM;AAAA,MACvC,YAAY,mBAAmB,IAAI,YAAY;AAAA,MAC/C,MAAM,mBAAmB,IAAI,KAAK;AAAA,MAClC,QAAQ,mBAAmB,IAAI,QAAQ;AAAA,MACvC,QAAQ,mBAAmB,IAAI,YAAY,KAAK,mBAAmB,IAAI,OAAO;AAAA,MAC9E,eAAe,mBAAmB,IAAI,cAAc;AAAA,IACxD;AAEA,WAAO;AAAA,MACH,SAAS;AAAA,MACT,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,eAAe;AACjB,WAAO;AAAA,MACH,OAAO,eAAe,mBAAmB;AAAA,IAC7C;AAAA,EACJ;AAAA,EAEA,MAAM,aAAa,SAA2B;AAC1C,QAAI,QAAQ,eAAe,UAAU,QAAQ,IAAI;AAEjD,QAAI,MAAM,WAAW,GAAG;AACpB,YAAM,MAAM,QAAQ,KAAK,SAAS,GAAG,IAAI,QAAQ,KAAK,MAAM,GAAG,EAAE,IAAI,QAAQ,OAAO;AACpF,cAAQ,eAAe,UAAU,GAAG;AAAA,IACxC;AACA,WAAO;AAAA,MACH,MAAM,QAAQ;AAAA,MACd;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,YAAY,SAAyC;AACvD,QAAI,OAAO,eAAe,QAAQ,QAAQ,MAAM,QAAQ,IAAI;AAE5D,QAAI,SAAS,QAAW;AACpB,YAAM,MAAM,QAAQ,KAAK,SAAS,GAAG,IAAI,QAAQ,KAAK,MAAM,GAAG,EAAE,IAAI,QAAQ,OAAO;AACpF,aAAO,eAAe,QAAQ,KAAK,QAAQ,IAAI;AAAA,IACnD;AACA,WAAO;AAAA,MACH,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,UAAU,SAAoD;AAChE,UAAM,SAAS,eAAe,UAAU,QAAQ,MAAM;AACtD,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,UAAU,QAAQ,MAAM,YAAY;AAEjE,UAAM,SAAS,OAAO,UAAU,CAAC;AACjC,UAAM,YAAY,OAAO,KAAK,MAAM;AAEpC,QAAI,QAAQ,SAAS,QAAQ;AAIzB,YAAM,iBAAiB,CAAC,QAAQ,SAAS,SAAS,WAAW,SAAS,UAAU,QAAQ,YAAY,YAAY;AAEhH,UAAI,UAAU,UAAU,OAAO,OAAK,eAAe,SAAS,CAAC,CAAC;AAG9D,UAAI,QAAQ,SAAS,GAAG;AACpB,cAAM,YAAY,UAAU,OAAO,OAAK,CAAC,QAAQ,SAAS,CAAC,KAAK,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM;AAC/F,kBAAU,CAAC,GAAG,SAAS,GAAG,UAAU,MAAM,GAAG,IAAI,QAAQ,MAAM,CAAC;AAAA,MACpE;AAKA,aAAO;AAAA,QACH,MAAM;AAAA,UACF,MAAM;AAAA,UACN,QAAQ,QAAQ;AAAA,UAChB,OAAO,OAAO,SAAS,OAAO;AAAA,UAC9B,SAAS,QAAQ,IAAI,QAAM;AAAA,YACvB,OAAO;AAAA,YACP,OAAO,OAAO,CAAC,GAAG,SAAS;AAAA,YAC3B,UAAU;AAAA,UACd,EAAE;AAAA,UACF,MAAM,OAAO,YAAY,IAAK,CAAC,EAAE,OAAO,cAAc,OAAO,OAAO,CAAC,IAAY;AAAA,UACjF,kBAAkB,QAAQ,MAAM,GAAG,CAAC;AAAA;AAAA,QACxC;AAAA,MACJ;AAAA,IACJ,OAAO;AAGF,YAAM,aAAa,UACf,OAAO,OAAK,MAAM,QAAQ,MAAM,gBAAgB,MAAM,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,EACvF,IAAI,QAAM;AAAA,QACP,OAAO;AAAA,QACP,OAAO,OAAO,CAAC,GAAG;AAAA,QAClB,UAAU,OAAO,CAAC,GAAG;AAAA,QACrB,UAAU,OAAO,CAAC,GAAG;AAAA,QACrB,MAAM,OAAO,CAAC,GAAG;AAAA;AAAA,QAEjB,SAAU,OAAO,CAAC,GAAG,SAAS,cAAc,OAAO,CAAC,GAAG,SAAS,SAAU,IAAI;AAAA,MAClF,EAAE;AAEL,aAAO;AAAA,QACJ,MAAM;AAAA,UACF,MAAM;AAAA,UACN,QAAQ,QAAQ;AAAA,UAChB,OAAO,QAAQ,OAAO,SAAS,OAAO,IAAI;AAAA,UAC1C,UAAU;AAAA,YACN;AAAA,cACI,OAAO;AAAA,cACP,SAAS;AAAA,cACT,aAAa;AAAA,cACb,WAAW;AAAA,cACX,QAAQ;AAAA,YACZ;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,SAAS,SAA0C;AACrD,UAAM,UAAe,EAAE,GAAG,QAAQ,MAAM;AAGxC,QAAI,QAAQ,OAAO,KAAM,SAAQ,MAAM,OAAO,QAAQ,GAAG;AACzD,QAAI,QAAQ,QAAQ,KAAM,SAAQ,OAAO,OAAO,QAAQ,IAAI;AAC5D,QAAI,QAAQ,SAAS,KAAM,SAAQ,QAAQ,OAAO,QAAQ,KAAK;AAG/D,QAAI,OAAO,QAAQ,WAAW,UAAU;AACpC,cAAQ,SAAS,QAAQ,OAAO,MAAM,GAAG,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,IAC1F;AAGA,UAAM,YAAY,QAAQ,WAAW,QAAQ;AAC7C,QAAI,OAAO,cAAc,UAAU;AAC/B,YAAM,SAAS,UAAU,MAAM,GAAG,EAAE,IAAI,CAAC,SAAiB;AACtD,cAAM,UAAU,KAAK,KAAK;AAC1B,YAAI,QAAQ,WAAW,GAAG,GAAG;AACzB,iBAAO,EAAE,OAAO,QAAQ,MAAM,CAAC,GAAG,OAAO,OAAgB;AAAA,QAC7D;AACA,cAAM,CAAC,OAAO,KAAK,IAAI,QAAQ,MAAM,KAAK;AAC1C,eAAO,EAAE,OAAO,OAAQ,OAAO,YAAY,MAAM,SAAS,SAAS,MAAyB;AAAA,MAChG,CAAC,EAAE,OAAO,CAAC,MAAW,EAAE,KAAK;AAC7B,cAAQ,OAAO;AACf,aAAO,QAAQ;AAAA,IACnB;AAIA,QAAI,QAAQ,YAAY,UAAa,QAAQ,WAAW,QAAW;AAC/D,cAAQ,SAAS,QAAQ;AAAA,IAC7B;AACA,WAAO,QAAQ;AAGf,QAAI,OAAO,QAAQ,WAAW,UAAU;AACpC,UAAI;AAAE,gBAAQ,SAAS,KAAK,MAAM,QAAQ,MAAM;AAAA,MAAG,QAAQ;AAAA,MAAmB;AAAA,IAClF;AAIA,QAAI,YAAY,QAAQ,MAAM,GAAG;AAC7B,cAAQ,SAAS,eAAe,QAAQ,MAAM;AAAA,IAClD;AAGA,QAAI,OAAO,QAAQ,aAAa,UAAU;AACtC,cAAQ,WAAW,QAAQ,SAAS,MAAM,GAAG,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,IAC9F;AAIA,UAAM,cAAc,QAAQ,WAAW,QAAQ;AAC/C,QAAI,eAAe,CAAC,QAAQ,UAAU;AAClC,UAAI,OAAO,gBAAgB,UAAU;AACjC,gBAAQ,WAAW,YAAY,MAAM,GAAG,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,MACzF,WAAW,MAAM,QAAQ,WAAW,GAAG;AACnC,gBAAQ,WAAW;AAAA,MACvB;AAAA,IACJ;AACA,WAAO,QAAQ;AACf,WAAO,QAAQ;AAGf,eAAW,OAAO,CAAC,YAAY,OAAO,GAAG;AACrC,UAAI,QAAQ,GAAG,MAAM,OAAQ,SAAQ,GAAG,IAAI;AAAA,eACnC,QAAQ,GAAG,MAAM,QAAS,SAAQ,GAAG,IAAI;AAAA,IACtD;AAOA,UAAM,cAAc,oBAAI,IAAI;AAAA,MACxB;AAAA,MAAO;AAAA,MAAQ;AAAA,MAAS;AAAA,MACxB;AAAA,MAAQ;AAAA,MACR;AAAA,MAAU;AAAA,MACV;AAAA,MAAU;AAAA,MAAW;AAAA,MACrB;AAAA,MAAY;AAAA,MAAU;AAAA,MACtB;AAAA,MAAY;AAAA,MACZ;AAAA,MAAgB;AAAA,MAChB;AAAA,MAAU;AAAA,IACd,CAAC;AACD,QAAI,CAAC,QAAQ,QAAQ;AACjB,YAAM,kBAA2C,CAAC;AAClD,iBAAW,OAAO,OAAO,KAAK,OAAO,GAAG;AACpC,YAAI,CAAC,YAAY,IAAI,GAAG,GAAG;AACvB,0BAAgB,GAAG,IAAI,QAAQ,GAAG;AAClC,iBAAO,QAAQ,GAAG;AAAA,QACtB;AAAA,MACJ;AACA,UAAI,OAAO,KAAK,eAAe,EAAE,SAAS,GAAG;AACzC,gBAAQ,SAAS;AAAA,MACrB;AAAA,IACJ;AAEA,UAAM,UAAU,MAAM,KAAK,OAAO,KAAK,QAAQ,QAAQ,OAAO;AAC9D,WAAO;AAAA,MACH,QAAQ,QAAQ;AAAA,MAChB,OAAO;AAAA;AAAA,MACP;AAAA;AAAA,MACA,OAAO,QAAQ;AAAA,MACf,SAAS;AAAA,IACb;AAAA,EACJ;AAAA,EAEA,MAAM,QAAQ,SAAiG;AAC3G,UAAM,eAAoB;AAAA,MACtB,QAAQ,EAAE,IAAI,QAAQ,GAAG;AAAA,IAC7B;AAGA,QAAI,QAAQ,QAAQ;AAChB,mBAAa,SAAS,OAAO,QAAQ,WAAW,WAC1C,QAAQ,OAAO,MAAM,GAAG,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,IACrE,QAAQ;AAAA,IAClB;AAGA,QAAI,QAAQ,QAAQ;AAChB,mBAAa,WAAW,OAAO,QAAQ,WAAW,WAC5C,QAAQ,OAAO,MAAM,GAAG,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,IACrE,QAAQ;AAAA,IAClB;AAEA,UAAM,SAAS,MAAM,KAAK,OAAO,QAAQ,QAAQ,QAAQ,YAAY;AACrE,QAAI,QAAQ;AACR,aAAO;AAAA,QACH,QAAQ,QAAQ;AAAA,QAChB,IAAI,QAAQ;AAAA,QACZ,QAAQ;AAAA,MACZ;AAAA,IACJ;AACA,UAAM,IAAI,MAAM,UAAU,QAAQ,EAAE,iBAAiB,QAAQ,MAAM,EAAE;AAAA,EACzE;AAAA,EAEA,MAAM,WAAW,SAAwC;AACrD,UAAM,SAAS,MAAM,KAAK,OAAO,OAAO,QAAQ,QAAQ,QAAQ,IAAI;AACpE,WAAO;AAAA,MACH,QAAQ,QAAQ;AAAA,MAChB,IAAI,OAAO;AAAA,MACX,QAAQ;AAAA,IACZ;AAAA,EACJ;AAAA,EAEA,MAAM,WAAW,SAAoD;AAEjE,UAAM,SAAS,MAAM,KAAK,OAAO,OAAO,QAAQ,QAAQ,QAAQ,MAAM,EAAE,QAAQ,EAAE,IAAI,QAAQ,GAAG,EAAE,CAAC;AACpG,WAAO;AAAA,MACH,QAAQ,QAAQ;AAAA,MAChB,IAAI,QAAQ;AAAA,MACZ,QAAQ;AAAA,IACZ;AAAA,EACJ;AAAA,EAEA,MAAM,WAAW,SAAyC;AAEtD,UAAM,KAAK,OAAO,OAAO,QAAQ,QAAQ,EAAE,QAAQ,EAAE,IAAI,QAAQ,GAAG,EAAE,CAAC;AACvE,WAAO;AAAA,MACH,QAAQ,QAAQ;AAAA,MAChB,IAAI,QAAQ;AAAA,MACZ,SAAS;AAAA,IACb;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,kBAAkB,SAA8G;AAClI,QAAI;AACA,YAAM,OAAO,eAAe,QAAQ,QAAQ,MAAM,QAAQ,IAAI;AAC9D,UAAI,CAAC,MAAM;AACP,cAAM,IAAI,MAAM,iBAAiB,QAAQ,IAAI,IAAI,QAAQ,IAAI,YAAY;AAAA,MAC7E;AAGA,YAAM,UAAU,KAAK,UAAU,IAAI;AACnC,YAAM,OAAO,WAAW,OAAO;AAC/B,YAAM,OAAO,EAAE,OAAO,MAAM,MAAM,MAAM;AAGxC,UAAI,QAAQ,cAAc,aAAa;AACnC,cAAM,aAAa,QAAQ,aAAa,YAAY,QAAQ,YAAY,IAAI,EAAE,QAAQ,eAAe,IAAI;AACzG,YAAI,eAAe,MAAM;AAErB,iBAAO;AAAA,YACH,aAAa;AAAA,YACb;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAGA,aAAO;AAAA,QACH,MAAM;AAAA,QACN;AAAA,QACA,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,QACrC,cAAc;AAAA,UACV,YAAY,CAAC,UAAU,SAAS;AAAA,UAChC,QAAQ;AAAA;AAAA,QACZ;AAAA,QACA,aAAa;AAAA,MACjB;AAAA,IACJ,SAAS,OAAY;AACjB,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAU,SAAwF;AACpG,UAAM,EAAE,QAAQ,SAAS,SAAS,IAAI;AACtC,UAAM,EAAE,WAAW,SAAS,QAAQ,IAAI;AACxC,UAAM,UAAkF,CAAC;AACzF,QAAI,YAAY;AAChB,QAAI,SAAS;AAEb,eAAW,UAAU,SAAS;AAC1B,UAAI;AACA,gBAAQ,WAAW;AAAA,UACf,KAAK,UAAU;AACX,kBAAM,UAAU,MAAM,KAAK,OAAO,OAAO,QAAQ,OAAO,QAAQ,MAAM;AACtE,oBAAQ,KAAK,EAAE,IAAI,QAAQ,IAAI,SAAS,MAAM,QAAQ,QAAQ,CAAC;AAC/D;AACA;AAAA,UACJ;AAAA,UACA,KAAK,UAAU;AACX,gBAAI,CAAC,OAAO,GAAI,OAAM,IAAI,MAAM,kCAAkC;AAClE,kBAAM,UAAU,MAAM,KAAK,OAAO,OAAO,QAAQ,OAAO,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,OAAO,GAAG,EAAE,CAAC;AACjG,oBAAQ,KAAK,EAAE,IAAI,OAAO,IAAI,SAAS,MAAM,QAAQ,QAAQ,CAAC;AAC9D;AACA;AAAA,UACJ;AAAA,UACA,KAAK,UAAU;AAEX,gBAAI,OAAO,IAAI;AACX,kBAAI;AACA,sBAAM,WAAW,MAAM,KAAK,OAAO,QAAQ,QAAQ,EAAE,QAAQ,EAAE,IAAI,OAAO,GAAG,EAAE,CAAC;AAChF,oBAAI,UAAU;AACV,wBAAM,UAAU,MAAM,KAAK,OAAO,OAAO,QAAQ,OAAO,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,OAAO,GAAG,EAAE,CAAC;AACjG,0BAAQ,KAAK,EAAE,IAAI,OAAO,IAAI,SAAS,MAAM,QAAQ,QAAQ,CAAC;AAAA,gBAClE,OAAO;AACH,wBAAM,UAAU,MAAM,KAAK,OAAO,OAAO,QAAQ,EAAE,IAAI,OAAO,IAAI,GAAI,OAAO,QAAQ,CAAC,EAAG,CAAC;AAC1F,0BAAQ,KAAK,EAAE,IAAI,QAAQ,IAAI,SAAS,MAAM,QAAQ,QAAQ,CAAC;AAAA,gBACnE;AAAA,cACJ,QAAQ;AACJ,sBAAM,UAAU,MAAM,KAAK,OAAO,OAAO,QAAQ,EAAE,IAAI,OAAO,IAAI,GAAI,OAAO,QAAQ,CAAC,EAAG,CAAC;AAC1F,wBAAQ,KAAK,EAAE,IAAI,QAAQ,IAAI,SAAS,MAAM,QAAQ,QAAQ,CAAC;AAAA,cACnE;AAAA,YACJ,OAAO;AACH,oBAAM,UAAU,MAAM,KAAK,OAAO,OAAO,QAAQ,OAAO,QAAQ,MAAM;AACtE,sBAAQ,KAAK,EAAE,IAAI,QAAQ,IAAI,SAAS,MAAM,QAAQ,QAAQ,CAAC;AAAA,YACnE;AACA;AACA;AAAA,UACJ;AAAA,UACA,KAAK,UAAU;AACX,gBAAI,CAAC,OAAO,GAAI,OAAM,IAAI,MAAM,kCAAkC;AAClE,kBAAM,KAAK,OAAO,OAAO,QAAQ,EAAE,QAAQ,EAAE,IAAI,OAAO,GAAG,EAAE,CAAC;AAC9D,oBAAQ,KAAK,EAAE,IAAI,OAAO,IAAI,SAAS,KAAK,CAAC;AAC7C;AACA;AAAA,UACJ;AAAA,UACA;AACI,oBAAQ,KAAK,EAAE,IAAI,OAAO,IAAI,SAAS,OAAO,OAAO,sBAAsB,SAAS,GAAG,CAAC;AACxF;AAAA,QACR;AAAA,MACJ,SAAS,KAAU;AACf,gBAAQ,KAAK,EAAE,IAAI,OAAO,IAAI,SAAS,OAAO,OAAO,IAAI,QAAQ,CAAC;AAClE;AACA,YAAI,SAAS,QAAQ;AAEjB;AAAA,QACJ;AACA,YAAI,CAAC,SAAS,iBAAiB;AAC3B;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO;AAAA,MACH,SAAS,WAAW;AAAA,MACpB;AAAA,MACA,OAAO,QAAQ;AAAA,MACf;AAAA,MACA;AAAA,MACA,SAAS,SAAS,kBAAkB,QAAQ,UAAU,QAAQ,IAAI,QAAM,EAAE,IAAI,EAAE,IAAI,SAAS,EAAE,SAAS,OAAO,EAAE,MAAM,EAAE;AAAA,IAC7H;AAAA,EACJ;AAAA,EAEA,MAAM,eAAe,SAA2D;AAC5E,UAAM,UAAU,MAAM,KAAK,OAAO,OAAO,QAAQ,QAAQ,QAAQ,OAAO;AACxE,WAAO;AAAA,MACH,QAAQ,QAAQ;AAAA,MAChB;AAAA,MACA,OAAO,QAAQ;AAAA,IACnB;AAAA,EACJ;AAAA,EAEA,MAAM,eAAe,SAA8D;AAC/E,UAAM,EAAE,QAAQ,SAAS,QAAQ,IAAI;AACrC,UAAM,UAAkF,CAAC;AACzF,QAAI,YAAY;AAChB,QAAI,SAAS;AAEb,eAAW,UAAU,SAAS;AAC1B,UAAI;AACA,cAAM,UAAU,MAAM,KAAK,OAAO,OAAO,QAAQ,OAAO,MAAM,EAAE,QAAQ,EAAE,IAAI,OAAO,GAAG,EAAE,CAAC;AAC3F,gBAAQ,KAAK,EAAE,IAAI,OAAO,IAAI,SAAS,MAAM,QAAQ,QAAQ,CAAC;AAC9D;AAAA,MACJ,SAAS,KAAU;AACf,gBAAQ,KAAK,EAAE,IAAI,OAAO,IAAI,SAAS,OAAO,OAAO,IAAI,QAAQ,CAAC;AAClE;AACA,YAAI,CAAC,SAAS,iBAAiB;AAC3B;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO;AAAA,MACH,SAAS,WAAW;AAAA,MACpB,WAAW;AAAA,MACX,OAAO,QAAQ;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,eAAe,SAA4B;AAG7C,UAAM,EAAE,OAAO,KAAK,IAAI;AACxB,UAAM,SAAS;AAGf,UAAM,UAAU,MAAM,cAAc,CAAC;AAKrC,UAAM,eAAwE,CAAC;AAC/E,QAAI,MAAM,UAAU;AAChB,iBAAW,WAAW,MAAM,UAAU;AAElC,YAAI,YAAY,WAAW,YAAY,aAAa;AAChD,uBAAa,KAAK,EAAE,OAAO,KAAK,QAAQ,SAAS,OAAO,QAAQ,CAAC;AAAA,QACrE,WAAW,QAAQ,SAAS,GAAG,GAAG;AAC9B,gBAAM,CAAC,OAAO,MAAM,IAAI,QAAQ,MAAM,GAAG;AACzC,uBAAa,KAAK,EAAE,OAAO,QAAQ,OAAO,GAAG,KAAK,IAAI,MAAM,GAAG,CAAC;AAAA,QACpE,OAAO;AAEH,uBAAa,KAAK,EAAE,OAAO,SAAS,QAAQ,OAAO,OAAO,QAAQ,CAAC;AAAA,QACvE;AAAA,MACJ;AAAA,IACJ;AAGA,QAAI,SAAc;AAClB,QAAI,MAAM,WAAW,MAAM,QAAQ,SAAS,GAAG;AAC3C,YAAM,aAAoB,MAAM,QAAQ,IAAI,CAAC,MAAW;AACpD,cAAM,KAAK,KAAK,qBAAqB,EAAE,QAAQ;AAC/C,YAAI,EAAE,UAAU,EAAE,OAAO,WAAW,GAAG;AACnC,iBAAO,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,QAC/C,WAAW,EAAE,UAAU,EAAE,OAAO,SAAS,GAAG;AACxC,iBAAO,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE;AAAA,QAC3C;AACA,eAAO,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE;AAAA,MACxC,CAAC;AACD,eAAS,WAAW,WAAW,IAAI,WAAW,CAAC,IAAI,EAAE,MAAM,WAAW;AAAA,IAC1E;AAGA,UAAM,OAAO,MAAM,KAAK,OAAO,UAAU,QAAQ;AAAA,MAC7C;AAAA,MACA,SAAS,QAAQ,SAAS,IAAI,UAAU;AAAA,MACxC,cAAc,aAAa,SAAS,IAC9B,aAAa,IAAI,QAAM,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,QAAe,OAAO,EAAE,MAAM,EAAE,IACnF,CAAC,EAAE,OAAO,KAAK,QAAQ,SAAgB,OAAO,QAAQ,CAAC;AAAA,IACjE,CAAC;AAGD,UAAM,SAAS;AAAA,MACX,GAAG,QAAQ,IAAI,CAAC,OAAe,EAAE,MAAM,GAAG,MAAM,SAAS,EAAE;AAAA,MAC3D,GAAG,aAAa,IAAI,QAAM,EAAE,MAAM,EAAE,OAAO,MAAM,SAAS,EAAE;AAAA,IAChE;AAEA,WAAO;AAAA,MACH,SAAS;AAAA,MACT,MAAM;AAAA,QACF;AAAA,QACA;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,iBAAiB,SAA4B;AAG/C,UAAM,UAAU,eAAe,UAAU,QAAQ;AACjD,UAAM,aAAa,SAAS;AAE5B,UAAM,QAAe,CAAC;AACtB,eAAW,OAAO,SAAS;AACvB,YAAM,SAAS;AACf,UAAI,cAAc,OAAO,SAAS,WAAY;AAE9C,YAAM,WAAgC,CAAC;AACvC,YAAM,aAAkC,CAAC;AACzC,YAAM,SAAS,OAAO,UAAU,CAAC;AAGjC,eAAS,OAAO,IAAI;AAAA,QAChB,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,MACT;AAEA,iBAAW,CAAC,WAAW,QAAQ,KAAK,OAAO,QAAQ,MAAM,GAAG;AACxD,cAAM,KAAK;AACX,cAAM,YAAY,GAAG,QAAQ;AAE7B,YAAI,CAAC,UAAU,YAAY,SAAS,EAAE,SAAS,SAAS,GAAG;AAEvD,mBAAS,GAAG,SAAS,MAAM,IAAI;AAAA,YAC3B,MAAM,GAAG,SAAS;AAAA,YAClB,OAAO,GAAG,GAAG,SAAS,SAAS;AAAA,YAC/B,MAAM;AAAA,YACN,KAAK;AAAA,UACT;AACA,mBAAS,GAAG,SAAS,MAAM,IAAI;AAAA,YAC3B,MAAM,GAAG,SAAS;AAAA,YAClB,OAAO,GAAG,GAAG,SAAS,SAAS;AAAA,YAC/B,MAAM;AAAA,YACN,KAAK;AAAA,UACT;AACA,qBAAW,SAAS,IAAI;AAAA,YACpB,MAAM;AAAA,YACN,OAAO,GAAG,SAAS;AAAA,YACnB,MAAM;AAAA,YACN,KAAK;AAAA,UACT;AAAA,QACJ,WAAW,CAAC,QAAQ,UAAU,EAAE,SAAS,SAAS,GAAG;AACjD,qBAAW,SAAS,IAAI;AAAA,YACpB,MAAM;AAAA,YACN,OAAO,GAAG,SAAS;AAAA,YACnB,MAAM;AAAA,YACN,KAAK;AAAA,YACL,eAAe,CAAC,OAAO,QAAQ,SAAS,WAAW,MAAM;AAAA,UAC7D;AAAA,QACJ,WAAW,CAAC,SAAS,EAAE,SAAS,SAAS,GAAG;AACxC,qBAAW,SAAS,IAAI;AAAA,YACpB,MAAM;AAAA,YACN,OAAO,GAAG,SAAS;AAAA,YACnB,MAAM;AAAA,YACN,KAAK;AAAA,UACT;AAAA,QACJ,OAAO;AAEH,qBAAW,SAAS,IAAI;AAAA,YACpB,MAAM;AAAA,YACN,OAAO,GAAG,SAAS;AAAA,YACnB,MAAM;AAAA,YACN,KAAK;AAAA,UACT;AAAA,QACJ;AAAA,MACJ;AAEA,YAAM,KAAK;AAAA,QACP,MAAM,OAAO;AAAA,QACb,OAAO,OAAO,SAAS,OAAO;AAAA,QAC9B,aAAa,OAAO;AAAA,QACpB,KAAK,OAAO;AAAA,QACZ;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MACZ,CAAC;AAAA,IACL;AAEA,WAAO;AAAA,MACH,SAAS;AAAA,MACT,MAAM,EAAE,MAAM;AAAA,IAClB;AAAA,EACJ;AAAA,EAEQ,qBAAqB,IAAoB;AAC7C,UAAM,MAA8B;AAAA,MAChC,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU;AAAA,MACV,aAAa;AAAA,MACb,IAAI;AAAA,MACJ,KAAK;AAAA,MACL,IAAI;AAAA,MACJ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,QAAQ;AAAA,IACZ;AACA,WAAO,IAAI,EAAE,KAAK;AAAA,EACtB;AAAA,EAEA,MAAM,kBAAkB,UAA6B;AACjD,UAAM,IAAI,MAAM,6HAA6H;AAAA,EACjJ;AAAA,EAEA,MAAM,eAAe,SAA8C;AAE/D,WAAO,KAAK,OAAO,OAAO,QAAQ,QAAQ;AAAA,MACtC,QAAQ,EAAE,IAAI,EAAE,KAAK,QAAQ,IAAI,EAAE;AAAA,MACnC,GAAG,QAAQ;AAAA,IACf,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,aAAa,SAAqD;AACpE,QAAI,CAAC,QAAQ,MAAM;AACf,YAAM,IAAI,MAAM,uBAAuB;AAAA,IAC3C;AAEA,mBAAe,aAAa,QAAQ,MAAM,QAAQ,MAAM,MAAM;AAC9D,WAAO;AAAA,MACH,SAAS;AAAA,MACT,SAAS;AAAA,IACb;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,SAAS,SAA4B;AACvC,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,SAAS,MAAM,IAAI,SAAS;AAAA,MAC9B,QAAQ,QAAQ;AAAA,MAChB,UAAU,QAAQ;AAAA,MAClB,QAAQ,QAAQ;AAAA,MAChB,OAAO,QAAQ;AAAA,MACf,QAAQ,QAAQ;AAAA,IACpB,CAAC;AACD,WAAO,EAAE,SAAS,MAAM,MAAM,OAAO;AAAA,EACzC;AAAA,EAEA,MAAM,eAAe,SAA4B;AAC7C,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,OAAO,MAAM,IAAI,eAAe;AAAA,MAClC,QAAQ,QAAQ;AAAA,MAChB,UAAU,QAAQ;AAAA,MAClB,MAAM,QAAQ;AAAA,MACd,OAAO,EAAE,MAAM,QAAQ,IAAI,eAAe;AAAA,MAC1C,MAAM,QAAQ;AAAA,MACd,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,MAClB,YAAY,QAAQ;AAAA,IACxB,CAAC;AACD,WAAO,EAAE,SAAS,MAAM,MAAM,KAAK;AAAA,EACvC;AAAA,EAEA,MAAM,eAAe,SAA4B;AAC7C,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,OAAO,MAAM,IAAI,eAAe,QAAQ,QAAQ;AAAA,MAClD,MAAM,QAAQ;AAAA,MACd,UAAU,QAAQ;AAAA,MAClB,YAAY,QAAQ;AAAA,IACxB,CAAC;AACD,WAAO,EAAE,SAAS,MAAM,MAAM,KAAK;AAAA,EACvC;AAAA,EAEA,MAAM,eAAe,SAA4B;AAC7C,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,IAAI,eAAe,QAAQ,MAAM;AACvC,WAAO,EAAE,SAAS,MAAM,MAAM,EAAE,QAAQ,QAAQ,OAAO,EAAE;AAAA,EAC7D;AAAA,EAEA,MAAM,YAAY,SAA4B;AAC1C,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,YAAY,MAAM,IAAI,YAAY,QAAQ,QAAQ,QAAQ,OAAO,cAAc;AACrF,WAAO,EAAE,SAAS,MAAM,MAAM,EAAE,UAAU,EAAE;AAAA,EAChD;AAAA,EAEA,MAAM,eAAe,SAA4B;AAC7C,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,YAAY,MAAM,IAAI,eAAe,QAAQ,QAAQ,QAAQ,OAAO,cAAc;AACxF,WAAO,EAAE,SAAS,MAAM,MAAM,EAAE,UAAU,EAAE;AAAA,EAChD;AAAA,EAEA,MAAM,YAAY,SAA4B;AAC1C,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,OAAO,MAAM,IAAI,YAAY,QAAQ,MAAM;AACjD,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,aAAa,QAAQ,MAAM,YAAY;AAElE,UAAM,IAAI,eAAe,QAAQ,QAAQ,EAAE,YAAY,KAAK,WAAW,CAAC;AACxE,WAAO,EAAE,SAAS,MAAM,MAAM,EAAE,QAAQ,QAAQ,QAAQ,QAAQ,MAAM,WAAU,oBAAI,KAAK,GAAE,YAAY,EAAE,EAAE;AAAA,EAC/G;AAAA,EAEA,MAAM,cAAc,SAA4B;AAC5C,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,OAAO,MAAM,IAAI,YAAY,QAAQ,MAAM;AACjD,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,aAAa,QAAQ,MAAM,YAAY;AAClE,UAAM,IAAI,eAAe,QAAQ,QAAQ,EAAE,YAAY,KAAK,WAAW,CAAC;AACxE,WAAO,EAAE,SAAS,MAAM,MAAM,EAAE,QAAQ,QAAQ,QAAQ,QAAQ,MAAM,EAAE;AAAA,EAC5E;AAAA,EAEA,MAAM,aAAa,SAA4B;AAC3C,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,OAAO,MAAM,IAAI,YAAY,QAAQ,MAAM;AACjD,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,aAAa,QAAQ,MAAM,YAAY;AAElE,UAAM,IAAI,eAAe,QAAQ,QAAQ,EAAE,YAAY,KAAK,WAAW,CAAC;AACxE,WAAO,EAAE,SAAS,MAAM,MAAM,EAAE,QAAQ,QAAQ,QAAQ,SAAS,MAAM,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,EAAE;AAAA,EACjH;AAAA,EAEA,MAAM,eAAe,SAA4B;AAC7C,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,OAAO,MAAM,IAAI,YAAY,QAAQ,MAAM;AACjD,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,aAAa,QAAQ,MAAM,YAAY;AAClE,UAAM,IAAI,eAAe,QAAQ,QAAQ,EAAE,YAAY,KAAK,WAAW,CAAC;AACxE,WAAO,EAAE,SAAS,MAAM,MAAM,EAAE,QAAQ,QAAQ,QAAQ,SAAS,MAAM,EAAE;AAAA,EAC7E;AAAA,EAEA,MAAM,WAAW,SAA4B;AACzC,UAAM,MAAM,KAAK,mBAAmB;AAEpC,UAAM,SAAS,MAAM,IAAI,SAAS;AAAA,MAC9B,QAAQ,QAAQ;AAAA,MAChB,UAAU,QAAQ;AAAA,MAClB,QAAQ,QAAQ;AAAA,MAChB,OAAO,QAAQ;AAAA,MACf,QAAQ,QAAQ;AAAA,IACpB,CAAC;AAED,UAAM,cAAc,QAAQ,SAAS,IAAI,YAAY;AACrD,UAAM,WAAW,OAAO,MAAM;AAAA,MAAO,CAAC,SAClC,KAAK,MAAM,YAAY,EAAE,SAAS,UAAU;AAAA,IAChD;AACA,WAAO,EAAE,SAAS,MAAM,MAAM,EAAE,OAAO,UAAU,OAAO,SAAS,QAAQ,SAAS,MAAM,EAAE;AAAA,EAC9F;AAAA,EAEA,MAAM,aAAa,SAA4B;AAC3C,UAAM,MAAM,KAAK,mBAAmB;AAEpC,UAAM,SAAS,MAAM,IAAI,SAAS;AAAA,MAC9B,QAAQ,QAAQ;AAAA,MAChB,UAAU,QAAQ;AAAA,MAClB,QAAQ;AAAA,MACR,OAAO,QAAQ;AAAA,MACf,QAAQ,QAAQ;AAAA,IACpB,CAAC;AACD,UAAM,UAAU,OAAO,MAAM,IAAI,CAAC,UAAe;AAAA,MAC7C,IAAI,KAAK;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK,WAAW,CAAC;AAAA,MAC1B,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK;AAAA,IACjB,EAAE;AACF,WAAO,EAAE,SAAS,MAAM,MAAM,EAAE,SAAS,OAAO,OAAO,OAAO,YAAY,OAAO,YAAY,SAAS,OAAO,QAAQ,EAAE;AAAA,EAC3H;AAAA,EAEA,MAAM,cAAc,SAA4B;AAC5C,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,eAAe,MAAM,IAAI,UAAU;AAAA,MACrC,QAAQ,QAAQ;AAAA,MAChB,UAAU,QAAQ;AAAA,MAClB,QAAQ;AAAA,MACR,QAAQ,QAAQ;AAAA,MAChB,UAAU,QAAQ;AAAA,IACtB,CAAC;AACD,WAAO,EAAE,SAAS,MAAM,MAAM,aAAa;AAAA,EAC/C;AAAA,EAEA,MAAM,gBAAgB,SAA4B;AAC9C,UAAM,MAAM,KAAK,mBAAmB;AACpC,UAAM,eAAe,MAAM,IAAI,YAAY,QAAQ,QAAQ,QAAQ,UAAU,cAAc;AAC3F,WAAO,EAAE,SAAS,MAAM,MAAM,EAAE,QAAQ,QAAQ,QAAQ,UAAU,QAAQ,UAAU,aAAa,EAAE;AAAA,EACvG;AACJ;;;ACp7BA,SAA2B,8BAA8B;AACzD,SAA+C,oBAAoB;AACnE,SAAS,uBAAuB;AAsDzB,IAAM,YAAN,MAAM,UAAgC;AAAA,EAyB3C,YAAY,cAAmC,CAAC,GAAG;AAxBnD,SAAQ,UAAU,oBAAI,IAA6B;AACnD,SAAQ,gBAA+B;AAIvC;AAAA,SAAQ,QAAkC,oBAAI,IAAI;AAAA,MAChD,CAAC,cAAc,CAAC,CAAC;AAAA,MAAG,CAAC,aAAa,CAAC,CAAC;AAAA,MACpC,CAAC,gBAAgB,CAAC,CAAC;AAAA,MAAG,CAAC,eAAe,CAAC,CAAC;AAAA,MACxC,CAAC,gBAAgB,CAAC,CAAC;AAAA,MAAG,CAAC,eAAe,CAAC,CAAC;AAAA,MACxC,CAAC,gBAAgB,CAAC,CAAC;AAAA,MAAG,CAAC,eAAe,CAAC,CAAC;AAAA,IAC1C,CAAC;AAGD;AAAA,SAAQ,cAGH,CAAC;AAGN;AAAA,SAAQ,UAAU,oBAAI,IAA6E;AAGnG;AAAA,SAAQ,cAAmC,CAAC;AAG1C,SAAK,cAAc;AAEnB,SAAK,SAAS,YAAY,UAAU,aAAa,EAAE,OAAO,QAAQ,QAAQ,SAAS,CAAC;AACpF,SAAK,OAAO,KAAK,kCAAkC;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY;AACR,WAAO;AAAA,MACH,MAAM,gBAAgB,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU,CAAC,QAAQ,SAAS,aAAa,gBAAgB,UAAU;AAAA,IACvE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAW;AACb,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IAAI,cAAmB,aAAmB;AAC9C,SAAK,OAAO,MAAM,kBAAkB;AAAA,MAClC,aAAa,CAAC,CAAC;AAAA,MACf,YAAY,CAAC,CAAC;AAAA,IAChB,CAAC;AAGD,QAAI,cAAc;AAChB,WAAK,YAAY,YAAY;AAAA,IAC/B;AAGA,QAAI,aAAa;AACd,YAAM,YAAa,YAAoB,WAAW;AAClD,UAAI,UAAU,UAAU;AACrB,aAAK,OAAO,MAAM,mCAAmC;AAErD,cAAM,UAA+B;AAAA,UACnC,IAAI;AAAA,UACJ,QAAQ,KAAK;AAAA;AAAA,UAEb,SAAS;AAAA,YACL,UAAU,CAAC,WAA4B,KAAK,eAAe,MAAM;AAAA,UACrE;AAAA,UACA,GAAG,KAAK;AAAA,QACV;AAEA,cAAM,UAAU,SAAS,OAAO;AAChC,aAAK,OAAO,MAAM,mCAAmC;AAAA,MACxD;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,OAAe,SAAsB,SAI/C;AACD,QAAI,CAAC,KAAK,MAAM,IAAI,KAAK,GAAG;AACxB,WAAK,MAAM,IAAI,OAAO,CAAC,CAAC;AAAA,IAC5B;AACA,UAAM,UAAU,KAAK,MAAM,IAAI,KAAK;AACpC,YAAQ,KAAK;AAAA,MACX;AAAA,MACA,QAAQ,SAAS;AAAA,MACjB,UAAU,SAAS,YAAY;AAAA,MAC/B,WAAW,SAAS;AAAA,IACtB,CAAC;AAED,YAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAC9C,SAAK,OAAO,MAAM,mBAAmB,EAAE,OAAO,QAAQ,SAAS,QAAQ,UAAU,SAAS,YAAY,KAAK,eAAe,QAAQ,OAAO,CAAC;AAAA,EAC5I;AAAA,EAEA,MAAa,aAAa,OAAe,SAAsB;AAC7D,UAAM,UAAU,KAAK,MAAM,IAAI,KAAK,KAAK,CAAC;AAE1C,QAAI,QAAQ,WAAW,GAAG;AACxB,WAAK,OAAO,MAAM,iCAAiC,EAAE,MAAM,CAAC;AAC5D;AAAA,IACF;AAEA,SAAK,OAAO,MAAM,oBAAoB,EAAE,OAAO,OAAO,QAAQ,OAAO,CAAC;AAEtE,eAAW,SAAS,SAAS;AAE3B,UAAI,MAAM,QAAQ;AAChB,cAAM,UAAU,MAAM,QAAQ,MAAM,MAAM,IAAI,MAAM,SAAS,CAAC,MAAM,MAAM;AAC1E,YAAI,CAAC,QAAQ,SAAS,GAAG,KAAK,CAAC,QAAQ,SAAS,QAAQ,MAAM,GAAG;AAC/D;AAAA,QACF;AAAA,MACF;AACA,YAAM,MAAM,QAAQ,OAAO;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,eAAe,YAAoB,YAAoB,SAA2C,aAA4B;AAC5H,UAAM,MAAM,GAAG,UAAU,IAAI,UAAU;AACvC,SAAK,QAAQ,IAAI,KAAK,EAAE,SAAS,SAAS,YAAY,CAAC;AACvD,SAAK,OAAO,MAAM,qBAAqB,EAAE,YAAY,YAAY,SAAS,YAAY,CAAC;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,YAAoB,YAAoB,KAAwB;AAClF,UAAM,QAAQ,KAAK,QAAQ,IAAI,GAAG,UAAU,IAAI,UAAU,EAAE;AAC5D,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,WAAW,UAAU,gBAAgB,UAAU,aAAa;AAAA,IAC9E;AACA,WAAO,MAAM,QAAQ,GAAG;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuB,aAA2B;AAChD,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,QAAQ,QAAQ,GAAG;AACjD,UAAI,MAAM,YAAY,aAAa;AACjC,aAAK,QAAQ,OAAO,GAAG;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,mBAAmB,IAAsB,SAAqC;AAC5E,SAAK,YAAY,KAAK,EAAE,IAAI,QAAQ,SAAS,OAAO,CAAC;AACrD,SAAK,OAAO,MAAM,yBAAyB,EAAE,QAAQ,SAAS,QAAQ,OAAO,KAAK,YAAY,OAAO,CAAC;AAAA,EACxG;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,sBAAsB,KAAuB,UAA4C;AACrG,UAAM,aAAa,KAAK,YAAY;AAAA,MAAO,OACzC,CAAC,EAAE,UAAU,EAAE,WAAW,OAAO,EAAE,WAAW,IAAI;AAAA,IACpD;AAEA,QAAI,QAAQ;AACZ,UAAM,OAAO,YAA2B;AACtC,UAAI,QAAQ,WAAW,QAAQ;AAC7B,cAAM,KAAK,WAAW,OAAO;AAC7B,cAAM,GAAG,GAAG,KAAK,IAAI;AAAA,MACvB,OAAO;AACL,YAAI,SAAS,MAAM,SAAS;AAAA,MAC9B;AAAA,IACF;AAEA,UAAM,KAAK;AACX,WAAO,IAAI;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,SAAoD;AACvE,QAAI,CAAC,QAAS,QAAO;AACrB,WAAO;AAAA,MACL,QAAQ,QAAQ;AAAA,MAChB,UAAU,QAAQ;AAAA,MAClB,OAAO,QAAQ;AAAA,MACf,aAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,YAAY,UAAe;AACvB,UAAM,KAAK,SAAS,MAAM,SAAS;AACnC,UAAM,YAAY,SAAS;AAC3B,SAAK,OAAO,MAAM,gCAAgC,EAAE,IAAI,UAAU,CAAC;AAGnE,mBAAe,eAAe,QAAQ;AACtC,SAAK,OAAO,MAAM,qBAAqB,EAAE,IAAI,SAAS,IAAI,MAAM,SAAS,MAAM,UAAU,CAAC;AAG1F,QAAI,SAAS,SAAS;AAClB,UAAI,MAAM,QAAQ,SAAS,OAAO,GAAG;AAClC,aAAK,OAAO,MAAM,6CAA6C,EAAE,IAAI,aAAa,SAAS,QAAQ,OAAO,CAAC;AAC3G,mBAAW,UAAU,SAAS,SAAS;AACpC,gBAAM,MAAM,eAAe,eAAe,QAAQ,IAAI,WAAW,KAAK;AACtE,eAAK,OAAO,MAAM,qBAAqB,EAAE,KAAK,MAAM,GAAG,CAAC;AAAA,QAC3D;AAAA,MACH,OAAO;AACJ,aAAK,OAAO,MAAM,2CAA2C,EAAE,IAAI,aAAa,OAAO,KAAK,SAAS,OAAO,EAAE,OAAO,CAAC;AACtH,mBAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,SAAS,OAAO,GAAG;AAE5D,UAAC,OAAe,OAAO;AACvB,gBAAM,MAAM,eAAe,eAAe,QAAe,IAAI,WAAW,KAAK;AAC7E,eAAK,OAAO,MAAM,qBAAqB,EAAE,KAAK,MAAM,GAAG,CAAC;AAAA,QAC3D;AAAA,MACH;AAAA,IACJ;AAGA,QAAI,MAAM,QAAQ,SAAS,gBAAgB,KAAK,SAAS,iBAAiB,SAAS,GAAG;AAClF,WAAK,OAAO,MAAM,iCAAiC,EAAE,IAAI,OAAO,SAAS,iBAAiB,OAAO,CAAC;AAClG,iBAAW,OAAO,SAAS,kBAAkB;AACzC,cAAM,YAAY,IAAI;AACtB,cAAM,WAAW,IAAI,YAAY;AAEjC,cAAM,SAAS;AAAA,UACX,MAAM;AAAA;AAAA,UACN,QAAQ,IAAI;AAAA,UACZ,OAAO,IAAI;AAAA,UACX,aAAa,IAAI;AAAA,UACjB,aAAa,IAAI;AAAA,UACjB,aAAa,IAAI;AAAA,UACjB,SAAS,IAAI;AAAA,QACjB;AAEA,uBAAe,eAAe,QAAe,IAAI,QAAW,UAAU,QAAQ;AAC9E,aAAK,OAAO,MAAM,+BAA+B,EAAE,QAAQ,WAAW,UAAU,MAAM,GAAG,CAAC;AAAA,MAC9F;AAAA,IACJ;AAGA,QAAI,MAAM,QAAQ,SAAS,IAAI,KAAK,SAAS,KAAK,SAAS,GAAG;AAC1D,WAAK,OAAO,MAAM,kCAAkC,EAAE,IAAI,OAAO,SAAS,KAAK,OAAO,CAAC;AACvF,iBAAW,OAAO,SAAS,MAAM;AAC7B,cAAM,UAAU,IAAI,QAAQ,IAAI;AAChC,YAAI,SAAS;AACT,yBAAe,YAAY,KAAK,EAAE;AAClC,eAAK,OAAO,MAAM,kBAAkB,EAAE,KAAK,SAAS,MAAM,GAAG,CAAC;AAAA,QAClE;AAAA,MACJ;AAAA,IACJ;AAIA,QAAI,SAAS,QAAQ,SAAS,cAAc,CAAC,SAAS,MAAM,QAAQ;AAChE,qBAAe,YAAY,UAAU,EAAE;AACvC,WAAK,OAAO,MAAM,8BAA8B,EAAE,KAAK,SAAS,MAAM,MAAM,GAAG,CAAC;AAAA,IACpF;AAGA,UAAM,oBAAoB;AAAA;AAAA,MAExB;AAAA,MAAW;AAAA,MAAS;AAAA,MAAS;AAAA,MAAc;AAAA,MAAW;AAAA;AAAA,MAEtD;AAAA,MAAS;AAAA,MAAa;AAAA,MAAa;AAAA;AAAA,MAEnC;AAAA,MAAS;AAAA,MAAe;AAAA,MAAY;AAAA,MAAgB;AAAA;AAAA,MAEpD;AAAA,MAAU;AAAA;AAAA,MAEV;AAAA;AAAA,MAEA;AAAA,MAAS;AAAA,MAAY;AAAA;AAAA,MAErB;AAAA,IACF;AACA,eAAW,OAAO,mBAAmB;AACjC,YAAM,QAAS,SAAiB,GAAG;AACnC,UAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,GAAG;AAC1C,aAAK,OAAO,MAAM,eAAe,GAAG,kBAAkB,EAAE,IAAI,OAAO,MAAM,OAAO,CAAC;AACjF,mBAAW,QAAQ,OAAO;AACtB,gBAAM,WAAW,KAAK,QAAQ,KAAK;AACnC,cAAI,UAAU;AACV,2BAAe,aAAa,KAAK,MAAM,QAAe,EAAE;AAAA,UAC5D;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAGA,UAAM,WAAY,SAAiB;AACnC,QAAI,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,GAAG;AAChD,WAAK,OAAO,MAAM,kCAAkC,EAAE,IAAI,OAAO,SAAS,OAAO,CAAC;AAClF,iBAAW,WAAW,UAAU;AAC5B,YAAI,QAAQ,QAAQ;AAChB,yBAAe,aAAa,QAAQ,SAAS,UAAiB,EAAE;AAAA,QACpE;AAAA,MACJ;AAAA,IACJ;AAGC,QAAI,SAAS,aAAa,OAAO;AAC9B,WAAK,OAAO,MAAM,mCAAmC,EAAE,IAAI,WAAW,SAAS,YAAY,MAAM,OAAO,CAAC;AACzG,iBAAW,QAAQ,SAAS,YAAY,OAAO;AAC7C,uBAAe,aAAa,IAAI;AAChC,aAAK,OAAO,MAAM,mBAAmB,EAAE,MAAM,KAAK,QAAQ,KAAK,MAAM,MAAM,GAAG,CAAC;AAAA,MACjF;AAAA,IACH;AAGD,QAAI,MAAM,QAAQ,SAAS,OAAO,KAAK,SAAS,QAAQ,SAAS,GAAG;AAChE,WAAK,OAAO,MAAM,6BAA6B,EAAE,IAAI,OAAO,SAAS,QAAQ,OAAO,CAAC;AACrF,iBAAW,UAAU,SAAS,SAAS;AACnC,YAAI,UAAU,OAAO,WAAW,UAAU;AACtC,gBAAM,aAAa,OAAO,QAAQ,OAAO,MAAM;AAC/C,eAAK,OAAO,MAAM,6BAA6B,EAAE,YAAY,UAAU,GAAG,CAAC;AAC3E,eAAK,eAAe,QAAQ,IAAI,SAAS;AAAA,QAC7C;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,eAAe,QAAa,UAAkB,iBAA0B;AAC5E,UAAM,aAAa,OAAO,QAAQ,OAAO,MAAM;AAC/C,UAAM,kBAAkB,OAAO,aAAa;AAK5C,UAAM,UAAU;AAGhB,QAAI,OAAO,SAAS;AAChB,UAAI;AACA,YAAI,MAAM,QAAQ,OAAO,OAAO,GAAG;AAC/B,eAAK,OAAO,MAAM,sCAAsC,EAAE,YAAY,OAAO,OAAO,QAAQ,OAAO,CAAC;AACpG,qBAAW,UAAU,OAAO,SAAS;AACjC,kBAAM,MAAM,eAAe,eAAe,QAAQ,SAAS,iBAAiB,KAAK;AACjF,iBAAK,OAAO,MAAM,qBAAqB,EAAE,KAAK,MAAM,WAAW,CAAC;AAAA,UACpE;AAAA,QACJ,OAAO;AACH,gBAAM,UAAU,OAAO,QAAQ,OAAO,OAAO;AAC7C,eAAK,OAAO,MAAM,oCAAoC,EAAE,YAAY,OAAO,QAAQ,OAAO,CAAC;AAC3F,qBAAW,CAAC,MAAM,MAAM,KAAK,SAAS;AAClC,YAAC,OAAe,OAAO;AACvB,kBAAM,MAAM,eAAe,eAAe,QAAe,SAAS,iBAAiB,KAAK;AACxF,iBAAK,OAAO,MAAM,qBAAqB,EAAE,KAAK,MAAM,WAAW,CAAC;AAAA,UACpE;AAAA,QACJ;AAAA,MACJ,SAAS,KAAU;AACf,aAAK,OAAO,KAAK,qCAAqC,EAAE,YAAY,OAAO,IAAI,QAAQ,CAAC;AAAA,MAC5F;AAAA,IACJ;AAGA,QAAI,OAAO,QAAQ,OAAO,YAAY;AAClC,UAAI;AACA,uBAAe,YAAY,QAAQ,OAAO;AAC1C,aAAK,OAAO,MAAM,4BAA4B,EAAE,KAAK,OAAO,MAAM,MAAM,WAAW,CAAC;AAAA,MACxF,SAAS,KAAU;AACf,aAAK,OAAO,KAAK,oCAAoC,EAAE,YAAY,OAAO,IAAI,QAAQ,CAAC;AAAA,MAC3F;AAAA,IACJ;AAGA,UAAM,oBAAoB;AAAA,MACtB;AAAA,MAAW;AAAA,MAAS;AAAA,MAAS;AAAA,MAAc;AAAA,MAAW;AAAA,MACtD;AAAA,MAAS;AAAA,MAAa;AAAA,MAAa;AAAA,MACnC;AAAA,MAAS;AAAA,MAAe;AAAA,MAAY;AAAA,MAAgB;AAAA,MACpD;AAAA,MAAU;AAAA,MAAgB;AAAA,MAC1B;AAAA,MAAS;AAAA,MAAY;AAAA,MAAkB;AAAA,IAC3C;AACA,eAAW,OAAO,mBAAmB;AACjC,YAAM,QAAS,OAAe,GAAG;AACjC,UAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,GAAG;AAC1C,mBAAW,QAAQ,OAAO;AACtB,gBAAM,WAAW,KAAK,QAAQ,KAAK;AACnC,cAAI,UAAU;AACV,2BAAe,aAAa,KAAK,MAAM,QAAe,OAAO;AAAA,UACjE;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,QAAyB,YAAqB,OAAO;AAClE,QAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,GAAG;AACjC,WAAK,OAAO,KAAK,uCAAuC,EAAE,YAAY,OAAO,KAAK,CAAC;AACnF;AAAA,IACF;AAEA,SAAK,QAAQ,IAAI,OAAO,MAAM,MAAM;AACpC,SAAK,OAAO,KAAK,qBAAqB;AAAA,MACpC,YAAY,OAAO;AAAA,MACnB,SAAS,OAAO;AAAA,IAClB,CAAC;AAED,QAAI,aAAa,KAAK,QAAQ,SAAS,GAAG;AACxC,WAAK,gBAAgB,OAAO;AAC5B,WAAK,OAAO,KAAK,sBAAsB,EAAE,YAAY,OAAO,KAAK,CAAC;AAAA,IACpE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,YAA+C;AACvD,WAAO,eAAe,UAAU,UAAU;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,kBAAkB,MAAsB;AAC9C,UAAM,SAAS,eAAe,UAAU,IAAI;AAC5C,QAAI,QAAQ;AAIV,aAAO,OAAO,aAAa,OAAO;AAAA,IACpC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAU,YAAqC;AACrD,UAAM,SAAS,eAAe,UAAU,UAAU;AAGlD,QAAI,QAAQ;AACV,YAAM,iBAAiB,OAAO,cAAc;AAG5C,UAAI,mBAAmB,WAAW;AAChC,YAAI,KAAK,iBAAiB,KAAK,QAAQ,IAAI,KAAK,aAAa,GAAG;AAC9D,iBAAO,KAAK,QAAQ,IAAI,KAAK,aAAa;AAAA,QAC5C;AAAA,MACF,OAAO;AAEL,YAAI,KAAK,QAAQ,IAAI,cAAc,GAAG;AAClC,iBAAO,KAAK,QAAQ,IAAI,cAAc;AAAA,QAC1C;AACA,cAAM,IAAI,MAAM,0BAA0B,cAAc,4BAA4B,UAAU,sBAAsB;AAAA,MACtH;AAAA,IACF;AAGA,QAAI,KAAK,eAAe;AACtB,aAAO,KAAK,QAAQ,IAAI,KAAK,aAAa;AAAA,IAC5C;AAEA,UAAM,IAAI,MAAM,8CAA8C,UAAU,GAAG;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO;AACX,SAAK,OAAO,KAAK,gCAAgC;AAAA,MAC/C,aAAa,KAAK,QAAQ;AAAA,MAC1B,SAAS,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAAA,IACzC,CAAC;AAED,eAAW,CAAC,MAAM,MAAM,KAAK,KAAK,SAAS;AACzC,UAAI;AACF,cAAM,OAAO,QAAQ;AACrB,aAAK,OAAO,KAAK,iCAAiC,EAAE,YAAY,KAAK,CAAC;AAAA,MACxE,SAAS,GAAG;AACV,aAAK,OAAO,MAAM,4BAA4B,GAAY,EAAE,YAAY,KAAK,CAAC;AAAA,MAChF;AAAA,IACF;AAEA,SAAK,OAAO,KAAK,yCAAyC;AAAA,EAC5D;AAAA,EAEA,MAAM,UAAU;AACd,SAAK,OAAO,KAAK,8BAA8B,EAAE,aAAa,KAAK,QAAQ,KAAK,CAAC;AAEjF,eAAW,CAAC,MAAM,MAAM,KAAK,KAAK,QAAQ,QAAQ,GAAG;AACnD,UAAI;AACF,cAAM,OAAO,WAAW;AAAA,MAC1B,SAAS,GAAG;AACV,aAAK,OAAO,MAAM,8BAA8B,GAAY,EAAE,YAAY,KAAK,CAAC;AAAA,MAClF;AAAA,IACF;AAEA,SAAK,OAAO,KAAK,2BAA2B;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,MAAc,qBACZ,YACA,SACA,QACA,QAAgB,GACA;AAChB,QAAI,CAAC,WAAW,QAAQ,WAAW,EAAG,QAAO;AAC7C,QAAI,SAAS,UAAS,iBAAkB,QAAO;AAE/C,UAAM,eAAe,eAAe,UAAU,UAAU;AAExD,QAAI,CAAC,gBAAgB,CAAC,aAAa,OAAQ,QAAO;AAElD,eAAW,CAAC,WAAW,SAAS,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3D,YAAM,WAAW,aAAa,OAAO,SAAS;AAG9C,UAAI,CAAC,YAAY,CAAC,SAAS,UAAW;AACtC,UAAI,SAAS,SAAS,YAAY,SAAS,SAAS,gBAAiB;AAErE,YAAM,kBAAkB,SAAS;AAGjC,YAAM,SAAgB,CAAC;AACvB,iBAAW,UAAU,SAAS;AAC5B,cAAM,MAAM,OAAO,SAAS;AAC5B,YAAI,OAAO,KAAM;AACjB,YAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,iBAAO,KAAK,GAAG,IAAI,OAAO,CAAC,OAAY,MAAM,IAAI,CAAC;AAAA,QACpD,WAAW,OAAO,QAAQ,UAAU;AAElC;AAAA,QACF,OAAO;AACL,iBAAO,KAAK,GAAG;AAAA,QACjB;AAAA,MACF;AAGA,YAAM,YAAY,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC;AACrC,UAAI,UAAU,WAAW,EAAG;AAG5B,UAAI;AACF,cAAM,eAAyB;AAAA,UAC7B,QAAQ;AAAA,UACR,OAAO,EAAE,IAAI,EAAE,KAAK,UAAU,EAAE;AAAA,UAChC,GAAI,UAAU,SAAS,EAAE,QAAQ,UAAU,OAAO,IAAI,CAAC;AAAA,UACvD,GAAI,UAAU,UAAU,EAAE,SAAS,UAAU,QAAQ,IAAI,CAAC;AAAA,QAC5D;AAEA,cAAM,SAAS,KAAK,UAAU,eAAe;AAC7C,cAAM,iBAAiB,MAAM,OAAO,KAAK,iBAAiB,YAAY,KAAK,CAAC;AAG5E,cAAM,YAAY,oBAAI,IAAiB;AACvC,mBAAW,OAAO,gBAAgB;AAChC,gBAAM,KAAK,IAAI;AACf,cAAI,MAAM,KAAM,WAAU,IAAI,OAAO,EAAE,GAAG,GAAG;AAAA,QAC/C;AAGA,YAAI,UAAU,UAAU,OAAO,KAAK,UAAU,MAAM,EAAE,SAAS,GAAG;AAChE,gBAAM,kBAAkB,MAAM,KAAK;AAAA,YACjC;AAAA,YACA;AAAA,YACA,UAAU;AAAA,YACV,QAAQ;AAAA,UACV;AAEA,oBAAU,MAAM;AAChB,qBAAW,OAAO,iBAAiB;AACjC,kBAAM,KAAK,IAAI;AACf,gBAAI,MAAM,KAAM,WAAU,IAAI,OAAO,EAAE,GAAG,GAAG;AAAA,UAC/C;AAAA,QACF;AAGA,mBAAW,UAAU,SAAS;AAC5B,gBAAM,MAAM,OAAO,SAAS;AAC5B,cAAI,OAAO,KAAM;AAEjB,cAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,mBAAO,SAAS,IAAI,IAAI,IAAI,CAAC,OAAY,UAAU,IAAI,OAAO,EAAE,CAAC,KAAK,EAAE;AAAA,UAC1E,WAAW,OAAO,QAAQ,UAAU;AAClC,mBAAO,SAAS,IAAI,UAAU,IAAI,OAAO,GAAG,CAAC,KAAK;AAAA,UACpD;AAAA,QAEF;AAAA,MACF,SAAS,GAAG;AAEV,aAAK,OAAO,KAAK,kEAAkE;AAAA,UACjF,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,WAAW;AAAA,UACX,OAAQ,EAAY;AAAA,QACtB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAW,QAAgB,SAA4C;AAC7E,UAAM,MAAgB,EAAE,OAAO;AAC/B,QAAI,CAAC,QAAS,QAAO;AAErB,QAAI,QAAQ,QAAQ;AAClB,UAAI,QAAQ,QAAQ;AAAA,IACtB;AACA,QAAI,QAAQ,QAAQ;AAClB,UAAI,SAAS,QAAQ;AAAA,IACvB;AACA,QAAI,QAAQ,MAAM;AAEf,UAAI,MAAM,QAAQ,QAAQ,IAAI,GAAG;AAE7B,YAAI,UAAU,QAAQ;AAAA,MAC1B,OAAO;AAEH,YAAI,UAAU,OAAO,QAAQ,QAAQ,IAAI,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO;AAAA,UAClE;AAAA,UACA,OAAQ,UAAU,MAAM,UAAU,SAAU,SAAS;AAAA,QACvD,EAAE;AAAA,MACN;AAAA,IACH;AAEA,QAAI,QAAQ,QAAQ,OAAW,KAAI,QAAQ,QAAQ;AAAA,aAC1C,QAAQ,UAAU,OAAW,KAAI,QAAQ,QAAQ;AAE1D,QAAI,QAAQ,SAAS,OAAW,KAAI,SAAS,QAAQ;AAGrD,QAAI,QAAQ,YAAY,QAAQ,SAAS,SAAS,GAAG;AACnD,UAAI,SAAS,CAAC;AACd,iBAAW,OAAO,QAAQ,UAAU;AAClC,YAAI,OAAO,GAAG,IAAI,EAAE,QAAQ,IAAI;AAAA,MAClC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAK,QAAgB,OAAgD;AACzE,aAAS,KAAK,kBAAkB,MAAM;AACtC,SAAK,OAAO,MAAM,2BAA2B,EAAE,QAAQ,MAAM,CAAC;AAC9D,UAAM,SAAS,KAAK,UAAU,MAAM;AACpC,UAAM,MAAM,KAAK,WAAW,QAAQ,KAAK;AAEzC,UAAM,QAA0B;AAAA,MAC9B;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA,SAAS;AAAA,MACT,SAAS,OAAO;AAAA,IAClB;AAEA,UAAM,KAAK,sBAAsB,OAAO,YAAY;AAClD,YAAM,cAA2B;AAAA,QAC7B;AAAA,QACA,OAAO;AAAA,QACP,OAAO,EAAE,KAAK,MAAM,KAAK,SAAS,MAAM,QAAQ;AAAA,QAChD,SAAS,KAAK,aAAa,MAAM,OAAO;AAAA,QACxC,aAAa,MAAM,SAAS;AAAA,QAC5B,IAAI;AAAA,MACR;AACA,YAAM,KAAK,aAAa,cAAc,WAAW;AAEjD,UAAI;AACA,YAAI,SAAS,MAAM,OAAO,KAAK,QAAQ,YAAY,MAAM,KAAiB,YAAY,MAAM,OAAc;AAG1G,YAAI,IAAI,UAAU,OAAO,KAAK,IAAI,MAAM,EAAE,SAAS,KAAK,MAAM,QAAQ,MAAM,GAAG;AAC7E,mBAAS,MAAM,KAAK,qBAAqB,QAAQ,QAAQ,IAAI,QAAQ,CAAC;AAAA,QACxE;AAEA,oBAAY,QAAQ;AACpB,oBAAY,SAAS;AACrB,cAAM,KAAK,aAAa,aAAa,WAAW;AAEhD,eAAO,YAAY;AAAA,MACvB,SAAS,GAAG;AACR,aAAK,OAAO,MAAM,yBAAyB,GAAY,EAAE,OAAO,CAAC;AACjE,cAAM;AAAA,MACV;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,MAAM,QAAQ,YAAoB,OAA8C;AAC9E,iBAAa,KAAK,kBAAkB,UAAU;AAC9C,SAAK,OAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC;AACrD,UAAM,SAAS,KAAK,UAAU,UAAU;AACxC,UAAM,MAAM,KAAK,WAAW,YAAY,KAAK;AAC7C,QAAI,QAAQ;AAEZ,UAAM,QAA0B;AAAA,MAC9B,QAAQ;AAAA,MACR,WAAW;AAAA,MACX;AAAA,MACA,SAAS;AAAA,MACT,SAAS,OAAO;AAAA,IAClB;AAEA,UAAM,KAAK,sBAAsB,OAAO,YAAY;AAClD,UAAI,SAAS,MAAM,OAAO,QAAQ,YAAY,MAAM,GAAe;AAGnE,UAAI,IAAI,UAAU,OAAO,KAAK,IAAI,MAAM,EAAE,SAAS,KAAK,UAAU,MAAM;AACtE,cAAM,WAAW,MAAM,KAAK,qBAAqB,YAAY,CAAC,MAAM,GAAG,IAAI,QAAQ,CAAC;AACpF,iBAAS,SAAS,CAAC;AAAA,MACrB;AAEA,aAAO;AAAA,IACT,CAAC;AAED,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,MAAM,OAAO,QAAgB,MAAmB,SAAiD;AAC/F,aAAS,KAAK,kBAAkB,MAAM;AACtC,SAAK,OAAO,MAAM,6BAA6B,EAAE,QAAQ,SAAS,MAAM,QAAQ,IAAI,EAAE,CAAC;AACvF,UAAM,SAAS,KAAK,UAAU,MAAM;AAEpC,UAAM,QAA0B;AAAA,MAC9B;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,SAAS,SAAS;AAAA,IACpB;AAEA,UAAM,KAAK,sBAAsB,OAAO,YAAY;AAClD,YAAM,cAA2B;AAAA,QAC7B;AAAA,QACA,OAAO;AAAA,QACP,OAAO,EAAE,MAAM,MAAM,MAAM,SAAS,MAAM,QAAQ;AAAA,QAClD,SAAS,KAAK,aAAa,MAAM,OAAO;AAAA,QACxC,aAAa,MAAM,SAAS;AAAA,QAC5B,IAAI;AAAA,MACR;AACA,YAAM,KAAK,aAAa,gBAAgB,WAAW;AAEnD,UAAI;AACF,YAAI;AACJ,YAAI,MAAM,QAAQ,YAAY,MAAM,IAAI,GAAG;AAEzC,cAAI,OAAO,YAAY;AAClB,qBAAS,MAAM,OAAO,WAAW,QAAQ,YAAY,MAAM,MAAe,YAAY,MAAM,OAAc;AAAA,UAC/G,OAAO;AAEF,qBAAS,MAAM,QAAQ,IAAK,YAAY,MAAM,KAAe,IAAI,CAAC,SAAc,OAAO,OAAO,QAAQ,MAAM,YAAY,MAAM,OAAc,CAAC,CAAC;AAAA,UACnJ;AAAA,QACF,OAAO;AACL,mBAAS,MAAM,OAAO,OAAO,QAAQ,YAAY,MAAM,MAAiC,YAAY,MAAM,OAAc;AAAA,QAC1H;AAEA,oBAAY,QAAQ;AACpB,oBAAY,SAAS;AACrB,cAAM,KAAK,aAAa,eAAe,WAAW;AAElD,eAAO,YAAY;AAAA,MACrB,SAAS,GAAG;AACV,aAAK,OAAO,MAAM,2BAA2B,GAAY,EAAE,OAAO,CAAC;AACnE,cAAM;AAAA,MACR;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,MAAM,OAAO,QAAgB,MAAW,SAAiD;AACtF,aAAS,KAAK,kBAAkB,MAAM;AACtC,SAAK,OAAO,MAAM,6BAA6B,EAAE,OAAO,CAAC;AACzD,UAAM,SAAS,KAAK,UAAU,MAAM;AAGpC,QAAI,KAAK,KAAK;AACd,QAAI,CAAC,MAAM,SAAS,QAAQ;AACxB,UAAI,OAAO,QAAQ,WAAW,SAAU,MAAK,QAAQ;AAAA,eAC5C,QAAQ,OAAO,GAAI,MAAK,QAAQ,OAAO;AAAA,IACpD;AAEA,UAAM,QAA0B;AAAA,MAC9B;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,SAAS,SAAS;AAAA,IACpB;AAEA,UAAM,KAAK,sBAAsB,OAAO,YAAY;AAClD,YAAM,cAA2B;AAAA,QAC9B;AAAA,QACA,OAAO;AAAA,QACP,OAAO,EAAE,IAAI,MAAM,MAAM,MAAM,SAAS,MAAM,QAAQ;AAAA,QACtD,SAAS,KAAK,aAAa,MAAM,OAAO;AAAA,QACxC,aAAa,MAAM,SAAS;AAAA,QAC5B,IAAI;AAAA,MACP;AACA,YAAM,KAAK,aAAa,gBAAgB,WAAW;AAEnD,UAAI;AACA,YAAI;AACJ,YAAI,YAAY,MAAM,IAAI;AACtB,mBAAS,MAAM,OAAO,OAAO,QAAQ,YAAY,MAAM,IAAc,YAAY,MAAM,MAAiC,YAAY,MAAM,OAAc;AAAA,QAC5J,WAAW,SAAS,SAAS,OAAO,YAAY;AAC5C,gBAAM,MAAM,KAAK,WAAW,QAAQ,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAC9D,mBAAS,MAAM,OAAO,WAAW,QAAQ,KAAK,YAAY,MAAM,MAAiC,YAAY,MAAM,OAAc;AAAA,QACrI,OAAO;AACH,gBAAM,IAAI,MAAM,6CAA6C;AAAA,QACjE;AAEA,oBAAY,QAAQ;AACpB,oBAAY,SAAS;AACrB,cAAM,KAAK,aAAa,eAAe,WAAW;AAClD,eAAO,YAAY;AAAA,MACvB,SAAS,GAAG;AACT,aAAK,OAAO,MAAM,2BAA2B,GAAY,EAAE,OAAO,CAAC;AACnE,cAAM;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AAAA,EAChB;AAAA,EAEA,MAAM,OAAO,QAAgB,SAAiD;AAC5E,aAAS,KAAK,kBAAkB,MAAM;AACtC,SAAK,OAAO,MAAM,6BAA6B,EAAE,OAAO,CAAC;AACzD,UAAM,SAAS,KAAK,UAAU,MAAM;AAGpC,QAAI,KAAU;AACd,QAAI,SAAS,QAAQ;AAChB,UAAI,OAAO,QAAQ,WAAW,SAAU,MAAK,QAAQ;AAAA,eAC5C,QAAQ,OAAO,GAAI,MAAK,QAAQ,OAAO;AAAA,IACrD;AAEA,UAAM,QAA0B;AAAA,MAC9B;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA,SAAS,SAAS;AAAA,IACpB;AAEA,UAAM,KAAK,sBAAsB,OAAO,YAAY;AAClD,YAAM,cAA2B;AAAA,QAC7B;AAAA,QACA,OAAO;AAAA,QACP,OAAO,EAAE,IAAI,SAAS,MAAM,QAAQ;AAAA,QACpC,SAAS,KAAK,aAAa,MAAM,OAAO;AAAA,QACxC,aAAa,MAAM,SAAS;AAAA,QAC5B,IAAI;AAAA,MACR;AACA,YAAM,KAAK,aAAa,gBAAgB,WAAW;AAEnD,UAAI;AACA,YAAI;AACJ,YAAI,YAAY,MAAM,IAAI;AACtB,mBAAS,MAAM,OAAO,OAAO,QAAQ,YAAY,MAAM,IAAc,YAAY,MAAM,OAAc;AAAA,QACzG,WAAW,SAAS,SAAS,OAAO,YAAY;AAC3C,gBAAM,MAAM,KAAK,WAAW,QAAQ,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAC9D,mBAAS,MAAM,OAAO,WAAW,QAAQ,KAAK,YAAY,MAAM,OAAc;AAAA,QACnF,OAAO;AACF,gBAAM,IAAI,MAAM,6CAA6C;AAAA,QAClE;AAEA,oBAAY,QAAQ;AACpB,oBAAY,SAAS;AACrB,cAAM,KAAK,aAAa,eAAe,WAAW;AAClD,eAAO,YAAY;AAAA,MACvB,SAAS,GAAG;AACR,aAAK,OAAO,MAAM,2BAA2B,GAAY,EAAE,OAAO,CAAC;AACnE,cAAM;AAAA,MACV;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,MAAM,MAAM,QAAgB,OAAiD;AAC1E,aAAS,KAAK,kBAAkB,MAAM;AACtC,UAAM,SAAS,KAAK,UAAU,MAAM;AAEpC,UAAM,QAA0B;AAAA,MAC9B;AAAA,MACA,WAAW;AAAA,MACX,SAAS;AAAA,MACT,SAAS,OAAO;AAAA,IAClB;AAEA,UAAM,KAAK,sBAAsB,OAAO,YAAY;AAClD,UAAI,OAAO,OAAO;AACd,cAAM,MAAM,KAAK,WAAW,QAAQ,EAAE,QAAQ,OAAO,OAAO,CAAC;AAC7D,eAAO,OAAO,MAAM,QAAQ,GAAG;AAAA,MACnC;AAEA,YAAM,MAAM,MAAM,KAAK,KAAK,QAAQ,EAAE,QAAQ,OAAO,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;AAC7E,aAAO,IAAI;AAAA,IACb,CAAC;AAED,WAAO,MAAM;AAAA,EAChB;AAAA,EAEA,MAAM,UAAU,QAAgB,OAAmD;AAC/E,aAAS,KAAK,kBAAkB,MAAM;AACtC,UAAM,SAAS,KAAK,UAAU,MAAM;AACpC,SAAK,OAAO,MAAM,gBAAgB,MAAM,UAAU,OAAO,IAAI,IAAI,KAAK;AAEtE,UAAM,QAA0B;AAAA,MAC9B;AAAA,MACA,WAAW;AAAA,MACX,SAAS;AAAA,MACT,SAAS,OAAO;AAAA,IAClB;AAEA,UAAM,KAAK,sBAAsB,OAAO,YAAY;AAClD,YAAM,MAAgB;AAAA,QAClB;AAAA,QACA,OAAO,MAAM;AAAA,QACb,SAAS,MAAM;AAAA,QACf,cAAc,MAAM,cAAc,IAAI,UAAQ;AAAA,UAC1C,UAAU,IAAI;AAAA,UACd,OAAO,IAAI;AAAA,UACX,OAAO,IAAI,SAAS,GAAG,IAAI,MAAM,IAAI,IAAI,SAAS,KAAK;AAAA,QAC3D,EAAE;AAAA,MACN;AAEA,aAAO,OAAO,KAAK,QAAQ,GAAG;AAAA,IAChC,CAAC;AAED,WAAO,MAAM;AAAA,EACjB;AAAA,EAEA,MAAM,QAAQ,SAAc,SAA6C;AAIrE,QAAI,SAAS,QAAQ;AACjB,YAAM,SAAS,KAAK,UAAU,QAAQ,MAAM;AAC5C,UAAI,OAAO,SAAS;AAChB,eAAO,OAAO,QAAQ,SAAS,QAAW,OAAO;AAAA,MACrD;AAAA,IACJ;AACA,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,eACE,QACA,YAAoB,eACpB,WACQ;AAER,QAAI,OAAO,QAAQ;AACjB,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,MAAM,GAAG;AACxD,YAAI,SAAS,OAAO,UAAU,YAAY,EAAE,UAAU,QAAQ;AAC5D,UAAC,MAAc,OAAO;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AACA,WAAO,eAAe,eAAe,QAAQ,WAAW,SAAS;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,MAAc,WAA0B;AACvD,QAAI,WAAW;AACb,qBAAe,2BAA2B,SAAS;AAAA,IACrD,OAAO;AAEL,qBAAe,eAAe,UAAU,IAAI;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,MAAyC;AACjD,WAAO,KAAK,UAAU,IAAI;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAA4C;AAC1C,UAAM,SAAwC,CAAC;AAC/C,UAAM,UAAU,eAAe,cAAc;AAC7C,eAAW,OAAO,SAAS;AACzB,UAAI,IAAI,MAAM;AACZ,eAAO,IAAI,IAAI,IAAI;AAAA,MACrB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB,MAA2C;AACzD,WAAO,KAAK,QAAQ,IAAI,IAAI;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,mBAAmB,YAAiD;AAClE,QAAI;AACF,aAAO,KAAK,UAAU,UAAU;AAAA,IAClC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,MAA+B;AACxC,UAAM,SAAS,KAAK,QAAQ,IAAI,IAAI;AACpC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,0BAA0B,IAAI,aAAa;AAAA,IAC7D;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,GACE,OACA,YACA,SACA,WACM;AACN,SAAK,aAAa,OAAO,SAAS,EAAE,QAAQ,YAAY,UAAU,CAAC;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,WAAyB;AAErC,eAAW,CAAC,KAAK,QAAQ,KAAK,KAAK,MAAM,QAAQ,GAAG;AAClD,YAAM,WAAW,SAAS,OAAO,OAAK,EAAE,cAAc,SAAS;AAC/D,UAAI,SAAS,WAAW,SAAS,QAAQ;AACvC,aAAK,MAAM,IAAI,KAAK,QAAQ;AAAA,MAC9B;AAAA,IACF;AAEA,SAAK,uBAAuB,SAAS;AAErC,mBAAe,2BAA2B,WAAW,IAAI;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAuB;AAC3B,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,cAAc,KAA+C;AAC3D,WAAO,IAAI;AAAA,MACT,uBAAuB,MAAM,GAAG;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,aAAa,OAAO,QAIE;AACpB,UAAM,KAAK,IAAI,UAAS;AAGxB,QAAI,OAAO,aAAa;AACtB,iBAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,WAAW,GAAG;AAE/D,YAAI,CAAC,OAAO,MAAM;AAChB,UAAC,OAAe,OAAO;AAAA,QACzB;AACA,WAAG,eAAe,QAAQ,SAAS,SAAS;AAAA,MAC9C;AAAA,IACF;AAGA,QAAI,OAAO,SAAS;AAClB,iBAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,OAAO,GAAG;AAC3D,WAAG,eAAe,MAAM;AAAA,MAC1B;AAAA,IACF;AAGA,QAAI,OAAO,OAAO;AAChB,iBAAW,QAAQ,OAAO,OAAO;AAC/B,WAAG,GAAG,KAAK,OAAO,KAAK,QAAQ,KAAK,OAAO;AAAA,MAC7C;AAAA,IACF;AAGA,UAAM,GAAG,KAAK;AAEd,WAAO;AAAA,EACT;AACF;AAAA;AAAA;AAAA;AAAA;AAvtCa,UAgjBa,mBAAmB;AAhjBtC,IAAM,WAAN;AAguCA,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YACU,YACA,SACA,QACR;AAHQ;AACA;AACA;AAAA,EACP;AAAA,EAEH,MAAM,KAAK,QAAa,CAAC,GAAmB;AAC1C,WAAO,KAAK,OAAO,KAAK,KAAK,YAAY;AAAA,MACvC,GAAG;AAAA,MACH,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,QAAQ,QAAa,CAAC,GAAiB;AAC3C,WAAO,KAAK,OAAO,QAAQ,KAAK,YAAY;AAAA,MAC1C,GAAG;AAAA,MACH,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,OAAO,MAAyB;AACpC,WAAO,KAAK,OAAO,OAAO,KAAK,YAAY,MAAM;AAAA,MAC/C,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,OAAO,MAAyB;AACpC,WAAO,KAAK,OAAO,IAAI;AAAA,EACzB;AAAA,EAEA,MAAM,OAAO,MAAW,UAAe,CAAC,GAAiB;AACvD,WAAO,KAAK,OAAO,OAAO,KAAK,YAAY,MAAM;AAAA,MAC/C,GAAG;AAAA,MACH,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,WAAW,IAAqB,MAAyB;AAC7D,WAAO,KAAK,OAAO,OAAO,KAAK,YAAY,EAAE,GAAG,MAAM,GAAO,GAAG;AAAA,MAC9D,QAAQ,EAAE,GAAO;AAAA,MACjB,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,OAAO,UAAe,CAAC,GAAiB;AAC5C,WAAO,KAAK,OAAO,OAAO,KAAK,YAAY;AAAA,MACzC,GAAG;AAAA,MACH,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,WAAW,IAAmC;AAClD,WAAO,KAAK,OAAO,OAAO,KAAK,YAAY;AAAA,MACzC,QAAQ,EAAE,GAAO;AAAA,MACjB,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAM,QAAa,CAAC,GAAoB;AAC5C,WAAO,KAAK,OAAO,MAAM,KAAK,YAAY;AAAA,MACxC,GAAG;AAAA,MACH,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,UAAU,QAAa,CAAC,GAAmB;AAC/C,WAAO,KAAK,OAAO,UAAU,KAAK,YAAY;AAAA,MAC5C,GAAG;AAAA,MACH,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,QAAQ,YAAoB,QAA4B;AAC5D,QAAI,KAAK,OAAO,eAAe;AAC7B,aAAO,KAAK,OAAO,cAAc,KAAK,YAAY,YAAY;AAAA,QAC5D,GAAG;AAAA,QACH,QAAQ,KAAK,QAAQ;AAAA,QACrB,UAAU,KAAK,QAAQ;AAAA,QACvB,OAAO,KAAK,QAAQ;AAAA,MACtB,CAAC;AAAA,IACH;AACA,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AACF;AASO,IAAM,gBAAN,MAAM,eAAc;AAAA,EACzB,YACU,kBACA,QACR;AAFQ;AACA;AAAA,EACP;AAAA;AAAA,EAGH,OAAO,MAAgC;AACrC,WAAO,IAAI,iBAAiB,MAAM,KAAK,kBAAkB,KAAK,MAAa;AAAA,EAC7E;AAAA;AAAA,EAGA,OAAsB;AACpB,WAAO,IAAI;AAAA,MACT,EAAE,GAAG,KAAK,kBAAkB,UAAU,KAAK;AAAA,MAC3C,KAAK;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,YAAY,UAAiE;AACjF,UAAM,SAAS,KAAK;AAGpB,UAAM,SAAS,OAAO,gBAClB,OAAO,SAAS,IAAI,OAAO,aAAa,IACxC;AAEJ,QAAI,CAAC,QAAQ,kBAAkB;AAE7B,aAAO,SAAS,IAAI;AAAA,IACtB;AAEA,UAAM,MAAM,MAAM,OAAO,iBAAiB;AAC1C,UAAM,SAAS,IAAI;AAAA,MACjB,EAAE,GAAG,KAAK,kBAAkB,aAAa,IAAI;AAAA,MAC7C,KAAK;AAAA,IACP;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,MAAM;AACpC,UAAI,OAAO,OAAQ,OAAM,OAAO,OAAO,GAAG;AAAA,eACjC,OAAO,kBAAmB,OAAM,OAAO,kBAAkB,GAAG;AACrE,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,OAAO,SAAU,OAAM,OAAO,SAAS,GAAG;AAAA,eACrC,OAAO,oBAAqB,OAAM,OAAO,oBAAoB,GAAG;AACzE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,IAAI,SAAS;AAAE,WAAO,KAAK,iBAAiB;AAAA,EAAQ;AAAA,EACpD,IAAI,WAAW;AAAE,WAAO,KAAK,iBAAiB;AAAA,EAAU;AAAA;AAAA,EAExD,IAAI,UAAU;AAAE,WAAO,KAAK,iBAAiB;AAAA,EAAU;AAAA,EACvD,IAAI,QAAQ;AAAE,WAAO,KAAK,iBAAiB;AAAA,EAAO;AAAA,EAClD,IAAI,WAAW;AAAE,WAAO,KAAK,iBAAiB;AAAA,EAAU;AAAA;AAAA,EAGxD,IAAI,oBAAoB;AAAE,WAAO,KAAK,iBAAiB;AAAA,EAAa;AACtE;;;AC57CO,IAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA,EAI1B,MAAM,SAAS,MAAc,MAAc,MAA0B;AACnE,UAAM,aAAa,OAAO,SAAS,YAAY,SAAS,OACpD,EAAE,GAAG,MAAM,MAAM,KAAK,QAAQ,KAAK,IACnC;AACJ,QAAI,SAAS,UAAU;AACrB,qBAAe,aAAa,MAAM,YAAY,MAAa;AAAA,IAC7D,OAAO;AACL,qBAAe,aAAa,MAAM,YAAY,WAAW,KAAK,OAAc,MAAa;AAAA,IAC3F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IAAI,MAAc,MAA4B;AAClD,UAAM,OAAO,eAAe,QAAQ,MAAM,IAAI;AAC9C,WAAO,MAAM,WAAW;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,MAAc,MAAmB;AACxC,WAAO,eAAe,QAAQ,MAAM,IAAI;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,MAA8B;AACvC,UAAM,QAAQ,eAAe,UAAU,IAAI;AAC3C,WAAO,MAAM,IAAI,CAAC,SAAc,MAAM,WAAW,IAAI;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,MAAc,MAA6B;AAC1D,mBAAe,eAAe,MAAM,IAAI;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,MAAc,MAAgC;AACzD,UAAM,OAAO,eAAe,QAAQ,MAAM,IAAI;AAC9C,WAAO,SAAS,UAAa,SAAS;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,MAAiC;AAC/C,UAAM,QAAQ,eAAe,UAAU,IAAI;AAC3C,WAAO,MAAM,IAAI,CAAC,SAAc,MAAM,QAAQ,MAAM,SAAS,QAAQ,EAAE,EAAE,OAAO,OAAO;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,aAAoC;AAC1D,mBAAe,2BAA2B,WAAW;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,MAA4B;AAC1C,WAAO,eAAe,UAAU,IAAI;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAA8B;AAClC,WAAO,eAAe,cAAc;AAAA,EACtC;AACF;;;ACtFO,IAAM,iBAAN,MAAuC;AAAA,EAQ5C,YAAY,IAAe,aAAmC;AAP9D,gBAAO;AACP,gBAAO;AACP,mBAAU;AAcV,gBAAO,OAAO,QAAuB;AACnC,UAAI,CAAC,KAAK,IAAI;AAEV,cAAM,UAAU,EAAE,GAAG,KAAK,aAAa,QAAQ,IAAI,OAAO;AAC1D,aAAK,KAAK,IAAI,SAAS,OAAO;AAAA,MAClC;AAGA,UAAI,gBAAgB,YAAY,KAAK,EAAE;AAGvC,UAAI,cAAc;AAClB,UAAI,mBAAmB;AACvB,UAAI;AACA,YAAI,IAAI,WAAW,UAAU,GAAG;AAC5B,wBAAc;AACd,6BAAmB;AAAA,QACvB;AAAA,MACJ,SAAS,GAAQ;AAAA,MAEjB;AAEA,UAAI,CAAC,aAAa;AACd,YAAI;AACA,gBAAM,iBAAiB,IAAI,eAAe;AAC1C,cAAI,gBAAgB,YAAY,cAAc;AAC9C,cAAI,OAAO,KAAK,iDAAiD;AAAA,YAC7D,MAAM;AAAA,YACN,UAAU,CAAC,YAAY,aAAa;AAAA,UACxC,CAAC;AAAA,QACL,SAAS,GAAQ;AAEZ,cAAI,CAAC,EAAE,SAAS,SAAS,oBAAoB,GAAG;AAC5C,kBAAM;AAAA,UACV;AAAA,QACL;AAAA,MACJ,OAAO;AACH,YAAI,OAAO,KAAK,sCAAsC;AAAA,UAClD,UAAU;AAAA,UACV,MAAM;AAAA,QACV,CAAC;AAAA,MACL;AAEA,UAAI,gBAAgB,QAAQ,KAAK,EAAE;AAEnC,UAAI,OAAO,KAAK,8BAA8B;AAAA,QAC1C,UAAU,CAAC,YAAY,MAAM;AAAA,QAC7B;AAAA,MACJ,CAAC;AAGD,YAAM,eAAe,IAAI;AAAA,QACvB,KAAK;AAAA,QACL,MAAM,IAAI,cAAc,IAAI,YAAY,IAAI,oBAAI,IAAI;AAAA,MACtD;AAEA,UAAI,gBAAgB,YAAY,YAAY;AAC5C,UAAI,OAAO,KAAK,6BAA6B;AAAA,IAC/C;AAEA,iBAAQ,OAAO,QAAuB;AACpC,UAAI,OAAO,KAAK,6BAA6B;AAG7C,UAAI;AACA,cAAM,kBAAkB,IAAI,WAAW,UAAU;AAEjD,YAAI,mBAAmB,EAAE,2BAA2B,mBAAmB,KAAK,IAAI;AAC5E,gBAAM,KAAK,wBAAwB,iBAAiB,GAAG;AAAA,QAC3D;AAAA,MACJ,SAAS,GAAQ;AAEb,YAAI,OAAO,MAAM,2CAA2C;AAAA,MAChE;AAGA,UAAI,IAAI,eAAe,KAAK,IAAI;AAC5B,cAAM,WAAW,IAAI,YAAY;AACjC,mBAAW,CAAC,MAAM,OAAO,KAAK,SAAS,QAAQ,GAAG;AAC9C,cAAI,KAAK,WAAW,SAAS,GAAG;AAE3B,iBAAK,GAAG,eAAe,OAAO;AAC9B,gBAAI,OAAO,MAAM,4CAA4C,EAAE,aAAa,KAAK,CAAC;AAAA,UACvF;AACA,cAAI,KAAK,WAAW,MAAM,GAAG;AAEzB,iBAAK,GAAG,YAAY,OAAO;AAC3B,gBAAI,OAAO,MAAM,yCAAyC,EAAE,aAAa,KAAK,CAAC;AAAA,UACnF;AAAA,QACJ;AAAA,MACJ;AAGA,YAAM,KAAK,IAAI,KAAK;AAKpB,YAAM,KAAK,sBAAsB,GAAG;AAGpC,WAAK,mBAAmB,GAAG;AAG3B,WAAK,yBAAyB,GAAG;AAEjC,UAAI,OAAO,KAAK,2BAA2B;AAAA,QACvC,mBAAmB,KAAK,KAAK,SAAS,GAAG,QAAQ;AAAA,QACjD,mBAAmB,KAAK,IAAI,UAAU,gBAAgB,GAAG,UAAU;AAAA,MACvE,CAAC;AAAA,IACH;AAtHE,QAAI,IAAI;AACJ,WAAK,KAAK;AAAA,IACd,OAAO;AACH,WAAK,cAAc;AAAA,IAEvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAsHQ,mBAAmB,KAAoB;AAC7C,QAAI,CAAC,KAAK,GAAI;AAGd,SAAK,GAAG,aAAa,gBAAgB,OAAO,YAAY;AACtD,UAAI,QAAQ,SAAS,UAAU,QAAQ,OAAO,MAAM;AAClD,cAAM,OAAO,QAAQ,MAAM;AAC3B,YAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,eAAK,aAAa,KAAK,cAAc,QAAQ,QAAQ;AACrD,eAAK,aAAa,QAAQ,QAAQ;AAClC,eAAK,aAAa,KAAK,eAAc,oBAAI,KAAK,GAAE,YAAY;AAC5D,eAAK,cAAa,oBAAI,KAAK,GAAE,YAAY;AACzC,cAAI,QAAQ,QAAQ,UAAU;AAC5B,iBAAK,YAAY,KAAK,aAAa,QAAQ,QAAQ;AAAA,UACrD;AAAA,QACF;AAAA,MACF;AAAA,IACF,GAAG,EAAE,QAAQ,KAAK,UAAU,GAAG,CAAC;AAGhC,SAAK,GAAG,aAAa,gBAAgB,OAAO,YAAY;AACtD,UAAI,QAAQ,SAAS,UAAU,QAAQ,OAAO,MAAM;AAClD,cAAM,OAAO,QAAQ,MAAM;AAC3B,YAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,eAAK,aAAa,QAAQ,QAAQ;AAClC,eAAK,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,QAC3C;AAAA,MACF;AAAA,IACF,GAAG,EAAE,QAAQ,KAAK,UAAU,GAAG,CAAC;AAGhC,SAAK,GAAG,aAAa,gBAAgB,OAAO,YAAY;AACtD,UAAI,QAAQ,OAAO,MAAM,CAAC,QAAQ,UAAU;AAC1C,YAAI;AACF,gBAAM,WAAW,MAAM,KAAK,GAAI,QAAQ,QAAQ,QAAQ;AAAA,YACtD,QAAQ,EAAE,IAAI,QAAQ,MAAM,GAAG;AAAA,UACjC,CAAC;AACD,cAAI,UAAU;AACZ,oBAAQ,WAAW;AAAA,UACrB;AAAA,QACF,SAAS,IAAI;AAAA,QAEb;AAAA,MACF;AAAA,IACF,GAAG,EAAE,QAAQ,KAAK,UAAU,EAAE,CAAC;AAG/B,SAAK,GAAG,aAAa,gBAAgB,OAAO,YAAY;AACtD,UAAI,QAAQ,OAAO,MAAM,CAAC,QAAQ,UAAU;AAC1C,YAAI;AACF,gBAAM,WAAW,MAAM,KAAK,GAAI,QAAQ,QAAQ,QAAQ;AAAA,YACtD,QAAQ,EAAE,IAAI,QAAQ,MAAM,GAAG;AAAA,UACjC,CAAC;AACD,cAAI,UAAU;AACZ,oBAAQ,WAAW;AAAA,UACrB;AAAA,QACF,SAAS,IAAI;AAAA,QAEb;AAAA,MACF;AAAA,IACF,GAAG,EAAE,QAAQ,KAAK,UAAU,EAAE,CAAC;AAE/B,QAAI,OAAO,MAAM,8DAA8D;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,yBAAyB,KAAoB;AACnD,QAAI,CAAC,KAAK,GAAI;AAEd,SAAK,GAAG,mBAAmB,OAAO,OAAO,SAAS;AAEhD,UAAI,CAAC,MAAM,SAAS,YAAY,MAAM,SAAS,UAAU;AACvD,eAAO,KAAK;AAAA,MACd;AAGA,UAAI,CAAC,QAAQ,WAAW,SAAS,WAAW,EAAE,SAAS,MAAM,SAAS,GAAG;AACvE,YAAI,MAAM,KAAK;AACb,gBAAM,eAAe,EAAE,WAAW,MAAM,QAAQ,SAAS;AACzD,cAAI,MAAM,IAAI,OAAO;AACnB,kBAAM,IAAI,QAAQ,EAAE,MAAM,CAAC,MAAM,IAAI,OAAO,YAAY,EAAE;AAAA,UAC5D,OAAO;AACL,kBAAM,IAAI,QAAQ;AAAA,UACpB;AAAA,QACF;AAAA,MACF;AAEA,YAAM,KAAK;AAAA,IACb,CAAC;AAED,QAAI,OAAO,MAAM,wCAAwC;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAc,sBAAsB,KAAoB;AACtD,QAAI,CAAC,KAAK,GAAI;AAEd,UAAM,aAAa,KAAK,GAAG,UAAU,gBAAgB,KAAK,CAAC;AAC3D,QAAI,WAAW,WAAW,EAAG;AAE7B,QAAI,SAAS;AACb,QAAI,UAAU;AAEd,eAAW,OAAO,YAAY;AAC5B,YAAM,SAAS,KAAK,GAAG,mBAAmB,IAAI,IAAI;AAClD,UAAI,CAAC,QAAQ;AACX,YAAI,OAAO,MAAM,wDAAwD;AAAA,UACvE,QAAQ,IAAI;AAAA,QACd,CAAC;AACD;AACA;AAAA,MACF;AAEA,UAAI,OAAO,OAAO,eAAe,YAAY;AAC3C,YAAI,OAAO,MAAM,gDAAgD;AAAA,UAC/D,QAAQ,IAAI;AAAA,UACZ,QAAQ,OAAO;AAAA,QACjB,CAAC;AACD;AACA;AAAA,MACF;AAKA,YAAM,YAAY,IAAI,aAAa,IAAI;AAEvC,UAAI;AACF,cAAM,OAAO,WAAW,WAAW,GAAG;AACtC;AAAA,MACF,SAAS,GAAY;AACnB,YAAI,OAAO,KAAK,oCAAoC;AAAA,UAClD,QAAQ,IAAI;AAAA,UACZ;AAAA,UACA,QAAQ,OAAO;AAAA,UACf,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,QAClD,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,SAAS,KAAK,UAAU,GAAG;AAC7B,UAAI,OAAO,KAAK,wBAAwB,EAAE,QAAQ,SAAS,OAAO,WAAW,OAAO,CAAC;AAAA,IACvF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,wBAAwB,iBAAsB,KAAoB;AAC9E,QAAI,OAAO,KAAK,kEAAkE;AAGlF,UAAM,gBAAgB,CAAC,UAAU,QAAQ,OAAO,QAAQ,YAAY,UAAU;AAC9E,QAAI,cAAc;AAElB,eAAW,QAAQ,eAAe;AAC9B,UAAI;AAEA,YAAI,OAAO,gBAAgB,aAAa,YAAY;AAChD,gBAAM,QAAQ,MAAM,gBAAgB,SAAS,IAAI;AAEjD,cAAI,SAAS,MAAM,SAAS,GAAG;AAC3B,kBAAM,QAAQ,CAAC,SAAc;AAEzB,oBAAM,WAAW,KAAK,KAAK,OAAO;AAGlC,kBAAI,SAAS,YAAY,KAAK,IAAI;AAG9B;AAAA,cACJ;AAGA,kBAAI,KAAK,IAAI,UAAU,cAAc;AACjC,qBAAK,GAAG,SAAS,aAAa,MAAM,MAAM,QAAQ;AAAA,cACtD;AAAA,YACJ,CAAC;AAED,2BAAe,MAAM;AACrB,gBAAI,OAAO,KAAK,UAAU,MAAM,MAAM,IAAI,IAAI,2BAA2B;AAAA,UAC7E;AAAA,QACJ;AAAA,MACJ,SAAS,GAAQ;AAEb,YAAI,OAAO,MAAM,MAAM,IAAI,oCAAoC;AAAA,UAC3D,OAAO,EAAE;AAAA,QACb,CAAC;AAAA,MACL;AAAA,IACJ;AAEA,QAAI,cAAc,GAAG;AACjB,UAAI,OAAO,KAAK,2BAA2B,WAAW,sCAAsC;AAAA,IAChG;AAAA,EACF;AACF;;;AC5VA,SAAS,oBAAoB;AA+B7B,eAAsB,qBAAqB,UAAiC,CAAC,GAA0B;AACrG,QAAM,SAAS,IAAI,aAAa;AAGhC,QAAM,OAAO,IAAI,IAAI,eAAe,CAAC;AAGrC,MAAI,QAAQ,SAAS;AACnB,eAAW,UAAU,QAAQ,SAAS;AACpC,YAAM,OAAO,IAAI,MAAM;AAAA,IACzB;AAAA,EACF;AAEA,SAAO;AACT;;;ACwBO,SAAS,YAAY,KAAqB;AAC/C,SAAO,IACJ,QAAQ,MAAM,GAAG,EACjB,QAAQ,SAAS,CAAC,SAAS,KAAK,YAAY,CAAC;AAClD;AAKA,SAAS,2BACP,QACoF;AACpF,QAAM,OAAO,OAAO,YAAY;AAGhC,MAAI,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,SAAS,KAAK,KAAK,SAAS,MAAM,GAAG;AAC9E,QAAI,KAAK,SAAS,MAAM,EAAG,QAAO;AAClC,WAAO;AAAA,EACT;AAGA,MACE,KAAK,SAAS,KAAK,KAAK,SAAS,aAAa,SAAS,YAAY,SAAS,YAC5E;AACA,WAAO;AAAA,EACT;AACA,MACE,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,SAAS,KAC5E,KAAK,SAAS,SAAS,KAAK,SAAS,QACrC;AACA,WAAO;AAAA,EACT;AAGA,MAAI,KAAK,SAAS,MAAM,GAAG;AACzB,WAAO;AAAA,EACT;AAGA,MAAI,KAAK,SAAS,WAAW,KAAK,SAAS,YAAY;AACrD,WAAO;AAAA,EACT;AACA,MAAI,SAAS,QAAQ;AACnB,WAAO;AAAA,EACT;AACA,MAAI,SAAS,QAAQ;AACnB,WAAO;AAAA,EACT;AAGA,MAAI,SAAS,UAAU,SAAS,SAAS;AACvC,WAAO;AAAA,EACT;AAGA,SAAO;AACT;AAoBO,SAAS,mCACd,oBACA,SAQiB;AACjB,QAAM,UAA2B,CAAC;AAClC,QAAM,gBAAgB,SAAS,iBAAiB,CAAC;AACjD,QAAM,gBAAgB,SAAS;AAC/B,QAAM,oBAAoB,SAAS,sBAAsB;AAEzD,aAAW,CAAC,WAAW,KAAK,KAAK,OAAO,QAAQ,mBAAmB,MAAM,GAAG;AAC1E,QAAI,cAAc,SAAS,SAAS,EAAG;AACvC,QAAI,iBAAiB,CAAC,cAAc,SAAS,SAAS,EAAG;AAEzD,UAAM,SAA8B,CAAC;AAErC,eAAW,UAAU,MAAM,SAAS;AAElC,UAAI,qBAAqB,CAAC,MAAM,cAAc,YAAY,EAAE,SAAS,OAAO,IAAI,GAAG;AACjF;AAAA,MACF;AAGA,YAAM,aAAa,MAAM,YAAY,KAAK,CAAC,OAAO,GAAG,eAAe,OAAO,IAAI;AAE/E,UAAI,YAAY;AACd,eAAO,OAAO,IAAI,IAAI;AAAA,UACpB,MAAM,OAAO;AAAA,UACb,MAAM;AAAA,UACN,WAAW,WAAW;AAAA,UACtB,OAAO,YAAY,OAAO,IAAI;AAAA,UAC9B,UAAU,CAAC,OAAO;AAAA,QACpB;AAAA,MACF,OAAO;AACL,cAAM,YAAY,2BAA2B,OAAO,IAAI;AAExD,cAAM,QAA6B;AAAA,UACjC,MAAM,OAAO;AAAA,UACb,MAAM;AAAA,UACN,OAAO,YAAY,OAAO,IAAI;AAAA,UAC9B,UAAU,CAAC,OAAO;AAAA,QACpB;AAEA,YAAI,OAAO,UAAU;AACnB,gBAAM,SAAS;AAAA,QACjB;AACA,YAAI,OAAO,cAAc,cAAc,UAAU,cAAc,aAAa;AAC1E,gBAAM,YAAY,OAAO;AAAA,QAC3B;AACA,YAAI,OAAO,gBAAgB,MAAM;AAC/B,gBAAM,eAAe,OAAO;AAAA,QAC9B;AAEA,eAAO,OAAO,IAAI,IAAI;AAAA,MACxB;AAAA,IACF;AAEA,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAO,YAAY,SAAS;AAAA,MAC5B;AAAA,IACF,CAAkB;AAAA,EACpB;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/registry.ts","../src/protocol.ts","../src/engine.ts","../src/metadata-facade.ts","../src/plugin.ts","../src/kernel-factory.ts","../src/util.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ServiceObject, ObjectSchema, ObjectOwnership } from '@objectstack/spec/data';\nimport { ObjectStackManifest, ManifestSchema, InstalledPackage, InstalledPackageSchema } from '@objectstack/spec/kernel';\nimport { AppSchema } from '@objectstack/spec/ui';\n\n/**\n * Reserved namespaces that do not get FQN prefix applied.\n * Objects in these namespaces keep their short names (e.g., \"user\" not \"base__user\").\n */\nexport const RESERVED_NAMESPACES = new Set(['base', 'system']);\n\n/**\n * Default priorities for ownership types.\n */\nexport const DEFAULT_OWNER_PRIORITY = 100;\nexport const DEFAULT_EXTENDER_PRIORITY = 200;\n\n/**\n * Contributor Record\n * Tracks how a package contributes to an object (own or extend).\n */\nexport interface ObjectContributor {\n packageId: string;\n namespace: string;\n ownership: ObjectOwnership;\n priority: number;\n definition: ServiceObject;\n}\n\n/**\n * Compute Fully Qualified Name (FQN) for an object.\n * \n * @param namespace - The package namespace (e.g., \"crm\", \"todo\")\n * @param shortName - The object's short name (e.g., \"task\", \"account\")\n * @returns FQN string (e.g., \"crm__task\") or just shortName for reserved namespaces\n * \n * @example\n * computeFQN('crm', 'account') // => 'crm__account'\n * computeFQN('base', 'user') // => 'user' (reserved, no prefix)\n * computeFQN(undefined, 'task') // => 'task' (legacy, no namespace)\n */\nexport function computeFQN(namespace: string | undefined, shortName: string): string {\n if (!namespace || RESERVED_NAMESPACES.has(namespace)) {\n return shortName;\n }\n return `${namespace}__${shortName}`;\n}\n\n/**\n * Parse FQN back to namespace and short name.\n * \n * @param fqn - Fully qualified name (e.g., \"crm__account\" or \"user\")\n * @returns { namespace, shortName } - namespace is undefined for unprefixed names\n */\nexport function parseFQN(fqn: string): { namespace: string | undefined; shortName: string } {\n const idx = fqn.indexOf('__');\n if (idx === -1) {\n return { namespace: undefined, shortName: fqn };\n }\n return {\n namespace: fqn.slice(0, idx),\n shortName: fqn.slice(idx + 2),\n };\n}\n\n/**\n * Deep merge two ServiceObject definitions.\n * Fields are merged additively. Other props: later value wins.\n */\nfunction mergeObjectDefinitions(base: ServiceObject, extension: Partial<ServiceObject>): ServiceObject {\n const merged = { ...base };\n\n // Merge fields additively\n if (extension.fields) {\n merged.fields = { ...base.fields, ...extension.fields };\n }\n\n // Merge validations additively\n if (extension.validations) {\n merged.validations = [...(base.validations || []), ...extension.validations];\n }\n\n // Merge indexes additively\n if (extension.indexes) {\n merged.indexes = [...(base.indexes || []), ...extension.indexes];\n }\n\n // Override scalar props (last writer wins)\n if (extension.label !== undefined) merged.label = extension.label;\n if (extension.pluralLabel !== undefined) merged.pluralLabel = extension.pluralLabel;\n if (extension.description !== undefined) merged.description = extension.description;\n\n return merged;\n}\n\n/**\n * Global Schema Registry\n * Unified storage for all metadata types (Objects, Apps, Flows, Layouts, etc.)\n * \n * ## Namespace & Ownership Model\n * \n * Objects use a namespace-based FQN system:\n * - `namespace`: Short identifier from package manifest (e.g., \"crm\", \"todo\")\n * - `FQN`: `{namespace}__{short_name}` (e.g., \"crm__account\")\n * - Reserved namespaces (`base`, `system`) don't get prefixed\n * \n * Ownership modes:\n * - `own`: One package owns the object (creates the table, defines base schema)\n * - `extend`: Multiple packages can extend an object (add fields, merge by priority)\n * \n * ## Package vs App Distinction\n * - **Package**: The unit of installation, stored under type 'package'.\n * Each InstalledPackage wraps a ManifestSchema with lifecycle state.\n * - **App**: A UI navigation shell (AppSchema), registered under type 'apps'.\n * Apps are extracted from packages during registration.\n * - A package may contain 0, 1, or many apps.\n */\nexport type RegistryLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\n\nexport class SchemaRegistry {\n // ==========================================\n // Logging control\n // ==========================================\n\n /** Controls verbosity of registry console messages. Default: 'info'. */\n private static _logLevel: RegistryLogLevel = 'info';\n\n static get logLevel(): RegistryLogLevel { return this._logLevel; }\n static set logLevel(level: RegistryLogLevel) { this._logLevel = level; }\n\n private static log(msg: string): void {\n if (this._logLevel === 'silent' || this._logLevel === 'error' || this._logLevel === 'warn') return;\n console.log(msg);\n }\n\n // ==========================================\n // Object-specific storage (Ownership Model)\n // ==========================================\n \n /** FQN → Contributor[] (all packages that own/extend this object) */\n private static objectContributors = new Map<string, ObjectContributor[]>();\n \n /** FQN → Merged ServiceObject (cached, invalidated on changes) */\n private static mergedObjectCache = new Map<string, ServiceObject>();\n \n /** Namespace → PackageId (ensures namespace uniqueness) */\n private static namespaceRegistry = new Map<string, string>();\n\n // ==========================================\n // Generic metadata storage (non-object types)\n // ==========================================\n \n /** Type → Name/ID → MetadataItem */\n private static metadata = new Map<string, Map<string, any>>();\n\n // ==========================================\n // Namespace Management\n // ==========================================\n\n /**\n * Register a namespace for a package.\n * Enforces namespace uniqueness within the instance.\n * \n * @throws Error if namespace is already registered to a different package\n */\n static registerNamespace(namespace: string, packageId: string): void {\n if (!namespace) return;\n \n const existing = this.namespaceRegistry.get(namespace);\n if (existing && existing !== packageId) {\n throw new Error(\n `Namespace \"${namespace}\" is already registered to package \"${existing}\". ` +\n `Package \"${packageId}\" cannot use the same namespace.`\n );\n }\n \n this.namespaceRegistry.set(namespace, packageId);\n this.log(`[Registry] Registered namespace: ${namespace} → ${packageId}`);\n }\n\n /**\n * Unregister a namespace when a package is uninstalled.\n */\n static unregisterNamespace(namespace: string, packageId: string): void {\n const existing = this.namespaceRegistry.get(namespace);\n if (existing === packageId) {\n this.namespaceRegistry.delete(namespace);\n this.log(`[Registry] Unregistered namespace: ${namespace}`);\n }\n }\n\n /**\n * Get the package that owns a namespace.\n */\n static getNamespaceOwner(namespace: string): string | undefined {\n return this.namespaceRegistry.get(namespace);\n }\n\n // ==========================================\n // Object Registration (Ownership Model)\n // ==========================================\n\n /**\n * Register an object with ownership semantics.\n * \n * @param schema - The object definition\n * @param packageId - The owning package ID\n * @param namespace - The package namespace (for FQN computation)\n * @param ownership - 'own' (single owner) or 'extend' (additive merge)\n * @param priority - Merge priority (lower applied first, higher wins on conflict)\n * \n * @throws Error if trying to 'own' an object that already has an owner\n */\n static registerObject(\n schema: ServiceObject,\n packageId: string,\n namespace?: string,\n ownership: ObjectOwnership = 'own',\n priority: number = ownership === 'own' ? DEFAULT_OWNER_PRIORITY : DEFAULT_EXTENDER_PRIORITY\n ): string {\n const shortName = schema.name;\n const fqn = computeFQN(namespace, shortName);\n\n // Ensure namespace is registered\n if (namespace) {\n this.registerNamespace(namespace, packageId);\n }\n\n // Get or create contributor list\n let contributors = this.objectContributors.get(fqn);\n if (!contributors) {\n contributors = [];\n this.objectContributors.set(fqn, contributors);\n }\n\n // Validate ownership rules\n if (ownership === 'own') {\n const existingOwner = contributors.find(c => c.ownership === 'own');\n if (existingOwner && existingOwner.packageId !== packageId) {\n throw new Error(\n `Object \"${fqn}\" is already owned by package \"${existingOwner.packageId}\". ` +\n `Package \"${packageId}\" cannot claim ownership. Use 'extend' to add fields.`\n );\n }\n // Remove existing owner contribution from same package (re-registration)\n const idx = contributors.findIndex(c => c.packageId === packageId && c.ownership === 'own');\n if (idx !== -1) {\n contributors.splice(idx, 1);\n console.warn(`[Registry] Re-registering owned object: ${fqn} from ${packageId}`);\n }\n } else {\n // extend mode: remove existing extension from same package\n const idx = contributors.findIndex(c => c.packageId === packageId && c.ownership === 'extend');\n if (idx !== -1) {\n contributors.splice(idx, 1);\n }\n }\n\n // Add new contributor\n const contributor: ObjectContributor = {\n packageId,\n namespace: namespace || '',\n ownership,\n priority,\n definition: { ...schema, name: fqn }, // Store with FQN as name\n };\n contributors.push(contributor);\n\n // Sort by priority (ascending: lower priority applied first)\n contributors.sort((a, b) => a.priority - b.priority);\n\n // Invalidate merge cache\n this.mergedObjectCache.delete(fqn);\n\n this.log(`[Registry] Registered object: ${fqn} (${ownership}, priority=${priority}) from ${packageId}`);\n return fqn;\n }\n\n /**\n * Resolve an object by FQN, merging all contributions.\n * Returns the merged object or undefined if not found.\n */\n static resolveObject(fqn: string): ServiceObject | undefined {\n // Check cache first\n const cached = this.mergedObjectCache.get(fqn);\n if (cached) return cached;\n\n const contributors = this.objectContributors.get(fqn);\n if (!contributors || contributors.length === 0) {\n return undefined;\n }\n\n // Find owner (must exist for a valid object)\n const ownerContrib = contributors.find(c => c.ownership === 'own');\n if (!ownerContrib) {\n console.warn(`[Registry] Object \"${fqn}\" has extenders but no owner. Skipping.`);\n return undefined;\n }\n\n // Start with owner's definition\n let merged = { ...ownerContrib.definition };\n\n // Apply extensions in priority order (already sorted)\n for (const contrib of contributors) {\n if (contrib.ownership === 'extend') {\n merged = mergeObjectDefinitions(merged, contrib.definition);\n }\n }\n\n // Cache the result\n this.mergedObjectCache.set(fqn, merged);\n return merged;\n }\n\n /**\n * Get object by name (FQN, short name, or physical table name).\n *\n * Resolution order:\n * 1. Exact FQN match (e.g., 'crm__account')\n * 2. Short name fallback (e.g., 'account' → 'crm__account')\n * 3. Physical table name match (e.g., 'sys_user' → 'sys__user')\n * ObjectSchema.create() auto-derives tableName as {namespace}_{name},\n * which uses a single underscore — different from the FQN double underscore.\n */\n static getObject(name: string): ServiceObject | undefined {\n // Direct FQN lookup\n const direct = this.resolveObject(name);\n if (direct) return direct;\n\n // Fallback: scan for objects ending with the short name\n // This handles legacy code that doesn't use FQN\n for (const fqn of this.objectContributors.keys()) {\n const { shortName } = parseFQN(fqn);\n if (shortName === name) {\n return this.resolveObject(fqn);\n }\n }\n\n // Fallback: match by physical table name (e.g., 'sys_user' → FQN 'sys__user')\n // This bridges the gap between protocol names (SystemObjectName) and FQN.\n for (const fqn of this.objectContributors.keys()) {\n const resolved = this.resolveObject(fqn);\n if (resolved?.tableName === name) {\n return resolved;\n }\n }\n\n return undefined;\n }\n\n /**\n * Get all registered objects (merged).\n * \n * @param packageId - Optional filter: only objects contributed by this package\n */\n static getAllObjects(packageId?: string): ServiceObject[] {\n const results: ServiceObject[] = [];\n\n for (const fqn of this.objectContributors.keys()) {\n // If filtering by package, check if this package contributes\n if (packageId) {\n const contributors = this.objectContributors.get(fqn);\n const hasContribution = contributors?.some(c => c.packageId === packageId);\n if (!hasContribution) continue;\n }\n\n const merged = this.resolveObject(fqn);\n if (merged) {\n // Tag with contributor info for UI\n (merged as any)._packageId = this.getObjectOwner(fqn)?.packageId;\n results.push(merged);\n }\n }\n\n return results;\n }\n\n /**\n * Get all contributors for an object.\n */\n static getObjectContributors(fqn: string): ObjectContributor[] {\n return this.objectContributors.get(fqn) || [];\n }\n\n /**\n * Get the owner contributor for an object.\n */\n static getObjectOwner(fqn: string): ObjectContributor | undefined {\n const contributors = this.objectContributors.get(fqn);\n return contributors?.find(c => c.ownership === 'own');\n }\n\n /**\n * Unregister all objects contributed by a package.\n * \n * @throws Error if trying to uninstall an owner that has extenders\n */\n static unregisterObjectsByPackage(packageId: string, force: boolean = false): void {\n for (const [fqn, contributors] of this.objectContributors.entries()) {\n // Find this package's contributions\n const packageContribs = contributors.filter(c => c.packageId === packageId);\n \n for (const contrib of packageContribs) {\n if (contrib.ownership === 'own' && !force) {\n // Check if there are extenders from other packages\n const otherExtenders = contributors.filter(\n c => c.packageId !== packageId && c.ownership === 'extend'\n );\n if (otherExtenders.length > 0) {\n throw new Error(\n `Cannot uninstall package \"${packageId}\": object \"${fqn}\" is extended by ` +\n `${otherExtenders.map(c => c.packageId).join(', ')}. Uninstall extenders first.`\n );\n }\n }\n\n // Remove contribution\n const idx = contributors.indexOf(contrib);\n if (idx !== -1) {\n contributors.splice(idx, 1);\n this.log(`[Registry] Removed ${contrib.ownership} contribution to ${fqn} from ${packageId}`);\n }\n }\n\n // Clean up empty contributor lists\n if (contributors.length === 0) {\n this.objectContributors.delete(fqn);\n }\n\n // Invalidate cache\n this.mergedObjectCache.delete(fqn);\n }\n }\n\n // ==========================================\n // Generic Metadata (Non-Object Types)\n // ==========================================\n\n /**\n * Universal Register Method for non-object metadata.\n */\n static registerItem<T>(type: string, item: T, keyField: keyof T = 'name' as keyof T, packageId?: string) {\n if (!this.metadata.has(type)) {\n this.metadata.set(type, new Map());\n }\n const collection = this.metadata.get(type)!;\n const baseName = String(item[keyField]);\n \n // Tag item with owning package for scoped queries\n if (packageId) {\n (item as any)._packageId = packageId;\n }\n\n // Validation Hook\n try {\n this.validate(type, item);\n } catch (e: any) {\n console.error(`[Registry] Validation failed for ${type} ${baseName}: ${e.message}`);\n }\n\n // Use composite key (packageId:name) when packageId is provided\n const storageKey = packageId ? `${packageId}:${baseName}` : baseName;\n\n if (collection.has(storageKey)) {\n console.warn(`[Registry] Overwriting ${type}: ${storageKey}`);\n }\n collection.set(storageKey, item);\n this.log(`[Registry] Registered ${type}: ${storageKey}`);\n }\n\n /**\n * Validate Metadata against Spec Zod Schemas\n */\n static validate(type: string, item: any) {\n if (type === 'object') {\n return ObjectSchema.parse(item);\n }\n if (type === 'apps') {\n return AppSchema.parse(item);\n }\n if (type === 'package') {\n return InstalledPackageSchema.parse(item);\n }\n if (type === 'plugin') {\n return ManifestSchema.parse(item);\n }\n return true;\n }\n\n /**\n * Universal Unregister Method\n */\n static unregisterItem(type: string, name: string) {\n const collection = this.metadata.get(type);\n if (!collection) {\n console.warn(`[Registry] Attempted to unregister non-existent ${type}: ${name}`);\n return;\n }\n if (collection.has(name)) {\n collection.delete(name);\n this.log(`[Registry] Unregistered ${type}: ${name}`);\n return;\n }\n // Scan composite keys\n for (const key of collection.keys()) {\n if (key.endsWith(`:${name}`)) {\n collection.delete(key);\n this.log(`[Registry] Unregistered ${type}: ${key}`);\n return;\n }\n }\n console.warn(`[Registry] Attempted to unregister non-existent ${type}: ${name}`);\n }\n\n /**\n * Universal Get Method\n */\n static getItem<T>(type: string, name: string): T | undefined {\n // Special handling for 'object' and 'objects' types - use objectContributors\n if (type === 'object' || type === 'objects') {\n return this.getObject(name) as unknown as T | undefined;\n }\n \n const collection = this.metadata.get(type);\n if (!collection) return undefined;\n const direct = collection.get(name);\n if (direct) return direct as T;\n // Scan for composite keys\n for (const [key, item] of collection) {\n if (key.endsWith(`:${name}`)) return item as T;\n }\n return undefined;\n }\n\n /**\n * Universal List Method\n */\n static listItems<T>(type: string, packageId?: string): T[] {\n // Special handling for 'object' and 'objects' types - use objectContributors\n if (type === 'object' || type === 'objects') {\n return this.getAllObjects(packageId) as unknown as T[];\n }\n \n const items = Array.from(this.metadata.get(type)?.values() || []) as T[];\n if (packageId) {\n return items.filter((item: any) => item._packageId === packageId);\n }\n return items;\n }\n\n /**\n * Get all registered metadata types (Kinds)\n */\n static getRegisteredTypes(): string[] {\n const types = Array.from(this.metadata.keys());\n // Always include 'object' even if stored separately\n if (!types.includes('object') && this.objectContributors.size > 0) {\n types.push('object');\n }\n return types;\n }\n\n // ==========================================\n // Package Management\n // ==========================================\n\n static installPackage(manifest: ObjectStackManifest, settings?: Record<string, any>): InstalledPackage {\n const now = new Date().toISOString();\n const pkg: InstalledPackage = {\n manifest,\n status: 'installed',\n enabled: true,\n installedAt: now,\n updatedAt: now,\n settings,\n };\n \n // Register namespace if present\n if (manifest.namespace) {\n this.registerNamespace(manifest.namespace, manifest.id);\n }\n \n if (!this.metadata.has('package')) {\n this.metadata.set('package', new Map());\n }\n const collection = this.metadata.get('package')!;\n if (collection.has(manifest.id)) {\n console.warn(`[Registry] Overwriting package: ${manifest.id}`);\n }\n collection.set(manifest.id, pkg);\n this.log(`[Registry] Installed package: ${manifest.id} (${manifest.name})`);\n return pkg;\n }\n\n static uninstallPackage(id: string): boolean {\n const pkg = this.getPackage(id);\n if (!pkg) {\n console.warn(`[Registry] Package not found for uninstall: ${id}`);\n return false;\n }\n\n // Unregister namespace\n if (pkg.manifest.namespace) {\n this.unregisterNamespace(pkg.manifest.namespace, id);\n }\n\n // Unregister objects (will throw if extenders exist)\n this.unregisterObjectsByPackage(id);\n\n // Remove package record\n const collection = this.metadata.get('package');\n if (collection) {\n collection.delete(id);\n this.log(`[Registry] Uninstalled package: ${id}`);\n return true;\n }\n return false;\n }\n\n static getPackage(id: string): InstalledPackage | undefined {\n return this.metadata.get('package')?.get(id) as InstalledPackage | undefined;\n }\n\n static getAllPackages(): InstalledPackage[] {\n return this.listItems<InstalledPackage>('package');\n }\n\n static enablePackage(id: string): InstalledPackage | undefined {\n const pkg = this.getPackage(id);\n if (pkg) {\n pkg.enabled = true;\n pkg.status = 'installed';\n pkg.statusChangedAt = new Date().toISOString();\n pkg.updatedAt = new Date().toISOString();\n this.log(`[Registry] Enabled package: ${id}`);\n }\n return pkg;\n }\n\n static disablePackage(id: string): InstalledPackage | undefined {\n const pkg = this.getPackage(id);\n if (pkg) {\n pkg.enabled = false;\n pkg.status = 'disabled';\n pkg.statusChangedAt = new Date().toISOString();\n pkg.updatedAt = new Date().toISOString();\n this.log(`[Registry] Disabled package: ${id}`);\n }\n return pkg;\n }\n\n // ==========================================\n // App Helpers\n // ==========================================\n\n static registerApp(app: any, packageId?: string) {\n this.registerItem('apps', app, 'name', packageId);\n }\n\n static getApp(name: string): any {\n return this.getItem('apps', name);\n }\n\n static getAllApps(): any[] {\n return this.listItems('apps');\n }\n\n // ==========================================\n // Plugin Helpers\n // ==========================================\n\n static registerPlugin(manifest: ObjectStackManifest) {\n this.registerItem('plugin', manifest, 'id');\n }\n\n static getAllPlugins(): ObjectStackManifest[] {\n return this.listItems<ObjectStackManifest>('plugin');\n }\n\n // ==========================================\n // Kind Helpers\n // ==========================================\n\n static registerKind(kind: { id: string, globs: string[] }) {\n this.registerItem('kind', kind, 'id');\n }\n \n static getAllKinds(): { id: string, globs: string[] }[] {\n return this.listItems('kind');\n }\n\n // ==========================================\n // Reset (for testing)\n // ==========================================\n\n /**\n * Clear all registry state. Use only for testing.\n */\n static reset(): void {\n this.objectContributors.clear();\n this.mergedObjectCache.clear();\n this.namespaceRegistry.clear();\n this.metadata.clear();\n this.log('[Registry] Reset complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { IDataEngine } from '@objectstack/core';\nimport type { \n BatchUpdateRequest, \n BatchUpdateResponse, \n UpdateManyDataRequest,\n DeleteManyDataRequest\n} from '@objectstack/spec/api';\nimport type { MetadataCacheRequest, MetadataCacheResponse, ServiceInfo, ApiRoutes, WellKnownCapabilities } from '@objectstack/spec/api';\nimport type { IFeedService } from '@objectstack/spec/contracts';\nimport { parseFilterAST, isFilterAST } from '@objectstack/spec/data';\n\n// We import SchemaRegistry directly since this class lives in the same package\nimport { SchemaRegistry } from './registry.js';\n\n/**\n * Simple hash function for ETag generation (browser-compatible)\n * Uses a basic hash algorithm instead of crypto.createHash\n */\nfunction simpleHash(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return Math.abs(hash).toString(16);\n}\n\n/**\n * Service Configuration for Discovery\n * Maps service names to their routes and plugin providers\n */\nconst SERVICE_CONFIG: Record<string, { route: string; plugin: string }> = {\n auth: { route: '/api/v1/auth', plugin: 'plugin-auth' },\n automation: { route: '/api/v1/automation', plugin: 'plugin-automation' },\n cache: { route: '/api/v1/cache', plugin: 'plugin-redis' },\n queue: { route: '/api/v1/queue', plugin: 'plugin-bullmq' },\n job: { route: '/api/v1/jobs', plugin: 'job-scheduler' },\n ui: { route: '/api/v1/ui', plugin: 'ui-plugin' },\n workflow: { route: '/api/v1/workflow', plugin: 'plugin-workflow' },\n realtime: { route: '/api/v1/realtime', plugin: 'plugin-realtime' },\n notification: { route: '/api/v1/notifications', plugin: 'plugin-notifications' },\n ai: { route: '/api/v1/ai', plugin: 'plugin-ai' },\n i18n: { route: '/api/v1/i18n', plugin: 'service-i18n' },\n graphql: { route: '/graphql', plugin: 'plugin-graphql' }, // GraphQL uses /graphql by convention (not versioned REST)\n 'file-storage': { route: '/api/v1/storage', plugin: 'plugin-storage' },\n search: { route: '/api/v1/search', plugin: 'plugin-search' },\n};\n\nexport class ObjectStackProtocolImplementation implements ObjectStackProtocol {\n private engine: IDataEngine;\n private getServicesRegistry?: () => Map<string, any>;\n private getFeedService?: () => IFeedService | undefined;\n\n constructor(engine: IDataEngine, getServicesRegistry?: () => Map<string, any>, getFeedService?: () => IFeedService | undefined) {\n this.engine = engine;\n this.getServicesRegistry = getServicesRegistry;\n this.getFeedService = getFeedService;\n }\n\n private requireFeedService(): IFeedService {\n const svc = this.getFeedService?.();\n if (!svc) {\n throw new Error('Feed service not available. Install and register service-feed to enable feed operations.');\n }\n return svc;\n }\n\n async getDiscovery() {\n // Get registered services from kernel if available\n const registeredServices = this.getServicesRegistry ? this.getServicesRegistry() : new Map();\n \n // Build dynamic service info with proper typing\n const services: Record<string, ServiceInfo> = {\n // --- Kernel-provided (objectql is an example kernel implementation) ---\n metadata: { enabled: true, status: 'degraded' as const, route: '/api/v1/meta', provider: 'objectql', message: 'In-memory registry only; DB persistence not yet implemented' },\n data: { enabled: true, status: 'available' as const, route: '/api/v1/data', provider: 'objectql' },\n analytics: { enabled: true, status: 'available' as const, route: '/api/v1/analytics', provider: 'objectql' },\n };\n\n // Check which services are actually registered\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n // Service is registered and available\n services[serviceName] = {\n enabled: true,\n status: 'available' as const,\n route: config.route,\n provider: config.plugin,\n };\n } else {\n // Service is not registered\n services[serviceName] = {\n enabled: false,\n status: 'unavailable' as const,\n message: `Install ${config.plugin} to enable`,\n };\n }\n }\n\n // Build routes from services — a flat convenience map for client routing\n const serviceToRouteKey: Record<string, keyof ApiRoutes> = {\n auth: 'auth',\n automation: 'automation',\n ui: 'ui',\n workflow: 'workflow',\n realtime: 'realtime',\n notification: 'notifications',\n ai: 'ai',\n i18n: 'i18n',\n graphql: 'graphql',\n 'file-storage': 'storage',\n };\n\n const optionalRoutes: Partial<ApiRoutes> = {\n analytics: '/api/v1/analytics',\n };\n\n // Add routes for available plugin services\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n const routeKey = serviceToRouteKey[serviceName];\n if (routeKey) {\n optionalRoutes[routeKey] = config.route;\n }\n }\n }\n\n // Add feed service status\n if (registeredServices.has('feed')) {\n services['feed'] = {\n enabled: true,\n status: 'available' as const,\n route: '/api/v1/data',\n provider: 'service-feed',\n };\n } else {\n services['feed'] = {\n enabled: false,\n status: 'unavailable' as const,\n message: 'Install service-feed to enable',\n };\n }\n\n const routes: ApiRoutes = {\n data: '/api/v1/data',\n metadata: '/api/v1/meta',\n ...optionalRoutes,\n };\n\n // Build well-known capabilities from registered services\n const capabilities: WellKnownCapabilities = {\n feed: registeredServices.has('feed'),\n comments: registeredServices.has('feed'),\n automation: registeredServices.has('automation'),\n cron: registeredServices.has('job'),\n search: registeredServices.has('search'),\n export: registeredServices.has('automation') || registeredServices.has('queue'),\n chunkedUpload: registeredServices.has('file-storage'),\n };\n\n return {\n version: '1.0',\n apiName: 'ObjectStack API',\n routes,\n services,\n capabilities,\n };\n }\n\n async getMetaTypes() {\n return {\n types: SchemaRegistry.getRegisteredTypes()\n };\n }\n\n async getMetaItems(request: { type: string }) {\n let items = SchemaRegistry.listItems(request.type);\n // Normalize singular/plural: REST uses singular ('app') but registry may store as plural ('apps')\n if (items.length === 0) {\n const alt = request.type.endsWith('s') ? request.type.slice(0, -1) : request.type + 's';\n items = SchemaRegistry.listItems(alt);\n }\n return {\n type: request.type,\n items\n };\n }\n\n async getMetaItem(request: { type: string, name: string }) {\n let item = SchemaRegistry.getItem(request.type, request.name);\n // Normalize singular/plural\n if (item === undefined) {\n const alt = request.type.endsWith('s') ? request.type.slice(0, -1) : request.type + 's';\n item = SchemaRegistry.getItem(alt, request.name);\n }\n return {\n type: request.type,\n name: request.name,\n item\n };\n }\n\n async getUiView(request: { object: string, type: 'list' | 'form' }) {\n const schema = SchemaRegistry.getObject(request.object);\n if (!schema) throw new Error(`Object ${request.object} not found`);\n\n const fields = schema.fields || {};\n const fieldKeys = Object.keys(fields);\n\n if (request.type === 'list') {\n // Intelligent Column Selection\n // 1. Always include 'name' or name-like fields\n // 2. Limit to 6 columns by default\n const priorityFields = ['name', 'title', 'label', 'subject', 'email', 'status', 'type', 'category', 'created_at'];\n \n let columns = fieldKeys.filter(k => priorityFields.includes(k));\n \n // If few priority fields, add others until 5\n if (columns.length < 5) {\n const remaining = fieldKeys.filter(k => !columns.includes(k) && k !== 'id' && !fields[k].hidden);\n columns = [...columns, ...remaining.slice(0, 5 - columns.length)];\n }\n \n // Sort columns by priority then alphabet or schema order\n // For now, just keep them roughly in order they appear in schema or priority list\n \n return {\n list: {\n type: 'grid' as const,\n object: request.object,\n label: schema.label || schema.name,\n columns: columns.map(f => ({\n field: f,\n label: fields[f]?.label || f,\n sortable: true\n })),\n sort: fields['created_at'] ? ([{ field: 'created_at', order: 'desc' }] as any) : undefined,\n searchableFields: columns.slice(0, 3) // Make first few textual columns searchable\n }\n };\n } else {\n // Form View Generation\n // Simple single-section layout for now\n const formFields = fieldKeys\n .filter(k => k !== 'id' && k !== 'created_at' && k !== 'updated_at' && !fields[k].hidden)\n .map(f => ({\n field: f,\n label: fields[f]?.label,\n required: fields[f]?.required,\n readonly: fields[f]?.readonly,\n type: fields[f]?.type,\n // Default to 2 columns for most, 1 for textareas\n colSpan: (fields[f]?.type === 'textarea' || fields[f]?.type === 'html') ? 2 : 1\n }));\n\n return {\n form: {\n type: 'simple' as const,\n object: request.object,\n label: `Edit ${schema.label || schema.name}`,\n sections: [\n {\n label: 'General Information',\n columns: 2 as const,\n collapsible: false,\n collapsed: false,\n fields: formFields\n }\n ]\n }\n };\n }\n }\n\n async findData(request: { object: string, query?: any }) {\n const options: any = { ...request.query };\n\n // Numeric fields\n if (options.top != null) options.top = Number(options.top);\n if (options.skip != null) options.skip = Number(options.skip);\n if (options.limit != null) options.limit = Number(options.limit);\n\n // Select: comma-separated string → array\n if (typeof options.select === 'string') {\n options.select = options.select.split(',').map((s: string) => s.trim()).filter(Boolean);\n }\n\n // Sort/orderBy: string → sort array (e.g. \"name asc,created_at desc\" or \"name,-created_at\")\n const sortValue = options.orderBy ?? options.sort;\n if (typeof sortValue === 'string') {\n const parsed = sortValue.split(',').map((part: string) => {\n const trimmed = part.trim();\n if (trimmed.startsWith('-')) {\n return { field: trimmed.slice(1), order: 'desc' as const };\n }\n const [field, order] = trimmed.split(/\\s+/);\n return { field, order: (order?.toLowerCase() === 'desc' ? 'desc' : 'asc') as 'asc' | 'desc' };\n }).filter((s: any) => s.field);\n options.sort = parsed;\n delete options.orderBy;\n }\n\n // Filter: normalize `filter`/`filters` (plural) → `filter` (singular, canonical)\n // Accept both `filter` and `filters` for backward compatibility.\n if (options.filters !== undefined && options.filter === undefined) {\n options.filter = options.filters;\n }\n delete options.filters;\n\n // Filter: JSON string → object\n if (typeof options.filter === 'string') {\n try { options.filter = JSON.parse(options.filter); } catch { /* keep as-is */ }\n }\n\n // Filter AST array → FilterCondition object\n // Converts [\"and\", [\"field\", \"=\", \"val\"], ...] to { $and: [{ field: \"val\" }, ...] }\n if (isFilterAST(options.filter)) {\n options.filter = parseFilterAST(options.filter);\n }\n\n // Populate: comma-separated string → array\n if (typeof options.populate === 'string') {\n options.populate = options.populate.split(',').map((s: string) => s.trim()).filter(Boolean);\n }\n\n // Expand → Populate: normalize $expand/expand to populate array\n // Supports OData $expand, REST expand, and JSON-RPC expand parameters\n const expandValue = options.$expand ?? options.expand;\n if (expandValue && !options.populate) {\n if (typeof expandValue === 'string') {\n options.populate = expandValue.split(',').map((s: string) => s.trim()).filter(Boolean);\n } else if (Array.isArray(expandValue)) {\n options.populate = expandValue;\n }\n }\n delete options.$expand;\n delete options.expand;\n\n // Boolean fields\n for (const key of ['distinct', 'count']) {\n if (options[key] === 'true') options[key] = true;\n else if (options[key] === 'false') options[key] = false;\n }\n \n // Flat field filters: REST-style query params like ?id=abc&status=open\n // After extracting all known query parameters, any remaining keys are\n // treated as implicit field-level equality filters. This is the standard\n // REST convention used by the client when serializing simple filter maps\n // (e.g. `{ filters: { id: \"...\" } }` → `?id=...`).\n const knownParams = new Set([\n 'top', 'skip', 'limit', 'offset',\n 'sort', 'orderBy',\n 'select', 'fields',\n 'filter', 'filters', '$filter',\n 'populate', 'expand', '$expand',\n 'distinct', 'count',\n 'aggregations', 'groupBy',\n 'search', 'context',\n ]);\n if (!options.filter) {\n const implicitFilters: Record<string, unknown> = {};\n for (const key of Object.keys(options)) {\n if (!knownParams.has(key)) {\n implicitFilters[key] = options[key];\n delete options[key];\n }\n }\n if (Object.keys(implicitFilters).length > 0) {\n options.filter = implicitFilters;\n }\n }\n \n const records = await this.engine.find(request.object, options);\n return {\n object: request.object,\n value: records, // OData compaibility\n records, // Legacy\n total: records.length,\n hasMore: false\n };\n }\n\n async getData(request: { object: string, id: string, expand?: string | string[], select?: string | string[] }) {\n const queryOptions: any = {\n filter: { id: request.id }\n };\n\n // Support select for single-record retrieval\n if (request.select) {\n queryOptions.select = typeof request.select === 'string'\n ? request.select.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.select;\n }\n\n // Support expand for single-record retrieval\n if (request.expand) {\n queryOptions.populate = typeof request.expand === 'string'\n ? request.expand.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.expand;\n }\n\n const result = await this.engine.findOne(request.object, queryOptions);\n if (result) {\n return {\n object: request.object,\n id: request.id,\n record: result\n };\n }\n throw new Error(`Record ${request.id} not found in ${request.object}`);\n }\n\n async createData(request: { object: string, data: any }) {\n const result = await this.engine.insert(request.object, request.data);\n return {\n object: request.object,\n id: result.id,\n record: result\n };\n }\n\n async updateData(request: { object: string, id: string, data: any }) {\n // Adapt: update(obj, id, data) -> update(obj, data, options)\n const result = await this.engine.update(request.object, request.data, { filter: { id: request.id } });\n return {\n object: request.object,\n id: request.id,\n record: result\n };\n }\n\n async deleteData(request: { object: string, id: string }) {\n // Adapt: delete(obj, id) -> delete(obj, options)\n await this.engine.delete(request.object, { filter: { id: request.id } });\n return {\n object: request.object,\n id: request.id,\n success: true\n };\n }\n\n // ==========================================\n // Metadata Caching\n // ==========================================\n\n async getMetaItemCached(request: { type: string, name: string, cacheRequest?: MetadataCacheRequest }): Promise<MetadataCacheResponse> {\n try {\n const item = SchemaRegistry.getItem(request.type, request.name);\n if (!item) {\n throw new Error(`Metadata item ${request.type}/${request.name} not found`);\n }\n\n // Calculate ETag (simple hash of the stringified metadata)\n const content = JSON.stringify(item);\n const hash = simpleHash(content);\n const etag = { value: hash, weak: false };\n\n // Check If-None-Match header\n if (request.cacheRequest?.ifNoneMatch) {\n const clientEtag = request.cacheRequest.ifNoneMatch.replace(/^\"(.*)\"$/, '$1').replace(/^W\\/\"(.*)\"$/, '$1');\n if (clientEtag === hash) {\n // Return 304 Not Modified\n return {\n notModified: true,\n etag,\n };\n }\n }\n\n // Return full metadata with cache headers\n return {\n data: item,\n etag,\n lastModified: new Date().toISOString(),\n cacheControl: {\n directives: ['public', 'max-age'],\n maxAge: 3600, // 1 hour\n },\n notModified: false,\n };\n } catch (error: any) {\n throw error;\n }\n }\n\n // ==========================================\n // Batch Operations\n // ==========================================\n\n async batchData(request: { object: string, request: BatchUpdateRequest }): Promise<BatchUpdateResponse> {\n const { object, request: batchReq } = request;\n const { operation, records, options } = batchReq;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n switch (operation) {\n case 'create': {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n succeeded++;\n break;\n }\n case 'update': {\n if (!record.id) throw new Error('Record id is required for update');\n const updated = await this.engine.update(object, record.data || {}, { filter: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n break;\n }\n case 'upsert': {\n // Try update first, then create if not found\n if (record.id) {\n try {\n const existing = await this.engine.findOne(object, { filter: { id: record.id } });\n if (existing) {\n const updated = await this.engine.update(object, record.data || {}, { filter: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n } else {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } catch {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } else {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n }\n succeeded++;\n break;\n }\n case 'delete': {\n if (!record.id) throw new Error('Record id is required for delete');\n await this.engine.delete(object, { filter: { id: record.id } });\n results.push({ id: record.id, success: true });\n succeeded++;\n break;\n }\n default:\n results.push({ id: record.id, success: false, error: `Unknown operation: ${operation}` });\n failed++;\n }\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (options?.atomic) {\n // Abort remaining operations on first failure in atomic mode\n break;\n }\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation,\n total: records.length,\n succeeded,\n failed,\n results: options?.returnRecords !== false ? results : results.map(r => ({ id: r.id, success: r.success, error: r.error })),\n } as BatchUpdateResponse;\n }\n \n async createManyData(request: { object: string, records: any[] }): Promise<any> {\n const records = await this.engine.insert(request.object, request.records);\n return {\n object: request.object,\n records,\n count: records.length\n };\n }\n \n async updateManyData(request: UpdateManyDataRequest): Promise<BatchUpdateResponse> {\n const { object, records, options } = request;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n const updated = await this.engine.update(object, record.data, { filter: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation: 'update',\n total: records.length,\n succeeded,\n failed,\n results,\n } as BatchUpdateResponse;\n }\n\n async analyticsQuery(request: any): Promise<any> {\n // Map AnalyticsQuery (cube-style) to engine aggregation.\n // cube name maps to object name; measures → aggregations; dimensions → groupBy.\n const { query, cube } = request;\n const object = cube;\n\n // Build groupBy from dimensions\n const groupBy = query.dimensions || [];\n\n // Build aggregations from measures\n // Measures can be simple field names like \"count\" or \"field_name.sum\"\n // Or cube-defined measure names. We support: field.function or just function(field).\n const aggregations: Array<{ field: string; method: string; alias: string }> = [];\n if (query.measures) {\n for (const measure of query.measures) {\n // Support formats: \"count\", \"amount.sum\", \"revenue.avg\"\n if (measure === 'count' || measure === 'count_all') {\n aggregations.push({ field: '*', method: 'count', alias: 'count' });\n } else if (measure.includes('.')) {\n const [field, method] = measure.split('.');\n aggregations.push({ field, method, alias: `${field}_${method}` });\n } else {\n // Treat as count of the field\n aggregations.push({ field: measure, method: 'sum', alias: measure });\n }\n }\n }\n\n // Build filter from analytics filters\n let filter: any = undefined;\n if (query.filters && query.filters.length > 0) {\n const conditions: any[] = query.filters.map((f: any) => {\n const op = this.mapAnalyticsOperator(f.operator);\n if (f.values && f.values.length === 1) {\n return { [f.member]: { [op]: f.values[0] } };\n } else if (f.values && f.values.length > 1) {\n return { [f.member]: { $in: f.values } };\n }\n return { [f.member]: { [op]: true } };\n });\n filter = conditions.length === 1 ? conditions[0] : { $and: conditions };\n }\n\n // Execute via engine.aggregate (which delegates to driver.find with groupBy/aggregations)\n const rows = await this.engine.aggregate(object, {\n filter,\n groupBy: groupBy.length > 0 ? groupBy : undefined,\n aggregations: aggregations.length > 0\n ? aggregations.map(a => ({ field: a.field, method: a.method as any, alias: a.alias }))\n : [{ field: '*', method: 'count' as any, alias: 'count' }],\n });\n\n // Build field metadata\n const fields = [\n ...groupBy.map((d: string) => ({ name: d, type: 'string' })),\n ...aggregations.map(a => ({ name: a.alias, type: 'number' })),\n ];\n\n return {\n success: true,\n data: {\n rows,\n fields,\n },\n };\n }\n\n async getAnalyticsMeta(request: any): Promise<any> {\n // Auto-generate cube metadata from registered objects in SchemaRegistry.\n // Each object becomes a cube; number fields → measures; other fields → dimensions.\n const objects = SchemaRegistry.listItems('object');\n const cubeFilter = request?.cube;\n\n const cubes: any[] = [];\n for (const obj of objects) {\n const schema = obj as any;\n if (cubeFilter && schema.name !== cubeFilter) continue;\n\n const measures: Record<string, any> = {};\n const dimensions: Record<string, any> = {};\n const fields = schema.fields || {};\n\n // Always add a count measure\n measures['count'] = {\n name: 'count',\n label: 'Count',\n type: 'count',\n sql: '*',\n };\n\n for (const [fieldName, fieldDef] of Object.entries(fields)) {\n const fd = fieldDef as any;\n const fieldType = fd.type || 'text';\n\n if (['number', 'currency', 'percent'].includes(fieldType)) {\n // Numeric fields become both measures and dimensions\n measures[`${fieldName}_sum`] = {\n name: `${fieldName}_sum`,\n label: `${fd.label || fieldName} (Sum)`,\n type: 'sum',\n sql: fieldName,\n };\n measures[`${fieldName}_avg`] = {\n name: `${fieldName}_avg`,\n label: `${fd.label || fieldName} (Avg)`,\n type: 'avg',\n sql: fieldName,\n };\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'number',\n sql: fieldName,\n };\n } else if (['date', 'datetime'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'time',\n sql: fieldName,\n granularities: ['day', 'week', 'month', 'quarter', 'year'],\n };\n } else if (['boolean'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'boolean',\n sql: fieldName,\n };\n } else {\n // text, select, lookup, etc. → dimension\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'string',\n sql: fieldName,\n };\n }\n }\n\n cubes.push({\n name: schema.name,\n title: schema.label || schema.name,\n description: schema.description,\n sql: schema.name,\n measures,\n dimensions,\n public: true,\n });\n }\n\n return {\n success: true,\n data: { cubes },\n };\n }\n\n private mapAnalyticsOperator(op: string): string {\n const map: Record<string, string> = {\n equals: '$eq',\n notEquals: '$ne',\n contains: '$contains',\n notContains: '$notContains',\n gt: '$gt',\n gte: '$gte',\n lt: '$lt',\n lte: '$lte',\n set: '$ne',\n notSet: '$eq',\n };\n return map[op] || '$eq';\n }\n\n async triggerAutomation(_request: any): Promise<any> {\n throw new Error('triggerAutomation requires plugin-automation service. Install and register a plugin that provides the \"automation\" service.');\n }\n\n async deleteManyData(request: DeleteManyDataRequest): Promise<any> {\n // This expects deleting by IDs.\n return this.engine.delete(request.object, {\n filter: { id: { $in: request.ids } },\n ...request.options\n });\n }\n\n async saveMetaItem(request: { type: string, name: string, item?: any }) {\n if (!request.item) {\n throw new Error('Item data is required');\n }\n // Default implementation saves to Memory Registry\n SchemaRegistry.registerItem(request.type, request.item, 'name');\n return {\n success: true,\n message: 'Saved to memory registry'\n };\n }\n\n // ==========================================\n // Feed Operations\n // ==========================================\n\n async listFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n return { success: true, data: result };\n }\n\n async createFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.createFeedItem({\n object: request.object,\n recordId: request.recordId,\n type: request.type,\n actor: { type: 'user', id: 'current_user' },\n body: request.body,\n mentions: request.mentions,\n parentId: request.parentId,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async updateFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.updateFeedItem(request.feedId, {\n body: request.body,\n mentions: request.mentions,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async deleteFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n await svc.deleteFeedItem(request.feedId);\n return { success: true, data: { feedId: request.feedId } };\n }\n\n async addReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.addReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async removeReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.removeReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async pinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated pin/unpin — use updateFeedItem to persist pin state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: true, pinnedAt: new Date().toISOString() } };\n }\n\n async unpinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: false } };\n }\n\n async starFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated star/unstar — verify item exists then return state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: true, starredAt: new Date().toISOString() } };\n }\n\n async unstarFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: false } };\n }\n\n async searchFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Search delegates to listFeed with filter since IFeedService doesn't have a dedicated search\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n // Filter by query text in body\n const queryLower = (request.query || '').toLowerCase();\n const filtered = result.items.filter((item: any) =>\n item.body?.toLowerCase().includes(queryLower)\n );\n return { success: true, data: { items: filtered, total: filtered.length, hasMore: false } };\n }\n\n async getChangelog(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Changelog retrieves field_change type feed items\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: 'changes_only',\n limit: request.limit,\n cursor: request.cursor,\n });\n const entries = result.items.map((item: any) => ({\n id: item.id,\n object: item.object,\n recordId: item.recordId,\n actor: item.actor,\n changes: item.changes || [],\n timestamp: item.createdAt,\n source: item.source,\n }));\n return { success: true, data: { entries, total: result.total, nextCursor: result.nextCursor, hasMore: result.hasMore } };\n }\n\n async feedSubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const subscription = await svc.subscribe({\n object: request.object,\n recordId: request.recordId,\n userId: 'current_user',\n events: request.events,\n channels: request.channels,\n });\n return { success: true, data: subscription };\n }\n\n async feedUnsubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const unsubscribed = await svc.unsubscribe(request.object, request.recordId, 'current_user');\n return { success: true, data: { object: request.object, recordId: request.recordId, unsubscribed } };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { QueryAST, HookContext, ServiceObject } from '@objectstack/spec/data';\nimport { \n DataEngineQueryOptions, \n DataEngineInsertOptions, \n DataEngineUpdateOptions, \n DataEngineDeleteOptions,\n DataEngineAggregateOptions,\n DataEngineCountOptions \n} from '@objectstack/spec/data';\nimport { ExecutionContext, ExecutionContextSchema } from '@objectstack/spec/kernel';\nimport { DriverInterface, IDataEngine, Logger, createLogger } from '@objectstack/core';\nimport { CoreServiceName } from '@objectstack/spec/system';\nimport { SchemaRegistry } from './registry.js';\n\nexport type HookHandler = (context: HookContext) => Promise<void> | void;\n\n/**\n * Per-object hook entry with priority support\n */\nexport interface HookEntry {\n handler: HookHandler;\n object?: string | string[]; // undefined = global hook\n priority: number;\n packageId?: string;\n}\n\n/**\n * Operation Context for Middleware Chain\n */\nexport interface OperationContext {\n object: string;\n operation: 'find' | 'findOne' | 'insert' | 'update' | 'delete' | 'count' | 'aggregate';\n ast?: QueryAST;\n data?: any;\n options?: any;\n context?: ExecutionContext;\n result?: any;\n}\n\n/**\n * Engine Middleware (Onion model)\n */\nexport type EngineMiddleware = (\n ctx: OperationContext,\n next: () => Promise<void>\n) => Promise<void>;\n\n/**\n * Host Context provided to plugins (Internal ObjectQL Plugin System)\n */\nexport interface ObjectQLHostContext {\n ql: ObjectQL;\n logger: Logger;\n // Extensible map for host-specific globals (like HTTP Router, etc.)\n [key: string]: any;\n}\n\n/**\n * ObjectQL Engine\n * \n * Implements the IDataEngine interface for data persistence.\n * Acts as the reference implementation for:\n * - CoreServiceName.data (CRUD)\n * - CoreServiceName.metadata (Schema Registry)\n */\nexport class ObjectQL implements IDataEngine {\n private drivers = new Map<string, DriverInterface>();\n private defaultDriver: string | null = null;\n private logger: Logger;\n \n // Per-object hooks with priority support\n private hooks: Map<string, HookEntry[]> = new Map([\n ['beforeFind', []], ['afterFind', []],\n ['beforeInsert', []], ['afterInsert', []],\n ['beforeUpdate', []], ['afterUpdate', []],\n ['beforeDelete', []], ['afterDelete', []],\n ]);\n\n // Middleware chain (onion model)\n private middlewares: Array<{\n fn: EngineMiddleware;\n object?: string;\n }> = [];\n\n // Action registry: key = \"objectName:actionName\"\n private actions = new Map<string, { handler: (ctx: any) => Promise<any> | any; package?: string }>();\n \n // Host provided context additions (e.g. Server router)\n private hostContext: Record<string, any> = {};\n\n constructor(hostContext: Record<string, any> = {}) {\n this.hostContext = hostContext;\n // Use provided logger or create a new one\n this.logger = hostContext.logger || createLogger({ level: 'info', format: 'pretty' });\n this.logger.info('ObjectQL Engine Instance Created');\n }\n\n /**\n * Service Status Report\n * Used by Kernel to verify health and capabilities.\n */\n getStatus() {\n return {\n name: CoreServiceName.enum.data,\n status: 'running',\n version: '0.9.0',\n features: ['crud', 'query', 'aggregate', 'transactions', 'metadata']\n };\n }\n\n /**\n * Expose the SchemaRegistry for plugins to register metadata\n */\n get registry() {\n return SchemaRegistry;\n }\n\n /**\n * Load and Register a Plugin\n */\n async use(manifestPart: any, runtimePart?: any) {\n this.logger.debug('Loading plugin', { \n hasManifest: !!manifestPart, \n hasRuntime: !!runtimePart \n });\n\n // 1. Validate / Register Manifest\n if (manifestPart) {\n this.registerApp(manifestPart);\n }\n\n // 2. Execute Runtime\n if (runtimePart) {\n const pluginDef = (runtimePart as any).default || runtimePart;\n if (pluginDef.onEnable) {\n this.logger.debug('Executing plugin runtime onEnable');\n \n const context: ObjectQLHostContext = {\n ql: this,\n logger: this.logger,\n // Expose the driver registry helper explicitly if needed\n drivers: {\n register: (driver: DriverInterface) => this.registerDriver(driver)\n },\n ...this.hostContext\n };\n \n await pluginDef.onEnable(context);\n this.logger.debug('Plugin runtime onEnable completed');\n }\n }\n }\n\n /**\n * Register a hook\n * @param event The event name (e.g. 'beforeFind', 'afterInsert')\n * @param handler The handler function\n * @param options Optional: target object(s) and priority\n */\n registerHook(event: string, handler: HookHandler, options?: {\n object?: string | string[];\n priority?: number;\n packageId?: string;\n }) {\n if (!this.hooks.has(event)) {\n this.hooks.set(event, []);\n }\n const entries = this.hooks.get(event)!;\n entries.push({\n handler,\n object: options?.object,\n priority: options?.priority ?? 100,\n packageId: options?.packageId,\n });\n // Sort by priority (lower runs first)\n entries.sort((a, b) => a.priority - b.priority);\n this.logger.debug('Registered hook', { event, object: options?.object, priority: options?.priority ?? 100, totalHandlers: entries.length });\n }\n\n public async triggerHooks(event: string, context: HookContext) {\n const entries = this.hooks.get(event) || [];\n \n if (entries.length === 0) {\n this.logger.debug('No hooks registered for event', { event });\n return;\n }\n\n this.logger.debug('Triggering hooks', { event, count: entries.length });\n \n for (const entry of entries) {\n // Per-object matching\n if (entry.object) {\n const targets = Array.isArray(entry.object) ? entry.object : [entry.object];\n if (!targets.includes('*') && !targets.includes(context.object)) {\n continue; // Skip non-matching hooks\n }\n }\n await entry.handler(context);\n }\n }\n\n // ========================================\n // Action System\n // ========================================\n\n /**\n * Register a named action on an object.\n * Actions are custom business logic callable via `repo.execute(actionName, params)`.\n *\n * @param objectName Target object\n * @param actionName Unique action name within the object\n * @param handler Handler function\n * @param packageName Optional package owner (for cleanup)\n */\n registerAction(objectName: string, actionName: string, handler: (ctx: any) => Promise<any> | any, packageName?: string): void {\n const key = `${objectName}:${actionName}`;\n this.actions.set(key, { handler, package: packageName });\n this.logger.debug('Registered action', { objectName, actionName, package: packageName });\n }\n\n /**\n * Execute a named action on an object.\n */\n async executeAction(objectName: string, actionName: string, ctx: any): Promise<any> {\n const entry = this.actions.get(`${objectName}:${actionName}`);\n if (!entry) {\n throw new Error(`Action '${actionName}' on object '${objectName}' not found`);\n }\n return entry.handler(ctx);\n }\n\n /**\n * Remove all actions registered by a specific package.\n */\n removeActionsByPackage(packageName: string): void {\n for (const [key, entry] of this.actions.entries()) {\n if (entry.package === packageName) {\n this.actions.delete(key);\n }\n }\n }\n\n /**\n * Register a middleware function\n * Middlewares execute in onion model around every data operation.\n * @param fn The middleware function\n * @param options Optional: target object filter\n */\n registerMiddleware(fn: EngineMiddleware, options?: { object?: string }): void {\n this.middlewares.push({ fn, object: options?.object });\n this.logger.debug('Registered middleware', { object: options?.object, total: this.middlewares.length });\n }\n\n /**\n * Execute an operation through the middleware chain\n */\n private async executeWithMiddleware(ctx: OperationContext, executor: () => Promise<any>): Promise<any> {\n const applicable = this.middlewares.filter(m =>\n !m.object || m.object === '*' || m.object === ctx.object\n );\n\n let index = 0;\n const next = async (): Promise<void> => {\n if (index < applicable.length) {\n const mw = applicable[index++];\n await mw.fn(ctx, next);\n } else {\n ctx.result = await executor();\n }\n };\n\n await next();\n return ctx.result;\n }\n\n /**\n * Build a HookContext.session from ExecutionContext\n */\n private buildSession(execCtx?: ExecutionContext): HookContext['session'] {\n if (!execCtx) return undefined;\n return {\n userId: execCtx.userId,\n tenantId: execCtx.tenantId,\n roles: execCtx.roles,\n accessToken: execCtx.accessToken,\n };\n }\n\n /**\n * Register contribution (Manifest)\n * \n * Installs the manifest as a Package (the unit of installation),\n * then decomposes it into individual metadata items (objects, apps, actions, etc.)\n * and registers each into the SchemaRegistry.\n * \n * Key: Package ≠ App. The manifest is the package. The apps[] array inside\n * the manifest contains UI navigation definitions (AppSchema).\n */\n registerApp(manifest: any) {\n const id = manifest.id || manifest.name;\n const namespace = manifest.namespace as string | undefined;\n this.logger.debug('Registering package manifest', { id, namespace });\n\n // 1. Register the Package (manifest + lifecycle state)\n SchemaRegistry.installPackage(manifest);\n this.logger.debug('Installed Package', { id: manifest.id, name: manifest.name, namespace });\n\n // 2. Register owned objects\n if (manifest.objects) {\n if (Array.isArray(manifest.objects)) {\n this.logger.debug('Registering objects from manifest (Array)', { id, objectCount: manifest.objects.length });\n for (const objDef of manifest.objects) {\n const fqn = SchemaRegistry.registerObject(objDef, id, namespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: id });\n }\n } else {\n this.logger.debug('Registering objects from manifest (Map)', { id, objectCount: Object.keys(manifest.objects).length });\n for (const [name, objDef] of Object.entries(manifest.objects)) {\n // Ensure name in definition matches key\n (objDef as any).name = name;\n const fqn = SchemaRegistry.registerObject(objDef as any, id, namespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: id });\n }\n }\n }\n\n // 2b. Register object extensions (fields added to objects owned by other packages)\n if (Array.isArray(manifest.objectExtensions) && manifest.objectExtensions.length > 0) {\n this.logger.debug('Registering object extensions', { id, count: manifest.objectExtensions.length });\n for (const ext of manifest.objectExtensions) {\n const targetFqn = ext.extend;\n const priority = ext.priority ?? 200;\n // Create a partial object definition for the extension\n const extDef = {\n name: targetFqn, // Use the target FQN as name\n fields: ext.fields,\n label: ext.label,\n pluralLabel: ext.pluralLabel,\n description: ext.description,\n validations: ext.validations,\n indexes: ext.indexes,\n };\n // Register as extension (namespace is undefined since we're targeting by FQN)\n SchemaRegistry.registerObject(extDef as any, id, undefined, 'extend', priority);\n this.logger.debug('Registered Object Extension', { target: targetFqn, priority, from: id });\n }\n }\n\n // 3. Register apps (UI navigation definitions) as their own metadata type\n if (Array.isArray(manifest.apps) && manifest.apps.length > 0) {\n this.logger.debug('Registering apps from manifest', { id, count: manifest.apps.length });\n for (const app of manifest.apps) {\n const appName = app.name || app.id;\n if (appName) {\n SchemaRegistry.registerApp(app, id);\n this.logger.debug('Registered App', { app: appName, from: id });\n }\n }\n }\n\n // 4. If manifest itself looks like an App (has navigation), also register as app\n // This handles the case where the manifest IS the app definition (legacy/simple packages)\n if (manifest.name && manifest.navigation && !manifest.apps?.length) {\n SchemaRegistry.registerApp(manifest, id);\n this.logger.debug('Registered manifest-as-app', { app: manifest.name, from: id });\n }\n\n // 5. Register all other metadata types generically\n const metadataArrayKeys = [\n // UI Protocol\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'themes',\n // Automation Protocol\n 'flows', 'workflows', 'approvals', 'webhooks',\n // Security Protocol\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n // AI Protocol\n 'agents', 'ragPipelines',\n // API Protocol\n 'apis',\n // Data Extensions\n 'hooks', 'mappings', 'analyticsCubes',\n // Integration Protocol\n 'connectors',\n ];\n for (const key of metadataArrayKeys) {\n const items = (manifest as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n this.logger.debug(`Registering ${key} from manifest`, { id, count: items.length });\n for (const item of items) {\n const itemName = item.name || item.id;\n if (itemName) {\n SchemaRegistry.registerItem(key, item, 'name' as any, id);\n }\n }\n }\n }\n\n // 6. Register seed data as metadata (keyed by target object name)\n const seedData = (manifest as any).data;\n if (Array.isArray(seedData) && seedData.length > 0) {\n this.logger.debug('Registering seed data datasets', { id, count: seedData.length });\n for (const dataset of seedData) {\n if (dataset.object) {\n SchemaRegistry.registerItem('data', dataset, 'object' as any, id);\n }\n }\n }\n\n // 6. Register contributions\n if (manifest.contributes?.kinds) {\n this.logger.debug('Registering kinds from manifest', { id, kindCount: manifest.contributes.kinds.length });\n for (const kind of manifest.contributes.kinds) {\n SchemaRegistry.registerKind(kind);\n this.logger.debug('Registered Kind', { kind: kind.name || kind.type, from: id });\n }\n }\n\n // 7. Recursively register nested plugins\n if (Array.isArray(manifest.plugins) && manifest.plugins.length > 0) {\n this.logger.debug('Processing nested plugins', { id, count: manifest.plugins.length });\n for (const plugin of manifest.plugins) {\n if (plugin && typeof plugin === 'object') {\n const pluginName = plugin.name || plugin.id || 'unnamed-plugin';\n this.logger.debug('Registering nested plugin', { pluginName, parentId: id });\n this.registerPlugin(plugin, id, namespace);\n }\n }\n }\n }\n\n /**\n * Register a nested plugin's metadata (objects, actions, views, etc.)\n *\n * Unlike registerApp(), this does NOT call SchemaRegistry.installPackage()\n * because plugins are not formal manifests — they are lightweight config\n * bundles with objects, actions, triggers, and navigation.\n *\n * @param plugin - The plugin config object\n * @param parentId - The parent package ID (for ownership tracking)\n * @param parentNamespace - The parent package's namespace (for FQN resolution)\n */\n private registerPlugin(plugin: any, parentId: string, parentNamespace?: string) {\n const pluginName = plugin.name || plugin.id || 'unnamed';\n const pluginNamespace = plugin.namespace || parentNamespace;\n\n // Use parentId as the owning package for namespace consistency.\n // The parent package already claimed the namespace — nested plugins\n // contribute objects UNDER the parent's ownership.\n const ownerId = parentId;\n\n // Register objects (supports both Array and Map formats)\n if (plugin.objects) {\n try {\n if (Array.isArray(plugin.objects)) {\n this.logger.debug('Registering plugin objects (Array)', { pluginName, count: plugin.objects.length });\n for (const objDef of plugin.objects) {\n const fqn = SchemaRegistry.registerObject(objDef, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n } else {\n const entries = Object.entries(plugin.objects);\n this.logger.debug('Registering plugin objects (Map)', { pluginName, count: entries.length });\n for (const [name, objDef] of entries) {\n (objDef as any).name = name;\n const fqn = SchemaRegistry.registerObject(objDef as any, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n }\n } catch (err: any) {\n this.logger.warn('Failed to register plugin objects', { pluginName, error: err.message });\n }\n }\n\n // Register plugin as app if it has navigation (for sidebar display)\n if (plugin.name && plugin.navigation) {\n try {\n SchemaRegistry.registerApp(plugin, ownerId);\n this.logger.debug('Registered plugin-as-app', { app: plugin.name, from: pluginName });\n } catch (err: any) {\n this.logger.warn('Failed to register plugin as app', { pluginName, error: err.message });\n }\n }\n\n // Register metadata arrays (actions, views, triggers, etc.)\n const metadataArrayKeys = [\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'themes',\n 'flows', 'workflows', 'approvals', 'webhooks',\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n 'agents', 'ragPipelines', 'apis',\n 'hooks', 'mappings', 'analyticsCubes', 'connectors',\n ];\n for (const key of metadataArrayKeys) {\n const items = (plugin as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n for (const item of items) {\n const itemName = item.name || item.id;\n if (itemName) {\n SchemaRegistry.registerItem(key, item, 'name' as any, ownerId);\n }\n }\n }\n }\n }\n\n /**\n * Register a new storage driver\n */\n registerDriver(driver: DriverInterface, isDefault: boolean = false) {\n if (this.drivers.has(driver.name)) {\n this.logger.warn('Driver already registered, skipping', { driverName: driver.name });\n return;\n }\n\n this.drivers.set(driver.name, driver);\n this.logger.info('Registered driver', { \n driverName: driver.name, \n version: driver.version\n });\n\n if (isDefault || this.drivers.size === 1) {\n this.defaultDriver = driver.name;\n this.logger.info('Set default driver', { driverName: driver.name });\n }\n }\n\n /**\n * Helper to get object definition\n */\n getSchema(objectName: string): ServiceObject | undefined {\n return SchemaRegistry.getObject(objectName);\n }\n\n /**\n * Resolve an object name to its Fully Qualified Name (FQN).\n * \n * Short names like 'task' are resolved to FQN like 'todo__task'\n * via SchemaRegistry lookup. If no match is found, the name is\n * returned as-is (for ad-hoc / unregistered objects).\n * \n * This ensures that all driver operations use a consistent key\n * regardless of whether the caller uses the short name or FQN.\n */\n private resolveObjectName(name: string): string {\n const schema = SchemaRegistry.getObject(name);\n if (schema) {\n // Prefer the physical table name (e.g., 'sys_user') over the FQN\n // (e.g., 'sys__user'). ObjectSchema.create() auto-derives tableName\n // as {namespace}_{name} which matches the storage convention.\n return schema.tableName || schema.name;\n }\n return name; // Ad-hoc object, keep as-is\n }\n\n /**\n * Helper to get the target driver\n */\n private getDriver(objectName: string): DriverInterface {\n const object = SchemaRegistry.getObject(objectName);\n \n // 1. If object definition exists, check for explicit datasource\n if (object) {\n const datasourceName = object.datasource || 'default';\n \n // If configured for 'default', try to find the default driver\n if (datasourceName === 'default') {\n if (this.defaultDriver && this.drivers.has(this.defaultDriver)) {\n return this.drivers.get(this.defaultDriver)!;\n }\n } else {\n // Specific datasource requested\n if (this.drivers.has(datasourceName)) {\n return this.drivers.get(datasourceName)!;\n }\n throw new Error(`[ObjectQL] Datasource '${datasourceName}' configured for object '${objectName}' is not registered.`);\n }\n }\n\n // 2. Fallback for ad-hoc objects or missing definitions\n if (this.defaultDriver) {\n return this.drivers.get(this.defaultDriver)!;\n }\n\n throw new Error(`[ObjectQL] No driver available for object '${objectName}'`);\n }\n\n /**\n * Initialize the engine and all registered drivers\n */\n async init() {\n this.logger.info('Initializing ObjectQL engine', { \n driverCount: this.drivers.size,\n drivers: Array.from(this.drivers.keys())\n });\n \n for (const [name, driver] of this.drivers) {\n try {\n await driver.connect();\n this.logger.info('Driver connected successfully', { driverName: name });\n } catch (e) {\n this.logger.error('Failed to connect driver', e as Error, { driverName: name });\n }\n }\n \n this.logger.info('ObjectQL engine initialization complete');\n }\n\n async destroy() {\n this.logger.info('Destroying ObjectQL engine', { driverCount: this.drivers.size });\n \n for (const [name, driver] of this.drivers.entries()) {\n try {\n await driver.disconnect();\n } catch (e) {\n this.logger.error('Error disconnecting driver', e as Error, { driverName: name });\n }\n }\n \n this.logger.info('ObjectQL engine destroyed');\n }\n\n // ============================================\n // Helper: Expand Related Records\n // ============================================\n\n /** Maximum depth for recursive expand to prevent infinite loops */\n private static readonly MAX_EXPAND_DEPTH = 3;\n\n /**\n * Post-process expand: resolve lookup/master_detail fields by batch-loading related records.\n * \n * This is a driver-agnostic implementation that uses secondary queries ($in batches)\n * to load related records, then injects them into the result set.\n * \n * @param objectName - The source object name\n * @param records - The records returned by the driver\n * @param expand - The expand map from QueryAST (field name → nested QueryAST)\n * @param depth - Current recursion depth (0-based)\n * @returns Records with expanded lookup fields (IDs replaced by full objects)\n */\n private async expandRelatedRecords(\n objectName: string,\n records: any[],\n expand: Record<string, QueryAST>,\n depth: number = 0,\n ): Promise<any[]> {\n if (!records || records.length === 0) return records;\n if (depth >= ObjectQL.MAX_EXPAND_DEPTH) return records;\n\n const objectSchema = SchemaRegistry.getObject(objectName);\n // If no schema registered, skip expand — return raw data\n if (!objectSchema || !objectSchema.fields) return records;\n\n for (const [fieldName, nestedAST] of Object.entries(expand)) {\n const fieldDef = objectSchema.fields[fieldName];\n\n // Skip if field not found or not a relationship type\n if (!fieldDef || !fieldDef.reference) continue;\n if (fieldDef.type !== 'lookup' && fieldDef.type !== 'master_detail') continue;\n\n const referenceObject = fieldDef.reference;\n\n // Collect all foreign key IDs from records (handle both single and multiple values)\n const allIds: any[] = [];\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n if (Array.isArray(val)) {\n allIds.push(...val.filter((id: any) => id != null));\n } else if (typeof val === 'object') {\n // Already expanded — skip\n continue;\n } else {\n allIds.push(val);\n }\n }\n\n // De-duplicate IDs\n const uniqueIds = [...new Set(allIds)];\n if (uniqueIds.length === 0) continue;\n\n // Batch-load related records using $in query\n try {\n const relatedQuery: QueryAST = {\n object: referenceObject,\n where: { id: { $in: uniqueIds } },\n ...(nestedAST.fields ? { fields: nestedAST.fields } : {}),\n ...(nestedAST.orderBy ? { orderBy: nestedAST.orderBy } : {}),\n };\n\n const driver = this.getDriver(referenceObject);\n const relatedRecords = await driver.find(referenceObject, relatedQuery) ?? [];\n\n // Build a lookup map: id → record\n const recordMap = new Map<string, any>();\n for (const rec of relatedRecords) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n\n // Recursively expand nested relations if present\n if (nestedAST.expand && Object.keys(nestedAST.expand).length > 0) {\n const expandedRelated = await this.expandRelatedRecords(\n referenceObject,\n relatedRecords,\n nestedAST.expand,\n depth + 1,\n );\n // Rebuild map with expanded records\n recordMap.clear();\n for (const rec of expandedRelated) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n }\n\n // Inject expanded records back into the original result set\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n\n if (Array.isArray(val)) {\n record[fieldName] = val.map((id: any) => recordMap.get(String(id)) ?? id);\n } else if (typeof val !== 'object') {\n record[fieldName] = recordMap.get(String(val)) ?? val;\n }\n // If val is already an object, leave it as-is\n }\n } catch (e) {\n // Graceful degradation: if expand fails, keep original IDs\n this.logger.warn('Failed to expand relationship field; retaining foreign key IDs', {\n object: objectName,\n field: fieldName,\n reference: referenceObject,\n error: (e as Error).message,\n });\n }\n }\n\n return records;\n }\n\n // ============================================\n // Helper: Query Conversion\n // ============================================\n\n private toQueryAST(object: string, options?: DataEngineQueryOptions): QueryAST {\n const ast: QueryAST = { object };\n if (!options) return ast;\n\n if (options.filter) {\n ast.where = options.filter;\n }\n if (options.select) {\n ast.fields = options.select;\n }\n if (options.sort) {\n // Support DataEngineSortSchema variant\n if (Array.isArray(options.sort)) {\n // [{ field: 'a', order: 'asc' }]\n ast.orderBy = options.sort; \n } else {\n // Record<string, 'asc' | 'desc' | 1 | -1>\n ast.orderBy = Object.entries(options.sort).map(([field, order]) => ({\n field,\n order: (order === -1 || order === 'desc') ? 'desc' : 'asc'\n }));\n }\n }\n \n if (options.top !== undefined) ast.limit = options.top;\n else if (options.limit !== undefined) ast.limit = options.limit;\n \n if (options.skip !== undefined) ast.offset = options.skip;\n\n // Map populate (relationship field names) to QueryAST expand entries\n if (options.populate && options.populate.length > 0) {\n ast.expand = {};\n for (const rel of options.populate) {\n ast.expand[rel] = { object: rel };\n }\n }\n\n return ast;\n }\n\n // ============================================\n // Data Access Methods (IDataEngine Interface)\n // ============================================\n\n async find(object: string, query?: DataEngineQueryOptions): Promise<any[]> {\n object = this.resolveObjectName(object);\n this.logger.debug('Find operation starting', { object, query });\n const driver = this.getDriver(object);\n const ast = this.toQueryAST(object, query);\n\n const opCtx: OperationContext = {\n object,\n operation: 'find',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeFind',\n input: { ast: opCtx.ast, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeFind', hookContext);\n\n try {\n let result = await driver.find(object, hookContext.input.ast as QueryAST, hookContext.input.options as any);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && Array.isArray(result)) {\n result = await this.expandRelatedRecords(object, result, ast.expand, 0);\n }\n \n hookContext.event = 'afterFind';\n hookContext.result = result;\n await this.triggerHooks('afterFind', hookContext);\n \n return hookContext.result;\n } catch (e) {\n this.logger.error('Find operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result as any[];\n }\n\n async findOne(objectName: string, query?: DataEngineQueryOptions): Promise<any> {\n objectName = this.resolveObjectName(objectName);\n this.logger.debug('FindOne operation', { objectName });\n const driver = this.getDriver(objectName);\n const ast = this.toQueryAST(objectName, query);\n ast.limit = 1;\n\n const opCtx: OperationContext = {\n object: objectName,\n operation: 'findOne',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n let result = await driver.findOne(objectName, opCtx.ast as QueryAST);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && result != null) {\n const expanded = await this.expandRelatedRecords(objectName, [result], ast.expand, 0);\n result = expanded[0];\n }\n\n return result;\n });\n\n return opCtx.result;\n }\n\n async insert(object: string, data: any | any[], options?: DataEngineInsertOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Insert operation starting', { object, isBatch: Array.isArray(data) });\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'insert',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeInsert',\n input: { data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeInsert', hookContext);\n\n try {\n let result;\n if (Array.isArray(hookContext.input.data)) {\n // Bulk Create\n if (driver.bulkCreate) {\n result = await driver.bulkCreate(object, hookContext.input.data as any[], hookContext.input.options as any);\n } else {\n // Fallback loop\n result = await Promise.all((hookContext.input.data as any[]).map((item: any) => driver.create(object, item, hookContext.input.options as any)));\n }\n } else {\n result = await driver.create(object, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n }\n\n hookContext.event = 'afterInsert';\n hookContext.result = result;\n await this.triggerHooks('afterInsert', hookContext);\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Insert operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async update(object: string, data: any, options?: DataEngineUpdateOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Update operation starting', { object });\n const driver = this.getDriver(object);\n \n // 1. Extract ID from data or filter if it's a single update by ID\n let id = data.id;\n if (!id && options?.filter) {\n if (typeof options.filter === 'string') id = options.filter;\n else if (options.filter.id) id = options.filter.id;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'update',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeUpdate',\n input: { id, data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeUpdate', hookContext);\n\n try {\n let result;\n if (hookContext.input.id) {\n result = await driver.update(object, hookContext.input.id as string, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else if (options?.multi && driver.updateMany) {\n const ast = this.toQueryAST(object, { filter: options.filter });\n result = await driver.updateMany(object, ast, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else {\n throw new Error('Update requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterUpdate';\n hookContext.result = result;\n await this.triggerHooks('afterUpdate', hookContext);\n return hookContext.result;\n } catch (e) {\n this.logger.error('Update operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async delete(object: string, options?: DataEngineDeleteOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Delete operation starting', { object });\n const driver = this.getDriver(object);\n\n // Extract ID logic similar to update\n let id: any = undefined;\n if (options?.filter) {\n if (typeof options.filter === 'string') id = options.filter;\n else if (options.filter.id) id = options.filter.id;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'delete',\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeDelete',\n input: { id, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeDelete', hookContext);\n\n try {\n let result;\n if (hookContext.input.id) {\n result = await driver.delete(object, hookContext.input.id as string, hookContext.input.options as any);\n } else if (options?.multi && driver.deleteMany) {\n const ast = this.toQueryAST(object, { filter: options.filter });\n result = await driver.deleteMany(object, ast, hookContext.input.options as any);\n } else {\n throw new Error('Delete requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterDelete';\n hookContext.result = result;\n await this.triggerHooks('afterDelete', hookContext);\n return hookContext.result;\n } catch (e) {\n this.logger.error('Delete operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async count(object: string, query?: DataEngineCountOptions): Promise<number> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'count',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n if (driver.count) {\n const ast = this.toQueryAST(object, { filter: query?.filter });\n return driver.count(object, ast);\n }\n // Fallback to find().length\n const res = await this.find(object, { filter: query?.filter, select: ['id'] });\n return res.length;\n });\n\n return opCtx.result as number;\n }\n\n async aggregate(object: string, query: DataEngineAggregateOptions): Promise<any[]> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n this.logger.debug(`Aggregate on ${object} using ${driver.name}`, query);\n\n const opCtx: OperationContext = {\n object,\n operation: 'aggregate',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const ast: QueryAST = {\n object,\n where: query.filter,\n groupBy: query.groupBy,\n aggregations: query.aggregations?.map(agg => ({\n function: agg.method,\n field: agg.field,\n alias: agg.alias || `${agg.method}_${agg.field || 'all'}`,\n })),\n };\n\n return driver.find(object, ast);\n });\n\n return opCtx.result as any[];\n }\n \n async execute(command: any, options?: Record<string, any>): Promise<any> {\n // Direct pass-through implies we know which driver to use?\n // Usually execute is tied to a specific object context OR we need a way to select driver.\n // If command has 'object', we use that.\n if (options?.object) {\n const driver = this.getDriver(options.object);\n if (driver.execute) {\n return driver.execute(command, undefined, options);\n }\n }\n throw new Error('Execute requires options.object to select driver');\n }\n\n // ============================================\n // Compatibility / Convenience API\n // ============================================\n // These methods provide a higher-level API matching the @objectql/core\n // ObjectQL interface, enabling painless migration from the legacy layer.\n\n /**\n * Register a single object definition.\n * \n * Proxies to SchemaRegistry.registerObject() with sensible defaults.\n * Fields without a `name` property are auto-assigned from their key.\n */\n registerObject(\n schema: ServiceObject,\n packageId: string = '__runtime__',\n namespace?: string\n ): string {\n // Auto-assign field names from keys\n if (schema.fields) {\n for (const [key, field] of Object.entries(schema.fields)) {\n if (field && typeof field === 'object' && !('name' in field)) {\n (field as any).name = key;\n }\n }\n }\n return SchemaRegistry.registerObject(schema, packageId, namespace);\n }\n\n /**\n * Unregister a single object by name.\n */\n unregisterObject(name: string, packageId?: string): void {\n if (packageId) {\n SchemaRegistry.unregisterObjectsByPackage(packageId);\n } else {\n // Remove from generic metadata as fallback\n SchemaRegistry.unregisterItem('object', name);\n }\n }\n\n /**\n * Get an object definition by name.\n * Alias for getSchema() — matches @objectql/core API.\n */\n getObject(name: string): ServiceObject | undefined {\n return this.getSchema(name);\n }\n\n /**\n * Get all registered object configs as a name→config map.\n * Matches @objectql/core getConfigs() API.\n */\n getConfigs(): Record<string, ServiceObject> {\n const result: Record<string, ServiceObject> = {};\n const objects = SchemaRegistry.getAllObjects();\n for (const obj of objects) {\n if (obj.name) {\n result[obj.name] = obj;\n }\n }\n return result;\n }\n\n /**\n * Get a registered driver by datasource name.\n * \n * Unlike the private getDriver() (which resolves by object name),\n * this method directly looks up a driver by its registered name.\n */\n getDriverByName(name: string): DriverInterface | undefined {\n return this.drivers.get(name);\n }\n\n /**\n * Get the driver responsible for the given object.\n *\n * Resolves datasource binding from the object's schema definition,\n * falling back to the default driver. This is a public version of\n * the internal getDriver() used by CRUD operations.\n *\n * @param objectName - FQN or short name of the registered object.\n * @returns The resolved DriverInterface, or undefined if no driver is available.\n */\n getDriverForObject(objectName: string): DriverInterface | undefined {\n try {\n return this.getDriver(objectName);\n } catch {\n return undefined;\n }\n }\n\n /**\n * Get a registered driver by datasource name.\n * Alias matching @objectql/core datasource() API.\n * \n * @throws Error if the datasource is not found\n */\n datasource(name: string): DriverInterface {\n const driver = this.drivers.get(name);\n if (!driver) {\n throw new Error(`[ObjectQL] Datasource '${name}' not found`);\n }\n return driver;\n }\n\n /**\n * Register a hook handler.\n * Convenience alias for registerHook() matching @objectql/core on() API.\n * \n * Usage:\n * ql.on('beforeInsert', 'user', async (ctx) => { ... });\n */\n on(\n event: string,\n objectName: string,\n handler: (ctx: HookContext) => Promise<void> | void,\n packageId?: string\n ): void {\n this.registerHook(event, handler, { object: objectName, packageId });\n }\n\n /**\n * Remove all hooks, actions, and objects contributed by a package.\n */\n removePackage(packageId: string): void {\n // Remove hooks\n for (const [key, handlers] of this.hooks.entries()) {\n const filtered = handlers.filter(h => h.packageId !== packageId);\n if (filtered.length !== handlers.length) {\n this.hooks.set(key, filtered);\n }\n }\n // Remove actions\n this.removeActionsByPackage(packageId);\n // Remove objects\n SchemaRegistry.unregisterObjectsByPackage(packageId, true);\n }\n\n /**\n * Gracefully shut down the engine, disconnecting all drivers.\n * Alias for destroy() — matches @objectql/core close() API.\n */\n async close(): Promise<void> {\n return this.destroy();\n }\n\n /**\n * Create a scoped execution context bound to this engine.\n * \n * Usage:\n * const ctx = engine.createContext({ userId: '...', tenantId: '...' });\n * const users = ctx.object('user');\n * await users.find({ filter: { status: 'active' } });\n */\n createContext(ctx: Partial<ExecutionContext>): ScopedContext {\n return new ScopedContext(\n ExecutionContextSchema.parse(ctx),\n this\n );\n }\n\n /**\n * Static factory: create a fully configured ObjectQL instance.\n * \n * Matches @objectql/core's `new ObjectQL(config)` pattern but also\n * registers drivers and objects, then calls init().\n * \n * Usage:\n * const ql = await ObjectQL.create({\n * datasources: { default: myDriver },\n * objects: { user: { name: 'user', fields: { ... } } }\n * });\n */\n static async create(config: {\n datasources?: Record<string, DriverInterface>;\n objects?: Record<string, ServiceObject>;\n hooks?: Array<{ event: string; object: string; handler: (ctx: HookContext) => Promise<void> | void }>;\n }): Promise<ObjectQL> {\n const ql = new ObjectQL();\n\n // Register drivers\n if (config.datasources) {\n for (const [name, driver] of Object.entries(config.datasources)) {\n // Set driver name if not already set\n if (!driver.name) {\n (driver as any).name = name;\n }\n ql.registerDriver(driver, name === 'default');\n }\n }\n\n // Register objects\n if (config.objects) {\n for (const [_key, schema] of Object.entries(config.objects)) {\n ql.registerObject(schema);\n }\n }\n\n // Register hooks\n if (config.hooks) {\n for (const hook of config.hooks) {\n ql.on(hook.event, hook.object, hook.handler);\n }\n }\n\n // Initialize (connect drivers)\n await ql.init();\n\n return ql;\n }\n}\n\n/**\n * Repository scoped to a single object, bound to an execution context.\n *\n * Provides both IDataEngine-style methods (find, insert, update, delete)\n * and convenience aliases (create, updateById, deleteById) matching\n * the @objectql/core ObjectRepository API.\n */\nexport class ObjectRepository {\n constructor(\n private objectName: string,\n private context: ExecutionContext,\n private engine: IDataEngine & { executeAction?: (o: string, a: string, c: any) => Promise<any> }\n ) {}\n\n async find(query: any = {}): Promise<any[]> {\n return this.engine.find(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async findOne(query: any = {}): Promise<any> {\n return this.engine.findOne(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async insert(data: any): Promise<any> {\n return this.engine.insert(this.objectName, data, {\n context: this.context,\n });\n }\n\n /** Alias for insert() — matches @objectql/core convention */\n async create(data: any): Promise<any> {\n return this.insert(data);\n }\n\n async update(data: any, options: any = {}): Promise<any> {\n return this.engine.update(this.objectName, data, {\n ...options,\n context: this.context,\n });\n }\n\n /** Update a single record by ID */\n async updateById(id: string | number, data: any): Promise<any> {\n return this.engine.update(this.objectName, { ...data, id: id }, {\n filter: { id: id },\n context: this.context,\n });\n }\n\n async delete(options: any = {}): Promise<any> {\n return this.engine.delete(this.objectName, {\n ...options,\n context: this.context,\n });\n }\n\n /** Delete a single record by ID */\n async deleteById(id: string | number): Promise<any> {\n return this.engine.delete(this.objectName, {\n filter: { id: id },\n context: this.context,\n });\n }\n\n async count(query: any = {}): Promise<number> {\n return this.engine.count(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Aggregate query */\n async aggregate(query: any = {}): Promise<any[]> {\n return this.engine.aggregate(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Execute a named action registered on this object */\n async execute(actionName: string, params?: any): Promise<any> {\n if (this.engine.executeAction) {\n return this.engine.executeAction(this.objectName, actionName, {\n ...params,\n userId: this.context.userId,\n tenantId: this.context.tenantId,\n roles: this.context.roles,\n });\n }\n throw new Error(`Actions not supported by engine`);\n }\n}\n\n/**\n * Scoped execution context with object() accessor.\n * \n * Provides identity (userId, tenantId/spaceId, roles),\n * repository access via object(), privilege escalation via sudo(),\n * and transactional execution via transaction().\n */\nexport class ScopedContext {\n constructor(\n private executionContext: ExecutionContext,\n private engine: IDataEngine\n ) {}\n\n /** Get a repository scoped to this context */\n object(name: string): ObjectRepository {\n return new ObjectRepository(name, this.executionContext, this.engine as any);\n }\n\n /** Create an elevated (system) context */\n sudo(): ScopedContext {\n return new ScopedContext(\n { ...this.executionContext, isSystem: true },\n this.engine\n );\n }\n\n /**\n * Execute a callback within a database transaction.\n *\n * The callback receives a new ScopedContext whose operations\n * share the same transaction handle. If the callback throws,\n * the transaction is rolled back; otherwise it is committed.\n *\n * Falls back to non-transactional execution if the driver\n * does not support transactions.\n */\n async transaction(callback: (trxCtx: ScopedContext) => Promise<any>): Promise<any> {\n const engine = this.engine as any;\n\n // Find the default driver for transaction support\n const driver = engine.defaultDriver\n ? engine.drivers?.get(engine.defaultDriver)\n : undefined;\n\n if (!driver?.beginTransaction) {\n // No transaction support — execute directly\n return callback(this);\n }\n\n const trx = await driver.beginTransaction();\n const trxCtx = new ScopedContext(\n { ...this.executionContext, transaction: trx },\n this.engine\n );\n\n try {\n const result = await callback(trxCtx);\n if (driver.commit) await driver.commit(trx);\n else if (driver.commitTransaction) await driver.commitTransaction(trx);\n return result;\n } catch (error) {\n if (driver.rollback) await driver.rollback(trx);\n else if (driver.rollbackTransaction) await driver.rollbackTransaction(trx);\n throw error;\n }\n }\n\n get userId() { return this.executionContext.userId; }\n get tenantId() { return this.executionContext.tenantId; }\n /** Alias for tenantId — matches ObjectQLContext.spaceId convention */\n get spaceId() { return this.executionContext.tenantId; }\n get roles() { return this.executionContext.roles; }\n get isSystem() { return this.executionContext.isSystem; }\n\n /** Internal: expose the transaction handle for driver-level access */\n get transactionHandle() { return this.executionContext.transaction; }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { SchemaRegistry } from './registry.js';\n\n/**\n * MetadataFacade\n * \n * Provides a clean, injectable interface over SchemaRegistry.\n * Registered as the 'metadata' kernel service to eliminate\n * downstream packages needing to manually wrap SchemaRegistry.\n * \n * Implements the async IMetadataService interface.\n * Internally delegates to SchemaRegistry (in-memory) with Promise wrappers.\n */\nexport class MetadataFacade {\n /**\n * Register a metadata item\n */\n async register(type: string, name: string, data: any): Promise<void> {\n const definition = typeof data === 'object' && data !== null\n ? { ...data, name: data.name ?? name }\n : data;\n if (type === 'object') {\n SchemaRegistry.registerItem(type, definition, 'name' as any);\n } else {\n SchemaRegistry.registerItem(type, definition, definition.id ? 'id' as any : 'name' as any);\n }\n }\n\n /**\n * Get a metadata item by type and name\n */\n async get(type: string, name: string): Promise<any> {\n const item = SchemaRegistry.getItem(type, name) as any;\n return item?.content ?? item;\n }\n\n /**\n * Get the raw entry (with metadata wrapper)\n */\n getEntry(type: string, name: string): any {\n return SchemaRegistry.getItem(type, name);\n }\n\n /**\n * List all items of a type\n */\n async list(type: string): Promise<any[]> {\n const items = SchemaRegistry.listItems(type);\n return items.map((item: any) => item?.content ?? item);\n }\n\n /**\n * Unregister a metadata item\n */\n async unregister(type: string, name: string): Promise<void> {\n SchemaRegistry.unregisterItem(type, name);\n }\n\n /**\n * Check if a metadata item exists\n */\n async exists(type: string, name: string): Promise<boolean> {\n const item = SchemaRegistry.getItem(type, name);\n return item !== undefined && item !== null;\n }\n\n /**\n * List all names of metadata items of a given type\n */\n async listNames(type: string): Promise<string[]> {\n const items = SchemaRegistry.listItems(type);\n return items.map((item: any) => item?.name ?? item?.content?.name ?? '').filter(Boolean);\n }\n\n /**\n * Unregister all metadata from a package\n */\n async unregisterPackage(packageName: string): Promise<void> {\n SchemaRegistry.unregisterObjectsByPackage(packageName);\n }\n\n /**\n * Convenience: get object definition\n */\n async getObject(name: string): Promise<any> {\n return SchemaRegistry.getObject(name);\n }\n\n /**\n * Convenience: list all objects\n */\n async listObjects(): Promise<any[]> {\n return SchemaRegistry.getAllObjects();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectQL } from './engine.js';\nimport { MetadataFacade } from './metadata-facade.js';\nimport { ObjectStackProtocolImplementation } from './protocol.js';\nimport { Plugin, PluginContext } from '@objectstack/core';\n\nexport type { Plugin, PluginContext };\n\nexport class ObjectQLPlugin implements Plugin {\n name = 'com.objectstack.engine.objectql';\n type = 'objectql';\n version = '1.0.0';\n \n private ql: ObjectQL | undefined;\n private hostContext?: Record<string, any>;\n\n constructor(ql?: ObjectQL, hostContext?: Record<string, any>) {\n if (ql) {\n this.ql = ql;\n } else {\n this.hostContext = hostContext;\n // Lazily created in init\n }\n }\n\n init = async (ctx: PluginContext) => {\n if (!this.ql) {\n // Pass kernel logger to engine to avoid creating a separate pino instance\n const hostCtx = { ...this.hostContext, logger: ctx.logger };\n this.ql = new ObjectQL(hostCtx);\n }\n \n // Register as provider for Core Kernel Services\n ctx.registerService('objectql', this.ql);\n \n // Register MetadataFacade as metadata service (unless external service exists)\n let hasMetadata = false;\n let metadataProvider = 'objectql';\n try {\n if (ctx.getService('metadata')) {\n hasMetadata = true;\n metadataProvider = 'external';\n }\n } catch (e: any) {\n // Ignore errors during check (e.g. \"Service is async\")\n }\n\n if (!hasMetadata) {\n try {\n const metadataFacade = new MetadataFacade();\n ctx.registerService('metadata', metadataFacade);\n ctx.logger.info('MetadataFacade registered as metadata service', {\n mode: 'in-memory',\n features: ['registry', 'fast-lookup']\n });\n } catch (e: any) {\n // Ignore if already registered (race condition or async mis-detection)\n if (!e.message?.includes('already registered')) {\n throw e;\n }\n }\n } else {\n ctx.logger.info('External metadata service detected', {\n provider: metadataProvider,\n mode: 'will-sync-in-start-phase'\n });\n }\n \n ctx.registerService('data', this.ql); // ObjectQL implements IDataEngine\n \n ctx.logger.info('ObjectQL engine registered', { \n services: ['objectql', 'data'],\n metadataProvider: metadataProvider\n });\n\n // Register Protocol Implementation\n const protocolShim = new ObjectStackProtocolImplementation(\n this.ql, \n () => ctx.getServices ? ctx.getServices() : new Map()\n );\n\n ctx.registerService('protocol', protocolShim);\n ctx.logger.info('Protocol service registered');\n }\n\n start = async (ctx: PluginContext) => {\n ctx.logger.info('ObjectQL engine starting...');\n \n // Check if we should load from external metadata service\n try {\n const metadataService = ctx.getService('metadata') as any;\n // Only sync if metadata service is external (not our own MetadataFacade)\n if (metadataService && !(metadataService instanceof MetadataFacade) && this.ql) {\n await this.loadMetadataFromService(metadataService, ctx);\n }\n } catch (e: any) {\n // No external metadata service or error accessing it\n ctx.logger.debug('No external metadata service to sync from');\n }\n \n // Discover features from Kernel Services\n if (ctx.getServices && this.ql) {\n const services = ctx.getServices();\n for (const [name, service] of services.entries()) {\n if (name.startsWith('driver.')) {\n // Register Driver\n this.ql.registerDriver(service);\n ctx.logger.debug('Discovered and registered driver service', { serviceName: name });\n }\n if (name.startsWith('app.')) {\n // Register App\n this.ql.registerApp(service); // service is Manifest\n ctx.logger.debug('Discovered and registered app service', { serviceName: name });\n }\n }\n }\n\n // Initialize drivers (calls driver.connect() which sets up persistence)\n await this.ql?.init();\n\n // Sync all registered object schemas to database\n // This ensures tables/collections are created or updated for every\n // object registered by plugins (e.g., sys_user from plugin-auth).\n await this.syncRegisteredSchemas(ctx);\n\n // Register built-in audit hooks\n this.registerAuditHooks(ctx);\n\n // Register tenant isolation middleware\n this.registerTenantMiddleware(ctx);\n \n ctx.logger.info('ObjectQL engine started', {\n driversRegistered: this.ql?.['drivers']?.size || 0,\n objectsRegistered: this.ql?.registry?.getAllObjects?.()?.length || 0\n });\n }\n\n /**\n * Register built-in audit hooks for auto-stamping created_by/updated_by\n * and fetching previousData for update/delete operations.\n */\n private registerAuditHooks(ctx: PluginContext) {\n if (!this.ql) return;\n\n // Auto-stamp created_by/updated_by on insert\n this.ql.registerHook('beforeInsert', async (hookCtx) => {\n if (hookCtx.session?.userId && hookCtx.input?.data) {\n const data = hookCtx.input.data as Record<string, any>;\n if (typeof data === 'object' && data !== null) {\n data.created_by = data.created_by ?? hookCtx.session.userId;\n data.updated_by = hookCtx.session.userId;\n data.created_at = data.created_at ?? new Date().toISOString();\n data.updated_at = new Date().toISOString();\n if (hookCtx.session.tenantId) {\n data.tenant_id = data.tenant_id ?? hookCtx.session.tenantId;\n }\n }\n }\n }, { object: '*', priority: 10 });\n\n // Auto-stamp updated_by on update\n this.ql.registerHook('beforeUpdate', async (hookCtx) => {\n if (hookCtx.session?.userId && hookCtx.input?.data) {\n const data = hookCtx.input.data as Record<string, any>;\n if (typeof data === 'object' && data !== null) {\n data.updated_by = hookCtx.session.userId;\n data.updated_at = new Date().toISOString();\n }\n }\n }, { object: '*', priority: 10 });\n\n // Auto-fetch previousData for update hooks\n this.ql.registerHook('beforeUpdate', async (hookCtx) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n filter: { id: hookCtx.input.id }\n });\n if (existing) {\n hookCtx.previous = existing;\n }\n } catch (_e) {\n // Non-fatal: some objects may not support findOne\n }\n }\n }, { object: '*', priority: 5 });\n\n // Auto-fetch previousData for delete hooks\n this.ql.registerHook('beforeDelete', async (hookCtx) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n filter: { id: hookCtx.input.id }\n });\n if (existing) {\n hookCtx.previous = existing;\n }\n } catch (_e) {\n // Non-fatal\n }\n }\n }, { object: '*', priority: 5 });\n\n ctx.logger.debug('Audit hooks registered (created_by/updated_by, previousData)');\n }\n\n /**\n * Register tenant isolation middleware that auto-injects tenant_id filter\n * for multi-tenant operations.\n */\n private registerTenantMiddleware(ctx: PluginContext) {\n if (!this.ql) return;\n\n this.ql.registerMiddleware(async (opCtx, next) => {\n // Only apply to operations with tenantId that are not system-level\n if (!opCtx.context?.tenantId || opCtx.context?.isSystem) {\n return next();\n }\n\n // Read operations: inject tenant_id filter into AST\n if (['find', 'findOne', 'count', 'aggregate'].includes(opCtx.operation)) {\n if (opCtx.ast) {\n const tenantFilter = { tenant_id: opCtx.context.tenantId };\n if (opCtx.ast.where) {\n opCtx.ast.where = { $and: [opCtx.ast.where, tenantFilter] };\n } else {\n opCtx.ast.where = tenantFilter;\n }\n }\n }\n\n await next();\n });\n\n ctx.logger.debug('Tenant isolation middleware registered');\n }\n\n /**\n * Synchronize all registered object schemas to the database.\n *\n * Groups objects by their responsible driver, then:\n * - If the driver advertises `supports.batchSchemaSync` and implements\n * `syncSchemasBatch()`, submits all schemas in a single call (reducing\n * network round-trips for remote drivers like Turso).\n * - Otherwise falls back to sequential `syncSchema()` per object.\n *\n * This is idempotent — drivers must tolerate repeated calls without\n * duplicating tables or erroring out.\n *\n * Drivers that do not implement `syncSchema` are silently skipped.\n */\n private async syncRegisteredSchemas(ctx: PluginContext) {\n if (!this.ql) return;\n\n const allObjects = this.ql.registry?.getAllObjects?.() ?? [];\n if (allObjects.length === 0) return;\n\n let synced = 0;\n let skipped = 0;\n\n // Group objects by driver for potential batch optimization\n const driverGroups = new Map<any, Array<{ obj: any; tableName: string }>>();\n\n for (const obj of allObjects) {\n const driver = this.ql.getDriverForObject(obj.name);\n if (!driver) {\n ctx.logger.debug('No driver available for object, skipping schema sync', {\n object: obj.name,\n });\n skipped++;\n continue;\n }\n\n if (typeof driver.syncSchema !== 'function') {\n ctx.logger.debug('Driver does not support syncSchema, skipping', {\n object: obj.name,\n driver: driver.name,\n });\n skipped++;\n continue;\n }\n\n const tableName = obj.tableName || obj.name;\n\n let group = driverGroups.get(driver);\n if (!group) {\n group = [];\n driverGroups.set(driver, group);\n }\n group.push({ obj, tableName });\n }\n\n // Process each driver group\n for (const [driver, entries] of driverGroups) {\n // Batch path: driver supports batch schema sync\n if (\n driver.supports?.batchSchemaSync &&\n typeof driver.syncSchemasBatch === 'function'\n ) {\n const batchPayload = entries.map((e) => ({\n object: e.tableName,\n schema: e.obj,\n }));\n try {\n await driver.syncSchemasBatch(batchPayload);\n synced += entries.length;\n ctx.logger.debug('Batch schema sync succeeded', {\n driver: driver.name,\n count: entries.length,\n });\n } catch (e: unknown) {\n ctx.logger.warn('Batch schema sync failed, falling back to sequential', {\n driver: driver.name,\n error: e instanceof Error ? e.message : String(e),\n });\n // Fallback: sequential sync for this driver's objects\n for (const { obj, tableName } of entries) {\n try {\n await driver.syncSchema(tableName, obj);\n synced++;\n } catch (seqErr: unknown) {\n ctx.logger.warn('Failed to sync schema for object', {\n object: obj.name,\n tableName,\n driver: driver.name,\n error: seqErr instanceof Error ? seqErr.message : String(seqErr),\n });\n }\n }\n }\n } else {\n // Sequential path: no batch support\n for (const { obj, tableName } of entries) {\n try {\n await driver.syncSchema(tableName, obj);\n synced++;\n } catch (e: unknown) {\n ctx.logger.warn('Failed to sync schema for object', {\n object: obj.name,\n tableName,\n driver: driver.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n }\n }\n\n if (synced > 0 || skipped > 0) {\n ctx.logger.info('Schema sync complete', { synced, skipped, total: allObjects.length });\n }\n }\n\n /**\n * Load metadata from external metadata service into ObjectQL registry\n * This enables ObjectQL to use file-based or remote metadata\n */\n private async loadMetadataFromService(metadataService: any, ctx: PluginContext) {\n ctx.logger.info('Syncing metadata from external service into ObjectQL registry...');\n \n // Metadata types to sync\n const metadataTypes = ['object', 'view', 'app', 'flow', 'workflow', 'function'];\n let totalLoaded = 0;\n \n for (const type of metadataTypes) {\n try {\n // Check if service has loadMany method\n if (typeof metadataService.loadMany === 'function') {\n const items = await metadataService.loadMany(type);\n \n if (items && items.length > 0) {\n items.forEach((item: any) => {\n // Determine key field (usually 'name' or 'id')\n const keyField = item.id ? 'id' : 'name';\n \n // For objects, use the ownership-aware registration\n if (type === 'object' && this.ql) {\n // Objects are registered differently (ownership model)\n // Skip for now - handled by app registration\n return;\n }\n \n // Register other types in the registry\n if (this.ql?.registry?.registerItem) {\n this.ql.registry.registerItem(type, item, keyField);\n }\n });\n \n totalLoaded += items.length;\n ctx.logger.info(`Synced ${items.length} ${type}(s) from metadata service`);\n }\n }\n } catch (e: any) {\n // Type might not exist in metadata service - that's ok\n ctx.logger.debug(`No ${type} metadata found or error loading`, { \n error: e.message \n });\n }\n }\n \n if (totalLoaded > 0) {\n ctx.logger.info(`Metadata sync complete: ${totalLoaded} items loaded into ObjectQL registry`);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectKernel } from '@objectstack/core';\nimport { ObjectQLPlugin } from './plugin.js';\nimport type { Plugin } from '@objectstack/core';\n\n/**\n * Options for creating an ObjectQL Kernel.\n */\nexport interface ObjectQLKernelOptions {\n /**\n * Additional plugins to register with the kernel.\n */\n plugins?: Plugin[];\n}\n\n/**\n * Convenience factory for creating an ObjectQL-ready kernel.\n *\n * Creates an ObjectKernel pre-configured with the ObjectQLPlugin\n * (data engine, schema registry, protocol implementation) plus any\n * additional plugins provided.\n *\n * @example\n * ```typescript\n * import { createObjectQLKernel } from '@objectstack/objectql';\n *\n * const kernel = createObjectQLKernel({\n * plugins: [myDriverPlugin, myAuthPlugin],\n * });\n * await kernel.bootstrap();\n * ```\n */\nexport async function createObjectQLKernel(options: ObjectQLKernelOptions = {}): Promise<ObjectKernel> {\n const kernel = new ObjectKernel();\n\n // Register the core ObjectQLPlugin first\n await kernel.use(new ObjectQLPlugin());\n\n // Register any additional plugins\n if (options.plugins) {\n for (const plugin of options.plugins) {\n await kernel.use(plugin);\n }\n }\n\n return kernel;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ServiceObject } from '@objectstack/spec/data';\n\n// ── Introspection Types ──────────────────────────────────────────────────────\n\n/**\n * Column metadata from database introspection.\n */\nexport interface IntrospectedColumn {\n /** Column name */\n name: string;\n /** Native database type (e.g., 'varchar', 'integer', 'timestamp') */\n type: string;\n /** Whether the column is nullable */\n nullable: boolean;\n /** Default value if any */\n defaultValue?: unknown;\n /** Whether this is a primary key */\n isPrimary?: boolean;\n /** Whether this column has a unique constraint */\n isUnique?: boolean;\n /** Maximum length for string types */\n maxLength?: number;\n}\n\n/**\n * Foreign key relationship metadata.\n */\nexport interface IntrospectedForeignKey {\n /** Column name in the source table */\n columnName: string;\n /** Referenced table name */\n referencedTable: string;\n /** Referenced column name */\n referencedColumn: string;\n /** Constraint name */\n constraintName?: string;\n}\n\n/**\n * Table metadata from database introspection.\n */\nexport interface IntrospectedTable {\n /** Table name */\n name: string;\n /** List of columns */\n columns: IntrospectedColumn[];\n /** List of foreign key relationships */\n foreignKeys: IntrospectedForeignKey[];\n /** Primary key columns */\n primaryKeys: string[];\n}\n\n/**\n * Complete database schema introspection result.\n */\nexport interface IntrospectedSchema {\n /** Map of table name to table metadata */\n tables: Record<string, IntrospectedTable>;\n}\n\n// ── Utility Functions ────────────────────────────────────────────────────────\n\n/**\n * Convert a snake_case or plain string to Title Case.\n *\n * @example\n * toTitleCase('first_name') // => 'First Name'\n * toTitleCase('project_task') // => 'Project Task'\n */\nexport function toTitleCase(str: string): string {\n return str\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n/**\n * Map a native database column type to an ObjectStack FieldType.\n */\nfunction mapDatabaseTypeToFieldType(\n dbType: string\n): 'text' | 'textarea' | 'number' | 'boolean' | 'datetime' | 'date' | 'time' | 'json' {\n const type = dbType.toLowerCase();\n\n // Text types\n if (type.includes('char') || type.includes('varchar') || type.includes('text')) {\n if (type.includes('text')) return 'textarea';\n return 'text';\n }\n\n // Numeric types\n if (\n type.includes('int') || type === 'integer' || type === 'bigint' || type === 'smallint'\n ) {\n return 'number';\n }\n if (\n type.includes('float') || type.includes('double') || type.includes('decimal') ||\n type.includes('numeric') || type === 'real'\n ) {\n return 'number';\n }\n\n // Boolean\n if (type.includes('bool')) {\n return 'boolean';\n }\n\n // Date / Time types\n if (type.includes('timestamp') || type === 'datetime') {\n return 'datetime';\n }\n if (type === 'date') {\n return 'date';\n }\n if (type === 'time') {\n return 'time';\n }\n\n // JSON types\n if (type === 'json' || type === 'jsonb') {\n return 'json';\n }\n\n // Default to text\n return 'text';\n}\n\n/**\n * Convert an introspected database schema to ObjectStack object definitions.\n *\n * This allows using existing database tables without manually defining metadata.\n *\n * @param introspectedSchema - The schema returned from driver.introspectSchema()\n * @param options - Optional filtering / conversion settings\n * @returns Array of ServiceObject definitions that can be registered with ObjectQL\n *\n * @example\n * ```typescript\n * const schema = await driver.introspectSchema();\n * const objects = convertIntrospectedSchemaToObjects(schema);\n * for (const obj of objects) {\n * engine.registerObject(obj);\n * }\n * ```\n */\nexport function convertIntrospectedSchemaToObjects(\n introspectedSchema: IntrospectedSchema,\n options?: {\n /** Tables to exclude from conversion */\n excludeTables?: string[];\n /** Tables to include (if specified, only these will be converted) */\n includeTables?: string[];\n /** Whether to skip system columns like id, created_at, updated_at (default: true) */\n skipSystemColumns?: boolean;\n }\n): ServiceObject[] {\n const objects: ServiceObject[] = [];\n const excludeTables = options?.excludeTables || [];\n const includeTables = options?.includeTables;\n const skipSystemColumns = options?.skipSystemColumns !== false;\n\n for (const [tableName, table] of Object.entries(introspectedSchema.tables)) {\n if (excludeTables.includes(tableName)) continue;\n if (includeTables && !includeTables.includes(tableName)) continue;\n\n const fields: Record<string, any> = {};\n\n for (const column of table.columns) {\n // Skip system columns if requested\n if (skipSystemColumns && ['id', 'created_at', 'updated_at'].includes(column.name)) {\n continue;\n }\n\n // Check for foreign key → lookup field\n const foreignKey = table.foreignKeys.find((fk) => fk.columnName === column.name);\n\n if (foreignKey) {\n fields[column.name] = {\n name: column.name,\n type: 'lookup' as const,\n reference: foreignKey.referencedTable,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n } else {\n const fieldType = mapDatabaseTypeToFieldType(column.type);\n\n const field: Record<string, any> = {\n name: column.name,\n type: fieldType,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n\n if (column.isUnique) {\n field.unique = true;\n }\n if (column.maxLength && (fieldType === 'text' || fieldType === 'textarea')) {\n field.maxLength = column.maxLength;\n }\n if (column.defaultValue != null) {\n field.defaultValue = column.defaultValue;\n }\n\n fields[column.name] = field;\n }\n }\n\n objects.push({\n name: tableName,\n label: toTitleCase(tableName),\n fields,\n } as ServiceObject);\n }\n\n return objects;\n}\n"],"mappings":"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","names":[]}