@objectstack/metadata 4.0.5 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/metadata-manager.ts","../src/serializers/json-serializer.ts","../src/serializers/yaml-serializer.ts","../src/serializers/typescript-serializer.ts","../src/loaders/database-loader.ts","../src/utils/metadata-history-utils.ts","../src/projection/metadata-projector.ts","../src/plugin.ts","../src/node-metadata-manager.ts","../src/loaders/filesystem-loader.ts","../src/loaders/memory-loader.ts","../src/loaders/remote-loader.ts","../src/index.ts","../src/routes/history-routes.ts","../src/utils/history-cleanup.ts","../src/migration/index.ts","../src/migration/executor.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata Manager\n * \n * Main orchestrator for metadata loading, saving, and persistence.\n * Implements the IMetadataService contract from @objectstack/spec.\n * Browser-compatible (Pure).\n */\n\nimport type {\n MetadataManagerConfig,\n MetadataLoadOptions,\n MetadataSaveOptions,\n MetadataSaveResult,\n MetadataWatchEvent,\n MetadataFormat,\n PackagePublishResult,\n MetadataHistoryQueryOptions,\n MetadataHistoryQueryResult,\n MetadataDiffResult,\n} from '@objectstack/spec/system';\nimport type {\n IMetadataService,\n MetadataWatchCallback,\n MetadataWatchHandle,\n MetadataExportOptions,\n MetadataImportOptions,\n MetadataImportResult,\n MetadataTypeInfo,\n IRealtimeService,\n RealtimeEventPayload,\n} from '@objectstack/spec/contracts';\nimport type {\n MetadataQuery,\n MetadataQueryResult,\n MetadataValidationResult,\n MetadataBulkResult,\n MetadataDependency,\n MetadataTypeRegistryEntry,\n} from '@objectstack/spec/kernel';\nimport type { MetadataOverlay } from '@objectstack/spec/kernel';\nimport { createLogger, type Logger } from '@objectstack/core';\nimport { JSONSerializer } from './serializers/json-serializer.js';\nimport { YAMLSerializer } from './serializers/yaml-serializer.js';\nimport { TypeScriptSerializer } from './serializers/typescript-serializer.js';\nimport type { MetadataSerializer } from './serializers/serializer-interface.js';\nimport type { IDataDriver, IDataEngine } from '@objectstack/spec/contracts';\nimport type { MetadataLoader } from './loaders/loader-interface.js';\nimport { DatabaseLoader } from './loaders/database-loader.js';\nimport { generateSimpleDiff, generateDiffSummary } from './utils/metadata-history-utils.js';\n\n/**\n * Watch callback function (legacy)\n */\nexport type WatchCallback = (event: MetadataWatchEvent) => void | Promise<void>;\n\nexport interface MetadataManagerOptions extends MetadataManagerConfig {\n loaders?: MetadataLoader[];\n /** Optional IDataDriver instance. When provided alongside config.datasource, auto-configures DatabaseLoader. */\n driver?: IDataDriver;\n}\n\n/**\n * Main metadata manager class.\n * Implements IMetadataService contract for unified metadata management.\n */\nexport class MetadataManager implements IMetadataService {\n private loaders: Map<string, MetadataLoader> = new Map();\n // Protected so subclasses can access serializers if needed\n protected serializers: Map<MetadataFormat, MetadataSerializer>;\n protected logger: Logger;\n protected watchCallbacks = new Map<string, Set<WatchCallback>>();\n protected config: MetadataManagerOptions;\n\n // In-memory metadata registry: type -> name -> data\n private registry = new Map<string, Map<string, unknown>>();\n\n // Overlay storage: \"type:name:scope\" -> MetadataOverlay\n private overlays = new Map<string, MetadataOverlay>();\n\n // Type registry for metadata type info\n private typeRegistry: MetadataTypeRegistryEntry[] = [];\n\n // Dependency tracking: \"type:name\" -> dependencies\n private dependencies = new Map<string, MetadataDependency[]>();\n\n // Realtime service for event publishing\n private realtimeService?: IRealtimeService;\n\n constructor(config: MetadataManagerOptions) {\n this.config = config;\n this.logger = createLogger({ level: 'info', format: 'pretty' });\n\n // Initialize serializers\n this.serializers = new Map();\n const formats = config.formats || ['typescript', 'json', 'yaml'];\n\n if (formats.includes('json')) {\n this.serializers.set('json', new JSONSerializer());\n }\n if (formats.includes('yaml')) {\n this.serializers.set('yaml', new YAMLSerializer());\n }\n if (formats.includes('typescript')) {\n this.serializers.set('typescript', new TypeScriptSerializer('typescript'));\n }\n if (formats.includes('javascript')) {\n this.serializers.set('javascript', new TypeScriptSerializer('javascript'));\n }\n\n // Initialize Loaders\n if (config.loaders && config.loaders.length > 0) {\n config.loaders.forEach(loader => this.registerLoader(loader));\n }\n\n // Auto-configure DatabaseLoader when datasource + driver are provided\n if (config.datasource && config.driver) {\n this.setDatabaseDriver(config.driver);\n }\n // Note: No default loader in base class. Subclasses (NodeMetadataManager) or caller must provide one.\n }\n\n /**\n * Set the type registry for metadata type discovery.\n */\n setTypeRegistry(entries: MetadataTypeRegistryEntry[]): void {\n this.typeRegistry = entries;\n }\n\n /**\n * Configure and register a DatabaseLoader for database-backed metadata persistence.\n * Can be called at any time to enable database storage (e.g. after kernel resolves the driver).\n *\n * @param driver - An IDataDriver instance for database operations\n * @param organizationId - Organization ID for multi-tenant isolation\n * @param projectId - Project ID (undefined = platform-global)\n */\n setDatabaseDriver(driver: IDataDriver, organizationId?: string, projectId?: string): void {\n if (projectId !== undefined) {\n this.logger.info('Project kernel — skipping DatabaseLoader for sys_metadata (control-plane only)', {\n organizationId,\n projectId,\n });\n return;\n }\n const tableName = this.config.tableName ?? 'sys_metadata';\n const dbLoader = new DatabaseLoader({\n driver,\n tableName,\n organizationId,\n projectId,\n });\n this.registerLoader(dbLoader);\n this.logger.info('DatabaseLoader configured', { datasource: this.config.datasource, tableName });\n }\n\n /**\n * Configure and register a DatabaseLoader backed by an IDataEngine (ObjectQL).\n * The engine handles datasource routing automatically — sys_metadata will\n * be routed to the correct driver via the standard namespace mapping.\n * No manual driver resolution needed.\n *\n * @param engine - An IDataEngine instance (typically the ObjectQL service)\n * @param organizationId - Organization ID for multi-tenant isolation\n * @param projectId - Project ID (undefined = platform-global)\n */\n setDataEngine(engine: IDataEngine, organizationId?: string, projectId?: string): void {\n if (projectId !== undefined) {\n this.logger.info('Project kernel — skipping DatabaseLoader for sys_metadata (control-plane only)', {\n organizationId,\n projectId,\n });\n return;\n }\n const tableName = this.config.tableName ?? 'sys_metadata';\n const dbLoader = new DatabaseLoader({\n engine,\n tableName,\n organizationId,\n projectId,\n });\n this.registerLoader(dbLoader);\n this.logger.info('DatabaseLoader configured via DataEngine', { tableName });\n }\n\n /**\n * Set the realtime service for publishing metadata 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 metadata events');\n }\n\n /**\n * Register a new metadata loader (data source)\n */\n registerLoader(loader: MetadataLoader) {\n this.loaders.set(loader.contract.name, loader);\n this.logger.info(`Registered metadata loader: ${loader.contract.name} (${loader.contract.protocol})`);\n }\n\n // ==========================================\n // IMetadataService — Core CRUD Operations\n // ==========================================\n\n /**\n * Register/save a metadata item by type\n * Stores in-memory registry and persists to database-backed loaders only.\n * FilesystemLoader (protocol 'file:') is read-only for static metadata and\n * should not be written to during runtime registration.\n */\n async register(type: string, name: string, data: unknown): Promise<void> {\n if (!this.registry.has(type)) {\n this.registry.set(type, new Map());\n }\n this.registry.get(type)!.set(name, data);\n\n // Persist only to database-backed loaders that declare write capability.\n // FilesystemLoader is read-only at runtime — writing to it can crash in\n // read-only environments (e.g. serverless, containerized deployments).\n for (const loader of this.loaders.values()) {\n if (loader.save && loader.contract.protocol === 'datasource:' && loader.contract.capabilities.write) {\n await loader.save(type, name, data);\n }\n }\n\n // Publish metadata.{type}.created event to realtime service\n if (this.realtimeService) {\n const event: RealtimeEventPayload = {\n type: `metadata.${type}.created`,\n object: type,\n payload: {\n metadataType: type,\n name,\n definition: data,\n packageId: (data as any)?.packageId,\n },\n timestamp: new Date().toISOString(),\n };\n\n try {\n await this.realtimeService.publish(event);\n this.logger.debug(`Published metadata.${type}.created event`, { name });\n } catch (error) {\n this.logger.warn(`Failed to publish metadata event`, { type, name, error });\n }\n }\n }\n\n /**\n * Get a metadata item by type and name.\n * Checks in-memory registry first, then falls back to loaders.\n */\n async get(type: string, name: string): Promise<unknown | undefined> {\n // Check in-memory registry first\n const typeStore = this.registry.get(type);\n if (typeStore?.has(name)) {\n return typeStore.get(name);\n }\n\n // Fallback to loaders\n const result = await this.load(type, name);\n return result ?? undefined;\n }\n\n /**\n * List all metadata items of a given type\n */\n async list(type: string): Promise<unknown[]> {\n const items = new Map<string, unknown>();\n\n // From in-memory registry\n const typeStore = this.registry.get(type);\n if (typeStore) {\n for (const [name, data] of typeStore) {\n items.set(name, data);\n }\n }\n\n // From loaders (deduplicate)\n for (const loader of this.loaders.values()) {\n try {\n const loaderItems = await loader.loadMany(type);\n for (const item of loaderItems) {\n const itemAny = item as any;\n if (itemAny && typeof itemAny.name === 'string' && !items.has(itemAny.name)) {\n items.set(itemAny.name, item);\n }\n }\n } catch (e) {\n this.logger.warn(`Loader ${loader.contract.name} failed to loadMany ${type}`, { error: e });\n }\n }\n\n return Array.from(items.values());\n }\n\n /**\n * Unregister/remove a metadata item by type and name.\n * Deletes from database-backed loaders only (same rationale as register()).\n */\n async unregister(type: string, name: string): Promise<void> {\n // Remove from in-memory registry\n const typeStore = this.registry.get(type);\n if (typeStore) {\n typeStore.delete(name);\n if (typeStore.size === 0) {\n this.registry.delete(type);\n }\n }\n\n // Delete only from database-backed loaders that declare write capability\n for (const loader of this.loaders.values()) {\n if (loader.contract.protocol !== 'datasource:' || !loader.contract.capabilities.write) continue;\n if (typeof (loader as any).delete === 'function') {\n try {\n await (loader as any).delete(type, name);\n } catch (error) {\n this.logger.warn(`Failed to delete ${type}/${name} from loader ${loader.contract.name}`, { error });\n }\n }\n }\n\n // Publish metadata.{type}.deleted event to realtime service\n if (this.realtimeService) {\n const event: RealtimeEventPayload = {\n type: `metadata.${type}.deleted`,\n object: type,\n payload: {\n metadataType: type,\n name,\n },\n timestamp: new Date().toISOString(),\n };\n\n try {\n await this.realtimeService.publish(event);\n this.logger.debug(`Published metadata.${type}.deleted event`, { name });\n } catch (error) {\n this.logger.warn(`Failed to publish metadata event`, { type, name, error });\n }\n }\n }\n\n /**\n * Check if a metadata item exists\n */\n async exists(type: string, name: string): Promise<boolean> {\n // Check in-memory registry\n if (this.registry.get(type)?.has(name)) {\n return true;\n }\n\n // Check loaders\n for (const loader of this.loaders.values()) {\n if (await loader.exists(type, name)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * List all names of metadata items of a given type\n */\n async listNames(type: string): Promise<string[]> {\n const names = new Set<string>();\n\n // From in-memory registry\n const typeStore = this.registry.get(type);\n if (typeStore) {\n for (const name of typeStore.keys()) {\n names.add(name);\n }\n }\n\n // From loaders\n for (const loader of this.loaders.values()) {\n const result = await loader.list(type);\n result.forEach(item => names.add(item));\n }\n\n return Array.from(names);\n }\n\n /**\n * Convenience: get an object definition by name\n */\n async getObject(name: string): Promise<unknown | undefined> {\n return this.get('object', name);\n }\n\n /**\n * Convenience: list all object definitions\n */\n async listObjects(): Promise<unknown[]> {\n return this.list('object');\n }\n\n // ==========================================\n // Convenience: UI Metadata\n // ==========================================\n\n /**\n * Convenience: get a view definition by name\n */\n async getView(name: string): Promise<unknown | undefined> {\n return this.get('view', name);\n }\n\n /**\n * Convenience: list view definitions, optionally filtered by object\n */\n async listViews(object?: string): Promise<unknown[]> {\n const views = await this.list('view');\n if (object) {\n return views.filter((v: any) => v?.object === object);\n }\n return views;\n }\n\n /**\n * Convenience: get a dashboard definition by name\n */\n async getDashboard(name: string): Promise<unknown | undefined> {\n return this.get('dashboard', name);\n }\n\n /**\n * Convenience: list all dashboard definitions\n */\n async listDashboards(): Promise<unknown[]> {\n return this.list('dashboard');\n }\n\n // ==========================================\n // Package Management\n // ==========================================\n\n /**\n * Unregister all metadata items from a specific package\n */\n async unregisterPackage(packageName: string): Promise<void> {\n // Collect all items to delete (type and name pairs)\n const itemsToDelete: Array<{ type: string; name: string }> = [];\n\n for (const [type, typeStore] of this.registry) {\n for (const [name, data] of typeStore) {\n const meta = data as any;\n if (meta?.packageId === packageName || meta?.package === packageName) {\n itemsToDelete.push({ type, name });\n }\n }\n }\n\n // Delete each item using unregister() to ensure deletion from both registry and loaders\n for (const { type, name } of itemsToDelete) {\n await this.unregister(type, name);\n }\n }\n\n /**\n * Publish an entire package:\n * 1. Validate all draft items\n * 2. Snapshot all items in the package (publishedDefinition = clone(metadata))\n * 3. Increment version\n * 4. Set all items state → active\n */\n async publishPackage(packageId: string, options?: {\n changeNote?: string;\n publishedBy?: string;\n validate?: boolean;\n }): Promise<PackagePublishResult> {\n const now = new Date().toISOString();\n const shouldValidate = options?.validate !== false;\n const publishedBy = options?.publishedBy;\n\n // Collect all items belonging to this package\n const packageItems: Array<{ type: string; name: string; data: any }> = [];\n for (const [type, typeStore] of this.registry) {\n for (const [name, data] of typeStore) {\n const meta = data as any;\n if (meta?.packageId === packageId || meta?.package === packageId) {\n packageItems.push({ type, name, data: meta });\n }\n }\n }\n\n if (packageItems.length === 0) {\n return {\n success: false,\n packageId,\n version: 0,\n publishedAt: now,\n itemsPublished: 0,\n validationErrors: [{ type: '', name: '', message: `No metadata items found for package '${packageId}'` }],\n };\n }\n\n // Validation pass\n if (shouldValidate) {\n const validationErrors: Array<{ type: string; name: string; message: string }> = [];\n\n // Schema validation\n for (const item of packageItems) {\n const result = await this.validate(item.type, item.data);\n if (!result.valid && result.errors) {\n for (const err of result.errors) {\n validationErrors.push({\n type: item.type,\n name: item.name,\n message: err.message,\n });\n }\n }\n }\n\n // Dependency validation: referenced items must be in the same package or already published\n const packageItemKeys = new Set(packageItems.map(i => `${i.type}:${i.name}`));\n for (const item of packageItems) {\n const deps = await this.getDependencies(item.type, item.name);\n for (const dep of deps) {\n const depKey = `${dep.targetType}:${dep.targetName}`;\n // Skip if the dependency is within this package\n if (packageItemKeys.has(depKey)) continue;\n // Check if the dependency exists and has been published\n const depItem = await this.get(dep.targetType, dep.targetName);\n if (!depItem) {\n validationErrors.push({\n type: item.type,\n name: item.name,\n message: `Dependency '${dep.targetType}:${dep.targetName}' not found`,\n });\n } else {\n const depMeta = depItem as any;\n if (depMeta.publishedDefinition === undefined && depMeta.state !== 'active') {\n validationErrors.push({\n type: item.type,\n name: item.name,\n message: `Dependency '${dep.targetType}:${dep.targetName}' is not published`,\n });\n }\n }\n }\n }\n\n if (validationErrors.length > 0) {\n return {\n success: false,\n packageId,\n version: 0,\n publishedAt: now,\n itemsPublished: 0,\n validationErrors,\n };\n }\n }\n\n // Determine the next version by finding the max current version across items\n let maxVersion = 0;\n for (const item of packageItems) {\n const v = typeof item.data.version === 'number' ? item.data.version : 0;\n if (v > maxVersion) maxVersion = v;\n }\n const newVersion = maxVersion + 1;\n\n // Snapshot and update all items\n for (const item of packageItems) {\n const updated = {\n ...item.data,\n publishedDefinition: structuredClone(item.data.metadata ?? item.data),\n publishedAt: now,\n publishedBy: publishedBy ?? item.data.publishedBy,\n version: newVersion,\n state: 'active',\n };\n await this.register(item.type, item.name, updated);\n }\n\n return {\n success: true,\n packageId,\n version: newVersion,\n publishedAt: now,\n itemsPublished: packageItems.length,\n };\n }\n\n /**\n * Revert entire package to last published state.\n * Restores all metadata definitions from their published snapshots.\n */\n async revertPackage(packageId: string): Promise<void> {\n const packageItems: Array<{ type: string; name: string; data: any }> = [];\n for (const [type, typeStore] of this.registry) {\n for (const [name, data] of typeStore) {\n const meta = data as any;\n if (meta?.packageId === packageId || meta?.package === packageId) {\n packageItems.push({ type, name, data: meta });\n }\n }\n }\n\n if (packageItems.length === 0) {\n throw new Error(`No metadata items found for package '${packageId}'`);\n }\n\n // Check that at least one item has a published snapshot\n const hasPublished = packageItems.some(item => item.data.publishedDefinition !== undefined);\n if (!hasPublished) {\n throw new Error(`Package '${packageId}' has never been published`);\n }\n\n for (const item of packageItems) {\n if (item.data.publishedDefinition !== undefined) {\n const reverted = {\n ...item.data,\n metadata: structuredClone(item.data.publishedDefinition),\n state: 'active',\n };\n await this.register(item.type, item.name, reverted);\n }\n }\n }\n\n /**\n * Get the published version of any metadata item (for runtime serving).\n * Returns publishedDefinition if exists, else current definition.\n */\n async getPublished(type: string, name: string): Promise<unknown | undefined> {\n const item = await this.get(type, name);\n if (!item) return undefined;\n\n const meta = item as any;\n if (meta.publishedDefinition !== undefined) {\n return meta.publishedDefinition;\n }\n\n // Fall back to current definition (metadata field or the item itself)\n return meta.metadata ?? item;\n }\n\n // ==========================================\n // Query / Search\n // ==========================================\n\n /**\n * Query metadata items with filtering, sorting, and pagination\n */\n async query(query: MetadataQuery): Promise<MetadataQueryResult> {\n const { types, search, page = 1, pageSize = 50, sortBy = 'name', sortOrder = 'asc' } = query;\n\n // Collect all items\n const allItems: Array<{\n type: string;\n name: string;\n namespace?: string;\n label?: string;\n scope?: 'system' | 'platform' | 'user';\n state?: 'draft' | 'active' | 'archived' | 'deprecated';\n packageId?: string;\n updatedAt?: string;\n }> = [];\n\n // Determine which types to scan\n const targetTypes = types && types.length > 0\n ? types\n : Array.from(this.registry.keys());\n\n for (const type of targetTypes) {\n const items = await this.list(type);\n for (const item of items) {\n const meta = item as any;\n allItems.push({\n type,\n name: meta?.name ?? '',\n namespace: meta?.namespace,\n label: meta?.label,\n scope: meta?.scope,\n state: meta?.state,\n packageId: meta?.packageId,\n updatedAt: meta?.updatedAt,\n });\n }\n }\n\n // Apply search filter\n let filtered = allItems;\n if (search) {\n const searchLower = search.toLowerCase();\n filtered = filtered.filter(item =>\n item.name.toLowerCase().includes(searchLower) ||\n (item.label && item.label.toLowerCase().includes(searchLower))\n );\n }\n\n // Apply scope filter\n if (query.scope) {\n filtered = filtered.filter(item => item.scope === query.scope);\n }\n\n // Apply state filter\n if (query.state) {\n filtered = filtered.filter(item => item.state === query.state);\n }\n\n // Apply namespace filter\n if (query.namespaces && query.namespaces.length > 0) {\n filtered = filtered.filter(item => item.namespace && query.namespaces!.includes(item.namespace));\n }\n\n // Apply packageId filter\n if (query.packageId) {\n filtered = filtered.filter(item => item.packageId === query.packageId);\n }\n\n // Apply tags filter\n if (query.tags && query.tags.length > 0) {\n filtered = filtered.filter(item => {\n const meta = item as any;\n return meta?.tags && query.tags!.some((t: string) => meta.tags.includes(t));\n });\n }\n\n // Sort\n filtered.sort((a, b) => {\n const aVal = (a as any)[sortBy] ?? '';\n const bVal = (b as any)[sortBy] ?? '';\n const cmp = String(aVal).localeCompare(String(bVal));\n return sortOrder === 'desc' ? -cmp : cmp;\n });\n\n // Paginate\n const total = filtered.length;\n const start = (page - 1) * pageSize;\n const paged = filtered.slice(start, start + pageSize);\n\n return {\n items: paged,\n total,\n page,\n pageSize,\n };\n }\n\n // ==========================================\n // Bulk Operations\n // ==========================================\n\n /**\n * Register multiple metadata items in a single batch\n */\n async bulkRegister(\n items: Array<{ type: string; name: string; data: unknown }>,\n options?: { continueOnError?: boolean; validate?: boolean }\n ): Promise<MetadataBulkResult> {\n const { continueOnError = false } = options ?? {};\n let succeeded = 0;\n let failed = 0;\n const errors: Array<{ type: string; name: string; error: string }> = [];\n\n for (const item of items) {\n try {\n await this.register(item.type, item.name, item.data);\n succeeded++;\n } catch (e) {\n failed++;\n errors.push({\n type: item.type,\n name: item.name,\n error: e instanceof Error ? e.message : String(e),\n });\n if (!continueOnError) break;\n }\n }\n\n return {\n total: items.length,\n succeeded,\n failed,\n errors: errors.length > 0 ? errors : undefined,\n };\n }\n\n /**\n * Unregister multiple metadata items in a single batch\n */\n async bulkUnregister(items: Array<{ type: string; name: string }>): Promise<MetadataBulkResult> {\n let succeeded = 0;\n let failed = 0;\n const errors: Array<{ type: string; name: string; error: string }> = [];\n\n for (const item of items) {\n try {\n await this.unregister(item.type, item.name);\n succeeded++;\n } catch (e) {\n failed++;\n errors.push({\n type: item.type,\n name: item.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n return {\n total: items.length,\n succeeded,\n failed,\n errors: errors.length > 0 ? errors : undefined,\n };\n }\n\n // ==========================================\n // Overlay / Customization Management\n // ==========================================\n\n private overlayKey(type: string, name: string, scope: string = 'platform'): string {\n return `${encodeURIComponent(type)}:${encodeURIComponent(name)}:${scope}`;\n }\n\n /**\n * Get the active overlay for a metadata item\n */\n async getOverlay(type: string, name: string, scope?: 'platform' | 'user'): Promise<MetadataOverlay | undefined> {\n return this.overlays.get(this.overlayKey(type, name, scope ?? 'platform'));\n }\n\n /**\n * Save/update an overlay for a metadata item\n */\n async saveOverlay(overlay: MetadataOverlay): Promise<void> {\n const key = this.overlayKey(overlay.baseType, overlay.baseName, overlay.scope);\n this.overlays.set(key, overlay);\n }\n\n /**\n * Remove an overlay, reverting to the base definition\n */\n async removeOverlay(type: string, name: string, scope?: 'platform' | 'user'): Promise<void> {\n this.overlays.delete(this.overlayKey(type, name, scope ?? 'platform'));\n }\n\n /**\n * Get the effective (merged) metadata after applying all overlays.\n * Resolution order: system ← merge(platform) ← merge(user)\n */\n async getEffective(type: string, name: string, context?: {\n userId?: string;\n tenantId?: string;\n roles?: string[];\n permissions?: string[];\n }): Promise<unknown | undefined> {\n const base = await this.get(type, name);\n if (!base) return undefined;\n\n let effective = { ...(base as Record<string, unknown>) };\n\n // Apply platform overlay\n const platformOverlay = await this.getOverlay(type, name, 'platform');\n if (platformOverlay?.active && platformOverlay.patch) {\n effective = { ...effective, ...platformOverlay.patch };\n }\n\n // Apply user overlay (scoped to specific user if context provided)\n if (context?.userId) {\n // Try user-specific key first, then fall back to generic user overlay.\n // The owner check below ensures we never apply another user's overlay.\n const userOverlayKey = this.overlayKey(type, name, 'user') + `:${context.userId}`;\n const userOverlay = this.overlays.get(userOverlayKey) \n ?? await this.getOverlay(type, name, 'user');\n if (userOverlay?.active && userOverlay.patch) {\n // Apply if: overlay has no owner (generic user-level), or owner matches current user\n if (!userOverlay.owner || userOverlay.owner === context.userId) {\n effective = { ...effective, ...userOverlay.patch };\n }\n }\n } else {\n // No user context — only apply user overlays without an owner restriction\n // (owner-scoped overlays require a userId to resolve)\n const userOverlay = await this.getOverlay(type, name, 'user');\n if (userOverlay?.active && userOverlay.patch && !userOverlay.owner) {\n effective = { ...effective, ...userOverlay.patch };\n }\n }\n\n return effective;\n }\n\n // ==========================================\n // Watch / Subscribe (IMetadataService)\n // ==========================================\n\n /**\n * Watch for metadata changes (IMetadataService contract).\n * Returns a handle for unsubscribing.\n */\n watchService(type: string, callback: MetadataWatchCallback): MetadataWatchHandle {\n const wrappedCallback: WatchCallback = (event) => {\n const mappedType = event.type === 'added' ? 'registered'\n : event.type === 'deleted' ? 'unregistered'\n : 'updated';\n callback({\n type: mappedType,\n metadataType: event.metadataType ?? type,\n name: event.name ?? '',\n data: event.data,\n });\n };\n this.addWatchCallback(type, wrappedCallback);\n return {\n unsubscribe: () => this.removeWatchCallback(type, wrappedCallback),\n };\n }\n\n // ==========================================\n // Import / Export\n // ==========================================\n\n /**\n * Export metadata as a portable bundle\n */\n async exportMetadata(options?: MetadataExportOptions): Promise<unknown> {\n const bundle: Record<string, unknown[]> = {};\n const targetTypes = options?.types ?? Array.from(this.registry.keys());\n\n for (const type of targetTypes) {\n const items = await this.list(type);\n if (items.length > 0) {\n bundle[type] = items;\n }\n }\n\n return bundle;\n }\n\n /**\n * Import metadata from a portable bundle\n */\n async importMetadata(data: unknown, options?: MetadataImportOptions): Promise<MetadataImportResult> {\n const {\n conflictResolution = 'skip',\n validate: _validate = true,\n dryRun = false,\n } = options ?? {};\n\n const bundle = data as Record<string, unknown[]>;\n let total = 0;\n let imported = 0;\n let skipped = 0;\n let failed = 0;\n const errors: Array<{ type: string; name: string; error: string }> = [];\n\n for (const [type, items] of Object.entries(bundle)) {\n if (!Array.isArray(items)) continue;\n\n for (const item of items) {\n total++;\n const meta = item as any;\n const name = meta?.name;\n\n if (!name) {\n failed++;\n errors.push({ type, name: '(unknown)', error: 'Item missing name field' });\n continue;\n }\n\n try {\n const itemExists = await this.exists(type, name);\n\n if (itemExists && conflictResolution === 'skip') {\n skipped++;\n continue;\n }\n\n if (!dryRun) {\n if (itemExists && conflictResolution === 'merge') {\n const existing = await this.get(type, name);\n const merged = { ...(existing as any), ...(item as any) };\n await this.register(type, name, merged);\n } else {\n await this.register(type, name, item);\n }\n }\n imported++;\n } catch (e) {\n failed++;\n errors.push({\n type,\n name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n }\n\n return {\n total,\n imported,\n skipped,\n failed,\n errors: errors.length > 0 ? errors : undefined,\n };\n }\n\n // ==========================================\n // Validation\n // ==========================================\n\n /**\n * Validate a metadata item against its type schema.\n * Returns validation result with errors and warnings.\n */\n async validate(_type: string, data: unknown): Promise<MetadataValidationResult> {\n // Basic structural validation\n if (data === null || data === undefined) {\n return {\n valid: false,\n errors: [{ path: '', message: 'Metadata data cannot be null or undefined' }],\n };\n }\n\n if (typeof data !== 'object') {\n return {\n valid: false,\n errors: [{ path: '', message: 'Metadata data must be an object' }],\n };\n }\n\n const meta = data as any;\n const warnings: Array<{ path: string; message: string }> = [];\n\n if (!meta.name) {\n return {\n valid: false,\n errors: [{ path: 'name', message: 'Metadata item must have a name field' }],\n };\n }\n\n if (!meta.label) {\n warnings.push({ path: 'label', message: 'Missing label field (recommended)' });\n }\n\n return { valid: true, warnings: warnings.length > 0 ? warnings : undefined };\n }\n\n // ==========================================\n // Type Registry\n // ==========================================\n\n /**\n * Get all registered metadata types\n */\n async getRegisteredTypes(): Promise<string[]> {\n const types = new Set<string>();\n\n // From type registry\n for (const entry of this.typeRegistry) {\n types.add(entry.type);\n }\n\n // From in-memory registry (custom types)\n for (const type of this.registry.keys()) {\n types.add(type);\n }\n\n return Array.from(types);\n }\n\n /**\n * Get detailed information about a metadata type\n */\n async getTypeInfo(type: string): Promise<MetadataTypeInfo | undefined> {\n const entry = this.typeRegistry.find(e => e.type === type);\n if (!entry) return undefined;\n\n return {\n type: entry.type,\n label: entry.label,\n description: entry.description,\n filePatterns: entry.filePatterns,\n supportsOverlay: entry.supportsOverlay,\n domain: entry.domain,\n };\n }\n\n // ==========================================\n // Dependency Tracking\n // ==========================================\n\n /**\n * Get metadata items that this item depends on\n */\n async getDependencies(type: string, name: string): Promise<MetadataDependency[]> {\n return this.dependencies.get(`${encodeURIComponent(type)}:${encodeURIComponent(name)}`) ?? [];\n }\n\n /**\n * Get metadata items that depend on this item\n */\n async getDependents(type: string, name: string): Promise<MetadataDependency[]> {\n const dependents: MetadataDependency[] = [];\n for (const deps of this.dependencies.values()) {\n for (const dep of deps) {\n if (dep.targetType === type && dep.targetName === name) {\n dependents.push(dep);\n }\n }\n }\n return dependents;\n }\n\n /**\n * Register a dependency between two metadata items.\n * Used internally to track cross-references.\n * Duplicate dependencies (same source, target, and kind) are ignored.\n */\n addDependency(dep: MetadataDependency): void {\n const key = `${encodeURIComponent(dep.sourceType)}:${encodeURIComponent(dep.sourceName)}`;\n if (!this.dependencies.has(key)) {\n this.dependencies.set(key, []);\n }\n const existing = this.dependencies.get(key)!;\n const isDuplicate = existing.some(\n d => d.targetType === dep.targetType && d.targetName === dep.targetName && d.kind === dep.kind\n );\n if (!isDuplicate) {\n existing.push(dep);\n }\n }\n\n // ==========================================\n // Legacy Loader API (backward compatible)\n // ==========================================\n\n /**\n * Load a single metadata item from loaders.\n * Iterates through registered loaders until found.\n */\n async load<T = any>(\n type: string,\n name: string,\n options?: MetadataLoadOptions\n ): Promise<T | null> {\n for (const loader of this.loaders.values()) {\n try {\n const result = await loader.load(type, name, options);\n if (result.data) {\n return result.data as T;\n }\n } catch (e) {\n this.logger.warn(`Loader ${loader.contract.name} failed to load ${type}:${name}`, { error: e });\n }\n }\n return null;\n }\n\n /**\n * Load multiple metadata items from loaders.\n * Aggregates results from all loaders.\n */\n async loadMany<T = any>(\n type: string,\n options?: MetadataLoadOptions\n ): Promise<T[]> {\n const results: T[] = [];\n\n for (const loader of this.loaders.values()) {\n try {\n const items = await loader.loadMany<T>(type, options);\n for (const item of items) {\n const itemAny = item as any;\n if (itemAny && typeof itemAny.name === 'string') {\n const exists = results.some((r: any) => r && r.name === itemAny.name);\n if (exists) continue;\n }\n results.push(item);\n }\n } catch (e) {\n this.logger.warn(`Loader ${loader.contract.name} failed to loadMany ${type}`, { error: e });\n }\n }\n return results;\n }\n\n /**\n * Save metadata item to a loader\n */\n async save<T = any>(\n type: string,\n name: string,\n data: T,\n options?: MetadataSaveOptions\n ): Promise<MetadataSaveResult> {\n const targetLoader = (options as any)?.loader;\n\n let loader: MetadataLoader | undefined;\n \n if (targetLoader) {\n loader = this.loaders.get(targetLoader);\n if (!loader) {\n throw new Error(`Loader not found: ${targetLoader}`);\n }\n } else {\n for (const l of this.loaders.values()) {\n if (!l.save) continue;\n try {\n if (await l.exists(type, name)) {\n loader = l;\n this.logger.info(`Updating existing metadata in loader: ${l.contract.name}`);\n break;\n }\n } catch (e) {\n // Ignore existence check errors\n }\n }\n\n if (!loader) {\n const fsLoader = this.loaders.get('filesystem');\n if (fsLoader && fsLoader.save) {\n loader = fsLoader;\n }\n }\n\n if (!loader) {\n for (const l of this.loaders.values()) {\n if (l.save) {\n loader = l;\n break;\n }\n }\n }\n }\n\n if (!loader) {\n throw new Error(`No loader available for saving type: ${type}`);\n }\n\n if (!loader.save) {\n throw new Error(`Loader '${loader.contract?.name}' does not support saving`);\n }\n\n return loader.save(type, name, data, options);\n }\n\n /**\n * Register a watch callback for metadata changes\n */\n protected addWatchCallback(type: string, callback: WatchCallback): void {\n if (!this.watchCallbacks.has(type)) {\n this.watchCallbacks.set(type, new Set());\n }\n this.watchCallbacks.get(type)!.add(callback);\n }\n\n /**\n * Remove a watch callback for metadata changes\n */\n protected removeWatchCallback(type: string, callback: WatchCallback): void {\n const callbacks = this.watchCallbacks.get(type);\n if (callbacks) {\n callbacks.delete(callback);\n if (callbacks.size === 0) {\n this.watchCallbacks.delete(type);\n }\n }\n }\n\n /**\n * Stop all watching\n */\n async stopWatching(): Promise<void> {\n // Override in subclass\n }\n\n protected notifyWatchers(type: string, event: MetadataWatchEvent) {\n const callbacks = this.watchCallbacks.get(type);\n if (!callbacks) return;\n\n for (const callback of callbacks) {\n try {\n void callback(event);\n } catch (error) {\n this.logger.error('Watch callback error', undefined, {\n type,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n\n // ==========================================\n // Version History & Rollback\n // ==========================================\n\n /**\n * Get the database loader for history operations.\n * Returns undefined if no database loader is configured.\n */\n private getDatabaseLoader(): DatabaseLoader | undefined {\n const dbLoader = this.loaders.get('database');\n if (dbLoader && dbLoader instanceof DatabaseLoader) {\n return dbLoader;\n }\n return undefined;\n }\n\n /**\n * Get version history for a metadata item.\n * Returns a timeline of all changes made to the item.\n */\n async getHistory(\n type: string,\n name: string,\n options?: MetadataHistoryQueryOptions\n ): Promise<MetadataHistoryQueryResult> {\n const dbLoader = this.getDatabaseLoader();\n if (!dbLoader) {\n throw new Error('History tracking requires a database loader to be configured');\n }\n\n return dbLoader.queryHistory(type, name, {\n operationType: options?.operationType,\n since: options?.since,\n until: options?.until,\n limit: options?.limit,\n offset: options?.offset,\n includeMetadata: options?.includeMetadata,\n });\n }\n\n /**\n * Rollback a metadata item to a specific version.\n * Restores the metadata definition from the history snapshot.\n */\n async rollback(\n type: string,\n name: string,\n version: number,\n options?: {\n changeNote?: string;\n recordedBy?: string;\n }\n ): Promise<unknown> {\n const dbLoader = this.getDatabaseLoader();\n if (!dbLoader) {\n throw new Error('Rollback requires a database loader to be configured');\n }\n\n // Fetch the target version snapshot directly from the history table\n const targetVersion = await dbLoader.getHistoryRecord(type, name, version);\n\n if (!targetVersion) {\n throw new Error(`Version ${version} not found in history for ${type}/${name}`);\n }\n\n if (!targetVersion.metadata) {\n throw new Error(`Version ${version} metadata snapshot not available`);\n }\n\n // Restore the metadata using the dedicated rollback path so that a single\n // 'revert' history entry is written (instead of a conflicting 'update' entry)\n const restoredMetadata = targetVersion.metadata;\n await dbLoader.registerRollback(\n type,\n name,\n restoredMetadata,\n version,\n options?.changeNote,\n options?.recordedBy\n );\n\n // Update in-memory registry with the restored metadata\n if (!this.registry.has(type)) {\n this.registry.set(type, new Map());\n }\n this.registry.get(type)!.set(name, restoredMetadata);\n\n return restoredMetadata;\n }\n\n /**\n * Compare two versions of a metadata item.\n * Returns a diff showing what changed between versions.\n */\n async diff(\n type: string,\n name: string,\n version1: number,\n version2: number\n ): Promise<MetadataDiffResult> {\n const dbLoader = this.getDatabaseLoader();\n if (!dbLoader) {\n throw new Error('Diff requires a database loader to be configured');\n }\n\n // Fetch the two version snapshots directly from the history table\n const v1 = await dbLoader.getHistoryRecord(type, name, version1);\n const v2 = await dbLoader.getHistoryRecord(type, name, version2);\n\n if (!v1) {\n throw new Error(`Version ${version1} not found in history for ${type}/${name}`);\n }\n\n if (!v2) {\n throw new Error(`Version ${version2} not found in history for ${type}/${name}`);\n }\n\n if (!v1.metadata || !v2.metadata) {\n throw new Error('Version metadata snapshots not available');\n }\n\n // Generate diff\n const patch = generateSimpleDiff(v1.metadata, v2.metadata);\n const identical = patch.length === 0;\n const summary = generateDiffSummary(patch);\n\n return {\n type,\n name,\n version1,\n version2,\n checksum1: v1.checksum,\n checksum2: v2.checksum,\n identical,\n patch,\n summary,\n };\n }\n}\n\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * JSON Metadata Serializer\n * \n * Handles JSON format serialization and deserialization\n */\n\nimport type { z } from 'zod';\nimport type { MetadataFormat } from '@objectstack/spec/system';\nimport type { MetadataSerializer, SerializeOptions } from './serializer-interface.js';\n\nexport class JSONSerializer implements MetadataSerializer {\n serialize<T>(item: T, options?: SerializeOptions): string {\n const { prettify = true, indent = 2, sortKeys = false } = options || {};\n\n if (sortKeys) {\n // Sort keys recursively\n const sorted = this.sortObjectKeys(item);\n return prettify\n ? JSON.stringify(sorted, null, indent)\n : JSON.stringify(sorted);\n }\n\n return prettify\n ? JSON.stringify(item, null, indent)\n : JSON.stringify(item);\n }\n\n deserialize<T>(content: string, schema?: z.ZodSchema): T {\n const parsed = JSON.parse(content);\n\n if (schema) {\n return schema.parse(parsed) as T;\n }\n\n return parsed as T;\n }\n\n getExtension(): string {\n return '.json';\n }\n\n canHandle(format: MetadataFormat): boolean {\n return format === 'json';\n }\n\n getFormat(): MetadataFormat {\n return 'json';\n }\n\n /**\n * Recursively sort object keys\n */\n private sortObjectKeys(obj: any): any {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => this.sortObjectKeys(item));\n }\n\n const sorted: Record<string, any> = {};\n const keys = Object.keys(obj).sort();\n\n for (const key of keys) {\n sorted[key] = this.sortObjectKeys(obj[key]);\n }\n\n return sorted;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * YAML Metadata Serializer\n * \n * Handles YAML format serialization and deserialization\n */\n\nimport * as yaml from 'js-yaml';\nimport type { z } from 'zod';\nimport type { MetadataFormat } from '@objectstack/spec/system';\nimport type { MetadataSerializer, SerializeOptions } from './serializer-interface.js';\n\nexport class YAMLSerializer implements MetadataSerializer {\n serialize<T>(item: T, options?: SerializeOptions): string {\n const { indent = 2, sortKeys = false } = options || {};\n\n return yaml.dump(item, {\n indent,\n sortKeys,\n lineWidth: -1, // Disable line wrapping\n noRefs: true, // Disable YAML references\n });\n }\n\n deserialize<T>(content: string, schema?: z.ZodSchema): T {\n // Use JSON_SCHEMA to prevent arbitrary code execution\n // This restricts YAML to JSON-compatible types only\n const parsed = yaml.load(content, { schema: yaml.JSON_SCHEMA });\n\n if (schema) {\n return schema.parse(parsed) as T;\n }\n\n return parsed as T;\n }\n\n getExtension(): string {\n return '.yaml';\n }\n\n canHandle(format: MetadataFormat): boolean {\n return format === 'yaml';\n }\n\n getFormat(): MetadataFormat {\n return 'yaml';\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * TypeScript/JavaScript Metadata Serializer\n * \n * Handles TypeScript/JavaScript module format serialization and deserialization\n */\n\nimport type { z } from 'zod';\nimport type { MetadataFormat } from '@objectstack/spec/system';\nimport type { MetadataSerializer, SerializeOptions } from './serializer-interface.js';\n\nexport class TypeScriptSerializer implements MetadataSerializer {\n constructor(private format: 'typescript' | 'javascript' = 'typescript') {}\n\n serialize<T>(item: T, options?: SerializeOptions): string {\n const { prettify = true, indent = 2 } = options || {};\n\n const jsonStr = JSON.stringify(item, null, prettify ? indent : 0);\n \n if (this.format === 'typescript') {\n return `import type { ServiceObject } from '@objectstack/spec/data';\\n\\n` +\n `export const metadata: ServiceObject = ${jsonStr};\\n\\n` +\n `export default metadata;\\n`;\n } else {\n return `export const metadata = ${jsonStr};\\n\\n` +\n `export default metadata;\\n`;\n }\n }\n\n deserialize<T>(content: string, schema?: z.ZodSchema): T {\n // For TypeScript/JavaScript files, we need to extract the exported object\n // Note: This is a simplified parser that works with JSON-like object literals\n // For complex TypeScript with nested objects, consider using a proper TypeScript parser\n \n // Try to find the object literal in various export patterns\n // Pattern 1: export const metadata = {...};\n let objectStart = content.indexOf('export const');\n if (objectStart === -1) {\n // Pattern 2: export default {...};\n objectStart = content.indexOf('export default');\n }\n \n if (objectStart === -1) {\n throw new Error(\n 'Could not parse TypeScript/JavaScript module. ' +\n 'Expected export pattern: \"export const metadata = {...};\" or \"export default {...};\"'\n );\n }\n\n // Find the first opening brace after the export statement\n const braceStart = content.indexOf('{', objectStart);\n if (braceStart === -1) {\n throw new Error('Could not find object literal in export statement');\n }\n\n // Find the matching closing brace by counting braces\n // Handle string literals to avoid counting braces inside strings\n let braceCount = 0;\n let braceEnd = -1;\n let inString = false;\n let stringChar = '';\n \n for (let i = braceStart; i < content.length; i++) {\n const char = content[i];\n const prevChar = i > 0 ? content[i - 1] : '';\n \n // Track string literals (simple handling of \" and ')\n if ((char === '\"' || char === \"'\") && prevChar !== '\\\\') {\n if (!inString) {\n inString = true;\n stringChar = char;\n } else if (char === stringChar) {\n inString = false;\n stringChar = '';\n }\n }\n \n // Count braces only when not inside strings\n if (!inString) {\n if (char === '{') braceCount++;\n if (char === '}') {\n braceCount--;\n if (braceCount === 0) {\n braceEnd = i;\n break;\n }\n }\n }\n }\n\n if (braceEnd === -1) {\n throw new Error('Could not find matching closing brace for object literal');\n }\n\n // Extract the object literal\n const objectLiteral = content.substring(braceStart, braceEnd + 1);\n\n try {\n // Parse as JSON\n const parsed = JSON.parse(objectLiteral);\n\n if (schema) {\n return schema.parse(parsed) as T;\n }\n\n return parsed as T;\n } catch (error) {\n throw new Error(\n `Failed to parse object literal as JSON: ${error instanceof Error ? error.message : String(error)}. ` +\n 'Make sure the TypeScript/JavaScript object uses JSON-compatible syntax (no functions, comments, or trailing commas).'\n );\n }\n }\n\n getExtension(): string {\n return this.format === 'typescript' ? '.ts' : '.js';\n }\n\n canHandle(format: MetadataFormat): boolean {\n return format === 'typescript' || format === 'javascript';\n }\n\n getFormat(): MetadataFormat {\n return this.format;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Database Metadata Loader\n *\n * Loads and persists metadata via an IDataDriver instance, enabling\n * database-backed storage for platform and user scoped metadata.\n * Uses the `sys_metadata` table (configurable) following the\n * MetadataRecordSchema envelope defined in @objectstack/spec.\n */\n\nimport type {\n MetadataLoadOptions,\n MetadataLoadResult,\n MetadataStats,\n MetadataLoaderContract,\n MetadataSaveOptions,\n MetadataSaveResult,\n MetadataRecord,\n MetadataHistoryRecord,\n} from '@objectstack/spec/system';\nimport { SysMetadataObject, SysMetadataHistoryObject } from '@objectstack/platform-objects/metadata';\nimport type { IDataDriver, IDataEngine } from '@objectstack/spec/contracts';\nimport type { MetadataLoader } from './loader-interface.js';\nimport { calculateChecksum } from '../utils/metadata-history-utils.js';\nimport { MetadataProjector } from '../projection/metadata-projector.js';\n\n/**\n * Configuration for the DatabaseLoader.\n *\n * Accepts either a raw `IDataDriver` or an `IDataEngine` (ObjectQL).\n * When `engine` is provided, all CRUD operations route through the engine\n * which handles datasource mapping automatically — no manual driver\n * resolution needed. Schema sync is also skipped (the engine handles it).\n */\nexport interface DatabaseLoaderOptions {\n /** The IDataDriver instance to use for database operations */\n driver?: IDataDriver;\n\n /** The IDataEngine (ObjectQL) instance — preferred over raw driver */\n engine?: IDataEngine;\n\n /** The table name to store metadata records (default: 'sys_metadata') */\n tableName?: string;\n\n /** The table name to store history records (default: 'sys_metadata_history') */\n historyTableName?: string;\n\n /** Organization ID for multi-tenant isolation */\n organizationId?: string;\n\n /** Project ID — null = platform-global, set = project-scoped */\n projectId?: string;\n\n /** Enable history tracking (default: true) */\n trackHistory?: boolean;\n\n /** Enable metadata projection to type-specific tables (default: true) */\n enableProjection?: boolean;\n}\n\n/**\n * DatabaseLoader — Datasource-backed metadata persistence.\n *\n * Implements the MetadataLoader interface to provide database read/write\n * for metadata records. Uses the MetadataRecordSchema envelope to persist\n * metadata with scope, versioning, and audit fields.\n */\nexport class DatabaseLoader implements MetadataLoader {\n readonly contract: MetadataLoaderContract = {\n name: 'database',\n protocol: 'datasource:',\n capabilities: {\n read: true,\n write: true,\n watch: false,\n list: true,\n },\n };\n\n private driver?: IDataDriver;\n private engine?: IDataEngine;\n private tableName: string;\n private historyTableName: string;\n private organizationId?: string;\n private projectId?: string;\n private trackHistory: boolean;\n private schemaReady = false;\n private historySchemaReady = false;\n private enableProjection: boolean;\n private projector?: MetadataProjector;\n\n constructor(options: DatabaseLoaderOptions) {\n if (!options.driver && !options.engine) {\n throw new Error('DatabaseLoader requires either a driver or engine');\n }\n this.driver = options.driver;\n this.engine = options.engine;\n this.tableName = options.tableName ?? 'sys_metadata';\n this.historyTableName = options.historyTableName ?? 'sys_metadata_history';\n this.organizationId = options.organizationId;\n this.projectId = options.projectId;\n this.trackHistory = options.trackHistory !== false; // Default to true\n this.enableProjection = options.enableProjection !== false; // Default to true\n\n // Initialize projector if projection is enabled\n if (this.enableProjection) {\n this.projector = new MetadataProjector({\n driver: this.driver,\n engine: this.engine,\n organizationId: this.organizationId,\n projectId: this.projectId,\n });\n }\n }\n\n // ==========================================\n // Internal CRUD helpers (driver vs engine)\n // ==========================================\n\n private async _find(table: string, query: Record<string, unknown>): Promise<Record<string, unknown>[]> {\n if (this.engine) {\n return this.engine.find(table, query as any);\n }\n return this.driver!.find(table, { object: table, ...query } as any);\n }\n\n private async _findOne(table: string, query: Record<string, unknown>): Promise<Record<string, unknown> | null> {\n if (this.engine) {\n return this.engine.findOne(table, query as any);\n }\n return this.driver!.findOne(table, { object: table, ...query } as any);\n }\n\n private async _count(table: string, query: Record<string, unknown>): Promise<number> {\n if (this.engine) {\n return this.engine.count(table, query as any);\n }\n return this.driver!.count(table, { object: table, ...query } as any);\n }\n\n private async _create(table: string, data: Record<string, unknown>): Promise<Record<string, unknown>> {\n if (this.engine) {\n return this.engine.insert(table, data);\n }\n return this.driver!.create(table, data);\n }\n\n private async _update(table: string, id: string, data: Record<string, unknown>): Promise<Record<string, unknown>> {\n if (this.engine) {\n return this.engine.update(table, { id, ...data });\n }\n return this.driver!.update(table, id, data);\n }\n\n private async _delete(table: string, id: string): Promise<any> {\n if (this.engine) {\n return this.engine.delete(table, { where: { id } } as any);\n }\n return this.driver!.delete(table, id);\n }\n\n /**\n * Ensure the metadata table exists.\n * Uses IDataDriver.syncSchema with the SysMetadataObject definition\n * to idempotently create/update the table.\n */\n private async ensureSchema(): Promise<void> {\n if (this.schemaReady) return;\n\n // When using engine, schema sync is handled by ObjectQL startup\n if (this.engine) {\n this.schemaReady = true;\n return;\n }\n\n try {\n await this.driver!.syncSchema(this.tableName, {\n ...SysMetadataObject,\n name: this.tableName,\n });\n this.schemaReady = true;\n } catch {\n // If syncSchema fails (e.g. table already exists), mark ready and continue\n this.schemaReady = true;\n }\n }\n\n /**\n * Ensure the history table exists.\n * Uses IDataDriver.syncSchema with the SysMetadataHistoryObject definition.\n */\n private async ensureHistorySchema(): Promise<void> {\n if (!this.trackHistory || this.historySchemaReady) return;\n\n // When using engine, schema sync is handled by ObjectQL startup\n if (this.engine) {\n this.historySchemaReady = true;\n return;\n }\n\n try {\n await this.driver!.syncSchema(this.historyTableName, {\n ...SysMetadataHistoryObject,\n name: this.historyTableName,\n });\n this.historySchemaReady = true;\n } catch (error) {\n // Log the error; historySchemaReady remains false so the next operation retries.\n // If the error is a benign \"already exists\" the next attempt will also succeed.\n console.error('Failed to ensure history schema, will retry on next operation:', error);\n }\n }\n\n /**\n * Build base filter conditions for queries.\n * Filters by organizationId when configured; project_id when projectId is set,\n * or null (platform-global) when not set.\n */\n private baseFilter(type: string, name?: string): Record<string, unknown> {\n const filter: Record<string, unknown> = { type };\n if (name !== undefined) {\n filter.name = name;\n }\n if (this.organizationId) {\n filter.organization_id = this.organizationId;\n }\n // When projectId is set, scope to that project; otherwise query platform-global (project_id = null).\n filter.project_id = this.projectId ?? null;\n return filter;\n }\n\n /**\n * Create a history record for a metadata change.\n *\n * @param metadataId - The metadata record ID\n * @param type - Metadata type\n * @param name - Metadata name\n * @param version - Version number\n * @param metadata - The metadata payload\n * @param operationType - Type of operation\n * @param previousChecksum - Checksum of previous version (if any)\n * @param changeNote - Optional change description\n * @param recordedBy - Optional user who made the change\n */\n private async createHistoryRecord(\n metadataId: string,\n type: string,\n name: string,\n version: number,\n metadata: unknown,\n operationType: 'create' | 'update' | 'publish' | 'revert' | 'delete',\n previousChecksum?: string,\n changeNote?: string,\n recordedBy?: string\n ): Promise<void> {\n if (!this.trackHistory) return;\n\n await this.ensureHistorySchema();\n\n const now = new Date().toISOString();\n const checksum = await calculateChecksum(metadata);\n\n // Skip if checksum matches previous version (no actual change)\n if (previousChecksum && checksum === previousChecksum && operationType === 'update') {\n return;\n }\n\n const historyId = generateId();\n const metadataJson = JSON.stringify(metadata);\n\n const historyRecord: Partial<MetadataHistoryRecord> = {\n id: historyId,\n metadataId,\n name,\n type,\n version,\n operationType,\n metadata: metadataJson as any,\n checksum,\n previousChecksum,\n changeNote,\n recordedBy,\n recordedAt: now,\n ...(this.organizationId ? { organizationId: this.organizationId } : {}),\n ...(this.projectId !== undefined ? { projectId: this.projectId } : {}),\n };\n\n try {\n await this._create(this.historyTableName, {\n id: historyRecord.id,\n metadata_id: historyRecord.metadataId,\n name: historyRecord.name,\n type: historyRecord.type,\n version: historyRecord.version,\n operation_type: historyRecord.operationType,\n metadata: historyRecord.metadata,\n checksum: historyRecord.checksum,\n previous_checksum: historyRecord.previousChecksum,\n change_note: historyRecord.changeNote,\n recorded_by: historyRecord.recordedBy,\n recorded_at: historyRecord.recordedAt,\n ...(this.organizationId ? { organization_id: this.organizationId } : {}),\n ...(this.projectId !== undefined ? { project_id: this.projectId } : {}),\n });\n } catch (error) {\n // Log error but don't fail the main operation\n console.error(`Failed to create history record for ${type}/${name}:`, error);\n }\n }\n\n /**\n * Convert a database row to a metadata payload.\n * Parses the JSON `metadata` column back into an object.\n */\n private rowToData(row: Record<string, unknown>): Record<string, unknown> | null {\n if (!row || !row.metadata) return null;\n\n const payload = typeof row.metadata === 'string'\n ? JSON.parse(row.metadata as string)\n : row.metadata;\n\n return payload as Record<string, unknown>;\n }\n\n /**\n * Convert a database row to a MetadataRecord-like object.\n */\n private rowToRecord(row: Record<string, unknown>): MetadataRecord {\n return {\n id: row.id as string,\n name: row.name as string,\n type: row.type as string,\n namespace: (row.namespace as string) ?? 'default',\n packageId: row.package_id as string | undefined,\n managedBy: row.managed_by as MetadataRecord['managedBy'],\n scope: (row.scope as MetadataRecord['scope']) ?? 'platform',\n metadata: this.rowToData(row) ?? {},\n extends: row.extends as string | undefined,\n strategy: (row.strategy as MetadataRecord['strategy']) ?? 'merge',\n owner: row.owner as string | undefined,\n state: (row.state as MetadataRecord['state']) ?? 'active',\n organizationId: row.organization_id as string | undefined,\n projectId: row.project_id as string | undefined,\n version: (row.version as number) ?? 1,\n checksum: row.checksum as string | undefined,\n source: row.source as MetadataRecord['source'],\n tags: row.tags ? (typeof row.tags === 'string' ? JSON.parse(row.tags as string) : row.tags as string[]) : undefined,\n createdBy: row.created_by as string | undefined,\n createdAt: row.created_at as string | undefined,\n updatedBy: row.updated_by as string | undefined,\n updatedAt: row.updated_at as string | undefined,\n };\n }\n\n // ==========================================\n // MetadataLoader Interface Implementation\n // ==========================================\n\n async load(\n type: string,\n name: string,\n _options?: MetadataLoadOptions\n ): Promise<MetadataLoadResult> {\n const startTime = Date.now();\n\n await this.ensureSchema();\n\n try {\n const row = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n if (!row) {\n return {\n data: null,\n loadTime: Date.now() - startTime,\n };\n }\n\n const data = this.rowToData(row);\n const record = this.rowToRecord(row);\n\n return {\n data,\n source: 'database',\n format: 'json',\n etag: record.checksum,\n loadTime: Date.now() - startTime,\n };\n } catch {\n return {\n data: null,\n loadTime: Date.now() - startTime,\n };\n }\n }\n\n async loadMany<T = any>(\n type: string,\n _options?: MetadataLoadOptions\n ): Promise<T[]> {\n await this.ensureSchema();\n\n try {\n const rows = await this._find(this.tableName, {\n where: this.baseFilter(type),\n });\n\n return rows\n .map(row => this.rowToData(row))\n .filter((data): data is Record<string, unknown> => data !== null) as T[];\n } catch {\n return [];\n }\n }\n\n async exists(type: string, name: string): Promise<boolean> {\n await this.ensureSchema();\n\n try {\n const count = await this._count(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n return count > 0;\n } catch {\n return false;\n }\n }\n\n async stat(type: string, name: string): Promise<MetadataStats | null> {\n await this.ensureSchema();\n\n try {\n const row = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n if (!row) return null;\n\n const record = this.rowToRecord(row);\n const metadataStr = typeof row.metadata === 'string'\n ? row.metadata as string\n : JSON.stringify(row.metadata);\n\n return {\n size: metadataStr.length,\n mtime: record.updatedAt ?? record.createdAt ?? new Date().toISOString(),\n format: 'json',\n etag: record.checksum,\n };\n } catch {\n return null;\n }\n }\n\n async list(type: string): Promise<string[]> {\n await this.ensureSchema();\n\n try {\n const rows = await this._find(this.tableName, {\n where: this.baseFilter(type),\n fields: ['name'],\n });\n\n return rows\n .map(row => row.name as string)\n .filter(name => typeof name === 'string');\n } catch {\n return [];\n }\n }\n\n /**\n * Fetch a single history snapshot by (type, name, version).\n * Returns null when the record does not exist.\n */\n async getHistoryRecord(\n type: string,\n name: string,\n version: number\n ): Promise<MetadataHistoryRecord | null> {\n if (!this.trackHistory) return null;\n\n await this.ensureHistorySchema();\n\n // Resolve the parent metadata record ID\n const metadataRow = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n if (!metadataRow) return null;\n\n const filter: Record<string, unknown> = {\n metadata_id: metadataRow.id,\n version,\n };\n if (this.organizationId) {\n filter.organization_id = this.organizationId;\n }\n filter.project_id = this.projectId ?? null;\n\n const row = await this._findOne(this.historyTableName, {\n where: filter,\n });\n if (!row) return null;\n\n return {\n id: row.id as string,\n metadataId: row.metadata_id as string,\n name: row.name as string,\n type: row.type as string,\n version: row.version as number,\n operationType: row.operation_type as MetadataHistoryRecord['operationType'],\n metadata: typeof row.metadata === 'string' ? JSON.parse(row.metadata as string) : row.metadata,\n checksum: row.checksum as string,\n previousChecksum: row.previous_checksum as string | undefined,\n changeNote: row.change_note as string | undefined,\n organizationId: row.organization_id as string | undefined,\n projectId: row.project_id as string | undefined,\n recordedBy: row.recorded_by as string | undefined,\n recordedAt: row.recorded_at as string,\n };\n }\n\n /**\n * Query history records with pagination and filtering.\n * Encapsulates history table queries so MetadataManager doesn't need\n * direct driver access.\n */\n async queryHistory(\n type: string,\n name: string,\n options?: {\n operationType?: string;\n since?: string;\n until?: string;\n limit?: number;\n offset?: number;\n includeMetadata?: boolean;\n }\n ): Promise<{ records: any[]; total: number; hasMore: boolean }> {\n if (!this.trackHistory) {\n return { records: [], total: 0, hasMore: false };\n }\n\n await this.ensureSchema();\n await this.ensureHistorySchema();\n\n // Find the metadata record\n const filter: Record<string, unknown> = { type, name };\n if (this.organizationId) filter.organization_id = this.organizationId;\n filter.project_id = this.projectId ?? null;\n\n const metadataRecord = await this._findOne(this.tableName, { where: filter });\n if (!metadataRecord) {\n return { records: [], total: 0, hasMore: false };\n }\n\n // Build history query\n const historyFilter: Record<string, unknown> = {\n metadata_id: metadataRecord.id,\n };\n if (this.organizationId) historyFilter.organization_id = this.organizationId;\n historyFilter.project_id = this.projectId ?? null;\n if (options?.operationType) historyFilter.operation_type = options.operationType;\n if (options?.since) historyFilter.recorded_at = { $gte: options.since };\n if (options?.until) {\n if (historyFilter.recorded_at) {\n (historyFilter.recorded_at as Record<string, unknown>).$lte = options.until;\n } else {\n historyFilter.recorded_at = { $lte: options.until };\n }\n }\n\n const limit = options?.limit ?? 50;\n const offset = options?.offset ?? 0;\n\n const historyRecords = await this._find(this.historyTableName, {\n where: historyFilter,\n orderBy: [\n { field: 'recorded_at', order: 'desc' as const },\n { field: 'version', order: 'desc' as const },\n ],\n limit: limit + 1,\n offset,\n });\n\n const hasMore = historyRecords.length > limit;\n const records = historyRecords.slice(0, limit);\n const total = await this._count(this.historyTableName, { where: historyFilter });\n\n const includeMetadata = options?.includeMetadata !== false;\n const result = records.map((row: Record<string, unknown>) => {\n const parsedMetadata =\n typeof row.metadata === 'string'\n ? JSON.parse(row.metadata as string)\n : (row.metadata as Record<string, unknown> | null | undefined);\n\n return {\n id: row.id as string,\n metadataId: row.metadata_id as string,\n name: row.name as string,\n type: row.type as string,\n version: row.version as number,\n operationType: row.operation_type as string,\n metadata: includeMetadata ? parsedMetadata : null,\n checksum: row.checksum as string,\n previousChecksum: row.previous_checksum as string | undefined,\n changeNote: row.change_note as string | undefined,\n organizationId: row.organization_id as string | undefined,\n projectId: row.project_id as string | undefined,\n recordedBy: row.recorded_by as string | undefined,\n recordedAt: row.recorded_at as string,\n };\n });\n\n return { records: result, total, hasMore };\n }\n\n /**\n * Perform a rollback: persist `restoredData` as the new current state and record a\n * single 'revert' history entry (instead of the usual 'update' entry that `save()`\n * would produce). This avoids the duplicate-version problem that arises when\n * `register()` → `save()` writes an 'update' entry followed by an additional\n * 'revert' entry for the same version number.\n */\n async registerRollback(\n type: string,\n name: string,\n restoredData: unknown,\n targetVersion: number,\n changeNote?: string,\n recordedBy?: string\n ): Promise<void> {\n await this.ensureSchema();\n\n const now = new Date().toISOString();\n const metadataJson = JSON.stringify(restoredData);\n const newChecksum = await calculateChecksum(restoredData);\n\n const existing = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n if (!existing) {\n throw new Error(`Metadata ${type}/${name} not found for rollback`);\n }\n\n const previousChecksum = existing.checksum as string | undefined;\n const newVersion = ((existing.version as number) ?? 0) + 1;\n\n await this._update(this.tableName, existing.id as string, {\n metadata: metadataJson,\n version: newVersion,\n checksum: newChecksum,\n updated_at: now,\n state: 'active',\n });\n\n // Write exactly one 'revert' history entry (not an 'update' entry)\n await this.createHistoryRecord(\n existing.id as string,\n type,\n name,\n newVersion,\n restoredData,\n 'revert',\n previousChecksum,\n changeNote ?? `Rolled back to version ${targetVersion}`,\n recordedBy\n );\n }\n\n async save(\n type: string,\n name: string,\n data: any,\n _options?: MetadataSaveOptions\n ): Promise<MetadataSaveResult> {\n const startTime = Date.now();\n\n await this.ensureSchema();\n\n const now = new Date().toISOString();\n const metadataJson = JSON.stringify(data);\n const newChecksum = await calculateChecksum(data);\n\n try {\n const existing = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n if (existing) {\n // Skip update if the content is identical (prevents phantom version bumps)\n const previousChecksum = existing.checksum as string | undefined;\n if (newChecksum === previousChecksum) {\n return {\n success: true,\n path: `datasource://${this.tableName}/${type}/${name}`,\n size: metadataJson.length,\n saveTime: Date.now() - startTime,\n };\n }\n\n // Update existing record\n const version = ((existing.version as number) ?? 0) + 1;\n\n await this._update(this.tableName, existing.id as string, {\n metadata: metadataJson,\n version,\n checksum: newChecksum,\n updated_at: now,\n state: 'active',\n });\n\n // Create history record for update\n await this.createHistoryRecord(\n existing.id as string,\n type,\n name,\n version,\n data,\n 'update',\n previousChecksum\n );\n\n // Project to type-specific table\n if (this.projector) {\n await this.projector.project(type, name, data);\n }\n\n return {\n success: true,\n path: `datasource://${this.tableName}/${type}/${name}`,\n size: metadataJson.length,\n saveTime: Date.now() - startTime,\n };\n } else {\n // Create new record\n const id = generateId();\n await this._create(this.tableName, {\n id,\n name,\n type,\n namespace: 'default',\n scope: (data as any)?.scope ?? 'platform',\n metadata: metadataJson,\n checksum: newChecksum,\n strategy: 'merge',\n state: 'active',\n version: 1,\n source: 'database',\n ...(this.organizationId ? { organization_id: this.organizationId } : {}),\n ...(this.projectId !== undefined ? { project_id: this.projectId } : { project_id: null }),\n created_at: now,\n updated_at: now,\n });\n\n // Create history record for creation\n await this.createHistoryRecord(\n id,\n type,\n name,\n 1,\n data,\n 'create'\n );\n\n // Project to type-specific table\n if (this.projector) {\n await this.projector.project(type, name, data);\n }\n\n return {\n success: true,\n path: `datasource://${this.tableName}/${type}/${name}`,\n size: metadataJson.length,\n saveTime: Date.now() - startTime,\n };\n }\n } catch (error) {\n throw new Error(\n `DatabaseLoader save failed for ${type}/${name}: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Delete a metadata item from the database\n */\n async delete(type: string, name: string): Promise<void> {\n await this.ensureSchema();\n\n // Find the existing record to get its ID\n const existing = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n if (!existing) {\n // Item doesn't exist, nothing to delete\n return;\n }\n\n // Delete from the main metadata table using the record's ID\n await this._delete(this.tableName, existing.id as string);\n\n // Delete projection from type-specific table\n if (this.projector) {\n await this.projector.deleteProjection(type, name);\n }\n }\n}\n\n/**\n * Generate a simple unique ID for metadata records.\n * Uses crypto.randomUUID when available, falls back to timestamp-based ID.\n */\nfunction generateId(): string {\n if (typeof globalThis.crypto !== 'undefined' && typeof globalThis.crypto.randomUUID === 'function') {\n return globalThis.crypto.randomUUID();\n }\n // Fallback for environments without crypto.randomUUID\n return `meta_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata History Utilities\n *\n * Utility functions for metadata versioning and history tracking,\n * including checksum calculation, JSON normalization, and diff generation.\n */\n\n/**\n * Calculate SHA-256 checksum of normalized JSON metadata.\n * Normalizes the JSON by sorting keys and removing whitespace\n * to ensure consistent checksums across identical content.\n *\n * @param metadata - The metadata object to checksum\n * @returns SHA-256 hex string\n */\nexport async function calculateChecksum(metadata: unknown): Promise<string> {\n // Normalize JSON by sorting keys recursively\n const normalized = normalizeJSON(metadata);\n const jsonString = JSON.stringify(normalized);\n\n // Use Web Crypto API (available in Node.js 15+ and all modern browsers)\n if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.subtle) {\n const encoder = new TextEncoder();\n const data = encoder.encode(jsonString);\n const hashBuffer = await globalThis.crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n }\n\n // Fallback for environments without Web Crypto API\n // Use a simple hash function (not cryptographically secure, but sufficient for change detection)\n return simpleHash(jsonString);\n}\n\n/**\n * Normalize JSON by recursively sorting object keys.\n * This ensures deterministic serialization for checksum calculation.\n *\n * @param value - The value to normalize\n * @returns Normalized value with sorted keys\n */\nfunction normalizeJSON(value: unknown): unknown {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map(normalizeJSON);\n }\n\n if (typeof value === 'object') {\n const sorted: Record<string, unknown> = {};\n const keys = Object.keys(value as object).sort();\n for (const key of keys) {\n sorted[key] = normalizeJSON((value as Record<string, unknown>)[key]);\n }\n return sorted;\n }\n\n return value;\n}\n\n/**\n * Simple hash function fallback for environments without Web Crypto API.\n * Based on djb2 hash algorithm.\n *\n * @param str - String to hash\n * @returns Hex hash string\n */\nfunction simpleHash(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash) + str.charCodeAt(i);\n hash = hash & hash; // Convert to 32-bit integer\n }\n // Convert to hex and pad to 64 characters to match SHA-256 length\n const hexHash = Math.abs(hash).toString(16);\n return hexHash.padStart(64, '0');\n}\n\n/**\n * Generate a simple JSON patch between two objects.\n * Returns an array of operations showing what changed.\n *\n * @param oldObj - Original object\n * @param newObj - New object\n * @param path - Current path (for recursion)\n * @returns Array of change operations\n */\nexport function generateSimpleDiff(\n oldObj: unknown,\n newObj: unknown,\n path: string = ''\n): Array<{ op: string; path: string; value?: unknown; oldValue?: unknown }> {\n const changes: Array<{ op: string; path: string; value?: unknown; oldValue?: unknown }> = [];\n\n // Handle primitives\n if (typeof oldObj !== 'object' || oldObj === null || typeof newObj !== 'object' || newObj === null) {\n if (oldObj !== newObj) {\n changes.push({ op: 'replace', path: path || '/', value: newObj, oldValue: oldObj });\n }\n return changes;\n }\n\n // Handle arrays\n if (Array.isArray(oldObj) || Array.isArray(newObj)) {\n if (!Array.isArray(oldObj) || !Array.isArray(newObj) || oldObj.length !== newObj.length) {\n changes.push({ op: 'replace', path: path || '/', value: newObj, oldValue: oldObj });\n } else {\n // Compare array elements\n for (let i = 0; i < oldObj.length; i++) {\n const subPath = `${path}/${i}`;\n changes.push(...generateSimpleDiff(oldObj[i], newObj[i], subPath));\n }\n }\n return changes;\n }\n\n // Handle objects\n const oldKeys = new Set(Object.keys(oldObj as object));\n const newKeys = new Set(Object.keys(newObj as object));\n\n // Check for added keys\n for (const key of newKeys) {\n if (!oldKeys.has(key)) {\n const subPath = path ? `${path}/${key}` : `/${key}`;\n changes.push({ op: 'add', path: subPath, value: (newObj as Record<string, unknown>)[key] });\n }\n }\n\n // Check for removed keys\n for (const key of oldKeys) {\n if (!newKeys.has(key)) {\n const subPath = path ? `${path}/${key}` : `/${key}`;\n changes.push({ op: 'remove', path: subPath, oldValue: (oldObj as Record<string, unknown>)[key] });\n }\n }\n\n // Check for modified keys\n for (const key of oldKeys) {\n if (newKeys.has(key)) {\n const subPath = path ? `${path}/${key}` : `/${key}`;\n changes.push(...generateSimpleDiff(\n (oldObj as Record<string, unknown>)[key],\n (newObj as Record<string, unknown>)[key],\n subPath\n ));\n }\n }\n\n return changes;\n}\n\n/**\n * Generate a human-readable summary of changes.\n *\n * @param diff - The diff operations\n * @returns Human-readable summary\n */\nexport function generateDiffSummary(\n diff: Array<{ op: string; path: string; value?: unknown; oldValue?: unknown }>\n): string {\n if (diff.length === 0) {\n return 'No changes';\n }\n\n const summary: string[] = [];\n const addCount = diff.filter(d => d.op === 'add').length;\n const removeCount = diff.filter(d => d.op === 'remove').length;\n const replaceCount = diff.filter(d => d.op === 'replace').length;\n\n if (addCount > 0) summary.push(`${addCount} field${addCount > 1 ? 's' : ''} added`);\n if (removeCount > 0) summary.push(`${removeCount} field${removeCount > 1 ? 's' : ''} removed`);\n if (replaceCount > 0) summary.push(`${replaceCount} field${replaceCount > 1 ? 's' : ''} modified`);\n\n return summary.join(', ');\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata Projection Service\n *\n * Implements the dual-table architecture pattern:\n * - sys_metadata: Source of truth for package management, versioning\n * - Type-specific tables (sys_object, sys_view, etc.): Queryable projections\n *\n * When metadata is saved to sys_metadata, this service projects it into\n * the appropriate type-specific table so Studio can query it via Object Protocol.\n */\n\nimport type { IDataDriver, IDataEngine } from '@objectstack/spec/contracts';\nimport { StorageNameMapping } from '@objectstack/spec/system';\n\n/**\n * Configuration for the MetadataProjector\n */\nexport interface MetadataProjectorOptions {\n /** The IDataDriver instance to use for database operations */\n driver?: IDataDriver;\n\n /** The IDataEngine (ObjectQL) instance — preferred over raw driver */\n engine?: IDataEngine;\n\n /** Organization ID for multi-tenant isolation */\n organizationId?: string;\n\n /** Project ID — null = platform-global, set = project-scoped */\n projectId?: string;\n}\n\n/**\n * MetadataProjector\n *\n * Handles projection from sys_metadata to type-specific tables.\n */\nexport class MetadataProjector {\n private driver?: IDataDriver;\n private engine?: IDataEngine;\n /** Reserved for future multi-tenant projection scoping */\n readonly scope: { organizationId?: string; projectId?: string };\n\n // Map of metadata types to their target table names\n private readonly typeTableMap: Record<string, string> = {\n object: 'sys_object',\n view: 'sys_view',\n agent: 'sys_agent',\n tool: 'sys_tool',\n flow: 'sys_flow',\n // Add more as needed: dashboard, app, action, workflow, etc.\n };\n\n constructor(options: MetadataProjectorOptions) {\n if (!options.driver && !options.engine) {\n throw new Error('MetadataProjector requires either a driver or engine');\n }\n this.driver = options.driver;\n this.engine = options.engine;\n this.scope = {\n organizationId: options.organizationId,\n projectId: options.projectId,\n };\n }\n\n /**\n * Project metadata to type-specific table\n */\n async project(type: string, name: string, data: any): Promise<void> {\n const targetTable = this.typeTableMap[type];\n if (!targetTable) {\n // Not all metadata types have projections (e.g., 'field' might not)\n return;\n }\n\n const projectedData = this.transformToProjection(type, name, data);\n if (!projectedData) {\n return;\n }\n\n try {\n // Check if projection already exists (scoped by project_id for isolation)\n const projId = this.scope.projectId ?? null;\n const existing = await this._findOne(targetTable, {\n where: { name, project_id: projId },\n });\n\n if (existing) {\n // Update existing projection\n await this._update(targetTable, existing.id as string, projectedData);\n } else {\n // Create new projection\n const id = this.generateId();\n await this._create(targetTable, {\n id,\n ...projectedData,\n });\n }\n } catch (error) {\n // Log but don't fail the main save operation\n console.error(`Failed to project ${type}/${name} to ${targetTable}:`, error);\n }\n }\n\n /**\n * Delete projection from type-specific table\n */\n async deleteProjection(type: string, name: string): Promise<void> {\n const targetTable = this.typeTableMap[type];\n if (!targetTable) {\n return;\n }\n\n try {\n // Find the projection (scoped by project_id for isolation)\n const projId = this.scope.projectId ?? null;\n const existing = await this._findOne(targetTable, {\n where: { name, project_id: projId },\n });\n\n if (existing) {\n await this._delete(targetTable, existing.id as string);\n }\n } catch (error) {\n console.error(`Failed to delete projection ${type}/${name} from ${targetTable}:`, error);\n }\n }\n\n /**\n * Transform metadata into projection record\n */\n private transformToProjection(type: string, name: string, data: any): Record<string, any> | null {\n const now = new Date().toISOString();\n\n switch (type) {\n case 'object':\n return this.projectObject(name, data, now);\n case 'view':\n return this.projectView(name, data, now);\n case 'agent':\n return this.projectAgent(name, data, now);\n case 'tool':\n return this.projectTool(name, data, now);\n case 'flow':\n return this.projectFlow(name, data, now);\n default:\n return null;\n }\n }\n\n /**\n * Project object metadata to sys_object\n */\n private projectObject(name: string, data: any, now: string): Record<string, any> {\n return {\n name,\n project_id: this.scope.projectId ?? null,\n label: data.label || name,\n plural_label: data.pluralLabel || data.label || name,\n description: data.description || '',\n icon: data.icon || 'database',\n namespace: data.namespace || 'default',\n tags: Array.isArray(data.tags) ? data.tags.join(',') : (data.tags || ''),\n active: data.active !== false,\n is_system: data.isSystem || false,\n abstract: data.abstract || false,\n datasource: data.datasource || 'default',\n table_name: data.name ? StorageNameMapping.resolveTableName({ name: data.name }) : name,\n // Serialize complex structures as JSON\n fields_json: data.fields ? JSON.stringify(data.fields) : null,\n indexes_json: data.indexes ? JSON.stringify(data.indexes) : null,\n validations_json: data.validations ? JSON.stringify(data.validations) : null,\n state_machines_json: data.stateMachines ? JSON.stringify(data.stateMachines) : null,\n capabilities_json: data.enable ? JSON.stringify(data.enable) : null,\n // Denormalized fields\n field_count: data.fields ? Object.keys(data.fields).length : 0,\n display_name_field: data.displayNameField || null,\n title_format: data.titleFormat || null,\n compact_layout: Array.isArray(data.compactLayout) ? data.compactLayout.join(',') : (data.compactLayout || null),\n // Capabilities (denormalized for easier querying)\n track_history: data.enable?.trackHistory || false,\n searchable: data.enable?.searchable !== false,\n api_enabled: data.enable?.apiEnabled !== false,\n files: data.enable?.files || false,\n feeds: data.enable?.feeds || false,\n activities: data.enable?.activities || false,\n trash: data.enable?.trash !== false,\n mru: data.enable?.mru !== false,\n clone: data.enable?.clone !== false,\n // Package management\n package_id: data.packageId || null,\n managed_by: data.managedBy || 'user',\n // Audit\n created_by: data.createdBy || null,\n created_at: data.createdAt || now,\n updated_by: data.updatedBy || null,\n updated_at: now,\n };\n }\n\n /**\n * Project view metadata to sys_view\n */\n private projectView(name: string, data: any, now: string): Record<string, any> {\n return {\n name,\n project_id: this.scope.projectId ?? null,\n label: data.label || name,\n description: data.description || '',\n object_name: data.object || '',\n view_type: data.type || 'grid',\n // Serialize configurations as JSON\n columns_json: data.columns ? JSON.stringify(data.columns) : null,\n filters_json: data.filters ? JSON.stringify(data.filters) : null,\n sort_json: data.sort ? JSON.stringify(data.sort) : null,\n config_json: data.config ? JSON.stringify(data.config) : null,\n // Display options\n page_size: data.pageSize || 25,\n show_search: data.showSearch !== false,\n show_filters: data.showFilters !== false,\n // Classification\n namespace: data.namespace || 'default',\n // Package management\n package_id: data.packageId || null,\n managed_by: data.managedBy || 'user',\n // Audit\n created_by: data.createdBy || null,\n created_at: data.createdAt || now,\n updated_by: data.updatedBy || null,\n updated_at: now,\n };\n }\n\n /**\n * Project agent metadata to sys_agent\n */\n private projectAgent(name: string, data: any, now: string): Record<string, any> {\n return {\n name,\n project_id: this.scope.projectId ?? null,\n label: data.label || name,\n description: data.description || '',\n agent_type: data.type || 'conversational',\n // Model configuration\n model: data.model || null,\n temperature: data.temperature ?? 0.7,\n max_tokens: data.maxTokens || null,\n top_p: data.topP || null,\n // System prompt\n system_prompt: data.systemPrompt || null,\n // Tools and skills as JSON\n tools_json: data.tools ? JSON.stringify(data.tools) : null,\n skills_json: data.skills ? JSON.stringify(data.skills) : null,\n // Memory\n memory_enabled: data.memoryEnabled || false,\n memory_window: data.memoryWindow || 10,\n // Classification\n namespace: data.namespace || 'default',\n // Package management\n package_id: data.packageId || null,\n managed_by: data.managedBy || 'user',\n // Audit\n created_by: data.createdBy || null,\n created_at: data.createdAt || now,\n updated_by: data.updatedBy || null,\n updated_at: now,\n };\n }\n\n /**\n * Project tool metadata to sys_tool\n */\n private projectTool(name: string, data: any, now: string): Record<string, any> {\n return {\n name,\n project_id: this.scope.projectId ?? null,\n label: data.label || name,\n description: data.description || '',\n // Parameters and implementation\n parameters_json: data.parameters ? JSON.stringify(data.parameters) : null,\n handler_code: data.handler || null,\n // Classification\n namespace: data.namespace || 'default',\n // Package management\n package_id: data.packageId || null,\n managed_by: data.managedBy || 'user',\n // Audit\n created_by: data.createdBy || null,\n created_at: data.createdAt || now,\n updated_by: data.updatedBy || null,\n updated_at: now,\n };\n }\n\n /**\n * Project flow metadata to sys_flow\n */\n private projectFlow(name: string, data: any, now: string): Record<string, any> {\n return {\n name,\n project_id: this.scope.projectId ?? null,\n label: data.label || name,\n description: data.description || '',\n flow_type: data.type || 'autolaunched',\n // Flow definition\n nodes_json: data.nodes ? JSON.stringify(data.nodes) : null,\n edges_json: data.edges ? JSON.stringify(data.edges) : null,\n variables_json: data.variables ? JSON.stringify(data.variables) : null,\n // Trigger configuration\n trigger_type: data.triggerType || null,\n trigger_object: data.triggerObject || null,\n // Status\n active: data.active || false,\n // Classification\n namespace: data.namespace || 'default',\n // Package management\n package_id: data.packageId || null,\n managed_by: data.managedBy || 'user',\n // Audit\n created_by: data.createdBy || null,\n created_at: data.createdAt || now,\n updated_by: data.updatedBy || null,\n updated_at: now,\n };\n }\n\n // ==========================================\n // Internal CRUD helpers (driver vs engine)\n // ==========================================\n\n private async _findOne(table: string, query: Record<string, unknown>): Promise<Record<string, unknown> | null> {\n if (this.engine) {\n return this.engine.findOne(table, query as any);\n }\n return this.driver!.findOne(table, { object: table, ...query } as any);\n }\n\n private async _create(table: string, data: Record<string, unknown>): Promise<Record<string, unknown>> {\n if (this.engine) {\n return this.engine.insert(table, data);\n }\n return this.driver!.create(table, data);\n }\n\n private async _update(table: string, id: string, data: Record<string, unknown>): Promise<Record<string, unknown>> {\n if (this.engine) {\n return this.engine.update(table, { id, ...data });\n }\n return this.driver!.update(table, id, data);\n }\n\n private async _delete(table: string, id: string): Promise<any> {\n if (this.engine) {\n return this.engine.delete(table, { where: { id } } as any);\n }\n return this.driver!.delete(table, id);\n }\n\n /**\n * Generate a simple unique ID\n */\n private generateId(): string {\n if (typeof globalThis.crypto !== 'undefined' && typeof globalThis.crypto.randomUUID === 'function') {\n return globalThis.crypto.randomUUID();\n }\n return `proj_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { readFile } from 'node:fs/promises';\nimport { createHash } from 'node:crypto';\nimport { Plugin, PluginContext } from '@objectstack/core';\nimport { NodeMetadataManager } from './node-metadata-manager.js';\nimport { MemoryLoader } from './loaders/memory-loader.js';\nimport { DEFAULT_METADATA_TYPE_REGISTRY } from '@objectstack/spec/kernel';\nimport type { MetadataPluginConfig } from '@objectstack/spec/kernel';\nimport {\n SysAgent,\n SysFlow,\n SysObject,\n SysTool,\n SysView,\n} from '@objectstack/platform-objects/metadata';\n\nconst queryableMetadataObjects = [SysObject, SysView, SysFlow, SysAgent, SysTool];\n\n// Map from ObjectStackDefinition field name to MetadataType name\nconst ARTIFACT_FIELD_TO_TYPE: Record<string, string> = {\n objects: 'object',\n objectExtensions: 'object_extension',\n apps: 'app',\n views: 'view',\n pages: 'page',\n dashboards: 'dashboard',\n reports: 'report',\n actions: 'action',\n themes: 'theme',\n workflows: 'workflow',\n approvals: 'approval',\n flows: 'flow',\n roles: 'role',\n permissions: 'permission',\n sharingRules: 'sharing_rule',\n policies: 'policy',\n apis: 'api',\n webhooks: 'webhook',\n agents: 'agent',\n skills: 'skill',\n ragPipelines: 'rag_pipeline',\n hooks: 'hook',\n mappings: 'mapping',\n analyticsCubes: 'analytics_cube',\n connectors: 'connector',\n data: 'dataset',\n};\n\nexport interface MetadataPluginOptions {\n rootDir?: string;\n watch?: boolean;\n config?: Partial<MetadataPluginConfig>;\n /** Organization ID for metadata-scoped consumers; MetadataPlugin itself does not persist runtime metadata. */\n organizationId?: string;\n /** Project ID used by local artifact envelopes and metadata-scoped consumers. */\n projectId?: string;\n /**\n * When set, MetadataPlugin loads metadata from an artifact instead of scanning\n * the filesystem. Only `local-file` is implemented now; `artifact-api` is\n * reserved for M3/M4.\n */\n artifactSource?: { mode: 'local-file'; path: string } | { mode: 'artifact-api'; url: string };\n /**\n * Register the queryable system metadata-storage objects\n * (`sys_object`, `sys_view`, `sys_flow`, `sys_agent`, `sys_tool`) on this\n * kernel. Default `true` for backward compatibility.\n *\n * Set to `false` for **per-project** kernels: in cloud / project mode the\n * control plane is the sole owner of metadata storage tables — exposing\n * them inside each project kernel would leak control-plane schema into\n * business-data namespaces.\n */\n registerSystemObjects?: boolean;\n}\n\nexport class MetadataPlugin implements Plugin {\n name = 'com.objectstack.metadata';\n type = 'standard';\n version = '1.0.0';\n\n private manager: NodeMetadataManager;\n private options: MetadataPluginOptions;\n\n constructor(options: MetadataPluginOptions = {}) {\n this.options = {\n watch: true,\n ...options\n };\n\n const rootDir = this.options.rootDir || process.cwd();\n\n this.manager = new NodeMetadataManager({\n rootDir,\n watch: this.options.watch ?? true,\n formats: ['yaml', 'json', 'typescript', 'javascript']\n });\n\n // Initialize with default type registry\n this.manager.setTypeRegistry(DEFAULT_METADATA_TYPE_REGISTRY);\n }\n\n init = async (ctx: PluginContext) => {\n ctx.logger.info('Initializing Metadata Manager', {\n root: this.options.rootDir || process.cwd(),\n watch: this.options.watch,\n artifactSource: this.options.artifactSource?.mode,\n });\n\n // Register Metadata Manager as the primary metadata service provider.\n ctx.registerService('metadata', this.manager);\n console.log('[MetadataPlugin] Registered metadata service, has getRegisteredTypes:', typeof this.manager.getRegisteredTypes);\n\n // Register metadata system objects via the manifest service (if available).\n // MetadataPlugin may init before ObjectQLPlugin, so wrap in try/catch.\n // Skipped when `registerSystemObjects: false` (per-project kernels in\n // cloud / project mode — sys_* live exclusively in the control plane).\n const registerSysObjects = this.options.registerSystemObjects !== false;\n if (registerSysObjects) {\n try {\n const manifestService = ctx.getService<{ register(m: any): void }>('manifest');\n\n // Register the queryable metadata-layer platform objects.\n manifestService.register({\n id: 'com.objectstack.metadata-objects',\n name: 'Metadata Platform Objects',\n version: '1.0.0',\n type: 'plugin',\n scope: 'system',\n defaultDatasource: 'cloud',\n objects: queryableMetadataObjects,\n });\n\n ctx.logger.info('Registered system metadata objects', {\n queryable: queryableMetadataObjects.map((object) => object.name),\n });\n } catch {\n // ObjectQL not loaded yet — objects will be discovered via legacy fallback\n }\n }\n\n ctx.logger.info('MetadataPlugin providing metadata service (primary mode)', {\n mode: this.options.artifactSource?.mode ?? 'file-system',\n features: ['watch', 'multi-format', 'query', 'overlay', 'type-registry']\n });\n }\n\n start = async (ctx: PluginContext) => {\n const src = this.options.artifactSource;\n\n if (src?.mode === 'local-file') {\n await this._loadFromLocalFile(ctx, src.path);\n } else if (src?.mode === 'artifact-api') {\n // M3/M4 — not yet implemented\n ctx.logger.warn('[MetadataPlugin] artifact-api source is not yet implemented; falling back to file-system scan');\n await this._loadFromFileSystem(ctx);\n } else {\n await this._loadFromFileSystem(ctx);\n }\n\n // Bridge realtime service from kernel service registry to MetadataManager.\n try {\n const realtimeService = ctx.getService('realtime');\n if (realtimeService && typeof realtimeService === 'object' && 'publish' in realtimeService) {\n ctx.logger.info('[MetadataPlugin] Bridging realtime service to MetadataManager for event publishing');\n this.manager.setRealtimeService(realtimeService as any);\n }\n } catch (e: any) {\n ctx.logger.debug('[MetadataPlugin] No realtime service found — metadata events will not be published', {\n error: e.message,\n });\n }\n }\n\n private async _loadFromLocalFile(ctx: PluginContext, filePath: string): Promise<void> {\n const isUrl = /^https?:\\/\\//i.test(filePath);\n ctx.logger.info(\n `[MetadataPlugin] Loading metadata from ${isUrl ? 'remote URL' : 'local artifact file'}`,\n { path: filePath },\n );\n\n let raw: unknown;\n try {\n let content: string;\n if (isUrl) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 15_000);\n try {\n const res = await fetch(filePath, {\n redirect: 'follow',\n signal: controller.signal,\n headers: { Accept: 'application/json, */*;q=0.5' },\n });\n if (!res.ok) {\n throw new Error(`HTTP ${res.status} ${res.statusText}`);\n }\n content = await res.text();\n } finally {\n clearTimeout(timer);\n }\n } else {\n content = await readFile(filePath, 'utf8');\n }\n raw = JSON.parse(content);\n } catch (e: any) {\n throw new Error(`[MetadataPlugin] Cannot read artifact ${isUrl ? 'URL' : 'file'} at \"${filePath}\": ${e.message}`);\n }\n\n // Dynamically import to avoid pulling @objectstack/spec/cloud into every\n // bundle — it includes heavy Zod schemas and is only needed in local mode.\n const { ProjectArtifactSchema } = await import('@objectstack/spec/cloud');\n const { ObjectStackDefinitionSchema } = await import('@objectstack/spec');\n\n let metadata: Record<string, unknown[]>;\n\n // Detect envelope vs bare ObjectStackDefinition.\n const obj = raw as any;\n if (obj?.schemaVersion && obj?.commitId && obj?.metadata !== undefined) {\n // Already an artifact envelope — validate and unwrap.\n const artifact = ProjectArtifactSchema.parse(obj);\n metadata = artifact.metadata as Record<string, unknown[]>;\n } else {\n // Bare ObjectStackDefinition produced by `objectstack compile`.\n const def = ObjectStackDefinitionSchema.parse(obj);\n const canonical = JSON.stringify(def, Object.keys(def).sort());\n const checksum = createHash('sha256').update(canonical).digest('hex');\n const projectId = this.options.projectId ?? 'proj_local';\n // Wrap into envelope and validate to confirm the structure is correct.\n ProjectArtifactSchema.parse({\n schemaVersion: '0.1',\n projectId,\n commitId: 'local-dev',\n checksum,\n metadata: def,\n });\n metadata = def as Record<string, unknown[]>;\n }\n\n // Register artifact items into a MemoryLoader so they are visible to\n // both `loadMany()` (used by ObjectQL's sync path) and `list()` (used\n // by REST meta endpoints). `register()` alone only writes to the in-memory\n // registry Map which `loadMany()` does not read.\n //\n // The artifact format flattens packages into top-level arrays\n // (`objects`, `views`, …) without per-item provenance. The package id\n // lives only on `metadata.manifest.id`. We tag each item with\n // `_packageId` here so REST list responses can carry it through —\n // Studio's metadata sidebar uses this tag to compute the package\n // path needed for record navigation.\n const memLoader = new MemoryLoader();\n const manifestPackageId =\n (metadata as any)?.manifest?.id ?? (metadata as any)?.id ?? undefined;\n\n let totalRegistered = 0;\n for (const [field, metaType] of Object.entries(ARTIFACT_FIELD_TO_TYPE)) {\n const items = (metadata as any)[field];\n if (!Array.isArray(items) || items.length === 0) continue;\n for (const item of items) {\n const name = (item as any)?.name;\n if (!name) continue;\n // Tag with owning package id (idempotent: respect existing tag).\n if (manifestPackageId && (item as any)._packageId === undefined) {\n (item as any)._packageId = manifestPackageId;\n }\n await memLoader.save(metaType, name, item);\n await this.manager.register(metaType, name, item);\n totalRegistered++;\n }\n }\n\n // Mount the loader so `loadMany` queries hit it.\n this.manager.registerLoader(memLoader);\n\n ctx.logger.info('[MetadataPlugin] Artifact metadata loaded', {\n path: filePath,\n totalRegistered,\n });\n }\n\n private async _loadFromFileSystem(ctx: PluginContext): Promise<void> {\n ctx.logger.info('Loading metadata from file system...');\n\n const sortedTypes = [...DEFAULT_METADATA_TYPE_REGISTRY]\n .sort((a, b) => a.loadOrder - b.loadOrder);\n\n let totalLoaded = 0;\n for (const entry of sortedTypes) {\n try {\n const items = await this.manager.loadMany(entry.type, {\n recursive: true,\n patterns: entry.filePatterns,\n });\n\n if (items.length > 0) {\n for (const item of items) {\n const meta = item as any;\n if (meta?.name) {\n await this.manager.register(entry.type, meta.name, item);\n }\n }\n ctx.logger.info(`Loaded ${items.length} ${entry.type} from file system`);\n totalLoaded += items.length;\n }\n } catch (e: any) {\n ctx.logger.debug(`No ${entry.type} metadata found`, { error: e.message });\n }\n }\n\n ctx.logger.info('Metadata loading complete', {\n totalItems: totalLoaded,\n registeredTypes: sortedTypes.length,\n });\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Node Metadata Manager\n * \n * Extends MetadataManager with Filesystem capabilities (Watching, default loader)\n */\n\nimport * as path from 'node:path';\nimport { watch as chokidarWatch, type FSWatcher } from 'chokidar';\nimport type {\n MetadataWatchEvent,\n} from '@objectstack/spec/system';\nimport { FilesystemLoader } from './loaders/filesystem-loader.js';\nimport { MetadataManager, type MetadataManagerOptions } from './metadata-manager.js';\n\n/**\n * Node metadata manager class\n */\nexport class NodeMetadataManager extends MetadataManager {\n private watcher?: FSWatcher;\n\n constructor(config: MetadataManagerOptions) {\n super(config);\n\n // Initialize Default Filesystem Loader if no loaders provided\n // This logic replaces the removed logic from base class\n if (!config.loaders || config.loaders.length === 0) {\n const rootDir = config.rootDir || process.cwd();\n this.registerLoader(new FilesystemLoader(rootDir, this.serializers, this.logger));\n }\n\n // Start watching if enabled\n if (config.watch) {\n this.startWatching();\n }\n }\n\n /**\n * Stop all watching\n */\n async stopWatching(): Promise<void> {\n if (this.watcher) {\n await this.watcher.close();\n this.watcher = undefined;\n }\n // Call base cleanup if any\n }\n\n /**\n * Start watching for file changes\n */\n private startWatching(): void {\n const rootDir = this.config.rootDir || process.cwd();\n const { ignored = ['**/node_modules/**', '**/*.test.*'], persistent = true } =\n this.config.watchOptions || {};\n\n this.watcher = chokidarWatch(rootDir, {\n ignored,\n persistent,\n ignoreInitial: true,\n });\n\n this.watcher.on('add', async (filePath) => {\n await this.handleFileEvent('added', filePath);\n });\n\n this.watcher.on('change', async (filePath) => {\n await this.handleFileEvent('changed', filePath);\n });\n\n this.watcher.on('unlink', async (filePath) => {\n await this.handleFileEvent('deleted', filePath);\n });\n\n this.logger.info('File watcher started', { rootDir });\n }\n\n /**\n * Handle file change events\n */\n private async handleFileEvent(\n eventType: 'added' | 'changed' | 'deleted',\n filePath: string\n ): Promise<void> {\n const rootDir = this.config.rootDir || process.cwd();\n const relativePath = path.relative(rootDir, filePath);\n const parts = relativePath.split(path.sep);\n\n if (parts.length < 2) {\n return; // Not a metadata file\n }\n\n const type = parts[0];\n const fileName = parts[parts.length - 1];\n const name = path.basename(fileName, path.extname(fileName));\n\n // We can't access private watchCallbacks from parent.\n // We need a protected method to trigger watch event or access it.\n // OPTION: Add a method `triggerWatchEvent` to MetadataManager\n \n let data: any = undefined;\n if (eventType !== 'deleted') {\n try {\n data = await this.load(type, name, { useCache: false });\n } catch (error) {\n this.logger.error('Failed to load changed file', undefined, {\n filePath,\n error: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const event: MetadataWatchEvent = {\n type: eventType,\n metadataType: type,\n name,\n path: filePath,\n data,\n timestamp: new Date().toISOString(),\n };\n\n this.notifyWatchers(type, event);\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Filesystem Metadata Loader\n * \n * Loads metadata from the filesystem using glob patterns\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { glob } from 'glob';\nimport { createHash } from 'node:crypto';\nimport type {\n MetadataLoadOptions,\n MetadataLoadResult,\n MetadataStats,\n MetadataLoaderContract,\n MetadataFormat,\n MetadataSaveOptions,\n MetadataSaveResult,\n} from '@objectstack/spec/system';\nimport type { Logger } from '@objectstack/core';\nimport type { MetadataLoader } from './loader-interface.js';\nimport type { MetadataSerializer } from '../serializers/serializer-interface.js';\n\nexport class FilesystemLoader implements MetadataLoader {\n readonly contract: MetadataLoaderContract = {\n name: 'filesystem',\n protocol: 'file:',\n capabilities: {\n read: true,\n write: true,\n watch: true,\n list: true,\n },\n supportedFormats: ['json', 'yaml', 'typescript', 'javascript'],\n supportsWatch: true,\n supportsWrite: true,\n supportsCache: true,\n };\n\n private cache = new Map<string, { data: any; etag: string; timestamp: number }>();\n\n constructor(\n private rootDir: string,\n private serializers: Map<MetadataFormat, MetadataSerializer>,\n private logger?: Logger\n ) {}\n\n async load(\n type: string,\n name: string,\n options?: MetadataLoadOptions\n ): Promise<MetadataLoadResult> {\n const startTime = Date.now();\n const { validate: _validate = true, useCache = true, ifNoneMatch } = options || {};\n\n try {\n // Find the file\n const filePath = await this.findFile(type, name);\n\n if (!filePath) {\n return {\n data: null,\n fromCache: false,\n notModified: false,\n loadTime: Date.now() - startTime,\n };\n }\n\n // Get stats\n const stats = await this.stat(type, name);\n\n if (!stats) {\n return {\n data: null,\n fromCache: false,\n notModified: false,\n loadTime: Date.now() - startTime,\n };\n }\n\n // Check cache\n if (useCache && ifNoneMatch && stats.etag === ifNoneMatch) {\n return {\n data: null,\n fromCache: true,\n notModified: true,\n etag: stats.etag,\n stats,\n loadTime: Date.now() - startTime,\n };\n }\n\n // Check memory cache\n const cacheKey = `${type}:${name}`;\n if (useCache && this.cache.has(cacheKey)) {\n const cached = this.cache.get(cacheKey)!;\n if (cached.etag === stats.etag) {\n return {\n data: cached.data,\n fromCache: true,\n notModified: false,\n etag: stats.etag,\n stats,\n loadTime: Date.now() - startTime,\n };\n }\n }\n\n // Load and deserialize\n const content = await fs.readFile(filePath, 'utf-8');\n const serializer = this.getSerializer(stats.format!);\n\n if (!serializer) {\n throw new Error(`No serializer found for format: ${stats.format}`);\n }\n\n const data = serializer.deserialize(content);\n\n // Update cache\n if (useCache) {\n this.cache.set(cacheKey, {\n data,\n etag: stats.etag || '',\n timestamp: Date.now(),\n });\n }\n\n return {\n data,\n fromCache: false,\n notModified: false,\n etag: stats.etag,\n stats,\n loadTime: Date.now() - startTime,\n };\n } catch (error) {\n this.logger?.error('Failed to load metadata', undefined, {\n type,\n name,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n async loadMany<T = any>(\n type: string,\n options?: MetadataLoadOptions\n ): Promise<T[]> {\n const { patterns = ['**/*'], recursive: _recursive = true, limit } = options || {};\n\n const typeDir = path.join(this.rootDir, type);\n const items: T[] = [];\n\n try {\n // Build glob patterns\n const globPatterns = patterns.map(pattern =>\n path.join(typeDir, pattern)\n );\n\n for (const pattern of globPatterns) {\n const files = await glob(pattern, {\n ignore: ['**/node_modules/**', '**/*.test.*', '**/*.spec.*', '**/*[*]*'],\n nodir: true,\n });\n\n for (const file of files) {\n if (limit && items.length >= limit) {\n break;\n }\n\n try {\n const content = await fs.readFile(file, 'utf-8');\n const format = this.detectFormat(file);\n const serializer = this.getSerializer(format);\n\n if (serializer) {\n const data = serializer.deserialize<T>(content);\n items.push(data);\n }\n } catch (error) {\n this.logger?.warn('Failed to load file', {\n file,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n if (limit && items.length >= limit) {\n break;\n }\n }\n\n return items;\n } catch (error) {\n this.logger?.error('Failed to load many', undefined, {\n type,\n patterns,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n async exists(type: string, name: string): Promise<boolean> {\n const filePath = await this.findFile(type, name);\n return filePath !== null;\n }\n\n async stat(type: string, name: string): Promise<MetadataStats | null> {\n const filePath = await this.findFile(type, name);\n\n if (!filePath) {\n return null;\n }\n\n try {\n const stats = await fs.stat(filePath);\n const content = await fs.readFile(filePath, 'utf-8');\n const etag = this.generateETag(content);\n const format = this.detectFormat(filePath);\n\n return {\n size: stats.size,\n modifiedAt: stats.mtime.toISOString(),\n etag,\n format,\n path: filePath,\n };\n } catch (error) {\n this.logger?.error('Failed to stat file', undefined, {\n type,\n name,\n filePath,\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n }\n\n async list(type: string): Promise<string[]> {\n const typeDir = path.join(this.rootDir, type);\n\n try {\n const files = await glob('**/*', {\n cwd: typeDir,\n ignore: ['**/node_modules/**', '**/*.test.*', '**/*.spec.*'],\n nodir: true,\n });\n\n return files.map(file => {\n const ext = path.extname(file);\n const basename = path.basename(file, ext);\n return basename;\n });\n } catch (error) {\n this.logger?.error('Failed to list', undefined, {\n type,\n error: error instanceof Error ? error.message : String(error),\n });\n return [];\n }\n }\n\n async save(\n type: string,\n name: string,\n data: any,\n options?: MetadataSaveOptions\n ): Promise<MetadataSaveResult> {\n const startTime = Date.now();\n const {\n format = 'typescript',\n prettify = true,\n indent = 2,\n sortKeys = false,\n backup = false,\n overwrite = true,\n atomic = true,\n path: customPath,\n } = options || {};\n\n try {\n // Get serializer\n const serializer = this.getSerializer(format);\n if (!serializer) {\n throw new Error(`No serializer found for format: ${format}`);\n }\n\n // Determine file path\n const typeDir = path.join(this.rootDir, type);\n const fileName = `${name}${serializer.getExtension()}`;\n const filePath = customPath || path.join(typeDir, fileName);\n\n // Check if file exists\n if (!overwrite) {\n try {\n await fs.access(filePath);\n throw new Error(`File already exists: ${filePath}`);\n } catch (error) {\n // File doesn't exist, continue\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error;\n }\n }\n }\n\n // Create directory if it doesn't exist\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n\n // Create backup if requested\n let backupPath: string | undefined;\n if (backup) {\n try {\n await fs.access(filePath);\n backupPath = `${filePath}.bak`;\n await fs.copyFile(filePath, backupPath);\n } catch {\n // File doesn't exist, no backup needed\n }\n }\n\n // Serialize data\n const content = serializer.serialize(data, {\n prettify,\n indent,\n sortKeys,\n });\n\n // Write to disk (atomic or direct)\n if (atomic) {\n const tempPath = `${filePath}.tmp`;\n await fs.writeFile(tempPath, content, 'utf-8');\n await fs.rename(tempPath, filePath);\n } else {\n await fs.writeFile(filePath, content, 'utf-8');\n }\n\n // Update cache logic if needed (e.g., invalidate or update)\n // For now, we rely on the watcher to pick up changes\n\n return {\n success: true,\n path: filePath,\n // format, // Not in schema\n size: Buffer.byteLength(content, 'utf-8'),\n backupPath,\n saveTime: Date.now() - startTime,\n };\n } catch (error) {\n this.logger?.error('Failed to save metadata', undefined, {\n type,\n name,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n /**\n * Find file for a given type and name\n */\n private async findFile(type: string, name: string): Promise<string | null> {\n const typeDir = path.join(this.rootDir, type);\n const extensions = ['.json', '.yaml', '.yml', '.ts', '.js'];\n\n for (const ext of extensions) {\n const filePath = path.join(typeDir, `${name}${ext}`);\n\n try {\n await fs.access(filePath);\n return filePath;\n } catch {\n // File doesn't exist, try next extension\n }\n }\n\n return null;\n }\n\n /**\n * Detect format from file extension\n */\n private detectFormat(filePath: string): MetadataFormat {\n const ext = path.extname(filePath).toLowerCase();\n\n switch (ext) {\n case '.json':\n return 'json';\n case '.yaml':\n case '.yml':\n return 'yaml';\n case '.ts':\n return 'typescript';\n case '.js':\n return 'javascript';\n default:\n return 'json'; // Default to JSON\n }\n }\n\n /**\n * Get serializer for format\n */\n private getSerializer(format: MetadataFormat): MetadataSerializer | undefined {\n return this.serializers.get(format);\n }\n\n /**\n * Generate ETag for content\n * Uses SHA-256 hash truncated to 32 characters for reasonable collision resistance\n * while keeping ETag headers compact (full 64-char hash is overkill for this use case)\n */\n private generateETag(content: string): string {\n const hash = createHash('sha256').update(content).digest('hex').substring(0, 32);\n return `\"${hash}\"`;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Memory Metadata Loader\n * \n * Stores metadata in memory only. Changes are lost when process restarts.\n * Useful for testing, temporary overrides, or \"dirty\" edits.\n */\n\nimport type {\n MetadataLoadOptions,\n MetadataLoadResult,\n MetadataStats,\n MetadataLoaderContract,\n MetadataSaveOptions,\n MetadataSaveResult,\n} from '@objectstack/spec/system';\nimport type { MetadataLoader } from './loader-interface.js';\n\nexport class MemoryLoader implements MetadataLoader {\n readonly contract: MetadataLoaderContract = {\n name: 'memory',\n protocol: 'memory:',\n capabilities: {\n read: true,\n write: true,\n watch: false,\n list: true,\n },\n };\n\n // Storage: Type -> Name -> Data\n private storage = new Map<string, Map<string, any>>();\n\n async load(\n type: string,\n name: string,\n _options?: MetadataLoadOptions\n ): Promise<MetadataLoadResult> {\n const typeStore = this.storage.get(type);\n const data = typeStore?.get(name);\n\n if (data) {\n return {\n data,\n source: 'memory',\n format: 'json',\n loadTime: 0,\n };\n }\n\n return { data: null };\n }\n\n async loadMany<T = any>(\n type: string,\n _options?: MetadataLoadOptions\n ): Promise<T[]> {\n const typeStore = this.storage.get(type);\n if (!typeStore) return [];\n return Array.from(typeStore.values()) as T[];\n }\n\n async exists(type: string, name: string): Promise<boolean> {\n return this.storage.get(type)?.has(name) ?? false;\n }\n\n async stat(type: string, name: string): Promise<MetadataStats | null> {\n if (await this.exists(type, name)) {\n return {\n size: 0, // In-memory\n mtime: new Date().toISOString(),\n format: 'json',\n };\n }\n return null;\n }\n\n async list(type: string): Promise<string[]> {\n const typeStore = this.storage.get(type);\n if (!typeStore) return [];\n return Array.from(typeStore.keys());\n }\n\n async save(\n type: string,\n name: string,\n data: any,\n _options?: MetadataSaveOptions\n ): Promise<MetadataSaveResult> {\n if (!this.storage.has(type)) {\n this.storage.set(type, new Map());\n }\n\n this.storage.get(type)!.set(name, data);\n\n return {\n success: true,\n path: `memory://${type}/${name}`,\n saveTime: 0,\n };\n }\n\n /**\n * Delete a metadata item from memory storage\n */\n async delete(type: string, name: string): Promise<void> {\n const typeStore = this.storage.get(type);\n if (typeStore) {\n typeStore.delete(name);\n if (typeStore.size === 0) {\n this.storage.delete(type);\n }\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Remote Metadata Loader\n * \n * Loads metadata from an HTTP API.\n * This loader is stateless and delegates storage to the remote server.\n */\n\nimport type {\n MetadataLoadOptions,\n MetadataLoadResult,\n MetadataStats,\n MetadataLoaderContract,\n MetadataSaveOptions,\n MetadataSaveResult,\n} from '@objectstack/spec/system';\nimport type { MetadataLoader } from './loader-interface.js';\n\nexport class RemoteLoader implements MetadataLoader {\n readonly contract: MetadataLoaderContract = {\n name: 'remote',\n protocol: 'http:',\n capabilities: {\n read: true,\n write: true,\n watch: false, // Could implement SSE/WebSocket in future\n list: true,\n },\n };\n\n constructor(private baseUrl: string, private authToken?: string) {}\n\n private get headers() {\n return {\n 'Content-Type': 'application/json',\n ...(this.authToken ? { Authorization: `Bearer ${this.authToken}` } : {}),\n };\n }\n\n async load(\n type: string,\n name: string,\n _options?: MetadataLoadOptions\n ): Promise<MetadataLoadResult> {\n try {\n const response = await fetch(`${this.baseUrl}/${type}/${name}`, {\n method: 'GET',\n headers: this.headers,\n });\n\n if (response.status === 404) {\n return { data: null };\n }\n\n if (!response.ok) {\n throw new Error(`Remote load failed: ${response.statusText}`);\n }\n\n const data = await response.json();\n return {\n data,\n source: this.baseUrl,\n format: 'json',\n loadTime: 0, \n };\n } catch (error) {\n console.error(`RemoteLoader error loading ${type}/${name}`, error);\n throw error;\n }\n }\n\n async loadMany<T = any>(\n type: string,\n _options?: MetadataLoadOptions\n ): Promise<T[]> {\n const response = await fetch(`${this.baseUrl}/${type}`, {\n method: 'GET',\n headers: this.headers,\n });\n\n if (!response.ok) {\n return [];\n }\n\n return (await response.json()) as T[];\n }\n\n async exists(type: string, name: string): Promise<boolean> {\n const response = await fetch(`${this.baseUrl}/${type}/${name}`, {\n method: 'HEAD',\n headers: this.headers,\n });\n return response.ok;\n }\n\n async stat(type: string, name: string): Promise<MetadataStats | null> {\n // Basic implementation using HEAD\n const response = await fetch(`${this.baseUrl}/${type}/${name}`, {\n method: 'HEAD',\n headers: this.headers,\n });\n \n if (!response.ok) return null;\n\n return {\n size: Number(response.headers.get('content-length') || 0),\n mtime: new Date(response.headers.get('last-modified') || Date.now()).toISOString(),\n format: 'json',\n };\n }\n\n async list(type: string): Promise<string[]> {\n const items = await this.loadMany<{ name: string }>(type);\n return items.map(i => i.name);\n }\n\n async save(\n type: string,\n name: string,\n data: any,\n _options?: MetadataSaveOptions\n ): Promise<MetadataSaveResult> {\n const response = await fetch(`${this.baseUrl}/${type}/${name}`, {\n method: 'PUT',\n headers: this.headers,\n body: JSON.stringify(data),\n });\n\n if (!response.ok) {\n throw new Error(`Remote save failed: ${response.statusText}`);\n }\n\n return {\n success: true,\n path: `${this.baseUrl}/${type}/${name}`,\n saveTime: 0,\n };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/metadata\n * \n * Metadata loading, saving, and persistence for ObjectStack.\n * Implements the IMetadataService contract from @objectstack/spec.\n */\n\n// Main Manager\nexport { MetadataManager, type WatchCallback, type MetadataManagerOptions } from './metadata-manager.js';\n\n// Plugin\nexport { MetadataPlugin } from './plugin.js';\n\n// Projection\nexport { MetadataProjector, type MetadataProjectorOptions } from './projection/index.js';\n\n// Loaders\nexport { type MetadataLoader } from './loaders/loader-interface.js';\nexport { MemoryLoader } from './loaders/memory-loader.js';\nexport { RemoteLoader } from './loaders/remote-loader.js';\nexport { DatabaseLoader, type DatabaseLoaderOptions } from './loaders/database-loader.js';\n\n// Objects\nexport { SysMetadataObject, SysMetadataHistoryObject } from '@objectstack/platform-objects/metadata';\n\n// Routes\nexport { registerMetadataHistoryRoutes } from './routes/history-routes.js';\n\n// Utils\nexport { calculateChecksum, generateSimpleDiff, generateDiffSummary } from './utils/metadata-history-utils.js';\nexport { HistoryCleanupManager } from './utils/history-cleanup.js';\n\n// Serializers\nexport { type MetadataSerializer, type SerializeOptions } from './serializers/serializer-interface.js';\nexport { JSONSerializer } from './serializers/json-serializer.js';\nexport { YAMLSerializer } from './serializers/yaml-serializer.js';\nexport * as Migration from './migration/index.js';\nexport { TypeScriptSerializer } from './serializers/typescript-serializer.js';\n\n// Re-export types from spec\nexport type {\n MetadataFormat,\n MetadataStats,\n MetadataLoadOptions,\n MetadataSaveOptions,\n MetadataExportOptions,\n MetadataImportOptions,\n MetadataLoadResult,\n MetadataSaveResult,\n MetadataWatchEvent,\n MetadataCollectionInfo,\n MetadataLoaderContract,\n MetadataManagerConfig,\n MetadataHistoryRecord,\n MetadataHistoryQueryOptions,\n MetadataHistoryQueryResult,\n MetadataDiffResult,\n MetadataHistoryRetentionPolicy,\n} from '@objectstack/spec/system';\n\n// Re-export IMetadataService contract\nexport type {\n IMetadataService,\n MetadataWatchCallback,\n MetadataWatchHandle,\n MetadataTypeInfo,\n MetadataImportResult,\n} from '@objectstack/spec/contracts';\n\n// Re-export kernel types for plugin protocol\nexport type {\n MetadataType,\n MetadataTypeRegistryEntry,\n MetadataPluginConfig,\n MetadataPluginManifest,\n MetadataQuery,\n MetadataQueryResult,\n MetadataValidationResult,\n MetadataBulkResult,\n MetadataDependency,\n} from '@objectstack/spec/kernel';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata History API Routes\n *\n * REST API endpoints for metadata version history, rollback, and diff operations.\n * These routes extend the standard metadata API with history-specific functionality.\n *\n * Routes:\n * - GET /api/v1/metadata/:type/:name/history - Get version history\n * - POST /api/v1/metadata/:type/:name/rollback - Rollback to a specific version\n * - GET /api/v1/metadata/:type/:name/diff - Compare two versions\n */\n\nimport type { IMetadataService } from '@objectstack/spec/contracts';\n\n/**\n * Register metadata history routes on a Hono app or any HTTP server.\n *\n * @param app - The HTTP server/router instance (Hono-compatible)\n * @param metadataService - The metadata service instance\n */\nexport function registerMetadataHistoryRoutes(\n app: any, // Hono app or compatible\n metadataService: IMetadataService\n): void {\n /**\n * GET /api/v1/metadata/:type/:name/history\n * Get version history for a metadata item\n *\n * Query parameters:\n * - limit: number (default: 50)\n * - offset: number (default: 0)\n * - since: ISO datetime string\n * - until: ISO datetime string\n * - operationType: create | update | publish | revert | delete\n * - includeMetadata: boolean (default: true)\n */\n app.get('/api/v1/metadata/:type/:name/history', async (c: any) => {\n if (!metadataService.getHistory) {\n return c.json({ error: 'History tracking not enabled' }, 501);\n }\n\n const { type, name } = c.req.param();\n const query = c.req.query();\n\n try {\n const options: any = {};\n\n if (query.limit !== undefined) {\n const limit = parseInt(query.limit, 10);\n if (!Number.isFinite(limit) || limit < 1) {\n return c.json({ success: false, error: 'limit must be a positive integer' }, 400);\n }\n options.limit = limit;\n }\n if (query.offset !== undefined) {\n const offset = parseInt(query.offset, 10);\n if (!Number.isFinite(offset) || offset < 0) {\n return c.json({ success: false, error: 'offset must be a non-negative integer' }, 400);\n }\n options.offset = offset;\n }\n if (query.since) options.since = query.since;\n if (query.until) options.until = query.until;\n if (query.operationType) options.operationType = query.operationType;\n if (query.includeMetadata !== undefined) {\n options.includeMetadata = query.includeMetadata === 'true';\n }\n\n const result = await metadataService.getHistory(type, name, options);\n\n return c.json({\n success: true,\n data: result,\n });\n } catch (error) {\n return c.json(\n {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve history',\n },\n 500\n );\n }\n });\n\n /**\n * POST /api/v1/metadata/:type/:name/rollback\n * Rollback a metadata item to a specific version\n *\n * Body:\n * - version: number (required) - Target version to rollback to\n * - changeNote: string (optional) - Description of rollback\n * - recordedBy: string (optional) - User performing rollback\n */\n app.post('/api/v1/metadata/:type/:name/rollback', async (c: any) => {\n if (!metadataService.rollback) {\n return c.json({ error: 'Rollback not supported' }, 501);\n }\n\n const { type, name } = c.req.param();\n\n try {\n const body = await c.req.json();\n const { version, changeNote, recordedBy } = body;\n\n if (typeof version !== 'number') {\n return c.json(\n {\n success: false,\n error: 'Version number is required',\n },\n 400\n );\n }\n\n const restoredMetadata = await metadataService.rollback(type, name, version, {\n changeNote,\n recordedBy,\n });\n\n return c.json({\n success: true,\n data: {\n type,\n name,\n version,\n metadata: restoredMetadata,\n },\n });\n } catch (error) {\n return c.json(\n {\n success: false,\n error: error instanceof Error ? error.message : 'Rollback failed',\n },\n 500\n );\n }\n });\n\n /**\n * GET /api/v1/metadata/:type/:name/diff\n * Compare two versions of a metadata item\n *\n * Query parameters:\n * - version1: number (required) - First version (older)\n * - version2: number (required) - Second version (newer)\n */\n app.get('/api/v1/metadata/:type/:name/diff', async (c: any) => {\n if (!metadataService.diff) {\n return c.json({ error: 'Diff not supported' }, 501);\n }\n\n const { type, name } = c.req.param();\n const query = c.req.query();\n\n try {\n const version1 = parseInt(query.version1, 10);\n const version2 = parseInt(query.version2, 10);\n\n if (isNaN(version1) || isNaN(version2)) {\n return c.json(\n {\n success: false,\n error: 'Both version1 and version2 query parameters are required',\n },\n 400\n );\n }\n\n const diffResult = await metadataService.diff(type, name, version1, version2);\n\n return c.json({\n success: true,\n data: diffResult,\n });\n } catch (error) {\n return c.json(\n {\n success: false,\n error: error instanceof Error ? error.message : 'Diff failed',\n },\n 500\n );\n }\n });\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata History Retention and Cleanup\n *\n * Manages automatic cleanup of old history records based on retention policies.\n * Supports both age-based and count-based retention strategies.\n */\n\nimport type { IDataDriver } from '@objectstack/spec/contracts';\nimport type { MetadataHistoryRetentionPolicy } from '@objectstack/spec/system';\nimport type { DatabaseLoader } from '../loaders/database-loader.js';\n\n/**\n * History Cleanup Manager\n *\n * Handles automatic cleanup of metadata history records based on\n * configured retention policies.\n */\nexport class HistoryCleanupManager {\n private policy: MetadataHistoryRetentionPolicy;\n private dbLoader: DatabaseLoader;\n private cleanupTimer?: NodeJS.Timeout;\n\n constructor(policy: MetadataHistoryRetentionPolicy, dbLoader: DatabaseLoader) {\n this.policy = policy;\n this.dbLoader = dbLoader;\n }\n\n /**\n * Start automatic cleanup if enabled in the policy.\n */\n start(): void {\n if (!this.policy.autoCleanup) {\n return;\n }\n\n const intervalMs = (this.policy.cleanupIntervalHours ?? 24) * 60 * 60 * 1000;\n\n // Run cleanup immediately on start\n void this.runCleanup();\n\n // Schedule periodic cleanup\n this.cleanupTimer = setInterval(() => {\n void this.runCleanup();\n }, intervalMs);\n }\n\n /**\n * Stop automatic cleanup.\n */\n stop(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = undefined;\n }\n }\n\n /**\n * Run cleanup based on the retention policy.\n * Removes history records that exceed the configured limits.\n */\n async runCleanup(): Promise<{ deleted: number; errors: number }> {\n const driver = (this.dbLoader as any).driver as IDataDriver;\n const historyTableName = (this.dbLoader as any).historyTableName as string;\n const organizationId = (this.dbLoader as any).organizationId as string | undefined;\n const projectId = (this.dbLoader as any).projectId as string | undefined;\n\n let deleted = 0;\n let errors = 0;\n\n try {\n // Age-based cleanup\n if (this.policy.maxAgeDays) {\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - this.policy.maxAgeDays);\n const cutoffISO = cutoffDate.toISOString();\n\n const filter: Record<string, unknown> = {\n recorded_at: { $lt: cutoffISO },\n };\n\n if (organizationId) {\n filter.organization_id = organizationId;\n }\n if (projectId !== undefined) {\n filter.project_id = projectId;\n }\n\n try {\n const result = await this.bulkDeleteByFilter(driver, historyTableName, filter);\n deleted += result.deleted;\n errors += result.errors;\n } catch {\n errors++;\n }\n }\n\n // Count-based cleanup per metadata item\n if (this.policy.maxVersions) {\n try {\n // Get all unique metadata IDs\n const baseWhere: Record<string, unknown> = {};\n if (organizationId) baseWhere.organization_id = organizationId;\n if (projectId !== undefined) baseWhere.project_id = projectId;\n\n const metadataIds = await driver.find(historyTableName, {\n object: historyTableName,\n where: baseWhere,\n fields: ['metadata_id'],\n });\n\n const uniqueIds = new Set<string>();\n for (const record of metadataIds) {\n if (record.metadata_id) {\n uniqueIds.add(record.metadata_id as string);\n }\n }\n\n // For each metadata item, keep only the latest N versions\n for (const metadataId of uniqueIds) {\n const filter: Record<string, unknown> = { metadata_id: metadataId, ...baseWhere };\n\n try {\n // Fetch only the IDs of records beyond the retention limit (oldest first)\n const historyRecords = await driver.find(historyTableName, {\n object: historyTableName,\n where: filter,\n orderBy: [{ field: 'version', order: 'desc' as const }],\n fields: ['id'],\n });\n\n if (historyRecords.length > this.policy.maxVersions) {\n const toDelete = historyRecords.slice(this.policy.maxVersions);\n const ids = toDelete.map(r => r.id as string).filter(Boolean);\n const result = await this.bulkDeleteByIds(driver, historyTableName, ids);\n deleted += result.deleted;\n errors += result.errors;\n }\n } catch {\n errors++;\n }\n }\n } catch {\n errors++;\n }\n }\n } catch (error) {\n console.error('History cleanup failed:', error);\n errors++;\n }\n\n return { deleted, errors };\n }\n\n /**\n * Delete records matching a filter using the most efficient method available on the driver.\n */\n private async bulkDeleteByFilter(\n driver: IDataDriver,\n table: string,\n filter: Record<string, unknown>\n ): Promise<{ deleted: number; errors: number }> {\n const driverAny = driver as any;\n if (typeof driverAny.deleteMany === 'function') {\n const count = await driverAny.deleteMany(table, filter);\n return { deleted: typeof count === 'number' ? count : 0, errors: 0 };\n }\n\n // Fallback: fetch IDs then delete\n const records = await driver.find(table, { object: table, where: filter, fields: ['id'] });\n const ids = records.map((r: Record<string, unknown>) => r.id as string).filter(Boolean);\n return this.bulkDeleteByIds(driver, table, ids);\n }\n\n /**\n * Delete records by IDs using bulkDelete when available, otherwise one-by-one.\n */\n private async bulkDeleteByIds(\n driver: IDataDriver,\n table: string,\n ids: string[]\n ): Promise<{ deleted: number; errors: number }> {\n if (ids.length === 0) return { deleted: 0, errors: 0 };\n\n const driverAny = driver as any;\n if (typeof driverAny.bulkDelete === 'function') {\n const result = await driverAny.bulkDelete(table, ids);\n return {\n deleted: typeof result === 'number' ? result : ids.length,\n errors: 0,\n };\n }\n\n // Fallback: sequential deletes\n let deleted = 0;\n let errors = 0;\n for (const id of ids) {\n try {\n await driver.delete(table, id);\n deleted++;\n } catch {\n errors++;\n }\n }\n return { deleted, errors };\n }\n\n /**\n * Get cleanup statistics without actually deleting anything.\n * Useful for previewing what would be cleaned up.\n */\n async getCleanupStats(): Promise<{\n recordsByAge: number;\n recordsByCount: number;\n total: number;\n }> {\n const driver = (this.dbLoader as any).driver as IDataDriver;\n const historyTableName = (this.dbLoader as any).historyTableName as string;\n const organizationId = (this.dbLoader as any).organizationId as string | undefined;\n const projectId = (this.dbLoader as any).projectId as string | undefined;\n\n let recordsByAge = 0;\n let recordsByCount = 0;\n\n try {\n const baseWhere: Record<string, unknown> = {};\n if (organizationId) baseWhere.organization_id = organizationId;\n if (projectId !== undefined) baseWhere.project_id = projectId;\n\n // Count records that would be deleted by age\n if (this.policy.maxAgeDays) {\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - this.policy.maxAgeDays);\n const cutoffISO = cutoffDate.toISOString();\n\n const filter: Record<string, unknown> = {\n recorded_at: { $lt: cutoffISO },\n ...baseWhere,\n };\n\n recordsByAge = await driver.count(historyTableName, {\n object: historyTableName,\n where: filter,\n });\n }\n\n // Count records that would be deleted by version limit\n if (this.policy.maxVersions) {\n const metadataIds = await driver.find(historyTableName, {\n object: historyTableName,\n where: baseWhere,\n fields: ['metadata_id'],\n });\n\n const uniqueIds = new Set<string>();\n for (const record of metadataIds) {\n if (record.metadata_id) {\n uniqueIds.add(record.metadata_id as string);\n }\n }\n\n for (const metadataId of uniqueIds) {\n const filter: Record<string, unknown> = { metadata_id: metadataId, ...baseWhere };\n\n const count = await driver.count(historyTableName, {\n object: historyTableName,\n where: filter,\n });\n\n if (count > this.policy.maxVersions) {\n recordsByCount += count - this.policy.maxVersions;\n }\n }\n }\n } catch (error) {\n console.error('Failed to get cleanup stats:', error);\n }\n\n // Return separate counts. The total is an upper-bound estimate: it may overcount\n // records that qualify under both policies (age and count). Use recordsByAge and\n // recordsByCount individually for precise breakdowns.\n return {\n recordsByAge,\n recordsByCount,\n total: recordsByAge + recordsByCount,\n };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nexport * from './executor.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport * as System from '@objectstack/spec/system';\nimport { ISchemaDriver } from '@objectstack/spec/contracts';\n\nexport class MigrationExecutor {\n constructor(private driver: ISchemaDriver) {}\n\n async executeChangeSet(changeSet: System.ChangeSet): Promise<void> {\n console.log(`Executing ChangeSet: ${changeSet.name} (${changeSet.id})`);\n \n for (const op of changeSet.operations) {\n try {\n await this.executeOperation(op);\n } catch (e) {\n console.error(`Failed to execute operation ${op.type}:`, e);\n throw e;\n }\n }\n }\n\n private async executeOperation(op: System.MigrationOperation): Promise<void> {\n switch (op.type) {\n case 'create_object':\n console.log(` > Create Object: ${op.object.name}`);\n await this.driver.createCollection(op.object.name, op.object);\n break;\n case 'add_field':\n console.log(` > Add Field: ${op.objectName}.${op.fieldName}`);\n await this.driver.addColumn(op.objectName, op.fieldName, op.field);\n break;\n case 'remove_field':\n console.log(` > Remove Field: ${op.objectName}.${op.fieldName}`);\n await this.driver.dropColumn(op.objectName, op.fieldName);\n break;\n case 'delete_object':\n console.log(` > Delete Object: ${op.objectName}`);\n await this.driver.dropCollection(op.objectName);\n break;\n case 'execute_sql':\n console.log(` > Execute SQL`);\n await this.driver.executeRaw(op.sql);\n break;\n case 'modify_field':\n console.warn(` ! Modify Field: ${op.objectName}.${op.fieldName} (Not fully implemented)`);\n break;\n case 'rename_object':\n console.warn(` ! Rename Object: ${op.oldName} -> ${op.newName} (Not fully implemented)`);\n break;\n default:\n throw new Error(`Unknown operation type`);\n }\n }\n}\n"],"mappings":"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","names":["path","readFile","createHash","path","basename","readFile","createHash","SysMetadataObject","SysMetadataHistoryObject"]}
1
+ {"version":3,"sources":["../src/metadata-manager.ts","../src/serializers/json-serializer.ts","../src/serializers/yaml-serializer.ts","../src/serializers/typescript-serializer.ts","../src/loaders/database-loader.ts","../src/utils/metadata-history-utils.ts","../src/utils/lru-cache.ts","../src/migrations/add-sys-metadata-overlay-index.ts","../src/plugin.ts","../src/node-metadata-manager.ts","../src/loaders/filesystem-loader.ts","../src/loaders/memory-loader.ts","../src/loaders/remote-loader.ts","../src/index.ts","../src/routes/history-routes.ts","../src/utils/history-cleanup.ts","../src/migration/index.ts","../src/migration/executor.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata Manager\n * \n * Main orchestrator for metadata loading, saving, and persistence.\n * Implements the IMetadataService contract from @objectstack/spec.\n * Browser-compatible (Pure).\n */\n\nimport type {\n MetadataManagerConfig,\n MetadataLoadOptions,\n MetadataSaveOptions,\n MetadataSaveResult,\n MetadataWatchEvent,\n MetadataFormat,\n PackagePublishResult,\n MetadataHistoryQueryOptions,\n MetadataHistoryQueryResult,\n MetadataDiffResult,\n} from '@objectstack/spec/system';\nimport type {\n IMetadataService,\n MetadataWatchCallback,\n MetadataWatchHandle,\n MetadataExportOptions,\n MetadataImportOptions,\n MetadataImportResult,\n MetadataTypeInfo,\n IRealtimeService,\n RealtimeEventPayload,\n} from '@objectstack/spec/contracts';\nimport type {\n MetadataQuery,\n MetadataQueryResult,\n MetadataValidationResult,\n MetadataBulkResult,\n MetadataDependency,\n MetadataTypeRegistryEntry,\n} from '@objectstack/spec/kernel';\nimport type { MetadataOverlay } from '@objectstack/spec/kernel';\nimport { createLogger, type Logger } from '@objectstack/core';\nimport { JSONSerializer } from './serializers/json-serializer.js';\nimport { YAMLSerializer } from './serializers/yaml-serializer.js';\nimport { TypeScriptSerializer } from './serializers/typescript-serializer.js';\nimport type { MetadataSerializer } from './serializers/serializer-interface.js';\nimport type { IDataDriver, IDataEngine } from '@objectstack/spec/contracts';\nimport type { MetadataLoader } from './loaders/loader-interface.js';\nimport { DatabaseLoader } from './loaders/database-loader.js';\nimport { generateSimpleDiff, generateDiffSummary } from './utils/metadata-history-utils.js';\n\n/**\n * Watch callback function (legacy)\n */\nexport type WatchCallback = (event: MetadataWatchEvent) => void | Promise<void>;\n\nexport interface MetadataManagerOptions extends MetadataManagerConfig {\n loaders?: MetadataLoader[];\n /** Optional IDataDriver instance. When provided alongside config.datasource, auto-configures DatabaseLoader. */\n driver?: IDataDriver;\n}\n\n/**\n * Main metadata manager class.\n * Implements IMetadataService contract for unified metadata management.\n */\nexport class MetadataManager implements IMetadataService {\n private loaders: Map<string, MetadataLoader> = new Map();\n // Protected so subclasses can access serializers if needed\n protected serializers: Map<MetadataFormat, MetadataSerializer>;\n protected logger: Logger;\n protected watchCallbacks = new Map<string, Set<WatchCallback>>();\n protected config: MetadataManagerOptions;\n\n // In-memory metadata registry: type -> name -> data\n private registry = new Map<string, Map<string, unknown>>();\n\n // Overlay storage: \"type:name:scope\" -> MetadataOverlay\n private overlays = new Map<string, MetadataOverlay>();\n\n // Type registry for metadata type info\n private typeRegistry: MetadataTypeRegistryEntry[] = [];\n\n // Dependency tracking: \"type:name\" -> dependencies\n private dependencies = new Map<string, MetadataDependency[]>();\n\n // Short-lived cache for list() results. Built primarily to break the\n // deadlock that occurs when security/permission middleware calls\n // `list('permission')` from inside a user-initiated DB transaction: the\n // DatabaseLoader's `engine.find('sys_metadata', ...)` would then try to\n // acquire a fresh knex connection while the transaction is still holding\n // SQLite's single connection — knex waits the full `acquireConnectionTimeout`\n // (60s) before returning []. The cache absorbs the repeated lookups so the\n // loader is only hit once per TTL window.\n //\n // Invalidated on every `register()` / `unregister()` to keep CRUD writes\n // visible to subsequent reads.\n private listCache = new Map<string, { ts: number; items: unknown[] }>();\n private static readonly LIST_CACHE_TTL_MS = 30_000;\n\n // Realtime service for event publishing\n private realtimeService?: IRealtimeService;\n\n constructor(config: MetadataManagerOptions) {\n this.config = config;\n this.logger = createLogger({ level: 'info', format: 'pretty' });\n\n // Initialize serializers\n this.serializers = new Map();\n const formats = config.formats || ['typescript', 'json', 'yaml'];\n\n if (formats.includes('json')) {\n this.serializers.set('json', new JSONSerializer());\n }\n if (formats.includes('yaml')) {\n this.serializers.set('yaml', new YAMLSerializer());\n }\n if (formats.includes('typescript')) {\n this.serializers.set('typescript', new TypeScriptSerializer('typescript'));\n }\n if (formats.includes('javascript')) {\n this.serializers.set('javascript', new TypeScriptSerializer('javascript'));\n }\n\n // Initialize Loaders\n if (config.loaders && config.loaders.length > 0) {\n config.loaders.forEach(loader => this.registerLoader(loader));\n }\n\n // Auto-configure DatabaseLoader when datasource + driver are provided\n if (config.datasource && config.driver) {\n this.setDatabaseDriver(config.driver);\n }\n // Note: No default loader in base class. Subclasses (NodeMetadataManager) or caller must provide one.\n }\n\n /**\n * Set the type registry for metadata type discovery.\n */\n setTypeRegistry(entries: MetadataTypeRegistryEntry[]): void {\n this.typeRegistry = entries;\n }\n\n /**\n * Configure and register a DatabaseLoader for database-backed metadata persistence.\n * Can be called at any time to enable database storage (e.g. after kernel resolves the driver).\n *\n * @param driver - An IDataDriver instance for database operations\n * @param organizationId - Organization ID for multi-tenant isolation\n * @param projectId - Project ID (undefined = platform-global)\n */\n setDatabaseDriver(driver: IDataDriver, organizationId?: string, projectId?: string): void {\n if (projectId !== undefined) {\n this.logger.info('Project kernel — skipping DatabaseLoader for sys_metadata (control-plane only)', {\n organizationId,\n projectId,\n });\n return;\n }\n const tableName = this.config.tableName ?? 'sys_metadata';\n const dbLoader = new DatabaseLoader({\n driver,\n tableName,\n organizationId,\n projectId,\n cache: this.config.cache?.databaseLoader,\n });\n this.registerLoader(dbLoader);\n this.logger.info('DatabaseLoader configured', { datasource: this.config.datasource, tableName });\n }\n\n /**\n * Configure and register a DatabaseLoader backed by an IDataEngine (ObjectQL).\n * The engine handles datasource routing automatically — sys_metadata will\n * be routed to the correct driver via the standard namespace mapping.\n * No manual driver resolution needed.\n *\n * @param engine - An IDataEngine instance (typically the ObjectQL service)\n * @param organizationId - Organization ID for multi-tenant isolation\n * @param projectId - Project ID (undefined = platform-global)\n */\n setDataEngine(engine: IDataEngine, organizationId?: string, projectId?: string): void {\n if (projectId !== undefined) {\n this.logger.info('Project kernel — skipping DatabaseLoader for sys_metadata (control-plane only)', {\n organizationId,\n projectId,\n });\n return;\n }\n const tableName = this.config.tableName ?? 'sys_metadata';\n const dbLoader = new DatabaseLoader({\n engine,\n tableName,\n organizationId,\n projectId,\n cache: this.config.cache?.databaseLoader,\n });\n this.registerLoader(dbLoader);\n this.logger.info('DatabaseLoader configured via DataEngine', { tableName });\n }\n\n /**\n * Set the realtime service for publishing metadata 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 metadata events');\n }\n\n /**\n * Register a new metadata loader (data source)\n */\n registerLoader(loader: MetadataLoader) {\n this.loaders.set(loader.contract.name, loader);\n this.logger.info(`Registered metadata loader: ${loader.contract.name} (${loader.contract.protocol})`);\n }\n\n // ==========================================\n // IMetadataService — Core CRUD Operations\n // ==========================================\n\n /**\n * Register/save a metadata item by type\n * Stores in-memory registry and persists to database-backed loaders only.\n * FilesystemLoader (protocol 'file:') is read-only for static metadata and\n * should not be written to during runtime registration.\n */\n async register(type: string, name: string, data: unknown): Promise<void> {\n // Persistence write gate: when `persistence.writable` is explicitly false\n // we treat register() as read-only. Default `true` (or omitted) preserves\n // historical behavior.\n if (this.config.persistence?.writable === false) {\n const msg = `MetadataManager is read-only (persistence.writable=false); refusing to register ${type}/${name}`;\n if (this.config.validation?.throwOnError) {\n throw new Error(msg);\n }\n this.logger.warn(msg);\n return;\n }\n\n if (!this.registry.has(type)) {\n this.registry.set(type, new Map());\n }\n this.registry.get(type)!.set(name, data);\n this.invalidateListCache(type);\n\n // Persist only to database-backed loaders that declare write capability.\n // FilesystemLoader is read-only at runtime — writing to it can crash in\n // read-only environments (e.g. serverless, containerized deployments).\n for (const loader of this.loaders.values()) {\n if (loader.save && loader.contract.protocol === 'datasource:' && loader.contract.capabilities.write) {\n await loader.save(type, name, data);\n }\n }\n\n // Publish metadata.{type}.created event to realtime service\n if (this.realtimeService) {\n const event: RealtimeEventPayload = {\n type: `metadata.${type}.created`,\n object: type,\n payload: {\n metadataType: type,\n name,\n definition: data,\n packageId: (data as any)?.packageId,\n },\n timestamp: new Date().toISOString(),\n };\n\n try {\n await this.realtimeService.publish(event);\n this.logger.debug(`Published metadata.${type}.created event`, { name });\n } catch (error) {\n this.logger.warn(`Failed to publish metadata event`, { type, name, error });\n }\n }\n }\n\n /**\n * Get a metadata item by type and name.\n * Checks in-memory registry first, then falls back to loaders.\n */\n async get(type: string, name: string): Promise<unknown | undefined> {\n // Check in-memory registry first\n const typeStore = this.registry.get(type);\n if (typeStore?.has(name)) {\n return typeStore.get(name);\n }\n\n // Fallback to loaders\n const result = await this.load(type, name);\n return result ?? undefined;\n }\n\n /**\n * List all metadata items of a given type\n */\n async list(type: string): Promise<unknown[]> {\n // Short-TTL cache: see field comment on `listCache`. Skip when called\n // from tests / hot reloads that rely on always-fresh reads — we only\n // cache positive (non-empty) hits or repeated hits with a stable miss\n // signature.\n const cached = this.listCache.get(type);\n if (cached && Date.now() - cached.ts < MetadataManager.LIST_CACHE_TTL_MS) {\n return cached.items;\n }\n\n const items = new Map<string, unknown>();\n\n // From in-memory registry\n const typeStore = this.registry.get(type);\n if (typeStore) {\n for (const [name, data] of typeStore) {\n items.set(name, data);\n }\n }\n\n // From loaders (deduplicate)\n for (const loader of this.loaders.values()) {\n try {\n const loaderItems = await loader.loadMany(type);\n for (const item of loaderItems) {\n const itemAny = item as any;\n if (itemAny && typeof itemAny.name === 'string' && !items.has(itemAny.name)) {\n items.set(itemAny.name, item);\n }\n }\n } catch (e) {\n this.logger.warn(`Loader ${loader.contract.name} failed to loadMany ${type}`, { error: e });\n }\n }\n\n const result = Array.from(items.values());\n this.cacheListResult(type, result);\n return result;\n }\n private cacheListResult(type: string, items: unknown[]): void {\n this.listCache.set(type, { ts: Date.now(), items });\n }\n\n /** Internal helper: drop the cached `list()` result for a type. */\n private invalidateListCache(type: string): void {\n this.listCache.delete(type);\n }\n\n /**\n * Unregister/remove a metadata item by type and name.\n * Deletes from database-backed loaders only (same rationale as register()).\n */\n async unregister(type: string, name: string): Promise<void> {\n // Remove from in-memory registry\n const typeStore = this.registry.get(type);\n if (typeStore) {\n typeStore.delete(name);\n if (typeStore.size === 0) {\n this.registry.delete(type);\n }\n }\n this.invalidateListCache(type);\n\n // Delete only from database-backed loaders that declare write capability\n for (const loader of this.loaders.values()) {\n if (loader.contract.protocol !== 'datasource:' || !loader.contract.capabilities.write) continue;\n if (typeof (loader as any).delete === 'function') {\n try {\n await (loader as any).delete(type, name);\n } catch (error) {\n this.logger.warn(`Failed to delete ${type}/${name} from loader ${loader.contract.name}`, { error });\n }\n }\n }\n\n // Publish metadata.{type}.deleted event to realtime service\n if (this.realtimeService) {\n const event: RealtimeEventPayload = {\n type: `metadata.${type}.deleted`,\n object: type,\n payload: {\n metadataType: type,\n name,\n },\n timestamp: new Date().toISOString(),\n };\n\n try {\n await this.realtimeService.publish(event);\n this.logger.debug(`Published metadata.${type}.deleted event`, { name });\n } catch (error) {\n this.logger.warn(`Failed to publish metadata event`, { type, name, error });\n }\n }\n }\n\n /**\n * Check if a metadata item exists\n */\n async exists(type: string, name: string): Promise<boolean> {\n // Check in-memory registry\n if (this.registry.get(type)?.has(name)) {\n return true;\n }\n\n // Check loaders\n for (const loader of this.loaders.values()) {\n if (await loader.exists(type, name)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * List all names of metadata items of a given type\n */\n async listNames(type: string): Promise<string[]> {\n const names = new Set<string>();\n\n // From in-memory registry\n const typeStore = this.registry.get(type);\n if (typeStore) {\n for (const name of typeStore.keys()) {\n names.add(name);\n }\n }\n\n // From loaders\n for (const loader of this.loaders.values()) {\n const result = await loader.list(type);\n result.forEach(item => names.add(item));\n }\n\n return Array.from(names);\n }\n\n /**\n * Convenience: get an object definition by name\n */\n async getObject(name: string): Promise<unknown | undefined> {\n return this.get('object', name);\n }\n\n /**\n * Convenience: list all object definitions\n */\n async listObjects(): Promise<unknown[]> {\n return this.list('object');\n }\n\n // ==========================================\n // Convenience: UI Metadata\n // ==========================================\n\n /**\n * Convenience: get a view definition by name\n */\n async getView(name: string): Promise<unknown | undefined> {\n return this.get('view', name);\n }\n\n /**\n * Convenience: list view definitions, optionally filtered by object\n */\n async listViews(object?: string): Promise<unknown[]> {\n const views = await this.list('view');\n if (object) {\n return views.filter((v: any) => v?.object === object);\n }\n return views;\n }\n\n /**\n * Convenience: get a dashboard definition by name\n */\n async getDashboard(name: string): Promise<unknown | undefined> {\n return this.get('dashboard', name);\n }\n\n /**\n * Convenience: list all dashboard definitions\n */\n async listDashboards(): Promise<unknown[]> {\n return this.list('dashboard');\n }\n\n // ==========================================\n // Package Management\n // ==========================================\n\n /**\n * Unregister all metadata items from a specific package\n */\n async unregisterPackage(packageName: string): Promise<void> {\n // Collect all items to delete (type and name pairs)\n const itemsToDelete: Array<{ type: string; name: string }> = [];\n\n for (const [type, typeStore] of this.registry) {\n for (const [name, data] of typeStore) {\n const meta = data as any;\n if (meta?.packageId === packageName || meta?.package === packageName) {\n itemsToDelete.push({ type, name });\n }\n }\n }\n\n // Delete each item using unregister() to ensure deletion from both registry and loaders\n for (const { type, name } of itemsToDelete) {\n await this.unregister(type, name);\n }\n }\n\n /**\n * Publish an entire package:\n * 1. Validate all draft items\n * 2. Snapshot all items in the package (publishedDefinition = clone(metadata))\n * 3. Increment version\n * 4. Set all items state → active\n */\n async publishPackage(packageId: string, options?: {\n changeNote?: string;\n publishedBy?: string;\n validate?: boolean;\n }): Promise<PackagePublishResult> {\n const now = new Date().toISOString();\n const shouldValidate = options?.validate !== false;\n const publishedBy = options?.publishedBy;\n\n // Collect all items belonging to this package\n const packageItems: Array<{ type: string; name: string; data: any }> = [];\n for (const [type, typeStore] of this.registry) {\n for (const [name, data] of typeStore) {\n const meta = data as any;\n if (meta?.packageId === packageId || meta?.package === packageId) {\n packageItems.push({ type, name, data: meta });\n }\n }\n }\n\n if (packageItems.length === 0) {\n return {\n success: false,\n packageId,\n version: 0,\n publishedAt: now,\n itemsPublished: 0,\n validationErrors: [{ type: '', name: '', message: `No metadata items found for package '${packageId}'` }],\n };\n }\n\n // Validation pass\n if (shouldValidate) {\n const validationErrors: Array<{ type: string; name: string; message: string }> = [];\n\n // Schema validation\n for (const item of packageItems) {\n const result = await this.validate(item.type, item.data);\n if (!result.valid && result.errors) {\n for (const err of result.errors) {\n validationErrors.push({\n type: item.type,\n name: item.name,\n message: err.message,\n });\n }\n }\n }\n\n // Dependency validation: referenced items must be in the same package or already published\n const packageItemKeys = new Set(packageItems.map(i => `${i.type}:${i.name}`));\n for (const item of packageItems) {\n const deps = await this.getDependencies(item.type, item.name);\n for (const dep of deps) {\n const depKey = `${dep.targetType}:${dep.targetName}`;\n // Skip if the dependency is within this package\n if (packageItemKeys.has(depKey)) continue;\n // Check if the dependency exists and has been published\n const depItem = await this.get(dep.targetType, dep.targetName);\n if (!depItem) {\n validationErrors.push({\n type: item.type,\n name: item.name,\n message: `Dependency '${dep.targetType}:${dep.targetName}' not found`,\n });\n } else {\n const depMeta = depItem as any;\n if (depMeta.publishedDefinition === undefined && depMeta.state !== 'active') {\n validationErrors.push({\n type: item.type,\n name: item.name,\n message: `Dependency '${dep.targetType}:${dep.targetName}' is not published`,\n });\n }\n }\n }\n }\n\n if (validationErrors.length > 0) {\n return {\n success: false,\n packageId,\n version: 0,\n publishedAt: now,\n itemsPublished: 0,\n validationErrors,\n };\n }\n }\n\n // Determine the next version by finding the max current version across items\n let maxVersion = 0;\n for (const item of packageItems) {\n const v = typeof item.data.version === 'number' ? item.data.version : 0;\n if (v > maxVersion) maxVersion = v;\n }\n const newVersion = maxVersion + 1;\n\n // Snapshot and update all items\n for (const item of packageItems) {\n const updated = {\n ...item.data,\n publishedDefinition: structuredClone(item.data.metadata ?? item.data),\n publishedAt: now,\n publishedBy: publishedBy ?? item.data.publishedBy,\n version: newVersion,\n state: 'active',\n };\n await this.register(item.type, item.name, updated);\n }\n\n return {\n success: true,\n packageId,\n version: newVersion,\n publishedAt: now,\n itemsPublished: packageItems.length,\n };\n }\n\n /**\n * Revert entire package to last published state.\n * Restores all metadata definitions from their published snapshots.\n */\n async revertPackage(packageId: string): Promise<void> {\n const packageItems: Array<{ type: string; name: string; data: any }> = [];\n for (const [type, typeStore] of this.registry) {\n for (const [name, data] of typeStore) {\n const meta = data as any;\n if (meta?.packageId === packageId || meta?.package === packageId) {\n packageItems.push({ type, name, data: meta });\n }\n }\n }\n\n if (packageItems.length === 0) {\n throw new Error(`No metadata items found for package '${packageId}'`);\n }\n\n // Check that at least one item has a published snapshot\n const hasPublished = packageItems.some(item => item.data.publishedDefinition !== undefined);\n if (!hasPublished) {\n throw new Error(`Package '${packageId}' has never been published`);\n }\n\n for (const item of packageItems) {\n if (item.data.publishedDefinition !== undefined) {\n const reverted = {\n ...item.data,\n metadata: structuredClone(item.data.publishedDefinition),\n state: 'active',\n };\n await this.register(item.type, item.name, reverted);\n }\n }\n }\n\n /**\n * Get the published version of any metadata item (for runtime serving).\n * Returns publishedDefinition if exists, else current definition.\n */\n async getPublished(type: string, name: string): Promise<unknown | undefined> {\n const item = await this.get(type, name);\n if (!item) return undefined;\n\n const meta = item as any;\n if (meta.publishedDefinition !== undefined) {\n return meta.publishedDefinition;\n }\n\n // Fall back to current definition (metadata field or the item itself)\n return meta.metadata ?? item;\n }\n\n // ==========================================\n // Query / Search\n // ==========================================\n\n /**\n * Query metadata items with filtering, sorting, and pagination\n */\n async query(query: MetadataQuery): Promise<MetadataQueryResult> {\n const { types, search, page = 1, pageSize = 50, sortBy = 'name', sortOrder = 'asc' } = query;\n\n // Collect all items\n const allItems: Array<{\n type: string;\n name: string;\n namespace?: string;\n label?: string;\n scope?: 'system' | 'platform' | 'user';\n state?: 'draft' | 'active' | 'archived' | 'deprecated';\n packageId?: string;\n updatedAt?: string;\n }> = [];\n\n // Determine which types to scan\n const targetTypes = types && types.length > 0\n ? types\n : Array.from(this.registry.keys());\n\n for (const type of targetTypes) {\n const items = await this.list(type);\n for (const item of items) {\n const meta = item as any;\n allItems.push({\n type,\n name: meta?.name ?? '',\n namespace: meta?.namespace,\n label: meta?.label,\n scope: meta?.scope,\n state: meta?.state,\n packageId: meta?.packageId,\n updatedAt: meta?.updatedAt,\n });\n }\n }\n\n // Apply search filter\n let filtered = allItems;\n if (search) {\n const searchLower = search.toLowerCase();\n filtered = filtered.filter(item =>\n item.name.toLowerCase().includes(searchLower) ||\n (item.label && item.label.toLowerCase().includes(searchLower))\n );\n }\n\n // Apply scope filter\n if (query.scope) {\n filtered = filtered.filter(item => item.scope === query.scope);\n }\n\n // Apply state filter\n if (query.state) {\n filtered = filtered.filter(item => item.state === query.state);\n }\n\n // Apply namespace filter\n if (query.namespaces && query.namespaces.length > 0) {\n filtered = filtered.filter(item => item.namespace && query.namespaces!.includes(item.namespace));\n }\n\n // Apply packageId filter\n if (query.packageId) {\n filtered = filtered.filter(item => item.packageId === query.packageId);\n }\n\n // Apply tags filter\n if (query.tags && query.tags.length > 0) {\n filtered = filtered.filter(item => {\n const meta = item as any;\n return meta?.tags && query.tags!.some((t: string) => meta.tags.includes(t));\n });\n }\n\n // Sort\n filtered.sort((a, b) => {\n const aVal = (a as any)[sortBy] ?? '';\n const bVal = (b as any)[sortBy] ?? '';\n const cmp = String(aVal).localeCompare(String(bVal));\n return sortOrder === 'desc' ? -cmp : cmp;\n });\n\n // Paginate\n const total = filtered.length;\n const start = (page - 1) * pageSize;\n const paged = filtered.slice(start, start + pageSize);\n\n return {\n items: paged,\n total,\n page,\n pageSize,\n };\n }\n\n // ==========================================\n // Bulk Operations\n // ==========================================\n\n /**\n * Register multiple metadata items in a single batch\n */\n async bulkRegister(\n items: Array<{ type: string; name: string; data: unknown }>,\n options?: { continueOnError?: boolean; validate?: boolean }\n ): Promise<MetadataBulkResult> {\n const { continueOnError = false } = options ?? {};\n let succeeded = 0;\n let failed = 0;\n const errors: Array<{ type: string; name: string; error: string }> = [];\n\n for (const item of items) {\n try {\n await this.register(item.type, item.name, item.data);\n succeeded++;\n } catch (e) {\n failed++;\n errors.push({\n type: item.type,\n name: item.name,\n error: e instanceof Error ? e.message : String(e),\n });\n if (!continueOnError) break;\n }\n }\n\n return {\n total: items.length,\n succeeded,\n failed,\n errors: errors.length > 0 ? errors : undefined,\n };\n }\n\n /**\n * Unregister multiple metadata items in a single batch\n */\n async bulkUnregister(items: Array<{ type: string; name: string }>): Promise<MetadataBulkResult> {\n let succeeded = 0;\n let failed = 0;\n const errors: Array<{ type: string; name: string; error: string }> = [];\n\n for (const item of items) {\n try {\n await this.unregister(item.type, item.name);\n succeeded++;\n } catch (e) {\n failed++;\n errors.push({\n type: item.type,\n name: item.name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n\n return {\n total: items.length,\n succeeded,\n failed,\n errors: errors.length > 0 ? errors : undefined,\n };\n }\n\n // ==========================================\n // Overlay / Customization Management\n // ==========================================\n\n private overlayKey(type: string, name: string, scope: string = 'platform'): string {\n return `${encodeURIComponent(type)}:${encodeURIComponent(name)}:${scope}`;\n }\n\n /**\n * Get the active overlay for a metadata item\n */\n async getOverlay(type: string, name: string, scope?: 'platform' | 'user'): Promise<MetadataOverlay | undefined> {\n return this.overlays.get(this.overlayKey(type, name, scope ?? 'platform'));\n }\n\n /**\n * Save/update an overlay for a metadata item\n */\n async saveOverlay(overlay: MetadataOverlay): Promise<void> {\n // Overlay write gate — independent from base writability so deployments\n // can freeze Studio overlays while still permitting base register().\n if (this.config.persistence?.overlayWritable === false) {\n const msg = `MetadataManager overlays are read-only (persistence.overlayWritable=false); refusing to save overlay for ${overlay.baseType}/${overlay.baseName}`;\n if (this.config.validation?.throwOnError) {\n throw new Error(msg);\n }\n this.logger.warn(msg);\n return;\n }\n const key = this.overlayKey(overlay.baseType, overlay.baseName, overlay.scope);\n this.overlays.set(key, overlay);\n }\n\n /**\n * Remove an overlay, reverting to the base definition\n */\n async removeOverlay(type: string, name: string, scope?: 'platform' | 'user'): Promise<void> {\n this.overlays.delete(this.overlayKey(type, name, scope ?? 'platform'));\n }\n\n /**\n * Get the effective (merged) metadata after applying all overlays.\n * Resolution order: system ← merge(platform) ← merge(user)\n */\n async getEffective(type: string, name: string, context?: {\n userId?: string;\n tenantId?: string;\n roles?: string[];\n permissions?: string[];\n }): Promise<unknown | undefined> {\n const base = await this.get(type, name);\n if (!base) return undefined;\n\n let effective = { ...(base as Record<string, unknown>) };\n\n // Apply platform overlay\n const platformOverlay = await this.getOverlay(type, name, 'platform');\n if (platformOverlay?.active && platformOverlay.patch) {\n effective = { ...effective, ...platformOverlay.patch };\n }\n\n // Apply user overlay (scoped to specific user if context provided)\n if (context?.userId) {\n // Try user-specific key first, then fall back to generic user overlay.\n // The owner check below ensures we never apply another user's overlay.\n const userOverlayKey = this.overlayKey(type, name, 'user') + `:${context.userId}`;\n const userOverlay = this.overlays.get(userOverlayKey) \n ?? await this.getOverlay(type, name, 'user');\n if (userOverlay?.active && userOverlay.patch) {\n // Apply if: overlay has no owner (generic user-level), or owner matches current user\n if (!userOverlay.owner || userOverlay.owner === context.userId) {\n effective = { ...effective, ...userOverlay.patch };\n }\n }\n } else {\n // No user context — only apply user overlays without an owner restriction\n // (owner-scoped overlays require a userId to resolve)\n const userOverlay = await this.getOverlay(type, name, 'user');\n if (userOverlay?.active && userOverlay.patch && !userOverlay.owner) {\n effective = { ...effective, ...userOverlay.patch };\n }\n }\n\n return effective;\n }\n\n // ==========================================\n // Watch / Subscribe (IMetadataService)\n // ==========================================\n\n /**\n * Watch for metadata changes (IMetadataService contract).\n * Returns a handle for unsubscribing.\n */\n watchService(type: string, callback: MetadataWatchCallback): MetadataWatchHandle {\n const wrappedCallback: WatchCallback = (event) => {\n const mappedType = event.type === 'added' ? 'registered'\n : event.type === 'deleted' ? 'unregistered'\n : 'updated';\n callback({\n type: mappedType,\n metadataType: event.metadataType ?? type,\n name: event.name ?? '',\n data: event.data,\n });\n };\n this.addWatchCallback(type, wrappedCallback);\n return {\n unsubscribe: () => this.removeWatchCallback(type, wrappedCallback),\n };\n }\n\n // ==========================================\n // Import / Export\n // ==========================================\n\n /**\n * Export metadata as a portable bundle\n */\n async exportMetadata(options?: MetadataExportOptions): Promise<unknown> {\n const bundle: Record<string, unknown[]> = {};\n const targetTypes = options?.types ?? Array.from(this.registry.keys());\n\n for (const type of targetTypes) {\n const items = await this.list(type);\n if (items.length > 0) {\n bundle[type] = items;\n }\n }\n\n return bundle;\n }\n\n /**\n * Import metadata from a portable bundle\n */\n async importMetadata(data: unknown, options?: MetadataImportOptions): Promise<MetadataImportResult> {\n const {\n conflictResolution = 'skip',\n validate: _validate = true,\n dryRun = false,\n } = options ?? {};\n\n const bundle = data as Record<string, unknown[]>;\n let total = 0;\n let imported = 0;\n let skipped = 0;\n let failed = 0;\n const errors: Array<{ type: string; name: string; error: string }> = [];\n\n for (const [type, items] of Object.entries(bundle)) {\n if (!Array.isArray(items)) continue;\n\n for (const item of items) {\n total++;\n const meta = item as any;\n const name = meta?.name;\n\n if (!name) {\n failed++;\n errors.push({ type, name: '(unknown)', error: 'Item missing name field' });\n continue;\n }\n\n try {\n const itemExists = await this.exists(type, name);\n\n if (itemExists && conflictResolution === 'skip') {\n skipped++;\n continue;\n }\n\n if (!dryRun) {\n if (itemExists && conflictResolution === 'merge') {\n const existing = await this.get(type, name);\n const merged = { ...(existing as any), ...(item as any) };\n await this.register(type, name, merged);\n } else {\n await this.register(type, name, item);\n }\n }\n imported++;\n } catch (e) {\n failed++;\n errors.push({\n type,\n name,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n }\n }\n\n return {\n total,\n imported,\n skipped,\n failed,\n errors: errors.length > 0 ? errors : undefined,\n };\n }\n\n // ==========================================\n // Validation\n // ==========================================\n\n /**\n * Validate a metadata item against its type schema.\n * Returns validation result with errors and warnings.\n */\n async validate(_type: string, data: unknown): Promise<MetadataValidationResult> {\n // Basic structural validation\n if (data === null || data === undefined) {\n return {\n valid: false,\n errors: [{ path: '', message: 'Metadata data cannot be null or undefined' }],\n };\n }\n\n if (typeof data !== 'object') {\n return {\n valid: false,\n errors: [{ path: '', message: 'Metadata data must be an object' }],\n };\n }\n\n const meta = data as any;\n const warnings: Array<{ path: string; message: string }> = [];\n\n if (!meta.name) {\n return {\n valid: false,\n errors: [{ path: 'name', message: 'Metadata item must have a name field' }],\n };\n }\n\n if (!meta.label) {\n warnings.push({ path: 'label', message: 'Missing label field (recommended)' });\n }\n\n return { valid: true, warnings: warnings.length > 0 ? warnings : undefined };\n }\n\n // ==========================================\n // Type Registry\n // ==========================================\n\n /**\n * Get all registered metadata types\n */\n async getRegisteredTypes(): Promise<string[]> {\n const types = new Set<string>();\n\n // From type registry\n for (const entry of this.typeRegistry) {\n types.add(entry.type);\n }\n\n // From in-memory registry (custom types)\n for (const type of this.registry.keys()) {\n types.add(type);\n }\n\n return Array.from(types);\n }\n\n /**\n * Get detailed information about a metadata type\n */\n async getTypeInfo(type: string): Promise<MetadataTypeInfo | undefined> {\n const entry = this.typeRegistry.find(e => e.type === type);\n if (!entry) return undefined;\n\n return {\n type: entry.type,\n label: entry.label,\n description: entry.description,\n filePatterns: entry.filePatterns,\n supportsOverlay: entry.supportsOverlay,\n domain: entry.domain,\n };\n }\n\n // ==========================================\n // Dependency Tracking\n // ==========================================\n\n /**\n * Get metadata items that this item depends on\n */\n async getDependencies(type: string, name: string): Promise<MetadataDependency[]> {\n return this.dependencies.get(`${encodeURIComponent(type)}:${encodeURIComponent(name)}`) ?? [];\n }\n\n /**\n * Get metadata items that depend on this item\n */\n async getDependents(type: string, name: string): Promise<MetadataDependency[]> {\n const dependents: MetadataDependency[] = [];\n for (const deps of this.dependencies.values()) {\n for (const dep of deps) {\n if (dep.targetType === type && dep.targetName === name) {\n dependents.push(dep);\n }\n }\n }\n return dependents;\n }\n\n /**\n * Register a dependency between two metadata items.\n * Used internally to track cross-references.\n * Duplicate dependencies (same source, target, and kind) are ignored.\n */\n addDependency(dep: MetadataDependency): void {\n const key = `${encodeURIComponent(dep.sourceType)}:${encodeURIComponent(dep.sourceName)}`;\n if (!this.dependencies.has(key)) {\n this.dependencies.set(key, []);\n }\n const existing = this.dependencies.get(key)!;\n const isDuplicate = existing.some(\n d => d.targetType === dep.targetType && d.targetName === dep.targetName && d.kind === dep.kind\n );\n if (!isDuplicate) {\n existing.push(dep);\n }\n }\n\n // ==========================================\n // Legacy Loader API (backward compatible)\n // ==========================================\n\n /**\n * Load a single metadata item from loaders.\n * Iterates through registered loaders until found.\n */\n async load<T = any>(\n type: string,\n name: string,\n options?: MetadataLoadOptions\n ): Promise<T | null> {\n for (const loader of this.loaders.values()) {\n try {\n const result = await loader.load(type, name, options);\n if (result.data) {\n return result.data as T;\n }\n } catch (e) {\n this.logger.warn(`Loader ${loader.contract.name} failed to load ${type}:${name}`, { error: e });\n }\n }\n return null;\n }\n\n /**\n * Load multiple metadata items from loaders.\n * Aggregates results from all loaders.\n */\n async loadMany<T = any>(\n type: string,\n options?: MetadataLoadOptions\n ): Promise<T[]> {\n const results: T[] = [];\n\n for (const loader of this.loaders.values()) {\n try {\n const items = await loader.loadMany<T>(type, options);\n for (const item of items) {\n const itemAny = item as any;\n if (itemAny && typeof itemAny.name === 'string') {\n const exists = results.some((r: any) => r && r.name === itemAny.name);\n if (exists) continue;\n }\n results.push(item);\n }\n } catch (e) {\n this.logger.warn(`Loader ${loader.contract.name} failed to loadMany ${type}`, { error: e });\n }\n }\n return results;\n }\n\n /**\n * Save metadata item to a loader\n */\n async save<T = any>(\n type: string,\n name: string,\n data: T,\n options?: MetadataSaveOptions\n ): Promise<MetadataSaveResult> {\n const targetLoader = (options as any)?.loader;\n\n let loader: MetadataLoader | undefined;\n \n if (targetLoader) {\n loader = this.loaders.get(targetLoader);\n if (!loader) {\n throw new Error(`Loader not found: ${targetLoader}`);\n }\n } else {\n for (const l of this.loaders.values()) {\n if (!l.save) continue;\n try {\n if (await l.exists(type, name)) {\n loader = l;\n this.logger.info(`Updating existing metadata in loader: ${l.contract.name}`);\n break;\n }\n } catch (e) {\n // Ignore existence check errors\n }\n }\n\n if (!loader) {\n const fsLoader = this.loaders.get('filesystem');\n if (fsLoader && fsLoader.save) {\n loader = fsLoader;\n }\n }\n\n if (!loader) {\n for (const l of this.loaders.values()) {\n if (l.save) {\n loader = l;\n break;\n }\n }\n }\n }\n\n if (!loader) {\n throw new Error(`No loader available for saving type: ${type}`);\n }\n\n if (!loader.save) {\n throw new Error(`Loader '${loader.contract?.name}' does not support saving`);\n }\n\n return loader.save(type, name, data, options);\n }\n\n /**\n * Register a watch callback for metadata changes\n */\n protected addWatchCallback(type: string, callback: WatchCallback): void {\n if (!this.watchCallbacks.has(type)) {\n this.watchCallbacks.set(type, new Set());\n }\n this.watchCallbacks.get(type)!.add(callback);\n }\n\n /**\n * Remove a watch callback for metadata changes\n */\n protected removeWatchCallback(type: string, callback: WatchCallback): void {\n const callbacks = this.watchCallbacks.get(type);\n if (callbacks) {\n callbacks.delete(callback);\n if (callbacks.size === 0) {\n this.watchCallbacks.delete(type);\n }\n }\n }\n\n /**\n * Stop all watching\n */\n async stopWatching(): Promise<void> {\n // Override in subclass\n }\n\n protected notifyWatchers(type: string, event: MetadataWatchEvent) {\n const callbacks = this.watchCallbacks.get(type);\n if (!callbacks) return;\n\n for (const callback of callbacks) {\n try {\n void callback(event);\n } catch (error) {\n this.logger.error('Watch callback error', undefined, {\n type,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n\n // ==========================================\n // Version History & Rollback\n // ==========================================\n\n /**\n * Get the database loader for history operations.\n * Returns undefined if no database loader is configured.\n */\n private getDatabaseLoader(): DatabaseLoader | undefined {\n const dbLoader = this.loaders.get('database');\n if (dbLoader && dbLoader instanceof DatabaseLoader) {\n return dbLoader;\n }\n return undefined;\n }\n\n /**\n * Get version history for a metadata item.\n * Returns a timeline of all changes made to the item.\n */\n async getHistory(\n type: string,\n name: string,\n options?: MetadataHistoryQueryOptions\n ): Promise<MetadataHistoryQueryResult> {\n const dbLoader = this.getDatabaseLoader();\n if (!dbLoader) {\n throw new Error('History tracking requires a database loader to be configured');\n }\n\n return dbLoader.queryHistory(type, name, {\n operationType: options?.operationType,\n since: options?.since,\n until: options?.until,\n limit: options?.limit,\n offset: options?.offset,\n includeMetadata: options?.includeMetadata,\n });\n }\n\n /**\n * Rollback a metadata item to a specific version.\n * Restores the metadata definition from the history snapshot.\n */\n async rollback(\n type: string,\n name: string,\n version: number,\n options?: {\n changeNote?: string;\n recordedBy?: string;\n }\n ): Promise<unknown> {\n const dbLoader = this.getDatabaseLoader();\n if (!dbLoader) {\n throw new Error('Rollback requires a database loader to be configured');\n }\n\n // Fetch the target version snapshot directly from the history table\n const targetVersion = await dbLoader.getHistoryRecord(type, name, version);\n\n if (!targetVersion) {\n throw new Error(`Version ${version} not found in history for ${type}/${name}`);\n }\n\n if (!targetVersion.metadata) {\n throw new Error(`Version ${version} metadata snapshot not available`);\n }\n\n // Restore the metadata using the dedicated rollback path so that a single\n // 'revert' history entry is written (instead of a conflicting 'update' entry)\n const restoredMetadata = targetVersion.metadata;\n await dbLoader.registerRollback(\n type,\n name,\n restoredMetadata,\n version,\n options?.changeNote,\n options?.recordedBy\n );\n\n // Update in-memory registry with the restored metadata\n if (!this.registry.has(type)) {\n this.registry.set(type, new Map());\n }\n this.registry.get(type)!.set(name, restoredMetadata);\n\n return restoredMetadata;\n }\n\n /**\n * Compare two versions of a metadata item.\n * Returns a diff showing what changed between versions.\n */\n async diff(\n type: string,\n name: string,\n version1: number,\n version2: number\n ): Promise<MetadataDiffResult> {\n const dbLoader = this.getDatabaseLoader();\n if (!dbLoader) {\n throw new Error('Diff requires a database loader to be configured');\n }\n\n // Fetch the two version snapshots directly from the history table\n const v1 = await dbLoader.getHistoryRecord(type, name, version1);\n const v2 = await dbLoader.getHistoryRecord(type, name, version2);\n\n if (!v1) {\n throw new Error(`Version ${version1} not found in history for ${type}/${name}`);\n }\n\n if (!v2) {\n throw new Error(`Version ${version2} not found in history for ${type}/${name}`);\n }\n\n if (!v1.metadata || !v2.metadata) {\n throw new Error('Version metadata snapshots not available');\n }\n\n // Generate diff\n const patch = generateSimpleDiff(v1.metadata, v2.metadata);\n const identical = patch.length === 0;\n const summary = generateDiffSummary(patch);\n\n return {\n type,\n name,\n version1,\n version2,\n checksum1: v1.checksum,\n checksum2: v2.checksum,\n identical,\n patch,\n summary,\n };\n }\n}\n\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * JSON Metadata Serializer\n * \n * Handles JSON format serialization and deserialization\n */\n\nimport type { z } from 'zod';\nimport type { MetadataFormat } from '@objectstack/spec/system';\nimport type { MetadataSerializer, SerializeOptions } from './serializer-interface.js';\n\nexport class JSONSerializer implements MetadataSerializer {\n serialize<T>(item: T, options?: SerializeOptions): string {\n const { prettify = true, indent = 2, sortKeys = false } = options || {};\n\n if (sortKeys) {\n // Sort keys recursively\n const sorted = this.sortObjectKeys(item);\n return prettify\n ? JSON.stringify(sorted, null, indent)\n : JSON.stringify(sorted);\n }\n\n return prettify\n ? JSON.stringify(item, null, indent)\n : JSON.stringify(item);\n }\n\n deserialize<T>(content: string, schema?: z.ZodSchema): T {\n const parsed = JSON.parse(content);\n\n if (schema) {\n return schema.parse(parsed) as T;\n }\n\n return parsed as T;\n }\n\n getExtension(): string {\n return '.json';\n }\n\n canHandle(format: MetadataFormat): boolean {\n return format === 'json';\n }\n\n getFormat(): MetadataFormat {\n return 'json';\n }\n\n /**\n * Recursively sort object keys\n */\n private sortObjectKeys(obj: any): any {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => this.sortObjectKeys(item));\n }\n\n const sorted: Record<string, any> = {};\n const keys = Object.keys(obj).sort();\n\n for (const key of keys) {\n sorted[key] = this.sortObjectKeys(obj[key]);\n }\n\n return sorted;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * YAML Metadata Serializer\n * \n * Handles YAML format serialization and deserialization\n */\n\nimport * as yaml from 'js-yaml';\nimport type { z } from 'zod';\nimport type { MetadataFormat } from '@objectstack/spec/system';\nimport type { MetadataSerializer, SerializeOptions } from './serializer-interface.js';\n\nexport class YAMLSerializer implements MetadataSerializer {\n serialize<T>(item: T, options?: SerializeOptions): string {\n const { indent = 2, sortKeys = false } = options || {};\n\n return yaml.dump(item, {\n indent,\n sortKeys,\n lineWidth: -1, // Disable line wrapping\n noRefs: true, // Disable YAML references\n });\n }\n\n deserialize<T>(content: string, schema?: z.ZodSchema): T {\n // Use JSON_SCHEMA to prevent arbitrary code execution\n // This restricts YAML to JSON-compatible types only\n const parsed = yaml.load(content, { schema: yaml.JSON_SCHEMA });\n\n if (schema) {\n return schema.parse(parsed) as T;\n }\n\n return parsed as T;\n }\n\n getExtension(): string {\n return '.yaml';\n }\n\n canHandle(format: MetadataFormat): boolean {\n return format === 'yaml';\n }\n\n getFormat(): MetadataFormat {\n return 'yaml';\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * TypeScript/JavaScript Metadata Serializer\n * \n * Handles TypeScript/JavaScript module format serialization and deserialization\n */\n\nimport type { z } from 'zod';\nimport type { MetadataFormat } from '@objectstack/spec/system';\nimport type { MetadataSerializer, SerializeOptions } from './serializer-interface.js';\n\nexport class TypeScriptSerializer implements MetadataSerializer {\n constructor(private format: 'typescript' | 'javascript' = 'typescript') {}\n\n serialize<T>(item: T, options?: SerializeOptions): string {\n const { prettify = true, indent = 2 } = options || {};\n\n const jsonStr = JSON.stringify(item, null, prettify ? indent : 0);\n \n if (this.format === 'typescript') {\n return `import type { ServiceObject } from '@objectstack/spec/data';\\n\\n` +\n `export const metadata: ServiceObject = ${jsonStr};\\n\\n` +\n `export default metadata;\\n`;\n } else {\n return `export const metadata = ${jsonStr};\\n\\n` +\n `export default metadata;\\n`;\n }\n }\n\n deserialize<T>(content: string, schema?: z.ZodSchema): T {\n // For TypeScript/JavaScript files, we need to extract the exported object\n // Note: This is a simplified parser that works with JSON-like object literals\n // For complex TypeScript with nested objects, consider using a proper TypeScript parser\n \n // Try to find the object literal in various export patterns\n // Pattern 1: export const metadata = {...};\n let objectStart = content.indexOf('export const');\n if (objectStart === -1) {\n // Pattern 2: export default {...};\n objectStart = content.indexOf('export default');\n }\n \n if (objectStart === -1) {\n throw new Error(\n 'Could not parse TypeScript/JavaScript module. ' +\n 'Expected export pattern: \"export const metadata = {...};\" or \"export default {...};\"'\n );\n }\n\n // Find the first opening brace after the export statement\n const braceStart = content.indexOf('{', objectStart);\n if (braceStart === -1) {\n throw new Error('Could not find object literal in export statement');\n }\n\n // Find the matching closing brace by counting braces\n // Handle string literals to avoid counting braces inside strings\n let braceCount = 0;\n let braceEnd = -1;\n let inString = false;\n let stringChar = '';\n \n for (let i = braceStart; i < content.length; i++) {\n const char = content[i];\n const prevChar = i > 0 ? content[i - 1] : '';\n \n // Track string literals (simple handling of \" and ')\n if ((char === '\"' || char === \"'\") && prevChar !== '\\\\') {\n if (!inString) {\n inString = true;\n stringChar = char;\n } else if (char === stringChar) {\n inString = false;\n stringChar = '';\n }\n }\n \n // Count braces only when not inside strings\n if (!inString) {\n if (char === '{') braceCount++;\n if (char === '}') {\n braceCount--;\n if (braceCount === 0) {\n braceEnd = i;\n break;\n }\n }\n }\n }\n\n if (braceEnd === -1) {\n throw new Error('Could not find matching closing brace for object literal');\n }\n\n // Extract the object literal\n const objectLiteral = content.substring(braceStart, braceEnd + 1);\n\n try {\n // Parse as JSON\n const parsed = JSON.parse(objectLiteral);\n\n if (schema) {\n return schema.parse(parsed) as T;\n }\n\n return parsed as T;\n } catch (error) {\n throw new Error(\n `Failed to parse object literal as JSON: ${error instanceof Error ? error.message : String(error)}. ` +\n 'Make sure the TypeScript/JavaScript object uses JSON-compatible syntax (no functions, comments, or trailing commas).'\n );\n }\n }\n\n getExtension(): string {\n return this.format === 'typescript' ? '.ts' : '.js';\n }\n\n canHandle(format: MetadataFormat): boolean {\n return format === 'typescript' || format === 'javascript';\n }\n\n getFormat(): MetadataFormat {\n return this.format;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Database Metadata Loader\n *\n * Loads and persists metadata via an IDataDriver instance, enabling\n * database-backed storage for platform and user scoped metadata.\n * Uses the `sys_metadata` table (configurable) following the\n * MetadataRecordSchema envelope defined in @objectstack/spec.\n */\n\nimport type {\n MetadataLoadOptions,\n MetadataLoadResult,\n MetadataStats,\n MetadataLoaderContract,\n MetadataSaveOptions,\n MetadataSaveResult,\n MetadataRecord,\n MetadataHistoryRecord,\n} from '@objectstack/spec/system';\nimport { SysMetadataObject, SysMetadataHistoryObject } from '@objectstack/platform-objects/metadata';\nimport type { IDataDriver, IDataEngine } from '@objectstack/spec/contracts';\nimport type { MetadataLoader } from './loader-interface.js';\nimport { calculateChecksum } from '../utils/metadata-history-utils.js';\nimport { LRUCache } from '../utils/lru-cache.js';\nimport { addSysMetadataOverlayIndex } from '../migrations/add-sys-metadata-overlay-index.js';\n\n/**\n * Cache configuration for `DatabaseLoader`.\n *\n * The cache sits in front of `load()`, `loadMany()`, `exists()`, `stat()`,\n * and `list()` so that hot read paths (REST `/meta/*`, ObjectQL plan\n * resolution, runtime overlay merges) do not hit the database on every\n * request. All write paths (`save`, `delete`, `registerRollback`) invalidate\n * the relevant entries.\n *\n * Defaults are conservative: 500 entries, 60s TTL — chosen so that single-\n * tenant Studio usage does not burn memory and so that an external write\n * (out-of-band SQL update) becomes visible within a minute even without\n * realtime invalidation.\n */\nexport interface DatabaseLoaderCacheOptions {\n /** Whether the cache is active. Default: `true`. */\n enabled?: boolean;\n /** Max number of cached `(type, name)` entries. Default: `500`. */\n maxSize?: number;\n /** TTL in milliseconds. Set to `0` to disable expiry. Default: `60_000`. */\n ttl?: number;\n}\n\n/**\n * Configuration for the DatabaseLoader.\n *\n * Accepts either a raw `IDataDriver` or an `IDataEngine` (ObjectQL).\n * When `engine` is provided, all CRUD operations route through the engine\n * which handles datasource mapping automatically — no manual driver\n * resolution needed. Schema sync is also skipped (the engine handles it).\n */\nexport interface DatabaseLoaderOptions {\n /** The IDataDriver instance to use for database operations */\n driver?: IDataDriver;\n\n /** The IDataEngine (ObjectQL) instance — preferred over raw driver */\n engine?: IDataEngine;\n\n /** The table name to store metadata records (default: 'sys_metadata') */\n tableName?: string;\n\n /** The table name to store history records (default: 'sys_metadata_history') */\n historyTableName?: string;\n\n /** Organization ID for multi-tenant isolation */\n organizationId?: string;\n\n /** Project ID — null = platform-global, set = project-scoped */\n projectId?: string;\n\n /** Enable history tracking (default: true) */\n trackHistory?: boolean;\n\n /**\n * Read-through cache configuration. Pass `{ enabled: false }` to disable\n * caching outright (useful in tests or when the caller wants the loader to\n * always read fresh from the database).\n */\n cache?: DatabaseLoaderCacheOptions;\n}\n\n/**\n * DatabaseLoader — Datasource-backed metadata persistence.\n *\n * Implements the MetadataLoader interface to provide database read/write\n * for metadata records. Uses the MetadataRecordSchema envelope to persist\n * metadata with scope, versioning, and audit fields.\n */\nexport class DatabaseLoader implements MetadataLoader {\n readonly contract: MetadataLoaderContract = {\n name: 'database',\n protocol: 'datasource:',\n capabilities: {\n read: true,\n write: true,\n watch: false,\n list: true,\n },\n };\n\n private driver?: IDataDriver;\n private engine?: IDataEngine;\n private tableName: string;\n private historyTableName: string;\n private organizationId?: string;\n private projectId?: string;\n private trackHistory: boolean;\n private schemaReady = false;\n private historySchemaReady = false;\n\n /** (type, name) → metadata payload — primes `load()` */\n private readonly loadCache?: LRUCache<string, Record<string, unknown> | null>;\n /** type → array of payloads — primes `loadMany()` */\n private readonly loadManyCache?: LRUCache<string, unknown[]>;\n /** type → list of names — primes `list()` */\n private readonly listCache?: LRUCache<string, string[]>;\n /** (type, name) → MetadataStats — primes `stat()` */\n private readonly statCache?: LRUCache<string, MetadataStats | null>;\n\n constructor(options: DatabaseLoaderOptions) {\n if (!options.driver && !options.engine) {\n throw new Error('DatabaseLoader requires either a driver or engine');\n }\n this.driver = options.driver;\n this.engine = options.engine;\n this.tableName = options.tableName ?? 'sys_metadata';\n this.historyTableName = options.historyTableName ?? 'sys_metadata_history';\n this.organizationId = options.organizationId;\n this.projectId = options.projectId;\n this.trackHistory = options.trackHistory !== false; // Default to true\n\n // Wire cache. Default: enabled with 500 entries / 60s TTL.\n const cacheOpts = options.cache;\n const cacheEnabled = cacheOpts?.enabled !== false;\n if (cacheEnabled) {\n const lruOpts = {\n maxSize: cacheOpts?.maxSize ?? 500,\n ttl: cacheOpts?.ttl ?? 60_000,\n };\n this.loadCache = new LRUCache(lruOpts);\n this.loadManyCache = new LRUCache(lruOpts);\n this.listCache = new LRUCache(lruOpts);\n this.statCache = new LRUCache(lruOpts);\n }\n }\n\n // ==========================================\n // Cache helpers\n // ==========================================\n\n private cacheKey(type: string, name: string): string {\n return `${type}::${name}`;\n }\n\n /**\n * Invalidate all cached entries for a specific (type, name) pair plus\n * the type-level aggregates (`loadMany`, `list`). Called from every write\n * path (`save`, `delete`, `registerRollback`).\n */\n private invalidate(type: string, name: string): void {\n if (!this.loadCache) return;\n const key = this.cacheKey(type, name);\n this.loadCache.delete(key);\n this.statCache?.delete(key);\n this.loadManyCache?.delete(type);\n this.listCache?.delete(type);\n }\n\n /** Drop the entire cache — useful after bulk imports or schema changes. */\n invalidateAll(): void {\n this.loadCache?.clear();\n this.loadManyCache?.clear();\n this.listCache?.clear();\n this.statCache?.clear();\n }\n\n /** Diagnostic: aggregated cache statistics for `metrics` endpoints. */\n getCacheStats(): {\n enabled: boolean;\n load: ReturnType<LRUCache<string, unknown>['stats']> | null;\n loadMany: ReturnType<LRUCache<string, unknown>['stats']> | null;\n list: ReturnType<LRUCache<string, unknown>['stats']> | null;\n stat: ReturnType<LRUCache<string, unknown>['stats']> | null;\n } {\n return {\n enabled: this.loadCache !== undefined,\n load: this.loadCache?.stats() ?? null,\n loadMany: this.loadManyCache?.stats() ?? null,\n list: this.listCache?.stats() ?? null,\n stat: this.statCache?.stats() ?? null,\n };\n }\n\n // ==========================================\n // Internal CRUD helpers (driver vs engine)\n // ==========================================\n\n private async _find(table: string, query: Record<string, unknown>): Promise<Record<string, unknown>[]> {\n if (this.engine) {\n return this.engine.find(table, query as any);\n }\n return this.driver!.find(table, { object: table, ...query } as any);\n }\n\n private async _findOne(table: string, query: Record<string, unknown>): Promise<Record<string, unknown> | null> {\n if (this.engine) {\n return this.engine.findOne(table, query as any);\n }\n return this.driver!.findOne(table, { object: table, ...query } as any);\n }\n\n private async _count(table: string, query: Record<string, unknown>): Promise<number> {\n if (this.engine) {\n return this.engine.count(table, query as any);\n }\n return this.driver!.count(table, { object: table, ...query } as any);\n }\n\n private async _create(table: string, data: Record<string, unknown>): Promise<Record<string, unknown>> {\n if (this.engine) {\n return this.engine.insert(table, data);\n }\n return this.driver!.create(table, data);\n }\n\n private async _update(table: string, id: string, data: Record<string, unknown>): Promise<Record<string, unknown>> {\n if (this.engine) {\n return this.engine.update(table, { id, ...data });\n }\n return this.driver!.update(table, id, data);\n }\n\n private async _delete(table: string, id: string): Promise<any> {\n if (this.engine) {\n return this.engine.delete(table, { where: { id } } as any);\n }\n return this.driver!.delete(table, id);\n }\n\n /**\n * Ensure the metadata table exists.\n * Uses IDataDriver.syncSchema with the SysMetadataObject definition\n * to idempotently create/update the table.\n */\n private async ensureSchema(): Promise<void> {\n if (this.schemaReady) return;\n\n // When using engine, schema sync is handled by ObjectQL startup\n if (this.engine) {\n this.schemaReady = true;\n // Best-effort: also ensure the overlay-uniqueness index.\n // The engine-managed driver may still benefit from a partial UNIQUE\n // INDEX (ADR-0005). Failures are swallowed by the migration itself.\n try {\n const engineAny = this.engine as any;\n let driver: IDataDriver | undefined =\n engineAny?.driver ?? engineAny?.getDriver?.();\n if (!driver && engineAny?.drivers instanceof Map) {\n for (const candidate of engineAny.drivers.values()) {\n const c = candidate as any;\n if (c && (typeof c.raw === 'function' || typeof c.execute === 'function')) {\n driver = candidate as IDataDriver;\n break;\n }\n }\n }\n if (driver) {\n await addSysMetadataOverlayIndex(driver);\n }\n } catch {\n // ignore — index is an optimization, not a correctness invariant\n }\n return;\n }\n\n try {\n await this.driver!.syncSchema(this.tableName, {\n ...SysMetadataObject,\n name: this.tableName,\n });\n this.schemaReady = true;\n // Apply ADR-0005 partial UNIQUE INDEX (best-effort, idempotent)\n try {\n await addSysMetadataOverlayIndex(this.driver!);\n } catch {\n // ignore — index is optimization\n }\n } catch {\n // If syncSchema fails (e.g. table already exists), mark ready and continue\n this.schemaReady = true;\n }\n }\n\n /**\n * Ensure the history table exists.\n * Uses IDataDriver.syncSchema with the SysMetadataHistoryObject definition.\n */\n private async ensureHistorySchema(): Promise<void> {\n if (!this.trackHistory || this.historySchemaReady) return;\n\n // When using engine, schema sync is handled by ObjectQL startup\n if (this.engine) {\n this.historySchemaReady = true;\n return;\n }\n\n try {\n await this.driver!.syncSchema(this.historyTableName, {\n ...SysMetadataHistoryObject,\n name: this.historyTableName,\n });\n this.historySchemaReady = true;\n } catch (error) {\n // Log the error; historySchemaReady remains false so the next operation retries.\n // If the error is a benign \"already exists\" the next attempt will also succeed.\n console.error('Failed to ensure history schema, will retry on next operation:', error);\n }\n }\n\n /**\n * Build base filter conditions for queries.\n * Filters by organizationId when configured; project_id when projectId is set,\n * or null (platform-global) when not set.\n */\n private baseFilter(type: string, name?: string): Record<string, unknown> {\n const filter: Record<string, unknown> = { type };\n if (name !== undefined) {\n filter.name = name;\n }\n if (this.organizationId) {\n filter.organization_id = this.organizationId;\n }\n // When projectId is set, scope to that project; otherwise query platform-global (project_id = null).\n filter.project_id = this.projectId ?? null;\n return filter;\n }\n\n /**\n * Create a history record for a metadata change.\n *\n * @param metadataId - The metadata record ID\n * @param type - Metadata type\n * @param name - Metadata name\n * @param version - Version number\n * @param metadata - The metadata payload\n * @param operationType - Type of operation\n * @param previousChecksum - Checksum of previous version (if any)\n * @param changeNote - Optional change description\n * @param recordedBy - Optional user who made the change\n */\n private async createHistoryRecord(\n metadataId: string,\n type: string,\n name: string,\n version: number,\n metadata: unknown,\n operationType: 'create' | 'update' | 'publish' | 'revert' | 'delete',\n previousChecksum?: string,\n changeNote?: string,\n recordedBy?: string\n ): Promise<void> {\n if (!this.trackHistory) return;\n\n await this.ensureHistorySchema();\n\n const now = new Date().toISOString();\n const checksum = await calculateChecksum(metadata);\n\n // Skip if checksum matches previous version (no actual change)\n if (previousChecksum && checksum === previousChecksum && operationType === 'update') {\n return;\n }\n\n const historyId = generateId();\n const metadataJson = JSON.stringify(metadata);\n\n const historyRecord: Partial<MetadataHistoryRecord> = {\n id: historyId,\n metadataId,\n name,\n type,\n version,\n operationType,\n metadata: metadataJson as any,\n checksum,\n previousChecksum,\n changeNote,\n recordedBy,\n recordedAt: now,\n ...(this.organizationId ? { organizationId: this.organizationId } : {}),\n ...(this.projectId !== undefined ? { projectId: this.projectId } : {}),\n };\n\n try {\n await this._create(this.historyTableName, {\n id: historyRecord.id,\n metadata_id: historyRecord.metadataId,\n name: historyRecord.name,\n type: historyRecord.type,\n version: historyRecord.version,\n operation_type: historyRecord.operationType,\n metadata: historyRecord.metadata,\n checksum: historyRecord.checksum,\n previous_checksum: historyRecord.previousChecksum,\n change_note: historyRecord.changeNote,\n recorded_by: historyRecord.recordedBy,\n recorded_at: historyRecord.recordedAt,\n ...(this.organizationId ? { organization_id: this.organizationId } : {}),\n ...(this.projectId !== undefined ? { project_id: this.projectId } : {}),\n });\n } catch (error) {\n // Log error but don't fail the main operation\n console.error(`Failed to create history record for ${type}/${name}:`, error);\n }\n }\n\n /**\n * Convert a database row to a metadata payload.\n * Parses the JSON `metadata` column back into an object.\n */\n private rowToData(row: Record<string, unknown>): Record<string, unknown> | null {\n if (!row || !row.metadata) return null;\n\n const payload = typeof row.metadata === 'string'\n ? JSON.parse(row.metadata as string)\n : row.metadata;\n\n return payload as Record<string, unknown>;\n }\n\n /**\n * Convert a database row to a MetadataRecord-like object.\n */\n private rowToRecord(row: Record<string, unknown>): MetadataRecord {\n return {\n id: row.id as string,\n name: row.name as string,\n type: row.type as string,\n namespace: (row.namespace as string) ?? 'default',\n packageId: row.package_id as string | undefined,\n managedBy: row.managed_by as MetadataRecord['managedBy'],\n scope: (row.scope as MetadataRecord['scope']) ?? 'platform',\n metadata: this.rowToData(row) ?? {},\n extends: row.extends as string | undefined,\n strategy: (row.strategy as MetadataRecord['strategy']) ?? 'merge',\n owner: row.owner as string | undefined,\n state: (row.state as MetadataRecord['state']) ?? 'active',\n organizationId: row.organization_id as string | undefined,\n projectId: row.project_id as string | undefined,\n version: (row.version as number) ?? 1,\n checksum: row.checksum as string | undefined,\n source: row.source as MetadataRecord['source'],\n tags: row.tags ? (typeof row.tags === 'string' ? JSON.parse(row.tags as string) : row.tags as string[]) : undefined,\n createdBy: row.created_by as string | undefined,\n createdAt: row.created_at as string | undefined,\n updatedBy: row.updated_by as string | undefined,\n updatedAt: row.updated_at as string | undefined,\n };\n }\n\n // ==========================================\n // MetadataLoader Interface Implementation\n // ==========================================\n\n async load(\n type: string,\n name: string,\n _options?: MetadataLoadOptions\n ): Promise<MetadataLoadResult> {\n const startTime = Date.now();\n\n await this.ensureSchema();\n\n // Read-through cache. We cache `null` (not-found) results too so a barrage\n // of misses does not hammer the database; invalidation on `save` upgrades\n // the entry once the row exists.\n const key = this.cacheKey(type, name);\n if (this.loadCache) {\n const cached = this.loadCache.get(key);\n if (cached !== undefined) {\n return {\n data: cached,\n source: 'database',\n format: 'json',\n loadTime: Date.now() - startTime,\n };\n }\n }\n\n try {\n const row = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n if (!row) {\n this.loadCache?.set(key, null);\n return {\n data: null,\n loadTime: Date.now() - startTime,\n };\n }\n\n const data = this.rowToData(row);\n const record = this.rowToRecord(row);\n\n this.loadCache?.set(key, data);\n\n return {\n data,\n source: 'database',\n format: 'json',\n etag: record.checksum,\n loadTime: Date.now() - startTime,\n };\n } catch {\n return {\n data: null,\n loadTime: Date.now() - startTime,\n };\n }\n }\n\n async loadMany<T = any>(\n type: string,\n _options?: MetadataLoadOptions\n ): Promise<T[]> {\n await this.ensureSchema();\n\n if (this.loadManyCache) {\n const cached = this.loadManyCache.get(type);\n if (cached !== undefined) return cached as T[];\n }\n\n try {\n const rows = await this._find(this.tableName, {\n where: this.baseFilter(type),\n });\n\n const result = rows\n .map(row => this.rowToData(row))\n .filter((data): data is Record<string, unknown> => data !== null) as T[];\n\n this.loadManyCache?.set(type, result);\n return result;\n } catch {\n return [];\n }\n }\n\n async exists(type: string, name: string): Promise<boolean> {\n await this.ensureSchema();\n\n // Honor cache: a cached non-null payload implies existence.\n if (this.loadCache) {\n const cached = this.loadCache.get(this.cacheKey(type, name));\n if (cached !== undefined) return cached !== null;\n }\n\n try {\n const count = await this._count(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n return count > 0;\n } catch {\n return false;\n }\n }\n\n async stat(type: string, name: string): Promise<MetadataStats | null> {\n await this.ensureSchema();\n\n const key = this.cacheKey(type, name);\n if (this.statCache) {\n const cached = this.statCache.get(key);\n if (cached !== undefined) return cached;\n }\n\n try {\n const row = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n if (!row) {\n this.statCache?.set(key, null);\n return null;\n }\n\n const record = this.rowToRecord(row);\n const metadataStr = typeof row.metadata === 'string'\n ? row.metadata as string\n : JSON.stringify(row.metadata);\n\n const stats: MetadataStats = {\n size: metadataStr.length,\n mtime: record.updatedAt ?? record.createdAt ?? new Date().toISOString(),\n format: 'json',\n etag: record.checksum,\n };\n this.statCache?.set(key, stats);\n return stats;\n } catch {\n return null;\n }\n }\n\n async list(type: string): Promise<string[]> {\n await this.ensureSchema();\n\n if (this.listCache) {\n const cached = this.listCache.get(type);\n if (cached !== undefined) return cached;\n }\n\n try {\n const rows = await this._find(this.tableName, {\n where: this.baseFilter(type),\n fields: ['name'],\n });\n\n const names = rows\n .map(row => row.name as string)\n .filter(name => typeof name === 'string');\n\n this.listCache?.set(type, names);\n return names;\n } catch {\n return [];\n }\n }\n\n /**\n * Fetch a single history snapshot by (type, name, version).\n * Returns null when the record does not exist.\n */\n async getHistoryRecord(\n type: string,\n name: string,\n version: number\n ): Promise<MetadataHistoryRecord | null> {\n if (!this.trackHistory) return null;\n\n await this.ensureHistorySchema();\n\n // Resolve the parent metadata record ID\n const metadataRow = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n if (!metadataRow) return null;\n\n const filter: Record<string, unknown> = {\n metadata_id: metadataRow.id,\n version,\n };\n if (this.organizationId) {\n filter.organization_id = this.organizationId;\n }\n filter.project_id = this.projectId ?? null;\n\n const row = await this._findOne(this.historyTableName, {\n where: filter,\n });\n if (!row) return null;\n\n return {\n id: row.id as string,\n metadataId: row.metadata_id as string,\n name: row.name as string,\n type: row.type as string,\n version: row.version as number,\n operationType: row.operation_type as MetadataHistoryRecord['operationType'],\n metadata: typeof row.metadata === 'string' ? JSON.parse(row.metadata as string) : row.metadata,\n checksum: row.checksum as string,\n previousChecksum: row.previous_checksum as string | undefined,\n changeNote: row.change_note as string | undefined,\n organizationId: row.organization_id as string | undefined,\n projectId: row.project_id as string | undefined,\n recordedBy: row.recorded_by as string | undefined,\n recordedAt: row.recorded_at as string,\n };\n }\n\n /**\n * Query history records with pagination and filtering.\n * Encapsulates history table queries so MetadataManager doesn't need\n * direct driver access.\n */\n async queryHistory(\n type: string,\n name: string,\n options?: {\n operationType?: string;\n since?: string;\n until?: string;\n limit?: number;\n offset?: number;\n includeMetadata?: boolean;\n }\n ): Promise<{ records: any[]; total: number; hasMore: boolean }> {\n if (!this.trackHistory) {\n return { records: [], total: 0, hasMore: false };\n }\n\n await this.ensureSchema();\n await this.ensureHistorySchema();\n\n // Find the metadata record\n const filter: Record<string, unknown> = { type, name };\n if (this.organizationId) filter.organization_id = this.organizationId;\n filter.project_id = this.projectId ?? null;\n\n const metadataRecord = await this._findOne(this.tableName, { where: filter });\n if (!metadataRecord) {\n return { records: [], total: 0, hasMore: false };\n }\n\n // Build history query\n const historyFilter: Record<string, unknown> = {\n metadata_id: metadataRecord.id,\n };\n if (this.organizationId) historyFilter.organization_id = this.organizationId;\n historyFilter.project_id = this.projectId ?? null;\n if (options?.operationType) historyFilter.operation_type = options.operationType;\n if (options?.since) historyFilter.recorded_at = { $gte: options.since };\n if (options?.until) {\n if (historyFilter.recorded_at) {\n (historyFilter.recorded_at as Record<string, unknown>).$lte = options.until;\n } else {\n historyFilter.recorded_at = { $lte: options.until };\n }\n }\n\n const limit = options?.limit ?? 50;\n const offset = options?.offset ?? 0;\n\n const historyRecords = await this._find(this.historyTableName, {\n where: historyFilter,\n orderBy: [\n { field: 'recorded_at', order: 'desc' as const },\n { field: 'version', order: 'desc' as const },\n ],\n limit: limit + 1,\n offset,\n });\n\n const hasMore = historyRecords.length > limit;\n const records = historyRecords.slice(0, limit);\n const total = await this._count(this.historyTableName, { where: historyFilter });\n\n const includeMetadata = options?.includeMetadata !== false;\n const result = records.map((row: Record<string, unknown>) => {\n const parsedMetadata =\n typeof row.metadata === 'string'\n ? JSON.parse(row.metadata as string)\n : (row.metadata as Record<string, unknown> | null | undefined);\n\n return {\n id: row.id as string,\n metadataId: row.metadata_id as string,\n name: row.name as string,\n type: row.type as string,\n version: row.version as number,\n operationType: row.operation_type as string,\n metadata: includeMetadata ? parsedMetadata : null,\n checksum: row.checksum as string,\n previousChecksum: row.previous_checksum as string | undefined,\n changeNote: row.change_note as string | undefined,\n organizationId: row.organization_id as string | undefined,\n projectId: row.project_id as string | undefined,\n recordedBy: row.recorded_by as string | undefined,\n recordedAt: row.recorded_at as string,\n };\n });\n\n return { records: result, total, hasMore };\n }\n\n /**\n * Perform a rollback: persist `restoredData` as the new current state and record a\n * single 'revert' history entry (instead of the usual 'update' entry that `save()`\n * would produce). This avoids the duplicate-version problem that arises when\n * `register()` → `save()` writes an 'update' entry followed by an additional\n * 'revert' entry for the same version number.\n */\n async registerRollback(\n type: string,\n name: string,\n restoredData: unknown,\n targetVersion: number,\n changeNote?: string,\n recordedBy?: string\n ): Promise<void> {\n await this.ensureSchema();\n\n const now = new Date().toISOString();\n const metadataJson = JSON.stringify(restoredData);\n const newChecksum = await calculateChecksum(restoredData);\n\n const existing = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n if (!existing) {\n throw new Error(`Metadata ${type}/${name} not found for rollback`);\n }\n\n const previousChecksum = existing.checksum as string | undefined;\n const newVersion = ((existing.version as number) ?? 0) + 1;\n\n await this._update(this.tableName, existing.id as string, {\n metadata: metadataJson,\n version: newVersion,\n checksum: newChecksum,\n updated_at: now,\n state: 'active',\n });\n\n this.invalidate(type, name);\n\n // Write exactly one 'revert' history entry (not an 'update' entry)\n await this.createHistoryRecord(\n existing.id as string,\n type,\n name,\n newVersion,\n restoredData,\n 'revert',\n previousChecksum,\n changeNote ?? `Rolled back to version ${targetVersion}`,\n recordedBy\n );\n }\n\n async save(\n type: string,\n name: string,\n data: any,\n _options?: MetadataSaveOptions\n ): Promise<MetadataSaveResult> {\n const startTime = Date.now();\n\n await this.ensureSchema();\n\n const now = new Date().toISOString();\n const metadataJson = JSON.stringify(data);\n const newChecksum = await calculateChecksum(data);\n\n try {\n const existing = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n if (existing) {\n // Skip update if the content is identical (prevents phantom version bumps)\n const previousChecksum = existing.checksum as string | undefined;\n if (newChecksum === previousChecksum) {\n // No DB write, but make sure the cached payload reflects the latest\n // call (prior cached `null` would otherwise mask a freshly-saved\n // record).\n this.loadCache?.set(this.cacheKey(type, name), data as Record<string, unknown>);\n return {\n success: true,\n path: `datasource://${this.tableName}/${type}/${name}`,\n size: metadataJson.length,\n saveTime: Date.now() - startTime,\n };\n }\n\n // Update existing record\n const version = ((existing.version as number) ?? 0) + 1;\n\n await this._update(this.tableName, existing.id as string, {\n metadata: metadataJson,\n version,\n checksum: newChecksum,\n updated_at: now,\n state: 'active',\n });\n\n this.invalidate(type, name);\n\n // Create history record for update\n await this.createHistoryRecord(\n existing.id as string,\n type,\n name,\n version,\n data,\n 'update',\n previousChecksum\n );\n\n return {\n success: true,\n path: `datasource://${this.tableName}/${type}/${name}`,\n size: metadataJson.length,\n saveTime: Date.now() - startTime,\n };\n } else {\n // Create new record\n const id = generateId();\n await this._create(this.tableName, {\n id,\n name,\n type,\n namespace: 'default',\n scope: (data as any)?.scope ?? 'platform',\n metadata: metadataJson,\n checksum: newChecksum,\n strategy: 'merge',\n state: 'active',\n version: 1,\n source: 'database',\n ...(this.organizationId ? { organization_id: this.organizationId } : {}),\n ...(this.projectId !== undefined ? { project_id: this.projectId } : { project_id: null }),\n created_at: now,\n updated_at: now,\n });\n\n this.invalidate(type, name);\n\n // Create history record for creation\n await this.createHistoryRecord(\n id,\n type,\n name,\n 1,\n data,\n 'create'\n );\n\n return {\n success: true,\n path: `datasource://${this.tableName}/${type}/${name}`,\n size: metadataJson.length,\n saveTime: Date.now() - startTime,\n };\n }\n } catch (error) {\n throw new Error(\n `DatabaseLoader save failed for ${type}/${name}: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n /**\n * Delete a metadata item from the database\n */\n async delete(type: string, name: string): Promise<void> {\n await this.ensureSchema();\n\n // Find the existing record to get its ID\n const existing = await this._findOne(this.tableName, {\n where: this.baseFilter(type, name),\n });\n\n if (!existing) {\n // Item doesn't exist, nothing to delete\n return;\n }\n\n // Delete from the main metadata table using the record's ID\n await this._delete(this.tableName, existing.id as string);\n\n this.invalidate(type, name);\n }\n}\n\n/**\n * Generate a simple unique ID for metadata records.\n * Uses crypto.randomUUID when available, falls back to timestamp-based ID.\n */\nfunction generateId(): string {\n if (typeof globalThis.crypto !== 'undefined' && typeof globalThis.crypto.randomUUID === 'function') {\n return globalThis.crypto.randomUUID();\n }\n // Fallback for environments without crypto.randomUUID\n return `meta_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata History Utilities\n *\n * Utility functions for metadata versioning and history tracking,\n * including checksum calculation, JSON normalization, and diff generation.\n */\n\n/**\n * Calculate SHA-256 checksum of normalized JSON metadata.\n * Normalizes the JSON by sorting keys and removing whitespace\n * to ensure consistent checksums across identical content.\n *\n * @param metadata - The metadata object to checksum\n * @returns SHA-256 hex string\n */\nexport async function calculateChecksum(metadata: unknown): Promise<string> {\n // Normalize JSON by sorting keys recursively\n const normalized = normalizeJSON(metadata);\n const jsonString = JSON.stringify(normalized);\n\n // Use Web Crypto API (available in Node.js 15+ and all modern browsers)\n if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.subtle) {\n const encoder = new TextEncoder();\n const data = encoder.encode(jsonString);\n const hashBuffer = await globalThis.crypto.subtle.digest('SHA-256', data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');\n }\n\n // Fallback for environments without Web Crypto API\n // Use a simple hash function (not cryptographically secure, but sufficient for change detection)\n return simpleHash(jsonString);\n}\n\n/**\n * Normalize JSON by recursively sorting object keys.\n * This ensures deterministic serialization for checksum calculation.\n *\n * @param value - The value to normalize\n * @returns Normalized value with sorted keys\n */\nfunction normalizeJSON(value: unknown): unknown {\n if (value === null || value === undefined) {\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map(normalizeJSON);\n }\n\n if (typeof value === 'object') {\n const sorted: Record<string, unknown> = {};\n const keys = Object.keys(value as object).sort();\n for (const key of keys) {\n sorted[key] = normalizeJSON((value as Record<string, unknown>)[key]);\n }\n return sorted;\n }\n\n return value;\n}\n\n/**\n * Simple hash function fallback for environments without Web Crypto API.\n * Based on djb2 hash algorithm.\n *\n * @param str - String to hash\n * @returns Hex hash string\n */\nfunction simpleHash(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash) + str.charCodeAt(i);\n hash = hash & hash; // Convert to 32-bit integer\n }\n // Convert to hex and pad to 64 characters to match SHA-256 length\n const hexHash = Math.abs(hash).toString(16);\n return hexHash.padStart(64, '0');\n}\n\n/**\n * Generate a simple JSON patch between two objects.\n * Returns an array of operations showing what changed.\n *\n * @param oldObj - Original object\n * @param newObj - New object\n * @param path - Current path (for recursion)\n * @returns Array of change operations\n */\nexport function generateSimpleDiff(\n oldObj: unknown,\n newObj: unknown,\n path: string = ''\n): Array<{ op: string; path: string; value?: unknown; oldValue?: unknown }> {\n const changes: Array<{ op: string; path: string; value?: unknown; oldValue?: unknown }> = [];\n\n // Handle primitives\n if (typeof oldObj !== 'object' || oldObj === null || typeof newObj !== 'object' || newObj === null) {\n if (oldObj !== newObj) {\n changes.push({ op: 'replace', path: path || '/', value: newObj, oldValue: oldObj });\n }\n return changes;\n }\n\n // Handle arrays\n if (Array.isArray(oldObj) || Array.isArray(newObj)) {\n if (!Array.isArray(oldObj) || !Array.isArray(newObj) || oldObj.length !== newObj.length) {\n changes.push({ op: 'replace', path: path || '/', value: newObj, oldValue: oldObj });\n } else {\n // Compare array elements\n for (let i = 0; i < oldObj.length; i++) {\n const subPath = `${path}/${i}`;\n changes.push(...generateSimpleDiff(oldObj[i], newObj[i], subPath));\n }\n }\n return changes;\n }\n\n // Handle objects\n const oldKeys = new Set(Object.keys(oldObj as object));\n const newKeys = new Set(Object.keys(newObj as object));\n\n // Check for added keys\n for (const key of newKeys) {\n if (!oldKeys.has(key)) {\n const subPath = path ? `${path}/${key}` : `/${key}`;\n changes.push({ op: 'add', path: subPath, value: (newObj as Record<string, unknown>)[key] });\n }\n }\n\n // Check for removed keys\n for (const key of oldKeys) {\n if (!newKeys.has(key)) {\n const subPath = path ? `${path}/${key}` : `/${key}`;\n changes.push({ op: 'remove', path: subPath, oldValue: (oldObj as Record<string, unknown>)[key] });\n }\n }\n\n // Check for modified keys\n for (const key of oldKeys) {\n if (newKeys.has(key)) {\n const subPath = path ? `${path}/${key}` : `/${key}`;\n changes.push(...generateSimpleDiff(\n (oldObj as Record<string, unknown>)[key],\n (newObj as Record<string, unknown>)[key],\n subPath\n ));\n }\n }\n\n return changes;\n}\n\n/**\n * Generate a human-readable summary of changes.\n *\n * @param diff - The diff operations\n * @returns Human-readable summary\n */\nexport function generateDiffSummary(\n diff: Array<{ op: string; path: string; value?: unknown; oldValue?: unknown }>\n): string {\n if (diff.length === 0) {\n return 'No changes';\n }\n\n const summary: string[] = [];\n const addCount = diff.filter(d => d.op === 'add').length;\n const removeCount = diff.filter(d => d.op === 'remove').length;\n const replaceCount = diff.filter(d => d.op === 'replace').length;\n\n if (addCount > 0) summary.push(`${addCount} field${addCount > 1 ? 's' : ''} added`);\n if (removeCount > 0) summary.push(`${removeCount} field${removeCount > 1 ? 's' : ''} removed`);\n if (replaceCount > 0) summary.push(`${replaceCount} field${replaceCount > 1 ? 's' : ''} modified`);\n\n return summary.join(', ');\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Generic LRU (Least Recently Used) cache with optional TTL.\n *\n * Implementation notes:\n * - Backed by a `Map`, which preserves insertion order. We promote entries on\n * read by deleting and re-inserting, so the oldest entry is always\n * `map.keys().next()`.\n * - TTL is checked lazily on `get` / `has`. Expired entries are evicted on\n * access; we do not run a background sweeper to keep the implementation\n * side-effect free in serverless / edge runtimes.\n * - Set `maxSize <= 0` to disable the size cap; set `ttl <= 0` (or omit) to\n * disable expiration.\n *\n * Designed for `DatabaseLoader` read-path caching — see\n * `packages/metadata/src/loaders/database-loader.ts`.\n */\nexport interface LRUCacheOptions {\n /** Maximum number of entries; when exceeded, the LRU entry is evicted. */\n maxSize?: number;\n /** Time-to-live in milliseconds. Zero or undefined disables TTL. */\n ttl?: number;\n}\n\ninterface Entry<V> {\n value: V;\n expiresAt: number; // 0 means \"never\"\n}\n\nexport class LRUCache<K, V> {\n private readonly map = new Map<K, Entry<V>>();\n private readonly maxSize: number;\n private readonly ttl: number;\n private hits = 0;\n private misses = 0;\n\n constructor(options: LRUCacheOptions = {}) {\n this.maxSize = options.maxSize && options.maxSize > 0 ? options.maxSize : 0;\n this.ttl = options.ttl && options.ttl > 0 ? options.ttl : 0;\n }\n\n get(key: K): V | undefined {\n const entry = this.map.get(key);\n if (!entry) {\n this.misses++;\n return undefined;\n }\n if (entry.expiresAt !== 0 && entry.expiresAt <= Date.now()) {\n this.map.delete(key);\n this.misses++;\n return undefined;\n }\n // Promote to most-recently-used.\n this.map.delete(key);\n this.map.set(key, entry);\n this.hits++;\n return entry.value;\n }\n\n set(key: K, value: V): void {\n if (this.map.has(key)) {\n this.map.delete(key);\n } else if (this.maxSize > 0 && this.map.size >= this.maxSize) {\n const oldest = this.map.keys().next();\n if (!oldest.done) this.map.delete(oldest.value);\n }\n this.map.set(key, {\n value,\n expiresAt: this.ttl > 0 ? Date.now() + this.ttl : 0,\n });\n }\n\n has(key: K): boolean {\n return this.get(key) !== undefined;\n }\n\n delete(key: K): boolean {\n return this.map.delete(key);\n }\n\n clear(): void {\n this.map.clear();\n }\n\n get size(): number {\n return this.map.size;\n }\n\n /** Diagnostic counters — useful for `metrics` endpoints. */\n stats(): { size: number; hits: number; misses: number; hitRate: number } {\n const total = this.hits + this.misses;\n return {\n size: this.map.size,\n hits: this.hits,\n misses: this.misses,\n hitRate: total === 0 ? 0 : this.hits / total,\n };\n }\n\n /** Resets hit/miss counters without dropping cached entries. */\n resetStats(): void {\n this.hits = 0;\n this.misses = 0;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Migration: ensure overlay-uniqueness index exists on `sys_metadata`.\n *\n * ADR-0005 Phase 1 — Overlay rows must be uniquely keyed by\n * `(type, name, organization_id, project_id, scope)` for active rows only.\n * The previous `(type, name, project_id)` unique constraint pre-dated\n * multi-tenant overlays and would incorrectly reject per-org customizations.\n *\n * Behaviour:\n * - SQLite / Postgres: creates a partial UNIQUE INDEX with `WHERE state = 'active'`.\n * - MySQL (no partial-index support): falls back to a non-unique composite index\n * plus an application-level guard (handled in `protocol.ts saveMetaItem`).\n * - Idempotent — uses `CREATE INDEX IF NOT EXISTS`. Safe to run on every boot.\n * - Best-effort: failures are recorded but never throw, so tenant boot is\n * not blocked on a database that doesn't support partial indexes.\n *\n * Usage:\n * import { addSysMetadataOverlayIndex } from '@objectstack/metadata/migrations';\n * await addSysMetadataOverlayIndex(driver);\n *\n * The `DatabaseLoader.ensureSchema()` invokes this automatically after the\n * `sys_metadata` table is created/synced, so most callers do not need to\n * invoke it directly.\n */\n\nimport type { IDataDriver } from '@objectstack/spec/contracts';\n\nconst INDEX_NAME = 'idx_sys_metadata_overlay_active';\nconst TABLE = 'sys_metadata';\nconst COLUMNS = '(type, name, organization_id, project_id, scope)';\nconst WHERE = \"state = 'active'\";\n\nexport interface AddSysMetadataOverlayIndexResult {\n index: string;\n status: 'created' | 'already_exists' | 'fallback_non_unique' | 'unsupported' | 'error';\n error?: string;\n}\n\n/**\n * Ensure the overlay-uniqueness index exists on `sys_metadata`.\n *\n * @param driver An `IDataDriver` exposing a `raw(sql, bindings?)` method.\n */\nexport async function addSysMetadataOverlayIndex(\n driver: IDataDriver,\n): Promise<AddSysMetadataOverlayIndexResult> {\n const driverAny = driver as any;\n const exec = async (sql: string): Promise<void> => {\n if (typeof driverAny.raw === 'function') {\n await driverAny.raw(sql);\n } else if (typeof driverAny.execute === 'function') {\n await driverAny.execute(sql);\n } else {\n throw new Error('driver has neither raw nor execute');\n }\n };\n\n const partialSql = `CREATE UNIQUE INDEX IF NOT EXISTS ${INDEX_NAME} ON ${TABLE} ${COLUMNS} WHERE ${WHERE}`;\n const fallbackSql = `CREATE INDEX IF NOT EXISTS ${INDEX_NAME} ON ${TABLE} ${COLUMNS}`;\n\n try {\n await exec(partialSql);\n return { index: INDEX_NAME, status: 'created' };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n\n // Partial-index unsupported (typically MySQL): fall back to a plain composite index.\n if (/partial|where clause|syntax/i.test(msg)) {\n try {\n await exec(fallbackSql);\n return { index: INDEX_NAME, status: 'fallback_non_unique' };\n } catch (fallbackErr) {\n return {\n index: INDEX_NAME,\n status: 'error',\n error:\n fallbackErr instanceof Error\n ? fallbackErr.message\n : String(fallbackErr),\n };\n }\n }\n\n if (/already exists/i.test(msg)) {\n return { index: INDEX_NAME, status: 'already_exists' };\n }\n\n return { index: INDEX_NAME, status: 'error', error: msg };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { readFile } from 'node:fs/promises';\nimport { createHash } from 'node:crypto';\nimport { Plugin, PluginContext } from '@objectstack/core';\nimport { NodeMetadataManager } from './node-metadata-manager.js';\nimport { MemoryLoader } from './loaders/memory-loader.js';\nimport { DEFAULT_METADATA_TYPE_REGISTRY } from '@objectstack/spec/kernel';\nimport type { MetadataPluginConfig } from '@objectstack/spec/kernel';\nimport {\n SysMetadataObject,\n SysMetadataHistoryObject,\n} from '@objectstack/platform-objects/metadata';\n\n// `SysMetadataObject` + `SysMetadataHistoryObject` are the customer overlay\n// storage substrate (ADR-0005). They must always be auto-provisioned so\n// `PUT /api/v1/meta/{view,dashboard}/...` has a place to write. All other\n// metadata types (object/view/flow/agent/tool/dashboard/app/...) live as\n// JSON inside `sys_metadata` — there are no separate per-type tables. The\n// previously shipped `SysObject` / `SysView` / `SysFlow` / `SysAgent` /\n// `SysTool` projection objects were removed in 2026-05 (see ADR 0005\n// addendum); the projection pipeline was removed at the same time.\nconst queryableMetadataObjects = [\n SysMetadataObject,\n SysMetadataHistoryObject,\n];\n\n// Map from ObjectStackDefinition field name to MetadataType name\nconst ARTIFACT_FIELD_TO_TYPE: Record<string, string> = {\n objects: 'object',\n objectExtensions: 'object_extension',\n apps: 'app',\n views: 'view',\n pages: 'page',\n dashboards: 'dashboard',\n reports: 'report',\n actions: 'action',\n themes: 'theme',\n workflows: 'workflow',\n approvals: 'approval',\n flows: 'flow',\n roles: 'role',\n permissions: 'permission',\n sharingRules: 'sharing_rule',\n policies: 'policy',\n apis: 'api',\n webhooks: 'webhook',\n agents: 'agent',\n skills: 'skill',\n ragPipelines: 'rag_pipeline',\n hooks: 'hook',\n mappings: 'mapping',\n analyticsCubes: 'analytics_cube',\n connectors: 'connector',\n data: 'dataset',\n};\n\nexport interface MetadataPluginOptions {\n rootDir?: string;\n watch?: boolean;\n config?: Partial<MetadataPluginConfig>;\n /** Organization ID for metadata-scoped consumers; MetadataPlugin itself does not persist runtime metadata. */\n organizationId?: string;\n /** Project ID used by local artifact envelopes and metadata-scoped consumers. */\n projectId?: string;\n /**\n * When set, MetadataPlugin loads metadata from an artifact instead of scanning\n * the filesystem. Only `local-file` is implemented now; `artifact-api` is\n * reserved for M3/M4.\n */\n artifactSource?:\n | { mode: 'local-file'; path: string; fetchTimeoutMs?: number }\n | { mode: 'artifact-api'; url: string; token?: string; commitId?: string; fetchTimeoutMs?: number };\n /**\n * Register the `sys_metadata` + `sys_metadata_history` storage objects\n * on this kernel. Default `true` for backward compatibility.\n *\n * Set to `false` for **per-project** kernels: in cloud / project mode the\n * control plane is the sole owner of metadata storage tables — exposing\n * them inside each project kernel would leak control-plane schema into\n * business-data namespaces.\n */\n registerSystemObjects?: boolean;\n}\n\nexport class MetadataPlugin implements Plugin {\n name = 'com.objectstack.metadata';\n type = 'standard';\n version = '1.0.0';\n\n private manager: NodeMetadataManager;\n private options: MetadataPluginOptions;\n\n constructor(options: MetadataPluginOptions = {}) {\n this.options = {\n watch: true,\n ...options\n };\n\n const rootDir = this.options.rootDir || process.cwd();\n\n // Sealed-runtime carve-out: `bootstrap: 'artifact-only'` MUST NOT touch\n // the filesystem at all — that includes chokidar subscriptions. Force\n // watch off in that mode regardless of `options.watch`. The other two\n // modes ('eager', 'lazy') honor the user's flag; `lazy` + watch is a\n // valid combination because chokidar attaches to `rootDir` directly,\n // not as a side effect of any priming pass.\n const bootstrapMode = this.options.config?.bootstrap ?? 'eager';\n const effectiveWatch =\n bootstrapMode === 'artifact-only' ? false : (this.options.watch ?? true);\n\n this.manager = new NodeMetadataManager({\n rootDir,\n watch: effectiveWatch,\n formats: ['yaml', 'json', 'typescript', 'javascript']\n });\n\n // Initialize with default type registry\n this.manager.setTypeRegistry(DEFAULT_METADATA_TYPE_REGISTRY);\n }\n\n init = async (ctx: PluginContext) => {\n ctx.logger.info('Initializing Metadata Manager', {\n root: this.options.rootDir || process.cwd(),\n watch: this.options.watch,\n artifactSource: this.options.artifactSource?.mode,\n });\n\n // Register Metadata Manager as the primary metadata service provider.\n ctx.registerService('metadata', this.manager);\n console.log('[MetadataPlugin] Registered metadata service, has getRegisteredTypes:', typeof this.manager.getRegisteredTypes);\n\n // Register metadata system objects via the manifest service (if available).\n // MetadataPlugin may init before ObjectQLPlugin, so wrap in try/catch.\n // Skipped when `registerSystemObjects: false` (per-project kernels in\n // cloud / project mode — sys_* live exclusively in the control plane).\n const registerSysObjects = this.options.registerSystemObjects !== false;\n if (registerSysObjects) {\n try {\n const manifestService = ctx.getService<{ register(m: any): void }>('manifest');\n\n // Register the queryable metadata-layer platform objects.\n manifestService.register({\n id: 'com.objectstack.metadata-objects',\n name: 'Metadata Platform Objects',\n version: '1.0.0',\n type: 'plugin',\n scope: 'system',\n defaultDatasource: 'cloud',\n objects: queryableMetadataObjects,\n });\n\n ctx.logger.info('Registered system metadata objects', {\n queryable: queryableMetadataObjects.map((object) => object.name),\n });\n } catch {\n // ObjectQL not loaded yet — objects will be discovered via legacy fallback\n }\n }\n\n ctx.logger.info('MetadataPlugin providing metadata service (primary mode)', {\n mode: this.options.artifactSource?.mode ?? 'file-system',\n features: ['watch', 'multi-format', 'query', 'overlay', 'type-registry']\n });\n }\n\n start = async (ctx: PluginContext) => {\n const src = this.options.artifactSource;\n const mode = this.options.config?.bootstrap ?? 'eager';\n\n ctx.logger.info('[MetadataPlugin] Bootstrapping metadata', {\n bootstrap: mode,\n artifactSource: src?.mode ?? 'none',\n });\n\n if (mode === 'artifact-only') {\n // Sealed-runtime mode: ONLY load from a pre-compiled artifact. Never\n // touch the filesystem. Required for Edge / serverless / read-only\n // production deployments where the running process must not depend\n // on local source files.\n if (src?.mode === 'local-file') {\n await this._loadFromLocalFile(ctx, src.path, src.fetchTimeoutMs);\n } else if (src?.mode === 'artifact-api') {\n await this._loadFromArtifactApi(ctx, src);\n } else {\n throw new Error('[MetadataPlugin] bootstrap=artifact-only requires options.artifactSource to be set');\n }\n } else if (mode === 'lazy') {\n // On-demand mode: skip the eager filesystem priming pass entirely.\n // Reads go through MetadataManager.load*/list* which are backed by\n // the DatabaseLoader read-through cache and any registered loaders.\n // An artifact source, if present, is still honored so projects can\n // pin a known set of metadata at boot without paying the FS scan.\n if (src?.mode === 'local-file') {\n await this._loadFromLocalFile(ctx, src.path, src.fetchTimeoutMs);\n } else if (src?.mode === 'artifact-api') {\n await this._loadFromArtifactApi(ctx, src);\n } else {\n ctx.logger.info('[MetadataPlugin] lazy bootstrap — skipping filesystem priming; metadata loads on demand');\n }\n } else {\n // 'eager' (default): preserve historical behavior.\n if (src?.mode === 'local-file') {\n await this._loadFromLocalFile(ctx, src.path, src.fetchTimeoutMs);\n } else if (src?.mode === 'artifact-api') {\n await this._loadFromArtifactApi(ctx, src);\n } else {\n await this._loadFromFileSystem(ctx);\n }\n }\n\n // Bridge realtime service from kernel service registry to MetadataManager.\n try {\n const realtimeService = ctx.getService('realtime');\n if (realtimeService && typeof realtimeService === 'object' && 'publish' in realtimeService) {\n ctx.logger.info('[MetadataPlugin] Bridging realtime service to MetadataManager for event publishing');\n this.manager.setRealtimeService(realtimeService as any);\n }\n } catch (e: any) {\n ctx.logger.debug('[MetadataPlugin] No realtime service found — metadata events will not be published', {\n error: e.message,\n });\n }\n }\n\n /**\n * Fetch JSON content from a URL with configurable timeout.\n */\n private async _fetchJson(url: string, fetchTimeoutMs?: number, token?: string): Promise<unknown> {\n const envTimeout = Number(process.env.OS_ARTIFACT_FETCH_TIMEOUT_MS);\n const timeoutMs = fetchTimeoutMs\n ?? (Number.isFinite(envTimeout) && envTimeout > 0 ? envTimeout : undefined)\n ?? 60_000;\n const controller = new AbortController();\n const timer = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : undefined;\n try {\n const headers: Record<string, string> = { Accept: 'application/json, */*;q=0.5' };\n if (token) headers.Authorization = `Bearer ${token}`;\n const res = await fetch(url, { redirect: 'follow', signal: controller.signal, headers });\n if (!res.ok) throw new Error(`HTTP ${res.status} ${res.statusText}`);\n const content = await res.text();\n return JSON.parse(content);\n } catch (e: any) {\n if (e?.name === 'AbortError') {\n throw new Error(\n `fetch timed out after ${timeoutMs}ms — set artifactSource.fetchTimeoutMs or OS_ARTIFACT_FETCH_TIMEOUT_MS to extend it (0 disables)`,\n );\n }\n throw e;\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n\n /**\n * Parse raw artifact JSON (envelope or bare definition) and register all\n * metadata items into the MetadataManager.\n */\n private async _parseAndRegisterArtifact(ctx: PluginContext, raw: unknown, label: string): Promise<number> {\n const { ProjectArtifactSchema } = await import('@objectstack/spec/cloud');\n const { ObjectStackDefinitionSchema } = await import('@objectstack/spec');\n\n let metadata: Record<string, unknown[]>;\n\n const obj = raw as any;\n if (obj?.schemaVersion && obj?.commitId && obj?.metadata !== undefined) {\n const artifact = ProjectArtifactSchema.parse(obj);\n metadata = artifact.metadata as Record<string, unknown[]>;\n } else if (obj?.success && obj?.data?.metadata) {\n // Unwrap cloud API envelope: { success: true, data: { metadata: {...} } }\n const artifact = ProjectArtifactSchema.parse(obj.data);\n metadata = artifact.metadata as Record<string, unknown[]>;\n } else {\n const def = ObjectStackDefinitionSchema.parse(obj);\n const canonical = JSON.stringify(def, Object.keys(def).sort());\n const checksum = createHash('sha256').update(canonical).digest('hex');\n const projectId = this.options.projectId ?? 'proj_local';\n ProjectArtifactSchema.parse({\n schemaVersion: '0.1',\n projectId,\n commitId: 'local-dev',\n checksum,\n metadata: def,\n });\n metadata = def as Record<string, unknown[]>;\n }\n\n const memLoader = new MemoryLoader();\n const manifestPackageId =\n (metadata as any)?.manifest?.id ?? (metadata as any)?.id ?? undefined;\n\n let totalRegistered = 0;\n for (const [field, metaType] of Object.entries(ARTIFACT_FIELD_TO_TYPE)) {\n const items = (metadata as any)[field];\n if (!Array.isArray(items) || items.length === 0) continue;\n for (const item of items) {\n const name = (item as any)?.name;\n if (!name) continue;\n if (manifestPackageId && (item as any)._packageId === undefined) {\n (item as any)._packageId = manifestPackageId;\n }\n await memLoader.save(metaType, name, item);\n await this.manager.register(metaType, name, item);\n totalRegistered++;\n }\n }\n\n this.manager.registerLoader(memLoader);\n ctx.logger.info('[MetadataPlugin] Artifact metadata loaded', { source: label, totalRegistered });\n return totalRegistered;\n }\n\n private async _loadFromLocalFile(ctx: PluginContext, filePath: string, fetchTimeoutMs?: number): Promise<void> {\n const isUrl = /^https?:\\/\\//i.test(filePath);\n ctx.logger.info(\n `[MetadataPlugin] Loading metadata from ${isUrl ? 'remote URL' : 'local artifact file'}`,\n { path: filePath },\n );\n\n let raw: unknown;\n try {\n if (isUrl) {\n raw = await this._fetchJson(filePath, fetchTimeoutMs);\n } else {\n const content = await readFile(filePath, 'utf8');\n raw = JSON.parse(content);\n }\n } catch (e: any) {\n throw new Error(`[MetadataPlugin] Cannot read artifact ${isUrl ? 'URL' : 'file'} at \"${filePath}\": ${e.message}`);\n }\n\n await this._parseAndRegisterArtifact(ctx, raw, filePath);\n }\n\n /**\n * P2: Load metadata from the cloud artifact API endpoint.\n */\n private async _loadFromArtifactApi(\n ctx: PluginContext,\n src: { url: string; token?: string; commitId?: string; fetchTimeoutMs?: number },\n ): Promise<void> {\n const projectId = this.options.projectId;\n if (!projectId) {\n throw new Error('[MetadataPlugin] artifact-api source requires options.projectId to be set');\n }\n\n // Build the artifact URL:\n // ${url}/api/v1/cloud/projects/${projectId}/artifact[?commit=${commitId}]\n let artifactUrl = src.url.replace(/\\/+$/, '');\n // If the URL already contains /api/v1, use it as-is; otherwise append default path.\n if (!/\\/api\\/v\\d+\\/cloud\\/projects\\//i.test(artifactUrl)) {\n artifactUrl = `${artifactUrl}/api/v1/cloud/projects/${projectId}/artifact`;\n }\n if (src.commitId) {\n artifactUrl += `${artifactUrl.includes('?') ? '&' : '?'}commit=${encodeURIComponent(src.commitId)}`;\n }\n\n ctx.logger.info('[MetadataPlugin] Loading metadata from artifact API', { url: artifactUrl });\n\n let raw: unknown;\n try {\n raw = await this._fetchJson(artifactUrl, src.fetchTimeoutMs, src.token);\n } catch (e: any) {\n throw new Error(`[MetadataPlugin] Cannot load artifact from API \"${artifactUrl}\": ${e.message}`);\n }\n\n await this._parseAndRegisterArtifact(ctx, raw, artifactUrl);\n }\n\n private async _loadFromFileSystem(ctx: PluginContext): Promise<void> {\n ctx.logger.info('Loading metadata from file system...');\n\n const sortedTypes = [...DEFAULT_METADATA_TYPE_REGISTRY]\n .sort((a, b) => a.loadOrder - b.loadOrder);\n\n let totalLoaded = 0;\n for (const entry of sortedTypes) {\n try {\n const items = await this.manager.loadMany(entry.type, {\n recursive: true,\n patterns: entry.filePatterns,\n });\n\n if (items.length > 0) {\n for (const item of items) {\n const meta = item as any;\n if (meta?.name) {\n await this.manager.register(entry.type, meta.name, item);\n }\n }\n ctx.logger.info(`Loaded ${items.length} ${entry.type} from file system`);\n totalLoaded += items.length;\n }\n } catch (e: any) {\n ctx.logger.debug(`No ${entry.type} metadata found`, { error: e.message });\n }\n }\n\n ctx.logger.info('Metadata loading complete', {\n totalItems: totalLoaded,\n registeredTypes: sortedTypes.length,\n });\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Node Metadata Manager\n * \n * Extends MetadataManager with Filesystem capabilities (Watching, default loader)\n */\n\nimport * as path from 'node:path';\nimport { watch as chokidarWatch, type FSWatcher } from 'chokidar';\nimport type {\n MetadataWatchEvent,\n} from '@objectstack/spec/system';\nimport { FilesystemLoader } from './loaders/filesystem-loader.js';\nimport { MetadataManager, type MetadataManagerOptions } from './metadata-manager.js';\n\n/**\n * Node metadata manager class\n */\nexport class NodeMetadataManager extends MetadataManager {\n private watcher?: FSWatcher;\n\n constructor(config: MetadataManagerOptions) {\n super(config);\n\n // Initialize Default Filesystem Loader if no loaders provided\n // This logic replaces the removed logic from base class\n if (!config.loaders || config.loaders.length === 0) {\n const rootDir = config.rootDir || process.cwd();\n this.registerLoader(new FilesystemLoader(rootDir, this.serializers, this.logger));\n }\n\n // Start watching if enabled\n if (config.watch) {\n this.startWatching();\n }\n }\n\n /**\n * Stop all watching\n */\n async stopWatching(): Promise<void> {\n if (this.watcher) {\n await this.watcher.close();\n this.watcher = undefined;\n }\n // Call base cleanup if any\n }\n\n /**\n * Start watching for file changes\n */\n private startWatching(): void {\n const rootDir = this.config.rootDir || process.cwd();\n const { ignored = ['**/node_modules/**', '**/*.test.*'], persistent = true } =\n this.config.watchOptions || {};\n\n this.watcher = chokidarWatch(rootDir, {\n ignored,\n persistent,\n ignoreInitial: true,\n });\n\n this.watcher.on('add', async (filePath) => {\n await this.handleFileEvent('added', filePath);\n });\n\n this.watcher.on('change', async (filePath) => {\n await this.handleFileEvent('changed', filePath);\n });\n\n this.watcher.on('unlink', async (filePath) => {\n await this.handleFileEvent('deleted', filePath);\n });\n\n this.logger.info('File watcher started', { rootDir });\n }\n\n /**\n * Handle file change events\n */\n private async handleFileEvent(\n eventType: 'added' | 'changed' | 'deleted',\n filePath: string\n ): Promise<void> {\n const rootDir = this.config.rootDir || process.cwd();\n const relativePath = path.relative(rootDir, filePath);\n const parts = relativePath.split(path.sep);\n\n if (parts.length < 2) {\n return; // Not a metadata file\n }\n\n const type = parts[0];\n const fileName = parts[parts.length - 1];\n const name = path.basename(fileName, path.extname(fileName));\n\n // We can't access private watchCallbacks from parent.\n // We need a protected method to trigger watch event or access it.\n // OPTION: Add a method `triggerWatchEvent` to MetadataManager\n \n let data: any = undefined;\n if (eventType !== 'deleted') {\n try {\n data = await this.load(type, name, { useCache: false });\n } catch (error) {\n this.logger.error('Failed to load changed file', undefined, {\n filePath,\n error: error instanceof Error ? error.message : String(error),\n });\n return;\n }\n }\n\n const event: MetadataWatchEvent = {\n type: eventType,\n metadataType: type,\n name,\n path: filePath,\n data,\n timestamp: new Date().toISOString(),\n };\n\n this.notifyWatchers(type, event);\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Filesystem Metadata Loader\n * \n * Loads metadata from the filesystem using glob patterns\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { glob } from 'glob';\nimport { createHash } from 'node:crypto';\nimport type {\n MetadataLoadOptions,\n MetadataLoadResult,\n MetadataStats,\n MetadataLoaderContract,\n MetadataFormat,\n MetadataSaveOptions,\n MetadataSaveResult,\n} from '@objectstack/spec/system';\nimport type { Logger } from '@objectstack/core';\nimport type { MetadataLoader } from './loader-interface.js';\nimport type { MetadataSerializer } from '../serializers/serializer-interface.js';\n\nexport class FilesystemLoader implements MetadataLoader {\n readonly contract: MetadataLoaderContract = {\n name: 'filesystem',\n protocol: 'file:',\n capabilities: {\n read: true,\n write: true,\n watch: true,\n list: true,\n },\n supportedFormats: ['json', 'yaml', 'typescript', 'javascript'],\n supportsWatch: true,\n supportsWrite: true,\n supportsCache: true,\n };\n\n private cache = new Map<string, { data: any; etag: string; timestamp: number }>();\n\n constructor(\n private rootDir: string,\n private serializers: Map<MetadataFormat, MetadataSerializer>,\n private logger?: Logger\n ) {}\n\n async load(\n type: string,\n name: string,\n options?: MetadataLoadOptions\n ): Promise<MetadataLoadResult> {\n const startTime = Date.now();\n const { validate: _validate = true, useCache = true, ifNoneMatch } = options || {};\n\n try {\n // Find the file\n const filePath = await this.findFile(type, name);\n\n if (!filePath) {\n return {\n data: null,\n fromCache: false,\n notModified: false,\n loadTime: Date.now() - startTime,\n };\n }\n\n // Get stats\n const stats = await this.stat(type, name);\n\n if (!stats) {\n return {\n data: null,\n fromCache: false,\n notModified: false,\n loadTime: Date.now() - startTime,\n };\n }\n\n // Check cache\n if (useCache && ifNoneMatch && stats.etag === ifNoneMatch) {\n return {\n data: null,\n fromCache: true,\n notModified: true,\n etag: stats.etag,\n stats,\n loadTime: Date.now() - startTime,\n };\n }\n\n // Check memory cache\n const cacheKey = `${type}:${name}`;\n if (useCache && this.cache.has(cacheKey)) {\n const cached = this.cache.get(cacheKey)!;\n if (cached.etag === stats.etag) {\n return {\n data: cached.data,\n fromCache: true,\n notModified: false,\n etag: stats.etag,\n stats,\n loadTime: Date.now() - startTime,\n };\n }\n }\n\n // Load and deserialize\n const content = await fs.readFile(filePath, 'utf-8');\n const serializer = this.getSerializer(stats.format!);\n\n if (!serializer) {\n throw new Error(`No serializer found for format: ${stats.format}`);\n }\n\n const data = serializer.deserialize(content);\n\n // Update cache\n if (useCache) {\n this.cache.set(cacheKey, {\n data,\n etag: stats.etag || '',\n timestamp: Date.now(),\n });\n }\n\n return {\n data,\n fromCache: false,\n notModified: false,\n etag: stats.etag,\n stats,\n loadTime: Date.now() - startTime,\n };\n } catch (error) {\n this.logger?.error('Failed to load metadata', undefined, {\n type,\n name,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n async loadMany<T = any>(\n type: string,\n options?: MetadataLoadOptions\n ): Promise<T[]> {\n const { patterns = ['**/*'], recursive: _recursive = true, limit } = options || {};\n\n const typeDir = path.join(this.rootDir, type);\n const items: T[] = [];\n\n try {\n // Build glob patterns\n const globPatterns = patterns.map(pattern =>\n path.join(typeDir, pattern)\n );\n\n for (const pattern of globPatterns) {\n const files = await glob(pattern, {\n ignore: ['**/node_modules/**', '**/*.test.*', '**/*.spec.*', '**/*[*]*'],\n nodir: true,\n });\n\n for (const file of files) {\n if (limit && items.length >= limit) {\n break;\n }\n\n try {\n const content = await fs.readFile(file, 'utf-8');\n const format = this.detectFormat(file);\n const serializer = this.getSerializer(format);\n\n if (serializer) {\n const data = serializer.deserialize<T>(content);\n items.push(data);\n }\n } catch (error) {\n this.logger?.warn('Failed to load file', {\n file,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n if (limit && items.length >= limit) {\n break;\n }\n }\n\n return items;\n } catch (error) {\n this.logger?.error('Failed to load many', undefined, {\n type,\n patterns,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n async exists(type: string, name: string): Promise<boolean> {\n const filePath = await this.findFile(type, name);\n return filePath !== null;\n }\n\n async stat(type: string, name: string): Promise<MetadataStats | null> {\n const filePath = await this.findFile(type, name);\n\n if (!filePath) {\n return null;\n }\n\n try {\n const stats = await fs.stat(filePath);\n const content = await fs.readFile(filePath, 'utf-8');\n const etag = this.generateETag(content);\n const format = this.detectFormat(filePath);\n\n return {\n size: stats.size,\n modifiedAt: stats.mtime.toISOString(),\n etag,\n format,\n path: filePath,\n };\n } catch (error) {\n this.logger?.error('Failed to stat file', undefined, {\n type,\n name,\n filePath,\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n }\n\n async list(type: string): Promise<string[]> {\n const typeDir = path.join(this.rootDir, type);\n\n try {\n const files = await glob('**/*', {\n cwd: typeDir,\n ignore: ['**/node_modules/**', '**/*.test.*', '**/*.spec.*'],\n nodir: true,\n });\n\n return files.map(file => {\n const ext = path.extname(file);\n const basename = path.basename(file, ext);\n return basename;\n });\n } catch (error) {\n this.logger?.error('Failed to list', undefined, {\n type,\n error: error instanceof Error ? error.message : String(error),\n });\n return [];\n }\n }\n\n async save(\n type: string,\n name: string,\n data: any,\n options?: MetadataSaveOptions\n ): Promise<MetadataSaveResult> {\n const startTime = Date.now();\n const {\n format = 'typescript',\n prettify = true,\n indent = 2,\n sortKeys = false,\n backup = false,\n overwrite = true,\n atomic = true,\n path: customPath,\n } = options || {};\n\n try {\n // Get serializer\n const serializer = this.getSerializer(format);\n if (!serializer) {\n throw new Error(`No serializer found for format: ${format}`);\n }\n\n // Determine file path\n const typeDir = path.join(this.rootDir, type);\n const fileName = `${name}${serializer.getExtension()}`;\n const filePath = customPath || path.join(typeDir, fileName);\n\n // Check if file exists\n if (!overwrite) {\n try {\n await fs.access(filePath);\n throw new Error(`File already exists: ${filePath}`);\n } catch (error) {\n // File doesn't exist, continue\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error;\n }\n }\n }\n\n // Create directory if it doesn't exist\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n\n // Create backup if requested\n let backupPath: string | undefined;\n if (backup) {\n try {\n await fs.access(filePath);\n backupPath = `${filePath}.bak`;\n await fs.copyFile(filePath, backupPath);\n } catch {\n // File doesn't exist, no backup needed\n }\n }\n\n // Serialize data\n const content = serializer.serialize(data, {\n prettify,\n indent,\n sortKeys,\n });\n\n // Write to disk (atomic or direct)\n if (atomic) {\n const tempPath = `${filePath}.tmp`;\n await fs.writeFile(tempPath, content, 'utf-8');\n await fs.rename(tempPath, filePath);\n } else {\n await fs.writeFile(filePath, content, 'utf-8');\n }\n\n // Update cache logic if needed (e.g., invalidate or update)\n // For now, we rely on the watcher to pick up changes\n\n return {\n success: true,\n path: filePath,\n // format, // Not in schema\n size: Buffer.byteLength(content, 'utf-8'),\n backupPath,\n saveTime: Date.now() - startTime,\n };\n } catch (error) {\n this.logger?.error('Failed to save metadata', undefined, {\n type,\n name,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n /**\n * Find file for a given type and name\n */\n private async findFile(type: string, name: string): Promise<string | null> {\n const typeDir = path.join(this.rootDir, type);\n const extensions = ['.json', '.yaml', '.yml', '.ts', '.js'];\n\n for (const ext of extensions) {\n const filePath = path.join(typeDir, `${name}${ext}`);\n\n try {\n await fs.access(filePath);\n return filePath;\n } catch {\n // File doesn't exist, try next extension\n }\n }\n\n return null;\n }\n\n /**\n * Detect format from file extension\n */\n private detectFormat(filePath: string): MetadataFormat {\n const ext = path.extname(filePath).toLowerCase();\n\n switch (ext) {\n case '.json':\n return 'json';\n case '.yaml':\n case '.yml':\n return 'yaml';\n case '.ts':\n return 'typescript';\n case '.js':\n return 'javascript';\n default:\n return 'json'; // Default to JSON\n }\n }\n\n /**\n * Get serializer for format\n */\n private getSerializer(format: MetadataFormat): MetadataSerializer | undefined {\n return this.serializers.get(format);\n }\n\n /**\n * Generate ETag for content\n * Uses SHA-256 hash truncated to 32 characters for reasonable collision resistance\n * while keeping ETag headers compact (full 64-char hash is overkill for this use case)\n */\n private generateETag(content: string): string {\n const hash = createHash('sha256').update(content).digest('hex').substring(0, 32);\n return `\"${hash}\"`;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Memory Metadata Loader\n * \n * Stores metadata in memory only. Changes are lost when process restarts.\n * Useful for testing, temporary overrides, or \"dirty\" edits.\n */\n\nimport type {\n MetadataLoadOptions,\n MetadataLoadResult,\n MetadataStats,\n MetadataLoaderContract,\n MetadataSaveOptions,\n MetadataSaveResult,\n} from '@objectstack/spec/system';\nimport type { MetadataLoader } from './loader-interface.js';\n\nexport class MemoryLoader implements MetadataLoader {\n readonly contract: MetadataLoaderContract = {\n name: 'memory',\n protocol: 'memory:',\n capabilities: {\n read: true,\n write: true,\n watch: false,\n list: true,\n },\n };\n\n // Storage: Type -> Name -> Data\n private storage = new Map<string, Map<string, any>>();\n\n async load(\n type: string,\n name: string,\n _options?: MetadataLoadOptions\n ): Promise<MetadataLoadResult> {\n const typeStore = this.storage.get(type);\n const data = typeStore?.get(name);\n\n if (data) {\n return {\n data,\n source: 'memory',\n format: 'json',\n loadTime: 0,\n };\n }\n\n return { data: null };\n }\n\n async loadMany<T = any>(\n type: string,\n _options?: MetadataLoadOptions\n ): Promise<T[]> {\n const typeStore = this.storage.get(type);\n if (!typeStore) return [];\n return Array.from(typeStore.values()) as T[];\n }\n\n async exists(type: string, name: string): Promise<boolean> {\n return this.storage.get(type)?.has(name) ?? false;\n }\n\n async stat(type: string, name: string): Promise<MetadataStats | null> {\n if (await this.exists(type, name)) {\n return {\n size: 0, // In-memory\n mtime: new Date().toISOString(),\n format: 'json',\n };\n }\n return null;\n }\n\n async list(type: string): Promise<string[]> {\n const typeStore = this.storage.get(type);\n if (!typeStore) return [];\n return Array.from(typeStore.keys());\n }\n\n async save(\n type: string,\n name: string,\n data: any,\n _options?: MetadataSaveOptions\n ): Promise<MetadataSaveResult> {\n if (!this.storage.has(type)) {\n this.storage.set(type, new Map());\n }\n\n this.storage.get(type)!.set(name, data);\n\n return {\n success: true,\n path: `memory://${type}/${name}`,\n saveTime: 0,\n };\n }\n\n /**\n * Delete a metadata item from memory storage\n */\n async delete(type: string, name: string): Promise<void> {\n const typeStore = this.storage.get(type);\n if (typeStore) {\n typeStore.delete(name);\n if (typeStore.size === 0) {\n this.storage.delete(type);\n }\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Remote Metadata Loader\n * \n * Loads metadata from an HTTP API.\n * This loader is stateless and delegates storage to the remote server.\n */\n\nimport type {\n MetadataLoadOptions,\n MetadataLoadResult,\n MetadataStats,\n MetadataLoaderContract,\n MetadataSaveOptions,\n MetadataSaveResult,\n} from '@objectstack/spec/system';\nimport type { MetadataLoader } from './loader-interface.js';\n\nexport class RemoteLoader implements MetadataLoader {\n readonly contract: MetadataLoaderContract = {\n name: 'remote',\n protocol: 'http:',\n capabilities: {\n read: true,\n write: true,\n watch: false, // Could implement SSE/WebSocket in future\n list: true,\n },\n };\n\n constructor(private baseUrl: string, private authToken?: string) {}\n\n private get headers() {\n return {\n 'Content-Type': 'application/json',\n ...(this.authToken ? { Authorization: `Bearer ${this.authToken}` } : {}),\n };\n }\n\n async load(\n type: string,\n name: string,\n _options?: MetadataLoadOptions\n ): Promise<MetadataLoadResult> {\n try {\n const response = await fetch(`${this.baseUrl}/${type}/${name}`, {\n method: 'GET',\n headers: this.headers,\n });\n\n if (response.status === 404) {\n return { data: null };\n }\n\n if (!response.ok) {\n throw new Error(`Remote load failed: ${response.statusText}`);\n }\n\n const data = await response.json();\n return {\n data,\n source: this.baseUrl,\n format: 'json',\n loadTime: 0, \n };\n } catch (error) {\n console.error(`RemoteLoader error loading ${type}/${name}`, error);\n throw error;\n }\n }\n\n async loadMany<T = any>(\n type: string,\n _options?: MetadataLoadOptions\n ): Promise<T[]> {\n const response = await fetch(`${this.baseUrl}/${type}`, {\n method: 'GET',\n headers: this.headers,\n });\n\n if (!response.ok) {\n return [];\n }\n\n return (await response.json()) as T[];\n }\n\n async exists(type: string, name: string): Promise<boolean> {\n const response = await fetch(`${this.baseUrl}/${type}/${name}`, {\n method: 'HEAD',\n headers: this.headers,\n });\n return response.ok;\n }\n\n async stat(type: string, name: string): Promise<MetadataStats | null> {\n // Basic implementation using HEAD\n const response = await fetch(`${this.baseUrl}/${type}/${name}`, {\n method: 'HEAD',\n headers: this.headers,\n });\n \n if (!response.ok) return null;\n\n return {\n size: Number(response.headers.get('content-length') || 0),\n mtime: new Date(response.headers.get('last-modified') || Date.now()).toISOString(),\n format: 'json',\n };\n }\n\n async list(type: string): Promise<string[]> {\n const items = await this.loadMany<{ name: string }>(type);\n return items.map(i => i.name);\n }\n\n async save(\n type: string,\n name: string,\n data: any,\n _options?: MetadataSaveOptions\n ): Promise<MetadataSaveResult> {\n const response = await fetch(`${this.baseUrl}/${type}/${name}`, {\n method: 'PUT',\n headers: this.headers,\n body: JSON.stringify(data),\n });\n\n if (!response.ok) {\n throw new Error(`Remote save failed: ${response.statusText}`);\n }\n\n return {\n success: true,\n path: `${this.baseUrl}/${type}/${name}`,\n saveTime: 0,\n };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/metadata\n * \n * Metadata loading, saving, and persistence for ObjectStack.\n * Implements the IMetadataService contract from @objectstack/spec.\n */\n\n// Main Manager\nexport { MetadataManager, type WatchCallback, type MetadataManagerOptions } from './metadata-manager.js';\n\n// Plugin\nexport { MetadataPlugin } from './plugin.js';\n\n// Loaders\nexport { type MetadataLoader } from './loaders/loader-interface.js';\nexport { MemoryLoader } from './loaders/memory-loader.js';\nexport { RemoteLoader } from './loaders/remote-loader.js';\nexport { DatabaseLoader, type DatabaseLoaderOptions } from './loaders/database-loader.js';\n\n// Objects\nexport { SysMetadataObject, SysMetadataHistoryObject } from '@objectstack/platform-objects/metadata';\n\n// Routes\nexport { registerMetadataHistoryRoutes } from './routes/history-routes.js';\n\n// Utils\nexport { calculateChecksum, generateSimpleDiff, generateDiffSummary } from './utils/metadata-history-utils.js';\nexport { HistoryCleanupManager } from './utils/history-cleanup.js';\n\n// Serializers\nexport { type MetadataSerializer, type SerializeOptions } from './serializers/serializer-interface.js';\nexport { JSONSerializer } from './serializers/json-serializer.js';\nexport { YAMLSerializer } from './serializers/yaml-serializer.js';\nexport * as Migration from './migration/index.js';\nexport { TypeScriptSerializer } from './serializers/typescript-serializer.js';\n\n// Re-export types from spec\nexport type {\n MetadataFormat,\n MetadataStats,\n MetadataLoadOptions,\n MetadataSaveOptions,\n MetadataExportOptions,\n MetadataImportOptions,\n MetadataLoadResult,\n MetadataSaveResult,\n MetadataWatchEvent,\n MetadataCollectionInfo,\n MetadataLoaderContract,\n MetadataManagerConfig,\n MetadataHistoryRecord,\n MetadataHistoryQueryOptions,\n MetadataHistoryQueryResult,\n MetadataDiffResult,\n MetadataHistoryRetentionPolicy,\n} from '@objectstack/spec/system';\n\n// Re-export IMetadataService contract\nexport type {\n IMetadataService,\n MetadataWatchCallback,\n MetadataWatchHandle,\n MetadataTypeInfo,\n MetadataImportResult,\n} from '@objectstack/spec/contracts';\n\n// Re-export kernel types for plugin protocol\nexport type {\n MetadataType,\n MetadataTypeRegistryEntry,\n MetadataPluginConfig,\n MetadataPluginManifest,\n MetadataQuery,\n MetadataQueryResult,\n MetadataValidationResult,\n MetadataBulkResult,\n MetadataDependency,\n} from '@objectstack/spec/kernel';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata History API Routes\n *\n * REST API endpoints for metadata version history, rollback, and diff operations.\n * These routes extend the standard metadata API with history-specific functionality.\n *\n * Routes:\n * - GET /api/v1/metadata/:type/:name/history - Get version history\n * - POST /api/v1/metadata/:type/:name/rollback - Rollback to a specific version\n * - GET /api/v1/metadata/:type/:name/diff - Compare two versions\n */\n\nimport type { IMetadataService } from '@objectstack/spec/contracts';\n\n/**\n * Register metadata history routes on a Hono app or any HTTP server.\n *\n * @param app - The HTTP server/router instance (Hono-compatible)\n * @param metadataService - The metadata service instance\n */\nexport function registerMetadataHistoryRoutes(\n app: any, // Hono app or compatible\n metadataService: IMetadataService\n): void {\n /**\n * GET /api/v1/metadata/:type/:name/history\n * Get version history for a metadata item\n *\n * Query parameters:\n * - limit: number (default: 50)\n * - offset: number (default: 0)\n * - since: ISO datetime string\n * - until: ISO datetime string\n * - operationType: create | update | publish | revert | delete\n * - includeMetadata: boolean (default: true)\n */\n app.get('/api/v1/metadata/:type/:name/history', async (c: any) => {\n if (!metadataService.getHistory) {\n return c.json({ error: 'History tracking not enabled' }, 501);\n }\n\n const { type, name } = c.req.param();\n const query = c.req.query();\n\n try {\n const options: any = {};\n\n if (query.limit !== undefined) {\n const limit = parseInt(query.limit, 10);\n if (!Number.isFinite(limit) || limit < 1) {\n return c.json({ success: false, error: 'limit must be a positive integer' }, 400);\n }\n options.limit = limit;\n }\n if (query.offset !== undefined) {\n const offset = parseInt(query.offset, 10);\n if (!Number.isFinite(offset) || offset < 0) {\n return c.json({ success: false, error: 'offset must be a non-negative integer' }, 400);\n }\n options.offset = offset;\n }\n if (query.since) options.since = query.since;\n if (query.until) options.until = query.until;\n if (query.operationType) options.operationType = query.operationType;\n if (query.includeMetadata !== undefined) {\n options.includeMetadata = query.includeMetadata === 'true';\n }\n\n const result = await metadataService.getHistory(type, name, options);\n\n return c.json({\n success: true,\n data: result,\n });\n } catch (error) {\n return c.json(\n {\n success: false,\n error: error instanceof Error ? error.message : 'Failed to retrieve history',\n },\n 500\n );\n }\n });\n\n /**\n * POST /api/v1/metadata/:type/:name/rollback\n * Rollback a metadata item to a specific version\n *\n * Body:\n * - version: number (required) - Target version to rollback to\n * - changeNote: string (optional) - Description of rollback\n * - recordedBy: string (optional) - User performing rollback\n */\n app.post('/api/v1/metadata/:type/:name/rollback', async (c: any) => {\n if (!metadataService.rollback) {\n return c.json({ error: 'Rollback not supported' }, 501);\n }\n\n const { type, name } = c.req.param();\n\n try {\n const body = await c.req.json();\n const { version, changeNote, recordedBy } = body;\n\n if (typeof version !== 'number') {\n return c.json(\n {\n success: false,\n error: 'Version number is required',\n },\n 400\n );\n }\n\n const restoredMetadata = await metadataService.rollback(type, name, version, {\n changeNote,\n recordedBy,\n });\n\n return c.json({\n success: true,\n data: {\n type,\n name,\n version,\n metadata: restoredMetadata,\n },\n });\n } catch (error) {\n return c.json(\n {\n success: false,\n error: error instanceof Error ? error.message : 'Rollback failed',\n },\n 500\n );\n }\n });\n\n /**\n * GET /api/v1/metadata/:type/:name/diff\n * Compare two versions of a metadata item\n *\n * Query parameters:\n * - version1: number (required) - First version (older)\n * - version2: number (required) - Second version (newer)\n */\n app.get('/api/v1/metadata/:type/:name/diff', async (c: any) => {\n if (!metadataService.diff) {\n return c.json({ error: 'Diff not supported' }, 501);\n }\n\n const { type, name } = c.req.param();\n const query = c.req.query();\n\n try {\n const version1 = parseInt(query.version1, 10);\n const version2 = parseInt(query.version2, 10);\n\n if (isNaN(version1) || isNaN(version2)) {\n return c.json(\n {\n success: false,\n error: 'Both version1 and version2 query parameters are required',\n },\n 400\n );\n }\n\n const diffResult = await metadataService.diff(type, name, version1, version2);\n\n return c.json({\n success: true,\n data: diffResult,\n });\n } catch (error) {\n return c.json(\n {\n success: false,\n error: error instanceof Error ? error.message : 'Diff failed',\n },\n 500\n );\n }\n });\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Metadata History Retention and Cleanup\n *\n * Manages automatic cleanup of old history records based on retention policies.\n * Supports both age-based and count-based retention strategies.\n */\n\nimport type { IDataDriver } from '@objectstack/spec/contracts';\nimport type { MetadataHistoryRetentionPolicy } from '@objectstack/spec/system';\nimport type { DatabaseLoader } from '../loaders/database-loader.js';\n\n/**\n * History Cleanup Manager\n *\n * Handles automatic cleanup of metadata history records based on\n * configured retention policies.\n */\nexport class HistoryCleanupManager {\n private policy: MetadataHistoryRetentionPolicy;\n private dbLoader: DatabaseLoader;\n private cleanupTimer?: NodeJS.Timeout;\n\n constructor(policy: MetadataHistoryRetentionPolicy, dbLoader: DatabaseLoader) {\n this.policy = policy;\n this.dbLoader = dbLoader;\n }\n\n /**\n * Start automatic cleanup if enabled in the policy.\n */\n start(): void {\n if (!this.policy.autoCleanup) {\n return;\n }\n\n const intervalMs = (this.policy.cleanupIntervalHours ?? 24) * 60 * 60 * 1000;\n\n // Run cleanup immediately on start\n void this.runCleanup();\n\n // Schedule periodic cleanup\n this.cleanupTimer = setInterval(() => {\n void this.runCleanup();\n }, intervalMs);\n }\n\n /**\n * Stop automatic cleanup.\n */\n stop(): void {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n this.cleanupTimer = undefined;\n }\n }\n\n /**\n * Run cleanup based on the retention policy.\n * Removes history records that exceed the configured limits.\n */\n async runCleanup(): Promise<{ deleted: number; errors: number }> {\n const driver = (this.dbLoader as any).driver as IDataDriver;\n const historyTableName = (this.dbLoader as any).historyTableName as string;\n const organizationId = (this.dbLoader as any).organizationId as string | undefined;\n const projectId = (this.dbLoader as any).projectId as string | undefined;\n\n let deleted = 0;\n let errors = 0;\n\n try {\n // Age-based cleanup\n if (this.policy.maxAgeDays) {\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - this.policy.maxAgeDays);\n const cutoffISO = cutoffDate.toISOString();\n\n const filter: Record<string, unknown> = {\n recorded_at: { $lt: cutoffISO },\n };\n\n if (organizationId) {\n filter.organization_id = organizationId;\n }\n if (projectId !== undefined) {\n filter.project_id = projectId;\n }\n\n try {\n const result = await this.bulkDeleteByFilter(driver, historyTableName, filter);\n deleted += result.deleted;\n errors += result.errors;\n } catch {\n errors++;\n }\n }\n\n // Count-based cleanup per metadata item\n if (this.policy.maxVersions) {\n try {\n // Get all unique metadata IDs\n const baseWhere: Record<string, unknown> = {};\n if (organizationId) baseWhere.organization_id = organizationId;\n if (projectId !== undefined) baseWhere.project_id = projectId;\n\n const metadataIds = await driver.find(historyTableName, {\n object: historyTableName,\n where: baseWhere,\n fields: ['metadata_id'],\n });\n\n const uniqueIds = new Set<string>();\n for (const record of metadataIds) {\n if (record.metadata_id) {\n uniqueIds.add(record.metadata_id as string);\n }\n }\n\n // For each metadata item, keep only the latest N versions\n for (const metadataId of uniqueIds) {\n const filter: Record<string, unknown> = { metadata_id: metadataId, ...baseWhere };\n\n try {\n // Fetch only the IDs of records beyond the retention limit (oldest first)\n const historyRecords = await driver.find(historyTableName, {\n object: historyTableName,\n where: filter,\n orderBy: [{ field: 'version', order: 'desc' as const }],\n fields: ['id'],\n });\n\n if (historyRecords.length > this.policy.maxVersions) {\n const toDelete = historyRecords.slice(this.policy.maxVersions);\n const ids = toDelete.map(r => r.id as string).filter(Boolean);\n const result = await this.bulkDeleteByIds(driver, historyTableName, ids);\n deleted += result.deleted;\n errors += result.errors;\n }\n } catch {\n errors++;\n }\n }\n } catch {\n errors++;\n }\n }\n } catch (error) {\n console.error('History cleanup failed:', error);\n errors++;\n }\n\n return { deleted, errors };\n }\n\n /**\n * Delete records matching a filter using the most efficient method available on the driver.\n */\n private async bulkDeleteByFilter(\n driver: IDataDriver,\n table: string,\n filter: Record<string, unknown>\n ): Promise<{ deleted: number; errors: number }> {\n const driverAny = driver as any;\n if (typeof driverAny.deleteMany === 'function') {\n const count = await driverAny.deleteMany(table, filter);\n return { deleted: typeof count === 'number' ? count : 0, errors: 0 };\n }\n\n // Fallback: fetch IDs then delete\n const records = await driver.find(table, { object: table, where: filter, fields: ['id'] });\n const ids = records.map((r: Record<string, unknown>) => r.id as string).filter(Boolean);\n return this.bulkDeleteByIds(driver, table, ids);\n }\n\n /**\n * Delete records by IDs using bulkDelete when available, otherwise one-by-one.\n */\n private async bulkDeleteByIds(\n driver: IDataDriver,\n table: string,\n ids: string[]\n ): Promise<{ deleted: number; errors: number }> {\n if (ids.length === 0) return { deleted: 0, errors: 0 };\n\n const driverAny = driver as any;\n if (typeof driverAny.bulkDelete === 'function') {\n const result = await driverAny.bulkDelete(table, ids);\n return {\n deleted: typeof result === 'number' ? result : ids.length,\n errors: 0,\n };\n }\n\n // Fallback: sequential deletes\n let deleted = 0;\n let errors = 0;\n for (const id of ids) {\n try {\n await driver.delete(table, id);\n deleted++;\n } catch {\n errors++;\n }\n }\n return { deleted, errors };\n }\n\n /**\n * Get cleanup statistics without actually deleting anything.\n * Useful for previewing what would be cleaned up.\n */\n async getCleanupStats(): Promise<{\n recordsByAge: number;\n recordsByCount: number;\n total: number;\n }> {\n const driver = (this.dbLoader as any).driver as IDataDriver;\n const historyTableName = (this.dbLoader as any).historyTableName as string;\n const organizationId = (this.dbLoader as any).organizationId as string | undefined;\n const projectId = (this.dbLoader as any).projectId as string | undefined;\n\n let recordsByAge = 0;\n let recordsByCount = 0;\n\n try {\n const baseWhere: Record<string, unknown> = {};\n if (organizationId) baseWhere.organization_id = organizationId;\n if (projectId !== undefined) baseWhere.project_id = projectId;\n\n // Count records that would be deleted by age\n if (this.policy.maxAgeDays) {\n const cutoffDate = new Date();\n cutoffDate.setDate(cutoffDate.getDate() - this.policy.maxAgeDays);\n const cutoffISO = cutoffDate.toISOString();\n\n const filter: Record<string, unknown> = {\n recorded_at: { $lt: cutoffISO },\n ...baseWhere,\n };\n\n recordsByAge = await driver.count(historyTableName, {\n object: historyTableName,\n where: filter,\n });\n }\n\n // Count records that would be deleted by version limit\n if (this.policy.maxVersions) {\n const metadataIds = await driver.find(historyTableName, {\n object: historyTableName,\n where: baseWhere,\n fields: ['metadata_id'],\n });\n\n const uniqueIds = new Set<string>();\n for (const record of metadataIds) {\n if (record.metadata_id) {\n uniqueIds.add(record.metadata_id as string);\n }\n }\n\n for (const metadataId of uniqueIds) {\n const filter: Record<string, unknown> = { metadata_id: metadataId, ...baseWhere };\n\n const count = await driver.count(historyTableName, {\n object: historyTableName,\n where: filter,\n });\n\n if (count > this.policy.maxVersions) {\n recordsByCount += count - this.policy.maxVersions;\n }\n }\n }\n } catch (error) {\n console.error('Failed to get cleanup stats:', error);\n }\n\n // Return separate counts. The total is an upper-bound estimate: it may overcount\n // records that qualify under both policies (age and count). Use recordsByAge and\n // recordsByCount individually for precise breakdowns.\n return {\n recordsByAge,\n recordsByCount,\n total: recordsByAge + recordsByCount,\n };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nexport * from './executor.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport * as System from '@objectstack/spec/system';\nimport { ISchemaDriver } from '@objectstack/spec/contracts';\n\nexport class MigrationExecutor {\n constructor(private driver: ISchemaDriver) {}\n\n async executeChangeSet(changeSet: System.ChangeSet): Promise<void> {\n console.log(`Executing ChangeSet: ${changeSet.name} (${changeSet.id})`);\n \n for (const op of changeSet.operations) {\n try {\n await this.executeOperation(op);\n } catch (e) {\n console.error(`Failed to execute operation ${op.type}:`, e);\n throw e;\n }\n }\n }\n\n private async executeOperation(op: System.MigrationOperation): Promise<void> {\n switch (op.type) {\n case 'create_object':\n console.log(` > Create Object: ${op.object.name}`);\n await this.driver.createCollection(op.object.name, op.object);\n break;\n case 'add_field':\n console.log(` > Add Field: ${op.objectName}.${op.fieldName}`);\n await this.driver.addColumn(op.objectName, op.fieldName, op.field);\n break;\n case 'remove_field':\n console.log(` > Remove Field: ${op.objectName}.${op.fieldName}`);\n await this.driver.dropColumn(op.objectName, op.fieldName);\n break;\n case 'delete_object':\n console.log(` > Delete Object: ${op.objectName}`);\n await this.driver.dropCollection(op.objectName);\n break;\n case 'execute_sql':\n console.log(` > Execute SQL`);\n await this.driver.executeRaw(op.sql);\n break;\n case 'modify_field':\n console.warn(` ! Modify Field: ${op.objectName}.${op.fieldName} (Not fully implemented)`);\n break;\n case 'rename_object':\n console.warn(` ! Rename Object: ${op.oldName} -> ${op.newName} (Not fully implemented)`);\n break;\n default:\n throw new Error(`Unknown operation type`);\n }\n }\n}\n"],"mappings":"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","names":["path","readFile","createHash","path","basename","SysMetadataObject","SysMetadataHistoryObject","createHash","readFile","SysMetadataObject","SysMetadataHistoryObject"]}