@objectstack/objectql 4.0.3 → 4.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/registry.ts","../src/protocol.ts","../src/engine.ts","../src/metadata-facade.ts","../src/plugin.ts","../src/kernel-factory.ts","../src/util.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ServiceObject, ObjectSchema, ObjectOwnership } from '@objectstack/spec/data';\nimport { ObjectStackManifest, ManifestSchema, InstalledPackage, InstalledPackageSchema } from '@objectstack/spec/kernel';\nimport { AppSchema } from '@objectstack/spec/ui';\n\n/**\n * Reserved namespaces that do not get FQN prefix applied.\n * Objects in these namespaces keep their short names (e.g., \"user\" not \"base__user\").\n */\nexport const RESERVED_NAMESPACES = new Set(['base', 'system']);\n\n/**\n * Default priorities for ownership types.\n */\nexport const DEFAULT_OWNER_PRIORITY = 100;\nexport const DEFAULT_EXTENDER_PRIORITY = 200;\n\n/**\n * Contributor Record\n * Tracks how a package contributes to an object (own or extend).\n */\nexport interface ObjectContributor {\n packageId: string;\n namespace: string;\n ownership: ObjectOwnership;\n priority: number;\n definition: ServiceObject;\n}\n\n/**\n * Compute Fully Qualified Name (FQN) for an object.\n * \n * @param namespace - The package namespace (e.g., \"crm\", \"todo\")\n * @param shortName - The object's short name (e.g., \"task\", \"account\")\n * @returns FQN string (e.g., \"crm__task\") or just shortName for reserved namespaces\n * \n * @example\n * computeFQN('crm', 'account') // => 'crm__account'\n * computeFQN('base', 'user') // => 'user' (reserved, no prefix)\n * computeFQN(undefined, 'task') // => 'task' (legacy, no namespace)\n */\nexport function computeFQN(namespace: string | undefined, shortName: string): string {\n if (!namespace || RESERVED_NAMESPACES.has(namespace)) {\n return shortName;\n }\n return `${namespace}__${shortName}`;\n}\n\n/**\n * Parse FQN back to namespace and short name.\n * \n * @param fqn - Fully qualified name (e.g., \"crm__account\" or \"user\")\n * @returns { namespace, shortName } - namespace is undefined for unprefixed names\n */\nexport function parseFQN(fqn: string): { namespace: string | undefined; shortName: string } {\n const idx = fqn.indexOf('__');\n if (idx === -1) {\n return { namespace: undefined, shortName: fqn };\n }\n return {\n namespace: fqn.slice(0, idx),\n shortName: fqn.slice(idx + 2),\n };\n}\n\n/**\n * Deep merge two ServiceObject definitions.\n * Fields are merged additively. Other props: later value wins.\n */\nfunction mergeObjectDefinitions(base: ServiceObject, extension: Partial<ServiceObject>): ServiceObject {\n const merged = { ...base };\n\n // Merge fields additively\n if (extension.fields) {\n merged.fields = { ...base.fields, ...extension.fields };\n }\n\n // Merge validations additively\n if (extension.validations) {\n merged.validations = [...(base.validations || []), ...extension.validations];\n }\n\n // Merge indexes additively\n if (extension.indexes) {\n merged.indexes = [...(base.indexes || []), ...extension.indexes];\n }\n\n // Override scalar props (last writer wins)\n if (extension.label !== undefined) merged.label = extension.label;\n if (extension.pluralLabel !== undefined) merged.pluralLabel = extension.pluralLabel;\n if (extension.description !== undefined) merged.description = extension.description;\n\n return merged;\n}\n\n/**\n * Global Schema Registry\n * Unified storage for all metadata types (Objects, Apps, Flows, Layouts, etc.)\n * \n * ## Namespace & Ownership Model\n * \n * Objects use a namespace-based FQN system:\n * - `namespace`: Short identifier from package manifest (e.g., \"crm\", \"todo\")\n * - `FQN`: `{namespace}__{short_name}` (e.g., \"crm__account\")\n * - Reserved namespaces (`base`, `system`) don't get prefixed\n * \n * Ownership modes:\n * - `own`: One package owns the object (creates the table, defines base schema)\n * - `extend`: Multiple packages can extend an object (add fields, merge by priority)\n * \n * ## Package vs App Distinction\n * - **Package**: The unit of installation, stored under type 'package'.\n * Each InstalledPackage wraps a ManifestSchema with lifecycle state.\n * - **App**: A UI navigation shell (AppSchema), registered under type 'apps'.\n * Apps are extracted from packages during registration.\n * - A package may contain 0, 1, or many apps.\n */\nexport type RegistryLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\n\nexport class SchemaRegistry {\n // ==========================================\n // Logging control\n // ==========================================\n\n /** Controls verbosity of registry console messages. Default: 'info'. */\n private static _logLevel: RegistryLogLevel = 'info';\n\n static get logLevel(): RegistryLogLevel { return this._logLevel; }\n static set logLevel(level: RegistryLogLevel) { this._logLevel = level; }\n\n private static log(msg: string): void {\n if (this._logLevel === 'silent' || this._logLevel === 'error' || this._logLevel === 'warn') return;\n console.log(msg);\n }\n\n // ==========================================\n // Object-specific storage (Ownership Model)\n // ==========================================\n \n /** FQN → Contributor[] (all packages that own/extend this object) */\n private static objectContributors = new Map<string, ObjectContributor[]>();\n \n /** FQN → Merged ServiceObject (cached, invalidated on changes) */\n private static mergedObjectCache = new Map<string, ServiceObject>();\n \n /** Namespace → Set<PackageId> (multiple packages can share a namespace) */\n private static namespaceRegistry = new Map<string, Set<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 * Multiple packages can share the same namespace (e.g. 'sys').\n */\n static registerNamespace(namespace: string, packageId: string): void {\n if (!namespace) return;\n\n let owners = this.namespaceRegistry.get(namespace);\n if (!owners) {\n owners = new Set();\n this.namespaceRegistry.set(namespace, owners);\n }\n owners.add(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 owners = this.namespaceRegistry.get(namespace);\n if (owners) {\n owners.delete(packageId);\n if (owners.size === 0) {\n this.namespaceRegistry.delete(namespace);\n }\n this.log(`[Registry] Unregistered namespace: ${namespace} ← ${packageId}`);\n }\n }\n\n /**\n * Get the packages that use a namespace.\n */\n static getNamespaceOwner(namespace: string): string | undefined {\n const owners = this.namespaceRegistry.get(namespace);\n if (!owners || owners.size === 0) return undefined;\n // Return the first registered package for backwards compatibility\n return owners.values().next().value;\n }\n\n /**\n * Get all packages that share a namespace.\n */\n static getNamespaceOwners(namespace: string): string[] {\n const owners = this.namespaceRegistry.get(namespace);\n return owners ? Array.from(owners) : [];\n }\n\n // ==========================================\n // Object Registration (Ownership Model)\n // ==========================================\n\n /**\n * Register an object with ownership semantics.\n * \n * @param schema - The object definition\n * @param packageId - The owning package ID\n * @param namespace - The package namespace (for FQN computation)\n * @param ownership - 'own' (single owner) or 'extend' (additive merge)\n * @param priority - Merge priority (lower applied first, higher wins on conflict)\n * \n * @throws Error if trying to 'own' an object that already has an owner\n */\n static registerObject(\n schema: ServiceObject,\n packageId: string,\n namespace?: string,\n ownership: ObjectOwnership = 'own',\n priority: number = ownership === 'own' ? DEFAULT_OWNER_PRIORITY : DEFAULT_EXTENDER_PRIORITY\n ): string {\n const shortName = schema.name;\n const fqn = computeFQN(namespace, shortName);\n\n // Ensure namespace is registered\n if (namespace) {\n this.registerNamespace(namespace, packageId);\n }\n\n // Get or create contributor list\n let contributors = this.objectContributors.get(fqn);\n if (!contributors) {\n contributors = [];\n this.objectContributors.set(fqn, contributors);\n }\n\n // Validate ownership rules\n if (ownership === 'own') {\n const existingOwner = contributors.find(c => c.ownership === 'own');\n if (existingOwner && existingOwner.packageId !== packageId) {\n throw new Error(\n `Object \"${fqn}\" is already owned by package \"${existingOwner.packageId}\". ` +\n `Package \"${packageId}\" cannot claim ownership. Use 'extend' to add fields.`\n );\n }\n // Remove existing owner contribution from same package (re-registration)\n const idx = contributors.findIndex(c => c.packageId === packageId && c.ownership === 'own');\n if (idx !== -1) {\n contributors.splice(idx, 1);\n console.warn(`[Registry] Re-registering owned object: ${fqn} from ${packageId}`);\n }\n } else {\n // extend mode: remove existing extension from same package\n const idx = contributors.findIndex(c => c.packageId === packageId && c.ownership === 'extend');\n if (idx !== -1) {\n contributors.splice(idx, 1);\n }\n }\n\n // Add new contributor\n const contributor: ObjectContributor = {\n packageId,\n namespace: namespace || '',\n ownership,\n priority,\n definition: { ...schema, name: fqn }, // Store with FQN as name\n };\n contributors.push(contributor);\n\n // Sort by priority (ascending: lower priority applied first)\n contributors.sort((a, b) => a.priority - b.priority);\n\n // Invalidate merge cache\n this.mergedObjectCache.delete(fqn);\n\n this.log(`[Registry] Registered object: ${fqn} (${ownership}, priority=${priority}) from ${packageId}`);\n return fqn;\n }\n\n /**\n * Resolve an object by FQN, merging all contributions.\n * Returns the merged object or undefined if not found.\n */\n static resolveObject(fqn: string): ServiceObject | undefined {\n // Check cache first\n const cached = this.mergedObjectCache.get(fqn);\n if (cached) return cached;\n\n const contributors = this.objectContributors.get(fqn);\n if (!contributors || contributors.length === 0) {\n return undefined;\n }\n\n // Find owner (must exist for a valid object)\n const ownerContrib = contributors.find(c => c.ownership === 'own');\n if (!ownerContrib) {\n console.warn(`[Registry] Object \"${fqn}\" has extenders but no owner. Skipping.`);\n return undefined;\n }\n\n // Start with owner's definition\n let merged = { ...ownerContrib.definition };\n\n // Apply extensions in priority order (already sorted)\n for (const contrib of contributors) {\n if (contrib.ownership === 'extend') {\n merged = mergeObjectDefinitions(merged, contrib.definition);\n }\n }\n\n // Cache the result\n this.mergedObjectCache.set(fqn, merged);\n return merged;\n }\n\n /**\n * Get object by name (FQN, short name, or physical table name).\n *\n * Resolution order:\n * 1. Exact FQN match (e.g., 'crm__account')\n * 2. Short name fallback (e.g., 'account' → 'crm__account')\n * 3. Physical table name match (e.g., 'sys_user' → 'sys__user')\n * ObjectSchema.create() auto-derives tableName as {namespace}_{name},\n * which uses a single underscore — different from the FQN double underscore.\n */\n static getObject(name: string): ServiceObject | undefined {\n // Direct FQN lookup\n const direct = this.resolveObject(name);\n if (direct) return direct;\n\n // Fallback: scan for objects ending with the short name\n // This handles legacy code that doesn't use FQN\n for (const fqn of this.objectContributors.keys()) {\n const { shortName } = parseFQN(fqn);\n if (shortName === name) {\n return this.resolveObject(fqn);\n }\n }\n\n // Fallback: match by physical table name (e.g., 'sys_user' → FQN 'sys__user')\n // This bridges the gap between protocol names (SystemObjectName) and FQN.\n for (const fqn of this.objectContributors.keys()) {\n const resolved = this.resolveObject(fqn);\n if (resolved?.tableName === name) {\n return resolved;\n }\n }\n\n return undefined;\n }\n\n /**\n * Get all registered objects (merged).\n * \n * @param packageId - Optional filter: only objects contributed by this package\n */\n static getAllObjects(packageId?: string): ServiceObject[] {\n const results: ServiceObject[] = [];\n\n for (const fqn of this.objectContributors.keys()) {\n // If filtering by package, check if this package contributes\n if (packageId) {\n const contributors = this.objectContributors.get(fqn);\n const hasContribution = contributors?.some(c => c.packageId === packageId);\n if (!hasContribution) continue;\n }\n\n const merged = this.resolveObject(fqn);\n if (merged) {\n // Tag with contributor info for UI\n (merged as any)._packageId = this.getObjectOwner(fqn)?.packageId;\n results.push(merged);\n }\n }\n\n return results;\n }\n\n /**\n * Get all contributors for an object.\n */\n static getObjectContributors(fqn: string): ObjectContributor[] {\n return this.objectContributors.get(fqn) || [];\n }\n\n /**\n * Get the owner contributor for an object.\n */\n static getObjectOwner(fqn: string): ObjectContributor | undefined {\n const contributors = this.objectContributors.get(fqn);\n return contributors?.find(c => c.ownership === 'own');\n }\n\n /**\n * Unregister all objects contributed by a package.\n * \n * @throws Error if trying to uninstall an owner that has extenders\n */\n static unregisterObjectsByPackage(packageId: string, force: boolean = false): void {\n for (const [fqn, contributors] of this.objectContributors.entries()) {\n // Find this package's contributions\n const packageContribs = contributors.filter(c => c.packageId === packageId);\n \n for (const contrib of packageContribs) {\n if (contrib.ownership === 'own' && !force) {\n // Check if there are extenders from other packages\n const otherExtenders = contributors.filter(\n c => c.packageId !== packageId && c.ownership === 'extend'\n );\n if (otherExtenders.length > 0) {\n throw new Error(\n `Cannot uninstall package \"${packageId}\": object \"${fqn}\" is extended by ` +\n `${otherExtenders.map(c => c.packageId).join(', ')}. Uninstall extenders first.`\n );\n }\n }\n\n // Remove contribution\n const idx = contributors.indexOf(contrib);\n if (idx !== -1) {\n contributors.splice(idx, 1);\n this.log(`[Registry] Removed ${contrib.ownership} contribution to ${fqn} from ${packageId}`);\n }\n }\n\n // Clean up empty contributor lists\n if (contributors.length === 0) {\n this.objectContributors.delete(fqn);\n }\n\n // Invalidate cache\n this.mergedObjectCache.delete(fqn);\n }\n }\n\n // ==========================================\n // Generic Metadata (Non-Object Types)\n // ==========================================\n\n /**\n * Universal Register Method for non-object metadata.\n */\n static registerItem<T>(type: string, item: T, keyField: keyof T = 'name' as keyof T, packageId?: string) {\n if (!this.metadata.has(type)) {\n this.metadata.set(type, new Map());\n }\n const collection = this.metadata.get(type)!;\n const baseName = String(item[keyField]);\n \n // Tag item with owning package for scoped queries\n if (packageId) {\n (item as any)._packageId = packageId;\n }\n\n // Validation Hook\n try {\n this.validate(type, item);\n } catch (e: any) {\n console.error(`[Registry] Validation failed for ${type} ${baseName}: ${e.message}`);\n }\n\n // Use composite key (packageId:name) when packageId is provided\n const storageKey = packageId ? `${packageId}:${baseName}` : baseName;\n\n if (collection.has(storageKey)) {\n console.warn(`[Registry] Overwriting ${type}: ${storageKey}`);\n }\n collection.set(storageKey, item);\n this.log(`[Registry] Registered ${type}: ${storageKey}`);\n }\n\n /**\n * Validate Metadata against Spec Zod Schemas\n */\n static validate(type: string, item: any) {\n if (type === 'object') {\n return ObjectSchema.parse(item);\n }\n if (type === 'app') {\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('app', app, 'name', packageId);\n }\n\n static getApp(name: string): any {\n return this.getItem('app', name);\n }\n\n static getAllApps(): any[] {\n return this.listItems('app');\n }\n\n // ==========================================\n // Plugin Helpers\n // ==========================================\n\n static registerPlugin(manifest: ObjectStackManifest) {\n this.registerItem('plugin', manifest, 'id');\n }\n\n static getAllPlugins(): ObjectStackManifest[] {\n return this.listItems<ObjectStackManifest>('plugin');\n }\n\n // ==========================================\n // Kind Helpers\n // ==========================================\n\n static registerKind(kind: { id: string, globs: string[] }) {\n this.registerItem('kind', kind, 'id');\n }\n \n static getAllKinds(): { id: string, globs: string[] }[] {\n return this.listItems('kind');\n }\n\n // ==========================================\n // Reset (for testing)\n // ==========================================\n\n /**\n * Clear all registry state. Use only for testing.\n */\n static reset(): void {\n this.objectContributors.clear();\n this.mergedObjectCache.clear();\n this.namespaceRegistry.clear();\n this.metadata.clear();\n this.log('[Registry] Reset complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { IDataEngine } from '@objectstack/core';\nimport type {\n BatchUpdateRequest,\n BatchUpdateResponse,\n UpdateManyDataRequest,\n DeleteManyDataRequest\n} from '@objectstack/spec/api';\nimport type { MetadataCacheRequest, MetadataCacheResponse, ServiceInfo, ApiRoutes, WellKnownCapabilities } from '@objectstack/spec/api';\nimport type { IFeedService } from '@objectstack/spec/contracts';\nimport { parseFilterAST, isFilterAST } from '@objectstack/spec/data';\nimport { PLURAL_TO_SINGULAR, SINGULAR_TO_PLURAL } from '@objectstack/spec/shared';\n\n// We import SchemaRegistry directly since this class lives in the same package\nimport { SchemaRegistry } from './registry.js';\n\n/**\n * Simple hash function for ETag generation (browser-compatible)\n * Uses a basic hash algorithm instead of crypto.createHash\n */\nfunction simpleHash(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return Math.abs(hash).toString(16);\n}\n\n/**\n * Service Configuration for Discovery\n * Maps service names to their routes and plugin providers\n */\nconst SERVICE_CONFIG: Record<string, { route: string; plugin: string }> = {\n auth: { route: '/api/v1/auth', plugin: 'plugin-auth' },\n automation: { route: '/api/v1/automation', plugin: 'plugin-automation' },\n cache: { route: '/api/v1/cache', plugin: 'plugin-redis' },\n queue: { route: '/api/v1/queue', plugin: 'plugin-bullmq' },\n job: { route: '/api/v1/jobs', plugin: 'job-scheduler' },\n ui: { route: '/api/v1/ui', plugin: 'ui-plugin' },\n workflow: { route: '/api/v1/workflow', plugin: 'plugin-workflow' },\n realtime: { route: '/api/v1/realtime', plugin: 'plugin-realtime' },\n notification: { route: '/api/v1/notifications', plugin: 'plugin-notifications' },\n ai: { route: '/api/v1/ai', plugin: 'plugin-ai' },\n i18n: { route: '/api/v1/i18n', plugin: 'service-i18n' },\n graphql: { route: '/graphql', plugin: 'plugin-graphql' }, // GraphQL uses /graphql by convention (not versioned REST)\n 'file-storage': { route: '/api/v1/storage', plugin: 'plugin-storage' },\n search: { route: '/api/v1/search', plugin: 'plugin-search' },\n};\n\nexport class ObjectStackProtocolImplementation implements ObjectStackProtocol {\n private engine: IDataEngine;\n private getServicesRegistry?: () => Map<string, any>;\n private getFeedService?: () => IFeedService | undefined;\n\n constructor(engine: IDataEngine, getServicesRegistry?: () => Map<string, any>, getFeedService?: () => IFeedService | undefined) {\n this.engine = engine;\n this.getServicesRegistry = getServicesRegistry;\n this.getFeedService = getFeedService;\n }\n\n private requireFeedService(): IFeedService {\n const svc = this.getFeedService?.();\n if (!svc) {\n throw new Error('Feed service not available. Install and register service-feed to enable feed operations.');\n }\n return svc;\n }\n\n async getDiscovery() {\n // Get registered services from kernel if available\n const registeredServices = this.getServicesRegistry ? this.getServicesRegistry() : new Map();\n \n // Build dynamic service info with proper typing\n const services: Record<string, ServiceInfo> = {\n // --- Kernel-provided (objectql is an example kernel implementation) ---\n metadata: { enabled: true, status: 'available' as const, route: '/api/v1/meta', provider: 'objectql' },\n data: { enabled: true, status: 'available' as const, route: '/api/v1/data', provider: 'objectql' },\n analytics: { enabled: true, status: 'available' as const, route: '/api/v1/analytics', provider: 'objectql' },\n };\n\n // Check which services are actually registered\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n // Service is registered and available\n services[serviceName] = {\n enabled: true,\n status: 'available' as const,\n route: config.route,\n provider: config.plugin,\n };\n } else {\n // Service is not registered\n services[serviceName] = {\n enabled: false,\n status: 'unavailable' as const,\n message: `Install ${config.plugin} to enable`,\n };\n }\n }\n\n // Build routes from services — a flat convenience map for client routing\n const serviceToRouteKey: Record<string, keyof ApiRoutes> = {\n auth: 'auth',\n automation: 'automation',\n ui: 'ui',\n workflow: 'workflow',\n realtime: 'realtime',\n notification: 'notifications',\n ai: 'ai',\n i18n: 'i18n',\n graphql: 'graphql',\n 'file-storage': 'storage',\n };\n\n const optionalRoutes: Partial<ApiRoutes> = {\n analytics: '/api/v1/analytics',\n };\n\n // Add routes for available plugin services\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n const routeKey = serviceToRouteKey[serviceName];\n if (routeKey) {\n optionalRoutes[routeKey] = config.route;\n }\n }\n }\n\n // Add feed service status\n if (registeredServices.has('feed')) {\n services['feed'] = {\n enabled: true,\n status: 'available' as const,\n route: '/api/v1/data',\n provider: 'service-feed',\n };\n } else {\n services['feed'] = {\n enabled: false,\n status: 'unavailable' as const,\n message: 'Install service-feed to enable',\n };\n }\n\n const routes: ApiRoutes = {\n data: '/api/v1/data',\n metadata: '/api/v1/meta',\n ...optionalRoutes,\n };\n\n // Build well-known capabilities from registered services.\n // DiscoverySchema defines capabilities as Record<string, { enabled, features?, description? }>\n // (hierarchical format). We also keep a flat WellKnownCapabilities for backward compat.\n const wellKnown: WellKnownCapabilities = {\n feed: registeredServices.has('feed'),\n comments: registeredServices.has('feed'),\n automation: registeredServices.has('automation'),\n cron: registeredServices.has('job'),\n search: registeredServices.has('search'),\n export: registeredServices.has('automation') || registeredServices.has('queue'),\n chunkedUpload: registeredServices.has('file-storage'),\n };\n\n // Convert flat booleans → hierarchical capability objects\n const capabilities: Record<string, { enabled: boolean; description?: string }> = {};\n for (const [key, enabled] of Object.entries(wellKnown)) {\n capabilities[key] = { enabled };\n }\n\n return {\n version: '1.0',\n apiName: 'ObjectStack API',\n routes,\n services,\n capabilities,\n };\n }\n\n async getMetaTypes() {\n const schemaTypes = SchemaRegistry.getRegisteredTypes();\n\n // Also include types from MetadataService (runtime-registered: agent, tool, etc.)\n let runtimeTypes: string[] = [];\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.getRegisteredTypes === 'function') {\n runtimeTypes = await metadataService.getRegisteredTypes();\n }\n } catch {\n // MetadataService not available\n }\n\n const allTypes = Array.from(new Set([...schemaTypes, ...runtimeTypes]));\n return { types: allTypes };\n }\n\n async getMetaItems(request: { type: string; packageId?: string }) {\n const { packageId } = request;\n let items = SchemaRegistry.listItems(request.type, packageId);\n // Normalize singular/plural using explicit mapping\n if (items.length === 0) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) items = SchemaRegistry.listItems(alt, packageId);\n }\n\n // Fallback to database if registry is empty for this type\n if (items.length === 0) {\n try {\n const whereClause: any = { type: request.type, state: 'active' };\n if (packageId) whereClause._packageId = packageId;\n const allRecords = await this.engine.find('sys_metadata', {\n where: whereClause\n });\n if (allRecords && allRecords.length > 0) {\n items = allRecords.map((record: any) => {\n const data = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n // Hydrate back into registry\n SchemaRegistry.registerItem(request.type, data, 'name' as any);\n return data;\n });\n } else {\n // Try alternate type name in DB using explicit mapping\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altRecords = await this.engine.find('sys_metadata', {\n where: { type: alt, state: 'active' }\n });\n if (altRecords && altRecords.length > 0) {\n items = altRecords.map((record: any) => {\n const data = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n SchemaRegistry.registerItem(request.type, data, 'name' as any);\n return data;\n });\n }\n }\n }\n } catch {\n // DB not available, return registry results (empty)\n }\n }\n\n // Merge with MetadataService (runtime-registered items: agents, tools, etc.)\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.list === 'function') {\n const runtimeItems = await metadataService.list(request.type);\n if (runtimeItems && runtimeItems.length > 0) {\n // Merge, avoiding duplicates by name\n const itemMap = new Map<string, any>();\n for (const item of items) {\n const entry = item as any;\n if (entry && typeof entry === 'object' && 'name' in entry) {\n itemMap.set(entry.name, entry);\n }\n }\n for (const item of runtimeItems) {\n const entry = item as any;\n if (entry && typeof entry === 'object' && 'name' in entry) {\n itemMap.set(entry.name, entry);\n }\n }\n items = Array.from(itemMap.values());\n }\n }\n } catch {\n // MetadataService not available or doesn't support this type\n }\n\n return {\n type: request.type,\n items\n };\n }\n\n async getMetaItem(request: { type: string, name: string, packageId?: string }) {\n let item = SchemaRegistry.getItem(request.type, request.name);\n // Normalize singular/plural using explicit mapping\n if (item === undefined) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) item = SchemaRegistry.getItem(alt, request.name);\n }\n\n // Fallback to database if not in registry\n if (item === undefined) {\n try {\n const record = await this.engine.findOne('sys_metadata', {\n where: { type: request.type, name: request.name, state: 'active' }\n });\n if (record) {\n item = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n // Hydrate back into registry for next time\n SchemaRegistry.registerItem(request.type, item, 'name' as any);\n } else {\n // Try alternate type name using explicit mapping\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altRecord = await this.engine.findOne('sys_metadata', {\n where: { type: alt, name: request.name, state: 'active' }\n });\n if (altRecord) {\n item = typeof altRecord.metadata === 'string'\n ? JSON.parse(altRecord.metadata)\n : altRecord.metadata;\n // Hydrate back into registry for next time\n SchemaRegistry.registerItem(request.type, item, 'name' as any);\n }\n }\n }\n } catch {\n // DB not available, return undefined\n }\n }\n\n // Fallback to MetadataService for runtime-registered items (agents, tools, etc.)\n if (item === undefined) {\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.get === 'function') {\n item = await metadataService.get(request.type, request.name);\n }\n } catch {\n // MetadataService not available\n }\n }\n\n return {\n type: request.type,\n name: request.name,\n item\n };\n }\n\n async getUiView(request: { object: string, type: 'list' | 'form' }) {\n const schema = SchemaRegistry.getObject(request.object);\n if (!schema) throw new Error(`Object ${request.object} not found`);\n\n const fields = schema.fields || {};\n const fieldKeys = Object.keys(fields);\n\n if (request.type === 'list') {\n // Intelligent Column Selection\n // 1. Always include 'name' or name-like fields\n // 2. Limit to 6 columns by default\n const priorityFields = ['name', 'title', 'label', 'subject', 'email', 'status', 'type', 'category', 'created_at'];\n \n let columns = fieldKeys.filter(k => priorityFields.includes(k));\n \n // If few priority fields, add others until 5\n if (columns.length < 5) {\n const remaining = fieldKeys.filter(k => !columns.includes(k) && k !== 'id' && !fields[k].hidden);\n columns = [...columns, ...remaining.slice(0, 5 - columns.length)];\n }\n \n // Sort columns by priority then alphabet or schema order\n // For now, just keep them roughly in order they appear in schema or priority list\n \n return {\n list: {\n type: 'grid' as const,\n object: request.object,\n label: schema.label || schema.name,\n columns: columns.map(f => ({\n field: f,\n label: fields[f]?.label || f,\n sortable: true\n })),\n sort: fields['created_at'] ? ([{ field: 'created_at', order: 'desc' }] as any) : undefined,\n searchableFields: columns.slice(0, 3) // Make first few textual columns searchable\n }\n };\n } else {\n // Form View Generation\n // Simple single-section layout for now\n const formFields = fieldKeys\n .filter(k => k !== 'id' && k !== 'created_at' && k !== 'updated_at' && !fields[k].hidden)\n .map(f => ({\n field: f,\n label: fields[f]?.label,\n required: fields[f]?.required,\n readonly: fields[f]?.readonly,\n type: fields[f]?.type,\n // Default to 2 columns for most, 1 for textareas\n colSpan: (fields[f]?.type === 'textarea' || fields[f]?.type === 'html') ? 2 : 1\n }));\n\n return {\n form: {\n type: 'simple' as const,\n object: request.object,\n label: `Edit ${schema.label || schema.name}`,\n sections: [\n {\n label: 'General Information',\n columns: 2 as const,\n collapsible: false,\n collapsed: false,\n fields: formFields\n }\n ]\n }\n };\n }\n }\n\n async findData(request: { object: string, query?: any }) {\n const options: any = { ...request.query };\n\n // ====================================================================\n // Normalize legacy params → QueryAST standard (where/fields/orderBy/offset/expand)\n // ====================================================================\n\n // Numeric fields — normalize top → limit, skip → offset\n if (options.top != null) {\n options.limit = Number(options.top);\n delete options.top;\n }\n if (options.skip != null) {\n options.offset = Number(options.skip);\n delete options.skip;\n }\n if (options.limit != null) options.limit = Number(options.limit);\n if (options.offset != null) options.offset = Number(options.offset);\n\n // Select → fields: comma-separated string → array\n if (typeof options.select === 'string') {\n options.fields = options.select.split(',').map((s: string) => s.trim()).filter(Boolean);\n } else if (Array.isArray(options.select)) {\n options.fields = options.select;\n }\n if (options.select !== undefined) delete options.select;\n\n // Sort/orderBy → orderBy: string → SortNode[] array\n const sortValue = options.orderBy ?? options.sort;\n if (typeof sortValue === 'string') {\n const parsed = sortValue.split(',').map((part: string) => {\n const trimmed = part.trim();\n if (trimmed.startsWith('-')) {\n return { field: trimmed.slice(1), order: 'desc' as const };\n }\n const [field, order] = trimmed.split(/\\s+/);\n return { field, order: (order?.toLowerCase() === 'desc' ? 'desc' : 'asc') as 'asc' | 'desc' };\n }).filter((s: any) => s.field);\n options.orderBy = parsed;\n } else if (Array.isArray(sortValue)) {\n options.orderBy = sortValue;\n }\n delete options.sort;\n\n // Filter/filters/$filter → where: normalize all filter aliases\n const filterValue = options.filter ?? options.filters ?? options.$filter ?? options.where;\n delete options.filter;\n delete options.filters;\n delete options.$filter;\n\n if (filterValue !== undefined) {\n let parsedFilter = filterValue;\n // JSON string → object\n if (typeof parsedFilter === 'string') {\n try { parsedFilter = JSON.parse(parsedFilter); } catch { /* keep as-is */ }\n }\n // Filter AST array → FilterCondition object\n if (isFilterAST(parsedFilter)) {\n parsedFilter = parseFilterAST(parsedFilter);\n }\n options.where = parsedFilter;\n }\n\n // Populate/expand/$expand → expand (Record<string, QueryAST>)\n const populateValue = options.populate;\n const expandValue = options.$expand ?? options.expand;\n const expandNames: string[] = [];\n if (typeof populateValue === 'string') {\n expandNames.push(...populateValue.split(',').map((s: string) => s.trim()).filter(Boolean));\n } else if (Array.isArray(populateValue)) {\n expandNames.push(...populateValue);\n }\n if (!expandNames.length && expandValue) {\n if (typeof expandValue === 'string') {\n expandNames.push(...expandValue.split(',').map((s: string) => s.trim()).filter(Boolean));\n } else if (Array.isArray(expandValue)) {\n expandNames.push(...expandValue);\n }\n }\n delete options.populate;\n delete options.$expand;\n // Clean up non-object expand (e.g. string) BEFORE the Record conversion\n // below, so that populate-derived names can create the expand Record even\n // when a legacy string expand was also present.\n if (typeof options.expand !== 'object' || options.expand === null) {\n delete options.expand;\n }\n // Only set expand if not already an object (advanced usage)\n if (expandNames.length > 0 && !options.expand) {\n options.expand = {} as Record<string, any>;\n for (const rel of expandNames) {\n options.expand[rel] = { object: rel };\n }\n }\n\n // Boolean fields\n for (const key of ['distinct', 'count']) {\n if (options[key] === 'true') options[key] = true;\n else if (options[key] === 'false') options[key] = false;\n }\n \n // Flat field filters: REST-style query params like ?id=abc&status=open\n // After extracting all known query parameters, any remaining keys are\n // treated as implicit field-level equality filters merged into `where`.\n const knownParams = new Set([\n 'top', 'limit', 'offset',\n 'orderBy',\n 'fields',\n 'where',\n 'expand',\n 'distinct', 'count',\n 'aggregations', 'groupBy',\n 'search', 'context', 'cursor',\n ]);\n if (!options.where) {\n const implicitFilters: Record<string, unknown> = {};\n for (const key of Object.keys(options)) {\n if (!knownParams.has(key)) {\n implicitFilters[key] = options[key];\n delete options[key];\n }\n }\n if (Object.keys(implicitFilters).length > 0) {\n options.where = implicitFilters;\n }\n }\n \n const records = await this.engine.find(request.object, options);\n // Spec: FindDataResponseSchema — only `records` is returned.\n // OData `value` adaptation (if needed) is handled in the HTTP dispatch layer.\n return {\n object: request.object,\n records,\n total: records.length,\n hasMore: false\n };\n }\n\n async getData(request: { object: string, id: string, expand?: string | string[], select?: string | string[] }) {\n const queryOptions: any = {\n where: { id: request.id }\n };\n\n // Support fields for single-record retrieval\n if (request.select) {\n queryOptions.fields = typeof request.select === 'string'\n ? request.select.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.select;\n }\n\n // Support expand for single-record retrieval\n if (request.expand) {\n const expandNames = typeof request.expand === 'string'\n ? request.expand.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.expand;\n queryOptions.expand = {} as Record<string, any>;\n for (const rel of expandNames) {\n queryOptions.expand[rel] = { object: rel };\n }\n }\n\n const result = await this.engine.findOne(request.object, queryOptions);\n if (result) {\n return {\n object: request.object,\n id: request.id,\n record: result\n };\n }\n throw new Error(`Record ${request.id} not found in ${request.object}`);\n }\n\n async createData(request: { object: string, data: any }) {\n const result = await this.engine.insert(request.object, request.data);\n return {\n object: request.object,\n id: result.id,\n record: result\n };\n }\n\n async updateData(request: { object: string, id: string, data: any }) {\n // Adapt: update(obj, id, data) -> update(obj, data, options)\n const result = await this.engine.update(request.object, request.data, { where: { 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, { where: { 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 let item = SchemaRegistry.getItem(request.type, request.name);\n\n // Normalize singular/plural using explicit mapping\n if (!item) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) item = SchemaRegistry.getItem(alt, request.name);\n }\n\n // Fallback to MetadataService (e.g. agents, tools registered in MetadataManager)\n if (!item) {\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.get === 'function') {\n item = await metadataService.get(request.type, request.name);\n }\n } catch {\n // MetadataService not available\n }\n }\n\n if (!item) {\n throw new Error(`Metadata item ${request.type}/${request.name} not found`);\n }\n\n // Calculate ETag (simple hash of the stringified metadata)\n const content = JSON.stringify(item);\n const hash = simpleHash(content);\n const etag = { value: hash, weak: false };\n\n // Check If-None-Match header\n if (request.cacheRequest?.ifNoneMatch) {\n const clientEtag = request.cacheRequest.ifNoneMatch.replace(/^\"(.*)\"$/, '$1').replace(/^W\\/\"(.*)\"$/, '$1');\n if (clientEtag === hash) {\n // Return 304 Not Modified\n return {\n notModified: true,\n etag,\n };\n }\n }\n\n // Return full metadata with cache headers\n return {\n data: item,\n etag,\n lastModified: new Date().toISOString(),\n cacheControl: {\n directives: ['public', 'max-age'],\n maxAge: 3600, // 1 hour\n },\n notModified: false,\n };\n } catch (error: any) {\n throw error;\n }\n }\n\n // ==========================================\n // Batch Operations\n // ==========================================\n\n async batchData(request: { object: string, request: BatchUpdateRequest }): Promise<BatchUpdateResponse> {\n const { object, request: batchReq } = request;\n const { operation, records, options } = batchReq;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n switch (operation) {\n case 'create': {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n succeeded++;\n break;\n }\n case 'update': {\n if (!record.id) throw new Error('Record id is required for update');\n const updated = await this.engine.update(object, record.data || {}, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n break;\n }\n case 'upsert': {\n // Try update first, then create if not found\n if (record.id) {\n try {\n const existing = await this.engine.findOne(object, { where: { id: record.id } });\n if (existing) {\n const updated = await this.engine.update(object, record.data || {}, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n } else {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } catch {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } else {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n }\n succeeded++;\n break;\n }\n case 'delete': {\n if (!record.id) throw new Error('Record id is required for delete');\n await this.engine.delete(object, { where: { id: record.id } });\n results.push({ id: record.id, success: true });\n succeeded++;\n break;\n }\n default:\n results.push({ id: record.id, success: false, error: `Unknown operation: ${operation}` });\n failed++;\n }\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (options?.atomic) {\n // Abort remaining operations on first failure in atomic mode\n break;\n }\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation,\n total: records.length,\n succeeded,\n failed,\n results: options?.returnRecords !== false ? results : results.map(r => ({ id: r.id, success: r.success, error: r.error })),\n } as BatchUpdateResponse;\n }\n \n async createManyData(request: { object: string, records: any[] }): Promise<any> {\n const records = await this.engine.insert(request.object, request.records);\n return {\n object: request.object,\n records,\n count: records.length\n };\n }\n \n async updateManyData(request: UpdateManyDataRequest): Promise<BatchUpdateResponse> {\n const { object, records, options } = request;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n const updated = await this.engine.update(object, record.data, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation: 'update',\n total: records.length,\n succeeded,\n failed,\n results,\n } as BatchUpdateResponse;\n }\n\n async analyticsQuery(request: any): Promise<any> {\n // Map AnalyticsQuery (cube-style) to engine aggregation.\n // cube name maps to object name; measures → aggregations; dimensions → groupBy.\n const { query, cube } = request;\n const object = cube;\n\n // Build groupBy from dimensions\n const groupBy = query.dimensions || [];\n\n // Build aggregations from measures\n // Measures can be simple field names like \"count\" or \"field_name.sum\"\n // Or cube-defined measure names. We support: field.function or just function(field).\n const aggregations: Array<{ field: string; method: string; alias: string }> = [];\n if (query.measures) {\n for (const measure of query.measures) {\n // Support formats: \"count\", \"amount.sum\", \"revenue.avg\"\n if (measure === 'count' || measure === 'count_all') {\n aggregations.push({ field: '*', method: 'count', alias: 'count' });\n } else if (measure.includes('.')) {\n const [field, method] = measure.split('.');\n aggregations.push({ field, method, alias: `${field}_${method}` });\n } else {\n // Treat as count of the field\n aggregations.push({ field: measure, method: 'sum', alias: measure });\n }\n }\n }\n\n // Build filter from analytics filters\n let filter: any = undefined;\n if (query.filters && query.filters.length > 0) {\n const conditions: any[] = query.filters.map((f: any) => {\n const op = this.mapAnalyticsOperator(f.operator);\n if (f.values && f.values.length === 1) {\n return { [f.member]: { [op]: f.values[0] } };\n } else if (f.values && f.values.length > 1) {\n return { [f.member]: { $in: f.values } };\n }\n return { [f.member]: { [op]: true } };\n });\n filter = conditions.length === 1 ? conditions[0] : { $and: conditions };\n }\n\n // Execute via engine.aggregate (which delegates to driver.find with groupBy/aggregations)\n const rows = await this.engine.aggregate(object, {\n where: filter,\n groupBy: groupBy.length > 0 ? groupBy : undefined,\n aggregations: aggregations.length > 0\n ? aggregations.map(a => ({ function: a.method as any, field: a.field, alias: a.alias }))\n : [{ function: 'count' as any, alias: 'count' }],\n });\n\n // Build field metadata\n const fields = [\n ...groupBy.map((d: string) => ({ name: d, type: 'string' })),\n ...aggregations.map(a => ({ name: a.alias, type: 'number' })),\n ];\n\n return {\n success: true,\n data: {\n rows,\n fields,\n },\n };\n }\n\n async getAnalyticsMeta(request: any): Promise<any> {\n // Auto-generate cube metadata from registered objects in SchemaRegistry.\n // Each object becomes a cube; number fields → measures; other fields → dimensions.\n const objects = SchemaRegistry.listItems('object');\n const cubeFilter = request?.cube;\n\n const cubes: any[] = [];\n for (const obj of objects) {\n const schema = obj as any;\n if (cubeFilter && schema.name !== cubeFilter) continue;\n\n const measures: Record<string, any> = {};\n const dimensions: Record<string, any> = {};\n const fields = schema.fields || {};\n\n // Always add a count measure\n measures['count'] = {\n name: 'count',\n label: 'Count',\n type: 'count',\n sql: '*',\n };\n\n for (const [fieldName, fieldDef] of Object.entries(fields)) {\n const fd = fieldDef as any;\n const fieldType = fd.type || 'text';\n\n if (['number', 'currency', 'percent'].includes(fieldType)) {\n // Numeric fields become both measures and dimensions\n measures[`${fieldName}_sum`] = {\n name: `${fieldName}_sum`,\n label: `${fd.label || fieldName} (Sum)`,\n type: 'sum',\n sql: fieldName,\n };\n measures[`${fieldName}_avg`] = {\n name: `${fieldName}_avg`,\n label: `${fd.label || fieldName} (Avg)`,\n type: 'avg',\n sql: fieldName,\n };\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'number',\n sql: fieldName,\n };\n } else if (['date', 'datetime'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'time',\n sql: fieldName,\n granularities: ['day', 'week', 'month', 'quarter', 'year'],\n };\n } else if (['boolean'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'boolean',\n sql: fieldName,\n };\n } else {\n // text, select, lookup, etc. → dimension\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'string',\n sql: fieldName,\n };\n }\n }\n\n cubes.push({\n name: schema.name,\n title: schema.label || schema.name,\n description: schema.description,\n sql: schema.name,\n measures,\n dimensions,\n public: true,\n });\n }\n\n return {\n success: true,\n data: { cubes },\n };\n }\n\n private mapAnalyticsOperator(op: string): string {\n const map: Record<string, string> = {\n equals: '$eq',\n notEquals: '$ne',\n contains: '$contains',\n notContains: '$notContains',\n gt: '$gt',\n gte: '$gte',\n lt: '$lt',\n lte: '$lte',\n set: '$ne',\n notSet: '$eq',\n };\n return map[op] || '$eq';\n }\n\n async triggerAutomation(_request: any): Promise<any> {\n throw new Error('triggerAutomation requires plugin-automation service. Install and register a plugin that provides the \"automation\" service.');\n }\n\n async deleteManyData(request: DeleteManyDataRequest): Promise<any> {\n // This expects deleting by IDs.\n return this.engine.delete(request.object, {\n where: { 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\n // 1. Always update the in-memory registry (runtime cache)\n SchemaRegistry.registerItem(request.type, request.item, 'name');\n\n // 2. Persist to database via data engine\n try {\n const now = new Date().toISOString();\n // Check if record exists\n const existing = await this.engine.findOne('sys_metadata', {\n where: { type: request.type, name: request.name }\n });\n\n if (existing) {\n await this.engine.update('sys_metadata', {\n metadata: JSON.stringify(request.item),\n updated_at: now,\n version: (existing.version || 0) + 1,\n }, {\n where: { id: existing.id }\n });\n } else {\n // Use crypto.randomUUID() when available (modern browsers and Node ≥ 14.17);\n // fall back to a time+random ID for older or restricted environments.\n const id = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : `meta_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n await this.engine.insert('sys_metadata', {\n id,\n name: request.name,\n type: request.type,\n scope: 'platform',\n metadata: JSON.stringify(request.item),\n state: 'active',\n version: 1,\n created_at: now,\n updated_at: now,\n });\n }\n\n return {\n success: true,\n message: 'Saved to database and registry'\n };\n } catch (dbError: any) {\n // DB write failed but in-memory registry was updated — degrade gracefully\n console.warn(`[Protocol] DB persistence failed for ${request.type}/${request.name}: ${dbError.message}`);\n return {\n success: true,\n message: 'Saved to memory registry (DB persistence unavailable)',\n warning: dbError.message\n };\n }\n }\n\n /**\n * Hydrate SchemaRegistry from the database on startup.\n * Loads all active metadata records and registers them in the in-memory registry.\n * Safe to call repeatedly — idempotent (latest DB record wins).\n */\n async loadMetaFromDb(): Promise<{ loaded: number; errors: number }> {\n let loaded = 0;\n let errors = 0;\n try {\n const records = await this.engine.find('sys_metadata', {\n where: { state: 'active' }\n });\n for (const record of records) {\n try {\n const data = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n // Normalize DB type to singular (DB may store legacy plural forms)\n const normalizedType = PLURAL_TO_SINGULAR[record.type] ?? record.type;\n if (normalizedType === 'object') {\n SchemaRegistry.registerObject(data as any, record.packageId || 'sys_metadata');\n } else {\n SchemaRegistry.registerItem(normalizedType, data, 'name' as any);\n }\n loaded++;\n } catch (e) {\n errors++;\n console.warn(`[Protocol] Failed to hydrate ${record.type}/${record.name}: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n } catch (e: any) {\n console.warn(`[Protocol] DB hydration skipped: ${e.message}`);\n }\n return { loaded, errors };\n }\n\n // ==========================================\n // Feed Operations\n // ==========================================\n\n async listFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n return { success: true, data: result };\n }\n\n async createFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.createFeedItem({\n object: request.object,\n recordId: request.recordId,\n type: request.type,\n actor: { type: 'user', id: 'current_user' },\n body: request.body,\n mentions: request.mentions,\n parentId: request.parentId,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async updateFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.updateFeedItem(request.feedId, {\n body: request.body,\n mentions: request.mentions,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async deleteFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n await svc.deleteFeedItem(request.feedId);\n return { success: true, data: { feedId: request.feedId } };\n }\n\n async addReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.addReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async removeReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.removeReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async pinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated pin/unpin — use updateFeedItem to persist pin state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: true, pinnedAt: new Date().toISOString() } };\n }\n\n async unpinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: false } };\n }\n\n async starFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated star/unstar — verify item exists then return state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: true, starredAt: new Date().toISOString() } };\n }\n\n async unstarFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: false } };\n }\n\n async searchFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Search delegates to listFeed with filter since IFeedService doesn't have a dedicated search\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n // Filter by query text in body\n const queryLower = (request.query || '').toLowerCase();\n const filtered = result.items.filter((item: any) =>\n item.body?.toLowerCase().includes(queryLower)\n );\n return { success: true, data: { items: filtered, total: filtered.length, hasMore: false } };\n }\n\n async getChangelog(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Changelog retrieves field_change type feed items\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: 'changes_only',\n limit: request.limit,\n cursor: request.cursor,\n });\n const entries = result.items.map((item: any) => ({\n id: item.id,\n object: item.object,\n recordId: item.recordId,\n actor: item.actor,\n changes: item.changes || [],\n timestamp: item.createdAt,\n source: item.source,\n }));\n return { success: true, data: { entries, total: result.total, nextCursor: result.nextCursor, hasMore: result.hasMore } };\n }\n\n async feedSubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const subscription = await svc.subscribe({\n object: request.object,\n recordId: request.recordId,\n userId: 'current_user',\n events: request.events,\n channels: request.channels,\n });\n return { success: true, data: subscription };\n }\n\n async feedUnsubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const unsubscribed = await svc.unsubscribe(request.object, request.recordId, 'current_user');\n return { success: true, data: { object: request.object, recordId: request.recordId, unsubscribed } };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { QueryAST, HookContext, ServiceObject } from '@objectstack/spec/data';\nimport {\n EngineQueryOptions,\n DataEngineInsertOptions,\n EngineUpdateOptions,\n EngineDeleteOptions,\n EngineAggregateOptions,\n EngineCountOptions\n} from '@objectstack/spec/data';\nimport { ExecutionContext, ExecutionContextSchema } from '@objectstack/spec/kernel';\nimport { DriverInterface, IDataEngine, Logger, createLogger } from '@objectstack/core';\nimport { CoreServiceName } from '@objectstack/spec/system';\nimport { IRealtimeService, RealtimeEventPayload } from '@objectstack/spec/contracts';\nimport { pluralToSingular } from '@objectstack/spec/shared';\nimport { SchemaRegistry } from './registry.js';\n\nexport type HookHandler = (context: HookContext) => Promise<void> | void;\n\n/**\n * Per-object hook entry with priority support\n */\nexport interface HookEntry {\n handler: HookHandler;\n object?: string | string[]; // undefined = global hook\n priority: number;\n packageId?: string;\n}\n\n/**\n * Operation Context for Middleware Chain\n */\nexport interface OperationContext {\n object: string;\n operation: 'find' | 'findOne' | 'insert' | 'update' | 'delete' | 'count' | 'aggregate';\n ast?: QueryAST;\n data?: any;\n options?: any;\n context?: ExecutionContext;\n result?: any;\n}\n\n/**\n * Engine Middleware (Onion model)\n */\nexport type EngineMiddleware = (\n ctx: OperationContext,\n next: () => Promise<void>\n) => Promise<void>;\n\n/**\n * Host Context provided to plugins (Internal ObjectQL Plugin System)\n */\nexport interface ObjectQLHostContext {\n ql: ObjectQL;\n logger: Logger;\n // Extensible map for host-specific globals (like HTTP Router, etc.)\n [key: string]: any;\n}\n\n/**\n * ObjectQL Engine\n * \n * Implements the IDataEngine interface for data persistence.\n * Acts as the reference implementation for:\n * - CoreServiceName.data (CRUD)\n * - CoreServiceName.metadata (Schema Registry)\n */\nexport class ObjectQL implements IDataEngine {\n private drivers = new Map<string, DriverInterface>();\n private defaultDriver: string | null = null;\n private logger: Logger;\n\n // Per-object hooks with priority support\n private hooks: Map<string, HookEntry[]> = new Map([\n ['beforeFind', []], ['afterFind', []],\n ['beforeInsert', []], ['afterInsert', []],\n ['beforeUpdate', []], ['afterUpdate', []],\n ['beforeDelete', []], ['afterDelete', []],\n ]);\n\n // Middleware chain (onion model)\n private middlewares: Array<{\n fn: EngineMiddleware;\n object?: string;\n }> = [];\n\n // Action registry: key = \"objectName:actionName\"\n private actions = new Map<string, { handler: (ctx: any) => Promise<any> | any; package?: string }>();\n\n // Host provided context additions (e.g. Server router)\n private hostContext: Record<string, any> = {};\n\n // Realtime service for event publishing\n private realtimeService?: IRealtimeService;\n\n constructor(hostContext: Record<string, any> = {}) {\n this.hostContext = hostContext;\n // Use provided logger or create a new one\n this.logger = hostContext.logger || createLogger({ level: 'info', format: 'pretty' });\n this.logger.info('ObjectQL Engine Instance Created');\n }\n\n /**\n * Service Status Report\n * Used by Kernel to verify health and capabilities.\n */\n getStatus() {\n return {\n name: CoreServiceName.enum.data,\n status: 'running',\n version: '0.9.0',\n features: ['crud', 'query', 'aggregate', 'transactions', 'metadata']\n };\n }\n\n /**\n * Expose the SchemaRegistry for plugins to register metadata\n */\n get registry() {\n return SchemaRegistry;\n }\n\n /**\n * Load and Register a Plugin\n */\n async use(manifestPart: any, runtimePart?: any) {\n this.logger.debug('Loading plugin', { \n hasManifest: !!manifestPart, \n hasRuntime: !!runtimePart \n });\n\n // 1. Validate / Register Manifest\n if (manifestPart) {\n this.registerApp(manifestPart);\n }\n\n // 2. Execute Runtime\n if (runtimePart) {\n const pluginDef = (runtimePart as any).default || runtimePart;\n if (pluginDef.onEnable) {\n this.logger.debug('Executing plugin runtime onEnable');\n \n const context: ObjectQLHostContext = {\n ql: this,\n logger: this.logger,\n // Expose the driver registry helper explicitly if needed\n drivers: {\n register: (driver: DriverInterface) => this.registerDriver(driver)\n },\n ...this.hostContext\n };\n \n await pluginDef.onEnable(context);\n this.logger.debug('Plugin runtime onEnable completed');\n }\n }\n }\n\n /**\n * Register a hook\n * @param event The event name (e.g. 'beforeFind', 'afterInsert')\n * @param handler The handler function\n * @param options Optional: target object(s) and priority\n */\n registerHook(event: string, handler: HookHandler, options?: {\n object?: string | string[];\n priority?: number;\n packageId?: string;\n }) {\n if (!this.hooks.has(event)) {\n this.hooks.set(event, []);\n }\n const entries = this.hooks.get(event)!;\n entries.push({\n handler,\n object: options?.object,\n priority: options?.priority ?? 100,\n packageId: options?.packageId,\n });\n // Sort by priority (lower runs first)\n entries.sort((a, b) => a.priority - b.priority);\n this.logger.debug('Registered hook', { event, object: options?.object, priority: options?.priority ?? 100, totalHandlers: entries.length });\n }\n\n public async triggerHooks(event: string, context: HookContext) {\n const entries = this.hooks.get(event) || [];\n \n if (entries.length === 0) {\n this.logger.debug('No hooks registered for event', { event });\n return;\n }\n\n this.logger.debug('Triggering hooks', { event, count: entries.length });\n \n for (const entry of entries) {\n // Per-object matching\n if (entry.object) {\n const targets = Array.isArray(entry.object) ? entry.object : [entry.object];\n if (!targets.includes('*') && !targets.includes(context.object)) {\n continue; // Skip non-matching hooks\n }\n }\n await entry.handler(context);\n }\n }\n\n // ========================================\n // Action System\n // ========================================\n\n /**\n * Register a named action on an object.\n * Actions are custom business logic callable via `repo.execute(actionName, params)`.\n *\n * @param objectName Target object\n * @param actionName Unique action name within the object\n * @param handler Handler function\n * @param packageName Optional package owner (for cleanup)\n */\n registerAction(objectName: string, actionName: string, handler: (ctx: any) => Promise<any> | any, packageName?: string): void {\n const key = `${objectName}:${actionName}`;\n this.actions.set(key, { handler, package: packageName });\n this.logger.debug('Registered action', { objectName, actionName, package: packageName });\n }\n\n /**\n * Execute a named action on an object.\n */\n async executeAction(objectName: string, actionName: string, ctx: any): Promise<any> {\n const entry = this.actions.get(`${objectName}:${actionName}`);\n if (!entry) {\n throw new Error(`Action '${actionName}' on object '${objectName}' not found`);\n }\n return entry.handler(ctx);\n }\n\n /**\n * Remove all actions registered by a specific package.\n */\n removeActionsByPackage(packageName: string): void {\n for (const [key, entry] of this.actions.entries()) {\n if (entry.package === packageName) {\n this.actions.delete(key);\n }\n }\n }\n\n /**\n * Register a middleware function\n * Middlewares execute in onion model around every data operation.\n * @param fn The middleware function\n * @param options Optional: target object filter\n */\n registerMiddleware(fn: EngineMiddleware, options?: { object?: string }): void {\n this.middlewares.push({ fn, object: options?.object });\n this.logger.debug('Registered middleware', { object: options?.object, total: this.middlewares.length });\n }\n\n /**\n * Execute an operation through the middleware chain\n */\n private async executeWithMiddleware(ctx: OperationContext, executor: () => Promise<any>): Promise<any> {\n const applicable = this.middlewares.filter(m =>\n !m.object || m.object === '*' || m.object === ctx.object\n );\n\n let index = 0;\n const next = async (): Promise<void> => {\n if (index < applicable.length) {\n const mw = applicable[index++];\n await mw.fn(ctx, next);\n } else {\n ctx.result = await executor();\n }\n };\n\n await next();\n return ctx.result;\n }\n\n /**\n * Build a HookContext.session from ExecutionContext\n */\n private buildSession(execCtx?: ExecutionContext): HookContext['session'] {\n if (!execCtx) return undefined;\n return {\n userId: execCtx.userId,\n tenantId: execCtx.tenantId,\n roles: execCtx.roles,\n accessToken: execCtx.accessToken,\n };\n }\n\n /**\n * Register contribution (Manifest)\n * \n * Installs the manifest as a Package (the unit of installation),\n * then decomposes it into individual metadata items (objects, apps, actions, etc.)\n * and registers each into the SchemaRegistry.\n * \n * Key: Package ≠ App. The manifest is the package. The apps[] array inside\n * the manifest contains UI navigation definitions (AppSchema).\n */\n registerApp(manifest: any) {\n const id = manifest.id || manifest.name;\n const namespace = manifest.namespace as string | undefined;\n this.logger.debug('Registering package manifest', { id, namespace });\n\n // 1. Register the Package (manifest + lifecycle state)\n SchemaRegistry.installPackage(manifest);\n this.logger.debug('Installed Package', { id: manifest.id, name: manifest.name, namespace });\n\n // 2. Register owned objects\n if (manifest.objects) {\n if (Array.isArray(manifest.objects)) {\n this.logger.debug('Registering objects from manifest (Array)', { id, objectCount: manifest.objects.length });\n for (const objDef of manifest.objects) {\n const fqn = SchemaRegistry.registerObject(objDef, id, namespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: id });\n }\n } else {\n this.logger.debug('Registering objects from manifest (Map)', { id, objectCount: Object.keys(manifest.objects).length });\n for (const [name, objDef] of Object.entries(manifest.objects)) {\n // Ensure name in definition matches key\n (objDef as any).name = name;\n const fqn = SchemaRegistry.registerObject(objDef as any, id, namespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: id });\n }\n }\n }\n\n // 2b. Register object extensions (fields added to objects owned by other packages)\n if (Array.isArray(manifest.objectExtensions) && manifest.objectExtensions.length > 0) {\n this.logger.debug('Registering object extensions', { id, count: manifest.objectExtensions.length });\n for (const ext of manifest.objectExtensions) {\n const targetFqn = ext.extend;\n const priority = ext.priority ?? 200;\n // Create a partial object definition for the extension\n const extDef = {\n name: targetFqn, // Use the target FQN as name\n fields: ext.fields,\n label: ext.label,\n pluralLabel: ext.pluralLabel,\n description: ext.description,\n validations: ext.validations,\n indexes: ext.indexes,\n };\n // Register as extension (namespace is undefined since we're targeting by FQN)\n SchemaRegistry.registerObject(extDef as any, id, undefined, 'extend', priority);\n this.logger.debug('Registered Object Extension', { target: targetFqn, priority, from: id });\n }\n }\n\n // 3. Register apps (UI navigation definitions) as their own metadata type\n if (Array.isArray(manifest.apps) && manifest.apps.length > 0) {\n this.logger.debug('Registering apps from manifest', { id, count: manifest.apps.length });\n for (const app of manifest.apps) {\n const appName = app.name || app.id;\n if (appName) {\n SchemaRegistry.registerApp(app, id);\n this.logger.debug('Registered App', { app: appName, from: id });\n }\n }\n }\n\n // 4. If manifest itself looks like an App (has navigation), also register as app\n // This handles the case where the manifest IS the app definition (legacy/simple packages)\n if (manifest.name && manifest.navigation && !manifest.apps?.length) {\n SchemaRegistry.registerApp(manifest, id);\n this.logger.debug('Registered manifest-as-app', { app: manifest.name, from: id });\n }\n\n // 5. Register all other metadata types generically\n const metadataArrayKeys = [\n // UI Protocol\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'themes',\n // Automation Protocol\n 'flows', 'workflows', 'approvals', 'webhooks',\n // Security Protocol\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n // AI Protocol\n 'agents', 'ragPipelines',\n // API Protocol\n 'apis',\n // Data Extensions\n 'hooks', 'mappings', 'analyticsCubes',\n // Integration Protocol\n 'connectors',\n ];\n for (const key of metadataArrayKeys) {\n const items = (manifest as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n this.logger.debug(`Registering ${key} from manifest`, { id, count: items.length });\n for (const item of items) {\n const itemName = item.name || item.id;\n if (itemName) {\n SchemaRegistry.registerItem(pluralToSingular(key), item, 'name' as any, id);\n }\n }\n }\n }\n\n // 6. Register seed data as metadata (keyed by target object name)\n const seedData = (manifest as any).data;\n if (Array.isArray(seedData) && seedData.length > 0) {\n this.logger.debug('Registering seed data datasets', { id, count: seedData.length });\n for (const dataset of seedData) {\n if (dataset.object) {\n SchemaRegistry.registerItem('data', dataset, 'object' as any, id);\n }\n }\n }\n\n // 6. Register contributions\n if (manifest.contributes?.kinds) {\n this.logger.debug('Registering kinds from manifest', { id, kindCount: manifest.contributes.kinds.length });\n for (const kind of manifest.contributes.kinds) {\n SchemaRegistry.registerKind(kind);\n this.logger.debug('Registered Kind', { kind: kind.name || kind.type, from: id });\n }\n }\n\n // 7. Recursively register nested plugins\n if (Array.isArray(manifest.plugins) && manifest.plugins.length > 0) {\n this.logger.debug('Processing nested plugins', { id, count: manifest.plugins.length });\n for (const plugin of manifest.plugins) {\n if (plugin && typeof plugin === 'object') {\n const pluginName = plugin.name || plugin.id || 'unnamed-plugin';\n this.logger.debug('Registering nested plugin', { pluginName, parentId: id });\n this.registerPlugin(plugin, id, namespace);\n }\n }\n }\n }\n\n /**\n * Register a nested plugin's metadata (objects, actions, views, etc.)\n *\n * Unlike registerApp(), this does NOT call SchemaRegistry.installPackage()\n * because plugins are not formal manifests — they are lightweight config\n * bundles with objects, actions, triggers, and navigation.\n *\n * @param plugin - The plugin config object\n * @param parentId - The parent package ID (for ownership tracking)\n * @param parentNamespace - The parent package's namespace (for FQN resolution)\n */\n private registerPlugin(plugin: any, parentId: string, parentNamespace?: string) {\n const pluginName = plugin.name || plugin.id || 'unnamed';\n const pluginNamespace = plugin.namespace || parentNamespace;\n\n // Use parentId as the owning package for namespace consistency.\n // The parent package already claimed the namespace — nested plugins\n // contribute objects UNDER the parent's ownership.\n const ownerId = parentId;\n\n // Register objects (supports both Array and Map formats)\n if (plugin.objects) {\n try {\n if (Array.isArray(plugin.objects)) {\n this.logger.debug('Registering plugin objects (Array)', { pluginName, count: plugin.objects.length });\n for (const objDef of plugin.objects) {\n const fqn = SchemaRegistry.registerObject(objDef, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n } else {\n const entries = Object.entries(plugin.objects);\n this.logger.debug('Registering plugin objects (Map)', { pluginName, count: entries.length });\n for (const [name, objDef] of entries) {\n (objDef as any).name = name;\n const fqn = SchemaRegistry.registerObject(objDef as any, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n }\n } catch (err: any) {\n this.logger.warn('Failed to register plugin objects', { pluginName, error: err.message });\n }\n }\n\n // Register plugin as app if it has navigation (for sidebar display)\n if (plugin.name && plugin.navigation) {\n try {\n SchemaRegistry.registerApp(plugin, ownerId);\n this.logger.debug('Registered plugin-as-app', { app: plugin.name, from: pluginName });\n } catch (err: any) {\n this.logger.warn('Failed to register plugin as app', { pluginName, error: err.message });\n }\n }\n\n // Register metadata arrays (actions, views, triggers, etc.)\n const metadataArrayKeys = [\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'themes',\n 'flows', 'workflows', 'approvals', 'webhooks',\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n 'agents', 'ragPipelines', 'apis',\n 'hooks', 'mappings', 'analyticsCubes', 'connectors',\n ];\n for (const key of metadataArrayKeys) {\n const items = (plugin as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n for (const item of items) {\n const itemName = item.name || item.id;\n if (itemName) {\n SchemaRegistry.registerItem(pluralToSingular(key), item, 'name' as any, ownerId);\n }\n }\n }\n }\n }\n\n /**\n * Register a new storage driver\n */\n registerDriver(driver: DriverInterface, isDefault: boolean = false) {\n if (this.drivers.has(driver.name)) {\n this.logger.warn('Driver already registered, skipping', { driverName: driver.name });\n return;\n }\n\n this.drivers.set(driver.name, driver);\n this.logger.info('Registered driver', {\n driverName: driver.name,\n version: driver.version\n });\n\n if (isDefault || this.drivers.size === 1) {\n this.defaultDriver = driver.name;\n this.logger.info('Set default driver', { driverName: driver.name });\n }\n }\n\n /**\n * Set the realtime service for publishing data change events.\n * Should be called after kernel resolves the realtime service.\n *\n * @param service - An IRealtimeService instance for event publishing\n */\n setRealtimeService(service: IRealtimeService): void {\n this.realtimeService = service;\n this.logger.info('RealtimeService configured for data events');\n }\n\n /**\n * Helper to get object definition\n */\n getSchema(objectName: string): ServiceObject | undefined {\n return SchemaRegistry.getObject(objectName);\n }\n\n /**\n * Resolve an object name to its Fully Qualified Name (FQN).\n * \n * Short names like 'task' are resolved to FQN like 'todo__task'\n * via SchemaRegistry lookup. If no match is found, the name is\n * returned as-is (for ad-hoc / unregistered objects).\n * \n * This ensures that all driver operations use a consistent key\n * regardless of whether the caller uses the short name or FQN.\n */\n private resolveObjectName(name: string): string {\n const schema = SchemaRegistry.getObject(name);\n if (schema) {\n // Prefer the physical table name (e.g., 'sys_user') over the FQN\n // (e.g., 'sys__user'). ObjectSchema.create() auto-derives tableName\n // as {namespace}_{name} which matches the storage convention.\n return schema.tableName || schema.name;\n }\n return name; // Ad-hoc object, keep as-is\n }\n\n /**\n * Helper to get the target driver\n */\n private getDriver(objectName: string): DriverInterface {\n const object = SchemaRegistry.getObject(objectName);\n \n // 1. If object definition exists, check for explicit datasource\n if (object) {\n const datasourceName = object.datasource || 'default';\n \n // If configured for 'default', try to find the default driver\n if (datasourceName === 'default') {\n if (this.defaultDriver && this.drivers.has(this.defaultDriver)) {\n return this.drivers.get(this.defaultDriver)!;\n }\n } else {\n // Specific datasource requested\n if (this.drivers.has(datasourceName)) {\n return this.drivers.get(datasourceName)!;\n }\n throw new Error(`[ObjectQL] Datasource '${datasourceName}' configured for object '${objectName}' is not registered.`);\n }\n }\n\n // 2. Fallback for ad-hoc objects or missing definitions\n if (this.defaultDriver) {\n return this.drivers.get(this.defaultDriver)!;\n }\n\n throw new Error(`[ObjectQL] No driver available for object '${objectName}'`);\n }\n\n /**\n * Initialize the engine and all registered drivers\n */\n async init() {\n this.logger.info('Initializing ObjectQL engine', { \n driverCount: this.drivers.size,\n drivers: Array.from(this.drivers.keys())\n });\n \n const failedDrivers: string[] = [];\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 failedDrivers.push(name);\n this.logger.error('Failed to connect driver', e as Error, { driverName: name });\n }\n }\n\n if (failedDrivers.length > 0) {\n this.logger.warn(\n `${failedDrivers.length} of ${this.drivers.size} driver(s) failed initial connect. ` +\n `Operations may recover via lazy reconnection or fail at query time.`,\n { failedDrivers }\n );\n }\n \n this.logger.info('ObjectQL engine initialization complete');\n }\n\n async destroy() {\n this.logger.info('Destroying ObjectQL engine', { driverCount: this.drivers.size });\n \n for (const [name, driver] of this.drivers.entries()) {\n try {\n await driver.disconnect();\n } catch (e) {\n this.logger.error('Error disconnecting driver', e as Error, { driverName: name });\n }\n }\n \n this.logger.info('ObjectQL engine destroyed');\n }\n\n // ============================================\n // Helper: Expand Related Records\n // ============================================\n\n /** Maximum depth for recursive expand to prevent infinite loops */\n private static readonly MAX_EXPAND_DEPTH = 3;\n\n /**\n * Post-process expand: resolve lookup/master_detail fields by batch-loading related records.\n * \n * This is a driver-agnostic implementation that uses secondary queries ($in batches)\n * to load related records, then injects them into the result set.\n * \n * @param objectName - The source object name\n * @param records - The records returned by the driver\n * @param expand - The expand map from QueryAST (field name → nested QueryAST)\n * @param depth - Current recursion depth (0-based)\n * @returns Records with expanded lookup fields (IDs replaced by full objects)\n */\n private async expandRelatedRecords(\n objectName: string,\n records: any[],\n expand: Record<string, QueryAST>,\n depth: number = 0,\n ): Promise<any[]> {\n if (!records || records.length === 0) return records;\n if (depth >= ObjectQL.MAX_EXPAND_DEPTH) return records;\n\n const objectSchema = SchemaRegistry.getObject(objectName);\n // If no schema registered, skip expand — return raw data\n if (!objectSchema || !objectSchema.fields) return records;\n\n for (const [fieldName, nestedAST] of Object.entries(expand)) {\n const fieldDef = objectSchema.fields[fieldName];\n\n // Skip if field not found or not a relationship type\n if (!fieldDef || !fieldDef.reference) continue;\n if (fieldDef.type !== 'lookup' && fieldDef.type !== 'master_detail') continue;\n\n const referenceObject = fieldDef.reference;\n\n // Collect all foreign key IDs from records (handle both single and multiple values)\n const allIds: any[] = [];\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n if (Array.isArray(val)) {\n allIds.push(...val.filter((id: any) => id != null));\n } else if (typeof val === 'object') {\n // Already expanded — skip\n continue;\n } else {\n allIds.push(val);\n }\n }\n\n // De-duplicate IDs\n const uniqueIds = [...new Set(allIds)];\n if (uniqueIds.length === 0) continue;\n\n // Batch-load related records using $in query\n try {\n const relatedQuery: QueryAST = {\n object: referenceObject,\n where: { id: { $in: uniqueIds } },\n ...(nestedAST.fields ? { fields: nestedAST.fields } : {}),\n ...(nestedAST.orderBy ? { orderBy: nestedAST.orderBy } : {}),\n };\n\n const driver = this.getDriver(referenceObject);\n const relatedRecords = await driver.find(referenceObject, relatedQuery) ?? [];\n\n // Build a lookup map: id → record\n const recordMap = new Map<string, any>();\n for (const rec of relatedRecords) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n\n // Recursively expand nested relations if present\n if (nestedAST.expand && Object.keys(nestedAST.expand).length > 0) {\n const expandedRelated = await this.expandRelatedRecords(\n referenceObject,\n relatedRecords,\n nestedAST.expand,\n depth + 1,\n );\n // Rebuild map with expanded records\n recordMap.clear();\n for (const rec of expandedRelated) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n }\n\n // Inject expanded records back into the original result set\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n\n if (Array.isArray(val)) {\n record[fieldName] = val.map((id: any) => recordMap.get(String(id)) ?? id);\n } else if (typeof val !== 'object') {\n record[fieldName] = recordMap.get(String(val)) ?? val;\n }\n // If val is already an object, leave it as-is\n }\n } catch (e) {\n // Graceful degradation: if expand fails, keep original IDs\n this.logger.warn('Failed to expand relationship field; retaining foreign key IDs', {\n object: objectName,\n field: fieldName,\n reference: referenceObject,\n error: (e as Error).message,\n });\n }\n }\n\n return records;\n }\n\n // ============================================\n // Data Access Methods (IDataEngine Interface)\n // ============================================\n\n async find(object: string, query?: EngineQueryOptions): 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: QueryAST = { object, ...query };\n // Remove context from the AST — it's not a driver concern\n delete (ast as any).context;\n // Normalize OData `top` alias → standard `limit`\n if ((ast as any).top != null && ast.limit == null) {\n ast.limit = (ast as any).top;\n }\n delete (ast as any).top;\n\n const opCtx: OperationContext = {\n object,\n operation: 'find',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeFind',\n input: { ast: opCtx.ast, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeFind', hookContext);\n\n try {\n let result = await driver.find(object, hookContext.input.ast as QueryAST, hookContext.input.options as any);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && Array.isArray(result)) {\n result = await this.expandRelatedRecords(object, result, ast.expand, 0);\n }\n \n hookContext.event = 'afterFind';\n hookContext.result = result;\n await this.triggerHooks('afterFind', hookContext);\n \n return hookContext.result;\n } catch (e) {\n this.logger.error('Find operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result as any[];\n }\n\n async findOne(objectName: string, query?: EngineQueryOptions): Promise<any> {\n objectName = this.resolveObjectName(objectName);\n this.logger.debug('FindOne operation', { objectName });\n const driver = this.getDriver(objectName);\n const ast: QueryAST = { object: objectName, ...query, limit: 1 };\n // Remove context and top alias from the AST\n delete (ast as any).context;\n delete (ast as any).top;\n\n const opCtx: OperationContext = {\n object: objectName,\n operation: 'findOne',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n let result = await driver.findOne(objectName, opCtx.ast as QueryAST);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && result != null) {\n const expanded = await this.expandRelatedRecords(objectName, [result], ast.expand, 0);\n result = expanded[0];\n }\n\n return result;\n });\n\n return opCtx.result;\n }\n\n async insert(object: string, data: any | any[], options?: DataEngineInsertOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Insert operation starting', { object, isBatch: Array.isArray(data) });\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'insert',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeInsert',\n input: { data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeInsert', hookContext);\n\n try {\n let result;\n if (Array.isArray(hookContext.input.data)) {\n // Bulk Create\n if (driver.bulkCreate) {\n result = await driver.bulkCreate(object, hookContext.input.data as any[], hookContext.input.options as any);\n } else {\n // Fallback loop\n result = await Promise.all((hookContext.input.data as any[]).map((item: any) => driver.create(object, item, hookContext.input.options as any)));\n }\n } else {\n result = await driver.create(object, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n }\n\n hookContext.event = 'afterInsert';\n hookContext.result = result;\n await this.triggerHooks('afterInsert', hookContext);\n\n // Publish data.record.created event to realtime service\n if (this.realtimeService) {\n try {\n if (Array.isArray(result)) {\n // Bulk insert - publish event for each record\n for (const record of result) {\n const event: RealtimeEventPayload = {\n type: 'data.record.created',\n object,\n payload: {\n recordId: record.id,\n after: record,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n }\n this.logger.debug(`Published ${result.length} data.record.created events`, { object });\n } else {\n const event: RealtimeEventPayload = {\n type: 'data.record.created',\n object,\n payload: {\n recordId: result.id,\n after: result,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.created event', { object, recordId: result.id });\n }\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Insert operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async update(object: string, data: any, options?: EngineUpdateOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Update operation starting', { object });\n const driver = this.getDriver(object);\n \n // 1. Extract ID from data or where if it's a single update by ID\n let id = data.id;\n if (!id && options?.where && typeof options.where === 'object' && 'id' in options.where) {\n id = (options.where as Record<string, unknown>).id;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'update',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeUpdate',\n input: { id, data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeUpdate', hookContext);\n\n try {\n let result;\n if (hookContext.input.id) {\n result = await driver.update(object, hookContext.input.id as string, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else if (options?.multi && driver.updateMany) {\n const ast: QueryAST = { object, where: options.where };\n result = await driver.updateMany(object, ast, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else {\n throw new Error('Update requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterUpdate';\n hookContext.result = result;\n await this.triggerHooks('afterUpdate', hookContext);\n\n // Publish data.record.updated event to realtime service\n if (this.realtimeService) {\n try {\n const resultId = (typeof result === 'object' && result && 'id' in result) ? (result as any).id : undefined;\n const recordId = String(hookContext.input.id || resultId || '');\n const event: RealtimeEventPayload = {\n type: 'data.record.updated',\n object,\n payload: {\n recordId,\n changes: hookContext.input.data,\n after: result,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.updated event', { object, recordId });\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Update operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async delete(object: string, options?: EngineDeleteOptions): 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?.where && typeof options.where === 'object' && 'id' in options.where) {\n id = (options.where as Record<string, unknown>).id;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'delete',\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeDelete',\n input: { id, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeDelete', hookContext);\n\n try {\n let result;\n if (hookContext.input.id) {\n result = await driver.delete(object, hookContext.input.id as string, hookContext.input.options as any);\n } else if (options?.multi && driver.deleteMany) {\n const ast: QueryAST = { object, where: options.where };\n result = await driver.deleteMany(object, ast, hookContext.input.options as any);\n } else {\n throw new Error('Delete requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterDelete';\n hookContext.result = result;\n await this.triggerHooks('afterDelete', hookContext);\n\n // Publish data.record.deleted event to realtime service\n if (this.realtimeService) {\n try {\n const resultId = (typeof result === 'object' && result && 'id' in result) ? (result as any).id : undefined;\n const recordId = String(hookContext.input.id || resultId || '');\n const event: RealtimeEventPayload = {\n type: 'data.record.deleted',\n object,\n payload: {\n recordId,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.deleted event', { object, recordId });\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Delete operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async count(object: string, query?: EngineCountOptions): Promise<number> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'count',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n if (driver.count) {\n const ast: QueryAST = { object, where: query?.where };\n return driver.count(object, ast);\n }\n // Fallback to find().length\n const res = await this.find(object, { where: query?.where, fields: ['id'] });\n return res.length;\n });\n\n return opCtx.result as number;\n }\n\n async aggregate(object: string, query: EngineAggregateOptions): Promise<any[]> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n this.logger.debug(`Aggregate on ${object} using ${driver.name}`, query);\n\n const opCtx: OperationContext = {\n object,\n operation: 'aggregate',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const ast: QueryAST = {\n object,\n where: query.where,\n groupBy: query.groupBy,\n aggregations: query.aggregations,\n };\n\n return driver.find(object, ast);\n });\n\n return opCtx.result as any[];\n }\n \n async execute(command: any, options?: Record<string, any>): Promise<any> {\n // Direct pass-through implies we know which driver to use?\n // Usually execute is tied to a specific object context OR we need a way to select driver.\n // If command has 'object', we use that.\n if (options?.object) {\n const driver = this.getDriver(options.object);\n if (driver.execute) {\n return driver.execute(command, undefined, options);\n }\n }\n throw new Error('Execute requires options.object to select driver');\n }\n\n // ============================================\n // Compatibility / Convenience API\n // ============================================\n // These methods provide a higher-level API matching the @objectql/core\n // ObjectQL interface, enabling painless migration from the legacy layer.\n\n /**\n * Register a single object definition.\n * \n * Proxies to SchemaRegistry.registerObject() with sensible defaults.\n * Fields without a `name` property are auto-assigned from their key.\n */\n registerObject(\n schema: ServiceObject,\n packageId: string = '__runtime__',\n namespace?: string\n ): string {\n // Auto-assign field names from keys\n if (schema.fields) {\n for (const [key, field] of Object.entries(schema.fields)) {\n if (field && typeof field === 'object' && !('name' in field)) {\n (field as any).name = key;\n }\n }\n }\n return SchemaRegistry.registerObject(schema, packageId, namespace);\n }\n\n /**\n * Unregister a single object by name.\n */\n unregisterObject(name: string, packageId?: string): void {\n if (packageId) {\n SchemaRegistry.unregisterObjectsByPackage(packageId);\n } else {\n // Remove from generic metadata as fallback\n SchemaRegistry.unregisterItem('object', name);\n }\n }\n\n /**\n * Get an object definition by name.\n * Alias for getSchema() — matches @objectql/core API.\n */\n getObject(name: string): ServiceObject | undefined {\n return this.getSchema(name);\n }\n\n /**\n * Get all registered object configs as a name→config map.\n * Matches @objectql/core getConfigs() API.\n */\n getConfigs(): Record<string, ServiceObject> {\n const result: Record<string, ServiceObject> = {};\n const objects = SchemaRegistry.getAllObjects();\n for (const obj of objects) {\n if (obj.name) {\n result[obj.name] = obj;\n }\n }\n return result;\n }\n\n /**\n * Get a registered driver by datasource name.\n * \n * Unlike the private getDriver() (which resolves by object name),\n * this method directly looks up a driver by its registered name.\n */\n getDriverByName(name: string): DriverInterface | undefined {\n return this.drivers.get(name);\n }\n\n /**\n * Get the driver responsible for the given object.\n *\n * Resolves datasource binding from the object's schema definition,\n * falling back to the default driver. This is a public version of\n * the internal getDriver() used by CRUD operations.\n *\n * @param objectName - FQN or short name of the registered object.\n * @returns The resolved DriverInterface, or undefined if no driver is available.\n */\n getDriverForObject(objectName: string): DriverInterface | undefined {\n try {\n return this.getDriver(objectName);\n } catch {\n return undefined;\n }\n }\n\n /**\n * Get a registered driver by datasource name.\n * Alias matching @objectql/core datasource() API.\n * \n * @throws Error if the datasource is not found\n */\n datasource(name: string): DriverInterface {\n const driver = this.drivers.get(name);\n if (!driver) {\n throw new Error(`[ObjectQL] Datasource '${name}' not found`);\n }\n return driver;\n }\n\n /**\n * Register a hook handler.\n * Convenience alias for registerHook() matching @objectql/core on() API.\n * \n * Usage:\n * ql.on('beforeInsert', 'user', async (ctx) => { ... });\n */\n on(\n event: string,\n objectName: string,\n handler: (ctx: HookContext) => Promise<void> | void,\n packageId?: string\n ): void {\n this.registerHook(event, handler, { object: objectName, packageId });\n }\n\n /**\n * Remove all hooks, actions, and objects contributed by a package.\n */\n removePackage(packageId: string): void {\n // Remove hooks\n for (const [key, handlers] of this.hooks.entries()) {\n const filtered = handlers.filter(h => h.packageId !== packageId);\n if (filtered.length !== handlers.length) {\n this.hooks.set(key, filtered);\n }\n }\n // Remove actions\n this.removeActionsByPackage(packageId);\n // Remove objects\n SchemaRegistry.unregisterObjectsByPackage(packageId, true);\n }\n\n /**\n * Gracefully shut down the engine, disconnecting all drivers.\n * Alias for destroy() — matches @objectql/core close() API.\n */\n async close(): Promise<void> {\n return this.destroy();\n }\n\n /**\n * Create a scoped execution context bound to this engine.\n * \n * Usage:\n * const ctx = engine.createContext({ userId: '...', tenantId: '...' });\n * const users = ctx.object('user');\n * await users.find({ filter: { status: 'active' } });\n */\n createContext(ctx: Partial<ExecutionContext>): ScopedContext {\n return new ScopedContext(\n ExecutionContextSchema.parse(ctx),\n this\n );\n }\n\n /**\n * Static factory: create a fully configured ObjectQL instance.\n * \n * Matches @objectql/core's `new ObjectQL(config)` pattern but also\n * registers drivers and objects, then calls init().\n * \n * Usage:\n * const ql = await ObjectQL.create({\n * datasources: { default: myDriver },\n * objects: { user: { name: 'user', fields: { ... } } }\n * });\n */\n static async create(config: {\n datasources?: Record<string, DriverInterface>;\n objects?: Record<string, ServiceObject>;\n hooks?: Array<{ event: string; object: string; handler: (ctx: HookContext) => Promise<void> | void }>;\n }): Promise<ObjectQL> {\n const ql = new ObjectQL();\n\n // Register drivers\n if (config.datasources) {\n for (const [name, driver] of Object.entries(config.datasources)) {\n // Set driver name if not already set\n if (!driver.name) {\n (driver as any).name = name;\n }\n ql.registerDriver(driver, name === 'default');\n }\n }\n\n // Register objects\n if (config.objects) {\n for (const [_key, schema] of Object.entries(config.objects)) {\n ql.registerObject(schema);\n }\n }\n\n // Register hooks\n if (config.hooks) {\n for (const hook of config.hooks) {\n ql.on(hook.event, hook.object, hook.handler);\n }\n }\n\n // Initialize (connect drivers)\n await ql.init();\n\n return ql;\n }\n}\n\n/**\n * Repository scoped to a single object, bound to an execution context.\n *\n * Provides both IDataEngine-style methods (find, insert, update, delete)\n * and convenience aliases (create, updateById, deleteById) matching\n * the @objectql/core ObjectRepository API.\n */\nexport class ObjectRepository {\n constructor(\n private objectName: string,\n private context: ExecutionContext,\n private engine: IDataEngine & { executeAction?: (o: string, a: string, c: any) => Promise<any> }\n ) {}\n\n async find(query: any = {}): Promise<any[]> {\n return this.engine.find(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async findOne(query: any = {}): Promise<any> {\n return this.engine.findOne(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async insert(data: any): Promise<any> {\n return this.engine.insert(this.objectName, data, {\n context: this.context,\n });\n }\n\n /** Alias for insert() — matches @objectql/core convention */\n async create(data: any): Promise<any> {\n return this.insert(data);\n }\n\n async update(data: any, options: any = {}): Promise<any> {\n return this.engine.update(this.objectName, data, {\n ...options,\n context: this.context,\n });\n }\n\n /** Update a single record by ID */\n async updateById(id: string | number, data: any): Promise<any> {\n return this.engine.update(this.objectName, { ...data, id: id }, {\n where: { id: id },\n context: this.context,\n });\n }\n\n async delete(options: any = {}): Promise<any> {\n return this.engine.delete(this.objectName, {\n ...options,\n context: this.context,\n });\n }\n\n /** Delete a single record by ID */\n async deleteById(id: string | number): Promise<any> {\n return this.engine.delete(this.objectName, {\n where: { id: id },\n context: this.context,\n });\n }\n\n async count(query: any = {}): Promise<number> {\n return this.engine.count(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Aggregate query */\n async aggregate(query: any = {}): Promise<any[]> {\n return this.engine.aggregate(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Execute a named action registered on this object */\n async execute(actionName: string, params?: any): Promise<any> {\n if (this.engine.executeAction) {\n return this.engine.executeAction(this.objectName, actionName, {\n ...params,\n userId: this.context.userId,\n tenantId: this.context.tenantId,\n roles: this.context.roles,\n });\n }\n throw new Error(`Actions not supported by engine`);\n }\n}\n\n/**\n * Scoped execution context with object() accessor.\n * \n * Provides identity (userId, tenantId/spaceId, roles),\n * repository access via object(), privilege escalation via sudo(),\n * and transactional execution via transaction().\n */\nexport class ScopedContext {\n constructor(\n private executionContext: ExecutionContext,\n private engine: IDataEngine\n ) {}\n\n /** Get a repository scoped to this context */\n object(name: string): ObjectRepository {\n return new ObjectRepository(name, this.executionContext, this.engine as any);\n }\n\n /** Create an elevated (system) context */\n sudo(): ScopedContext {\n return new ScopedContext(\n { ...this.executionContext, isSystem: true },\n this.engine\n );\n }\n\n /**\n * Execute a callback within a database transaction.\n *\n * The callback receives a new ScopedContext whose operations\n * share the same transaction handle. If the callback throws,\n * the transaction is rolled back; otherwise it is committed.\n *\n * Falls back to non-transactional execution if the driver\n * does not support transactions.\n */\n async transaction(callback: (trxCtx: ScopedContext) => Promise<any>): Promise<any> {\n const engine = this.engine as any;\n\n // Find the default driver for transaction support\n const driver = engine.defaultDriver\n ? engine.drivers?.get(engine.defaultDriver)\n : undefined;\n\n if (!driver?.beginTransaction) {\n // No transaction support — execute directly\n return callback(this);\n }\n\n const trx = await driver.beginTransaction();\n const trxCtx = new ScopedContext(\n { ...this.executionContext, transaction: trx },\n this.engine\n );\n\n try {\n const result = await callback(trxCtx);\n if (driver.commit) await driver.commit(trx);\n else if (driver.commitTransaction) await driver.commitTransaction(trx);\n return result;\n } catch (error) {\n if (driver.rollback) await driver.rollback(trx);\n else if (driver.rollbackTransaction) await driver.rollbackTransaction(trx);\n throw error;\n }\n }\n\n get userId() { return this.executionContext.userId; }\n get tenantId() { return this.executionContext.tenantId; }\n /** Alias for tenantId — matches ObjectQLContext.spaceId convention */\n get spaceId() { return this.executionContext.tenantId; }\n get roles() { return this.executionContext.roles; }\n get isSystem() { return this.executionContext.isSystem; }\n\n /** Internal: expose the transaction handle for driver-level access */\n get transactionHandle() { return this.executionContext.transaction; }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { SchemaRegistry } from './registry.js';\n\n/**\n * MetadataFacade\n * \n * Provides a clean, injectable interface over SchemaRegistry.\n * Registered as the 'metadata' kernel service to eliminate\n * downstream packages needing to manually wrap SchemaRegistry.\n * \n * Implements the async IMetadataService interface.\n * Internally delegates to SchemaRegistry (in-memory) with Promise wrappers.\n */\nexport class MetadataFacade {\n /**\n * Register a metadata item\n */\n async register(type: string, name: string, data: any): Promise<void> {\n const definition = typeof data === 'object' && data !== null\n ? { ...data, name: data.name ?? name }\n : data;\n if (type === 'object') {\n SchemaRegistry.registerItem(type, definition, 'name' as any);\n } else {\n SchemaRegistry.registerItem(type, definition, definition.id ? 'id' as any : 'name' as any);\n }\n }\n\n /**\n * Get a metadata item by type and name\n */\n async get(type: string, name: string): Promise<any> {\n const item = SchemaRegistry.getItem(type, name) as any;\n return item?.content ?? item;\n }\n\n /**\n * Get the raw entry (with metadata wrapper)\n */\n getEntry(type: string, name: string): any {\n return SchemaRegistry.getItem(type, name);\n }\n\n /**\n * List all items of a type\n */\n async list(type: string): Promise<any[]> {\n const items = SchemaRegistry.listItems(type);\n return items.map((item: any) => item?.content ?? item);\n }\n\n /**\n * Unregister a metadata item\n */\n async unregister(type: string, name: string): Promise<void> {\n SchemaRegistry.unregisterItem(type, name);\n }\n\n /**\n * Check if a metadata item exists\n */\n async exists(type: string, name: string): Promise<boolean> {\n const item = SchemaRegistry.getItem(type, name);\n return item !== undefined && item !== null;\n }\n\n /**\n * List all names of metadata items of a given type\n */\n async listNames(type: string): Promise<string[]> {\n const items = SchemaRegistry.listItems(type);\n return items.map((item: any) => item?.name ?? item?.content?.name ?? '').filter(Boolean);\n }\n\n /**\n * Unregister all metadata from a package\n */\n async unregisterPackage(packageName: string): Promise<void> {\n SchemaRegistry.unregisterObjectsByPackage(packageName);\n }\n\n /**\n * Convenience: get object definition\n */\n async getObject(name: string): Promise<any> {\n return SchemaRegistry.getObject(name);\n }\n\n /**\n * Convenience: list all objects\n */\n async listObjects(): Promise<any[]> {\n return SchemaRegistry.getAllObjects();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectQL } from './engine.js';\nimport { ObjectStackProtocolImplementation } from './protocol.js';\nimport { Plugin, PluginContext } from '@objectstack/core';\n\nexport type { Plugin, PluginContext };\n\n/**\n * Protocol extension for DB-based metadata hydration.\n * `loadMetaFromDb` is implemented by ObjectStackProtocolImplementation but\n * is NOT (yet) part of the canonical ObjectStackProtocol wire-contract in\n * `@objectstack/spec`, since it is a server-side bootstrap concern only.\n */\ninterface ProtocolWithDbRestore {\n loadMetaFromDb(): Promise<{ loaded: number; errors: number }>;\n}\n\n/** Type guard — checks whether the service exposes `loadMetaFromDb`. */\nfunction hasLoadMetaFromDb(service: unknown): service is ProtocolWithDbRestore {\n return (\n typeof service === 'object' &&\n service !== null &&\n typeof (service as Record<string, unknown>)['loadMetaFromDb'] === 'function'\n );\n}\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 ctx.registerService('data', this.ql); // ObjectQL implements IDataEngine\n\n // Register manifest service for direct app/package registration.\n // Plugins call ctx.getService('manifest').register(manifestData)\n // instead of the legacy ctx.registerService('app.<id>', manifestData) convention.\n const ql = this.ql;\n ctx.registerService('manifest', {\n register: (manifest: any) => {\n ql.registerApp(manifest);\n ctx.logger.debug('Manifest registered via manifest service', {\n id: manifest.id || manifest.name\n });\n }\n });\n\n ctx.logger.info('ObjectQL engine registered', {\n services: ['objectql', 'data', 'manifest'],\n });\n\n // Register Protocol Implementation\n const protocolShim = new ObjectStackProtocolImplementation(\n this.ql, \n () => ctx.getServices ? ctx.getServices() : new Map()\n );\n\n ctx.registerService('protocol', protocolShim);\n ctx.logger.info('Protocol service registered');\n }\n\n start = async (ctx: PluginContext) => {\n ctx.logger.info('ObjectQL engine starting...');\n\n // Sync from external metadata service (e.g. MetadataPlugin) if available\n try {\n const metadataService = ctx.getService('metadata') as any;\n if (metadataService && typeof metadataService.loadMany === 'function' && this.ql) {\n await this.loadMetadataFromService(metadataService, ctx);\n }\n } catch (e: any) {\n ctx.logger.debug('No external metadata service to sync from');\n }\n \n // Discover features from Kernel Services\n if (ctx.getServices && this.ql) {\n const services = ctx.getServices();\n for (const [name, service] of services.entries()) {\n if (name.startsWith('driver.')) {\n // Register Driver\n this.ql.registerDriver(service);\n ctx.logger.debug('Discovered and registered driver service', { serviceName: name });\n }\n if (name.startsWith('app.')) {\n // Legacy fallback: discover app.* services (DEPRECATED)\n ctx.logger.warn(\n `[DEPRECATED] Service \"${name}\" uses legacy app.* convention. ` +\n `Migrate to ctx.getService('manifest').register(data).`\n );\n this.ql.registerApp(service); // service is Manifest\n ctx.logger.debug('Discovered and registered app service (legacy)', { serviceName: name });\n }\n }\n\n // Bridge realtime service from kernel service registry to ObjectQL.\n // RealtimeServicePlugin registers as 'realtime' service during init().\n // This enables ObjectQL to publish data change events.\n try {\n const realtimeService = ctx.getService('realtime');\n if (realtimeService && typeof realtimeService === 'object' && 'publish' in realtimeService) {\n ctx.logger.info('[ObjectQLPlugin] Bridging realtime service to ObjectQL for event publishing');\n this.ql.setRealtimeService(realtimeService as any);\n }\n } catch (e: any) {\n ctx.logger.debug('[ObjectQLPlugin] No realtime service found — data events will not be published', {\n error: e.message,\n });\n }\n }\n\n // Initialize drivers (calls driver.connect() which sets up persistence)\n await this.ql?.init();\n\n // Restore persisted metadata from sys_metadata table.\n // This hydrates SchemaRegistry with objects/views/apps that were saved\n // via protocol.saveMetaItem() in a previous session, ensuring custom\n // schemas survive cold starts and redeployments.\n await this.restoreMetadataFromDb(ctx);\n\n // Sync all registered object schemas to database\n // This ensures tables/collections are created or updated for every\n // object registered by plugins (e.g., sys_user from plugin-auth).\n await this.syncRegisteredSchemas(ctx);\n\n // Bridge all SchemaRegistry objects to metadata service\n // This ensures AI tools and other IMetadataService consumers can see all objects\n await this.bridgeObjectsToMetadataService(ctx);\n\n // Register built-in audit hooks\n this.registerAuditHooks(ctx);\n\n // Register tenant isolation middleware\n this.registerTenantMiddleware(ctx);\n\n ctx.logger.info('ObjectQL engine started', {\n driversRegistered: this.ql?.['drivers']?.size || 0,\n objectsRegistered: this.ql?.registry?.getAllObjects?.()?.length || 0\n });\n }\n\n /**\n * Register built-in audit hooks for auto-stamping created_by/updated_by\n * and fetching previousData for update/delete operations.\n */\n private registerAuditHooks(ctx: PluginContext) {\n if (!this.ql) return;\n\n // Auto-stamp created_by/updated_by on insert\n this.ql.registerHook('beforeInsert', async (hookCtx) => {\n if (hookCtx.session?.userId && hookCtx.input?.data) {\n const data = hookCtx.input.data as Record<string, any>;\n if (typeof data === 'object' && data !== null) {\n data.created_by = data.created_by ?? hookCtx.session.userId;\n data.updated_by = hookCtx.session.userId;\n data.created_at = data.created_at ?? new Date().toISOString();\n data.updated_at = new Date().toISOString();\n if (hookCtx.session.tenantId) {\n data.tenant_id = data.tenant_id ?? hookCtx.session.tenantId;\n }\n }\n }\n }, { object: '*', priority: 10 });\n\n // Auto-stamp updated_by on update\n this.ql.registerHook('beforeUpdate', async (hookCtx) => {\n if (hookCtx.session?.userId && hookCtx.input?.data) {\n const data = hookCtx.input.data as Record<string, any>;\n if (typeof data === 'object' && data !== null) {\n data.updated_by = hookCtx.session.userId;\n data.updated_at = new Date().toISOString();\n }\n }\n }, { object: '*', priority: 10 });\n\n // Auto-fetch previousData for update hooks\n this.ql.registerHook('beforeUpdate', async (hookCtx) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n where: { id: hookCtx.input.id }\n });\n if (existing) {\n hookCtx.previous = existing;\n }\n } catch (_e) {\n // Non-fatal: some objects may not support findOne\n }\n }\n }, { object: '*', priority: 5 });\n\n // Auto-fetch previousData for delete hooks\n this.ql.registerHook('beforeDelete', async (hookCtx) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n where: { id: hookCtx.input.id }\n });\n if (existing) {\n hookCtx.previous = existing;\n }\n } catch (_e) {\n // Non-fatal\n }\n }\n }, { object: '*', priority: 5 });\n\n ctx.logger.debug('Audit hooks registered (created_by/updated_by, previousData)');\n }\n\n /**\n * Register tenant isolation middleware that auto-injects tenant_id filter\n * for multi-tenant operations.\n */\n private registerTenantMiddleware(ctx: PluginContext) {\n if (!this.ql) return;\n\n this.ql.registerMiddleware(async (opCtx, next) => {\n // Only apply to operations with tenantId that are not system-level\n if (!opCtx.context?.tenantId || opCtx.context?.isSystem) {\n return next();\n }\n\n // Read operations: inject tenant_id filter into AST\n if (['find', 'findOne', 'count', 'aggregate'].includes(opCtx.operation)) {\n if (opCtx.ast) {\n const tenantFilter = { tenant_id: opCtx.context.tenantId };\n if (opCtx.ast.where) {\n opCtx.ast.where = { $and: [opCtx.ast.where, tenantFilter] };\n } else {\n opCtx.ast.where = tenantFilter;\n }\n }\n }\n\n await next();\n });\n\n ctx.logger.debug('Tenant isolation middleware registered');\n }\n\n /**\n * Synchronize all registered object schemas to the database.\n *\n * Groups objects by their responsible driver, then:\n * - If the driver advertises `supports.batchSchemaSync` and implements\n * `syncSchemasBatch()`, submits all schemas in a single call (reducing\n * network round-trips for remote drivers like Turso).\n * - Otherwise falls back to sequential `syncSchema()` per object.\n *\n * This is idempotent — drivers must tolerate repeated calls without\n * duplicating tables or erroring out.\n *\n * Drivers that do not implement `syncSchema` are silently skipped.\n */\n private async syncRegisteredSchemas(ctx: PluginContext) {\n if (!this.ql) return;\n\n const allObjects = this.ql.registry?.getAllObjects?.() ?? [];\n if (allObjects.length === 0) return;\n\n let synced = 0;\n let skipped = 0;\n\n // Group objects by driver for potential batch optimization\n const driverGroups = new Map<any, Array<{ obj: any; tableName: string }>>();\n\n for (const obj of allObjects) {\n const driver = this.ql.getDriverForObject(obj.name);\n if (!driver) {\n ctx.logger.debug('No driver available for object, skipping schema sync', {\n object: obj.name,\n });\n skipped++;\n continue;\n }\n\n if (typeof driver.syncSchema !== 'function') {\n ctx.logger.debug('Driver does not support syncSchema, skipping', {\n object: obj.name,\n driver: driver.name,\n });\n skipped++;\n continue;\n }\n\n const tableName = obj.tableName || obj.name;\n\n let group = driverGroups.get(driver);\n if (!group) {\n group = [];\n driverGroups.set(driver, group);\n }\n group.push({ obj, tableName });\n }\n\n // Process each driver group\n for (const [driver, entries] of driverGroups) {\n // Batch path: driver supports batch schema sync\n if (\n driver.supports?.batchSchemaSync &&\n typeof driver.syncSchemasBatch === 'function'\n ) {\n const batchPayload = entries.map((e) => ({\n object: e.tableName,\n schema: e.obj,\n }));\n try {\n await driver.syncSchemasBatch(batchPayload);\n synced += entries.length;\n ctx.logger.debug('Batch schema sync succeeded', {\n driver: driver.name,\n count: entries.length,\n });\n } catch (e: unknown) {\n ctx.logger.warn('Batch schema sync failed, falling back to sequential', {\n driver: driver.name,\n error: e instanceof Error ? e.message : String(e),\n });\n // Fallback: sequential sync for this driver's objects\n for (const { obj, tableName } of entries) {\n try {\n await driver.syncSchema(tableName, obj);\n synced++;\n } catch (seqErr: unknown) {\n ctx.logger.warn('Failed to sync schema for object', {\n object: obj.name,\n tableName,\n driver: driver.name,\n error: seqErr instanceof Error ? seqErr.message : String(seqErr),\n });\n }\n }\n }\n } else {\n // Sequential path: no batch support\n for (const { obj, tableName } of entries) {\n try {\n await driver.syncSchema(tableName, obj);\n synced++;\n } catch (e: unknown) {\n ctx.logger.warn('Failed to sync schema for object', {\n object: obj.name,\n tableName,\n driver: driver.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n }\n }\n\n if (synced > 0 || skipped > 0) {\n ctx.logger.info('Schema sync complete', { synced, skipped, total: allObjects.length });\n }\n }\n\n /**\n * Restore persisted metadata from the database (sys_metadata) on startup.\n *\n * Calls `protocol.loadMetaFromDb()` to bulk-load all active metadata\n * records (objects, views, apps, etc.) into the in-memory SchemaRegistry.\n * This closes the persistence loop so that user-created schemas survive\n * kernel cold starts and redeployments.\n *\n * Gracefully degrades when:\n * - The protocol service is unavailable (e.g., in-memory-only mode).\n * - `loadMetaFromDb` is not implemented by the protocol shim.\n * - The underlying driver/table does not exist yet (first-run scenario).\n */\n private async restoreMetadataFromDb(ctx: PluginContext): Promise<void> {\n // Phase 1: Resolve protocol service (separate from DB I/O for clearer diagnostics)\n let protocol: ProtocolWithDbRestore;\n try {\n const service = ctx.getService('protocol');\n if (!service || !hasLoadMetaFromDb(service)) {\n ctx.logger.debug('Protocol service does not support loadMetaFromDb, skipping DB restore');\n return;\n }\n protocol = service;\n } catch (e: unknown) {\n ctx.logger.debug('Protocol service unavailable, skipping DB restore', {\n error: e instanceof Error ? e.message : String(e),\n });\n return;\n }\n\n // Phase 2: DB hydration (loads into SchemaRegistry)\n try {\n const { loaded, errors } = await protocol.loadMetaFromDb();\n\n if (loaded > 0 || errors > 0) {\n ctx.logger.info('Metadata restored from database to SchemaRegistry', { loaded, errors });\n } else {\n ctx.logger.debug('No persisted metadata found in database');\n }\n } catch (e: unknown) {\n // Non-fatal: first-run or in-memory driver may not have sys_metadata yet\n ctx.logger.debug('DB metadata restore failed (non-fatal)', {\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n /**\n * Bridge all SchemaRegistry objects to the metadata service.\n *\n * This ensures objects registered by plugins and loaded from sys_metadata\n * are visible to AI tools and other consumers that query IMetadataService.\n *\n * Runs after both restoreMetadataFromDb() and syncRegisteredSchemas() to\n * catch all objects in the SchemaRegistry regardless of their source.\n */\n private async bridgeObjectsToMetadataService(ctx: PluginContext): Promise<void> {\n try {\n const metadataService = ctx.getService<any>('metadata');\n if (!metadataService || typeof metadataService.register !== 'function') {\n ctx.logger.debug('Metadata service unavailable for bridging, skipping');\n return;\n }\n\n if (!this.ql?.registry) {\n ctx.logger.debug('SchemaRegistry unavailable for bridging, skipping');\n return;\n }\n\n const objects = this.ql.registry.getAllObjects();\n let bridged = 0;\n\n for (const obj of objects) {\n try {\n // Check if object is already in metadata service to avoid duplicates\n const existing = await metadataService.getObject(obj.name);\n if (!existing) {\n // Register object that exists in SchemaRegistry but not in metadata service\n await metadataService.register('object', obj.name, obj);\n bridged++;\n }\n } catch (e: unknown) {\n ctx.logger.debug('Failed to bridge object to metadata service', {\n object: obj.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n if (bridged > 0) {\n ctx.logger.info('Bridged objects from SchemaRegistry to metadata service', {\n count: bridged,\n total: objects.length\n });\n } else {\n ctx.logger.debug('No objects needed bridging (all already in metadata service)');\n }\n } catch (e: unknown) {\n ctx.logger.debug('Failed to bridge objects to metadata service', {\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n /**\n * Load metadata from external metadata service into ObjectQL registry\n * This enables ObjectQL to use file-based or remote metadata\n */\n private async loadMetadataFromService(metadataService: any, ctx: PluginContext) {\n ctx.logger.info('Syncing metadata from external service into ObjectQL registry...');\n \n // Metadata types to sync\n const metadataTypes = ['object', 'view', 'app', 'flow', 'workflow', 'function'];\n let totalLoaded = 0;\n \n for (const type of metadataTypes) {\n try {\n // Check if service has loadMany method\n if (typeof metadataService.loadMany === 'function') {\n const items = await metadataService.loadMany(type);\n \n if (items && items.length > 0) {\n items.forEach((item: any) => {\n // Determine key field (usually 'name' or 'id')\n const keyField = item.id ? 'id' : 'name';\n \n // For objects, use the ownership-aware registration\n if (type === 'object' && this.ql) {\n // Objects are registered differently (ownership model)\n // Skip for now - handled by app registration\n return;\n }\n \n // Register other types in the registry\n if (this.ql?.registry?.registerItem) {\n this.ql.registry.registerItem(type, item, keyField);\n }\n });\n \n totalLoaded += items.length;\n ctx.logger.info(`Synced ${items.length} ${type}(s) from metadata service`);\n }\n }\n } catch (e: any) {\n // Type might not exist in metadata service - that's ok\n ctx.logger.debug(`No ${type} metadata found or error loading`, { \n error: e.message \n });\n }\n }\n \n if (totalLoaded > 0) {\n ctx.logger.info(`Metadata sync complete: ${totalLoaded} items loaded into ObjectQL registry`);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectKernel } from '@objectstack/core';\nimport { ObjectQLPlugin } from './plugin.js';\nimport type { Plugin } from '@objectstack/core';\n\n/**\n * Options for creating an ObjectQL Kernel.\n */\nexport interface ObjectQLKernelOptions {\n /**\n * Additional plugins to register with the kernel.\n */\n plugins?: Plugin[];\n}\n\n/**\n * Convenience factory for creating an ObjectQL-ready kernel.\n *\n * Creates an ObjectKernel pre-configured with the ObjectQLPlugin\n * (data engine, schema registry, protocol implementation) plus any\n * additional plugins provided.\n *\n * @example\n * ```typescript\n * import { createObjectQLKernel } from '@objectstack/objectql';\n *\n * const kernel = createObjectQLKernel({\n * plugins: [myDriverPlugin, myAuthPlugin],\n * });\n * await kernel.bootstrap();\n * ```\n */\nexport async function createObjectQLKernel(options: ObjectQLKernelOptions = {}): Promise<ObjectKernel> {\n const kernel = new ObjectKernel();\n\n // Register the core ObjectQLPlugin first\n await kernel.use(new ObjectQLPlugin());\n\n // Register any additional plugins\n if (options.plugins) {\n for (const plugin of options.plugins) {\n await kernel.use(plugin);\n }\n }\n\n return kernel;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ServiceObject } from '@objectstack/spec/data';\n\n// ── Introspection Types ──────────────────────────────────────────────────────\n\n/**\n * Column metadata from database introspection.\n */\nexport interface IntrospectedColumn {\n /** Column name */\n name: string;\n /** Native database type (e.g., 'varchar', 'integer', 'timestamp') */\n type: string;\n /** Whether the column is nullable */\n nullable: boolean;\n /** Default value if any */\n defaultValue?: unknown;\n /** Whether this is a primary key */\n isPrimary?: boolean;\n /** Whether this column has a unique constraint */\n isUnique?: boolean;\n /** Maximum length for string types */\n maxLength?: number;\n}\n\n/**\n * Foreign key relationship metadata.\n */\nexport interface IntrospectedForeignKey {\n /** Column name in the source table */\n columnName: string;\n /** Referenced table name */\n referencedTable: string;\n /** Referenced column name */\n referencedColumn: string;\n /** Constraint name */\n constraintName?: string;\n}\n\n/**\n * Table metadata from database introspection.\n */\nexport interface IntrospectedTable {\n /** Table name */\n name: string;\n /** List of columns */\n columns: IntrospectedColumn[];\n /** List of foreign key relationships */\n foreignKeys: IntrospectedForeignKey[];\n /** Primary key columns */\n primaryKeys: string[];\n}\n\n/**\n * Complete database schema introspection result.\n */\nexport interface IntrospectedSchema {\n /** Map of table name to table metadata */\n tables: Record<string, IntrospectedTable>;\n}\n\n// ── Utility Functions ────────────────────────────────────────────────────────\n\n/**\n * Convert a snake_case or plain string to Title Case.\n *\n * @example\n * toTitleCase('first_name') // => 'First Name'\n * toTitleCase('project_task') // => 'Project Task'\n */\nexport function toTitleCase(str: string): string {\n return str\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n/**\n * Map a native database column type to an ObjectStack FieldType.\n */\nfunction mapDatabaseTypeToFieldType(\n dbType: string\n): 'text' | 'textarea' | 'number' | 'boolean' | 'datetime' | 'date' | 'time' | 'json' {\n const type = dbType.toLowerCase();\n\n // Text types\n if (type.includes('char') || type.includes('varchar') || type.includes('text')) {\n if (type.includes('text')) return 'textarea';\n return 'text';\n }\n\n // Numeric types\n if (\n type.includes('int') || type === 'integer' || type === 'bigint' || type === 'smallint'\n ) {\n return 'number';\n }\n if (\n type.includes('float') || type.includes('double') || type.includes('decimal') ||\n type.includes('numeric') || type === 'real'\n ) {\n return 'number';\n }\n\n // Boolean\n if (type.includes('bool')) {\n return 'boolean';\n }\n\n // Date / Time types\n if (type.includes('timestamp') || type === 'datetime') {\n return 'datetime';\n }\n if (type === 'date') {\n return 'date';\n }\n if (type === 'time') {\n return 'time';\n }\n\n // JSON types\n if (type === 'json' || type === 'jsonb') {\n return 'json';\n }\n\n // Default to text\n return 'text';\n}\n\n/**\n * Convert an introspected database schema to ObjectStack object definitions.\n *\n * This allows using existing database tables without manually defining metadata.\n *\n * @param introspectedSchema - The schema returned from driver.introspectSchema()\n * @param options - Optional filtering / conversion settings\n * @returns Array of ServiceObject definitions that can be registered with ObjectQL\n *\n * @example\n * ```typescript\n * const schema = await driver.introspectSchema();\n * const objects = convertIntrospectedSchemaToObjects(schema);\n * for (const obj of objects) {\n * engine.registerObject(obj);\n * }\n * ```\n */\nexport function convertIntrospectedSchemaToObjects(\n introspectedSchema: IntrospectedSchema,\n options?: {\n /** Tables to exclude from conversion */\n excludeTables?: string[];\n /** Tables to include (if specified, only these will be converted) */\n includeTables?: string[];\n /** Whether to skip system columns like id, created_at, updated_at (default: true) */\n skipSystemColumns?: boolean;\n }\n): ServiceObject[] {\n const objects: ServiceObject[] = [];\n const excludeTables = options?.excludeTables || [];\n const includeTables = options?.includeTables;\n const skipSystemColumns = options?.skipSystemColumns !== false;\n\n for (const [tableName, table] of Object.entries(introspectedSchema.tables)) {\n if (excludeTables.includes(tableName)) continue;\n if (includeTables && !includeTables.includes(tableName)) continue;\n\n const fields: Record<string, any> = {};\n\n for (const column of table.columns) {\n // Skip system columns if requested\n if (skipSystemColumns && ['id', 'created_at', 'updated_at'].includes(column.name)) {\n continue;\n }\n\n // Check for foreign key → lookup field\n const foreignKey = table.foreignKeys.find((fk) => fk.columnName === column.name);\n\n if (foreignKey) {\n fields[column.name] = {\n name: column.name,\n type: 'lookup' as const,\n reference: foreignKey.referencedTable,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n } else {\n const fieldType = mapDatabaseTypeToFieldType(column.type);\n\n const field: Record<string, any> = {\n name: column.name,\n type: fieldType,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n\n if (column.isUnique) {\n field.unique = true;\n }\n if (column.maxLength && (fieldType === 'text' || fieldType === 'textarea')) {\n field.maxLength = column.maxLength;\n }\n if (column.defaultValue != null) {\n field.defaultValue = column.defaultValue;\n }\n\n fields[column.name] = field;\n }\n }\n\n objects.push({\n name: tableName,\n label: toTitleCase(tableName),\n fields,\n } as ServiceObject);\n }\n\n return objects;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/registry.ts","../src/protocol.ts","../src/engine.ts","../src/hook-wrappers.ts","../src/hook-metrics.ts","../src/hook-binder.ts","../src/metadata-facade.ts","../src/plugin.ts","../src/kernel-factory.ts","../src/util.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ServiceObject, ObjectSchema, ObjectOwnership } from '@objectstack/spec/data';\nimport { ObjectStackManifest, ManifestSchema, InstalledPackage, InstalledPackageSchema } from '@objectstack/spec/kernel';\nimport { AppSchema } from '@objectstack/spec/ui';\n\n/**\n * Reserved namespaces that do not get FQN prefix applied.\n * Objects in these namespaces keep their short names (e.g., \"user\" — short name IS the canonical key).\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 canonical registry key for an object.\n *\n * Under the current naming convention, object names are canonical identifiers\n * and are used as-is (no namespace__ prefix). The namespace parameter is\n * retained for backward compatibility but no longer affects the returned key.\n *\n * @param namespace - The package namespace (unused, kept for API compatibility)\n * @param shortName - The object's name (already the canonical identifier)\n * @returns The object name unchanged\n *\n * @example\n * computeFQN('crm', 'account') // => 'account'\n * computeFQN(undefined, 'task') // => 'task'\n */\nexport function computeFQN(_namespace: string | undefined, shortName: string): string {\n return shortName;\n}\n\n/**\n * Parse FQN back to namespace and short name.\n * \n * @param fqn - Object name (e.g., \"account\" or legacy \"crm__account\" for backward compat)\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 * - `name`: canonical object name (e.g., \"account\", \"sys_user\")\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\n/**\n * Construction options for {@link SchemaRegistry}.\n */\nexport interface SchemaRegistryOptions {\n /**\n * Whether the host kernel runs in multi-tenant mode. When `true` (default),\n * the registry auto-injects `organization_id` (lookup → sys_organization)\n * into every registered user object that doesn't already declare it and\n * isn't `managedBy` an external subsystem or explicitly opted-out via\n * `systemFields: false`.\n *\n * Sourced from the `OS_MULTI_TENANT` env var when not explicitly set —\n * matches how the SecurityPlugin and CLI startup banner pick the mode.\n * Pass an explicit boolean to override (useful in tests).\n */\n multiTenant?: boolean;\n}\n\n/**\n * Augment a registered object with implicit system fields.\n *\n * Returns a *new* schema object when fields are added; returns the input\n * unchanged when nothing applies (the cheap path for system tables).\n *\n * Author-declared fields always win — we splice the system fields at the\n * front of the field map, so any same-named author field overwrites them\n * via the natural `{ ...sys, ...authored }` merge.\n *\n * Currently injects:\n * - `organization_id` — multi-tenant deployments. Required-false (the\n * SecurityPlugin populates it on insert; nullable rows are still\n * filtered out by the `tenant_isolation` RLS USING clause).\n */\nexport function applySystemFields(\n schema: ServiceObject,\n opts: { multiTenant: boolean }\n): ServiceObject {\n // 1. Hard opt-out at object level (e.g. seed/migration tables).\n if ((schema as any).systemFields === false) return schema;\n\n // 2. Skip externally-managed tables. better-auth/system/platform tables\n // declare exactly what they need; injecting more would either collide\n // with the manager's expectations (better-auth migrations) or pollute\n // audit-grade ledgers.\n if (schema.managedBy) return schema;\n\n const sf =\n typeof (schema as any).systemFields === 'object' && (schema as any).systemFields !== null\n ? ((schema as any).systemFields as { tenant?: boolean })\n : undefined;\n\n const wantTenant = opts.multiTenant && sf?.tenant !== false;\n\n const additions: Record<string, any> = {};\n\n if (wantTenant && !schema.fields?.organization_id) {\n additions.organization_id = {\n type: 'lookup',\n reference: 'sys_organization',\n label: 'Organization',\n required: false,\n indexed: true,\n hidden: true,\n readonly: true,\n description: 'Tenant scope (auto-populated by SecurityPlugin on insert).',\n };\n }\n\n if (Object.keys(additions).length === 0) return schema;\n\n return {\n ...schema,\n fields: { ...additions, ...(schema.fields ?? {}) },\n };\n}\n\nexport class SchemaRegistry {\n // ==========================================\n // Logging control\n // ==========================================\n\n /** Controls verbosity of registry console messages. Default: 'info'. */\n private _logLevel: RegistryLogLevel = 'info';\n\n /** Whether to auto-inject multi-tenant system fields. */\n private readonly multiTenant: boolean;\n\n constructor(options: SchemaRegistryOptions = {}) {\n if (options.multiTenant !== undefined) {\n this.multiTenant = options.multiTenant;\n } else {\n // Mirror the SecurityPlugin / CLI banner default (env-driven, on by default).\n this.multiTenant =\n String(process.env.OS_MULTI_TENANT ?? 'true').toLowerCase() !== 'false';\n }\n }\n\n get logLevel(): RegistryLogLevel { return this._logLevel; }\n set logLevel(level: RegistryLogLevel) { this._logLevel = level; }\n\n private 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 objectContributors = new Map<string, ObjectContributor[]>();\n\n /** FQN → Merged ServiceObject (cached, invalidated on changes) */\n private mergedObjectCache = new Map<string, ServiceObject>();\n\n /** Namespace → Set<PackageId> (multiple packages can share a namespace) */\n private namespaceRegistry = new Map<string, Set<string>>();\n\n // ==========================================\n // Generic metadata storage (non-object types)\n // ==========================================\n\n /** Type → Name/ID → MetadataItem */\n private metadata = new Map<string, Map<string, any>>();\n\n // ==========================================\n // Namespace Management\n // ==========================================\n\n /**\n * Register a namespace for a package.\n * Multiple packages can share the same namespace (e.g. 'sys').\n */\n registerNamespace(namespace: string, packageId: string): void {\n if (!namespace) return;\n\n let owners = this.namespaceRegistry.get(namespace);\n if (!owners) {\n owners = new Set();\n this.namespaceRegistry.set(namespace, owners);\n }\n owners.add(packageId);\n this.log(`[Registry] Registered namespace: ${namespace} → ${packageId}`);\n }\n\n /**\n * Unregister a namespace when a package is uninstalled.\n */\n unregisterNamespace(namespace: string, packageId: string): void {\n const owners = this.namespaceRegistry.get(namespace);\n if (owners) {\n owners.delete(packageId);\n if (owners.size === 0) {\n this.namespaceRegistry.delete(namespace);\n }\n this.log(`[Registry] Unregistered namespace: ${namespace} ← ${packageId}`);\n }\n }\n\n /**\n * Get the packages that use a namespace.\n */\n getNamespaceOwner(namespace: string): string | undefined {\n const owners = this.namespaceRegistry.get(namespace);\n if (!owners || owners.size === 0) return undefined;\n // Return the first registered package for backwards compatibility\n return owners.values().next().value;\n }\n\n /**\n * Get all packages that share a namespace.\n */\n getNamespaceOwners(namespace: string): string[] {\n const owners = this.namespaceRegistry.get(namespace);\n return owners ? Array.from(owners) : [];\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 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 // Apply system-field injection (multi-tenant org_id, future owner/audit)\n // BEFORE FQN computation and contributor storage so every consumer of\n // the registered schema (driver syncSchema, REST projector, hooks)\n // sees the same canonical shape. Author-declared fields win — see\n // applySystemFields().\n schema = applySystemFields(schema, { multiTenant: this.multiTenant });\n\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 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 (short name canonical, FQN supported for disambiguation).\n *\n * Short names are canonical for user code, AI generation, and most lookups.\n * FQN is accepted as an explicit fallback for cross-package disambiguation\n * when two packages contribute objects with the same short name.\n *\n * Resolution order:\n * 1. Exact name match — the name IS the canonical key.\n * If multiple packages contribute the same short name, a warning is logged\n * and the first match wins — disambiguate by passing the FQN explicitly.\n * 2. Legacy FQN match (e.g., 'crm__account') — backward compat.\n */\n getObject(name: string): ServiceObject | undefined {\n // Canonical: short name lookup\n const matches: string[] = [];\n for (const fqn of this.objectContributors.keys()) {\n const { shortName } = parseFQN(fqn);\n if (shortName === name) {\n matches.push(fqn);\n }\n }\n if (matches.length > 0) {\n if (matches.length > 1) {\n console.warn(\n `[SchemaRegistry] Ambiguous short name \"${name}\" matches: ${matches.join(', ')}. ` +\n `Returning first match. Use FQN to disambiguate.`\n );\n }\n return this.resolveObject(matches[0]);\n }\n\n // Fallback: explicit FQN\n return this.resolveObject(name);\n }\n\n /**\n * Get all registered objects (merged).\n * \n * @param packageId - Optional filter: only objects contributed by this package\n */\n 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 getObjectContributors(fqn: string): ObjectContributor[] {\n return this.objectContributors.get(fqn) || [];\n }\n\n /**\n * Get the owner contributor for an object.\n */\n 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 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 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 this.log(`[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 validate(type: string, item: any): unknown {\n if (type === 'object') {\n return ObjectSchema.parse(item);\n }\n if (type === 'app') {\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 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 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 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 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 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 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 getPackage(id: string): InstalledPackage | undefined {\n return this.metadata.get('package')?.get(id) as InstalledPackage | undefined;\n }\n\n getAllPackages(): InstalledPackage[] {\n return this.listItems<InstalledPackage>('package');\n }\n\n 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 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 registerApp(app: any, packageId?: string) {\n this.registerItem('app', app, 'name', packageId);\n }\n\n getApp(name: string): any {\n return this.getItem('app', name);\n }\n\n getAllApps(): any[] {\n return this.listItems('app');\n }\n\n // ==========================================\n // Plugin Helpers\n // ==========================================\n\n registerPlugin(manifest: ObjectStackManifest) {\n this.registerItem('plugin', manifest, 'id');\n }\n\n getAllPlugins(): ObjectStackManifest[] {\n return this.listItems<ObjectStackManifest>('plugin');\n }\n\n // ==========================================\n // Kind Helpers\n // ==========================================\n\n registerKind(kind: { id: string, globs: string[] }) {\n this.registerItem('kind', kind, 'id');\n }\n \n 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 reset(): void {\n this.objectContributors.clear();\n this.mergedObjectCache.clear();\n this.namespaceRegistry.clear();\n this.metadata.clear();\n this.log('[Registry] Reset complete');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectStackProtocol } from '@objectstack/spec/api';\nimport { IDataEngine } from '@objectstack/core';\nimport type { ObjectQL } from './engine.js';\nimport type {\n BatchUpdateRequest,\n BatchUpdateResponse,\n UpdateManyDataRequest,\n DeleteManyDataRequest\n} from '@objectstack/spec/api';\nimport type { MetadataCacheRequest, MetadataCacheResponse, ServiceInfo, ApiRoutes, WellKnownCapabilities } from '@objectstack/spec/api';\nimport type { IFeedService } from '@objectstack/spec/contracts';\nimport { parseFilterAST, isFilterAST } from '@objectstack/spec/data';\nimport { PLURAL_TO_SINGULAR, SINGULAR_TO_PLURAL } from '@objectstack/spec/shared';\n\n/**\n * Simple hash function for ETag generation (browser-compatible)\n * Uses a basic hash algorithm instead of crypto.createHash\n */\nfunction simpleHash(str: string): string {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return Math.abs(hash).toString(16);\n}\n\n/**\n * Service Configuration for Discovery\n * Maps service names to their routes and plugin providers\n */\nconst SERVICE_CONFIG: Record<string, { route: string; plugin: string }> = {\n auth: { route: '/api/v1/auth', plugin: 'plugin-auth' },\n automation: { route: '/api/v1/automation', plugin: 'plugin-automation' },\n cache: { route: '/api/v1/cache', plugin: 'plugin-redis' },\n queue: { route: '/api/v1/queue', plugin: 'plugin-bullmq' },\n job: { route: '/api/v1/jobs', plugin: 'job-scheduler' },\n ui: { route: '/api/v1/ui', plugin: 'ui-plugin' },\n workflow: { route: '/api/v1/workflow', plugin: 'plugin-workflow' },\n realtime: { route: '/api/v1/realtime', plugin: 'plugin-realtime' },\n notification: { route: '/api/v1/notifications', plugin: 'plugin-notifications' },\n ai: { route: '/api/v1/ai', plugin: 'plugin-ai' },\n i18n: { route: '/api/v1/i18n', plugin: 'service-i18n' },\n graphql: { route: '/graphql', plugin: 'plugin-graphql' }, // GraphQL uses /graphql by convention (not versioned REST)\n 'file-storage': { route: '/api/v1/storage', plugin: 'plugin-storage' },\n search: { route: '/api/v1/search', plugin: 'plugin-search' },\n};\n\nexport class ObjectStackProtocolImplementation implements ObjectStackProtocol {\n private engine: ObjectQL;\n private getServicesRegistry?: () => Map<string, any>;\n private getFeedService?: () => IFeedService | undefined;\n /**\n * Project scope applied to sys_metadata reads/writes. When undefined\n * (single-kernel deployments), rows land in / come from the\n * platform-global bucket (`project_id IS NULL`). When set, every\n * saveMetaItem insert/update and loadMetaFromDb query is filtered by\n * `project_id = projectId`, so per-project kernels see only their own\n * metadata even if several projects share the same physical database.\n */\n private projectId?: string;\n\n constructor(\n engine: IDataEngine,\n getServicesRegistry?: () => Map<string, any>,\n getFeedService?: () => IFeedService | undefined,\n projectId?: string,\n ) {\n this.engine = engine as ObjectQL;\n this.getServicesRegistry = getServicesRegistry;\n this.getFeedService = getFeedService;\n this.projectId = projectId;\n }\n\n /**\n * Exposes the project scope the protocol is bound to. Consumers like\n * the HTTP dispatcher use this to decide whether to trust the process-\n * wide SchemaRegistry or whether they must route a read through the\n * protocol's project_id-filtered lookup.\n */\n getProjectId(): string | undefined {\n return this.projectId;\n }\n\n private requireFeedService(): IFeedService {\n const svc = this.getFeedService?.();\n if (!svc) {\n throw new Error('Feed service not available. Install and register service-feed to enable feed operations.');\n }\n return svc;\n }\n\n async getDiscovery() {\n // Get registered services from kernel if available\n const registeredServices = this.getServicesRegistry ? this.getServicesRegistry() : new Map();\n \n // Build dynamic service info with proper typing\n const services: Record<string, ServiceInfo> = {\n // --- Kernel-provided (objectql is an example kernel implementation) ---\n metadata: { enabled: true, status: 'available' as const, route: '/api/v1/meta', provider: 'objectql' },\n data: { enabled: true, status: 'available' as const, route: '/api/v1/data', provider: 'objectql' },\n analytics: { enabled: true, status: 'available' as const, route: '/api/v1/analytics', provider: 'objectql' },\n };\n\n // Check which services are actually registered\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n // Service is registered and available\n services[serviceName] = {\n enabled: true,\n status: 'available' as const,\n route: config.route,\n provider: config.plugin,\n };\n } else {\n // Service is not registered\n services[serviceName] = {\n enabled: false,\n status: 'unavailable' as const,\n message: `Install ${config.plugin} to enable`,\n };\n }\n }\n\n // Build routes from services — a flat convenience map for client routing\n const serviceToRouteKey: Record<string, keyof ApiRoutes> = {\n auth: 'auth',\n automation: 'automation',\n ui: 'ui',\n workflow: 'workflow',\n realtime: 'realtime',\n notification: 'notifications',\n ai: 'ai',\n i18n: 'i18n',\n graphql: 'graphql',\n 'file-storage': 'storage',\n };\n\n const optionalRoutes: Partial<ApiRoutes> = {\n analytics: '/api/v1/analytics',\n };\n\n // Add routes for available plugin services\n for (const [serviceName, config] of Object.entries(SERVICE_CONFIG)) {\n if (registeredServices.has(serviceName)) {\n const routeKey = serviceToRouteKey[serviceName];\n if (routeKey) {\n optionalRoutes[routeKey] = config.route;\n }\n }\n }\n\n // Add feed service status\n if (registeredServices.has('feed')) {\n services['feed'] = {\n enabled: true,\n status: 'available' as const,\n route: '/api/v1/data',\n provider: 'service-feed',\n };\n } else {\n services['feed'] = {\n enabled: false,\n status: 'unavailable' as const,\n message: 'Install service-feed to enable',\n };\n }\n\n const routes: ApiRoutes = {\n data: '/api/v1/data',\n metadata: '/api/v1/meta',\n ...optionalRoutes,\n };\n\n // Build well-known capabilities from registered services.\n // DiscoverySchema defines capabilities as Record<string, { enabled, features?, description? }>\n // (hierarchical format). We also keep a flat WellKnownCapabilities for backward compat.\n const wellKnown: WellKnownCapabilities = {\n feed: registeredServices.has('feed'),\n comments: registeredServices.has('feed'),\n automation: registeredServices.has('automation'),\n cron: registeredServices.has('job'),\n search: registeredServices.has('search'),\n export: registeredServices.has('automation') || registeredServices.has('queue'),\n chunkedUpload: registeredServices.has('file-storage'),\n };\n\n // Convert flat booleans → hierarchical capability objects\n const capabilities: Record<string, { enabled: boolean; description?: string }> = {};\n for (const [key, enabled] of Object.entries(wellKnown)) {\n capabilities[key] = { enabled };\n }\n\n return {\n version: '1.0',\n apiName: 'ObjectStack API',\n routes,\n services,\n capabilities,\n };\n }\n\n async getMetaTypes() {\n const schemaTypes = this.engine.registry.getRegisteredTypes();\n\n // Also include types from MetadataService (runtime-registered: agent, tool, etc.)\n let runtimeTypes: string[] = [];\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.getRegisteredTypes === 'function') {\n runtimeTypes = await metadataService.getRegisteredTypes();\n }\n } catch {\n // MetadataService not available\n }\n\n const allTypes = Array.from(new Set([...schemaTypes, ...runtimeTypes]));\n return { types: allTypes };\n }\n\n async getMetaItems(request: { type: string; packageId?: string }) {\n const { packageId } = request;\n let items: unknown[] = [];\n\n // Unscoped kernels (control plane): read everything from SchemaRegistry.\n // Scoped (project) kernels: skip user-project entries in SchemaRegistry to\n // prevent cross-project leakage, but DO include scope:'system' packages\n // (plugin-auth, plugin-security, plugin-audit, …) — those are globally\n // shared and must be visible at every project's meta endpoint.\n if (this.projectId === undefined) {\n items = [...this.engine.registry.listItems(request.type, packageId)];\n // Normalize singular/plural using explicit mapping\n if (items.length === 0) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) items = [...this.engine.registry.listItems(alt, packageId)];\n }\n } else {\n // For project kernels: the SchemaRegistry is owned by THIS\n // kernel's ObjectQL instance (not shared across projects in the\n // process), so we can safely include every package — system\n // plugins (auth/security/audit) and the project's own app\n // package alike. The `_packageId` tag added by `listItems`\n // (registry.ts) is preserved for the sidebar to compute the\n // correct navigation URL.\n items = [...this.engine.registry.listItems(request.type, packageId)];\n if (items.length === 0) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) items = [...this.engine.registry.listItems(alt, packageId)];\n }\n }\n\n // Always consult the DB so metadata persisted by the seeder /\n // bulkRegister shows up even when the registry already has unrelated\n // entries (the previous fallback-only logic meant project metadata\n // was never surfaced whenever system-bridged items populated the\n // registry). Deduplicate against whatever the registry returned.\n // Skip on project kernels — sys_metadata is control-plane only.\n if (this.projectId === undefined) try {\n const whereClause: Record<string, unknown> = {\n type: request.type,\n state: 'active',\n // Always filter by project_id: project kernels use their projectId,\n // control-plane kernels use NULL (global scope only).\n project_id: this.projectId ?? null,\n };\n if (packageId) whereClause._packageId = packageId;\n let records = await this.engine.find('sys_metadata', { where: whereClause });\n if ((!records || records.length === 0)) {\n // Try alternate type name in DB using explicit mapping\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altWhere: Record<string, unknown> = { type: alt, state: 'active', project_id: this.projectId ?? null };\n if (packageId) altWhere._packageId = packageId;\n records = await this.engine.find('sys_metadata', { where: altWhere });\n }\n }\n if (records && records.length > 0) {\n const byName = new Map<string, any>();\n for (const existing of items) {\n const entry = existing as any;\n if (entry && typeof entry === 'object' && 'name' in entry) {\n byName.set(entry.name, entry);\n }\n }\n for (const record of records) {\n const data = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n if (data && typeof data === 'object' && 'name' in data) {\n byName.set(data.name, data);\n }\n // Only hydrate the global registry for unscoped calls —\n // scoped project entries must not leak process-wide.\n if (this.projectId === undefined) {\n this.engine.registry.registerItem(request.type, data, 'name' as any);\n }\n }\n items = Array.from(byName.values());\n }\n } catch {\n // DB not available — fall through with whatever we already have.\n }\n\n // Merge with MetadataService (runtime-registered items: agents, tools, etc.)\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.list === 'function') {\n let runtimeItems = await metadataService.list(request.type);\n // When filtering by packageId, only include runtime items that\n // belong to the requested package. MetadataService.list() returns\n // items from ALL packages, so we must filter here to respect the\n // package scope requested by the caller (e.g., Studio sidebar).\n if (packageId && runtimeItems && runtimeItems.length > 0) {\n runtimeItems = runtimeItems.filter((item: any) => item?._packageId === packageId);\n }\n if (runtimeItems && runtimeItems.length > 0) {\n // Merge, avoiding duplicates by name\n const itemMap = new Map<string, any>();\n for (const item of items) {\n const entry = item as any;\n if (entry && typeof entry === 'object' && 'name' in entry) {\n itemMap.set(entry.name, entry);\n }\n }\n for (const item of runtimeItems) {\n const entry = item as any;\n if (entry && typeof entry === 'object' && 'name' in entry) {\n itemMap.set(entry.name, entry);\n }\n }\n items = Array.from(itemMap.values());\n }\n }\n } catch {\n // MetadataService not available or doesn't support this type\n }\n\n return {\n type: request.type,\n items\n };\n }\n\n async getMetaItem(request: { type: string, name: string, packageId?: string }) {\n let item: unknown;\n\n // When scoped to a project, SchemaRegistry (a process-wide static\n // singleton) cannot be trusted — it's shared across every project\n // kernel in this process and would leak one project's definitions\n // into another's responses. Go straight to the database so the\n // project_id filter guarantees isolation.\n if (this.projectId === undefined) {\n item = this.engine.registry.getItem(request.type, request.name);\n // Normalize singular/plural using explicit mapping\n if (item === undefined) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) item = this.engine.registry.getItem(alt, request.name);\n }\n }\n\n // Fallback to database if not in registry.\n // Skip on project kernels — sys_metadata is control-plane only;\n // project kernels source metadata from the artifact via MetadataService below.\n if (item === undefined && this.projectId === undefined) {\n try {\n const scopedWhere: Record<string, unknown> = {\n type: request.type,\n name: request.name,\n state: 'active',\n };\n // Always filter by project_id: project kernels use their projectId,\n // control-plane kernels use NULL (global scope only).\n scopedWhere.project_id = this.projectId ?? null;\n const record = await this.engine.findOne('sys_metadata', {\n where: scopedWhere,\n });\n if (record) {\n item = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n // Only hydrate the global registry for unscoped calls,\n // see getMetaItem preamble for why scoped calls must not.\n if (this.projectId === undefined) {\n this.engine.registry.registerItem(request.type, item, 'name' as any);\n }\n } else {\n // Try alternate type name using explicit mapping\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) {\n const altWhere: Record<string, unknown> = { type: alt, name: request.name, state: 'active' };\n altWhere.project_id = this.projectId ?? null;\n const altRecord = await this.engine.findOne('sys_metadata', { where: altWhere });\n if (altRecord) {\n item = typeof altRecord.metadata === 'string'\n ? JSON.parse(altRecord.metadata)\n : altRecord.metadata;\n // Only hydrate back into the global registry\n // when we're NOT scoped — otherwise the entry\n // would leak into other projects in this process.\n if (this.projectId === undefined) {\n this.engine.registry.registerItem(request.type, item, 'name' as any);\n }\n }\n }\n }\n } catch {\n // DB not available, return undefined\n }\n }\n\n // Fallback to MetadataService for runtime-registered items (agents, tools, etc.)\n if (item === undefined) {\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.get === 'function') {\n item = await metadataService.get(request.type, request.name);\n }\n } catch {\n // MetadataService not available\n }\n }\n\n return {\n type: request.type,\n name: request.name,\n item\n };\n }\n\n async getUiView(request: { object: string, type: 'list' | 'form' }) {\n const schema = this.engine.registry.getObject(request.object);\n if (!schema) throw new Error(`Object ${request.object} not found`);\n\n const fields = schema.fields || {};\n const fieldKeys = Object.keys(fields);\n\n if (request.type === 'list') {\n // Intelligent Column Selection\n // 1. Always include 'name' or name-like fields\n // 2. Limit to 6 columns by default\n const priorityFields = ['name', 'title', 'label', 'subject', 'email', 'status', 'type', 'category', 'created_at'];\n \n let columns = fieldKeys.filter(k => priorityFields.includes(k));\n \n // If few priority fields, add others until 5\n if (columns.length < 5) {\n const remaining = fieldKeys.filter(k => !columns.includes(k) && k !== 'id' && !fields[k].hidden);\n columns = [...columns, ...remaining.slice(0, 5 - columns.length)];\n }\n \n // Sort columns by priority then alphabet or schema order\n // For now, just keep them roughly in order they appear in schema or priority list\n \n return {\n list: {\n type: 'grid' as const,\n object: request.object,\n label: schema.label || schema.name,\n columns: columns.map(f => ({\n field: f,\n label: fields[f]?.label || f,\n sortable: true\n })),\n sort: fields['created_at'] ? ([{ field: 'created_at', order: 'desc' }] as any) : undefined,\n searchableFields: columns.slice(0, 3) // Make first few textual columns searchable\n }\n };\n } else {\n // Form View Generation\n // Simple single-section layout for now\n const formFields = fieldKeys\n .filter(k => k !== 'id' && k !== 'created_at' && k !== 'updated_at' && !fields[k].hidden)\n .map(f => ({\n field: f,\n label: fields[f]?.label,\n required: fields[f]?.required,\n readonly: fields[f]?.readonly,\n type: fields[f]?.type,\n // Default to 2 columns for most, 1 for textareas\n colSpan: (fields[f]?.type === 'textarea' || fields[f]?.type === 'html') ? 2 : 1\n }));\n\n return {\n form: {\n type: 'simple' as const,\n object: request.object,\n label: `Edit ${schema.label || schema.name}`,\n sections: [\n {\n label: 'General Information',\n columns: 2 as const,\n collapsible: false,\n collapsed: false,\n fields: formFields\n }\n ]\n }\n };\n }\n }\n\n async findData(request: { object: string, query?: any, context?: any }) {\n const options: any = { ...request.query };\n // Forward the dispatcher's ExecutionContext so RBAC/RLS middleware\n // can apply per-request enforcement. The protocol layer is purely\n // a normalizer — it must never strip security context.\n if (request.context !== undefined) {\n options.context = request.context;\n }\n\n // ====================================================================\n // Normalize legacy params → QueryAST standard (where/fields/orderBy/offset/expand)\n // ====================================================================\n\n // Numeric fields — normalize top → limit, skip → offset\n if (options.top != null) {\n options.limit = Number(options.top);\n delete options.top;\n }\n if (options.skip != null) {\n options.offset = Number(options.skip);\n delete options.skip;\n }\n if (options.limit != null) options.limit = Number(options.limit);\n if (options.offset != null) options.offset = Number(options.offset);\n\n // Select → fields: comma-separated string → array\n if (typeof options.select === 'string') {\n options.fields = options.select.split(',').map((s: string) => s.trim()).filter(Boolean);\n } else if (Array.isArray(options.select)) {\n options.fields = options.select;\n }\n if (options.select !== undefined) delete options.select;\n\n // Sort/orderBy → orderBy: string → SortNode[] array\n const sortValue = options.orderBy ?? options.sort;\n if (typeof sortValue === 'string') {\n const parsed = sortValue.split(',').map((part: string) => {\n const trimmed = part.trim();\n if (trimmed.startsWith('-')) {\n return { field: trimmed.slice(1), order: 'desc' as const };\n }\n const [field, order] = trimmed.split(/\\s+/);\n return { field, order: (order?.toLowerCase() === 'desc' ? 'desc' : 'asc') as 'asc' | 'desc' };\n }).filter((s: any) => s.field);\n options.orderBy = parsed;\n } else if (Array.isArray(sortValue)) {\n options.orderBy = sortValue;\n }\n delete options.sort;\n\n // Filter/filters/$filter → where: normalize all filter aliases\n const filterValue = options.filter ?? options.filters ?? options.$filter ?? options.where;\n delete options.filter;\n delete options.filters;\n delete options.$filter;\n\n if (filterValue !== undefined) {\n let parsedFilter = filterValue;\n // JSON string → object\n if (typeof parsedFilter === 'string') {\n try { parsedFilter = JSON.parse(parsedFilter); } catch { /* keep as-is */ }\n }\n // Filter AST array → FilterCondition object\n if (isFilterAST(parsedFilter)) {\n parsedFilter = parseFilterAST(parsedFilter);\n }\n options.where = parsedFilter;\n }\n\n // Populate/expand/$expand → expand (Record<string, QueryAST>)\n const populateValue = options.populate;\n const expandValue = options.$expand ?? options.expand;\n const expandNames: string[] = [];\n if (typeof populateValue === 'string') {\n expandNames.push(...populateValue.split(',').map((s: string) => s.trim()).filter(Boolean));\n } else if (Array.isArray(populateValue)) {\n expandNames.push(...populateValue);\n }\n if (!expandNames.length && expandValue) {\n if (typeof expandValue === 'string') {\n expandNames.push(...expandValue.split(',').map((s: string) => s.trim()).filter(Boolean));\n } else if (Array.isArray(expandValue)) {\n expandNames.push(...expandValue);\n }\n }\n delete options.populate;\n delete options.$expand;\n // Clean up non-object expand (e.g. string) BEFORE the Record conversion\n // below, so that populate-derived names can create the expand Record even\n // when a legacy string expand was also present.\n if (typeof options.expand !== 'object' || options.expand === null) {\n delete options.expand;\n }\n // Only set expand if not already an object (advanced usage)\n if (expandNames.length > 0 && !options.expand) {\n options.expand = {} as Record<string, any>;\n for (const rel of expandNames) {\n options.expand[rel] = { object: rel };\n }\n }\n\n // Boolean fields\n for (const key of ['distinct', 'count']) {\n if (options[key] === 'true') options[key] = true;\n else if (options[key] === 'false') options[key] = false;\n }\n \n // Flat field filters: REST-style query params like ?id=abc&status=open\n // After extracting all known query parameters, any remaining keys are\n // treated as implicit field-level equality filters merged into `where`.\n const knownParams = new Set([\n 'top', 'limit', 'offset',\n 'orderBy',\n 'fields',\n 'where',\n 'expand',\n 'distinct', 'count',\n 'aggregations', 'groupBy',\n 'search', 'context', 'cursor',\n ]);\n if (!options.where) {\n const implicitFilters: Record<string, unknown> = {};\n for (const key of Object.keys(options)) {\n if (!knownParams.has(key)) {\n implicitFilters[key] = options[key];\n delete options[key];\n }\n }\n if (Object.keys(implicitFilters).length > 0) {\n options.where = implicitFilters;\n }\n }\n \n const records = await this.engine.find(request.object, options);\n // Spec: FindDataResponseSchema — only `records` is returned.\n // OData `value` adaptation (if needed) is handled in the HTTP dispatch layer.\n return {\n object: request.object,\n records,\n total: records.length,\n hasMore: false\n };\n }\n\n async getData(request: { object: string, id: string, expand?: string | string[], select?: string | string[], context?: any }) {\n const queryOptions: any = {\n where: { id: request.id }\n };\n if (request.context !== undefined) {\n queryOptions.context = request.context;\n }\n\n // Support fields for single-record retrieval\n if (request.select) {\n queryOptions.fields = typeof request.select === 'string'\n ? request.select.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.select;\n }\n\n // Support expand for single-record retrieval\n if (request.expand) {\n const expandNames = typeof request.expand === 'string'\n ? request.expand.split(',').map((s: string) => s.trim()).filter(Boolean)\n : request.expand;\n queryOptions.expand = {} as Record<string, any>;\n for (const rel of expandNames) {\n queryOptions.expand[rel] = { object: rel };\n }\n }\n\n const result = await this.engine.findOne(request.object, queryOptions);\n if (result) {\n return {\n object: request.object,\n id: request.id,\n record: result\n };\n }\n throw new Error(`Record ${request.id} not found in ${request.object}`);\n }\n\n async createData(request: { object: string, data: any, context?: any }) {\n const result = await this.engine.insert(\n request.object,\n request.data,\n request.context !== undefined ? { context: request.context } as any : undefined,\n );\n return {\n object: request.object,\n id: result.id,\n record: result\n };\n }\n\n async updateData(request: { object: string, id: string, data: any, context?: any }) {\n const opts: any = { where: { id: request.id } };\n if (request.context !== undefined) opts.context = request.context;\n const result = await this.engine.update(request.object, request.data, opts);\n return {\n object: request.object,\n id: request.id,\n record: result\n };\n }\n\n async deleteData(request: { object: string, id: string, context?: any }) {\n const opts: any = { where: { id: request.id } };\n if (request.context !== undefined) opts.context = request.context;\n await this.engine.delete(request.object, opts);\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 let item = this.engine.registry.getItem(request.type, request.name);\n\n // Normalize singular/plural using explicit mapping\n if (!item) {\n const alt = PLURAL_TO_SINGULAR[request.type] ?? SINGULAR_TO_PLURAL[request.type];\n if (alt) item = this.engine.registry.getItem(alt, request.name);\n }\n\n // Fallback to MetadataService (e.g. agents, tools registered in MetadataManager)\n if (!item) {\n try {\n const services = this.getServicesRegistry?.();\n const metadataService = services?.get('metadata');\n if (metadataService && typeof metadataService.get === 'function') {\n item = await metadataService.get(request.type, request.name);\n }\n } catch {\n // MetadataService not available\n }\n }\n\n if (!item) {\n throw new Error(`Metadata item ${request.type}/${request.name} not found`);\n }\n\n // Calculate ETag (simple hash of the stringified metadata)\n const content = JSON.stringify(item);\n const hash = simpleHash(content);\n const etag = { value: hash, weak: false };\n\n // Check If-None-Match header\n if (request.cacheRequest?.ifNoneMatch) {\n const clientEtag = request.cacheRequest.ifNoneMatch.replace(/^\"(.*)\"$/, '$1').replace(/^W\\/\"(.*)\"$/, '$1');\n if (clientEtag === hash) {\n // Return 304 Not Modified\n return {\n notModified: true,\n etag,\n };\n }\n }\n\n // Return full metadata with cache headers\n return {\n data: item,\n etag,\n lastModified: new Date().toISOString(),\n cacheControl: {\n directives: ['public', 'max-age'],\n maxAge: 3600, // 1 hour\n },\n notModified: false,\n };\n } catch (error: any) {\n throw error;\n }\n }\n\n // ==========================================\n // Batch Operations\n // ==========================================\n\n async batchData(request: { object: string, request: BatchUpdateRequest }): Promise<BatchUpdateResponse> {\n const { object, request: batchReq } = request;\n const { operation, records, options } = batchReq;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n switch (operation) {\n case 'create': {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n succeeded++;\n break;\n }\n case 'update': {\n if (!record.id) throw new Error('Record id is required for update');\n const updated = await this.engine.update(object, record.data || {}, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n break;\n }\n case 'upsert': {\n // Try update first, then create if not found\n if (record.id) {\n try {\n const existing = await this.engine.findOne(object, { where: { id: record.id } });\n if (existing) {\n const updated = await this.engine.update(object, record.data || {}, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n } else {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } catch {\n const created = await this.engine.insert(object, { id: record.id, ...(record.data || {}) });\n results.push({ id: created.id, success: true, record: created });\n }\n } else {\n const created = await this.engine.insert(object, record.data || record);\n results.push({ id: created.id, success: true, record: created });\n }\n succeeded++;\n break;\n }\n case 'delete': {\n if (!record.id) throw new Error('Record id is required for delete');\n await this.engine.delete(object, { where: { id: record.id } });\n results.push({ id: record.id, success: true });\n succeeded++;\n break;\n }\n default:\n results.push({ id: record.id, success: false, error: `Unknown operation: ${operation}` });\n failed++;\n }\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (options?.atomic) {\n // Abort remaining operations on first failure in atomic mode\n break;\n }\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation,\n total: records.length,\n succeeded,\n failed,\n results: options?.returnRecords !== false ? results : results.map(r => ({ id: r.id, success: r.success, error: r.error })),\n } as BatchUpdateResponse;\n }\n \n async createManyData(request: { object: string, records: any[] }): Promise<any> {\n const records = await this.engine.insert(request.object, request.records);\n return {\n object: request.object,\n records,\n count: records.length\n };\n }\n \n async updateManyData(request: UpdateManyDataRequest): Promise<BatchUpdateResponse> {\n const { object, records, options } = request;\n const results: Array<{ id?: string; success: boolean; error?: string; record?: any }> = [];\n let succeeded = 0;\n let failed = 0;\n\n for (const record of records) {\n try {\n const updated = await this.engine.update(object, record.data, { where: { id: record.id } });\n results.push({ id: record.id, success: true, record: updated });\n succeeded++;\n } catch (err: any) {\n results.push({ id: record.id, success: false, error: err.message });\n failed++;\n if (!options?.continueOnError) {\n break;\n }\n }\n }\n\n return {\n success: failed === 0,\n operation: 'update',\n total: records.length,\n succeeded,\n failed,\n results,\n } as BatchUpdateResponse;\n }\n\n async analyticsQuery(request: any): Promise<any> {\n // Map AnalyticsQuery (cube-style) to engine aggregation.\n // cube name maps to object name; measures → aggregations; dimensions → groupBy.\n const { query, cube } = request;\n const object = cube;\n\n // Build groupBy from dimensions\n const groupBy = query.dimensions || [];\n\n // Build aggregations from measures\n // Measures can be simple field names like \"count\" or \"field_name.sum\"\n // Or cube-defined measure names. We support: field.function or just function(field).\n const aggregations: Array<{ field: string; method: string; alias: string }> = [];\n if (query.measures) {\n for (const measure of query.measures) {\n // Support formats: \"count\", \"amount.sum\", \"revenue.avg\"\n if (measure === 'count' || measure === 'count_all') {\n aggregations.push({ field: '*', method: 'count', alias: 'count' });\n } else if (measure.includes('.')) {\n const [field, method] = measure.split('.');\n aggregations.push({ field, method, alias: `${field}_${method}` });\n } else {\n // Treat as count of the field\n aggregations.push({ field: measure, method: 'sum', alias: measure });\n }\n }\n }\n\n // Build filter from analytics filters\n let filter: any = undefined;\n if (query.filters && query.filters.length > 0) {\n const conditions: any[] = query.filters.map((f: any) => {\n const op = this.mapAnalyticsOperator(f.operator);\n if (f.values && f.values.length === 1) {\n return { [f.member]: { [op]: f.values[0] } };\n } else if (f.values && f.values.length > 1) {\n return { [f.member]: { $in: f.values } };\n }\n return { [f.member]: { [op]: true } };\n });\n filter = conditions.length === 1 ? conditions[0] : { $and: conditions };\n }\n\n // Execute via engine.aggregate (which delegates to driver.find with groupBy/aggregations)\n const rows = await this.engine.aggregate(object, {\n where: filter,\n groupBy: groupBy.length > 0 ? groupBy : undefined,\n aggregations: aggregations.length > 0\n ? aggregations.map(a => ({ function: a.method as any, field: a.field, alias: a.alias }))\n : [{ function: 'count' as any, alias: 'count' }],\n });\n\n // Build field metadata\n const fields = [\n ...groupBy.map((d: string) => ({ name: d, type: 'string' })),\n ...aggregations.map(a => ({ name: a.alias, type: 'number' })),\n ];\n\n return {\n success: true,\n data: {\n rows,\n fields,\n },\n };\n }\n\n async getAnalyticsMeta(request: any): Promise<any> {\n // Auto-generate cube metadata from registered objects in SchemaRegistry.\n // Each object becomes a cube; number fields → measures; other fields → dimensions.\n const objects = this.engine.registry.listItems('object');\n const cubeFilter = request?.cube;\n\n const cubes: any[] = [];\n for (const obj of objects) {\n const schema = obj as any;\n if (cubeFilter && schema.name !== cubeFilter) continue;\n\n const measures: Record<string, any> = {};\n const dimensions: Record<string, any> = {};\n const fields = schema.fields || {};\n\n // Always add a count measure\n measures['count'] = {\n name: 'count',\n label: 'Count',\n type: 'count',\n sql: '*',\n };\n\n for (const [fieldName, fieldDef] of Object.entries(fields)) {\n const fd = fieldDef as any;\n const fieldType = fd.type || 'text';\n\n if (['number', 'currency', 'percent'].includes(fieldType)) {\n // Numeric fields become both measures and dimensions\n measures[`${fieldName}_sum`] = {\n name: `${fieldName}_sum`,\n label: `${fd.label || fieldName} (Sum)`,\n type: 'sum',\n sql: fieldName,\n };\n measures[`${fieldName}_avg`] = {\n name: `${fieldName}_avg`,\n label: `${fd.label || fieldName} (Avg)`,\n type: 'avg',\n sql: fieldName,\n };\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'number',\n sql: fieldName,\n };\n } else if (['date', 'datetime'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'time',\n sql: fieldName,\n granularities: ['day', 'week', 'month', 'quarter', 'year'],\n };\n } else if (['boolean'].includes(fieldType)) {\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'boolean',\n sql: fieldName,\n };\n } else {\n // text, select, lookup, etc. → dimension\n dimensions[fieldName] = {\n name: fieldName,\n label: fd.label || fieldName,\n type: 'string',\n sql: fieldName,\n };\n }\n }\n\n cubes.push({\n name: schema.name,\n title: schema.label || schema.name,\n description: schema.description,\n sql: schema.name,\n measures,\n dimensions,\n public: true,\n });\n }\n\n return {\n success: true,\n data: { cubes },\n };\n }\n\n private mapAnalyticsOperator(op: string): string {\n const map: Record<string, string> = {\n equals: '$eq',\n notEquals: '$ne',\n contains: '$contains',\n notContains: '$notContains',\n gt: '$gt',\n gte: '$gte',\n lt: '$lt',\n lte: '$lte',\n set: '$ne',\n notSet: '$eq',\n };\n return map[op] || '$eq';\n }\n\n async triggerAutomation(_request: any): Promise<any> {\n throw new Error('triggerAutomation requires plugin-automation service. Install and register a plugin that provides the \"automation\" service.');\n }\n\n async deleteManyData(request: DeleteManyDataRequest): Promise<any> {\n // This expects deleting by IDs.\n return this.engine.delete(request.object, {\n where: { 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\n // Project kernels (projectId set) never persist to sys_metadata\n // locally — runtime metadata is sourced from the artifact and writes\n // belong to the control plane. Update the in-memory registry only.\n if (this.projectId !== undefined) {\n this.engine.registry.registerItem(request.type, request.item, 'name');\n if (request.type === 'object' || request.type === 'objects') {\n try {\n this.engine.registry.registerObject(request.item as any, 'sys_metadata');\n } catch (err: any) {\n console.warn(\n `[Protocol] registerObject failed for ${request.name}: ${err?.message ?? err}`,\n );\n }\n }\n return {\n success: true,\n message: 'Saved to memory registry (project kernel — sys_metadata is control-plane only)',\n };\n }\n\n // 1. Always update the in-memory registry (runtime cache).\n // For `type === 'object'` we additionally register in the\n // dedicated objects map so that downstream calls (e.g.\n // `/meta/objects/:name`, `registry.getObject(name)`, and the\n // engine's schema sync) pick the new definition up without a\n // kernel restart. Without this mirror the HTTP dispatcher\n // returns 404 for freshly-created objects even though the\n // generic item collection has them.\n this.engine.registry.registerItem(request.type, request.item, 'name');\n if (request.type === 'object' || request.type === 'objects') {\n try {\n this.engine.registry.registerObject(request.item as any, 'sys_metadata');\n } catch (err: any) {\n console.warn(\n `[Protocol] this.engine.registry.registerObject failed for ${request.name}: ${err?.message ?? err}`,\n );\n }\n }\n\n // 2. Persist to database via data engine\n try {\n const now = new Date().toISOString();\n // Scope to the current project when configured. A missing\n // projectId means \"platform-global\" (single-kernel deploys,\n // legacy callers) — kept as the default to preserve back-compat.\n const scopedWhere: Record<string, unknown> = {\n type: request.type,\n name: request.name,\n };\n if (this.projectId !== undefined) {\n scopedWhere.project_id = this.projectId;\n }\n const existing = await this.engine.findOne('sys_metadata', {\n where: scopedWhere,\n });\n\n if (existing) {\n await this.engine.update('sys_metadata', {\n metadata: JSON.stringify(request.item),\n updated_at: now,\n version: (existing.version || 0) + 1,\n }, {\n where: { id: existing.id }\n });\n } else {\n // Use crypto.randomUUID() when available (modern browsers and Node ≥ 14.17);\n // fall back to a time+random ID for older or restricted environments.\n const id = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : `meta_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n const row: Record<string, unknown> = {\n id,\n name: request.name,\n type: request.type,\n // `scope` tracks platform vs project authorship. With\n // project_id carries the project id, 'project' is the\n // honest label whenever we know we're inside one.\n scope: this.projectId !== undefined ? 'project' : 'platform',\n metadata: JSON.stringify(request.item),\n state: 'active',\n version: 1,\n created_at: now,\n updated_at: now,\n };\n if (this.projectId !== undefined) {\n row.project_id = this.projectId;\n }\n await this.engine.insert('sys_metadata', row);\n }\n\n return {\n success: true,\n message: 'Saved to database and registry'\n };\n } catch (dbError: any) {\n // DB write failed but in-memory registry was updated — degrade gracefully\n console.warn(`[Protocol] DB persistence failed for ${request.type}/${request.name}: ${dbError.message}`);\n return {\n success: true,\n message: 'Saved to memory registry (DB persistence unavailable)',\n warning: dbError.message\n };\n }\n }\n\n /**\n * Hydrate SchemaRegistry from the database on startup.\n * Loads all active metadata records and registers them in the in-memory registry.\n * Safe to call repeatedly — idempotent (latest DB record wins).\n */\n async loadMetaFromDb(): Promise<{ loaded: number; errors: number }> {\n // Project kernels never read sys_metadata locally — the table only\n // exists on the control plane. Metadata is sourced from the artifact\n // (MetadataPlugin) or routed via ControlPlaneProxyDriver.\n if (this.projectId !== undefined) {\n return { loaded: 0, errors: 0 };\n }\n let loaded = 0;\n let errors = 0;\n try {\n // Always scope by project_id: project kernels hydrate only their own\n // rows; control-plane kernels (no projectId) hydrate only\n // rows with project_id = NULL (global scope). Without this filter the\n // control-plane registry would absorb every project's objects and\n // expose them at the control-plane metadata endpoints.\n const where: Record<string, unknown> = {\n state: 'active',\n project_id: this.projectId ?? null,\n };\n const records = await this.engine.find('sys_metadata', { where });\n for (const record of records) {\n try {\n const data = typeof record.metadata === 'string'\n ? JSON.parse(record.metadata)\n : record.metadata;\n // Normalize DB type to singular (DB may store legacy plural forms)\n const normalizedType = PLURAL_TO_SINGULAR[record.type] ?? record.type;\n if (normalizedType === 'object') {\n this.engine.registry.registerObject(data as any, record.packageId || 'sys_metadata');\n } else {\n this.engine.registry.registerItem(normalizedType, data, 'name' as any);\n }\n loaded++;\n } catch (e) {\n errors++;\n console.warn(`[Protocol] Failed to hydrate ${record.type}/${record.name}: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n } catch (e: any) {\n // \"no such table\" is expected on first run before migrations execute — not an error.\n if (!/no such table/i.test(e.message ?? '')) {\n console.warn(`[Protocol] DB hydration skipped: ${e.message}`);\n }\n }\n return { loaded, errors };\n }\n\n // ==========================================\n // Feed Operations\n // ==========================================\n\n async listFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n return { success: true, data: result };\n }\n\n async createFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.createFeedItem({\n object: request.object,\n recordId: request.recordId,\n type: request.type,\n actor: { type: 'user', id: 'current_user' },\n body: request.body,\n mentions: request.mentions,\n parentId: request.parentId,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async updateFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.updateFeedItem(request.feedId, {\n body: request.body,\n mentions: request.mentions,\n visibility: request.visibility,\n });\n return { success: true, data: item };\n }\n\n async deleteFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n await svc.deleteFeedItem(request.feedId);\n return { success: true, data: { feedId: request.feedId } };\n }\n\n async addReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.addReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async removeReaction(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const reactions = await svc.removeReaction(request.feedId, request.emoji, 'current_user');\n return { success: true, data: { reactions } };\n }\n\n async pinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated pin/unpin — use updateFeedItem to persist pin state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: true, pinnedAt: new Date().toISOString() } };\n }\n\n async unpinFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, pinned: false } };\n }\n\n async starFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n // IFeedService doesn't have dedicated star/unstar — verify item exists then return state\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: true, starredAt: new Date().toISOString() } };\n }\n\n async unstarFeedItem(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const item = await svc.getFeedItem(request.feedId);\n if (!item) throw new Error(`Feed item ${request.feedId} not found`);\n await svc.updateFeedItem(request.feedId, { visibility: item.visibility });\n return { success: true, data: { feedId: request.feedId, starred: false } };\n }\n\n async searchFeed(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Search delegates to listFeed with filter since IFeedService doesn't have a dedicated search\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: request.type,\n limit: request.limit,\n cursor: request.cursor,\n });\n // Filter by query text in body\n const queryLower = (request.query || '').toLowerCase();\n const filtered = result.items.filter((item: any) =>\n item.body?.toLowerCase().includes(queryLower)\n );\n return { success: true, data: { items: filtered, total: filtered.length, hasMore: false } };\n }\n\n async getChangelog(request: any): Promise<any> {\n const svc = this.requireFeedService();\n // Changelog retrieves field_change type feed items\n const result = await svc.listFeed({\n object: request.object,\n recordId: request.recordId,\n filter: 'changes_only',\n limit: request.limit,\n cursor: request.cursor,\n });\n const entries = result.items.map((item: any) => ({\n id: item.id,\n object: item.object,\n recordId: item.recordId,\n actor: item.actor,\n changes: item.changes || [],\n timestamp: item.createdAt,\n source: item.source,\n }));\n return { success: true, data: { entries, total: result.total, nextCursor: result.nextCursor, hasMore: result.hasMore } };\n }\n\n async feedSubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const subscription = await svc.subscribe({\n object: request.object,\n recordId: request.recordId,\n userId: 'current_user',\n events: request.events,\n channels: request.channels,\n });\n return { success: true, data: subscription };\n }\n\n async feedUnsubscribe(request: any): Promise<any> {\n const svc = this.requireFeedService();\n const unsubscribed = await svc.unsubscribe(request.object, request.recordId, 'current_user');\n return { success: true, data: { object: request.object, recordId: request.recordId, unsubscribed } };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { QueryAST, HookContext, ServiceObject } from '@objectstack/spec/data';\nimport {\n EngineQueryOptions,\n DataEngineInsertOptions,\n EngineUpdateOptions,\n EngineDeleteOptions,\n EngineAggregateOptions,\n EngineCountOptions\n} from '@objectstack/spec/data';\nimport { ExecutionContext, ExecutionContextSchema } from '@objectstack/spec/kernel';\nimport { DriverInterface, IDataEngine, Logger, createLogger } from '@objectstack/core';\nimport { CoreServiceName, StorageNameMapping } from '@objectstack/spec/system';\nimport { IRealtimeService, RealtimeEventPayload } from '@objectstack/spec/contracts';\nimport { pluralToSingular } from '@objectstack/spec/shared';\nimport { SchemaRegistry, computeFQN } from './registry.js';\nimport { ExpressionEngine } from '@objectstack/formula';\nimport type { Expression } from '@objectstack/spec';\nimport { bindHooksToEngine } from './hook-binder.js';\n\ninterface FormulaPlanEntry { name: string; expression: Expression; }\n\nfunction planFormulaProjection(\n schema: any,\n requestedFields: string[] | undefined\n): { plan: FormulaPlanEntry[]; projected?: string[] } {\n if (!schema?.fields) return { plan: [] };\n const allFieldNames = Object.keys(schema.fields);\n // When no explicit projection, evaluate every formula field on the schema —\n // matches REST default of \"return everything\". Explicit projection still\n // honours the caller's selection.\n const targets = (Array.isArray(requestedFields) && requestedFields.length > 0)\n ? requestedFields\n : allFieldNames;\n const plan: FormulaPlanEntry[] = [];\n const projected = new Set<string>();\n for (const f of targets) {\n const def = (schema.fields as any)[f];\n if (def?.type === 'formula' && def.expression) {\n // Normalize string-shorthand → Expression envelope (M9 transition).\n const expr: Expression = typeof def.expression === 'string'\n ? { dialect: 'cel', source: def.expression }\n : def.expression;\n plan.push({ name: f, expression: expr });\n // Pre-compile to surface syntax errors at planning stage rather than\n // per-row eval. Dependency discovery (which fields the formula reads)\n // is no longer used — CEL uses dynamic projection via `record.<field>`.\n ExpressionEngine.compile(expr);\n } else if (Array.isArray(requestedFields) && requestedFields.length > 0) {\n projected.add(f);\n }\n }\n if (plan.length === 0) return { plan: [] };\n // For formulas: project all schema fields so CEL `record.<field>` lookups\n // see complete data. Static dependency analysis on AST is M9.7 work.\n if (Array.isArray(requestedFields) && requestedFields.length > 0) {\n if (!projected.has('id')) projected.add('id');\n for (const fname of allFieldNames) projected.add(fname);\n return { plan, projected: Array.from(projected) };\n }\n // Implicit/full projection — leave projected undefined so the driver\n // returns its default columns (typically *).\n return { plan };\n}\n\nfunction applyFormulaPlan(plan: FormulaPlanEntry[], records: any[]): void {\n if (!plan.length) return;\n for (const rec of records) {\n if (rec == null) continue;\n for (const fp of plan) {\n const r = ExpressionEngine.evaluate(fp.expression, { record: rec });\n rec[fp.name] = r.ok ? r.value : null;\n }\n }\n}\n\nexport type HookHandler = (context: HookContext) => Promise<void> | void;\n\n/**\n * Per-object hook entry with priority support\n */\nexport interface HookEntry {\n handler: HookHandler;\n object?: string | string[]; // undefined = global hook\n priority: number;\n packageId?: string;\n /**\n * Original metadata-form `Hook` definition this entry was bound from\n * (when registered via `bindHooksToEngine`). Pure code-paths that call\n * `engine.registerHook` directly leave this undefined.\n */\n meta?: any;\n /** Hook `name` from metadata; used for diagnostics & deduplication. */\n hookName?: string;\n}\n\n/** Function registry entry — see `registerFunction`. */\ninterface FunctionEntry {\n handler: HookHandler;\n packageId?: string;\n}\n\n/**\n * Operation Context for Middleware Chain\n */\nexport interface OperationContext {\n object: string;\n operation: 'find' | 'findOne' | 'insert' | 'update' | 'delete' | 'count' | 'aggregate';\n ast?: QueryAST;\n data?: any;\n options?: any;\n context?: ExecutionContext;\n result?: any;\n}\n\n/**\n * Engine Middleware (Onion model)\n */\nexport type EngineMiddleware = (\n ctx: OperationContext,\n next: () => Promise<void>\n) => Promise<void>;\n\n/**\n * Host Context provided to plugins (Internal ObjectQL Plugin System)\n */\nexport interface ObjectQLHostContext {\n ql: ObjectQL;\n logger: Logger;\n // Extensible map for host-specific globals (like HTTP Router, etc.)\n [key: string]: any;\n}\n\n/**\n * Derive the registry key for a metadata item.\n *\n * Most metadata items expose a top-level `name` (or `id`). The `View`\n * container defined by `@objectstack/spec/ui` is special: it aggregates\n * `list / form / listViews / formViews` for a single object and is\n * keyed implicitly by its target object name (see `data.object`).\n *\n * Per spec, `ViewSchema` does NOT have a top-level `name` field\n * (view.zod.ts), so we resolve it from the inner data source. This\n * matches the server-side metadata API contract (`/api/v1/meta/views/:object`).\n */\nfunction resolveMetadataItemName(key: string, item: any): string | undefined {\n if (!item) return undefined;\n if (item.name) return item.name;\n if (item.id) return item.id;\n if (key === 'views') {\n return (\n item?.list?.data?.object ||\n item?.form?.data?.object ||\n undefined\n );\n }\n return undefined;\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 // Datasource mapping rules (imported from defineStack)\n private datasourceMapping: Array<{\n namespace?: string;\n package?: string;\n objectPattern?: string;\n default?: boolean;\n datasource: string;\n priority?: number;\n }> = [];\n\n // Package manifests registry (for defaultDatasource lookup)\n private manifests = new Map<string, any>();\n\n // Per-object hooks with priority support\n private hooks: Map<string, HookEntry[]> = new Map([\n ['beforeFind', []], ['afterFind', []],\n ['beforeInsert', []], ['afterInsert', []],\n ['beforeUpdate', []], ['afterUpdate', []],\n ['beforeDelete', []], ['afterDelete', []],\n ]);\n\n // Middleware chain (onion model)\n private middlewares: Array<{\n fn: EngineMiddleware;\n object?: string;\n }> = [];\n\n // Action registry: key = \"objectName:actionName\"\n private actions = new Map<string, { handler: (ctx: any) => Promise<any> | any; package?: string }>();\n\n // Function registry: name → handler. Used by `bindHooksToEngine` to\n // resolve string-named hook handlers (the JSON-safe form). Populated by\n // `defineStack({ functions })` via `AppPlugin`, or directly via\n // `engine.registerFunction(...)`.\n private functions = new Map<string, FunctionEntry>();\n\n // Host provided context additions (e.g. Server router)\n private hostContext: Record<string, any> = {};\n\n // Realtime service for event publishing\n private realtimeService?: IRealtimeService;\n\n // Per-engine SchemaRegistry instance.\n //\n // Historically SchemaRegistry was a process-wide singleton of static state,\n // which broke multi-project servers: a project kernel would inherit every\n // object registered by the control plane (e.g. sys_metadata), and\n // getDriver()'s owner lookup would route CRUD to the wrong database. Each\n // engine now owns its registry so kernels are fully isolated.\n private _registry: SchemaRegistry = new SchemaRegistry();\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 // Pick up production hardening switches from env so deployers can\n // enforce strict-body without code changes:\n // OBJECTQL_STRICT_HOOKS=1 → unresolved hooks throw at bind time\n // OBJECTQL_WARN_LEGACY_HANDLER=1 → log a deprecation per legacy bind\n if (process?.env?.OBJECTQL_STRICT_HOOKS === '1') {\n (this as any)._strictHookBinding = true;\n }\n if (process?.env?.OBJECTQL_WARN_LEGACY_HANDLER === '1') {\n (this as any)._warnLegacyHandler = true;\n }\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 * Returns the per-engine instance, NOT the class. Each ObjectQL engine\n * owns its registry so multi-project kernels remain isolated.\n */\n get registry(): SchemaRegistry {\n return this._registry;\n }\n\n /**\n * Load and Register a Plugin\n */\n async use(manifestPart: any, runtimePart?: any) {\n this.logger.debug('Loading plugin', { \n hasManifest: !!manifestPart, \n hasRuntime: !!runtimePart \n });\n\n // 1. Validate / Register Manifest\n if (manifestPart) {\n this.registerApp(manifestPart);\n }\n\n // 2. Execute Runtime\n if (runtimePart) {\n const pluginDef = (runtimePart as any).default || runtimePart;\n if (pluginDef.onEnable) {\n this.logger.debug('Executing plugin runtime onEnable');\n \n const context: ObjectQLHostContext = {\n ql: this,\n logger: this.logger,\n // Expose the driver registry helper explicitly if needed\n drivers: {\n register: (driver: DriverInterface) => this.registerDriver(driver)\n },\n ...this.hostContext\n };\n \n await pluginDef.onEnable(context);\n this.logger.debug('Plugin runtime onEnable completed');\n }\n }\n }\n\n /**\n * Register a hook\n * @param event The event name (e.g. 'beforeFind', 'afterInsert')\n * @param handler The handler function\n * @param options Optional: target object(s) and priority\n */\n registerHook(event: string, handler: HookHandler, options?: {\n object?: string | string[];\n priority?: number;\n packageId?: string;\n /** Original metadata Hook definition (set by `bindHooksToEngine`). */\n meta?: any;\n /** Stable name from metadata (set by `bindHooksToEngine`). */\n hookName?: string;\n }) {\n if (!this.hooks.has(event)) {\n this.hooks.set(event, []);\n }\n const entries = this.hooks.get(event)!;\n entries.push({\n handler,\n object: options?.object,\n priority: options?.priority ?? 100,\n packageId: options?.packageId,\n meta: options?.meta,\n hookName: options?.hookName,\n });\n // Sort by priority (lower runs first)\n entries.sort((a, b) => a.priority - b.priority);\n this.logger.debug('Registered hook', { event, object: options?.object, priority: options?.priority ?? 100, totalHandlers: entries.length });\n }\n\n /**\n * Remove all hooks registered under a given `packageId`. Used by\n * `bindHooksToEngine` to make re-binding (hot reload, app reinstall)\n * idempotent, and by app uninstall flows.\n */\n unregisterHooksByPackage(packageId: string): number {\n if (!packageId) return 0;\n let removed = 0;\n for (const [event, entries] of this.hooks.entries()) {\n const before = entries.length;\n const kept = entries.filter((e) => e.packageId !== packageId);\n if (kept.length !== before) {\n this.hooks.set(event, kept);\n removed += before - kept.length;\n }\n }\n if (removed > 0) {\n this.logger.debug('Unregistered hooks by package', { packageId, removed });\n }\n return removed;\n }\n\n /**\n * Register a named function handler that can later be referenced by\n * string from a `Hook.handler` field. This is the JSON-safe form of\n * handler binding — declarative metadata persisted to disk or shipped\n * over the wire only carries the name.\n */\n registerFunction(name: string, handler: HookHandler, packageId?: string): void {\n if (!name || typeof handler !== 'function') return;\n this.functions.set(name, { handler, packageId });\n this.logger.debug('Registered function', { name, packageId });\n }\n\n /** Look up a registered function by name. */\n resolveFunction(name: string): HookHandler | undefined {\n return this.functions.get(name)?.handler;\n }\n\n /** Remove all functions registered under a given `packageId`. */\n unregisterFunctionsByPackage(packageId: string): number {\n if (!packageId) return 0;\n let removed = 0;\n for (const [name, entry] of this.functions.entries()) {\n if (entry.packageId === packageId) {\n this.functions.delete(name);\n removed += 1;\n }\n }\n if (removed > 0) {\n this.logger.debug('Unregistered functions by package', { packageId, removed });\n }\n return removed;\n }\n\n /**\n * Bind a list of declarative `Hook` metadata definitions to this engine.\n *\n * Convenience proxy to the canonical `bindHooksToEngine` so callers do\n * not need a separate import. Use `import { bindHooksToEngine } from\n * '@objectstack/objectql'` directly when you want the result object.\n */\n bindHooks(hooks: any[] | undefined, opts?: {\n packageId?: string;\n functions?: Record<string, HookHandler>;\n bodyRunner?: any;\n strict?: boolean;\n warnLegacyHandler?: boolean;\n metrics?: any;\n }): void {\n const merged = { ...(opts ?? {}), logger: this.logger } as any;\n if (!merged.bodyRunner && (this as any)._defaultBodyRunner) {\n merged.bodyRunner = (this as any)._defaultBodyRunner;\n }\n if (merged.strict === undefined && (this as any)._strictHookBinding) {\n merged.strict = true;\n }\n if (merged.warnLegacyHandler === undefined && (this as any)._warnLegacyHandler) {\n merged.warnLegacyHandler = true;\n }\n if (!merged.metrics && (this as any)._hookMetricsRecorder) {\n merged.metrics = (this as any)._hookMetricsRecorder;\n }\n bindHooksToEngine(this, hooks, merged);\n }\n\n /**\n * Install a default body-runner used when `bindHooks` is called without\n * an explicit one. The runtime layer sets this once on each per-project\n * engine so every binding path (template seed, metadata sync, AppPlugin)\n * can execute hook `body.source` consistently.\n */\n setDefaultBodyRunner(runner: any): void {\n (this as any)._defaultBodyRunner = runner;\n }\n\n /**\n * Toggle strict hook-binding mode for this engine. When enabled, every\n * subsequent `bindHooks` call rejects on the first unresolved hook\n * instead of silently warning. Production runtimes should enable this.\n */\n setStrictHookBinding(strict: boolean): void {\n (this as any)._strictHookBinding = strict;\n }\n\n /** Toggle deprecation warnings for hooks still using legacy `handler` ref. */\n setWarnLegacyHandler(warn: boolean): void {\n (this as any)._warnLegacyHandler = warn;\n }\n\n /**\n * Install a metrics recorder used by every subsequent `bindHooks` call.\n * The recorder's methods are invoked per-execution to count outcomes\n * (success / error / timeout / capability_rejected), skips, and retries.\n * Defaults to no-op so the engine pays zero cost when nobody is observing.\n */\n setHookMetricsRecorder(recorder: any): void {\n (this as any)._hookMetricsRecorder = recorder;\n }\n\n /** Read the engine's installed metrics recorder, if any. */\n getHookMetricsRecorder(): any {\n return (this as any)._hookMetricsRecorder;\n }\n\n public async triggerHooks(event: string, context: HookContext) {\n const entries = this.hooks.get(event) || [];\n \n if (entries.length === 0) {\n this.logger.debug('No hooks registered for event', { event });\n return;\n }\n\n this.logger.debug('Triggering hooks', { event, count: entries.length });\n \n for (const entry of entries) {\n // Per-object matching\n if (entry.object) {\n const targets = Array.isArray(entry.object) ? entry.object : [entry.object];\n if (!targets.includes('*') && !targets.includes(context.object)) {\n continue; // Skip non-matching hooks\n }\n }\n await entry.handler(context);\n }\n }\n\n // ========================================\n // Action System\n // ========================================\n\n /**\n * Register a named action on an object.\n * Actions are custom business logic callable via `repo.execute(actionName, params)`.\n *\n * @param objectName Target object\n * @param actionName Unique action name within the object\n * @param handler Handler function\n * @param packageName Optional package owner (for cleanup)\n */\n registerAction(objectName: string, actionName: string, handler: (ctx: any) => Promise<any> | any, packageName?: string): void {\n const key = `${objectName}:${actionName}`;\n this.actions.set(key, { handler, package: packageName });\n this.logger.debug('Registered action', { objectName, actionName, package: packageName });\n }\n\n /**\n * Execute a named action on an object.\n */\n async executeAction(objectName: string, actionName: string, ctx: any): Promise<any> {\n const entry = this.actions.get(`${objectName}:${actionName}`);\n if (!entry) {\n throw new Error(`Action '${actionName}' on object '${objectName}' not found`);\n }\n return entry.handler(ctx);\n }\n\n /**\n * Remove all actions registered by a specific package.\n */\n removeActionsByPackage(packageName: string): void {\n for (const [key, entry] of this.actions.entries()) {\n if (entry.package === packageName) {\n this.actions.delete(key);\n }\n }\n }\n\n /**\n * Register a middleware function\n * Middlewares execute in onion model around every data operation.\n * @param fn The middleware function\n * @param options Optional: target object filter\n */\n registerMiddleware(fn: EngineMiddleware, options?: { object?: string }): void {\n this.middlewares.push({ fn, object: options?.object });\n this.logger.debug('Registered middleware', { object: options?.object, total: this.middlewares.length });\n }\n\n /**\n * Execute an operation through the middleware chain\n */\n private async executeWithMiddleware(ctx: OperationContext, executor: () => Promise<any>): Promise<any> {\n const applicable = this.middlewares.filter(m =>\n !m.object || m.object === '*' || m.object === ctx.object\n );\n\n let index = 0;\n const next = async (): Promise<void> => {\n if (index < applicable.length) {\n const mw = applicable[index++];\n await mw.fn(ctx, next);\n } else {\n ctx.result = await executor();\n }\n };\n\n await next();\n return ctx.result;\n }\n\n /**\n * Build a HookContext.session from ExecutionContext\n */\n private buildSession(execCtx?: ExecutionContext): HookContext['session'] {\n if (!execCtx) return undefined;\n return {\n userId: execCtx.userId,\n tenantId: execCtx.tenantId,\n roles: execCtx.roles,\n accessToken: execCtx.accessToken,\n };\n }\n\n /**\n * Build a HookContext.api: a ScopedContext that hooks can use to\n * read/write other objects within the same execution context.\n * Falls back to a system-elevated empty context when no execCtx\n * is supplied (e.g. system-triggered hooks).\n */\n private buildHookApi(execCtx?: ExecutionContext): ScopedContext {\n const safeCtx: ExecutionContext = execCtx ?? ({ isSystem: true } as any);\n return new ScopedContext(safeCtx, this as unknown as IDataEngine);\n }\n\n /**\n * Apply field defaults to an incoming insert payload. Defaults that are\n * Expression envelopes (e.g. `{ dialect: 'cel', source: 'today()' }`,\n * `{ dialect: 'cel', source: 'os.user.id' }`) are evaluated via\n * `ExpressionEngine` against the calling user/org/now snapshot. Static\n * defaults are applied verbatim. Records that already supplied a value for a\n * field are left untouched.\n *\n * Implements ROADMAP §M9.9b — `defaultValue` accepts Expression so authors\n * can replace \"write a hook to default to today/current-user\" with a\n * declarative `defaultValue: cel\\`today()\\``.\n */\n private applyFieldDefaults(\n object: string,\n record: Record<string, unknown>,\n execCtx?: ExecutionContext,\n nowSnapshot?: Date,\n ): Record<string, unknown> {\n const schema = this.getSchema(object);\n const fieldsRaw = (schema as any)?.fields;\n if (!fieldsRaw || typeof fieldsRaw !== 'object') return record;\n // `fields` may be a Record<string, Field> (canonical) or an array (legacy).\n const fieldEntries: Array<{ name: string; defaultValue?: unknown }> = Array.isArray(fieldsRaw)\n ? fieldsRaw\n : Object.entries(fieldsRaw).map(([name, def]) => ({ name, ...(def as object) }));\n const out = { ...record };\n const now = nowSnapshot ?? new Date();\n for (const f of fieldEntries) {\n if (out[f.name] !== undefined) continue;\n if (f.defaultValue == null) continue;\n const dv = f.defaultValue;\n if (typeof dv === 'object' && dv !== null && (dv as any).dialect && typeof (dv as any).source === 'string') {\n const result = ExpressionEngine.evaluate(dv as any, {\n now,\n user: execCtx?.userId ? { id: String(execCtx.userId), role: execCtx?.roles?.[0] } : undefined,\n org: execCtx?.tenantId ? { id: String(execCtx.tenantId) } : undefined,\n record: out,\n extra: { object },\n });\n if (result.ok) {\n out[f.name] = result.value as unknown;\n } else {\n this.logger.warn('Failed to evaluate default expression', {\n object, field: f.name, error: result.error,\n });\n }\n } else {\n out[f.name] = dv;\n }\n }\n return out;\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 console.warn(`[ObjectQL:registerApp] id=${id} flows=${Array.isArray(manifest.flows) ? manifest.flows.length : typeof manifest.flows} keys=${Object.keys(manifest).join(',')}`);\n\n // Store manifest for defaultDatasource lookup\n if (id) {\n this.manifests.set(id, manifest);\n }\n\n // 1. Register the Package (manifest + lifecycle state)\n this._registry.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 = this._registry.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 = this._registry.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 this._registry.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 // Resolve short objectName references in navigation to FQN so the\n // Console UI can match them against the object registry.\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 const resolved = namespace ? this.resolveNavObjectNames(app, namespace) : app;\n this._registry.registerApp(resolved, 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 const resolved = namespace ? this.resolveNavObjectNames(manifest, namespace) : manifest;\n this._registry.registerApp(resolved, id);\n this.logger.debug('Registered manifest-as-app', { app: manifest.name, from: id });\n }\n\n // 5. Register all other metadata types generically\n const metadataArrayKeys = [\n // UI Protocol\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'themes',\n // Automation Protocol\n 'flows', 'workflows', 'approvals', 'webhooks',\n // Security Protocol\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n // AI Protocol\n 'agents', 'ragPipelines',\n // API Protocol\n 'apis',\n // Data Extensions\n 'hooks', 'mappings', 'analyticsCubes',\n // Integration Protocol\n 'connectors',\n ];\n for (const key of metadataArrayKeys) {\n const items = (manifest as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n this.logger.debug(`Registering ${key} from manifest`, { id, count: items.length });\n for (const item of items) {\n const itemName = resolveMetadataItemName(key, item);\n if (itemName) {\n const toRegister = item.name === itemName ? item : { ...item, name: itemName };\n this._registry.registerItem(pluralToSingular(key), toRegister, 'name' as any, id);\n } else {\n this.logger.warn(`Skipping ${pluralToSingular(key)} without a derivable name`, { 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 this._registry.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 this._registry.registerKind(kind);\n this.logger.debug('Registered Kind', { kind: kind.name || kind.type, from: id });\n }\n }\n\n // 7. Recursively register nested plugins\n if (Array.isArray(manifest.plugins) && manifest.plugins.length > 0) {\n this.logger.debug('Processing nested plugins', { id, count: manifest.plugins.length });\n for (const plugin of manifest.plugins) {\n if (plugin && typeof plugin === 'object') {\n const pluginName = plugin.name || plugin.id || 'unnamed-plugin';\n this.logger.debug('Registering nested plugin', { pluginName, parentId: id });\n this.registerPlugin(plugin, id, namespace);\n }\n }\n }\n }\n\n /**\n * Deep-clone an app definition, resolving objectName references in navigation\n * items via the registry. Object names are canonical identifiers — no FQN\n * expansion is applied.\n */\n private resolveNavObjectNames(app: any, namespace: string): any {\n if (!app.navigation) return app;\n\n const resolveItems = (items: any[]): any[] =>\n items.map((item: any) => {\n const resolved = { ...item };\n if (resolved.objectName && !resolved.objectName.includes('__')) {\n resolved.objectName = computeFQN(namespace, resolved.objectName);\n }\n if (Array.isArray(resolved.children)) {\n resolved.children = resolveItems(resolved.children);\n }\n return resolved;\n });\n\n return { ...app, navigation: resolveItems(app.navigation) };\n }\n\n /**\n * Register a nested plugin's metadata (objects, actions, views, etc.)\n *\n * Unlike registerApp(), this does NOT call SchemaRegistry.installPackage()\n * because plugins are not formal manifests — they are lightweight config\n * bundles with objects, actions, triggers, and navigation.\n *\n * @param plugin - The plugin config object\n * @param parentId - The parent package ID (for ownership tracking)\n * @param parentNamespace - The parent package's namespace (for FQN resolution)\n */\n private registerPlugin(plugin: any, parentId: string, parentNamespace?: string) {\n const pluginName = plugin.name || plugin.id || 'unnamed';\n const pluginNamespace = plugin.namespace || parentNamespace;\n\n // Use parentId as the owning package for namespace consistency.\n // The parent package already claimed the namespace — nested plugins\n // contribute objects UNDER the parent's ownership.\n const ownerId = parentId;\n\n // Register objects (supports both Array and Map formats)\n if (plugin.objects) {\n try {\n if (Array.isArray(plugin.objects)) {\n this.logger.debug('Registering plugin objects (Array)', { pluginName, count: plugin.objects.length });\n for (const objDef of plugin.objects) {\n const fqn = this._registry.registerObject(objDef, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n } else {\n const entries = Object.entries(plugin.objects);\n this.logger.debug('Registering plugin objects (Map)', { pluginName, count: entries.length });\n for (const [name, objDef] of entries) {\n (objDef as any).name = name;\n const fqn = this._registry.registerObject(objDef as any, ownerId, pluginNamespace, 'own');\n this.logger.debug('Registered Object', { fqn, from: pluginName });\n }\n }\n } catch (err: any) {\n this.logger.warn('Failed to register plugin objects', { pluginName, error: err.message });\n }\n }\n\n // Register plugin as app if it has navigation (for sidebar display)\n if (plugin.name && plugin.navigation) {\n try {\n const resolved = pluginNamespace ? this.resolveNavObjectNames(plugin, pluginNamespace) : plugin;\n this._registry.registerApp(resolved, ownerId);\n this.logger.debug('Registered plugin-as-app', { app: plugin.name, from: pluginName });\n } catch (err: any) {\n this.logger.warn('Failed to register plugin as app', { pluginName, error: err.message });\n }\n }\n\n // Register metadata arrays (actions, views, triggers, etc.)\n const metadataArrayKeys = [\n 'actions', 'views', 'pages', 'dashboards', 'reports', 'themes',\n 'flows', 'workflows', 'approvals', 'webhooks',\n 'roles', 'permissions', 'profiles', 'sharingRules', 'policies',\n 'agents', 'ragPipelines', 'apis',\n 'hooks', 'mappings', 'analyticsCubes', 'connectors',\n ];\n for (const key of metadataArrayKeys) {\n const items = (plugin as any)[key];\n if (Array.isArray(items) && items.length > 0) {\n for (const item of items) {\n const itemName = resolveMetadataItemName(key, item);\n if (itemName) {\n const toRegister = item.name === itemName ? item : { ...item, name: itemName };\n this._registry.registerItem(pluralToSingular(key), toRegister, 'name' as any, ownerId);\n }\n }\n }\n }\n }\n\n /**\n * Register a new storage driver\n */\n registerDriver(driver: DriverInterface, isDefault: boolean = false) {\n if (this.drivers.has(driver.name)) {\n this.logger.warn('Driver already registered, skipping', { driverName: driver.name });\n return;\n }\n\n this.drivers.set(driver.name, driver);\n this.logger.info('Registered driver', {\n driverName: driver.name,\n version: driver.version\n });\n\n if (isDefault || this.drivers.size === 1) {\n this.defaultDriver = driver.name;\n this.logger.info('Set default driver', { driverName: driver.name });\n }\n }\n\n /**\n * Set the realtime service for publishing data change events.\n * Should be called after kernel resolves the realtime service.\n *\n * @param service - An IRealtimeService instance for event publishing\n */\n setRealtimeService(service: IRealtimeService): void {\n this.realtimeService = service;\n this.logger.info('RealtimeService configured for data events');\n }\n\n /**\n * Helper to get object definition\n */\n getSchema(objectName: string): ServiceObject | undefined {\n return this._registry.getObject(objectName);\n }\n\n /**\n * Resolve any object identifier to the physical storage name used by drivers.\n *\n * Accepts the canonical short name (e.g., 'account') or, for explicit\n * cross-package disambiguation, the canonical object name (e.g., 'account'). The result is\n * the physical table name derived via `StorageNameMapping.resolveTableName`.\n */\n private resolveObjectName(name: string): string {\n const schema = this._registry.getObject(name);\n if (schema) {\n return StorageNameMapping.resolveTableName(schema);\n }\n // Return name as-is (canonical name = table name; no FQN prefix to strip)\n return StorageNameMapping.resolveTableName({ name });\n }\n\n /**\n * Helper to get the target driver\n *\n * Resolution priority (first match wins):\n * 1. Object's explicit `datasource` field (if not 'default')\n * 2. DatasourceMapping rules (namespace/package/pattern matching)\n * 3. Package's `defaultDatasource` from manifest\n * 4. Global default driver\n */\n private getDriver(objectName: string): DriverInterface {\n const object = this._registry.getObject(objectName);\n\n // 1. Object's explicit datasource field (highest priority)\n if (object?.datasource && object.datasource !== 'default') {\n if (this.drivers.has(object.datasource)) {\n return this.drivers.get(object.datasource)!;\n }\n throw new Error(`[ObjectQL] Datasource '${object.datasource}' configured for object '${objectName}' is not registered.`);\n }\n\n // 2. Check datasourceMapping rules\n const mappedDatasource = this.resolveDatasourceFromMapping(objectName, object);\n if (mappedDatasource && this.drivers.has(mappedDatasource)) {\n this.logger.debug('Resolved datasource from mapping', {\n object: objectName,\n datasource: mappedDatasource\n });\n return this.drivers.get(mappedDatasource)!;\n }\n\n // 3. Check package's defaultDatasource\n // Use the object's FQN name (from getObject) for ownership lookup\n const fqn = object?.name || objectName;\n const owner = this._registry.getObjectOwner(fqn);\n if (owner?.packageId) {\n const manifest = this.manifests.get(owner.packageId);\n if (manifest?.defaultDatasource && manifest.defaultDatasource !== 'default') {\n if (this.drivers.has(manifest.defaultDatasource)) {\n this.logger.debug('Resolved datasource from package manifest', {\n object: objectName,\n package: owner.packageId,\n datasource: manifest.defaultDatasource\n });\n return this.drivers.get(manifest.defaultDatasource)!;\n }\n }\n }\n\n // 4. Fallback to global default driver\n if (this.defaultDriver && this.drivers.has(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 * Resolve datasource from mapping rules\n *\n * Rules are evaluated in order (or by priority if specified).\n * First matching rule wins.\n */\n private resolveDatasourceFromMapping(\n objectName: string,\n object?: any\n ): string | null {\n if (!this.datasourceMapping || this.datasourceMapping.length === 0) {\n return null;\n }\n\n // Sort rules by priority if any have priority set\n const sortedRules = [...this.datasourceMapping].sort((a, b) => {\n const aPriority = a.priority ?? 1000;\n const bPriority = b.priority ?? 1000;\n return aPriority - bPriority;\n });\n\n for (const rule of sortedRules) {\n // 1. Match by namespace\n if (rule.namespace && object?.namespace === rule.namespace) {\n return rule.datasource;\n }\n\n // 2. Match by package ID\n if (rule.package && object?.packageId === rule.package) {\n return rule.datasource;\n }\n\n // 3. Match by object name pattern (glob-style)\n if (rule.objectPattern && this.matchPattern(objectName, rule.objectPattern)) {\n return rule.datasource;\n }\n\n // 4. Default fallback rule\n if (rule.default) {\n return rule.datasource;\n }\n }\n\n return null;\n }\n\n /**\n * Simple glob pattern matching\n * Supports * (any chars) and ? (single char)\n */\n private matchPattern(objectName: string, pattern: string): boolean {\n const regexPattern = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&') // Escape regex special chars\n .replace(/\\*/g, '.*') // * → .*\n .replace(/\\?/g, '.'); // ? → .\n\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(objectName);\n }\n\n /**\n * Set datasource mapping rules\n * Called by ObjectQLPlugin during bootstrap\n */\n setDatasourceMapping(rules: Array<{\n namespace?: string;\n package?: string;\n objectPattern?: string;\n default?: boolean;\n datasource: string;\n priority?: number;\n }>) {\n this.datasourceMapping = rules;\n this.logger.info('Datasource mapping rules configured', {\n ruleCount: rules.length\n });\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 const failedDrivers: string[] = [];\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 failedDrivers.push(name);\n this.logger.error('Failed to connect driver', e as Error, { driverName: name });\n }\n }\n\n if (failedDrivers.length > 0) {\n this.logger.warn(\n `${failedDrivers.length} of ${this.drivers.size} driver(s) failed initial connect. ` +\n `Operations may recover via lazy reconnection or fail at query time.`,\n { failedDrivers }\n );\n }\n \n this.logger.info('ObjectQL engine initialization complete');\n }\n\n async destroy() {\n this.logger.info('Destroying ObjectQL engine', { driverCount: this.drivers.size });\n \n for (const [name, driver] of this.drivers.entries()) {\n try {\n await driver.disconnect();\n } catch (e) {\n this.logger.error('Error disconnecting driver', e as Error, { driverName: name });\n }\n }\n \n this.logger.info('ObjectQL engine destroyed');\n }\n\n // ============================================\n // Helper: Expand Related Records\n // ============================================\n\n /** Maximum depth for recursive expand to prevent infinite loops */\n private static readonly MAX_EXPAND_DEPTH = 3;\n\n /**\n * Post-process expand: resolve lookup/master_detail fields by batch-loading related records.\n * \n * This is a driver-agnostic implementation that uses secondary queries ($in batches)\n * to load related records, then injects them into the result set.\n * \n * @param objectName - The source object name\n * @param records - The records returned by the driver\n * @param expand - The expand map from QueryAST (field name → nested QueryAST)\n * @param depth - Current recursion depth (0-based)\n * @returns Records with expanded lookup fields (IDs replaced by full objects)\n */\n private async expandRelatedRecords(\n objectName: string,\n records: any[],\n expand: Record<string, QueryAST>,\n depth: number = 0,\n ): Promise<any[]> {\n if (!records || records.length === 0) return records;\n if (depth >= ObjectQL.MAX_EXPAND_DEPTH) return records;\n\n const objectSchema = this._registry.getObject(objectName);\n // If no schema registered, skip expand — return raw data\n if (!objectSchema || !objectSchema.fields) return records;\n\n for (const [fieldName, nestedAST] of Object.entries(expand)) {\n const fieldDef = objectSchema.fields[fieldName];\n\n // Skip if field not found or not a relationship type\n if (!fieldDef || !fieldDef.reference) continue;\n if (fieldDef.type !== 'lookup' && fieldDef.type !== 'master_detail') continue;\n\n const referenceObject = fieldDef.reference;\n\n // Collect all foreign key IDs from records (handle both single and multiple values)\n const allIds: any[] = [];\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n if (Array.isArray(val)) {\n allIds.push(...val.filter((id: any) => id != null));\n } else if (typeof val === 'object') {\n // Already expanded — skip\n continue;\n } else {\n allIds.push(val);\n }\n }\n\n // De-duplicate IDs\n const uniqueIds = [...new Set(allIds)];\n if (uniqueIds.length === 0) continue;\n\n // Batch-load related records using $in query\n try {\n const relatedQuery: QueryAST = {\n object: referenceObject,\n where: { id: { $in: uniqueIds } },\n ...(nestedAST.fields ? { fields: nestedAST.fields } : {}),\n ...(nestedAST.orderBy ? { orderBy: nestedAST.orderBy } : {}),\n };\n\n const driver = this.getDriver(referenceObject);\n const relatedRecords = await driver.find(referenceObject, relatedQuery) ?? [];\n\n // Build a lookup map: id → record\n const recordMap = new Map<string, any>();\n for (const rec of relatedRecords) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n\n // Recursively expand nested relations if present\n if (nestedAST.expand && Object.keys(nestedAST.expand).length > 0) {\n const expandedRelated = await this.expandRelatedRecords(\n referenceObject,\n relatedRecords,\n nestedAST.expand,\n depth + 1,\n );\n // Rebuild map with expanded records\n recordMap.clear();\n for (const rec of expandedRelated) {\n const id = rec.id;\n if (id != null) recordMap.set(String(id), rec);\n }\n }\n\n // Inject expanded records back into the original result set\n for (const record of records) {\n const val = record[fieldName];\n if (val == null) continue;\n\n if (Array.isArray(val)) {\n record[fieldName] = val.map((id: any) => recordMap.get(String(id)) ?? id);\n } else if (typeof val !== 'object') {\n record[fieldName] = recordMap.get(String(val)) ?? val;\n }\n // If val is already an object, leave it as-is\n }\n } catch (e) {\n // Graceful degradation: if expand fails, keep original IDs\n this.logger.warn('Failed to expand relationship field; retaining foreign key IDs', {\n object: objectName,\n field: fieldName,\n reference: referenceObject,\n error: (e as Error).message,\n });\n }\n }\n\n return records;\n }\n\n // ============================================\n // Data Access Methods (IDataEngine Interface)\n // ============================================\n\n async find(object: string, query?: EngineQueryOptions): 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: QueryAST = { object, ...query };\n // Remove context from the AST — it's not a driver concern\n delete (ast as any).context;\n // Normalize OData `top` alias → standard `limit`\n if ((ast as any).top != null && ast.limit == null) {\n ast.limit = (ast as any).top;\n }\n delete (ast as any).top;\n\n // Plan formula projection: rewrite ast.fields to drop virtual formula\n // names and inject their dependencies, so the driver returns the raw\n // fields needed to compute the formulas after fetch.\n const _findSchema = this._registry.getObject(object);\n const _findFormula = planFormulaProjection(_findSchema, ast.fields as string[] | undefined);\n if (_findFormula.projected) ast.fields = _findFormula.projected;\n\n // Drop any requested field that doesn't exist on the schema. Without\n // this, drivers (notably SqlDriver) emit `SELECT unknown_col FROM ...`\n // which the DB rejects (\"no such column\") — and SqlDriver swallows\n // that error and returns `[]`, making a frontend bug (e.g. a generic\n // view requesting `name`/`due_date` on every object) look like \"no\n // records exist\". Silently filtering matches the existing OData\n // tolerance and Salesforce/Postgres behavior of `SELECT *` semantics.\n if (_findSchema?.fields && Array.isArray(ast.fields) && ast.fields.length > 0) {\n const known = new Set(Object.keys(_findSchema.fields));\n // Always allow the primary key + audit columns even if not present in\n // schema.fields. Without this, callers requesting `select=id,name`\n // silently get the `id` projected away, breaking record navigation.\n known.add('id');\n known.add('created_at');\n known.add('updated_at');\n const filtered = (ast.fields as string[]).filter(f => {\n // Keep relationship paths like `owner.name` — the engine will\n // resolve those via populate; only validate top-level segment.\n const head = String(f).split('.')[0];\n return known.has(head);\n });\n // Guard against an empty projection — fall back to `*` so the\n // request still returns rows. An empty SELECT list would either\n // 400 in Postgres or silently project nothing.\n ast.fields = filtered.length > 0 ? filtered : undefined;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'find',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeFind',\n input: { ast: opCtx.ast, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeFind', hookContext);\n\n try {\n let result = await driver.find(object, hookContext.input.ast as QueryAST, hookContext.input.options as any);\n\n // Post-process: evaluate formula virtual fields against the raw rows\n if (Array.isArray(result)) applyFormulaPlan(_findFormula.plan, result);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && Array.isArray(result)) {\n result = await this.expandRelatedRecords(object, result, ast.expand, 0);\n }\n \n hookContext.event = 'afterFind';\n hookContext.result = result;\n await this.triggerHooks('afterFind', hookContext);\n \n return hookContext.result;\n } catch (e) {\n this.logger.error('Find operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result as any[];\n }\n\n async findOne(objectName: string, query?: EngineQueryOptions): Promise<any> {\n objectName = this.resolveObjectName(objectName);\n this.logger.debug('FindOne operation', { objectName });\n const driver = this.getDriver(objectName);\n const ast: QueryAST = { object: objectName, ...query, limit: 1 };\n // Remove context and top alias from the AST\n delete (ast as any).context;\n delete (ast as any).top;\n\n // Plan formula projection (same as find): rewrite ast.fields so the driver\n // returns the raw dependency fields, then evaluate formulas after fetch.\n const _findOneSchema = this._registry.getObject(objectName);\n const _findOneFormula = planFormulaProjection(_findOneSchema, ast.fields as string[] | undefined);\n if (_findOneFormula.projected) ast.fields = _findOneFormula.projected;\n\n // Drop unknown fields — see equivalent block in `find()` for rationale.\n if (_findOneSchema?.fields && Array.isArray(ast.fields) && ast.fields.length > 0) {\n const known = new Set(Object.keys(_findOneSchema.fields));\n // Always allow the primary key + audit columns even if not present\n // in schema.fields (matches `find()` behavior).\n known.add('id');\n known.add('created_at');\n known.add('updated_at');\n const filtered = (ast.fields as string[]).filter(f => known.has(String(f).split('.')[0]));\n ast.fields = filtered.length > 0 ? filtered : undefined;\n }\n\n const opCtx: OperationContext = {\n object: objectName,\n operation: 'findOne',\n ast,\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n let result = await driver.findOne(objectName, opCtx.ast as QueryAST);\n\n // Post-process: evaluate formula virtual fields against the raw row\n if (result != null) applyFormulaPlan(_findOneFormula.plan, [result]);\n\n // Post-process: expand related records if expand is requested\n if (ast.expand && Object.keys(ast.expand).length > 0 && result != null) {\n const expanded = await this.expandRelatedRecords(objectName, [result], ast.expand, 0);\n result = expanded[0];\n }\n\n return result;\n });\n\n return opCtx.result;\n }\n\n async insert(object: string, data: any | any[], options?: DataEngineInsertOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Insert operation starting', { object, isBatch: Array.isArray(data) });\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'insert',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeInsert',\n input: { data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeInsert', hookContext);\n\n try {\n let result;\n const nowSnap = new Date();\n if (Array.isArray(hookContext.input.data)) {\n // Bulk Create — apply defaults per row\n const rows = (hookContext.input.data as any[]).map((row) =>\n this.applyFieldDefaults(object, row as Record<string, unknown>, opCtx.context, nowSnap),\n );\n if (driver.bulkCreate) {\n result = await driver.bulkCreate(object, rows, hookContext.input.options as any);\n } else {\n // Fallback loop\n result = await Promise.all(rows.map((item) => driver.create(object, item, hookContext.input.options as any)));\n }\n } else {\n const row = this.applyFieldDefaults(\n object,\n hookContext.input.data as Record<string, unknown>,\n opCtx.context,\n nowSnap,\n );\n result = await driver.create(object, row, hookContext.input.options as any);\n }\n\n hookContext.event = 'afterInsert';\n hookContext.result = result;\n await this.triggerHooks('afterInsert', hookContext);\n\n // Publish data.record.created event to realtime service\n if (this.realtimeService) {\n try {\n if (Array.isArray(result)) {\n // Bulk insert - publish event for each record\n for (const record of result) {\n const event: RealtimeEventPayload = {\n type: 'data.record.created',\n object,\n payload: {\n recordId: record.id,\n after: record,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n }\n this.logger.debug(`Published ${result.length} data.record.created events`, { object });\n } else {\n const event: RealtimeEventPayload = {\n type: 'data.record.created',\n object,\n payload: {\n recordId: result.id,\n after: result,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.created event', { object, recordId: result.id });\n }\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Insert operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async update(object: string, data: any, options?: EngineUpdateOptions): Promise<any> {\n object = this.resolveObjectName(object);\n this.logger.debug('Update operation starting', { object });\n const driver = this.getDriver(object);\n \n // 1. Extract ID from data or where if it's a single update by ID\n let id = data.id;\n if (!id && options?.where && typeof options.where === 'object' && 'id' in options.where) {\n id = (options.where as Record<string, unknown>).id;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'update',\n data,\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeUpdate',\n input: { id, data: opCtx.data, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeUpdate', hookContext);\n\n try {\n let result;\n if (hookContext.input.id) {\n result = await driver.update(object, hookContext.input.id as string, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else if (options?.multi && driver.updateMany) {\n const ast: QueryAST = { object, where: options.where };\n result = await driver.updateMany(object, ast, hookContext.input.data as Record<string, unknown>, hookContext.input.options as any);\n } else {\n throw new Error('Update requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterUpdate';\n hookContext.result = result;\n await this.triggerHooks('afterUpdate', hookContext);\n\n // Publish data.record.updated event to realtime service\n if (this.realtimeService) {\n try {\n const resultId = (typeof result === 'object' && result && 'id' in result) ? (result as any).id : undefined;\n const recordId = String(hookContext.input.id || resultId || '');\n const event: RealtimeEventPayload = {\n type: 'data.record.updated',\n object,\n payload: {\n recordId,\n changes: hookContext.input.data,\n after: result,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.updated event', { object, recordId });\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Update operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async delete(object: string, options?: EngineDeleteOptions): 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?.where && typeof options.where === 'object' && 'id' in options.where) {\n id = (options.where as Record<string, unknown>).id;\n }\n\n const opCtx: OperationContext = {\n object,\n operation: 'delete',\n options,\n context: options?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const hookContext: HookContext = {\n object,\n event: 'beforeDelete',\n input: { id, options: opCtx.options },\n session: this.buildSession(opCtx.context),\n api: this.buildHookApi(opCtx.context),\n transaction: opCtx.context?.transaction,\n ql: this\n };\n await this.triggerHooks('beforeDelete', hookContext);\n\n try {\n let result;\n if (hookContext.input.id) {\n result = await driver.delete(object, hookContext.input.id as string, hookContext.input.options as any);\n } else if (options?.multi && driver.deleteMany) {\n const ast: QueryAST = { object, where: options.where };\n result = await driver.deleteMany(object, ast, hookContext.input.options as any);\n } else {\n throw new Error('Delete requires an ID or options.multi=true');\n }\n\n hookContext.event = 'afterDelete';\n hookContext.result = result;\n await this.triggerHooks('afterDelete', hookContext);\n\n // Publish data.record.deleted event to realtime service\n if (this.realtimeService) {\n try {\n const resultId = (typeof result === 'object' && result && 'id' in result) ? (result as any).id : undefined;\n const recordId = String(hookContext.input.id || resultId || '');\n const event: RealtimeEventPayload = {\n type: 'data.record.deleted',\n object,\n payload: {\n recordId,\n },\n timestamp: new Date().toISOString(),\n };\n await this.realtimeService.publish(event);\n this.logger.debug('Published data.record.deleted event', { object, recordId });\n } catch (error) {\n this.logger.warn('Failed to publish data event', { object, error });\n }\n }\n\n return hookContext.result;\n } catch (e) {\n this.logger.error('Delete operation failed', e as Error, { object });\n throw e;\n }\n });\n\n return opCtx.result;\n }\n\n async count(object: string, query?: EngineCountOptions): Promise<number> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n\n const opCtx: OperationContext = {\n object,\n operation: 'count',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n if (driver.count) {\n const ast: QueryAST = { object, where: query?.where };\n return driver.count(object, ast);\n }\n // Fallback to find().length\n const res = await this.find(object, { where: query?.where, fields: ['id'] });\n return res.length;\n });\n\n return opCtx.result as number;\n }\n\n async aggregate(object: string, query: EngineAggregateOptions): Promise<any[]> {\n object = this.resolveObjectName(object);\n const driver = this.getDriver(object);\n this.logger.debug(`Aggregate on ${object} using ${driver.name}`, query);\n\n const opCtx: OperationContext = {\n object,\n operation: 'aggregate',\n options: query,\n context: query?.context,\n };\n\n await this.executeWithMiddleware(opCtx, async () => {\n const ast: QueryAST = {\n object,\n where: query.where,\n groupBy: query.groupBy,\n aggregations: query.aggregations,\n };\n\n // Prefer driver.aggregate() when available — driver.find() in many\n // drivers (e.g. driver-sql) does not honor `groupBy` / `aggregations`\n // and would silently return ungrouped raw rows. Fall back to find()\n // for drivers that handle aggregations through their query AST.\n const drv = driver as any;\n if (typeof drv.aggregate === 'function') {\n return drv.aggregate(object, ast);\n }\n return driver.find(object, ast);\n });\n\n return opCtx.result as any[];\n }\n \n async execute(command: any, options?: Record<string, any>): Promise<any> {\n // Driver selection priority:\n // 1. options.object → route via getDriver(objectName)\n // 2. options.datasource → explicit driver name\n // 3. default driver (set via datasourceMapping or defaultDriver)\n // This lets system services (e.g. PackageService, AuditService) issue raw\n // SQL against the control-plane / default DB without having to know the\n // object name behind every CREATE TABLE / SELECT statement.\n let driver: DriverInterface | undefined;\n if (options?.object) {\n driver = this.getDriver(options.object);\n } else if (options?.datasource && this.drivers.has(options.datasource)) {\n driver = this.drivers.get(options.datasource);\n } else if (this.defaultDriver && this.drivers.has(this.defaultDriver)) {\n driver = this.drivers.get(this.defaultDriver);\n } else if (this.drivers.size === 1) {\n // Single registered driver — unambiguously the right one.\n driver = this.drivers.values().next().value;\n }\n\n if (!driver) {\n throw new Error(\n 'Execute requires options.object to select a driver, or a default driver to be configured. ' +\n 'Configure datasourceMapping with `default: true` or pass `{ object }` / `{ datasource }` in options.',\n );\n }\n if (!driver.execute) {\n throw new Error('Selected driver does not implement execute()');\n }\n\n // Support both call shapes:\n // execute('SELECT ...', { args: [...] })\n // execute({ sql: 'SELECT ...', args: [...] })\n let rawCommand: any = command;\n let params: any[] | undefined = options?.args ?? options?.params;\n if (command && typeof command === 'object' && !Array.isArray(command) && 'sql' in command) {\n rawCommand = command.sql;\n if (params === undefined) {\n params = command.args ?? command.params;\n }\n }\n\n return driver.execute(rawCommand, params, options);\n }\n\n // ============================================\n // Compatibility / Convenience API\n // ============================================\n // These methods provide a higher-level API matching the @objectql/core\n // ObjectQL interface, enabling painless migration from the legacy layer.\n\n /**\n * Register a single object definition.\n * \n * Proxies to SchemaRegistry.registerObject() with sensible defaults.\n * Fields without a `name` property are auto-assigned from their key.\n */\n registerObject(\n schema: ServiceObject,\n packageId: string = '__runtime__',\n namespace?: string\n ): string {\n // Auto-assign field names from keys\n if (schema.fields) {\n for (const [key, field] of Object.entries(schema.fields)) {\n if (field && typeof field === 'object' && !('name' in field)) {\n (field as any).name = key;\n }\n }\n }\n return this._registry.registerObject(schema, packageId, namespace);\n }\n\n /**\n * Unregister a single object by name.\n */\n unregisterObject(name: string, packageId?: string): void {\n if (packageId) {\n this._registry.unregisterObjectsByPackage(packageId);\n } else {\n // Remove from generic metadata as fallback\n this._registry.unregisterItem('object', name);\n }\n }\n\n /**\n * Get an object definition by name.\n * Alias for getSchema() — matches @objectql/core API.\n */\n getObject(name: string): ServiceObject | undefined {\n return this.getSchema(name);\n }\n\n /**\n * Get all registered object configs as a name→config map.\n * Matches @objectql/core getConfigs() API.\n */\n getConfigs(): Record<string, ServiceObject> {\n const result: Record<string, ServiceObject> = {};\n const objects = this._registry.getAllObjects();\n for (const obj of objects) {\n if (obj.name) {\n result[obj.name] = obj;\n }\n }\n return result;\n }\n\n /**\n * Get a registered driver by datasource name.\n * \n * Unlike the private getDriver() (which resolves by object name),\n * this method directly looks up a driver by its registered name.\n */\n getDriverByName(name: string): DriverInterface | undefined {\n return this.drivers.get(name);\n }\n\n /**\n * Get the driver responsible for the given object.\n *\n * Resolves datasource binding from the object's schema definition,\n * falling back to the default driver. This is a public version of\n * the internal getDriver() used by CRUD operations.\n *\n * @param objectName - FQN or short name of the registered object.\n * @returns The resolved DriverInterface, or undefined if no driver is available.\n */\n getDriverForObject(objectName: string): DriverInterface | undefined {\n try {\n return this.getDriver(objectName);\n } catch {\n return undefined;\n }\n }\n\n /**\n * Sync all registered object schemas to their respective drivers.\n * Call this after dynamically registering new objects at runtime\n * (e.g. after template seeding) to ensure tables/collections exist\n * before inserting seed data.\n */\n async syncSchemas(): Promise<void> {\n const allObjects = this._registry.getAllObjects();\n for (const obj of allObjects) {\n const driver = this.getDriverForObject(obj.name);\n if (!driver) continue;\n const tableName = StorageNameMapping.resolveTableName(obj);\n if (typeof (driver as any).syncSchemasBatch === 'function' && (driver as any).supports?.batchSchemaSync) {\n // Already handled per-driver below; skip individual call\n }\n if (typeof (driver as any).syncSchema === 'function') {\n try {\n await (driver as any).syncSchema(tableName, obj);\n } catch {\n // best effort — log suppressed to avoid noise on already-synced tables\n }\n }\n }\n }\n\n /**\n * Get a registered driver by datasource name.\n * Alias matching @objectql/core datasource() API.\n *\n * @throws Error if the datasource is not found\n */\n datasource(name: string): DriverInterface {\n const driver = this.drivers.get(name);\n if (!driver) {\n throw new Error(`[ObjectQL] Datasource '${name}' not found`);\n }\n return driver;\n }\n\n /**\n * Register a hook handler.\n * Convenience alias for registerHook() matching @objectql/core on() API.\n * \n * Usage:\n * ql.on('beforeInsert', 'user', async (ctx) => { ... });\n */\n on(\n event: string,\n objectName: string,\n handler: (ctx: HookContext) => Promise<void> | void,\n packageId?: string\n ): void {\n this.registerHook(event, handler, { object: objectName, packageId });\n }\n\n /**\n * Remove all hooks, actions, and objects contributed by a package.\n */\n removePackage(packageId: string): void {\n // Remove hooks\n for (const [key, handlers] of this.hooks.entries()) {\n const filtered = handlers.filter(h => h.packageId !== packageId);\n if (filtered.length !== handlers.length) {\n this.hooks.set(key, filtered);\n }\n }\n // Remove actions\n this.removeActionsByPackage(packageId);\n // Remove objects\n this._registry.unregisterObjectsByPackage(packageId, true);\n }\n\n /**\n * Gracefully shut down the engine, disconnecting all drivers.\n * Alias for destroy() — matches @objectql/core close() API.\n */\n async close(): Promise<void> {\n return this.destroy();\n }\n\n /**\n * Create a scoped execution context bound to this engine.\n * \n * Usage:\n * const ctx = engine.createContext({ userId: '...', tenantId: '...' });\n * const users = ctx.object('user');\n * await users.find({ filter: { status: 'active' } });\n */\n createContext(ctx: Partial<ExecutionContext>): ScopedContext {\n return new ScopedContext(\n ExecutionContextSchema.parse(ctx),\n this\n );\n }\n\n /**\n * Static factory: create a fully configured ObjectQL instance.\n * \n * Matches @objectql/core's `new ObjectQL(config)` pattern but also\n * registers drivers and objects, then calls init().\n * \n * Usage:\n * const ql = await ObjectQL.create({\n * datasources: { default: myDriver },\n * objects: { user: { name: 'user', fields: { ... } } }\n * });\n */\n static async create(config: {\n datasources?: Record<string, DriverInterface>;\n objects?: Record<string, ServiceObject>;\n hooks?: Array<{ event: string; object: string; handler: (ctx: HookContext) => Promise<void> | void }>;\n }): Promise<ObjectQL> {\n const ql = new ObjectQL();\n\n // Register drivers\n if (config.datasources) {\n for (const [name, driver] of Object.entries(config.datasources)) {\n // Set driver name if not already set\n if (!driver.name) {\n (driver as any).name = name;\n }\n ql.registerDriver(driver, name === 'default');\n }\n }\n\n // Register objects\n if (config.objects) {\n for (const [_key, schema] of Object.entries(config.objects)) {\n ql.registerObject(schema);\n }\n }\n\n // Register hooks\n if (config.hooks) {\n for (const hook of config.hooks) {\n ql.on(hook.event, hook.object, hook.handler);\n }\n }\n\n // Initialize (connect drivers)\n await ql.init();\n\n return ql;\n }\n}\n\n/**\n * Repository scoped to a single object, bound to an execution context.\n *\n * Provides both IDataEngine-style methods (find, insert, update, delete)\n * and convenience aliases (create, updateById, deleteById) matching\n * the @objectql/core ObjectRepository API.\n */\nexport class ObjectRepository {\n constructor(\n private objectName: string,\n private context: ExecutionContext,\n private engine: IDataEngine & { executeAction?: (o: string, a: string, c: any) => Promise<any> }\n ) {}\n\n async find(query: any = {}): Promise<any[]> {\n return this.engine.find(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async findOne(query: any = {}): Promise<any> {\n return this.engine.findOne(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n async insert(data: any): Promise<any> {\n return this.engine.insert(this.objectName, data, {\n context: this.context,\n });\n }\n\n /** Alias for insert() — matches @objectql/core convention */\n async create(data: any): Promise<any> {\n return this.insert(data);\n }\n\n async update(data: any, options: any = {}): Promise<any> {\n return this.engine.update(this.objectName, data, {\n ...options,\n context: this.context,\n });\n }\n\n /** Update a single record by ID */\n async updateById(id: string | number, data: any): Promise<any> {\n return this.engine.update(this.objectName, { ...data, id: id }, {\n where: { id: id },\n context: this.context,\n });\n }\n\n async delete(options: any = {}): Promise<any> {\n return this.engine.delete(this.objectName, {\n ...options,\n context: this.context,\n });\n }\n\n /** Delete a single record by ID */\n async deleteById(id: string | number): Promise<any> {\n return this.engine.delete(this.objectName, {\n where: { id: id },\n context: this.context,\n });\n }\n\n async count(query: any = {}): Promise<number> {\n return this.engine.count(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Aggregate query */\n async aggregate(query: any = {}): Promise<any[]> {\n return this.engine.aggregate(this.objectName, {\n ...query,\n context: this.context,\n });\n }\n\n /** Execute a named action registered on this object */\n async execute(actionName: string, params?: any): Promise<any> {\n if (this.engine.executeAction) {\n return this.engine.executeAction(this.objectName, actionName, {\n ...params,\n userId: this.context.userId,\n tenantId: this.context.tenantId,\n roles: this.context.roles,\n });\n }\n throw new Error(`Actions not supported by engine`);\n }\n}\n\n/**\n * Scoped execution context with object() accessor.\n * \n * Provides identity (userId, tenantId/spaceId, roles),\n * repository access via object(), privilege escalation via sudo(),\n * and transactional execution via transaction().\n */\nexport class ScopedContext {\n constructor(\n private executionContext: ExecutionContext,\n private engine: IDataEngine\n ) {}\n\n /** Get a repository scoped to this context */\n object(name: string): ObjectRepository {\n return new ObjectRepository(name, this.executionContext, this.engine as any);\n }\n\n /** Create an elevated (system) context */\n sudo(): ScopedContext {\n return new ScopedContext(\n { ...this.executionContext, isSystem: true },\n this.engine\n );\n }\n\n /**\n * Execute a callback within a database transaction.\n *\n * The callback receives a new ScopedContext whose operations\n * share the same transaction handle. If the callback throws,\n * the transaction is rolled back; otherwise it is committed.\n *\n * Falls back to non-transactional execution if the driver\n * does not support transactions.\n */\n async transaction(callback: (trxCtx: ScopedContext) => Promise<any>): Promise<any> {\n const engine = this.engine as any;\n\n // Find the default driver for transaction support\n const driver = engine.defaultDriver\n ? engine.drivers?.get(engine.defaultDriver)\n : undefined;\n\n if (!driver?.beginTransaction) {\n // No transaction support — execute directly\n return callback(this);\n }\n\n const trx = await driver.beginTransaction();\n const trxCtx = new ScopedContext(\n { ...this.executionContext, transaction: trx },\n this.engine\n );\n\n try {\n const result = await callback(trxCtx);\n if (driver.commit) await driver.commit(trx);\n else if (driver.commitTransaction) await driver.commitTransaction(trx);\n return result;\n } catch (error) {\n if (driver.rollback) await driver.rollback(trx);\n else if (driver.rollbackTransaction) await driver.rollbackTransaction(trx);\n throw error;\n }\n }\n\n get userId() { return this.executionContext.userId; }\n get tenantId() { return this.executionContext.tenantId; }\n /** Alias for tenantId — matches ObjectQLContext.spaceId convention */\n get spaceId() { return this.executionContext.tenantId; }\n get roles() { return this.executionContext.roles; }\n get isSystem() { return this.executionContext.isSystem; }\n\n /** Internal: expose the transaction handle for driver-level access */\n get transactionHandle() { return this.executionContext.transaction; }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Declarative Hook Wrappers\n *\n * Turns a raw `HookHandler` into one that honours the declarative metadata\n * fields defined on `HookSchema` (`condition`, `async`, `retryPolicy`,\n * `timeout`, `onError`). This lives outside the engine's `triggerHooks`\n * loop so the engine stays minimal and the semantics are unit-testable in\n * isolation.\n *\n * The resulting wrapped handler keeps the original `(ctx) => Promise<void>`\n * signature, so `engine.registerHook` does not need to know anything about\n * the metadata-driven behaviours.\n */\nimport type { Hook, HookContext } from '@objectstack/spec/data';\nimport type { Expression } from '@objectstack/spec';\nimport type { HookHandler } from './engine.js';\nimport { ExpressionEngine } from '@objectstack/formula';\nimport { noopHookMetricsRecorder, type HookMetricsRecorder, type HookMetricOutcome } from './hook-metrics.js';\n\nexport interface WrapDeclarativeOptions {\n /** Logger for declarative-layer diagnostics (timeouts, retries, swallowed errors). */\n logger?: {\n debug: (msg: string, meta?: any) => void;\n info: (msg: string, meta?: any) => void;\n warn: (msg: string, meta?: any) => void;\n error: (msg: string, meta?: any) => void;\n };\n /** Optional per-execution metrics sink. Defaults to no-op. */\n metrics?: HookMetricsRecorder;\n}\n\nconst noopLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/**\n * Wrap a hook handler so it honours the declarative fields defined on\n * `HookSchema`. The wrapping order, from outermost to innermost, is:\n *\n * 1. condition → skip when formula evaluates falsy\n * 2. async → fire-and-forget (after* events only)\n * 3. retry → repeat on throw with backoff\n * 4. timeout → abort if handler runs too long\n * 5. onError → swallow when set to 'log'\n *\n * The condition formula is evaluated against the most useful record-shaped\n * payload available on the context (write payloads first, then `previous`,\n * then a flat merge of input). Read events typically have no record yet,\n * so a condition on a `beforeFind` will simply skip when no data is\n * present.\n */\nexport function wrapDeclarativeHook(\n meta: Hook,\n handler: HookHandler,\n opts: WrapDeclarativeOptions = {},\n): HookHandler {\n const logger = opts.logger ?? noopLogger;\n const metrics = opts.metrics ?? noopHookMetricsRecorder;\n const isAfterEvent = meta.events?.some((e) => typeof e === 'string' && e.startsWith('after')) ?? false;\n const hasBody = Boolean((meta as any).body);\n const labelFor = (ctx: HookContext) => ({\n hook: meta.name,\n object: ctx.object ?? (typeof (meta as any).object === 'string' ? (meta as any).object : undefined),\n event: ctx.event,\n body: hasBody,\n });\n\n // Pre-compile condition once so each invocation is cheap.\n let conditionFn: ((record: any) => boolean) | undefined;\n if (meta.condition) {\n // Accept either string shorthand or full Expression envelope.\n const expr: Expression = typeof meta.condition === 'string'\n ? { dialect: 'cel', source: meta.condition }\n : (meta.condition as Expression);\n if (expr.source && expr.source.trim()) {\n const check = ExpressionEngine.compile(expr);\n if (check.ok) {\n conditionFn = (record: any) => {\n const r = ExpressionEngine.evaluate<boolean>(expr, { record: record ?? {} });\n if (!r.ok) {\n logger.warn('[hook] condition evaluation failed; treating as false', {\n hook: meta.name,\n condition: expr.source,\n error: r.error.message,\n });\n return false;\n }\n return Boolean(r.value);\n };\n } else {\n logger.warn('[hook] condition formula failed to compile; condition ignored', {\n hook: meta.name,\n condition: expr.source,\n error: check.error.message,\n });\n }\n }\n }\n\n const retryMax = Math.max(0, Number(meta.retryPolicy?.maxRetries ?? 0));\n const retryBackoffMs = Math.max(0, Number(meta.retryPolicy?.backoffMs ?? 0));\n const timeoutMs = typeof meta.timeout === 'number' && meta.timeout > 0 ? meta.timeout : undefined;\n const onError = meta.onError ?? 'abort';\n // `async` is only meaningful for after* events; ignore on before* (we must\n // wait for the handler to potentially mutate ctx.input).\n const fireAndForget = Boolean(meta.async) && isAfterEvent;\n\n const runWithTimeout = async (ctx: HookContext): Promise<void> => {\n if (!timeoutMs) {\n await handler(ctx);\n return;\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n Promise.resolve().then(() => handler(ctx)),\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(new Error(`Hook '${meta.name}' timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n };\n\n const runWithRetry = async (ctx: HookContext): Promise<void> => {\n let attempt = 0;\n let lastErr: unknown;\n // attempts = 1 + retryMax\n while (attempt <= retryMax) {\n try {\n await runWithTimeout(ctx);\n return;\n } catch (err) {\n lastErr = err;\n attempt += 1;\n if (attempt > retryMax) break;\n if (retryBackoffMs > 0) {\n await new Promise((r) => setTimeout(r, retryBackoffMs * attempt));\n }\n try { metrics.recordRetry(labelFor(ctx), attempt); } catch { /* noop */ }\n logger.warn('[hook] retrying after failure', {\n hook: meta.name,\n attempt,\n maxRetries: retryMax,\n error: (err as any)?.message,\n });\n }\n }\n throw lastErr;\n };\n\n const runWithErrorPolicy = async (ctx: HookContext): Promise<void> => {\n try {\n await runWithRetry(ctx);\n } catch (err) {\n if (onError === 'log') {\n logger.error('[hook] handler failed (onError=log; suppressing)', {\n hook: meta.name,\n object: ctx.object,\n event: ctx.event,\n error: (err as any)?.message,\n });\n return;\n }\n throw err;\n }\n };\n\n return async (ctx: HookContext): Promise<void> => {\n // 1. Condition gate\n if (conditionFn) {\n const record = pickRecordPayload(ctx);\n if (!conditionFn(record)) {\n logger.debug('[hook] skipped by condition', {\n hook: meta.name,\n object: ctx.object,\n event: ctx.event,\n });\n try { metrics.recordSkip(labelFor(ctx), 'condition'); } catch { /* noop */ }\n return;\n }\n }\n\n const restore = installFlatInput(ctx);\n const startedAt = Date.now();\n\n const recordOutcome = (err?: any) => {\n const elapsed = Date.now() - startedAt;\n let outcome: HookMetricOutcome = 'success';\n if (err) {\n const msg = String(err?.message ?? err ?? '');\n if (/timed out after/i.test(msg)) outcome = 'timeout';\n else if (/capability|cap-rejection|capability_rejected/i.test(msg)) outcome = 'capability_rejected';\n else outcome = 'error';\n }\n try { metrics.recordExecution(labelFor(ctx), outcome, elapsed); } catch { /* noop */ }\n };\n\n try {\n // 2. Fire-and-forget for declarative async after* hooks\n if (fireAndForget) {\n try { metrics.recordSkip(labelFor(ctx), 'fire_and_forget'); } catch { /* noop */ }\n // For fire-and-forget we can't keep ctx.input swapped while the\n // engine moves on — copy what we need, restore, and run async.\n void runWithErrorPolicy(ctx)\n .then(() => recordOutcome())\n .catch((err) => {\n recordOutcome(err);\n logger.error('[hook] async handler error (fire-and-forget)', {\n hook: meta.name,\n error: (err as any)?.message,\n });\n });\n return;\n }\n\n try {\n await runWithErrorPolicy(ctx);\n recordOutcome();\n } catch (err) {\n recordOutcome(err);\n throw err;\n }\n } finally {\n restore();\n }\n };\n}\n\n/**\n * Swap `ctx.input` in place for a Proxy that exposes a flat record view\n * over the engine's `{ data, options, id? }` wrapper. Returns a function\n * that restores the original `ctx.input` reference. Reads of\n * `id` / `options` / `ast` / `data` fall through to the wrapper; reads\n * of any other key fall through to `data`. Writes always go to `data`\n * (creating it if missing) so the engine's downstream `input.data`\n * read picks up mutations made by user code as `input.field = value`.\n */\nfunction installFlatInput(ctx: HookContext): () => void {\n const raw: any = ctx.input ?? {};\n const looksWrapped =\n raw && typeof raw === 'object' &&\n ('data' in raw || 'options' in raw || 'id' in raw || 'ast' in raw);\n if (!looksWrapped) return () => {};\n\n const ensureData = (): Record<string, unknown> => {\n if (!raw.data || typeof raw.data !== 'object') {\n raw.data = {};\n }\n return raw.data as Record<string, unknown>;\n };\n\n const proxy = new Proxy(raw, {\n get(target, prop, receiver) {\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n return Reflect.get(target, prop, receiver);\n }\n const data = target.data;\n if (data && typeof data === 'object' && prop in data) {\n return (data as any)[prop];\n }\n return Reflect.get(target, prop, receiver);\n },\n set(target, prop, value) {\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n (target as any)[prop] = value;\n return true;\n }\n ensureData()[prop as string] = value;\n return true;\n },\n has(target, prop) {\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n return prop in target;\n }\n const data = target.data;\n if (data && typeof data === 'object' && prop in data) return true;\n return prop in target;\n },\n ownKeys(target) {\n // Only enumerate the flat record fields. Wrapper keys\n // (id/options/ast/data) remain accessible via dot/bracket notation\n // but are hidden from Object.keys/for-in so user code that does\n // `Object.keys(input).filter(k => input[k] !== previous[k])` only\n // sees actual record fields.\n const dataKeys = target.data && typeof target.data === 'object'\n ? Object.keys(target.data)\n : [];\n return Array.from(new Set(dataKeys));\n },\n getOwnPropertyDescriptor(target, prop) {\n const data = target.data;\n if (data && typeof data === 'object' && prop in data) {\n return { configurable: true, enumerable: true, writable: true, value: (data as any)[prop] };\n }\n // Wrapper keys: still descriptors so `prop in input` works, but\n // marked non-enumerable so they don't appear in Object.keys().\n if (prop === 'id' || prop === 'options' || prop === 'ast' || prop === 'data') {\n const desc = Object.getOwnPropertyDescriptor(target, prop);\n return desc ? { ...desc, enumerable: false } : undefined;\n }\n return Object.getOwnPropertyDescriptor(target, prop);\n },\n });\n\n (ctx as any).input = proxy;\n return () => {\n (ctx as any).input = raw;\n };\n}\n\n/**\n * Choose the record-shaped object the condition formula should evaluate\n * against. Order:\n * 1. ctx.input.data — write operations carry the new record here\n * 2. ctx.previous — update/delete carry pre-image here\n * 3. ctx.input — fall back to flat input bag (read ops, custom shapes)\n */\nfunction pickRecordPayload(ctx: HookContext): any {\n const input: any = ctx.input ?? {};\n if (input && typeof input === 'object' && input.data && typeof input.data === 'object') {\n return input.data;\n }\n if (ctx.previous && typeof ctx.previous === 'object') {\n return ctx.previous;\n }\n return input;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Hook Execution Metrics\n *\n * Lightweight, transport-agnostic recorder interface for per-hook execution\n * counters and latencies. The default implementation is a no-op so the\n * engine pays zero cost when nobody is observing.\n *\n * Wire a real recorder by calling `engine.setHookMetricsRecorder(recorder)`.\n * The runtime / kernel can adapt this to Otel, Prometheus, StatsD, or\n * whatever telemetry pipeline ships with the deployment.\n *\n * Recorded events:\n * - `recordExecution(label, outcome, durationMs)`\n * outcome ∈ 'success' | 'error' | 'timeout' | 'capability_rejected'\n * - `recordSkip(label, reason)`\n * reason ∈ 'condition' | 'fire_and_forget'\n * - `recordRetry(label, attempt)`\n */\n\nexport type HookMetricOutcome =\n | 'success'\n | 'error'\n | 'timeout'\n | 'capability_rejected';\n\nexport type HookSkipReason = 'condition' | 'fire_and_forget';\n\nexport interface HookMetricLabel {\n /** Hook name (stable id from metadata). */\n hook: string;\n /** Object name the hook is bound to. May be undefined for global hooks. */\n object?: string;\n /** Lifecycle event (`beforeInsert`, `afterUpdate`, etc.). */\n event?: string;\n /** True when the handler comes from a metadata `body` (sandboxed JS). */\n body?: boolean;\n}\n\nexport interface HookMetricsRecorder {\n recordExecution(label: HookMetricLabel, outcome: HookMetricOutcome, durationMs: number): void;\n recordSkip(label: HookMetricLabel, reason: HookSkipReason): void;\n recordRetry(label: HookMetricLabel, attempt: number): void;\n}\n\nexport const noopHookMetricsRecorder: HookMetricsRecorder = {\n recordExecution: () => {},\n recordSkip: () => {},\n recordRetry: () => {},\n};\n\n/**\n * In-memory recorder useful for tests, dev-mode dashboards, and as a\n * starting point for adapter implementations. Aggregates counts + a\n * rolling sum of latency per (hook, outcome).\n */\nexport class InMemoryHookMetricsRecorder implements HookMetricsRecorder {\n private executions = new Map<string, { count: number; totalMs: number }>();\n private skips = new Map<string, number>();\n private retries = new Map<string, number>();\n\n recordExecution(label: HookMetricLabel, outcome: HookMetricOutcome, durationMs: number): void {\n const key = `${label.hook}|${outcome}`;\n const cur = this.executions.get(key) ?? { count: 0, totalMs: 0 };\n cur.count += 1;\n cur.totalMs += Math.max(0, durationMs);\n this.executions.set(key, cur);\n }\n\n recordSkip(label: HookMetricLabel, reason: HookSkipReason): void {\n const key = `${label.hook}|${reason}`;\n this.skips.set(key, (this.skips.get(key) ?? 0) + 1);\n }\n\n recordRetry(label: HookMetricLabel, _attempt: number): void {\n this.retries.set(label.hook, (this.retries.get(label.hook) ?? 0) + 1);\n }\n\n snapshot(): {\n executions: Array<{ hook: string; outcome: HookMetricOutcome; count: number; totalMs: number }>;\n skips: Array<{ hook: string; reason: HookSkipReason; count: number }>;\n retries: Array<{ hook: string; count: number }>;\n } {\n return {\n executions: Array.from(this.executions, ([key, v]) => {\n const [hook, outcome] = key.split('|');\n return { hook, outcome: outcome as HookMetricOutcome, count: v.count, totalMs: v.totalMs };\n }),\n skips: Array.from(this.skips, ([key, count]) => {\n const [hook, reason] = key.split('|');\n return { hook, reason: reason as HookSkipReason, count };\n }),\n retries: Array.from(this.retries, ([hook, count]) => ({ hook, count })),\n };\n }\n\n reset(): void {\n this.executions.clear();\n this.skips.clear();\n this.retries.clear();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Hook Binder\n *\n * Single, canonical entry point that turns declarative `Hook` metadata into\n * runtime registrations on the `ObjectQL` engine. Every metadata source —\n * `defineStack({ hooks })` (consumed by `AppPlugin`), the per-project\n * template seeder (`MultiProjectPlugin`), and the metadata service\n * (`ObjectQLPlugin.loadMetadataFromService`) — funnels through here so\n * that:\n *\n * - Inline function handlers and string-named handlers share one resolver.\n * - Declarative fields (`condition`, `async`, `retryPolicy`, `timeout`,\n * `onError`) are honoured uniformly via `wrapDeclarativeHook`.\n * - Hooks can be unregistered as a unit via `packageId`, enabling clean\n * hot-reload and app uninstall.\n *\n * The ObjectQL engine itself stays simple — it knows how to store and\n * trigger handlers, but knows nothing about declarative semantics. All\n * metadata-aware behaviour lives in this binder + the wrapper module.\n */\n\nimport type { Hook } from '@objectstack/spec/data';\nimport type { ObjectQL, HookHandler } from './engine.js';\nimport { wrapDeclarativeHook } from './hook-wrappers.js';\nimport type { HookMetricsRecorder } from './hook-metrics.js';\n\nexport interface BindHooksOptions {\n /** Owning package / app id — used for `unregisterHooksByPackage`. */\n packageId?: string;\n\n /**\n * Optional name → function map for resolving string `handler` references.\n * Typically supplied by `defineStack({ functions })` and merged with any\n * functions previously registered on the engine.\n */\n functions?: Record<string, HookHandler>;\n\n /**\n * Optional factory that converts a metadata-only `Hook.body` (L1 expression\n * or L2 sandboxed JS source) into an executable `HookHandler`. The runtime\n * package wires this up using `QuickJSScriptRunner`; objectql itself stays\n * sandbox-free so it can run in lightweight environments.\n *\n * If `hook.body` is set and this factory is missing, the hook is skipped\n * with a clear error.\n */\n bodyRunner?: (hook: Hook) => HookHandler | undefined;\n\n /**\n * When true, treat unresolved hooks (body present but no runner, or handler\n * string with no implementation) as fatal errors instead of warnings. Used\n * by production runtimes to fail fast on misconfiguration. Defaults false.\n */\n strict?: boolean;\n\n /**\n * When true, emit a deprecation warning for every hook that still relies\n * on a `handler` ref string instead of the metadata-only `body`. Used by\n * the CLI (compile time) and runtime (boot time) to nudge users away from\n * the legacy `.mjs` runtime bundle path. Defaults false.\n */\n warnLegacyHandler?: boolean;\n\n /** Per-hook execution metrics sink. Defaults to no-op. */\n metrics?: HookMetricsRecorder;\n\n /** Logger; defaults to a silent no-op. */\n logger?: {\n debug: (msg: string, meta?: any) => void;\n info: (msg: string, meta?: any) => void;\n warn: (msg: string, meta?: any) => void;\n error: (msg: string, meta?: any) => void;\n };\n}\n\nconst noopLogger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\n/** Counter for stats. */\nexport interface BindHooksResult {\n registered: number;\n skipped: number;\n errors: Array<{ hook: string; reason: string }>;\n}\n\n/**\n * Bind a list of declarative `Hook` definitions to a running ObjectQL engine.\n *\n * Idempotent on `(packageId, hook.name, event, object)`: re-binding the\n * same set after a hot reload first calls `unregisterHooksByPackage`\n * (when `packageId` is provided).\n */\nexport function bindHooksToEngine(\n engine: ObjectQL,\n hooks: Hook[] | undefined,\n opts: BindHooksOptions = {},\n): BindHooksResult {\n const logger = opts.logger ?? noopLogger;\n const result: BindHooksResult = { registered: 0, skipped: 0, errors: [] };\n\n if (!Array.isArray(hooks) || hooks.length === 0) {\n return result;\n }\n\n // Hot-reload friendly: drop anything we previously bound under this\n // packageId so the new set fully replaces the old.\n if (opts.packageId && typeof (engine as any).unregisterHooksByPackage === 'function') {\n try {\n (engine as any).unregisterHooksByPackage(opts.packageId);\n } catch (err: any) {\n logger.warn('[hook-binder] unregister-by-package failed; continuing', {\n packageId: opts.packageId,\n error: err?.message,\n });\n }\n }\n\n // Pre-load any inline functions supplied via `bundle.functions` so\n // string-handler resolution works.\n if (opts.functions && typeof (engine as any).registerFunction === 'function') {\n for (const [name, fn] of Object.entries(opts.functions)) {\n try {\n (engine as any).registerFunction(name, fn, opts.packageId);\n } catch (err: any) {\n logger.warn('[hook-binder] failed to register function', {\n name,\n error: err?.message,\n });\n }\n }\n }\n\n for (const hook of hooks) {\n try {\n const resolved = resolveHandler(engine, hook, opts);\n if (!resolved) {\n result.skipped += 1;\n const reason = (hook as any).body\n ? `hook body present but no bodyRunner supplied to bindHooksToEngine (runtime must wire QuickJSScriptRunner)`\n : typeof hook.handler === 'string'\n ? `unknown function '${hook.handler}'`\n : 'no handler';\n result.errors.push({ hook: hook.name, reason });\n if (opts.strict) {\n throw new Error(`[hook-binder] strict: cannot bind hook '${hook.name}': ${reason}`);\n }\n logger.warn('[hook-binder] skipping hook with unresolved handler', {\n hook: hook.name,\n handler: hook.handler,\n hasBody: Boolean((hook as any).body),\n });\n continue;\n }\n\n if (opts.warnLegacyHandler && !(hook as any).body && typeof hook.handler === 'string') {\n logger.warn('[hook-binder] DEPRECATED: hook uses legacy handler ref without body', {\n hook: hook.name,\n handler: hook.handler,\n hint: 'Move the handler source into Hook.body so the artifact stays metadata-only and the .mjs runtime bundle can be dropped.',\n });\n }\n\n const wrapped = wrapDeclarativeHook(hook, resolved, { logger, metrics: opts.metrics });\n const objects = normalizeObjects(hook.object);\n const events = Array.isArray(hook.events) ? hook.events : [];\n\n for (const event of events) {\n for (const object of objects) {\n engine.registerHook(event, wrapped, {\n object,\n priority: typeof hook.priority === 'number' ? hook.priority : 100,\n packageId: opts.packageId,\n // Reflect metadata so future tooling can introspect / unregister\n // and so we can detect duplicate name collisions.\n // The engine ignores unknown options today; this is forward-only.\n ...({ meta: hook, hookName: hook.name } as any),\n } as any);\n result.registered += 1;\n }\n }\n } catch (err: any) {\n result.errors.push({ hook: hook.name, reason: err?.message ?? String(err) });\n logger.error('[hook-binder] failed to bind hook', {\n hook: hook.name,\n error: err?.message,\n });\n }\n }\n\n if (result.registered > 0) {\n logger.debug('[hook-binder] hooks bound', {\n packageId: opts.packageId,\n registered: result.registered,\n skipped: result.skipped,\n });\n }\n\n return result;\n}\n\nfunction normalizeObjects(target: Hook['object']): string[] {\n if (Array.isArray(target)) return target.length > 0 ? target : ['*'];\n if (typeof target === 'string' && target.length > 0) return [target];\n return ['*'];\n}\n\nfunction resolveHandler(\n engine: ObjectQL,\n hook: Hook,\n opts: BindHooksOptions,\n): HookHandler | undefined {\n // Metadata-only body (L1 expression or L2 sandboxed JS) takes precedence\n // over the legacy `handler` field. This is the cloud-deployable path —\n // the body string ships inside the artifact JSON and runs under a\n // capability-gated sandbox supplied by the runtime.\n const body = (hook as any).body;\n if (body && typeof body === 'object') {\n let runner = opts.bodyRunner;\n if (typeof runner !== 'function') {\n const fallback = (engine as any)?._defaultBodyRunner;\n if (typeof fallback === 'function') runner = fallback;\n }\n if (typeof runner !== 'function') {\n return undefined;\n }\n const fn = runner(hook);\n if (typeof fn === 'function') return fn;\n return undefined;\n }\n\n const h = hook.handler;\n if (typeof h === 'function') return h as HookHandler;\n if (typeof h === 'string' && h.length > 0) {\n // Try the per-bundle map first (hot path during initial bind),\n // then fall back to whatever the engine already knows.\n const fromBundle = opts.functions?.[h];\n if (typeof fromBundle === 'function') return fromBundle;\n if (typeof (engine as any).resolveFunction === 'function') {\n const fn = (engine as any).resolveFunction(h);\n if (typeof fn === 'function') return fn as HookHandler;\n }\n }\n return undefined;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { SchemaRegistry } from './registry.js';\n\n/**\n * MetadataFacade\n *\n * Provides a clean, injectable interface over SchemaRegistry.\n * Registered as the 'metadata' kernel service to eliminate\n * downstream packages needing to manually wrap SchemaRegistry.\n *\n * Implements the async IMetadataService interface.\n * Internally delegates to SchemaRegistry (in-memory) with Promise wrappers.\n *\n * Each facade is bound to a specific SchemaRegistry instance — passed in the\n * constructor — so that multi-kernel servers can give every kernel its own\n * metadata surface without leaking state across tenants.\n */\nexport class MetadataFacade {\n constructor(private registry: SchemaRegistry) {}\n\n /**\n * Register a metadata item\n */\n async register(type: string, name: string, data: any): Promise<void> {\n const definition = typeof data === 'object' && data !== null\n ? { ...data, name: data.name ?? name }\n : data;\n if (type === 'object') {\n this.registry.registerItem(type, definition, 'name' as any);\n } else {\n this.registry.registerItem(type, definition, definition.id ? 'id' as any : 'name' as any);\n }\n }\n\n /**\n * Get a metadata item by type and name\n */\n async get(type: string, name: string): Promise<any> {\n const item = this.registry.getItem(type, name) as any;\n return item?.content ?? item;\n }\n\n /**\n * Get the raw entry (with metadata wrapper)\n */\n getEntry(type: string, name: string): any {\n return this.registry.getItem(type, name);\n }\n\n /**\n * List all items of a type\n */\n async list(type: string): Promise<any[]> {\n const items = this.registry.listItems(type);\n return items.map((item: any) => item?.content ?? item);\n }\n\n /**\n * Unregister a metadata item\n */\n async unregister(type: string, name: string): Promise<void> {\n this.registry.unregisterItem(type, name);\n }\n\n /**\n * Check if a metadata item exists\n */\n async exists(type: string, name: string): Promise<boolean> {\n const item = this.registry.getItem(type, name);\n return item !== undefined && item !== null;\n }\n\n /**\n * List all names of metadata items of a given type\n */\n async listNames(type: string): Promise<string[]> {\n const items = this.registry.listItems(type);\n return items.map((item: any) => item?.name ?? item?.content?.name ?? '').filter(Boolean);\n }\n\n /**\n * Unregister all metadata from a package\n */\n async unregisterPackage(packageName: string): Promise<void> {\n this.registry.unregisterObjectsByPackage(packageName);\n }\n\n /**\n * Convenience: get object definition\n */\n async getObject(name: string): Promise<any> {\n return this.registry.getObject(name);\n }\n\n /**\n * Convenience: list all objects\n */\n async listObjects(): Promise<any[]> {\n return this.registry.getAllObjects();\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectQL } from './engine.js';\nimport { ObjectStackProtocolImplementation } from './protocol.js';\nimport { Plugin, PluginContext } from '@objectstack/core';\nimport { StorageNameMapping } from '@objectstack/spec/system';\n\nexport type { Plugin, PluginContext };\n\n/**\n * Protocol extension for DB-based metadata hydration.\n * `loadMetaFromDb` is implemented by ObjectStackProtocolImplementation but\n * is NOT (yet) part of the canonical ObjectStackProtocol wire-contract in\n * `@objectstack/spec`, since it is a server-side bootstrap concern only.\n */\ninterface ProtocolWithDbRestore {\n loadMetaFromDb(): Promise<{ loaded: number; errors: number }>;\n}\n\n/** Type guard — checks whether the service exposes `loadMetaFromDb`. */\nfunction hasLoadMetaFromDb(service: unknown): service is ProtocolWithDbRestore {\n return (\n typeof service === 'object' &&\n service !== null &&\n typeof (service as Record<string, unknown>)['loadMetaFromDb'] === 'function'\n );\n}\n\n/**\n * Options for ObjectQLPlugin.\n *\n * `projectId` scopes all metadata writes + reads to a specific project.\n * When set, `protocol.saveMetaItem` stamps `project_id = <projectId>` on\n * new sys_metadata rows, and `protocol.loadMetaFromDb` filters by the same\n * column. Leave undefined in single-kernel / self-hosted mode — rows land\n * in the platform-global scope (project_id IS NULL).\n */\nexport interface ObjectQLPluginOptions {\n /** Optional pre-built engine. When absent, one is lazily created in init. */\n ql?: ObjectQL;\n /** Passed to `new ObjectQL(...)` when `ql` is not supplied. */\n hostContext?: Record<string, any>;\n /** Scope sys_metadata reads/writes to this project. */\n projectId?: string;\n}\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 private projectId?: string;\n\n constructor(qlOrOptions?: ObjectQL | ObjectQLPluginOptions, hostContext?: Record<string, any>) {\n // Back-compat: legacy callers passed `(ObjectQL, hostContext)` positionally.\n if (qlOrOptions instanceof ObjectQL) {\n this.ql = qlOrOptions;\n this.hostContext = hostContext;\n return;\n }\n // New signature: options bag.\n const opts = (qlOrOptions as ObjectQLPluginOptions | undefined) ?? {};\n if (opts.ql) {\n this.ql = opts.ql;\n }\n this.hostContext = opts.hostContext ?? hostContext;\n this.projectId = opts.projectId;\n }\n\n init = async (ctx: PluginContext) => {\n if (!this.ql) {\n // Pass kernel logger to engine to avoid creating a separate logger 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 ctx.registerService('data', this.ql); // ObjectQL implements IDataEngine\n\n // Register manifest service for direct app/package registration.\n // Plugins call ctx.getService('manifest').register(manifestData)\n // instead of the legacy ctx.registerService('app.<id>', manifestData) convention.\n const ql = this.ql;\n ctx.registerService('manifest', {\n register: (manifest: any) => {\n ql.registerApp(manifest);\n ctx.logger.debug('Manifest registered via manifest service', {\n id: manifest.id || manifest.name\n });\n }\n });\n\n ctx.logger.info('ObjectQL engine registered', {\n services: ['objectql', 'data', 'manifest'],\n });\n\n // Register Protocol Implementation\n const protocolShim = new ObjectStackProtocolImplementation(\n this.ql,\n () => ctx.getServices ? ctx.getServices() : new Map(),\n undefined,\n this.projectId,\n );\n\n ctx.registerService('protocol', protocolShim);\n ctx.logger.info('Protocol service registered');\n }\n\n start = async (ctx: PluginContext) => {\n ctx.logger.info('ObjectQL engine starting...');\n\n // Sync from external metadata service (e.g. MetadataPlugin) if available\n try {\n const metadataService = ctx.getService('metadata') as any;\n if (metadataService && typeof metadataService.loadMany === 'function' && this.ql) {\n await this.loadMetadataFromService(metadataService, ctx);\n }\n } catch (e: any) {\n ctx.logger.debug('No external metadata service to sync from');\n }\n \n // Discover features from Kernel Services\n if (ctx.getServices && this.ql) {\n const services = ctx.getServices();\n for (const [name, service] of services.entries()) {\n if (name.startsWith('driver.')) {\n // Register Driver\n this.ql.registerDriver(service);\n ctx.logger.debug('Discovered and registered driver service', { serviceName: name });\n }\n if (name.startsWith('app.')) {\n // Legacy fallback: discover app.* services (DEPRECATED)\n ctx.logger.warn(\n `[DEPRECATED] Service \"${name}\" uses legacy app.* convention. ` +\n `Migrate to ctx.getService('manifest').register(data).`\n );\n this.ql.registerApp(service); // service is Manifest\n ctx.logger.debug('Discovered and registered app service (legacy)', { serviceName: name });\n }\n }\n\n // Bridge realtime service from kernel service registry to ObjectQL.\n // RealtimeServicePlugin registers as 'realtime' service during init().\n // This enables ObjectQL to publish data change events.\n try {\n const realtimeService = ctx.getService('realtime');\n if (realtimeService && typeof realtimeService === 'object' && 'publish' in realtimeService) {\n ctx.logger.info('[ObjectQLPlugin] Bridging realtime service to ObjectQL for event publishing');\n this.ql.setRealtimeService(realtimeService as any);\n }\n } catch (e: any) {\n ctx.logger.debug('[ObjectQLPlugin] No realtime service found — data events will not be published', {\n error: e.message,\n });\n }\n }\n\n // Initialize drivers (calls driver.connect() which sets up persistence)\n await this.ql?.init();\n\n // Phase 1: Sync built-in schemas so sys_metadata table exists before reading it.\n await this.syncRegisteredSchemas(ctx);\n\n // Phase 2: Hydrate SchemaRegistry from sys_metadata (loads custom/template objects).\n // Project kernels (projectId set) never persist sys_metadata locally —\n // metadata is sourced from the artifact (MetadataPlugin) or routed to the\n // control plane via ControlPlaneProxyDriver. Skip to avoid querying a table\n // that does not exist on local project DBs.\n if (this.projectId === undefined) {\n await this.restoreMetadataFromDb(ctx);\n } else {\n ctx.logger.info('Project kernel — skipping sys_metadata hydration (metadata sourced from artifact)');\n }\n\n // Phase 3: Sync any new schemas that were just hydrated from the DB\n // (e.g. CRM objects seeded via template — they must have tables before use).\n await this.syncRegisteredSchemas(ctx);\n\n // Bridge all SchemaRegistry objects to metadata service.\n //\n // `SchemaRegistry` is a process-wide singleton, so project kernels in a\n // multi-project server would otherwise inherit every object ever\n // registered by any sibling project. When this plugin was constructed\n // with a `projectId`, the kernel is project-scoped — its\n // metadata comes from the artifact (MetadataPlugin) or the\n // control-plane proxy, not from local sys_metadata. The bridge would\n // only pollute its metadata service with cross-project leakage, so\n // skip it in that case.\n if (this.projectId === undefined) {\n await this.bridgeObjectsToMetadataService(ctx);\n }\n\n // Register built-in audit hooks\n this.registerAuditHooks(ctx);\n\n // Tenant isolation is now handled by `@objectstack/plugin-security`\n // via the `member_default` permission set's RLS rule\n // (`organization_id = current_user.organization_id`, with\n // field-existence guards). The legacy hard-coded `tenant_id` filter\n // middleware was removed because it (a) collided with the\n // SecurityPlugin RLS pipeline and (b) blindly filtered tables that\n // don't have a `tenant_id` column (e.g. `sys_organization`),\n // returning 0 rows instead of all rows.\n\n ctx.logger.info('ObjectQL engine started', {\n driversRegistered: this.ql?.['drivers']?.size || 0,\n objectsRegistered: this.ql?.registry?.getAllObjects?.()?.length || 0\n });\n }\n\n /**\n * Register built-in audit hooks for auto-stamping created_by/updated_by\n * and fetching previousData for update/delete operations. These are\n * declared as canonical `Hook` metadata and bound through the same\n * `bindHooksToEngine` path used by `defineStack({ hooks })`, so the\n * engine's built-ins flow through the same rails as user code\n * (dogfooding the protocol).\n */\n private registerAuditHooks(ctx: PluginContext) {\n if (!this.ql) return;\n\n const stamp = () => new Date().toISOString();\n\n /**\n * Returns true when the resolved object schema declares a field with the\n * given name. Audit fields (`created_by`, `updated_by`, `tenant_id`) are\n * NOT auto-injected by the SQL driver, so we must only stamp values for\n * fields the user has explicitly declared on the object — otherwise the\n * driver will issue an INSERT against a column that does not exist in\n * the physical table (e.g. `table lead has no column named created_by`).\n *\n * `created_at`/`updated_at` are unconditional because driver-sql creates\n * them as built-in columns on every table.\n */\n const hasField = (objectName: string, field: string): boolean => {\n try {\n const schema: any = this.ql?.getSchema?.(objectName);\n if (!schema || typeof schema !== 'object') return false;\n const fields = schema.fields;\n if (!fields || typeof fields !== 'object') return false;\n return Object.prototype.hasOwnProperty.call(fields, field);\n } catch {\n return false;\n }\n };\n\n const applyToRecord = (\n record: Record<string, any>,\n objectName: string,\n session: any,\n isInsert: boolean,\n ) => {\n const now = stamp();\n if (isInsert) {\n record.created_at = record.created_at ?? now;\n }\n record.updated_at = now;\n if (session?.userId) {\n if (isInsert && hasField(objectName, 'created_by')) {\n record.created_by = record.created_by ?? session.userId;\n }\n if (hasField(objectName, 'updated_by')) {\n record.updated_by = session.userId;\n }\n }\n if (isInsert && session?.tenantId && hasField(objectName, 'tenant_id')) {\n record.tenant_id = record.tenant_id ?? session.tenantId;\n }\n };\n\n const stampData = (\n data: unknown,\n objectName: string,\n session: any,\n isInsert: boolean,\n ) => {\n if (Array.isArray(data)) {\n for (const row of data) {\n if (row && typeof row === 'object') {\n applyToRecord(row as Record<string, any>, objectName, session, isInsert);\n }\n }\n } else if (data && typeof data === 'object') {\n applyToRecord(data as Record<string, any>, objectName, session, isInsert);\n }\n };\n\n const builtinHooks: any[] = [\n {\n name: 'sys_stamp_audit_insert',\n object: '*',\n events: ['beforeInsert'],\n priority: 10,\n description: 'Auto-stamp created_by / updated_by / created_at / updated_at / tenant_id on insert (only when the field exists on the object schema)',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.data) {\n stampData(hookCtx.input.data, hookCtx.object, hookCtx.session, true);\n }\n },\n },\n {\n name: 'sys_stamp_audit_update',\n object: '*',\n events: ['beforeUpdate'],\n priority: 10,\n description: 'Auto-stamp updated_by / updated_at on update (only when the field exists on the object schema)',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.data) {\n stampData(hookCtx.input.data, hookCtx.object, hookCtx.session, false);\n }\n },\n },\n {\n name: 'sys_fetch_previous_update',\n object: '*',\n events: ['beforeUpdate'],\n priority: 5,\n description: 'Auto-fetch the previous record for update hooks',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n where: { id: hookCtx.input.id }\n });\n if (existing) hookCtx.previous = existing;\n } catch (_e) {\n // Non-fatal: some objects may not support findOne\n }\n }\n },\n },\n {\n name: 'sys_fetch_previous_delete',\n object: '*',\n events: ['beforeDelete'],\n priority: 5,\n description: 'Auto-fetch the previous record for delete hooks',\n handler: async (hookCtx: any) => {\n if (hookCtx.input?.id && !hookCtx.previous) {\n try {\n const existing = await this.ql!.findOne(hookCtx.object, {\n where: { id: hookCtx.input.id }\n });\n if (existing) hookCtx.previous = existing;\n } catch (_e) {\n // Non-fatal\n }\n }\n },\n },\n ];\n\n if (typeof (this.ql as any).bindHooks === 'function') {\n (this.ql as any).bindHooks(builtinHooks, { packageId: 'sys:audit' });\n } else {\n // Defensive fallback if binder isn't available (older builds).\n for (const h of builtinHooks) {\n for (const event of h.events) {\n this.ql.registerHook(event, h.handler, {\n object: h.object,\n priority: h.priority,\n packageId: 'sys:audit',\n });\n }\n }\n }\n\n ctx.logger.debug('Audit hooks registered via binder (created_by/updated_by, previousData)');\n }\n\n /**\n * Tenant isolation moved to `@objectstack/plugin-security`'s\n * `member_default` permission set RLS\n * (`organization_id = current_user.organization_id`, with\n * field-existence guards). The legacy `registerTenantMiddleware`\n * method was removed because it (a) collided with SecurityPlugin's\n * RLS pipeline and (b) blindly filtered tables that don't have a\n * `tenant_id` column (e.g. `sys_organization`), returning 0 rows\n * instead of all rows.\n */\n\n /**\n * Synchronize all registered object schemas to the database.\n *\n * Groups objects by their responsible driver, then:\n * - If the driver advertises `supports.batchSchemaSync` and implements\n * `syncSchemasBatch()`, submits all schemas in a single call (reducing\n * network round-trips for remote drivers like Turso).\n * - Otherwise falls back to sequential `syncSchema()` per object.\n *\n * This is idempotent — drivers must tolerate repeated calls without\n * duplicating tables or erroring out.\n *\n * Drivers that do not implement `syncSchema` are silently skipped.\n */\n private async syncRegisteredSchemas(ctx: PluginContext) {\n if (!this.ql) return;\n\n const allObjects = this.ql.registry?.getAllObjects?.() ?? [];\n if (allObjects.length === 0) return;\n\n let synced = 0;\n let skipped = 0;\n\n // Group objects by driver for potential batch optimization\n const driverGroups = new Map<any, Array<{ obj: any; tableName: string }>>();\n\n for (const obj of allObjects) {\n const driver = this.ql.getDriverForObject(obj.name);\n if (!driver) {\n ctx.logger.debug('No driver available for object, skipping schema sync', {\n object: obj.name,\n });\n skipped++;\n continue;\n }\n\n if (typeof driver.syncSchema !== 'function') {\n ctx.logger.debug('Driver does not support syncSchema, skipping', {\n object: obj.name,\n driver: driver.name,\n });\n skipped++;\n continue;\n }\n\n const tableName = StorageNameMapping.resolveTableName(obj);\n\n let group = driverGroups.get(driver);\n if (!group) {\n group = [];\n driverGroups.set(driver, group);\n }\n group.push({ obj, tableName });\n }\n\n // Process each driver group\n for (const [driver, entries] of driverGroups) {\n // Batch path: driver supports batch schema sync\n if (\n driver.supports?.batchSchemaSync &&\n typeof driver.syncSchemasBatch === 'function'\n ) {\n const batchPayload = entries.map((e) => ({\n object: e.tableName,\n schema: e.obj,\n }));\n try {\n await driver.syncSchemasBatch(batchPayload);\n synced += entries.length;\n ctx.logger.debug('Batch schema sync succeeded', {\n driver: driver.name,\n count: entries.length,\n });\n } catch (e: unknown) {\n ctx.logger.warn('Batch schema sync failed, falling back to sequential', {\n driver: driver.name,\n error: e instanceof Error ? e.message : String(e),\n });\n // Fallback: sequential sync for this driver's objects\n for (const { obj, tableName } of entries) {\n try {\n await driver.syncSchema(tableName, obj);\n synced++;\n } catch (seqErr: unknown) {\n ctx.logger.warn('Failed to sync schema for object', {\n object: obj.name,\n tableName,\n driver: driver.name,\n error: seqErr instanceof Error ? seqErr.message : String(seqErr),\n });\n }\n }\n }\n } else {\n // Sequential path: no batch support\n for (const { obj, tableName } of entries) {\n try {\n await driver.syncSchema(tableName, obj);\n synced++;\n } catch (e: unknown) {\n ctx.logger.warn('Failed to sync schema for object', {\n object: obj.name,\n tableName,\n driver: driver.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n }\n }\n\n if (synced > 0 || skipped > 0) {\n ctx.logger.info('Schema sync complete', { synced, skipped, total: allObjects.length });\n }\n }\n\n /**\n * Restore persisted metadata from the database (sys_metadata) on startup.\n *\n * Calls `protocol.loadMetaFromDb()` to bulk-load all active metadata\n * records (objects, views, apps, etc.) into the in-memory SchemaRegistry.\n * This closes the persistence loop so that user-created schemas survive\n * kernel cold starts and redeployments.\n *\n * Gracefully degrades when:\n * - The protocol service is unavailable (e.g., in-memory-only mode).\n * - `loadMetaFromDb` is not implemented by the protocol shim.\n * - The underlying driver/table does not exist yet (first-run scenario).\n */\n private async restoreMetadataFromDb(ctx: PluginContext): Promise<void> {\n // Phase 1: Resolve protocol service (separate from DB I/O for clearer diagnostics)\n let protocol: ProtocolWithDbRestore;\n try {\n const service = ctx.getService('protocol');\n if (!service || !hasLoadMetaFromDb(service)) {\n ctx.logger.debug('Protocol service does not support loadMetaFromDb, skipping DB restore');\n return;\n }\n protocol = service;\n } catch (e: unknown) {\n ctx.logger.debug('Protocol service unavailable, skipping DB restore', {\n error: e instanceof Error ? e.message : String(e),\n });\n return;\n }\n\n // Phase 2: DB hydration (loads into SchemaRegistry)\n try {\n const { loaded, errors } = await protocol.loadMetaFromDb();\n\n if (loaded > 0 || errors > 0) {\n ctx.logger.info('Metadata restored from database to SchemaRegistry', { loaded, errors });\n } else {\n ctx.logger.debug('No persisted metadata found in database');\n }\n } catch (e: unknown) {\n // Non-fatal: first-run or in-memory driver may not have sys_metadata yet\n ctx.logger.debug('DB metadata restore failed (non-fatal)', {\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n /**\n * Bridge all SchemaRegistry objects to the metadata service.\n *\n * This ensures objects registered by plugins and loaded from sys_metadata\n * are visible to AI tools and other consumers that query IMetadataService.\n *\n * Runs after both restoreMetadataFromDb() and syncRegisteredSchemas() to\n * catch all objects in the SchemaRegistry regardless of their source.\n */\n private async bridgeObjectsToMetadataService(ctx: PluginContext): Promise<void> {\n try {\n const metadataService = ctx.getService<any>('metadata');\n if (!metadataService || typeof metadataService.register !== 'function') {\n ctx.logger.debug('Metadata service unavailable for bridging, skipping');\n return;\n }\n\n if (!this.ql?.registry) {\n ctx.logger.debug('SchemaRegistry unavailable for bridging, skipping');\n return;\n }\n\n const objects = this.ql.registry.getAllObjects();\n let bridged = 0;\n\n for (const obj of objects) {\n try {\n // Check if object is already in metadata service to avoid duplicates\n const existing = await metadataService.getObject(obj.name);\n if (!existing) {\n // Register object that exists in SchemaRegistry but not in metadata service\n await metadataService.register('object', obj.name, obj);\n bridged++;\n }\n } catch (e: unknown) {\n ctx.logger.debug('Failed to bridge object to metadata service', {\n object: obj.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n if (bridged > 0) {\n ctx.logger.info('Bridged objects from SchemaRegistry to metadata service', {\n count: bridged,\n total: objects.length\n });\n } else {\n ctx.logger.debug('No objects needed bridging (all already in metadata service)');\n }\n } catch (e: unknown) {\n ctx.logger.debug('Failed to bridge objects to metadata service', {\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n /**\n * Load metadata from external metadata service into ObjectQL registry\n * This enables ObjectQL to use file-based or remote metadata\n */\n private async loadMetadataFromService(metadataService: any, ctx: PluginContext) {\n ctx.logger.info('Syncing metadata from external service into ObjectQL registry...');\n \n // Metadata types to sync\n const metadataTypes = ['object', 'view', 'app', 'flow', 'workflow', 'function', 'hook'];\n let totalLoaded = 0;\n \n for (const type of metadataTypes) {\n try {\n // Check if service has loadMany method\n if (typeof metadataService.loadMany === 'function') {\n const items = await metadataService.loadMany(type);\n\n if (items && items.length > 0) {\n // Functions arrive as JSON-safe records ({name, handler})\n // where `handler` is a function reference or compiled code\n // already attached by the metadata pipeline. Register them\n // BEFORE binding hooks so string-named hook handlers can\n // resolve.\n if (type === 'function' && this.ql && typeof (this.ql as any).registerFunction === 'function') {\n for (const item of items) {\n if (item?.name && typeof item.handler === 'function') {\n (this.ql as any).registerFunction(item.name, item.handler, 'metadata-service');\n }\n }\n }\n\n items.forEach((item: any) => {\n // Determine key field (usually 'name' or 'id')\n const keyField = item.id ? 'id' : 'name';\n \n // For objects, use the ownership-aware registration\n if (type === 'object' && this.ql) {\n // Objects are registered differently (ownership model)\n // Skip for now - handled by app registration\n return;\n }\n \n // Register other types in the registry\n if (this.ql?.registry?.registerItem) {\n this.ql.registry.registerItem(type, item, keyField);\n }\n });\n\n // Hooks need to be wired into the execution pipeline,\n // not just stored in the registry. Funnel through the\n // canonical binder so declarative semantics (condition,\n // retry, timeout, async, onError, priority, packageId)\n // are honoured uniformly with the AppPlugin path.\n if (type === 'hook' && this.ql && typeof (this.ql as any).bindHooks === 'function') {\n (this.ql as any).bindHooks(items, {\n packageId: 'metadata-service',\n });\n }\n\n totalLoaded += items.length;\n ctx.logger.info(`Synced ${items.length} ${type}(s) from metadata service`);\n }\n }\n } catch (e: any) {\n // Type might not exist in metadata service - that's ok\n ctx.logger.debug(`No ${type} metadata found or error loading`, { \n error: e.message \n });\n }\n }\n \n if (totalLoaded > 0) {\n ctx.logger.info(`Metadata sync complete: ${totalLoaded} items loaded into ObjectQL registry`);\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { ObjectKernel } from '@objectstack/core';\nimport { ObjectQLPlugin } from './plugin.js';\nimport type { Plugin } from '@objectstack/core';\n\n/**\n * Options for creating an ObjectQL Kernel.\n */\nexport interface ObjectQLKernelOptions {\n /**\n * Additional plugins to register with the kernel.\n */\n plugins?: Plugin[];\n}\n\n/**\n * Convenience factory for creating an ObjectQL-ready kernel.\n *\n * Creates an ObjectKernel pre-configured with the ObjectQLPlugin\n * (data engine, schema registry, protocol implementation) plus any\n * additional plugins provided.\n *\n * @example\n * ```typescript\n * import { createObjectQLKernel } from '@objectstack/objectql';\n *\n * const kernel = createObjectQLKernel({\n * plugins: [myDriverPlugin, myAuthPlugin],\n * });\n * await kernel.bootstrap();\n * ```\n */\nexport async function createObjectQLKernel(options: ObjectQLKernelOptions = {}): Promise<ObjectKernel> {\n const kernel = new ObjectKernel();\n\n // Register the core ObjectQLPlugin first\n await kernel.use(new ObjectQLPlugin());\n\n // Register any additional plugins\n if (options.plugins) {\n for (const plugin of options.plugins) {\n await kernel.use(plugin);\n }\n }\n\n return kernel;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ServiceObject } from '@objectstack/spec/data';\n\n// ── Introspection Types ──────────────────────────────────────────────────────\n\n/**\n * Column metadata from database introspection.\n */\nexport interface IntrospectedColumn {\n /** Column name */\n name: string;\n /** Native database type (e.g., 'varchar', 'integer', 'timestamp') */\n type: string;\n /** Whether the column is nullable */\n nullable: boolean;\n /** Default value if any */\n defaultValue?: unknown;\n /** Whether this is a primary key */\n isPrimary?: boolean;\n /** Whether this column has a unique constraint */\n isUnique?: boolean;\n /** Maximum length for string types */\n maxLength?: number;\n}\n\n/**\n * Foreign key relationship metadata.\n */\nexport interface IntrospectedForeignKey {\n /** Column name in the source table */\n columnName: string;\n /** Referenced table name */\n referencedTable: string;\n /** Referenced column name */\n referencedColumn: string;\n /** Constraint name */\n constraintName?: string;\n}\n\n/**\n * Table metadata from database introspection.\n */\nexport interface IntrospectedTable {\n /** Table name */\n name: string;\n /** List of columns */\n columns: IntrospectedColumn[];\n /** List of foreign key relationships */\n foreignKeys: IntrospectedForeignKey[];\n /** Primary key columns */\n primaryKeys: string[];\n}\n\n/**\n * Complete database schema introspection result.\n */\nexport interface IntrospectedSchema {\n /** Map of table name to table metadata */\n tables: Record<string, IntrospectedTable>;\n}\n\n// ── Utility Functions ────────────────────────────────────────────────────────\n\n/**\n * Convert a snake_case or plain string to Title Case.\n *\n * @example\n * toTitleCase('first_name') // => 'First Name'\n * toTitleCase('project_task') // => 'Project Task'\n */\nexport function toTitleCase(str: string): string {\n return str\n .replace(/_/g, ' ')\n .replace(/\\b\\w/g, (char) => char.toUpperCase());\n}\n\n/**\n * Map a native database column type to an ObjectStack FieldType.\n */\nfunction mapDatabaseTypeToFieldType(\n dbType: string\n): 'text' | 'textarea' | 'number' | 'boolean' | 'datetime' | 'date' | 'time' | 'json' {\n const type = dbType.toLowerCase();\n\n // Text types\n if (type.includes('char') || type.includes('varchar') || type.includes('text')) {\n if (type.includes('text')) return 'textarea';\n return 'text';\n }\n\n // Numeric types\n if (\n type.includes('int') || type === 'integer' || type === 'bigint' || type === 'smallint'\n ) {\n return 'number';\n }\n if (\n type.includes('float') || type.includes('double') || type.includes('decimal') ||\n type.includes('numeric') || type === 'real'\n ) {\n return 'number';\n }\n\n // Boolean\n if (type.includes('bool')) {\n return 'boolean';\n }\n\n // Date / Time types\n if (type.includes('timestamp') || type === 'datetime') {\n return 'datetime';\n }\n if (type === 'date') {\n return 'date';\n }\n if (type === 'time') {\n return 'time';\n }\n\n // JSON types\n if (type === 'json' || type === 'jsonb') {\n return 'json';\n }\n\n // Default to text\n return 'text';\n}\n\n/**\n * Convert an introspected database schema to ObjectStack object definitions.\n *\n * This allows using existing database tables without manually defining metadata.\n *\n * @param introspectedSchema - The schema returned from driver.introspectSchema()\n * @param options - Optional filtering / conversion settings\n * @returns Array of ServiceObject definitions that can be registered with ObjectQL\n *\n * @example\n * ```typescript\n * const schema = await driver.introspectSchema();\n * const objects = convertIntrospectedSchemaToObjects(schema);\n * for (const obj of objects) {\n * engine.registerObject(obj);\n * }\n * ```\n */\nexport function convertIntrospectedSchemaToObjects(\n introspectedSchema: IntrospectedSchema,\n options?: {\n /** Tables to exclude from conversion */\n excludeTables?: string[];\n /** Tables to include (if specified, only these will be converted) */\n includeTables?: string[];\n /** Whether to skip system columns like id, created_at, updated_at (default: true) */\n skipSystemColumns?: boolean;\n }\n): ServiceObject[] {\n const objects: ServiceObject[] = [];\n const excludeTables = options?.excludeTables || [];\n const includeTables = options?.includeTables;\n const skipSystemColumns = options?.skipSystemColumns !== false;\n\n for (const [tableName, table] of Object.entries(introspectedSchema.tables)) {\n if (excludeTables.includes(tableName)) continue;\n if (includeTables && !includeTables.includes(tableName)) continue;\n\n const fields: Record<string, any> = {};\n\n for (const column of table.columns) {\n // Skip system columns if requested\n if (skipSystemColumns && ['id', 'created_at', 'updated_at'].includes(column.name)) {\n continue;\n }\n\n // Check for foreign key → lookup field\n const foreignKey = table.foreignKeys.find((fk) => fk.columnName === column.name);\n\n if (foreignKey) {\n fields[column.name] = {\n name: column.name,\n type: 'lookup' as const,\n reference: foreignKey.referencedTable,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n } else {\n const fieldType = mapDatabaseTypeToFieldType(column.type);\n\n const field: Record<string, any> = {\n name: column.name,\n type: fieldType,\n label: toTitleCase(column.name),\n required: !column.nullable,\n };\n\n if (column.isUnique) {\n field.unique = true;\n }\n if (column.maxLength && (fieldType === 'text' || fieldType === 'textarea')) {\n field.maxLength = column.maxLength;\n }\n if (column.defaultValue != null) {\n field.defaultValue = column.defaultValue;\n }\n\n fields[column.name] = field;\n }\n }\n\n objects.push({\n name: tableName,\n label: toTitleCase(tableName),\n fields,\n } as ServiceObject);\n }\n\n return objects;\n}\n"],"mappings":"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","names":["ExpressionEngine","noopLogger","ExpressionEngine","StorageNameMapping"]}