@objectstack/objectql 1.0.10 → 1.0.12

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/plugin.ts"],"sourcesContent":["import { ServiceObject, ObjectSchema } from '@objectstack/spec/data';\nimport { ObjectStackManifest, ManifestSchema } from '@objectstack/spec/kernel';\nimport { AppSchema } from '@objectstack/spec/ui';\n\n/**\n * Global Schema Registry\n * Unified storage for all metadata types (Objects, Apps, Flows, Layouts, etc.)\n */\nexport class SchemaRegistry {\n // Nested Map: Type -> Name/ID -> MetadataItem\n private static metadata = new Map<string, Map<string, any>>();\n\n /**\n * Universal Register Method\n * @param type The category of metadata (e.g., 'object', 'app', 'plugin')\n * @param item The metadata item itself\n * @param keyField The property to use as the unique key (default: 'name')\n */\n static registerItem<T>(type: string, item: T, keyField: keyof T = 'name' as keyof T) {\n if (!this.metadata.has(type)) {\n this.metadata.set(type, new Map());\n }\n const collection = this.metadata.get(type)!;\n const key = String(item[keyField]);\n\n // Validation Hook\n try {\n this.validate(type, item);\n } catch (e: any) {\n console.error(`[Registry] Validation failed for ${type} ${key}: ${e.message}`);\n // For now, warn but don't crash, allowing partial/legacy loads\n // throw e; \n }\n\n if (collection.has(key)) {\n console.warn(`[Registry] Overwriting ${type}: ${key}`);\n }\n collection.set(key, item);\n console.log(`[Registry] Registered ${type}: ${key}`);\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 === 'app') {\n // AppSchema might rely on Zod, imported via UI protocol\n return AppSchema.parse(item);\n }\n if (type === 'plugin') {\n return ManifestSchema.parse(item);\n }\n // Add more validations as needed\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 && collection.has(name)) {\n collection.delete(name);\n console.log(`[Registry] Unregistered ${type}: ${name}`);\n } else {\n console.warn(`[Registry] Attempted to unregister non-existent ${type}: ${name}`);\n }\n }\n\n /**\n * Universal Get Method\n */\n static getItem<T>(type: string, name: string): T | undefined {\n return this.metadata.get(type)?.get(name) as T;\n }\n\n /**\n * Universal List Method\n */\n static listItems<T>(type: string): T[] {\n return Array.from(this.metadata.get(type)?.values() || []) as T[];\n }\n\n /**\n * Get all registered metadata types (Kinds)\n */\n static getRegisteredTypes(): string[] {\n return Array.from(this.metadata.keys());\n }\n\n // ==========================================\n // Typed Helper Methods (Shortcuts)\n // ==========================================\n\n /**\n * Object Helpers\n */\n static registerObject(schema: ServiceObject) {\n this.registerItem('object', schema, 'name');\n }\n\n static getObject(name: string): ServiceObject | undefined {\n return this.getItem<ServiceObject>('object', name);\n }\n\n static getAllObjects(): ServiceObject[] {\n return this.listItems<ServiceObject>('object');\n }\n\n /**\n * Plugin Helpers\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 (Metadata Type) Helpers\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","import { 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 } from '@objectstack/spec/api';\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\nexport class ObjectStackProtocolImplementation implements ObjectStackProtocol {\n private engine: IDataEngine;\n\n constructor(engine: IDataEngine) {\n this.engine = engine;\n }\n\n async getDiscovery(_request: {}) {\n return {\n version: '1.0',\n apiName: 'ObjectStack API',\n capabilities: {\n graphql: false,\n search: false,\n websockets: false,\n files: true,\n analytics: false,\n hub: false\n },\n endpoints: {\n data: '/api/data',\n metadata: '/api/meta',\n auth: '/api/auth'\n }\n };\n }\n\n async getMetaTypes(_request: {}) {\n return {\n types: SchemaRegistry.getRegisteredTypes()\n };\n }\n\n async getMetaItems(request: { type: string }) {\n return {\n type: request.type,\n items: SchemaRegistry.listItems(request.type)\n };\n }\n\n async getMetaItem(request: { type: string, name: string }) {\n return {\n type: request.type,\n name: request.name,\n item: SchemaRegistry.getItem(request.type, request.name)\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 let view: any;\n if (request.type === 'list') {\n view = {\n type: 'list',\n object: request.object,\n columns: Object.keys(schema.fields || {}).slice(0, 5).map(f => ({\n field: f,\n label: schema.fields[f].label || f\n }))\n };\n } else {\n view = {\n type: 'form',\n object: request.object,\n sections: [\n {\n label: 'General',\n fields: Object.keys(schema.fields || {}).map(f => ({\n field: f\n }))\n }\n ]\n };\n }\n return view;\n }\n\n async findData(request: { object: string, query?: any }) {\n // TODO: Normalize query from HTTP Query params (string values) to DataEngineQueryOptions (typed)\n // For now, we assume query is partially compatible or simple enough.\n // We should parse 'top', 'skip', 'limit' to numbers if they are strings.\n const options: any = { ...request.query };\n if (options.top) options.top = Number(options.top);\n if (options.skip) options.skip = Number(options.skip);\n if (options.limit) options.limit = Number(options.limit);\n \n // Handle OData style $filter if present, or flat filters\n // This is a naive implementation, a real OData parser is needed for complex scenarios.\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 }) {\n const result = await this.engine.findOne(request.object, {\n filter: { _id: request.id }\n });\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 || 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 // Map high-level batch request to DataEngine batch if available\n // Or implement loop here.\n // For now, let's just fail or implement basic loop to satisfying interface\n // since full batch mapping requires careful type handling.\n throw new Error('Batch operations not yet fully implemented in protocol adapter');\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<any> {\n // TODO: Implement proper updateMany in DataEngine\n throw new Error('updateManyData not implemented');\n }\n\n async analyticsQuery(_request: any): Promise<any> {\n throw new Error('analyticsQuery not implemented');\n }\n\n async getAnalyticsMeta(_request: any): Promise<any> {\n throw new Error('getAnalyticsMeta not implemented');\n }\n\n async triggerAutomation(_request: any): Promise<any> {\n throw new Error('triggerAutomation not implemented');\n }\n\n async listSpaces(_request: any): Promise<any> {\n throw new Error('listSpaces not implemented');\n }\n\n async createSpace(_request: any): Promise<any> {\n throw new Error('createSpace not implemented');\n }\n\n async installPlugin(_request: any): Promise<any> {\n throw new Error('installPlugin not implemented');\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","import { QueryAST, HookContext } from '@objectstack/spec/data';\nimport { \n DataEngineQueryOptions, \n DataEngineInsertOptions, \n DataEngineUpdateOptions, \n DataEngineDeleteOptions,\n DataEngineAggregateOptions,\n DataEngineCountOptions \n} from '@objectstack/spec/data';\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 * 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 // Hooks Registry\n private hooks: Record<string, HookHandler[]> = {\n 'beforeFind': [], 'afterFind': [],\n 'beforeInsert': [], 'afterInsert': [],\n 'beforeUpdate': [], 'afterUpdate': [],\n 'beforeDelete': [], 'afterDelete': [],\n };\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 */\n registerHook(event: string, handler: HookHandler) {\n if (!this.hooks[event]) {\n this.hooks[event] = [];\n }\n this.hooks[event].push(handler);\n this.logger.debug('Registered hook', { event, totalHandlers: this.hooks[event].length });\n }\n\n public async triggerHooks(event: string, context: HookContext) {\n const handlers = this.hooks[event] || [];\n \n if (handlers.length === 0) {\n this.logger.debug('No hooks registered for event', { event });\n return;\n }\n\n this.logger.debug('Triggering hooks', { event, count: handlers.length });\n \n for (const handler of handlers) {\n await handler(context);\n }\n }\n\n /**\n * Register contribution (Manifest)\n */\n registerApp(manifest: any) {\n const id = manifest.id;\n this.logger.debug('Registering app manifest', { id });\n\n // Register 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 SchemaRegistry.registerObject(objDef);\n this.logger.debug('Registered Object', { object: objDef.name, 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 SchemaRegistry.registerObject(objDef as any);\n this.logger.debug('Registered Object', { object: name, from: id });\n }\n }\n }\n\n // 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\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) {\n return SchemaRegistry.getObject(objectName);\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: 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 // TODO: Handle populate/joins mapping if Driver supports it in QueryAST\n return ast;\n }\n\n // ============================================\n // Data Access Methods (IDataEngine Interface)\n // ============================================\n\n async find(object: string, query?: DataEngineQueryOptions): Promise<any[]> {\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 hookContext: HookContext = {\n object,\n event: 'beforeFind',\n input: { ast, options: undefined }, // Should map options?\n ql: this\n };\n await this.triggerHooks('beforeFind', hookContext);\n\n try {\n const result = await driver.find(object, hookContext.input.ast, hookContext.input.options);\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 async findOne(objectName: string, query?: DataEngineQueryOptions): Promise<any> {\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 // Reuse find logic or call generic driver.findOne if available\n // Assuming driver has findOne\n return driver.findOne(objectName, ast);\n }\n\n async insert(object: string, data: any | any[], options?: DataEngineInsertOptions): Promise<any> {\n this.logger.debug('Insert operation starting', { object, isBatch: Array.isArray(data) });\n const driver = this.getDriver(object);\n\n const hookContext: HookContext = {\n object,\n event: 'beforeInsert',\n input: { data, options },\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, hookContext.input.options);\n } else {\n // Fallback loop\n result = await Promise.all(hookContext.input.data.map((item: any) => driver.create(object, item, hookContext.input.options)));\n }\n } else {\n result = await driver.create(object, hookContext.input.data, hookContext.input.options);\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 async update(object: string, data: any, options?: DataEngineUpdateOptions): Promise<any> {\n // NOTE: This signature is tricky because Driver expects (obj, id, data) usually.\n // DataEngine protocol puts filter in options.\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 // This is a simplification. Real implementation needs robust filter handling.\n let id = data.id || data._id;\n if (!id && options?.filter) {\n // Optimization: If filter is simple ID check, extract it\n if (typeof options.filter === 'string') id = options.filter;\n else if (options.filter._id) id = options.filter._id;\n else if (options.filter.id) id = options.filter.id;\n }\n\n const hookContext: HookContext = {\n object,\n event: 'beforeUpdate',\n input: { id, data, options },\n ql: this\n };\n await this.triggerHooks('beforeUpdate', hookContext);\n\n try {\n let result;\n if (hookContext.input.id) {\n // Single update by ID\n result = await driver.update(object, hookContext.input.id, hookContext.input.data, hookContext.input.options);\n } else if (options?.multi && driver.updateMany) {\n // Bulk update by Query\n const ast = this.toQueryAST(object, { filter: options.filter });\n result = await driver.updateMany(object, ast, hookContext.input.data, hookContext.input.options);\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 async delete(object: string, options?: DataEngineDeleteOptions): Promise<any> {\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 else if (options.filter.id) id = options.filter.id;\n }\n\n const hookContext: HookContext = {\n object,\n event: 'beforeDelete',\n input: { id, options },\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, hookContext.input.options);\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);\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 async count(object: string, query?: DataEngineCountOptions): Promise<number> {\n const driver = this.getDriver(object);\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 async aggregate(object: string, query: DataEngineAggregateOptions): Promise<any[]> {\n const driver = this.getDriver(object);\n this.logger.debug(`Aggregate on ${object} using ${driver.name}`, query);\n // Driver needs support for raw aggregation or mapped aggregation\n // For now, if driver supports 'execute', we might pass it down, or we need to add 'aggregate' to DriverInterface\n // In this version, we'll assume driver might handle it via special 'find' or throw not implemented\n throw new Error('Aggregate not yet fully implemented in ObjectQL->Driver mapping');\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","import { ObjectQL } from './engine.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 this.ql = new ObjectQL(this.hostContext);\n }\n \n // Register as provider for Core Kernel Services\n ctx.registerService('objectql', this.ql);\n \n // Respect existing metadata service (e.g. from MetadataPlugin)\n let hasMetadata = false;\n try {\n if (ctx.getService('metadata')) {\n hasMetadata = true;\n }\n } catch (e: any) {\n // Ignore errors during check (e.g. \"Service is async\")\n }\n\n if (!hasMetadata) {\n try {\n ctx.registerService('metadata', this.ql);\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 }\n \n ctx.registerService('data', this.ql); // ObjectQL implements IDataEngine\n ctx.registerService('auth', this.ql);\n \n ctx.logger.info('ObjectQL engine registered as service', { \n provides: ['objectql', 'metadata', 'data', 'auth'] \n });\n\n // Register Protocol Implementation\n const protocolShim = new ObjectStackProtocolImplementation(this.ql);\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 initialized');\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}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/registry.ts","../src/protocol.ts","../src/engine.ts","../src/plugin.ts"],"sourcesContent":["import { 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 or short name with fallback scan).\n * For compatibility, tries exact match first, then scans for suffix match.\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 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","import { 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 } from '@objectstack/spec/api';\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\nexport class ObjectStackProtocolImplementation implements ObjectStackProtocol {\n private engine: IDataEngine;\n\n constructor(engine: IDataEngine) {\n this.engine = engine;\n }\n\n async getDiscovery(_request: {}) {\n return {\n version: '1.0',\n apiName: 'ObjectStack API',\n capabilities: {\n graphql: false,\n search: false,\n websockets: false,\n files: true,\n analytics: false,\n hub: false\n },\n endpoints: {\n data: '/api/data',\n metadata: '/api/meta',\n auth: '/api/auth'\n }\n };\n }\n\n async getMetaTypes(_request: {}) {\n return {\n types: SchemaRegistry.getRegisteredTypes()\n };\n }\n\n async getMetaItems(request: { type: string; packageId?: string }) {\n return {\n type: request.type,\n items: SchemaRegistry.listItems(request.type, request.packageId)\n };\n }\n\n async getMetaItem(request: { type: string, name: string }) {\n return {\n type: request.type,\n name: request.name,\n item: SchemaRegistry.getItem(request.type, request.name)\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 !== 'modified_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 // TODO: Normalize query from HTTP Query params (string values) to DataEngineQueryOptions (typed)\n // For now, we assume query is partially compatible or simple enough.\n // We should parse 'top', 'skip', 'limit' to numbers if they are strings.\n const options: any = { ...request.query };\n if (options.top) options.top = Number(options.top);\n if (options.skip) options.skip = Number(options.skip);\n if (options.limit) options.limit = Number(options.limit);\n \n // Handle OData style $filter if present, or flat filters\n // This is a naive implementation, a real OData parser is needed for complex scenarios.\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 }) {\n const result = await this.engine.findOne(request.object, {\n filter: { _id: request.id }\n });\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 || 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 // Map high-level batch request to DataEngine batch if available\n // Or implement loop here.\n // For now, let's just fail or implement basic loop to satisfying interface\n // since full batch mapping requires careful type handling.\n throw new Error('Batch operations not yet fully implemented in protocol adapter');\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<any> {\n // TODO: Implement proper updateMany in DataEngine\n throw new Error('updateManyData not implemented');\n }\n\n async analyticsQuery(_request: any): Promise<any> {\n throw new Error('analyticsQuery not implemented');\n }\n\n async getAnalyticsMeta(_request: any): Promise<any> {\n throw new Error('getAnalyticsMeta not implemented');\n }\n\n async triggerAutomation(_request: any): Promise<any> {\n throw new Error('triggerAutomation not implemented');\n }\n\n async listSpaces(_request: any): Promise<any> {\n throw new Error('listSpaces not implemented');\n }\n\n async createSpace(_request: any): Promise<any> {\n throw new Error('createSpace not implemented');\n }\n\n async installPlugin(_request: any): Promise<any> {\n throw new Error('installPlugin not implemented');\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","import { QueryAST, HookContext } from '@objectstack/spec/data';\nimport { \n DataEngineQueryOptions, \n DataEngineInsertOptions, \n DataEngineUpdateOptions, \n DataEngineDeleteOptions,\n DataEngineAggregateOptions,\n DataEngineCountOptions \n} from '@objectstack/spec/data';\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 * 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 // Hooks Registry\n private hooks: Record<string, HookHandler[]> = {\n 'beforeFind': [], 'afterFind': [],\n 'beforeInsert': [], 'afterInsert': [],\n 'beforeUpdate': [], 'afterUpdate': [],\n 'beforeDelete': [], 'afterDelete': [],\n };\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 */\n registerHook(event: string, handler: HookHandler) {\n if (!this.hooks[event]) {\n this.hooks[event] = [];\n }\n this.hooks[event].push(handler);\n this.logger.debug('Registered hook', { event, totalHandlers: this.hooks[event].length });\n }\n\n public async triggerHooks(event: string, context: HookContext) {\n const handlers = this.hooks[event] || [];\n \n if (handlers.length === 0) {\n this.logger.debug('No hooks registered for event', { event });\n return;\n }\n\n this.logger.debug('Triggering hooks', { event, count: handlers.length });\n \n for (const handler of handlers) {\n await handler(context);\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 'actions', 'dashboards', 'reports', 'flows', 'agents',\n 'apis', 'ragPipelines', 'profiles', 'sharingRules'\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\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) {\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 return schema.name; // FQN from registry (e.g., 'todo__task')\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: 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 // TODO: Handle populate/joins mapping if Driver supports it in QueryAST\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 hookContext: HookContext = {\n object,\n event: 'beforeFind',\n input: { ast, options: undefined }, // Should map options?\n ql: this\n };\n await this.triggerHooks('beforeFind', hookContext);\n\n try {\n const result = await driver.find(object, hookContext.input.ast, hookContext.input.options);\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 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 // Reuse find logic or call generic driver.findOne if available\n // Assuming driver has findOne\n return driver.findOne(objectName, ast);\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 hookContext: HookContext = {\n object,\n event: 'beforeInsert',\n input: { data, options },\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, hookContext.input.options);\n } else {\n // Fallback loop\n result = await Promise.all(hookContext.input.data.map((item: any) => driver.create(object, item, hookContext.input.options)));\n }\n } else {\n result = await driver.create(object, hookContext.input.data, hookContext.input.options);\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 async update(object: string, data: any, options?: DataEngineUpdateOptions): Promise<any> {\n object = this.resolveObjectName(object);\n // NOTE: This signature is tricky because Driver expects (obj, id, data) usually.\n // DataEngine protocol puts filter in options.\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 // This is a simplification. Real implementation needs robust filter handling.\n let id = data.id || data._id;\n if (!id && options?.filter) {\n // Optimization: If filter is simple ID check, extract it\n if (typeof options.filter === 'string') id = options.filter;\n else if (options.filter._id) id = options.filter._id;\n else if (options.filter.id) id = options.filter.id;\n }\n\n const hookContext: HookContext = {\n object,\n event: 'beforeUpdate',\n input: { id, data, options },\n ql: this\n };\n await this.triggerHooks('beforeUpdate', hookContext);\n\n try {\n let result;\n if (hookContext.input.id) {\n // Single update by ID\n result = await driver.update(object, hookContext.input.id, hookContext.input.data, hookContext.input.options);\n } else if (options?.multi && driver.updateMany) {\n // Bulk update by Query\n const ast = this.toQueryAST(object, { filter: options.filter });\n result = await driver.updateMany(object, ast, hookContext.input.data, hookContext.input.options);\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 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 else if (options.filter.id) id = options.filter.id;\n }\n\n const hookContext: HookContext = {\n object,\n event: 'beforeDelete',\n input: { id, options },\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, hookContext.input.options);\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);\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 async count(object: string, query?: DataEngineCountOptions): Promise<number> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\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 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 // Driver needs support for raw aggregation or mapped aggregation\n // For now, if driver supports 'execute', we might pass it down, or we need to add 'aggregate' to DriverInterface\n // In this version, we'll assume driver might handle it via special 'find' or throw not implemented\n throw new Error('Aggregate not yet fully implemented in ObjectQL->Driver mapping');\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","import { ObjectQL } from './engine.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 // Respect existing metadata service (e.g. from MetadataPlugin)\n let hasMetadata = false;\n try {\n if (ctx.getService('metadata')) {\n hasMetadata = true;\n }\n } catch (e: any) {\n // Ignore errors during check (e.g. \"Service is async\")\n }\n\n if (!hasMetadata) {\n try {\n ctx.registerService('metadata', this.ql);\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 }\n \n ctx.registerService('data', this.ql); // ObjectQL implements IDataEngine\n ctx.registerService('auth', this.ql);\n \n ctx.logger.info('ObjectQL engine registered as service', { \n provides: ['objectql', 'metadata', 'data', 'auth'] \n });\n\n // Register Protocol Implementation\n const protocolShim = new ObjectStackProtocolImplementation(this.ql);\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 initialized');\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}\n"],"mappings":";AAAA,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,EAMA,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;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;AA3jBa,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;;;ACvI9D,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;AAEO,IAAM,oCAAN,MAAuE;AAAA,EAG1E,YAAY,QAAqB;AAC7B,SAAK,SAAS;AAAA,EAClB;AAAA,EAEA,MAAM,aAAa,UAAc;AAC7B,WAAO;AAAA,MACH,SAAS;AAAA,MACT,SAAS;AAAA,MACT,cAAc;AAAA,QACV,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,WAAW;AAAA,QACX,KAAK;AAAA,MACT;AAAA,MACA,WAAW;AAAA,QACP,MAAM;AAAA,QACN,UAAU;AAAA,QACV,MAAM;AAAA,MACV;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,aAAa,UAAc;AAC7B,WAAO;AAAA,MACH,OAAO,eAAe,mBAAmB;AAAA,IAC7C;AAAA,EACJ;AAAA,EAEA,MAAM,aAAa,SAA+C;AAC9D,WAAO;AAAA,MACH,MAAM,QAAQ;AAAA,MACd,OAAO,eAAe,UAAU,QAAQ,MAAM,QAAQ,SAAS;AAAA,IACnE;AAAA,EACJ;AAAA,EAEA,MAAM,YAAY,SAAyC;AACvD,WAAO;AAAA,MACH,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,MAAM,eAAe,QAAQ,QAAQ,MAAM,QAAQ,IAAI;AAAA,IAC3D;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,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,EACxF,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;AAIrD,UAAM,UAAe,EAAE,GAAG,QAAQ,MAAM;AACxC,QAAI,QAAQ,IAAK,SAAQ,MAAM,OAAO,QAAQ,GAAG;AACjD,QAAI,QAAQ,KAAM,SAAQ,OAAO,OAAO,QAAQ,IAAI;AACpD,QAAI,QAAQ,MAAO,SAAQ,QAAQ,OAAO,QAAQ,KAAK;AAKvD,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,SAAyC;AACnD,UAAM,SAAS,MAAM,KAAK,OAAO,QAAQ,QAAQ,QAAQ;AAAA,MACrD,QAAQ,EAAE,KAAK,QAAQ,GAAG;AAAA,IAC9B,CAAC;AACD,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,OAAO,OAAO;AAAA,MACzB,QAAQ;AAAA,IACZ;AAAA,EACJ;AAAA,EAEA,MAAM,WAAW,SAAoD;AAEjE,UAAM,SAAS,MAAM,KAAK,OAAO,OAAO,QAAQ,QAAQ,QAAQ,MAAM,EAAE,QAAQ,EAAE,KAAK,QAAQ,GAAG,EAAE,CAAC;AACrG,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,KAAK,QAAQ,GAAG,EAAE,CAAC;AACxE,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,UAAyF;AAKrG,UAAM,IAAI,MAAM,gEAAgE;AAAA,EACpF;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,UAA+C;AAEhE,UAAM,IAAI,MAAM,gCAAgC;AAAA,EACpD;AAAA,EAEA,MAAM,eAAe,UAA6B;AAC9C,UAAM,IAAI,MAAM,gCAAgC;AAAA,EACpD;AAAA,EAEA,MAAM,iBAAiB,UAA6B;AAChD,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACtD;AAAA,EAEA,MAAM,kBAAkB,UAA6B;AACjD,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACvD;AAAA,EAEA,MAAM,WAAW,UAA6B;AAC1C,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAChD;AAAA,EAEA,MAAM,YAAY,UAA6B;AAC3C,UAAM,IAAI,MAAM,6BAA6B;AAAA,EACjD;AAAA,EAEA,MAAM,cAAc,UAA6B;AAC7C,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACnD;AAAA,EAEA,MAAM,eAAe,SAA8C;AAE/D,WAAO,KAAK,OAAO,OAAO,QAAQ,QAAQ;AAAA,MACtC,QAAQ,EAAE,KAAK,EAAE,KAAK,QAAQ,IAAI,EAAE;AAAA,MACpC,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;AACJ;;;AC5TA,SAA+C,oBAAoB;AACnE,SAAS,uBAAuB;AAuBzB,IAAM,WAAN,MAAsC;AAAA,EAgB3C,YAAY,cAAmC,CAAC,GAAG;AAfnD,SAAQ,UAAU,oBAAI,IAA6B;AACnD,SAAQ,gBAA+B;AAIvC;AAAA,SAAQ,QAAuC;AAAA,MAC7C,cAAc,CAAC;AAAA,MAAG,aAAa,CAAC;AAAA,MAChC,gBAAgB,CAAC;AAAA,MAAG,eAAe,CAAC;AAAA,MACpC,gBAAgB,CAAC;AAAA,MAAG,eAAe,CAAC;AAAA,MACpC,gBAAgB,CAAC;AAAA,MAAG,eAAe,CAAC;AAAA,IACtC;AAGA;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,EAOA,aAAa,OAAe,SAAsB;AAChD,QAAI,CAAC,KAAK,MAAM,KAAK,GAAG;AACpB,WAAK,MAAM,KAAK,IAAI,CAAC;AAAA,IACzB;AACA,SAAK,MAAM,KAAK,EAAE,KAAK,OAAO;AAC9B,SAAK,OAAO,MAAM,mBAAmB,EAAE,OAAO,eAAe,KAAK,MAAM,KAAK,EAAE,OAAO,CAAC;AAAA,EACzF;AAAA,EAEA,MAAa,aAAa,OAAe,SAAsB;AAC7D,UAAM,WAAW,KAAK,MAAM,KAAK,KAAK,CAAC;AAEvC,QAAI,SAAS,WAAW,GAAG;AACzB,WAAK,OAAO,MAAM,iCAAiC,EAAE,MAAM,CAAC;AAC5D;AAAA,IACF;AAEA,SAAK,OAAO,MAAM,oBAAoB,EAAE,OAAO,OAAO,SAAS,OAAO,CAAC;AAEvE,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,OAAO;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,MACxB;AAAA,MAAW;AAAA,MAAc;AAAA,MAAW;AAAA,MAAS;AAAA,MAC7C;AAAA,MAAQ;AAAA,MAAgB;AAAA,MAAY;AAAA,IACtC;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;AAAA,EACL;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,YAAoB;AAC5B,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;AACV,aAAO,OAAO;AAAA,IAChB;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,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,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,cAA2B;AAAA,MAC7B;AAAA,MACA,OAAO;AAAA,MACP,OAAO,EAAE,KAAK,SAAS,OAAU;AAAA;AAAA,MACjC,IAAI;AAAA,IACR;AACA,UAAM,KAAK,aAAa,cAAc,WAAW;AAEjD,QAAI;AACA,YAAM,SAAS,MAAM,OAAO,KAAK,QAAQ,YAAY,MAAM,KAAK,YAAY,MAAM,OAAO;AAEzF,kBAAY,QAAQ;AACpB,kBAAY,SAAS;AACrB,YAAM,KAAK,aAAa,aAAa,WAAW;AAEhD,aAAO,YAAY;AAAA,IACvB,SAAS,GAAG;AACR,WAAK,OAAO,MAAM,yBAAyB,GAAY,EAAE,OAAO,CAAC;AACjE,YAAM;AAAA,IACV;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;AAIZ,WAAO,OAAO,QAAQ,YAAY,GAAG;AAAA,EACvC;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,cAA2B;AAAA,MAC7B;AAAA,MACA,OAAO;AAAA,MACP,OAAO,EAAE,MAAM,QAAQ;AAAA,MACvB,IAAI;AAAA,IACR;AACA,UAAM,KAAK,aAAa,gBAAgB,WAAW;AAEnD,QAAI;AACF,UAAI;AACJ,UAAI,MAAM,QAAQ,YAAY,MAAM,IAAI,GAAG;AAEzC,YAAI,OAAO,YAAY;AAClB,mBAAS,MAAM,OAAO,WAAW,QAAQ,YAAY,MAAM,MAAM,YAAY,MAAM,OAAO;AAAA,QAC/F,OAAO;AAEF,mBAAS,MAAM,QAAQ,IAAI,YAAY,MAAM,KAAK,IAAI,CAAC,SAAc,OAAO,OAAO,QAAQ,MAAM,YAAY,MAAM,OAAO,CAAC,CAAC;AAAA,QACjI;AAAA,MACF,OAAO;AACL,iBAAS,MAAM,OAAO,OAAO,QAAQ,YAAY,MAAM,MAAM,YAAY,MAAM,OAAO;AAAA,MACxF;AAEA,kBAAY,QAAQ;AACpB,kBAAY,SAAS;AACrB,YAAM,KAAK,aAAa,eAAe,WAAW;AAElD,aAAO,YAAY;AAAA,IACrB,SAAS,GAAG;AACV,WAAK,OAAO,MAAM,2BAA2B,GAAY,EAAE,OAAO,CAAC;AACnE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,QAAgB,MAAW,SAAiD;AACtF,aAAS,KAAK,kBAAkB,MAAM;AAGtC,SAAK,OAAO,MAAM,6BAA6B,EAAE,OAAO,CAAC;AACzD,UAAM,SAAS,KAAK,UAAU,MAAM;AAIpC,QAAI,KAAK,KAAK,MAAM,KAAK;AACzB,QAAI,CAAC,MAAM,SAAS,QAAQ;AAExB,UAAI,OAAO,QAAQ,WAAW,SAAU,MAAK,QAAQ;AAAA,eAC5C,QAAQ,OAAO,IAAK,MAAK,QAAQ,OAAO;AAAA,eACxC,QAAQ,OAAO,GAAI,MAAK,QAAQ,OAAO;AAAA,IACpD;AAEA,UAAM,cAA2B;AAAA,MAC9B;AAAA,MACA,OAAO;AAAA,MACP,OAAO,EAAE,IAAI,MAAM,QAAQ;AAAA,MAC3B,IAAI;AAAA,IACR;AACA,UAAM,KAAK,aAAa,gBAAgB,WAAW;AAElD,QAAI;AACA,UAAI;AACJ,UAAI,YAAY,MAAM,IAAI;AAEtB,iBAAS,MAAM,OAAO,OAAO,QAAQ,YAAY,MAAM,IAAI,YAAY,MAAM,MAAM,YAAY,MAAM,OAAO;AAAA,MAChH,WAAW,SAAS,SAAS,OAAO,YAAY;AAE5C,cAAM,MAAM,KAAK,WAAW,QAAQ,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAC9D,iBAAS,MAAM,OAAO,WAAW,QAAQ,KAAK,YAAY,MAAM,MAAM,YAAY,MAAM,OAAO;AAAA,MACnG,OAAO;AACH,cAAM,IAAI,MAAM,6CAA6C;AAAA,MACjE;AAEA,kBAAY,QAAQ;AACpB,kBAAY,SAAS;AACrB,YAAM,KAAK,aAAa,eAAe,WAAW;AAClD,aAAO,YAAY;AAAA,IACvB,SAAS,GAAG;AACT,WAAK,OAAO,MAAM,2BAA2B,GAAY,EAAE,OAAO,CAAC;AACnE,YAAM;AAAA,IACT;AAAA,EACH;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,IAAK,MAAK,QAAQ,OAAO;AAAA,eACxC,QAAQ,OAAO,GAAI,MAAK,QAAQ,OAAO;AAAA,IACrD;AAEA,UAAM,cAA2B;AAAA,MAC7B;AAAA,MACA,OAAO;AAAA,MACP,OAAO,EAAE,IAAI,QAAQ;AAAA,MACrB,IAAI;AAAA,IACR;AACA,UAAM,KAAK,aAAa,gBAAgB,WAAW;AAEnD,QAAI;AACA,UAAI;AACJ,UAAI,YAAY,MAAM,IAAI;AACtB,iBAAS,MAAM,OAAO,OAAO,QAAQ,YAAY,MAAM,IAAI,YAAY,MAAM,OAAO;AAAA,MACxF,WAAW,SAAS,SAAS,OAAO,YAAY;AAC3C,cAAM,MAAM,KAAK,WAAW,QAAQ,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAC9D,iBAAS,MAAM,OAAO,WAAW,QAAQ,KAAK,YAAY,MAAM,OAAO;AAAA,MAC5E,OAAO;AACF,cAAM,IAAI,MAAM,6CAA6C;AAAA,MAClE;AAEA,kBAAY,QAAQ;AACpB,kBAAY,SAAS;AACrB,YAAM,KAAK,aAAa,eAAe,WAAW;AAClD,aAAO,YAAY;AAAA,IACvB,SAAS,GAAG;AACR,WAAK,OAAO,MAAM,2BAA2B,GAAY,EAAE,OAAO,CAAC;AACnE,YAAM;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,QAAgB,OAAiD;AAC1E,aAAS,KAAK,kBAAkB,MAAM;AACtC,UAAM,SAAS,KAAK,UAAU,MAAM;AACpC,QAAI,OAAO,OAAO;AACd,YAAM,MAAM,KAAK,WAAW,QAAQ,EAAE,QAAQ,OAAO,OAAO,CAAC;AAC7D,aAAO,OAAO,MAAM,QAAQ,GAAG;AAAA,IACnC;AAEA,UAAM,MAAM,MAAM,KAAK,KAAK,QAAQ,EAAE,QAAQ,OAAO,QAAQ,QAAQ,CAAC,KAAK,EAAE,CAAC;AAC9E,WAAO,IAAI;AAAA,EACd;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;AAItE,UAAM,IAAI,MAAM,iEAAiE;AAAA,EACrF;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;AACF;;;AChmBO,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;AACA,YAAI,IAAI,WAAW,UAAU,GAAG;AAC5B,wBAAc;AAAA,QAClB;AAAA,MACJ,SAAS,GAAQ;AAAA,MAEjB;AAEA,UAAI,CAAC,aAAa;AACd,YAAI;AACA,cAAI,gBAAgB,YAAY,KAAK,EAAE;AAAA,QAC3C,SAAS,GAAQ;AAEZ,cAAI,CAAC,EAAE,SAAS,SAAS,oBAAoB,GAAG;AAC5C,kBAAM;AAAA,UACV;AAAA,QACL;AAAA,MACJ;AAEA,UAAI,gBAAgB,QAAQ,KAAK,EAAE;AACnC,UAAI,gBAAgB,QAAQ,KAAK,EAAE;AAEnC,UAAI,OAAO,KAAK,yCAAyC;AAAA,QACrD,UAAU,CAAC,YAAY,YAAY,QAAQ,MAAM;AAAA,MACrD,CAAC;AAGD,YAAM,eAAe,IAAI,kCAAkC,KAAK,EAAE;AAElE,UAAI,gBAAgB,YAAY,YAAY;AAC5C,UAAI,OAAO,KAAK,6BAA6B;AAAA,IAC/C;AAEA,iBAAQ,OAAO,QAAuB;AACpC,UAAI,OAAO,KAAK,6BAA6B;AAG7C,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;AAAA,IACF;AAxEE,QAAI,IAAI;AACJ,WAAK,KAAK;AAAA,IACd,OAAO;AACH,WAAK,cAAc;AAAA,IAEvB;AAAA,EACF;AAmEF;","names":[]}
package/package.json CHANGED
@@ -1,14 +1,21 @@
1
1
  {
2
2
  "name": "@objectstack/objectql",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Isomorphic ObjectQL Engine for ObjectStack",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
8
15
  "dependencies": {
9
- "@objectstack/core": "1.0.10",
10
- "@objectstack/spec": "1.0.10",
11
- "@objectstack/types": "1.0.10"
16
+ "@objectstack/core": "1.0.12",
17
+ "@objectstack/spec": "1.0.12",
18
+ "@objectstack/types": "1.0.12"
12
19
  },
13
20
  "devDependencies": {
14
21
  "typescript": "^5.0.0",
@@ -9,8 +9,23 @@ vi.mock('./registry', () => {
9
9
  return {
10
10
  SchemaRegistry: {
11
11
  getObject: vi.fn((name) => mockObjects.get(name)),
12
- registerObject: vi.fn((obj) => mockObjects.set(obj.name, obj)),
12
+ resolveObject: vi.fn((name) => mockObjects.get(name)),
13
+ registerObject: vi.fn((obj, packageId, namespace, ownership, priority) => {
14
+ const fqn = namespace ? `${namespace}__${obj.name}` : obj.name;
15
+ mockObjects.set(fqn, { ...obj, name: fqn });
16
+ return fqn;
17
+ }),
18
+ registerNamespace: vi.fn(),
13
19
  registerKind: vi.fn(),
20
+ registerItem: vi.fn(),
21
+ registerApp: vi.fn(),
22
+ installPackage: vi.fn((manifest) => ({
23
+ manifest,
24
+ status: 'installed',
25
+ enabled: true,
26
+ installedAt: new Date().toISOString(),
27
+ })),
28
+ reset: vi.fn(() => mockObjects.clear()),
14
29
  metadata: {
15
30
  get: vi.fn(() => mockObjects) // Expose for verification if needed
16
31
  }
@@ -71,16 +86,58 @@ describe('ObjectQL Engine', () => {
71
86
  });
72
87
 
73
88
  describe('Metadata Registration', () => {
74
- it('should register objects from app manifest', () => {
89
+ it('should register objects from app manifest with namespace', () => {
75
90
  const manifest = {
76
91
  id: 'com.example.app',
92
+ namespace: 'example',
77
93
  objects: [
78
94
  { name: 'task', fields: {} }
79
95
  ]
80
96
  };
81
97
 
82
98
  engine.registerApp(manifest);
83
- expect(SchemaRegistry.registerObject).toHaveBeenCalledWith(expect.objectContaining({ name: 'task' }));
99
+ expect(SchemaRegistry.registerObject).toHaveBeenCalledWith(
100
+ expect.objectContaining({ name: 'task' }),
101
+ 'com.example.app',
102
+ 'example',
103
+ 'own'
104
+ );
105
+ });
106
+
107
+ it('should register objects without namespace (legacy)', () => {
108
+ const manifest = {
109
+ id: 'com.legacy.app',
110
+ objects: [
111
+ { name: 'item', fields: {} }
112
+ ]
113
+ };
114
+
115
+ engine.registerApp(manifest);
116
+ expect(SchemaRegistry.registerObject).toHaveBeenCalledWith(
117
+ expect.objectContaining({ name: 'item' }),
118
+ 'com.legacy.app',
119
+ undefined,
120
+ 'own'
121
+ );
122
+ });
123
+
124
+ it('should register object extensions', () => {
125
+ const manifest = {
126
+ id: 'com.extender.app',
127
+ namespace: 'ext',
128
+ objectExtensions: [
129
+ { extend: 'base__contact', fields: { custom_field: { type: 'text' } }, priority: 250 }
130
+ ]
131
+ };
132
+
133
+ engine.registerApp(manifest);
134
+ expect(SchemaRegistry.registerObject).toHaveBeenCalledWith(
135
+ expect.objectContaining({ name: 'base__contact' }),
136
+ 'com.extender.app',
137
+ undefined,
138
+ 'extend',
139
+ 250
140
+ );
84
141
  });
85
142
 
86
143
  it('should register kinds from app manifest', () => {