@happyvertical/smrt-core 0.36.8 → 0.37.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.
Files changed (105) hide show
  1. package/dist/child-accessors.d.ts +1 -1
  2. package/dist/child-accessors.d.ts.map +1 -1
  3. package/dist/child-accessors.js +1 -1
  4. package/dist/child-accessors.js.map +1 -1
  5. package/dist/class.d.ts.map +1 -1
  6. package/dist/class.js +3 -1
  7. package/dist/class.js.map +1 -1
  8. package/dist/collection-cache.d.ts.map +1 -1
  9. package/dist/collection-cache.js +5 -3
  10. package/dist/collection-cache.js.map +1 -1
  11. package/dist/collection.d.ts +39 -16
  12. package/dist/collection.d.ts.map +1 -1
  13. package/dist/collection.js +40 -19
  14. package/dist/collection.js.map +1 -1
  15. package/dist/consumer-plugin/index.js.map +1 -1
  16. package/dist/decorators/compatibility.d.ts +1 -1
  17. package/dist/decorators/compatibility.d.ts.map +1 -1
  18. package/dist/decorators/compatibility.js.map +1 -1
  19. package/dist/decorators/index.d.ts +4 -4
  20. package/dist/decorators/index.d.ts.map +1 -1
  21. package/dist/decorators/index.js.map +1 -1
  22. package/dist/hierarchical.d.ts.map +1 -1
  23. package/dist/hierarchical.js.map +1 -1
  24. package/dist/junction.d.ts.map +1 -1
  25. package/dist/junction.js.map +1 -1
  26. package/dist/manifest/discover-smrt-packages.d.ts +10 -0
  27. package/dist/manifest/discover-smrt-packages.d.ts.map +1 -1
  28. package/dist/manifest/discover-smrt-packages.js.map +1 -1
  29. package/dist/manifest/generator.d.ts.map +1 -1
  30. package/dist/manifest/generator.js +34 -37
  31. package/dist/manifest/generator.js.map +1 -1
  32. package/dist/manifest/index.js +2 -2
  33. package/dist/manifest/index.js.map +1 -1
  34. package/dist/manifest/manifest-loader.d.ts +10 -0
  35. package/dist/manifest/manifest-loader.d.ts.map +1 -1
  36. package/dist/manifest/manifest-loader.js.map +1 -1
  37. package/dist/manifest/static-manifest.d.ts.map +1 -1
  38. package/dist/manifest/static-manifest.js +39 -20
  39. package/dist/manifest/static-manifest.js.map +1 -1
  40. package/dist/manifest/store.js +2 -2
  41. package/dist/manifest/store.js.map +1 -1
  42. package/dist/manifest/test-manifest-stub.d.ts.map +1 -1
  43. package/dist/manifest/test-manifest-stub.js +2301 -629
  44. package/dist/manifest/test-manifest-stub.js.map +1 -1
  45. package/dist/manifest.json +39 -20
  46. package/dist/migrations/differ.d.ts +104 -13
  47. package/dist/migrations/differ.d.ts.map +1 -1
  48. package/dist/migrations/differ.js +199 -26
  49. package/dist/migrations/differ.js.map +1 -1
  50. package/dist/node_modules/.pnpm/{minimatch@10.2.3 → minimatch@10.2.5}/node_modules/minimatch/dist/esm/assert-valid-pattern.js.map +1 -1
  51. package/dist/node_modules/.pnpm/{minimatch@10.2.3 → minimatch@10.2.5}/node_modules/minimatch/dist/esm/ast.js +1 -7
  52. package/dist/node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/dist/esm/ast.js.map +1 -0
  53. package/dist/node_modules/.pnpm/{minimatch@10.2.3 → minimatch@10.2.5}/node_modules/minimatch/dist/esm/brace-expressions.js.map +1 -1
  54. package/dist/node_modules/.pnpm/{minimatch@10.2.3 → minimatch@10.2.5}/node_modules/minimatch/dist/esm/escape.js.map +1 -1
  55. package/dist/node_modules/.pnpm/{minimatch@10.2.3 → minimatch@10.2.5}/node_modules/minimatch/dist/esm/index.js +17 -14
  56. package/dist/node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/dist/esm/index.js.map +1 -0
  57. package/dist/node_modules/.pnpm/minimatch@10.2.5/node_modules/minimatch/dist/esm/unescape.js +10 -0
  58. package/dist/node_modules/.pnpm/{minimatch@10.2.3 → minimatch@10.2.5}/node_modules/minimatch/dist/esm/unescape.js.map +1 -1
  59. package/dist/object.d.ts +64 -17
  60. package/dist/object.d.ts.map +1 -1
  61. package/dist/object.js +76 -30
  62. package/dist/object.js.map +1 -1
  63. package/dist/registry/class-registration.d.ts +3 -3
  64. package/dist/registry/class-registration.d.ts.map +1 -1
  65. package/dist/registry/class-registration.js +39 -42
  66. package/dist/registry/class-registration.js.map +1 -1
  67. package/dist/registry/inheritance-resolver.d.ts +17 -3
  68. package/dist/registry/inheritance-resolver.d.ts.map +1 -1
  69. package/dist/registry/inheritance-resolver.js +1 -1
  70. package/dist/registry/inheritance-resolver.js.map +1 -1
  71. package/dist/registry/manifest-field-merge.d.ts +17 -3
  72. package/dist/registry/manifest-field-merge.d.ts.map +1 -1
  73. package/dist/registry/manifest-field-merge.js +8 -6
  74. package/dist/registry/manifest-field-merge.js.map +1 -1
  75. package/dist/registry/schema-builder.d.ts +1 -1
  76. package/dist/registry/schema-builder.d.ts.map +1 -1
  77. package/dist/registry/schema-builder.js.map +1 -1
  78. package/dist/registry/shared-state.d.ts +3 -3
  79. package/dist/registry/shared-state.d.ts.map +1 -1
  80. package/dist/registry/shared-state.js.map +1 -1
  81. package/dist/registry/types.d.ts +78 -19
  82. package/dist/registry/types.d.ts.map +1 -1
  83. package/dist/registry/validator.d.ts +2 -1
  84. package/dist/registry/validator.d.ts.map +1 -1
  85. package/dist/registry/validator.js +38 -39
  86. package/dist/registry/validator.js.map +1 -1
  87. package/dist/registry.d.ts +84 -57
  88. package/dist/registry.d.ts.map +1 -1
  89. package/dist/registry.js +31 -25
  90. package/dist/registry.js.map +1 -1
  91. package/dist/scanner/manifest-generator.d.ts.map +1 -1
  92. package/dist/scanner/manifest-generator.js +22 -20
  93. package/dist/scanner/manifest-generator.js.map +1 -1
  94. package/dist/smrt-knowledge.json +8 -7
  95. package/dist/system-fields.d.ts +1 -1
  96. package/dist/system-fields.d.ts.map +1 -1
  97. package/dist/system-fields.js.map +1 -1
  98. package/dist/vite-plugin/index.js +1 -1
  99. package/package.json +7 -7
  100. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/ast.js.map +0 -1
  101. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/index.js.map +0 -1
  102. package/dist/node_modules/.pnpm/minimatch@10.2.3/node_modules/minimatch/dist/esm/unescape.js +0 -10
  103. /package/dist/node_modules/.pnpm/{minimatch@10.2.3 → minimatch@10.2.5}/node_modules/minimatch/dist/esm/assert-valid-pattern.js +0 -0
  104. /package/dist/node_modules/.pnpm/{minimatch@10.2.3 → minimatch@10.2.5}/node_modules/minimatch/dist/esm/brace-expressions.js +0 -0
  105. /package/dist/node_modules/.pnpm/{minimatch@10.2.3 → minimatch@10.2.5}/node_modules/minimatch/dist/esm/escape.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sources":["../src/registry.ts"],"sourcesContent":["/**\n * Global object registry for SMRT classes\n *\n * Maintains a central registry of all @smrt decorated classes, enabling\n * module awareness, automatic API generation, and runtime introspection.\n * The registry tracks class definitions, field metadata, and configuration\n * options for code generation and runtime operations.\n *\n * @example Registering a class manually\n * ```typescript\n * import { ObjectRegistry } from '@happyvertical/smrt-core';\n *\n * ObjectRegistry.register(MyClass, {\n * api: { exclude: ['delete'] },\n * cli: true\n * });\n * ```\n *\n * @example Using the decorator (recommended)\n * ```typescript\n * import { smrt, field } from '@happyvertical/smrt-core';\n *\n * @smrt({ api: { exclude: ['delete'] } })\n * class Product extends SmrtObject {\n * @field({ required: true })\n * name: string = '';\n * }\n * ```\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { applyOneToManyChildAccessors } from './child-accessors';\nimport { SmrtCollection } from './collection';\nimport type { CollectionCacheConfig } from './collection-cache';\nimport { applyPendingDecoratorRegistrations } from './decorators/compatibility.js';\nimport type {\n ClassEmbeddingConfig,\n ProjectEmbeddingConfig,\n ResolvedEmbeddingConfig,\n} from './embeddings/types';\nimport { ConfigurationError } from './errors';\nimport { getDefaultCompositeSource } from './manifest/sources/composite.js';\nimport { ExplicitPathsManifestSource } from './manifest/sources/explicit-paths.js';\nimport {\n cloneManifestSchemaColumns,\n discoverCachedManifestSync,\n getNodeBuiltins,\n loadExternalManifestSyncWithNode,\n} from './manifest/store.js';\nimport type { SmrtObject } from './object';\n// ── Extracted modules (Issue #1006) ──────────────────────────────────────\nimport { resolveCollectionCacheConfig as _resolveCollectionCacheConfig } from './registry/cache-config';\nimport {\n invalidateInheritanceEntries as _invalidateInheritanceEntries,\n register as _register,\n registerCollection as _registerCollection,\n registerFromManifest as _registerFromManifest,\n} from './registry/class-registration';\nimport {\n clearRegistryDiagnostics,\n flushRegistryDiagnostics,\n getRegistryDiagnostics,\n type RegistryDiagnostic,\n recordRegistryDiagnostic,\n} from './registry/diagnostics';\nimport {\n getEmbeddingClasses as _getEmbeddingClasses,\n getEmbeddingConfig as _getEmbeddingConfig,\n getProjectEmbeddingConfig as _getProjectEmbeddingConfig,\n hasEmbeddings as _hasEmbeddings,\n resolveEmbeddingConfig as _resolveEmbeddingConfig,\n} from './registry/embedding-manager';\nimport {\n getAllFields as _getAllFields,\n getAllMethods as _getAllMethods,\n getInheritanceChain as _getInheritanceChain,\n mergeFieldConfigs as _mergeFieldConfigs,\n} from './registry/inheritance-resolver';\nimport {\n createFieldFromManifest,\n manifestFieldDiffers,\n mergeManifestField,\n} from './registry/manifest-field-merge.js';\nimport {\n findClass as _findClass,\n findClassesByName as _findClassesByName,\n getAllClasses as _getAllClasses,\n getCanonicalClassName as _getCanonicalClassName,\n getClass as _getClass,\n getClassByConstructor as _getClassByConstructor,\n getClassByQualifiedName as _getClassByQualifiedName,\n getClassesByPackage as _getClassesByPackage,\n getClassesByVisibility as _getClassesByVisibility,\n getClassInPackage as _getClassInPackage,\n getClassNames as _getClassNames,\n getPublicClasses as _getPublicClasses,\n getQualifiedClassNames as _getQualifiedClassNames,\n hasClass as _hasClass,\n hasClassCaseInsensitive as _hasClassCaseInsensitive,\n resolveType as _resolveType,\n} from './registry/name-resolver';\nimport {\n getDependencyGraph as _getDependencyGraph,\n getRelationshipMap as _getRelationshipMap,\n} from './registry/relationship-graph';\nimport {\n getAllSchemas as _getAllSchemas,\n getAllSchemasAsDefinitions as _getAllSchemasAsDefinitions,\n getSchema as _getSchema,\n getSchemaDDL as _getSchemaDDL,\n getTableName as _getTableName,\n} from './registry/schema-builder';\nimport {\n getClasses,\n getCollectionCache,\n getCollections,\n getCollectionTableNames,\n getDbInstanceIds,\n getDiscoveryAttemptCache,\n getFieldDecorators,\n getInheritanceCache,\n getNextDbId,\n getStiSiblingsLoaded,\n setNextDbId,\n verboseLog,\n} from './registry/shared-state';\nimport type {\n RegisteredClass,\n RelationshipMetadata,\n SmartObjectConfig,\n SmrtObjectConstructor,\n ValidatorFunction,\n} from './registry/types';\nimport { compileValidators as _compileValidators } from './registry/validator';\nimport type {\n QualifiedClassName,\n SmartObjectManifest,\n SmrtVisibility,\n ValidationRule,\n} from './scanner/types.js';\nimport type { ColumnDefinition, SchemaDefinition } from './schema/types.js';\nimport { classnameToTablename, toSnakeCase } from './utils';\nimport { LRUCache } from './utils/lru-cache';\nimport {\n createQualifiedName,\n isQualifiedName,\n parseQualifiedName,\n} from './utils/qualified-names.js';\n\nconst logger = createLogger({ level: 'info' });\n\n// Re-export the canonical collection-base detector so downstream tooling\n// (e.g. @happyvertical/smrt-vitest's manifest-based test-db builder) can share\n// the single source of truth instead of maintaining a drift-prone copy. The\n// junction-collection schema-drop bug (#1342) half-survived precisely because\n// a second copy of this detector existed; exporting it publicly kills that\n// drift class. See `./registry/collection-resolution.ts`.\nexport {\n isSmrtCollectionExtendsName,\n SMRT_COLLECTION_BASE_NAMES,\n} from './registry/collection-resolution';\n// Re-export types for backward compatibility\nexport type {\n RelationshipMetadata,\n RelationshipType,\n SmartObjectConfig,\n} from './registry/types';\n\n// Types, utility functions, and globalThis declarations have been extracted\n// to registry/types.ts and registry/shared-state.ts (Issue #1006).\n// The SmartObjectConfig, RelationshipType, and RelationshipMetadata types\n// are re-exported above for backward compatibility.\n\ntype ManifestLoaderModule = typeof import('./manifest/index.js');\n\nfunction getManifestLoaderSpecifier(): string {\n return import.meta.url.endsWith('.ts')\n ? './manifest/index.ts'\n : './manifest/index.js';\n}\n\nasync function importManifestLoader(): Promise<ManifestLoaderModule> {\n return (await import(getManifestLoaderSpecifier())) as ManifestLoaderModule;\n}\n\nfunction getReferenceKindFromFieldOptions(\n fieldOptions: any,\n): ColumnDefinition['referenceKind'] | undefined {\n if (\n fieldOptions?.__tenancy?.isTenantIdField ||\n fieldOptions?._meta?.__tenancy?.isTenantIdField\n ) {\n return 'tenantId';\n }\n\n if (fieldOptions?.type === 'foreignKey') {\n return 'foreignKey';\n }\n\n if (fieldOptions?.type === 'crossPackageRef') {\n return 'crossPackageRef';\n }\n\n return undefined;\n}\n\nfunction applyManifestFieldColumnMetadata(\n columns: Record<string, ColumnDefinition>,\n fieldEntries: Iterable<[string, any]> | undefined,\n): void {\n if (!fieldEntries) {\n return;\n }\n\n for (const [fieldName, fieldOptions] of fieldEntries) {\n const sqlType = fieldOptions?.sqlType ?? fieldOptions?._meta?.sqlType;\n const referenceKind = getReferenceKindFromFieldOptions(fieldOptions);\n if (!sqlType && !referenceKind) {\n continue;\n }\n\n const columnName = toSnakeCase(fieldName);\n const existingColumn = columns[columnName];\n if (!existingColumn) {\n continue;\n }\n\n columns[columnName] = {\n ...existingColumn,\n ...(sqlType\n ? { type: String(sqlType).toUpperCase() as ColumnDefinition['type'] }\n : {}),\n ...(referenceKind ? { referenceKind } : {}),\n };\n }\n}\n\nasync function discoverInstalledSmrtPackages(): Promise<string[]> {\n const discoverSpecifier = import.meta.url.endsWith('.ts')\n ? './manifest/discover-smrt-packages.ts'\n : './manifest/discover-smrt-packages.js';\n\n const { discoverSmrtPackages } = await import(discoverSpecifier);\n return discoverSmrtPackages();\n}\n\n/**\n * Recover a package's `manifest.json` when the path derived from the\n * `__smrt-register__` shim's `import.meta.url` does not exist.\n *\n * The shim resolves the manifest with `new URL('./manifest.json',\n * import.meta.url)`, which assumes the compiled side-effect sits directly\n * next to `dist/manifest.json`. Vite chunk-splitting is non-deterministic and\n * occasionally hoists that side-effect into a `dist/chunks/<hash>.js` chunk,\n * so the URL resolves to a non-existent `dist/chunks/manifest.json`. This\n * walks up a bounded number of parent directories looking for a sibling\n * `manifest.json`, keeping self-registration working regardless of where the\n * bundler placed the shim (#1331).\n *\n * @param builtins - Node fs/path/url modules from `getNodeBuiltins()`.\n * @param missingPath - The non-existent manifest path the shim derived.\n * @returns The recovered manifest path, or `null` if none was found.\n */\nfunction resolveManifestByUpwardSearch(\n builtins: NonNullable<ReturnType<typeof getNodeBuiltins>>,\n missingPath: string,\n): string | null {\n const { fs, path } = builtins;\n const fileName = path.basename(missingPath);\n // Bound the walk so a stray, deeply-nested path can never trigger a slow or\n // unbounded filesystem crawl. Chunks are normally one directory deep\n // (`dist/chunks/`), so a handful of levels is comfortably sufficient. The\n // package-root stop below is the authoritative guard; this is just a backstop.\n const MAX_LEVELS = 4;\n let dir = path.dirname(missingPath);\n for (let level = 0; level < MAX_LEVELS; level++) {\n const parent = path.dirname(dir);\n // Reached the filesystem root — `dirname` is now idempotent.\n if (parent === dir) {\n break;\n }\n const candidate = path.join(parent, fileName);\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n // Never search above the package root. The real manifest is always at\n // `<pkg>/dist/manifest.json`; once we have checked the directory that holds\n // `package.json` (the package root), stop. Otherwise a chunk whose\n // `dist/manifest.json` is genuinely absent could match an unrelated\n // `manifest.json` from a parent package, the monorepo root, or a\n // `node_modules` ancestor — registering the WRONG package's schema, which\n // is worse than a clean no-op.\n if (fs.existsSync(path.join(parent, 'package.json'))) {\n break;\n }\n dir = parent;\n }\n return null;\n}\n\n/**\n * Central registry for all SMRT objects\n *\n * Uses globalThis for cross-module state sharing, ensuring all module instances\n * (even from different package resolution paths) share the same registry state.\n */\nexport class ObjectRegistry {\n /**\n * Get the classes map from globalThis, initializing if needed\n */\n private static get classes(): Map<string, RegisteredClass> {\n return getClasses();\n }\n\n /**\n * Get the collections map from globalThis, initializing if needed\n */\n private static get collections(): Map<string, typeof SmrtCollection> {\n return getCollections();\n }\n\n /**\n * Get the collection table names map from globalThis, initializing if needed\n * Maps collection class name -> tableName for getTableName lookups\n */\n private static get collectionTableNames(): Map<string, string> {\n return getCollectionTableNames();\n }\n\n /**\n * Set the table name for a collection class\n * Used by @smrt() decorator to enable getTableName lookups for collections\n */\n static setCollectionTableName(\n collectionName: string,\n tableName: string,\n ): void {\n ObjectRegistry.collectionTableNames.set(collectionName, tableName);\n }\n\n /**\n * Get the collection cache from globalThis, initializing if needed\n */\n private static get collectionCache(): LRUCache<string, SmrtCollection<any>> {\n return getCollectionCache();\n }\n\n /**\n * Configure the collection cache size (for testing purposes)\n *\n * Resets the collection cache with a new maximum size.\n * Use this in tests to avoid creating many database files.\n *\n * @param maxSize - Maximum number of collections to cache (system default is 100)\n * @throws Error if maxSize is not a positive finite number\n * @example\n * ```typescript\n * // In test setup, use a small cache to test LRU eviction with fewer DBs\n * ObjectRegistry.configureCollectionCache(5);\n * ```\n */\n static configureCollectionCache(maxSize: number): void {\n if (!Number.isFinite(maxSize) || maxSize <= 0) {\n throw new Error(`maxSize must be a positive number, got: ${maxSize}`);\n }\n globalThis.__smrtRegistryCollectionCache = new LRUCache<\n string,\n SmrtCollection<any>\n >(maxSize);\n }\n\n /**\n * WeakMap to assign unique IDs to database instances for cache keys\n * Prevents cache key collisions when different db instances are used\n */\n private static get dbInstanceIds(): WeakMap<object, number> {\n return getDbInstanceIds();\n }\n\n /**\n * Get/set the next database ID counter\n */\n private static get nextDbId(): number {\n return getNextDbId();\n }\n\n private static set nextDbId(value: number) {\n setNextDbId(value);\n }\n\n /**\n * Storage for field decorator metadata (decorator pattern)\n * Maps className → Map<propertyKey, FieldOptions>\n * Used by @field(), @foreignKey(), @oneToMany(), @manyToMany() decorators\n */\n private static get fieldDecorators(): Map<string, Map<string, any>> {\n return getFieldDecorators();\n }\n\n /**\n * Track collections that have been processed for STI siblings\n * Prevents infinite recursion when loading siblings\n */\n private static get stiSiblingsLoaded(): Set<string> {\n return getStiSiblingsLoaded();\n }\n\n /**\n * Check if a class is already registered (case-insensitive)\n * Returns the canonical name if found, undefined otherwise.\n *\n * Release B (#1133): iteration over `classes` replaces the old eagerly-\n * maintained classNameMap index. Negligible cost at production scale and\n * removes an entire class of cache-sync bugs.\n */\n static getCanonicalClassName(name: string): string | undefined {\n return _getCanonicalClassName(name);\n }\n\n /**\n * Check if a class exists by name (case-insensitive)\n */\n static hasClassCaseInsensitive(name: string): boolean {\n return _hasClassCaseInsensitive(name);\n }\n\n /**\n * Global cache for inheritance chains (shared across all instances)\n * Maps className → full inheritance chain (base to child)\n * Performance optimization: ~100x faster than re-walking prototype chain\n * Cache size is configurable via smrt.inheritance.cacheSize (default: 200)\n */\n private static getInheritanceCache(): LRUCache<string, string[]> {\n return getInheritanceCache();\n }\n\n /**\n * Global cache for manifest discovery attempts (Issue #735 optimization)\n * Maps className → boolean (true = found and registered, false = not found)\n * Prevents repeated discoverManifestSync calls for the same class name\n */\n private static getDiscoveryAttemptCache(): Map<string, boolean> {\n return getDiscoveryAttemptCache();\n }\n\n /**\n * Register field decorator metadata\n *\n * Called by property decorators (@field, @foreignKey, etc.) to store\n * field configuration metadata. This enables the decorator pattern\n * where field metadata is attached at class definition time.\n *\n * @param className - Name of the class containing the field\n * @param propertyKey - Name of the property being decorated\n * @param options - Field options (type, constraints, etc.)\n * @example\n * ```typescript\n * // Called internally by decorators\n * ObjectRegistry.registerFieldDecorator('Product', 'name', {\n * type: 'text',\n * required: true\n * });\n * ```\n */\n static registerFieldDecorator(\n className: string,\n propertyKey: string,\n options: any,\n ): void {\n if (!ObjectRegistry.fieldDecorators.has(className)) {\n ObjectRegistry.fieldDecorators.set(className, new Map());\n }\n\n // Merge with existing decorator options to support multiple decorators on same field\n const classDecorators = ObjectRegistry.fieldDecorators.get(className);\n if (!classDecorators) {\n // Should not happen since we just set it above, but TypeScript doesn't know that\n return;\n }\n const existing = classDecorators.get(propertyKey);\n\n if (existing) {\n // Merge options, with new options taking precedence\n classDecorators.set(propertyKey, { ...existing, ...options });\n } else {\n classDecorators.set(propertyKey, options);\n }\n }\n\n /**\n * Get field decorator metadata for a specific field\n *\n * @param className - Name of the class\n * @param propertyKey - Name of the property\n * @returns Field options or undefined if not decorated\n * @example\n * ```typescript\n * const options = ObjectRegistry.getFieldDecorator('Product', 'name');\n * // { type: 'text', required: true }\n * ```\n */\n static getFieldDecorator(\n className: string,\n propertyKey: string,\n ): any | undefined {\n return ObjectRegistry.fieldDecorators.get(className)?.get(propertyKey);\n }\n\n /**\n * Get all field decorator metadata for a class\n *\n * @param className - Name of the class\n * @returns Map of property names to field options\n * @example\n * ```typescript\n * const fields = ObjectRegistry.getFieldDecorators('Product');\n * // Map { 'name' => { type: 'text', required: true }, ... }\n * ```\n */\n static getFieldDecorators(className: string): Map<string, any> {\n return ObjectRegistry.fieldDecorators.get(className) || new Map();\n }\n\n /**\n * Check if a class has any field decorators registered\n *\n * @param className - Name of the class\n * @returns True if the class has field decorators, false otherwise\n * @example\n * ```typescript\n * if (ObjectRegistry.hasFieldDecorators('Product')) {\n * // Class uses decorators - skip legacy field initialization\n * }\n * ```\n */\n static hasFieldDecorators(className: string): boolean {\n const decorators = ObjectRegistry.fieldDecorators.get(className);\n return decorators !== undefined && decorators.size > 0;\n }\n\n /**\n * Register a new SMRT object class with the global registry\n *\n * @param constructor - The class constructor extending SmrtObject\n * @param config - Configuration options for API/CLI/MCP generation\n * @throws {Error} If the class cannot be introspected for field definitions\n * @example\n * ```typescript\n * ObjectRegistry.register(Product, {\n * api: { exclude: ['delete'] },\n * cli: true,\n * mcp: { include: ['list', 'get'] }\n * });\n * ```\n */\n static register(\n ctor: typeof SmrtObject,\n config: SmartObjectConfig = {},\n ): void {\n _register(ctor, config);\n }\n\n /**\n * Register a collection class for an object\n *\n * @param objectName - Name of the object class this collection manages\n * @param collectionConstructor - The collection class constructor\n * @example\n * ```typescript\n * ObjectRegistry.registerCollection('Product', ProductCollection);\n * ```\n */\n static registerCollection(\n objectName: string,\n collectionConstructor: new (options: any) => SmrtCollection<any>,\n ): void {\n _registerCollection(objectName, collectionConstructor);\n }\n static registerFromManifest(\n name: string,\n objectDef: any,\n packageName?: string,\n ): void {\n _registerFromManifest(name, objectDef, packageName);\n }\n\n /**\n * Helper method for class lookup with qualified name support.\n *\n * Lookup priority:\n * 1. Direct hit on classes map (works for qualified names as keys)\n * 2. If input contains ':', treat as qualified name — direct only, no fallback\n * 3. classNameMap lookup by simple name (lowercase)\n * - Unambiguous (1 entry) → return it\n * - Ambiguous (>1 entry) → throw descriptive error\n * 4. Case-insensitive iteration fallback (backward compat)\n *\n * @param name - Name of the class to find (simple or qualified)\n * @returns Registered class information or undefined if not found\n * @remarks When a simple name is ambiguous (multiple packages define it),\n * logs a warning and returns the first match. Use qualified names\n * or resolveType() for strict disambiguation.\n * @private\n */\n private static findClass(name: string): RegisteredClass | undefined {\n return _findClass(name);\n }\n\n // The private `findClassStrict` wrapper that used to live here was removed\n // with the inline inheritance-chain copy (#1378); strict, package-aware\n // resolution now lives solely in registry/inheritance-resolver, which calls\n // the name-resolver helper directly.\n\n /**\n * Get a registered class by name (case-insensitive)\n *\n * @param name - Name of the registered class\n * @returns Registered class information or undefined if not found\n * @example\n * ```typescript\n * const productInfo = ObjectRegistry.getClass('Product');\n * // Also works with: 'product', 'PRODUCT', etc.\n * if (productInfo) {\n * console.log(productInfo.config.api?.exclude);\n * }\n * ```\n */\n static getClass(name: string): RegisteredClass | undefined {\n return _getClass(name);\n }\n\n /**\n * Get a registered class by its constructor reference.\n * This is the most reliable lookup method as it avoids name collision issues\n * that can occur when multiple packages define classes with the same name.\n *\n * Uses a WeakMap index for O(1) lookups.\n *\n * @param ctor - The class constructor to look up\n * @returns Registered class information or undefined if not found\n * @example\n * ```typescript\n * import { Meeting } from '@happyvertical/praeco';\n *\n * const info = ObjectRegistry.getClassByConstructor(Meeting);\n * if (info) {\n * console.log(info.qualifiedName); // '@happyvertical/praeco:Meeting'\n * }\n * ```\n */\n static getClassByConstructor(\n ctor: SmrtObjectConstructor,\n ): RegisteredClass | undefined {\n return _getClassByConstructor(ctor);\n }\n\n /**\n * Get a registered class by its qualified name.\n * Qualified names are in format \"@package/name:ClassName\".\n *\n * @param qualifiedName - The fully qualified class name\n * @returns Registered class information or undefined if not found\n * @example\n * ```typescript\n * const product = ObjectRegistry.getClassByQualifiedName('@happyvertical/smrt-products:Product');\n * if (product) {\n * console.log(`Found: ${product.name} from ${product.packageName}`);\n * }\n * ```\n */\n static getClassByQualifiedName(\n qualifiedName: string,\n ): RegisteredClass | undefined {\n return _getClassByQualifiedName(qualifiedName);\n }\n\n /**\n * Get a registered class by package name and class name.\n * This is a convenience method for looking up classes by their namespace components.\n *\n * @param packageName - The package name (e.g., \"@happyvertical/smrt-products\")\n * @param className - The class name (e.g., \"Product\")\n * @returns Registered class information or undefined if not found\n * @example\n * ```typescript\n * const product = ObjectRegistry.getClassInPackage('@happyvertical/smrt-products', 'Product');\n * ```\n */\n static getClassInPackage(\n packageName: string,\n className: string,\n ): RegisteredClass | undefined {\n return _getClassInPackage(packageName, className);\n }\n\n /**\n * Find all registered classes with a given simple class name.\n * Useful for detecting collisions or when multiple packages have the same class name.\n *\n * @param className - The simple class name to search for\n * @returns Array of registered classes with matching name\n * @example\n * ```typescript\n * const products = ObjectRegistry.findClassesByName('Product');\n * if (products.length > 1) {\n * console.log(`Found ${products.length} classes named \"Product\":`);\n * for (const p of products) {\n * console.log(` - ${p.qualifiedName} from ${p.packageName}`);\n * }\n * }\n * ```\n */\n static findClassesByName(className: string): RegisteredClass[] {\n return _findClassesByName(className);\n }\n\n /**\n * Resolve a short class name to its qualified name.\n * Throws an error if the name is ambiguous (multiple packages define the same class name).\n *\n * @param shortName - The simple class name to resolve (e.g., 'MeetingRecap')\n * @returns The qualified class name (e.g., '@happyvertical/praeco:MeetingRecap')\n * @throws {Error} If no class with that name is registered\n * @throws {Error} If multiple classes with that name exist (ambiguous)\n *\n * @example\n * ```typescript\n * // Unambiguous resolution\n * const qualified = ObjectRegistry.resolveType('MeetingRecap');\n * // Returns: '@happyvertical/praeco:MeetingRecap'\n *\n * // Already qualified names pass through\n * const same = ObjectRegistry.resolveType('@happyvertical/praeco:MeetingRecap');\n * // Returns: '@happyvertical/praeco:MeetingRecap'\n *\n * // Ambiguous names throw\n * ObjectRegistry.resolveType('Event');\n * // Error: \"Event\" is ambiguous. Found in multiple packages:\n * // - @happyvertical/smrt-events:Event\n * // - @happyvertical/calendar:Event\n * // Use the fully qualified name instead.\n * ```\n */\n static resolveType(shortName: string): QualifiedClassName {\n return _resolveType(shortName);\n }\n\n /**\n * Get all registered classes from a specific package.\n *\n * @param packageName - The package name to filter by\n * @returns Map of class names to registered class information\n * @example\n * ```typescript\n * const coreClasses = ObjectRegistry.getClassesByPackage('@happyvertical/smrt-core');\n * for (const [name, info] of coreClasses) {\n * console.log(` ${name}: ${info.qualifiedName}`);\n * }\n * ```\n */\n static getClassesByPackage(\n packageName: string,\n ): Map<string, RegisteredClass> {\n return _getClassesByPackage(packageName);\n }\n\n /**\n * Get all registered classes with a specific visibility level.\n *\n * @param visibility - The visibility level to filter by\n * @returns Map of class names to registered class information\n * @example\n * ```typescript\n * const publicClasses = ObjectRegistry.getClassesByVisibility('public');\n * console.log(`Found ${publicClasses.size} public classes`);\n * ```\n */\n static getClassesByVisibility(\n visibility: SmrtVisibility,\n ): Map<string, RegisteredClass> {\n return _getClassesByVisibility(visibility);\n }\n\n /**\n * Get all public registered classes (excludes 'internal' and 'test' visibility).\n * Useful for generating published manifests or public APIs.\n *\n * @returns Map of class names to registered class information\n * @example\n * ```typescript\n * const publicClasses = ObjectRegistry.getPublicClasses();\n * console.log(`Publishing ${publicClasses.size} public classes to manifest`);\n * ```\n */\n static getPublicClasses(): Map<string, RegisteredClass> {\n return _getPublicClasses();\n }\n\n /**\n * Get all registered classes\n *\n * @returns Map of class names to registered class information\n * @example\n * ```typescript\n * const allClasses = ObjectRegistry.getAllClasses();\n * for (const [name, info] of allClasses) {\n * console.log(`Class: ${name}, Fields: ${info.fields.size}`);\n * }\n * ```\n */\n static getAllClasses(): Map<string, RegisteredClass> {\n return _getAllClasses();\n }\n\n /**\n * Get class names, deduplicated by simple class name.\n *\n * This is useful for display and backwards compatibility. Use\n * `getQualifiedClassNames()` for schema/bootstrap loops that must preserve\n * cross-package collisions.\n */\n static getClassNames(): string[] {\n return _getClassNames();\n }\n\n /**\n * Get one lookup name per registered class, preserving cross-package\n * collisions by preferring qualified class names where available.\n */\n static getQualifiedClassNames(): string[] {\n return _getQualifiedClassNames();\n }\n\n /**\n * Try to load and register a class from external SMRT packages\n *\n * This method attempts to auto-discover classes from @happyvertical/smrt-* packages\n * when they're referenced but not yet registered. Solves issue #343 where STI classes\n * from external packages (e.g., Person from smrt-profiles) weren't loading correctly.\n *\n * @param className - Name of the class to load\n * @returns Promise<boolean> - True if successfully loaded and registered, false otherwise\n * @private\n */\n static async tryLoadFromExternalPackage(className: string): Promise<boolean> {\n const requestedQualifiedName = isQualifiedName(className)\n ? parseQualifiedName(className)\n : null;\n const requestedClassName = requestedQualifiedName?.className || className;\n const requestedPackageName = requestedQualifiedName?.packageName;\n const smrtPackages = requestedPackageName\n ? [requestedPackageName]\n : await discoverInstalledSmrtPackages();\n const { loadExternalManifest } = await importManifestLoader();\n\n verboseLog(\n `[ObjectRegistry] Attempting to auto-load ${className} from ${smrtPackages.length} external packages...`,\n );\n\n const matches: Array<{\n manifest: any;\n packageName: string;\n objectDef: any;\n }> = [];\n\n // Try each package\n for (const packageName of smrtPackages) {\n const manifest = await loadExternalManifest(packageName);\n\n if (!manifest || !manifest.objects) {\n continue;\n }\n\n // Look for the class in this manifest (case-insensitive)\n // Support both qualified keys (@pkg:Class) and simple class names\n const lowerClassName = requestedClassName.toLowerCase();\n let objectDef =\n manifest.objects[lowerClassName] ||\n manifest.objects[requestedClassName] ||\n (requestedPackageName\n ? manifest.objects[\n `${requestedPackageName}:${requestedClassName}` as string\n ]\n : undefined);\n\n // If not found by direct key lookup, search by className field (Issue #713)\n // This handles manifests with qualified keys while allowing simple name lookups\n if (!objectDef) {\n for (const [_key, def] of Object.entries(\n manifest.objects as Record<string, any>,\n )) {\n if (\n def.className?.toLowerCase() === lowerClassName ||\n def.className === requestedClassName\n ) {\n objectDef = def;\n break;\n }\n }\n }\n\n if (!objectDef) {\n continue;\n }\n\n matches.push({\n manifest,\n packageName: manifest.packageName || packageName,\n objectDef,\n });\n }\n\n if (matches.length === 0) {\n verboseLog(\n `[ObjectRegistry] ❌ Could not find ${className} in any SMRT package`,\n );\n return false;\n }\n\n if (!requestedPackageName && matches.length > 1) {\n throw new ConfigurationError(\n `Ambiguous class name \"${className}\" — found in multiple external SMRT packages: ` +\n `${matches.map((match) => match.packageName).join(', ')}. ` +\n 'Preserve package identity or use a qualified class name to disambiguate.',\n 'CONFIG_AMBIGUOUS_CLASS',\n {\n className,\n candidates: matches.map((match) => match.packageName),\n },\n );\n }\n\n const { manifest, packageName, objectDef } = matches[0];\n\n verboseLog(\n `[ObjectRegistry] ✅ Found ${className} in ${packageName} manifest`,\n );\n\n // Register the class from manifest\n ObjectRegistry.registerFromManifest(\n objectDef.className || requestedClassName,\n objectDef,\n manifest.packageName,\n );\n\n // If this is an STI class, also register the parent class\n // Skip if extends points to the same className (self-referential):\n // This happens when a child class in one package extends a parent with the\n // same name from another package (e.g., histrio:Performer extends smrt-video:Performer)\n // and only the child package is installed\n const childClassName = objectDef.className || requestedClassName;\n if (objectDef.extends && objectDef.extends !== childClassName) {\n const parentName = objectDef.extends;\n const lowerParentName = parentName.toLowerCase();\n let parentDef =\n manifest.objects[lowerParentName] || manifest.objects[parentName];\n\n // Search by className field if not found by key (Issue #713)\n if (!parentDef) {\n for (const [_key, def] of Object.entries(\n manifest.objects as Record<string, any>,\n )) {\n if (\n def.className?.toLowerCase() === lowerParentName ||\n def.className === parentName\n ) {\n parentDef = def;\n break;\n }\n }\n }\n\n if (parentDef && !ObjectRegistry.hasClass(objectDef.extends)) {\n verboseLog(\n `[ObjectRegistry] Also registering parent class ${objectDef.extends} for STI`,\n );\n ObjectRegistry.registerFromManifest(\n parentDef.className || objectDef.extends,\n parentDef,\n manifest.packageName,\n );\n }\n\n // Merge inherited fields from parent into child\n // This ensures STI child classes get all parent fields\n verboseLog(\n `[ObjectRegistry] Merging inherited fields for ${className}...`,\n );\n await ObjectRegistry.getAllFields(requestedClassName);\n const registered = ObjectRegistry.findClass(requestedClassName);\n if (registered?.inheritedFields) {\n verboseLog(\n `[ObjectRegistry] ✅ ${className} now has ${registered.inheritedFields.size} total fields (including inherited)`,\n );\n }\n }\n\n return true;\n }\n\n /**\n * Load all manifests upfront so inheritance queries are pure lookups.\n *\n * After this method completes, every class across all packages is\n * registered and `getInheritanceChain()` will never need to mutate\n * registry state.\n *\n * @param options - Optional configuration\n * @param options.manifestPaths - Explicit list of manifest.json file paths to load.\n * When omitted the method discovers packages via `loadExternalManifestSync()`\n * for every `@happyvertical` package found in `node_modules`.\n * @returns Summary statistics about the load operation\n *\n * @example\n * ```typescript\n * // At CLI / server startup\n * ObjectRegistry.loadAllManifests();\n * // All classes are now registered — inheritance lookups are side-effect free\n * ```\n *\n * @see https://github.com/happyvertical/smrt/issues/1007\n */\n static loadAllManifests(options?: { manifestPaths?: string[] }): {\n packagesLoaded: number;\n objectsRegistered: number;\n } {\n let packagesLoaded = 0;\n let objectsRegistered = 0;\n\n if (options?.manifestPaths) {\n // Explicit paths → ExplicitPathsManifestSource. Preserves the\n // full-registry-integration.test.ts:72-76 contract.\n const source = new ExplicitPathsManifestSource(options.manifestPaths);\n for (const entry of source.entries()) {\n if (!ObjectRegistry.hasClassCaseInsensitive(entry.className)) {\n ObjectRegistry.registerFromManifest(\n entry.className,\n entry.def,\n entry.packageName,\n );\n objectsRegistered++;\n }\n }\n // Preserve historical semantics: packagesLoaded counts each\n // successfully-read manifest path (not distinct packageName values).\n // Two paths pointing at the same package counted as two before Release\n // B and must continue to do so.\n packagesLoaded = source.loadedCount;\n } else {\n // Auto-discover: seed the embedded cache from every installed\n // @happyvertical/smrt-* package, then iterate composite.entries() —\n // LocalTest/Test sources gate themselves on isTestEnvironment() and\n // NodeModulesFallback is a no-op on `.lookup()`, so the iteration\n // yields exactly the same set of entries as the old manual scan.\n const packagePrefixes = ['@happyvertical/smrt-'];\n try {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return { packagesLoaded, objectsRegistered };\n }\n\n const scopeDir = builtins.path.join(\n process.cwd(),\n 'node_modules',\n '@happyvertical',\n );\n if (!builtins.fs.existsSync(scopeDir)) {\n return { packagesLoaded, objectsRegistered };\n }\n\n const packages = builtins.fs\n .readdirSync(scopeDir)\n .filter((name) =>\n packagePrefixes.some((prefix) =>\n `@happyvertical/${name}`.startsWith(prefix),\n ),\n );\n\n const seenPackages = new Set<string>();\n for (const pkgDir of packages) {\n const packageName = `@happyvertical/${pkgDir}`;\n const manifest = loadExternalManifestSyncWithNode(packageName);\n if (!manifest?.objects) continue;\n seenPackages.add(packageName);\n }\n\n const composite = getDefaultCompositeSource();\n for (const entry of composite.entries()) {\n if (!entry.packageName || !seenPackages.has(entry.packageName)) {\n continue;\n }\n if (!ObjectRegistry.hasClassCaseInsensitive(entry.className)) {\n ObjectRegistry.registerFromManifest(\n entry.className,\n entry.def,\n entry.packageName,\n );\n objectsRegistered++;\n }\n }\n packagesLoaded = seenPackages.size;\n } catch (err) {\n verboseLog(\n `[ObjectRegistry] Auto-discovery of manifests failed: ${err}`,\n );\n }\n }\n\n verboseLog(\n `[ObjectRegistry] loadAllManifests complete: ${packagesLoaded} packages, ${objectsRegistered} objects registered`,\n );\n\n return { packagesLoaded, objectsRegistered };\n }\n\n /**\n * Register a package's own bundled manifest, called by the package itself at\n * import time to eliminate the consumer-runtime field-drop bug (issue #1132).\n *\n * Packages ship a `dist/manifest.json` next to their compiled entry. A small\n * `__smrt-register__.js` side-effect module imports that file URL and calls\n * this method *before* any `@smrt()` decorator in the package fires, so the\n * decorator's synchronous manifest lookup hits a populated cache instead of\n * registering classes with zero fields.\n *\n * Silently no-ops if the URL can't be read — in dev/test the vitest plugin\n * populates manifests through a different path, and this fallback is expected\n * to miss in those contexts.\n *\n * @param manifestUrl - File URL (or string) pointing to the package's\n * manifest.json. Typical call site:\n * `new URL('./manifest.json', import.meta.url)`\n * @returns Summary with loaded status, package name, and object count\n *\n * @example\n * ```typescript\n * // packages/smrt-places/src/__smrt-register__.ts\n * import { ObjectRegistry } from '@happyvertical/smrt-core';\n * ObjectRegistry.registerPackageManifest(\n * new URL('./manifest.json', import.meta.url),\n * );\n * ```\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\n static registerPackageManifest(manifestUrl: string | URL): {\n loaded: boolean;\n packageName?: string;\n objectsRegistered: number;\n } {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return { loaded: false, objectsRegistered: 0 };\n }\n\n let manifest: SmartObjectManifest | null = null;\n try {\n // Decode file URLs via fileURLToPath() rather than `new URL(...).pathname`:\n // pathname leaves percent-encoding intact and on Windows yields paths like\n // `/C:/foo` that fs rejects. Either failure mode would otherwise make\n // self-registration silently no-op and reintroduce #1132.\n const urlString =\n manifestUrl instanceof URL ? manifestUrl.href : manifestUrl;\n let filePath: string;\n if (manifestUrl instanceof URL) {\n filePath = builtins.url.fileURLToPath(manifestUrl);\n } else if (urlString.startsWith('file:')) {\n filePath = builtins.url.fileURLToPath(urlString);\n } else {\n filePath = urlString;\n }\n\n // The `__smrt-register__` shim resolves the manifest via\n // `new URL('./manifest.json', import.meta.url)`, which assumes the\n // compiled side-effect sits directly next to `dist/manifest.json`.\n // Vite chunk-splitting is non-deterministic and sometimes hoists that\n // side-effect into a `dist/chunks/<hash>.js` chunk (observed for\n // smrt-users / smrt-profiles), so the shim's URL resolves to a\n // non-existent `dist/chunks/manifest.json` and self-registration\n // silently no-ops — dropping every plain (undecorated) field from the\n // package's models in consumer runtimes (#1331). When the direct path\n // is missing, walk up a bounded number of parent directories to locate\n // the real `manifest.json`. This keeps resolution deterministic\n // regardless of where the bundler places the shim.\n if (!builtins.fs.existsSync(filePath)) {\n const recovered = resolveManifestByUpwardSearch(builtins, filePath);\n if (!recovered) {\n recordRegistryDiagnostic(\n 'warn',\n 'PACKAGE_MANIFEST_NOT_FOUND',\n `Package manifest not found at ${filePath}. Self-registration is a no-op; the vitest plugin may still populate this manifest via its own path.`,\n { manifestUrl: String(manifestUrl), filePath },\n );\n return { loaded: false, objectsRegistered: 0 };\n }\n filePath = recovered;\n }\n\n const parsed = JSON.parse(\n builtins.fs.readFileSync(filePath, 'utf-8'),\n ) as SmartObjectManifest;\n\n if (!parsed?.objects || typeof parsed.objects !== 'object') {\n recordRegistryDiagnostic(\n 'warn',\n 'PACKAGE_MANIFEST_INVALID_SHAPE',\n `Package manifest at ${String(manifestUrl)} is missing an \"objects\" record`,\n { manifestUrl: String(manifestUrl) },\n );\n return { loaded: false, objectsRegistered: 0 };\n }\n\n manifest = parsed;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n recordRegistryDiagnostic(\n 'error',\n 'PACKAGE_MANIFEST_READ_FAILED',\n `registerPackageManifest: failed to read manifest at ${String(manifestUrl)}: ${errorMessage}`,\n { manifestUrl: String(manifestUrl), errorMessage },\n );\n verboseLog(\n `[ObjectRegistry] registerPackageManifest: failed to read manifest at ${String(manifestUrl)}: ${errorMessage}`,\n );\n return { loaded: false, objectsRegistered: 0 };\n }\n\n const packageName = manifest.packageName;\n\n // Seed the manifest cache so discoverManifestSync() finds entries when\n // @smrt() decorators run for classes in this package.\n const manifestGlobals = globalThis as typeof globalThis & {\n __smrtManifestCache?: Map<string, SmartObjectManifest>;\n };\n if (!manifestGlobals.__smrtManifestCache) {\n manifestGlobals.__smrtManifestCache = new Map();\n }\n const cacheKey = packageName || String(manifestUrl);\n manifestGlobals.__smrtManifestCache.set(cacheKey, manifest);\n\n // Merge manifest fields into any already-registered classes. This covers\n // the case where class modules were evaluated before the package's\n // self-register shim (e.g., a consumer imported a deep subpath that\n // bypassed the main entry).\n let objectsRegistered = 0;\n for (const [key, def] of Object.entries(manifest.objects)) {\n const objectDef = def as any;\n const className = objectDef.className || key;\n ObjectRegistry.registerFromManifest(className, objectDef, packageName);\n objectsRegistered++;\n }\n\n verboseLog(\n `[ObjectRegistry] registerPackageManifest: loaded ${objectsRegistered} objects from ${packageName || String(manifestUrl)}`,\n );\n\n return { loaded: true, packageName, objectsRegistered };\n }\n\n /**\n * Snapshot of diagnostics collected from registry load paths.\n *\n * Registry paths that previously `console.warn(...); return null` also\n * record a structured diagnostic. Apps can inspect this buffer at startup\n * or from an error route to surface failures that would otherwise be silent.\n *\n * Strict mode is **on by default** since Release C (#1134): severity\n * `'error'` diagnostics throw at record time. Set\n * `SMRT_STRICT_REGISTRY=false` to restore the pre-Release-C permissive\n * behavior where only the diagnostic is recorded and nothing throws.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n * @see https://github.com/happyvertical/smrt/issues/1134\n */\n static getDiagnostics(): readonly RegistryDiagnostic[] {\n return getRegistryDiagnostics();\n }\n\n /** Clear the diagnostic buffer. Primarily for tests. */\n static clearDiagnostics(): void {\n clearRegistryDiagnostics();\n }\n\n /**\n * Pretty-print the diagnostic buffer via `console.warn` / `console.error`.\n * No-op when the buffer is empty.\n */\n static flushDiagnostics(): void {\n flushRegistryDiagnostics();\n }\n\n /**\n * Check if a class is registered (case-insensitive)\n */\n static hasClass(name: string): boolean {\n return _hasClass(name);\n }\n\n /**\n * Clear all registered classes (mainly for testing)\n */\n static clear(): void {\n ObjectRegistry.classes.clear();\n ObjectRegistry.collections.clear();\n ObjectRegistry.collectionCache.clear();\n ObjectRegistry.collectionTableNames.clear();\n ObjectRegistry.getInheritanceCache().clear();\n ObjectRegistry.getDiscoveryAttemptCache().clear();\n ObjectRegistry.fieldDecorators.clear();\n ObjectRegistry.stiSiblingsLoaded.clear();\n // Release B (#1133) dropped classNameMap — case-insensitive lookups\n // iterate the classes Map directly, so there's no secondary index to\n // clear here.\n // Note: dbInstanceIds WeakMap and constructorIndex WeakMap will be\n // garbage collected automatically when classes are no longer referenced\n // Reset the counter for clean test state\n ObjectRegistry.nextDbId = 1;\n }\n\n /**\n * Invalidate inheritance cache for a specific class\n *\n * Clears cached inheritance chain and merged fields/methods for the given class.\n * Call this when a class definition changes at runtime (e.g., hot module reload).\n *\n * @param className - The class name to invalidate cache for\n * @example\n * ```typescript\n * // After hot module reload of a parent class\n * ObjectRegistry.invalidateInheritanceCache('BentleyContent');\n * ```\n */\n static invalidateInheritanceCache(className: string): void {\n // Delegate to the stronger sweep in class-registration.ts. The previous\n // implementation here recursed via `childClass.extends === className`\n // — a simple-string exact match — so qualified-extends descendants\n // (e.g. a child whose `extends` is stored as `@pkg:Parent` after\n // `qualifyExtendsName`) were silently missed. The shared sweep checks\n // both `extends === existing.name` and `extends === existing.qualifiedName`,\n // plus transitive descendants via the inheritance-chain cache. See\n // #1139 Gap 1.\n const registered = ObjectRegistry.findClass(className);\n if (!registered) {\n // Class not found: still clear any stray chain-cache entry keyed on\n // this name so a future lookup rebuilds from scratch.\n ObjectRegistry.getInheritanceCache().delete(className);\n return;\n }\n _invalidateInheritanceEntries(registered);\n }\n\n /**\n * Invalidate all inheritance caches\n *\n * Clears all cached inheritance chains and merged fields/methods.\n * Call this when multiple classes change at runtime.\n *\n * @example\n * ```typescript\n * // After hot module reload of multiple classes\n * ObjectRegistry.invalidateAllInheritanceCaches();\n * ```\n */\n static invalidateAllInheritanceCaches(): void {\n ObjectRegistry.getInheritanceCache().clear();\n ObjectRegistry.getDiscoveryAttemptCache().clear();\n\n for (const registered of ObjectRegistry.classes.values()) {\n registered.inheritedFields = undefined;\n registered.inheritedMethods = undefined;\n }\n }\n\n /**\n * Resolve a collection lookup name to the registered object metadata and\n * collection constructor that should back it.\n *\n * Accepts any supported collection identifier:\n * - simple class name (`FactRecord`)\n * - qualified class name (`@pkg:FactRecord`)\n * - explicit collection alias (`fact_records`) when registered\n *\n * Returns a canonical class identity so cache keys remain stable across\n * aliases that refer to the same underlying collection.\n */\n private static resolveCollectionRegistration(className: string): {\n canonicalName: string;\n registered?: RegisteredClass;\n collectionConstructor?: new (options: any) => SmrtCollection<any>;\n } {\n let registered = ObjectRegistry.findClass(className);\n let collectionConstructor = registered?.collectionConstructor;\n\n if (!collectionConstructor) {\n collectionConstructor = ObjectRegistry.collections.get(className);\n }\n\n if (!registered && collectionConstructor) {\n const itemClass = (collectionConstructor as any)._itemClass as\n | SmrtObjectConstructor\n | undefined;\n if (itemClass) {\n registered =\n ObjectRegistry.getClassByConstructor(itemClass) ||\n ObjectRegistry.findClass(itemClass.name);\n }\n }\n\n const canonicalName =\n registered?.qualifiedName || registered?.name || className;\n\n return {\n canonicalName,\n registered,\n collectionConstructor,\n };\n }\n\n /**\n * Get or create a cached collection instance (Singleton pattern - Phase 4 optimization)\n *\n * Returns a cached collection if one exists for the given class and options,\n * otherwise creates, initializes, and caches a new instance. This significantly\n * improves performance by avoiding repeated collection initialization.\n *\n * **Performance Impact**: 60-80% reduction in collection initialization overhead\n *\n * **Cache Key Strategy**: Collections are cached based on:\n * - className\n * - persistence configuration (type, url, baseUrl)\n * - db presence (not full config)\n * - ai presence (not full config)\n *\n * Different persistence configurations create separate cached instances.\n *\n * @param className - Name of the object class\n * @param options - Configuration options for the collection\n * @returns Cached or newly created collection instance\n * @throws {Error} If the class is not registered or has no collection\n *\n * @example\n * ```typescript\n * // First call creates and caches the collection\n * const orders1 = await ObjectRegistry.getCollection('Order', {\n * persistence: { type: 'sql', url: 'orders.db' }\n * });\n *\n * // Subsequent calls return the cached instance (much faster)\n * const orders2 = await ObjectRegistry.getCollection('Order', {\n * persistence: { type: 'sql', url: 'orders.db' }\n * });\n * console.log(orders1 === orders2); // true (same instance)\n *\n * // Different configuration creates new instance\n * const orders3 = await ObjectRegistry.getCollection('Order', {\n * persistence: { type: 'sql', url: 'orders-copy.db' }\n * });\n * console.log(orders1 === orders3); // false (different config)\n * ```\n *\n * @see {@link https://github.com/happyvertical/sdk/blob/main/packages/core/CLAUDE.md#singleton-collection-management-phase-4|Phase 4 Documentation}\n */\n static async getCollection<T extends SmrtObject>(\n className: string,\n options: any = {},\n ): Promise<SmrtCollection<T>> {\n let { canonicalName, registered, collectionConstructor } =\n ObjectRegistry.resolveCollectionRegistration(className);\n\n if (!registered && !collectionConstructor) {\n // Try to auto-load from external SMRT packages before throwing error\n // This handles cases where classes from @happyvertical/smrt-* packages\n // are used without explicitly importing them (e.g., Person from smrt-profiles)\n const loaded = await ObjectRegistry.tryLoadFromExternalPackage(className);\n\n if (loaded) {\n ({ canonicalName, registered, collectionConstructor } =\n ObjectRegistry.resolveCollectionRegistration(className));\n }\n\n if (!registered && !collectionConstructor) {\n throw new Error(\n `Class ${className} not found in ObjectRegistry. Make sure to register it with @smrt() decorator or ObjectRegistry.register()`,\n );\n }\n }\n\n // Create a cache key from className and relevant options\n // We use a simplified key that includes only persistence config\n // to avoid cache misses from transient options\n\n // CRITICAL FIX for issue #384: Use unique db instance ID for cache key\n // Without this, different tests with different db instances would share\n // the same cached collection, causing queries to hit the wrong database\n let dbId: number | undefined;\n if (options.db && typeof options.db === 'object') {\n // Get or assign unique ID for this db instance\n if (!ObjectRegistry.dbInstanceIds.has(options.db)) {\n ObjectRegistry.dbInstanceIds.set(options.db, ObjectRegistry.nextDbId++);\n }\n dbId = ObjectRegistry.dbInstanceIds.get(options.db);\n }\n\n const cacheKey = `${canonicalName}:${JSON.stringify({\n persistence: options.persistence,\n db: dbId !== undefined ? `db:${dbId}` : undefined,\n ai: options.ai ? 'present' : undefined,\n })}`;\n\n // Return cached instance if available\n if (ObjectRegistry.collectionCache.has(cacheKey)) {\n return ObjectRegistry.collectionCache.get(cacheKey) as SmrtCollection<T>;\n }\n\n // Auto-create default collection if not registered\n if (!collectionConstructor) {\n if (!registered) {\n throw new Error(\n `Collection ${className} is registered without a backing object class, which is not supported.`,\n );\n }\n\n // Lazy-load SmrtCollection to avoid circular dependency\n const { SmrtCollection: SmrtCollectionClass } = await import(\n './collection'\n );\n\n // Create a default collection class dynamically\n class DefaultCollection extends SmrtCollectionClass<T> {\n static readonly _itemClass = registered?.constructor as any;\n }\n\n // Register it for future use\n collectionConstructor = DefaultCollection as any;\n registered.collectionConstructor = DefaultCollection as any;\n ObjectRegistry.collections.set(canonicalName, DefaultCollection as any);\n }\n\n // Create and initialize new collection instance using static factory method\n // collectionConstructor is guaranteed to be defined here\n const collection = (await (collectionConstructor as any).create(\n options,\n )) as SmrtCollection<T>;\n\n // Cache the initialized instance\n ObjectRegistry.collectionCache.set(cacheKey, collection);\n\n return collection;\n }\n\n /**\n * Get field definitions for a registered class.\n * Supports both qualified names and simple class names.\n */\n static getFields(name: string): Map<string, any> {\n // Issue #951: Use findClass for multi-strategy lookup (qualified key, classNameMap, case-insensitive)\n const registered = ObjectRegistry.findClass(name);\n return registered ? registered.fields : new Map();\n }\n\n /**\n * Get method definitions for a registered class\n *\n * Returns method metadata extracted from the manifest during AST scanning.\n * This enables code generators (CLI, API, MCP) to discover custom methods\n * and automatically generate corresponding commands/endpoints/tools.\n *\n * @param name - Name of the registered class\n * @returns Map of method names to MethodDefinition objects\n * @example\n * ```typescript\n * const methods = ObjectRegistry.getMethods('Agent');\n * for (const [name, methodDef] of methods) {\n * console.log(`Method: ${name}`);\n * console.log(` Async: ${methodDef.async}`);\n * console.log(` Public: ${methodDef.isPublic}`);\n * console.log(` Params: ${methodDef.parameters.map(p => p.name).join(', ')}`);\n * }\n * ```\n */\n static getMethods(name: string): Map<string, any> {\n // Issue #951: Use findClass for multi-strategy lookup (qualified key, classNameMap, case-insensitive)\n const registered = ObjectRegistry.findClass(name);\n if (registered) {\n return registered.methods;\n }\n\n return new Map();\n }\n\n static compileValidators(\n className: string,\n fields: Map<string, any>,\n ): ValidatorFunction[] {\n return _compileValidators(className, fields);\n }\n\n /**\n * Ensure manifest is loaded for external package classes\n *\n * For classes from external packages, the manifest may not be loaded during\n * initial registration (which must be synchronous for decorator support).\n * This method loads the manifest asynchronously when needed.\n *\n * @param className - Name of the class to ensure manifest is loaded for\n * @returns Promise that resolves when manifest is loaded (or already loaded)\n * @throws {Error} If manifest cannot be found\n *\n * @example\n * ```typescript\n * // Before using fields from external package\n * await ObjectRegistry.ensureManifestLoaded('Place');\n * const fields = ObjectRegistry.getFields('Place'); // Now has fields\n * ```\n */\n static async ensureManifestLoaded(className: string): Promise<void> {\n let registered = ObjectRegistry.findClass(className);\n if (!registered) {\n const loaded = await ObjectRegistry.tryLoadFromExternalPackage(className);\n if (loaded) {\n registered = ObjectRegistry.findClass(className);\n }\n }\n\n if (!registered) {\n // Detect if running in test environment\n const isTestEnv =\n process.env.NODE_ENV === 'test' ||\n process.env.VITEST === 'true' ||\n typeof (globalThis as any).describe !== 'undefined' ||\n typeof (globalThis as any).it !== 'undefined';\n\n const testHint = isTestEnv\n ? `\\n\\n⚠️ Are you using 'smrt test'? ` +\n `Tests require manifest generation.\\n` +\n ` ✅ Use: smrt test\\n` +\n ` ❌ NOT: npx vitest\\n`\n : '';\n\n throw new Error(\n `Class '${className}' is not registered. ` +\n `Ensure the class is decorated with @smrt() before using it.` +\n testHint,\n );\n }\n\n // Try to load manifest from external package (even if some fields exist)\n // This handles cases where AST scanner missed optional fields without initializers\n const existingFieldCount = registered.fields.size;\n\n const { discoverManifestEntry } = await importManifestLoader();\n const manifestEntry = await discoverManifestEntry(\n registered.constructor,\n className,\n );\n\n if (!manifestEntry) {\n // Bundled consumers can register external classes without preserving the\n // package identity we normally use for direct manifest discovery. In\n // that case, fall back to class-name package scans and merge any fields\n // found into the existing registration instead of leaving a sparse entry.\n if (!registered.packageName || !registered.qualifiedName) {\n const loaded =\n await ObjectRegistry.tryLoadFromExternalPackage(className);\n if (loaded) {\n ObjectRegistry.invalidateInheritanceCache(className);\n }\n }\n return;\n }\n\n if (manifestEntry?.fields) {\n const manifestFieldCount = Object.keys(manifestEntry.fields).length;\n let didHydrate = false;\n const needsFieldHydration = Object.entries(manifestEntry.fields).some(\n ([fieldName, fieldDef]) => {\n const existingField = registered.fields.get(fieldName);\n if (!existingField) {\n return true;\n }\n\n return manifestFieldDiffers(existingField, fieldDef);\n },\n );\n const needsMethodHydration =\n !!manifestEntry.methods &&\n Object.entries(manifestEntry.methods).some(\n ([methodName, methodDef]) => {\n return (\n JSON.stringify(registered.methods.get(methodName)) !==\n JSON.stringify(methodDef)\n );\n },\n );\n const needsRegistrationHydration =\n (!!manifestEntry.packageName &&\n registered.packageName !== manifestEntry.packageName) ||\n (!!manifestEntry.extends &&\n registered.extends !== manifestEntry.extends);\n\n if (\n existingFieldCount > 0 &&\n existingFieldCount >= manifestFieldCount &&\n !needsFieldHydration &&\n !needsMethodHydration &&\n !needsRegistrationHydration\n ) {\n return;\n }\n\n // Convert FieldDefinition to Field objects and merge with existing\n for (const [fieldName, fieldDef] of Object.entries(\n manifestEntry.fields,\n )) {\n const existingField = registered.fields.get(fieldName);\n\n if (!existingField) {\n registered.fields.set(fieldName, createFieldFromManifest(fieldDef));\n didHydrate = true;\n continue;\n }\n\n if (manifestFieldDiffers(existingField, fieldDef)) {\n registered.fields.set(\n fieldName,\n mergeManifestField(existingField, fieldDef),\n );\n didHydrate = true;\n }\n }\n\n // Load method definitions from manifest\n if (manifestEntry.methods) {\n for (const [methodName, methodDef] of Object.entries(\n manifestEntry.methods,\n )) {\n registered.methods.set(methodName, methodDef);\n }\n didHydrate = true;\n }\n\n if (manifestEntry.schema) {\n const columns = cloneManifestSchemaColumns(\n manifestEntry.schema.columns,\n );\n applyManifestFieldColumnMetadata(columns, registered.fields.entries());\n\n registered.schema = {\n ddl: manifestEntry.schema.ddl,\n tableName:\n manifestEntry.schema.tableName ||\n registered.schema?.tableName ||\n classnameToTablename(registered.name),\n columns,\n indexes:\n manifestEntry.schema.indexes?.map((indexDef) => ({\n ...indexDef,\n columns: [...(indexDef.columns || [])],\n })) || [],\n triggers: [],\n foreignKeys: [],\n dependencies: [],\n version: manifestEntry.schema.version || '',\n packageName: manifestEntry.packageName,\n baseClass: registered.schema?.baseClass,\n };\n didHydrate = true;\n }\n\n // Extract and store package name from manifest entry (for getPackageName() lookup)\n if (manifestEntry.packageName) {\n registered.packageName = manifestEntry.packageName;\n registered.qualifiedName = createQualifiedName(\n manifestEntry.packageName,\n registered.name,\n ) as QualifiedClassName;\n didHydrate = true;\n }\n\n // Store extends info for getAllFields() to use (if present)\n if (manifestEntry.extends) {\n registered.extends = manifestEntry.extends;\n didHydrate = true;\n }\n\n if (didHydrate) {\n ObjectRegistry.invalidateInheritanceCache(className);\n }\n\n verboseLog(\n `📦 Loaded manifest for external package class: ${className} (${registered.fields.size} fields, ${registered.methods.size} methods)`,\n );\n } else {\n // Manifest not found - throw helpful error\n throw new Error(\n `Cannot find manifest for class '${className}'.\\n\\n` +\n `SMRT classes require a manifest generated at build time by the AST scanner.\\n\\n` +\n `If this is an external package class, verify:\\n` +\n ` 1. Package exports manifest: Check package.json has:\\n` +\n ` \"exports\": { \"./manifest\": \"./dist/manifest.json\" }\\n` +\n ` 2. Package is built: Run npm run build in the package\\n` +\n ` 3. Manifest exists: Confirm dist/manifest.json exists\\n\\n` +\n `See: https://github.com/happyvertical/smrt/issues/131`,\n );\n }\n }\n\n /**\n * Get configuration for a registered class\n */\n static getConfig(name: string): SmartObjectConfig {\n // Issue #951: Use findClass for multi-strategy lookup\n const registered = ObjectRegistry.findClass(name);\n return registered ? registered.config : {};\n }\n\n /**\n * Get cached schema definition for a registered class\n */\n static getSchema(name: string): SchemaDefinition | undefined {\n return _getSchema(name);\n }\n\n /**\n * Get SQL DDL statement for a registered class\n */\n static getSchemaDDL(name: string): string | undefined {\n return _getSchemaDDL(name);\n }\n\n /**\n * Get table name for a registered class\n */\n static getTableName(name: string): string | undefined {\n return _getTableName(name);\n }\n\n /**\n * Get all pre-generated schemas for passing to database adapters\n */\n static getAllSchemas(): Record<\n string,\n { tableName: string; ddl: string; indexes?: string[] }\n > {\n return _getAllSchemas();\n }\n\n /**\n * Get all registered schemas as SchemaDefinition objects\n */\n static getAllSchemasAsDefinitions(): Record<string, SchemaDefinition> {\n return _getAllSchemasAsDefinitions();\n }\n /**\n * Get compiled validation functions for a registered class\n *\n * Returns pre-compiled validation functions that can be executed\n * at runtime for efficient validation without repeated setup.\n *\n * @param name - Name of the registered class\n * @returns Array of validation functions or undefined if not found\n * @example\n * ```typescript\n * const validators = ObjectRegistry.getValidators('Product');\n * for (const validator of validators || []) {\n * const error = await validator(productInstance);\n * if (error) console.error(error);\n * }\n * ```\n */\n static getValidators(name: string): ValidatorFunction[] | undefined {\n // Issue #951: Use findClass for multi-strategy lookup\n const registered = ObjectRegistry.findClass(name);\n return registered?.validators;\n }\n\n /**\n * Get pre-computed validation rules for a registered class\n *\n * Returns serializable validation rules that can be evaluated at runtime\n * without needing pre-compiled validator closures. This significantly\n * reduces CLI startup time for projects with many SMRT objects.\n *\n * @param name - Name of the registered class\n * @returns Array of validation rules or undefined if not found\n * @see https://github.com/happyvertical/smrt/issues/782\n */\n static getValidationRules(name: string): ValidationRule[] | undefined {\n // Issue #951: Use findClass for multi-strategy lookup\n const registered = ObjectRegistry.findClass(name);\n return registered?.validationRules;\n }\n\n /**\n * Validate an instance using pre-computed validation rules\n *\n * This method evaluates validation rules without creating closures,\n * providing faster validation than compiled validator functions.\n *\n * @param instance - The object instance to validate\n * @param rules - Array of validation rules to apply\n * @param className - Name of the class for error messages\n * @returns Array of validation errors (empty if valid)\n * @see https://github.com/happyvertical/smrt/issues/782\n */\n static async validateWithRules(\n instance: any,\n rules: ValidationRule[],\n className: string,\n ): Promise<any[]> {\n // Import ValidationError lazily to avoid circular dependency at module load\n const { ValidationError } = await import('./errors');\n const errors: any[] = [];\n\n for (const rule of rules) {\n const value = instance[rule.field];\n\n switch (rule.rule) {\n case 'required':\n if (value === null || value === undefined || value === '') {\n errors.push(ValidationError.requiredField(rule.field, className));\n }\n break;\n\n case 'min':\n if (\n value !== null &&\n value !== undefined &&\n value < (rule.value as number)\n ) {\n errors.push(\n ValidationError.rangeError(\n rule.field,\n value,\n rule.value as number,\n undefined,\n ),\n );\n }\n break;\n\n case 'max':\n if (\n value !== null &&\n value !== undefined &&\n value > (rule.value as number)\n ) {\n errors.push(\n ValidationError.rangeError(\n rule.field,\n value,\n undefined,\n rule.value as number,\n ),\n );\n }\n break;\n\n case 'minLength':\n if (\n value &&\n typeof value === 'string' &&\n value.length < (rule.value as number)\n ) {\n errors.push(\n ValidationError.invalidValue(\n rule.field,\n value,\n `string with minimum length ${rule.value}`,\n ),\n );\n }\n break;\n\n case 'maxLength':\n if (\n value &&\n typeof value === 'string' &&\n value.length > (rule.value as number)\n ) {\n errors.push(\n ValidationError.invalidValue(\n rule.field,\n value,\n `string with maximum length ${rule.value}`,\n ),\n );\n }\n break;\n\n case 'pattern':\n // Note: Creates regex on each validation call, trading runtime efficiency\n // for faster startup time (no closure compilation needed)\n if (value && typeof value === 'string') {\n const regex = new RegExp(rule.value as string);\n if (!regex.test(value)) {\n errors.push(\n ValidationError.invalidValue(\n rule.field,\n value,\n `string matching pattern ${rule.value}`,\n ),\n );\n }\n }\n break;\n }\n }\n\n return errors;\n }\n\n /**\n * Build dependency graph from foreignKey relationships\n *\n * Returns a map where keys are class names and values are arrays\n * of class names that the key depends on (via foreignKey fields).\n *\n * @returns Map of class name to array of dependency class names\n * @example\n * ```typescript\n * const deps = ObjectRegistry.getDependencyGraph();\n * // { 'Order': ['Customer', 'Product'], 'Customer': [], 'Product': ['Category'] }\n * ```\n */\n static getDependencyGraph(): Map<string, string[]> {\n return _getDependencyGraph();\n }\n\n /**\n * Get initialization order for classes based on dependency graph\n *\n * Uses topological sort to ensure that classes are initialized in\n * an order that respects foreignKey dependencies (dependencies first).\n *\n * Foreign-key cycles (e.g. smrt-chat's ChatMessage.threadId -> ChatThread\n * and ChatThread.rootMessageId -> ChatMessage) are BROKEN rather than\n * treated as a fatal error: when a back-edge is encountered the recursion\n * stops there, so every class still appears in the returned order. SMRT does\n * not emit real DB `FOREIGN KEY` constraints in its generated CREATE TABLE\n * DDL, so a table can be created before its cyclic reference target exists —\n * the reference is satisfied once both tables are present. This mirrors the\n * standard RDBMS approach (create tables first, wire cyclic references\n * afterward) and matches SchemaManager.sortByDependencies, which already\n * tolerates cycles. See issue #1333.\n *\n * @returns Array of class names in initialization order. Every registered\n * class appears exactly once; cycle back-edges are dropped from the\n * ordering constraints.\n * @example\n * ```typescript\n * const order = ObjectRegistry.getInitializationOrder();\n * // ['Category', 'Product', 'Customer', 'Order']\n * // Tables are created in this order to avoid foreign key errors\n * ```\n */\n static getInitializationOrder(): string[] {\n const graph = ObjectRegistry.getDependencyGraph();\n const visited = new Set<string>();\n const visiting = new Set<string>();\n const order: string[] = [];\n const cycleMembers = new Set<string>();\n\n function visit(className: string): void {\n // Back-edge: this class is already on the current DFS path, so following\n // it would close a foreign-key cycle. Break the cycle by stopping here\n // instead of throwing — the class is created earlier on the path and the\n // cyclic reference resolves once both tables exist (#1333).\n if (visiting.has(className)) {\n cycleMembers.add(className);\n return;\n }\n\n // Already processed\n if (visited.has(className)) {\n return;\n }\n\n visiting.add(className);\n\n // Visit all dependencies first\n const dependencies = graph.get(className) || [];\n for (const dep of dependencies) {\n visit(dep);\n }\n\n visiting.delete(className);\n visited.add(className);\n order.push(className);\n }\n\n // Visit all classes\n for (const className of graph.keys()) {\n if (!visited.has(className)) {\n visit(className);\n }\n }\n\n if (cycleMembers.size > 0) {\n // Informational only — cycles are handled, not fatal. Surfacing the\n // involved classes helps operators understand why strict FK ordering\n // could not be honored for these tables.\n logger.warn(\n `[ObjectRegistry] Foreign-key cycle(s) detected and broken for ordering: ${[\n ...cycleMembers,\n ].join(', ')}. Tables are created without strict cyclic ordering; ` +\n 'SMRT does not emit DB-level FOREIGN KEY constraints, so this is safe.',\n );\n }\n\n return order;\n }\n\n /**\n * Build comprehensive relationship map from all field types\n *\n * Returns a map containing all relationships (foreignKey, oneToMany, manyToMany)\n * discovered in registered classes. This enables runtime relationship traversal\n * and eager/lazy loading of related objects.\n *\n * @returns Map of class name to array of relationship metadata\n * @example\n * ```typescript\n * const relationships = ObjectRegistry.getRelationshipMap();\n * // {\n * // 'Order': [\n * // { sourceClass: 'Order', fieldName: 'customerId', targetClass: 'Customer',\n * // type: 'foreignKey', options: { onDelete: 'restrict' } }\n * // ],\n * // 'Customer': [\n * // { sourceClass: 'Customer', fieldName: 'orders', targetClass: 'Order',\n * // type: 'oneToMany', options: {} }\n * // ]\n * // }\n * ```\n */\n static getRelationshipMap(): Map<string, RelationshipMetadata[]> {\n return _getRelationshipMap();\n }\n\n /**\n * Get relationships for a specific class\n *\n * @param className - Name of the class to get relationships for\n * @returns Array of relationship metadata for the class\n * @example\n * ```typescript\n * const orderRelationships = ObjectRegistry.getRelationships('Order');\n * // [{ sourceClass: 'Order', fieldName: 'customerId', ... }]\n * ```\n */\n static getRelationships(className: string): RelationshipMetadata[] {\n return ObjectRegistry.getRelationshipMap().get(className) || [];\n }\n\n /**\n * Get full inheritance chain for a class\n *\n * Returns array of registered ancestor class names from the oldest\n * registered ancestor down to the input class. Framework base classes\n * (`SmrtObject`, `SmrtClass`, `SmrtCollection`) are **NOT** included\n * because they are never registered — the walk terminates one step\n * before them.\n *\n * Chain entries are **qualified names** (`@package/name:ClassName`)\n * whenever the corresponding registration has one — i.e. for every\n * class loaded via a manifest or `@smrt()` decorator with a package\n * context. Classes registered without a package (some tests) fall\n * back to their simple name.\n *\n * Results are cached globally for performance (~100x faster than re-walking).\n *\n * @param className - Name of the registered class (simple or qualified)\n * @returns Array of class names from oldest registered ancestor to\n * the input class, or empty array if not found\n * @example\n * ```typescript\n * const chain = ObjectRegistry.getInheritanceChain(\n * '@happyvertical/smrt-content:BentleyContent',\n * );\n * // [\n * // '@happyvertical/smrt-content:Content',\n * // '@happyvertical/smrt-content:PraecoContent',\n * // '@happyvertical/smrt-content:BentleyContent',\n * // ]\n * ```\n */\n static getInheritanceChain(className: string): string[] {\n // Delegate to the single source of truth in registry/inheritance-resolver.\n // The inline copy that used to live here drifted from the module (it lacked\n // the SmrtHierarchical `parentId` normalization in field merging), so the\n // duplication was removed (#1378). The module shares the same name-resolver\n // and shared-state helpers this class delegates to, so behavior is\n // identical aside from the drift fix.\n return _getInheritanceChain(className);\n }\n\n /**\n * Get all fields including inherited ones from parent classes\n *\n * **Hybrid approach (v0.17+):**\n * - External packages: Use build-time merged fields from manifests\n * - Local classes: Use runtime merging by walking inheritance chain\n *\n * @param className - Name of the registered class\n * @returns Map of all fields (including inherited)\n */\n static async getAllFields(className: string): Promise<Map<string, any>> {\n // Delegate to registry/inheritance-resolver (#1378). The inline copy\n // omitted the SmrtHierarchical `parentId` normalization the module applies,\n // so inherited self-FK fields could surface with the wrong shape. Removing\n // the duplicate keeps field merging consistent everywhere.\n return _getAllFields(className);\n }\n\n /**\n * Merge field configurations from parent and child.\n *\n * Thin wrapper around the single shared implementation in\n * registry/inheritance-resolver (#1378). The previous inline copy here had\n * drifted from the module; both paths now run the same code. Kept as a\n * private static so existing reach-in tests (issue #841 field-merge coverage)\n * still resolve it.\n *\n * @param parentField - Field config from parent class\n * @param childField - Field config from child class\n * @param fieldName - Name of the field (for warning messages)\n * @returns Merged field configuration\n */\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: reached in by issue #841 field-merge tests via `(ObjectRegistry as any).mergeFieldConfigs`; kept as the registry-side surface delegating to the shared resolver impl.\n private static mergeFieldConfigs(\n parentField: any,\n childField: any,\n fieldName: string,\n ): any {\n return _mergeFieldConfigs(parentField, childField, fieldName);\n }\n\n /**\n * Get all methods including inherited ones from parent classes\n *\n * Walks the full inheritance chain and merges methods:\n * - Parent methods are added first\n * - Child methods override parent methods (no config merging for methods)\n *\n * Results are cached per-class for performance.\n *\n * **Note:** This is an async method that ensures manifests are loaded for external package classes.\n *\n * @param className - Name of the registered class\n * @returns Promise resolving to Map of all methods (own + inherited)\n * @example\n * ```typescript\n * // Given: Content → PraecoContent → BentleyContent\n * const allMethods = await ObjectRegistry.getAllMethods('BentleyContent');\n * // Includes: generateSummary() (from PraecoContent) + analyzeLocal() (from BentleyContent)\n * ```\n */\n static async getAllMethods(className: string): Promise<Map<string, any>> {\n // Delegate to registry/inheritance-resolver (#1378) — single source of\n // truth for inheritance-chain method merging.\n return _getAllMethods(className);\n }\n\n /**\n * Get complete metadata for a single object (convenience method)\n *\n * Returns all available metadata for an object in a single call, including:\n * - Class information\n * - Field definitions\n * - Configuration\n * - Schema definition\n * - Validators\n * - Relationships\n * - Tools (AI-callable methods)\n *\n * This is a convenience method that aggregates multiple registry queries\n * into a single comprehensive metadata object.\n *\n * @param className - Name of the class to get metadata for\n * @returns Complete metadata object or null if class not found\n * @example\n * ```typescript\n * const productMeta = ObjectRegistry.getObjectMetadata('Product');\n * if (productMeta) {\n * console.log('Name:', productMeta.name);\n * console.log('Table:', productMeta.schema.tableName);\n * console.log('Fields:', productMeta.fields.size);\n * console.log('API config:', productMeta.config.api);\n * console.log('Relationships:', productMeta.relationships.length);\n * }\n * ```\n */\n static getObjectMetadata(className: string): {\n name: string;\n constructor: typeof SmrtObject;\n collectionConstructor?: new (options: any) => SmrtCollection<any>;\n config: SmartObjectConfig;\n fields: Map<string, any>;\n methods: Map<string, any>;\n schema: SchemaDefinition | undefined;\n validators: ValidatorFunction[];\n relationships: RelationshipMetadata[];\n inverseRelationships: RelationshipMetadata[];\n tools?: Array<{\n type: 'function';\n function: {\n name: string;\n description?: string;\n parameters?: Record<string, any>;\n };\n }>;\n } | null {\n const registered = ObjectRegistry.findClass(className);\n if (!registered) {\n return null;\n }\n\n return {\n name: registered.name,\n constructor: registered.constructor,\n collectionConstructor: registered.collectionConstructor,\n config: registered.config,\n fields: new Map(registered.fields), // Return copy to prevent mutations\n methods: new Map(registered.methods), // Return copy to prevent mutations\n schema: registered.schema,\n validators: registered.validators || [],\n relationships: ObjectRegistry.getRelationships(className),\n inverseRelationships: ObjectRegistry.getInverseRelationships(className),\n tools: registered.tools,\n };\n }\n\n /**\n * Get metadata for all registered objects (convenience method)\n *\n * Returns comprehensive metadata for every registered object, combining\n * multiple registry queries into a single convenient data structure.\n *\n * This is particularly useful for:\n * - Admin dashboards showing all objects\n * - Documentation generation\n * - Schema visualization\n * - Debugging and introspection\n *\n * @returns Array of complete metadata objects for all registered classes\n * @example\n * ```typescript\n * const allMetadata = ObjectRegistry.getAllObjectMetadata();\n *\n * // Generate admin dashboard\n * for (const meta of allMetadata) {\n * console.log(`${meta.name}:`);\n * console.log(` Table: ${meta.schema?.tableName}`);\n * console.log(` Fields: ${meta.fields.size}`);\n * console.log(` API: ${meta.config.api ? 'enabled' : 'disabled'}`);\n * console.log(` Relationships: ${meta.relationships.length}`);\n * }\n *\n * // Generate schema documentation\n * const schemaDoc = allMetadata.map(meta => ({\n * name: meta.name,\n * table: meta.schema?.tableName,\n * fields: Array.from(meta.fields.entries()).map(([name, field]) => ({\n * name,\n * type: field.type,\n * required: field._meta?.required || false\n * })),\n * relationships: meta.relationships.map(rel => ({\n * field: rel.fieldName,\n * target: rel.targetClass,\n * type: rel.type\n * }))\n * }));\n * ```\n */\n static getAllObjectMetadata(): Array<{\n name: string;\n constructor: typeof SmrtObject;\n collectionConstructor?: new (options: any) => SmrtCollection<any>;\n config: SmartObjectConfig;\n fields: Map<string, any>;\n methods: Map<string, any>;\n schema: SchemaDefinition | undefined;\n validators: ValidatorFunction[];\n relationships: RelationshipMetadata[];\n inverseRelationships: RelationshipMetadata[];\n tools?: Array<{\n type: 'function';\n function: {\n name: string;\n description?: string;\n parameters?: Record<string, any>;\n };\n }>;\n }> {\n const allMetadata: Array<any> = [];\n\n // Issue #951: Use simple names (map keys may be qualified)\n for (const [_key, entry] of ObjectRegistry.classes) {\n const metadata = ObjectRegistry.getObjectMetadata(entry.name || _key);\n if (metadata) {\n allMetadata.push(metadata);\n }\n }\n\n return allMetadata;\n }\n\n /**\n * Get inverse relationships (relationships where this class is the target)\n *\n * @param className - Name of the class to find inverse relationships for\n * @returns Array of relationship metadata where this class is the target\n * @example\n * ```typescript\n * const customerInverseRels = ObjectRegistry.getInverseRelationships('Customer');\n * // [{ sourceClass: 'Order', fieldName: 'customerId', targetClass: 'Customer', ... }]\n * ```\n */\n static getInverseRelationships(className: string): RelationshipMetadata[] {\n const allRelationships = ObjectRegistry.getRelationshipMap();\n const inverseRelationships: RelationshipMetadata[] = [];\n\n for (const [_sourceClass, relationships] of allRelationships) {\n for (const rel of relationships) {\n if (rel.targetClass === className) {\n inverseRelationships.push(rel);\n }\n }\n }\n\n return inverseRelationships;\n }\n\n /**\n * Names by which an instance of `className` can be referenced by an inverse\n * foreign key: its own (simple) class name plus every registered ancestor in\n * its inheritance chain.\n *\n * Used by oneToMany resolution so an STI subclass can resolve a relationship\n * declared on its base — the inverse `@foreignKey` is declared against the\n * base class name, while the runtime instance may be a subclass.\n *\n * @param className - Simple or qualified class name\n * @returns Set of names (simple and, where available, qualified) the\n * instance is assignable to\n */\n static getSelfReferableNames(className: string): Set<string> {\n const names = new Set<string>([className]);\n for (const ancestor of ObjectRegistry.getInheritanceChain(className)) {\n names.add(ancestor);\n const simple = ObjectRegistry.getClass(ancestor)?.name;\n if (simple) {\n names.add(simple);\n }\n }\n return names;\n }\n\n /**\n * Inverse relationships targeting `className` OR any (STI) ancestor it\n * inherits from.\n *\n * `getInverseRelationships` matches the target class name exactly. This\n * variant also matches inverse foreign keys declared against an ancestor,\n * so an STI subclass instance can resolve a `@oneToMany` declared on its\n * base — whose inverse `@foreignKey` points at the base class name.\n *\n * @param className - Name of the class to find inverse relationships for\n * @returns Relationship metadata whose target is the class or one of its\n * registered ancestors\n */\n static getInverseRelationshipsForSelf(\n className: string,\n ): RelationshipMetadata[] {\n const names = ObjectRegistry.getSelfReferableNames(className);\n const result: RelationshipMetadata[] = [];\n for (const [, relationships] of ObjectRegistry.getRelationshipMap()) {\n for (const rel of relationships) {\n if (names.has(rel.targetClass)) {\n result.push(rel);\n }\n }\n }\n return result;\n }\n\n /**\n * Get table inheritance strategy for a class\n *\n * Returns the table strategy (CTI or STI) for a class, with automatic\n * inheritance from parent classes. If not explicitly configured,\n * walks up the inheritance chain to find the strategy.\n *\n * **Strategy Inheritance:**\n * - Set once on base class, children inherit automatically\n * - Children can explicitly override (not recommended)\n * - Default is 'cti' if not found in hierarchy\n *\n * @param className - Name of the class to get strategy for\n * @returns 'cti' (Class Table Inheritance) or 'sti' (Single Table Inheritance)\n * @example\n * ```typescript\n * @smrt({ tableStrategy: 'sti' })\n * class Event extends SmrtObject { }\n *\n * @smrt() // Inherits 'sti'\n * class Meeting extends Event { }\n *\n * ObjectRegistry.getTableStrategy('Meeting'); // 'sti'\n * ObjectRegistry.getTableStrategy('Event'); // 'sti'\n * ```\n */\n static getTableStrategy(className: string): 'cti' | 'sti' {\n const registered = ObjectRegistry.findClass(className);\n if (!registered) {\n return 'cti'; // Default for unregistered classes\n }\n\n // Explicit config wins\n if (registered.config?.tableStrategy) {\n return registered.config.tableStrategy;\n }\n\n // Inherit from ancestors\n const chain = ObjectRegistry.getInheritanceChain(className);\n for (const ancestorName of chain) {\n const ancestor = ObjectRegistry.findClass(ancestorName);\n if (ancestor?.config?.tableStrategy) {\n return ancestor.config.tableStrategy;\n }\n }\n\n return 'cti'; // Default strategy\n }\n\n /**\n * Get the conflict columns for UPSERT operations on a class\n *\n * Returns custom conflict columns if specified, otherwise defaults based on\n * table strategy:\n * - CTI: ['slug', 'context']\n * - STI: ['slug', 'context', '_meta_type']\n *\n * STI subclasses share a table, so the discriminator participates in\n * identity — two subtypes can coexist with the same (slug, context). The\n * matching unique constraint on `(slug, context, _meta_type)` must exist\n * in the live schema; if a deployment carries a stale 2-column unique\n * instead, run `smrt db:migrate` to repair it (see issue #1165).\n *\n * @param className - Name of the class to get conflict columns for\n * @returns Array of column names to use for conflict detection\n *\n * @example\n * ```typescript\n * // Junction table with custom conflict columns\n * @smrt({ conflictColumns: ['event_id', 'profile_id'] })\n * class EventParticipant extends SmrtObject {}\n *\n * ObjectRegistry.getConflictColumns('EventParticipant');\n * // Returns: ['event_id', 'profile_id']\n * ```\n */\n static getConflictColumns(className: string): string[] {\n const registered = ObjectRegistry.findClass(className);\n if (!registered) {\n return ['slug', 'context']; // Default for unregistered classes\n }\n\n // Explicit config wins\n if (registered.config?.conflictColumns) {\n return registered.config.conflictColumns;\n }\n\n if (registered.config?.report) {\n const tenantField = registered.tenantScopedConfig?.field;\n const tenantColumn =\n tenantField && registered.fields.has(tenantField)\n ? toSnakeCase(tenantField)\n : '';\n const reportConflictColumns = Array.from(registered.fields.entries())\n .filter(([, field]) => {\n const kind = field?._meta?.__report?.kind ?? field?.__report?.kind;\n return kind === 'group' || kind === 'bucket';\n })\n .map(([fieldName]) => toSnakeCase(fieldName));\n\n return reportConflictColumns.length > 0\n ? [...(tenantColumn ? [tenantColumn] : []), ...reportConflictColumns]\n : ['id'];\n }\n\n // Fall back to table strategy-based defaults\n const tableStrategy = ObjectRegistry.getTableStrategy(className);\n return tableStrategy === 'sti'\n ? ['slug', 'context', '_meta_type']\n : ['slug', 'context'];\n }\n\n /**\n * Get the tenant scoping configuration for a class (Issue #688)\n *\n * Returns the normalized tenant scoping configuration if the class\n * was registered with `tenantScoped: true` or a tenantScoped config object.\n *\n * @param className - Name of the class to check\n * @returns Tenant scoping config or undefined if not tenant-scoped\n *\n * @example\n * ```typescript\n * @smrt({ tenantScoped: true })\n * class Document extends SmrtObject { }\n *\n * const config = ObjectRegistry.getTenantScopedConfig('Document');\n * // { mode: 'required', field: 'tenantId', autoFilter: true, autoPopulate: true, allowSuperAdminBypass: false }\n * ```\n */\n static getTenantScopedConfig(\n className: string,\n ): RegisteredClass['tenantScopedConfig'] | undefined {\n const registered = ObjectRegistry.findClass(className);\n return registered?.tenantScopedConfig;\n }\n\n /**\n * Check if a class is tenant-scoped (Issue #688)\n *\n * @param className - Name of the class to check\n * @returns true if the class has tenantScoped configuration\n */\n static isTenantScoped(className: string): boolean {\n return ObjectRegistry.getTenantScopedConfig(className) !== undefined;\n }\n\n /**\n * Get the base class for an STI hierarchy\n *\n * Walks up the inheritance chain to find the first class configured\n * with `tableStrategy: 'sti'`. This is the class that owns the shared table.\n *\n * **Returns:**\n * - The base class's **qualified name** (`@package/name:ClassName`) when\n * the registration has one — same convention as\n * `getInheritanceChain`. Falls back to the simple name only for\n * registrations without a package context (some test classes).\n * - `null` if the class uses CTI strategy.\n *\n * Accepts either a simple or a qualified name on input.\n *\n * @param className - Name of the class to find STI base for\n * @returns Qualified base class name or null if CTI\n * @example\n * ```typescript\n * @smrt({ tableStrategy: 'sti' })\n * class Event extends SmrtObject { }\n *\n * @smrt()\n * class Meeting extends Event { }\n *\n * ObjectRegistry.getSTIBase('@happyvertical/smrt-events:Meeting');\n * // '@happyvertical/smrt-events:Event'\n * ObjectRegistry.getSTIBase('@happyvertical/smrt-events:Event');\n * // '@happyvertical/smrt-events:Event'\n * ```\n */\n static getSTIBase(className: string): string | null {\n const strategy = ObjectRegistry.getTableStrategy(className);\n if (strategy === 'cti') {\n return null; // Not using STI\n }\n\n // Find the OLDEST/ROOT class in the chain with explicit tableStrategy: 'sti'\n // (Issue #703 fix: don't rely on tableName matching)\n //\n // In multi-level STI hierarchies (e.g., Council → Organization → Profile),\n // we need to return the oldest ancestor (Profile), not the first one found (Organization)\n //\n // IMPORTANT: Don't rely on tableName matching because:\n // 1. STI subclasses loaded from external manifests may have tableName: null\n // 2. registerFromManifest() derives a tableName from class name when null\n // 3. This causes tableName mismatch ('meetings' vs 'events')\n // 4. Instead, find the oldest ancestor with EXPLICIT tableStrategy: 'sti'\n //\n // R5-canon: chain entries are qualified names (when the class has a\n // package context), so the returned STI base is also qualified —\n // ambiguity across packages with same-simple-name STI roots is gone.\n const chain = ObjectRegistry.getInheritanceChain(className);\n\n // Walk the chain (ordered [root, ..., className]) to find oldest STI base\n for (const ancestorName of chain) {\n const ancestor = ObjectRegistry.findClass(ancestorName);\n if (!ancestor) continue;\n\n // Check if this ancestor EXPLICITLY declares tableStrategy: 'sti'\n // (not inherited via getTableStrategy(), but set directly in config)\n if (ancestor.config?.tableStrategy === 'sti') {\n // Found the OLDEST ancestor with explicit STI - this is the base\n // All descendants inherit from this table regardless of their tableName\n return ancestor.qualifiedName ?? ancestor.name;\n }\n }\n\n // If no explicit STI ancestor found but we detected STI strategy,\n // this class is its own STI base (it must have declared tableStrategy: 'sti').\n // Return its qualified name when available.\n const self = ObjectRegistry.findClass(className);\n return self?.qualifiedName ?? self?.name ?? className;\n }\n\n /**\n * Get all descendant classes of a base class\n *\n * Returns all registered classes that inherit from the specified base class.\n * Uses the `extends` field from manifest to build the descendant tree.\n *\n * **Use cases:**\n * - Schema generation: Aggregate fields from all children for STI table\n * - Polymorphic queries: Find all types to instantiate\n * - Documentation: Show class hierarchy\n *\n * Accepts either a simple or a qualified name on input. The returned\n * descendant names are **qualified** (`@package/name:ClassName`) when\n * the registration has one — same convention as `getInheritanceChain`\n * and `getSTIBase`.\n *\n * @param className - Name of the base class (simple or qualified)\n * @returns Array of qualified descendant class names (direct and indirect)\n * @example\n * ```typescript\n * @smrt({ tableStrategy: 'sti' })\n * class Event extends SmrtObject { }\n *\n * @smrt()\n * class Meeting extends Event { }\n *\n * @smrt()\n * class HockeyGame extends Event { }\n *\n * ObjectRegistry.getDescendants('@happyvertical/smrt-events:Event');\n * // [\n * // '@happyvertical/smrt-events:Meeting',\n * // '@happyvertical/smrt-events:HockeyGame',\n * // ]\n * ```\n */\n static getDescendants(className: string): string[] {\n const descendants: string[] = [];\n // main: dedup by RegisteredClass identity so a class registered under\n // multiple map keys (simple + qualified) is only emitted once.\n const seenRegistrations = new Set<RegisteredClass>();\n\n // R5-canon: inheritance chains are emitted with qualified names when\n // available, so the comparison against `className` must accept either\n // a qualified or simple input from the caller. Resolve once up-front\n // to whichever form actually appears in the chain.\n const target = ObjectRegistry.findClass(className);\n const targetKey = target?.qualifiedName ?? target?.name ?? className;\n\n // Find all classes that extend the given class\n for (const [_key, childClass] of ObjectRegistry.classes) {\n // main: skip classes already visited under another map key so the same\n // descendant isn't pushed twice (simple + qualified registrations point\n // at the same RegisteredClass object).\n if (seenRegistrations.has(childClass)) {\n continue;\n }\n seenRegistrations.add(childClass);\n\n // R5-canon: compare and emit qualified-when-available names so the\n // chain membership test (the chain holds qualified names) and the\n // returned descendants stay unambiguous across packages.\n const childKey = childClass.qualifiedName ?? childClass.name ?? _key;\n if (childKey === targetKey) continue;\n\n const chain = ObjectRegistry.getInheritanceChain(childKey);\n if (chain.includes(targetKey)) {\n descendants.push(childKey);\n }\n }\n\n return descendants;\n }\n\n /**\n * Persist registry state to system tables\n *\n * Saves all registered class metadata to the _smrt_registry system table\n * for runtime introspection and debugging. This enables applications to\n * query what SMRT objects exist and their configurations.\n *\n * @param db - Database interface to persist to\n * @returns Promise that resolves when persistence is complete\n * @example\n * ```typescript\n * // After registering all classes\n * await ObjectRegistry.persistToDatabase(db);\n *\n * // Later, query the system table\n * const rows = await db.all('SELECT * FROM _smrt_registry');\n * console.log('Registered classes:', rows.map(r => r.class_name));\n * ```\n */\n static async persistToDatabase(\n db: import('@happyvertical/sql').DatabaseInterface,\n ): Promise<void> {\n for (const [className, registered] of ObjectRegistry.classes.entries()) {\n const fieldsData: any = {};\n for (const [key, value] of registered.fields) {\n fieldsData[key] = {\n type: value.type,\n options: value.options,\n };\n }\n\n // Use upsert() for database-agnostic INSERT OR REPLACE\n // SQLite: INSERT OR REPLACE\n // Postgres/DuckDB: INSERT ... ON CONFLICT ... DO UPDATE\n await db.upsert(\n '_smrt_registry',\n ['class_name'], // PRIMARY KEY for conflict detection\n {\n class_name: className,\n schema_version: '1.0.0', // Could be derived from package version\n fields: JSON.stringify(fieldsData),\n relationships: JSON.stringify(\n ObjectRegistry.getRelationships(className),\n ),\n config: JSON.stringify(registered.config),\n manifest: JSON.stringify({\n name: registered.name,\n tableName: registered.schema?.tableName,\n tools: registered.tools,\n }),\n last_updated: new Date(),\n },\n );\n }\n }\n\n /**\n * Load registry metadata from system tables\n *\n * Reads the _smrt_registry system table to inspect what classes\n * have been registered. This is primarily for introspection and\n * debugging - actual class registration happens via @smrt() decorator.\n *\n * @param db - Database interface to load from\n * @returns Promise resolving to array of class metadata\n * @example\n * ```typescript\n * const metadata = await ObjectRegistry.loadFromDatabase(db);\n * for (const meta of metadata) {\n * console.log(`Class: ${meta.class_name}`);\n * console.log(`Table: ${JSON.parse(meta.manifest).tableName}`);\n * }\n * ```\n */\n static async loadFromDatabase(\n db: import('@happyvertical/sql').DatabaseInterface,\n ): Promise<any[]> {\n const { rows } = await db.query(\n 'SELECT * FROM _smrt_registry ORDER BY class_name',\n );\n return rows;\n }\n\n // ============================================================================\n // Embedding Configuration Methods\n // ============================================================================\n\n /**\n * Get embedding configuration for a class\n *\n * Returns the class-specific embedding config if embeddings are enabled.\n * This includes the fields to embed, provider override, and generation options.\n *\n * @param className - Name of the class to get embedding config for\n * @returns Class embedding config or undefined if not configured\n * @example\n * ```typescript\n * @smrt({\n * embeddings: {\n * fields: ['title', 'body'],\n * autoGenerate: true\n * }\n * })\n * class Article extends SmrtObject { }\n *\n * const config = ObjectRegistry.getEmbeddingConfig('Article');\n * // { fields: ['title', 'body'], autoGenerate: true }\n * ```\n */\n static getEmbeddingConfig(\n className: string,\n ): ClassEmbeddingConfig | undefined {\n return _getEmbeddingConfig(className);\n }\n\n /**\n * Check if a class has embeddings enabled\n *\n * @param className - Name of the class to check\n * @returns True if the class has embedding configuration\n * @example\n * ```typescript\n * if (ObjectRegistry.hasEmbeddings('Article')) {\n * await article.generateEmbeddings();\n * }\n * ```\n */\n static hasEmbeddings(className: string): boolean {\n return _hasEmbeddings(className);\n }\n\n /**\n * Get all registered classes that have embeddings enabled\n *\n * @returns Array of class names with embedding configuration\n * @example\n * ```typescript\n * const embeddableClasses = ObjectRegistry.getEmbeddingClasses();\n * // ['Article', 'Profile', 'Event']\n * ```\n */\n static getEmbeddingClasses(): string[] {\n return _getEmbeddingClasses();\n }\n\n /**\n * Get project-level embedding configuration\n *\n * Returns the global embedding settings from smrt.config (or defaults).\n * These settings apply to all classes unless overridden at the class level.\n *\n * @returns Project embedding configuration with defaults applied\n * @example\n * ```typescript\n * const projectConfig = ObjectRegistry.getProjectEmbeddingConfig();\n * // {\n * // dimensions: 768,\n * // provider: 'local',\n * // localModel: 'Xenova/bge-base-en-v1.5',\n * // aiModel: 'text-embedding-3-small',\n * // fallbackToAI: false\n * // }\n * ```\n */\n static getProjectEmbeddingConfig(): ProjectEmbeddingConfig {\n return _getProjectEmbeddingConfig();\n }\n\n /**\n * Resolve complete embedding configuration for a class\n *\n * Merges project-level config with class-level overrides.\n * Returns undefined if the class doesn't have embeddings enabled.\n *\n * @param className - Name of the class to resolve config for\n * @returns Fully resolved embedding config or undefined\n * @example\n * ```typescript\n * const config = ObjectRegistry.resolveEmbeddingConfig('Article');\n * // Merges project defaults with class-specific settings\n * // {\n * // fields: ['title', 'body'],\n * // dimensions: 768,\n * // provider: 'local',\n * // localModel: 'Xenova/bge-base-en-v1.5',\n * // autoGenerate: true,\n * // regenerateOnChange: true,\n * // ...\n * // }\n * ```\n */\n static resolveEmbeddingConfig(\n className: string,\n ): ResolvedEmbeddingConfig | undefined {\n return _resolveEmbeddingConfig(className);\n }\n\n /**\n * Resolve the effective collection read-cache config for a class (issue #1498)\n *\n * Walks the inheritance chain nearest-first so an STI base class opt-in\n * covers its children, while a child can opt back out with `cache: false`.\n *\n * @param className - Simple or qualified class name\n * @returns Effective cache config, or undefined when caching is not opted in\n */\n static resolveCollectionCacheConfig(\n className: string,\n ): CollectionCacheConfig | undefined {\n return _resolveCollectionCacheConfig(className);\n }\n}\n\n/**\n * Registers a `SmrtObject` or `SmrtCollection` subclass with the global `ObjectRegistry`.\n *\n * This decorator is the primary entry point for the SMRT framework. Applying it to a class:\n *\n * 1. Captures the original class name before minification and stores it as the\n * `SMRT_TABLE_NAME` static property — ensuring table names are stable in production builds.\n * 2. Registers class metadata (fields, schema, config) in the singleton `ObjectRegistry`.\n * 3. Enables automatic code generation: REST API endpoints (`api`), CLI commands (`cli`),\n * and MCP server tools (`mcp`) are generated at build time from the registered config.\n * 4. Activates lifecycle hooks (`hooks.beforeSave`, `hooks.afterDelete`, etc.).\n * 5. Configures AI-callable methods exposed to `is()` / `do()` via function calling (`ai`).\n * 6. Enables automatic vector embedding generation (`embeddings`).\n *\n * Apply to `SmrtCollection` subclasses as well — the decorator uses `_itemClass` to\n * register the collection under the correct table name and creates a collection-to-table\n * lookup used by the CLI and introspection tools.\n *\n * For Single Table Inheritance (STI), set `tableStrategy: 'sti'` on the base class only.\n * Child classes inherit the strategy automatically.\n *\n * @param config - Optional configuration for the class. All fields are optional; defaults\n * are derived from the class name and framework conventions.\n * @returns A class decorator that registers the class and returns the original constructor\n *\n * @example\n * ```typescript\n * // Basic usage — convention-based defaults\n * @smrt()\n * class Product extends SmrtObject {\n * @field({ required: true })\n * name: string = '';\n * price: number = 0.0; // 0.0 → DECIMAL column\n * }\n *\n * // Paired collection (required for collection.create())\n * @smrt()\n * class Products extends SmrtCollection<Product> {\n * static readonly _itemClass = Product;\n * }\n *\n * // STI base class\n * @smrt({ tableStrategy: 'sti' })\n * class Content extends SmrtObject {\n * title: string = '';\n * }\n *\n * // STI child — inherits strategy, adds @meta() fields stored in _meta_data JSON\n * @smrt()\n * class Article extends Content {\n * @meta() wordCount: number = 0;\n * }\n *\n * // Restrict generated API surface\n * @smrt({ api: { exclude: ['delete'] }, mcp: true, cli: false })\n * class Invoice extends SmrtObject {}\n *\n * // Junction/upsert table with natural key\n * @smrt({ conflictColumns: ['event_id', 'profile_id'] })\n * class EventParticipant extends SmrtObject {\n * eventId: string = '';\n * profileId: string = '';\n * }\n * ```\n *\n * @see {@link SmartObjectConfig} for all available configuration options\n * @see {@link field} / {@link meta} / {@link foreignKey} for field decorators\n */\nexport function smrt(config: SmartObjectConfig = {}) {\n return <T extends abstract new (...args: any[]) => any>(\n ctor: T,\n decoratorContext?: ClassDecoratorContext<T>,\n ): T => {\n applyPendingDecoratorRegistrations(ctor, decoratorContext);\n\n // Check if this is a SmrtCollection class\n const isCollection = ctor.prototype instanceof SmrtCollection;\n\n if (isCollection) {\n // Handle SmrtCollection registration\n const itemClass = (ctor as any)._itemClass;\n if (itemClass) {\n // Register the item class (SmrtObject) with metadata\n // For STI: Check if this class uses STI and get the base class's table name\n let tableName = config.tableName;\n\n if (!tableName) {\n // Check if this class or any parent uses STI.\n // R5-canon: resolve the item class to its qualified\n // registration first, then pass that qualified key to\n // `getSTIBase` / `getTableStrategy` so a colliding simple\n // name in another package can't yield the wrong base.\n // Falls back to the simple name when no registration exists\n // yet. Feeding a qualified string straight into\n // `classnameToTablename` would yield a garbled identifier —\n // route through the registered class's actual `schema.tableName`\n // when present.\n const itemClassName = itemClass.name;\n const itemReg = ObjectRegistry.getClassByConstructor(\n itemClass as any,\n );\n const itemQualified = itemReg?.qualifiedName ?? itemClassName;\n const stiBase = ObjectRegistry.getSTIBase(itemQualified);\n\n if (stiBase && stiBase !== itemQualified) {\n // Use STI base's table name\n const baseReg = ObjectRegistry.getClass(stiBase);\n tableName =\n baseReg?.schema?.tableName ??\n classnameToTablename(baseReg?.name ?? stiBase);\n } else if (ObjectRegistry.getTableStrategy(itemQualified) === 'sti') {\n // This is the STI base - use its own table name\n tableName = classnameToTablename(itemClassName);\n } else {\n // CTI: Use own table name\n tableName = classnameToTablename(itemClassName);\n }\n }\n\n ObjectRegistry.register(itemClass, { ...config, tableName });\n\n const registeredItemClass = ObjectRegistry.getClass(itemClass.name);\n\n // Register the collection constructor under the item class identity first.\n // This ensures ObjectRegistry.getCollection('ItemClass') uses the explicit\n // collection subclass rather than falling back to a generated default.\n ObjectRegistry.registerCollection(itemClass.name, ctor as any);\n if (registeredItemClass?.qualifiedName) {\n ObjectRegistry.registerCollection(\n registeredItemClass.qualifiedName,\n ctor as any,\n );\n }\n\n // Also register the collection constructor using tableName.\n // This preserves existing CLI/introspection lookups by table name\n // (e.g., \"meetings\") and keeps backward compatibility.\n ObjectRegistry.registerCollection(tableName, ctor as any);\n\n // Store collection class name -> tableName mapping for getTableName lookups\n // This enables ObjectRegistry.getTableName('CollectionClassName') to work\n ObjectRegistry.setCollectionTableName(ctor.name, tableName);\n }\n } else {\n // Handle SmrtObject registration (existing behavior)\n let tableName = config.tableName;\n\n if (!tableName) {\n // First, check manifest for tableName (manifest generator correctly handles STI inheritance)\n // This handles the case where a child class sets tableStrategy: 'sti' explicitly\n // but should still inherit the parent's table name\n const manifestEntry = discoverCachedManifestSync(ctor.name);\n if (manifestEntry?.decoratorConfig?.tableName) {\n tableName = manifestEntry.decoratorConfig.tableName;\n } else if (config.tableStrategy === 'sti') {\n // Fallback: Runtime prototype chain walking for STI detection\n // This is used when:\n // 1. Class is dynamically registered (not in manifest)\n // 2. Development mode without a build\n // 3. Test scenarios without manifest generation\n // Note: This relies on parents being registered first, which is why\n // the manifest check above is preferred (it has correct build-time data).\n //\n // R5-canon: `getSTIBase` now returns the qualified name. We\n // resolve back to the registered class and prefer its actual\n // `schema.tableName` when present; otherwise fall back to the\n // simple-name-derived table name. Deriving directly from a\n // qualified string would produce a garbled identifier.\n let proto = Object.getPrototypeOf(ctor);\n let stiBaseName: string | null = null;\n\n while (proto?.name && proto.name !== 'SmrtObject') {\n // R5-canon: walk via constructor identity (qualified name\n // from registration) rather than `proto.name`, so a\n // colliding simple name in another package can't yield the\n // wrong STI base. Falls through to simple `proto.name` for\n // unregistered prototypes.\n const protoReg = ObjectRegistry.getClassByConstructor(proto as any);\n const protoKey = protoReg?.qualifiedName ?? proto.name;\n if (ObjectRegistry.getTableStrategy(protoKey) === 'sti') {\n stiBaseName = ObjectRegistry.getSTIBase(protoKey);\n break;\n }\n proto = Object.getPrototypeOf(proto);\n }\n\n if (stiBaseName) {\n // This is an STI child - use parent's table name. Resolve the\n // qualified stiBaseName to its registration to pick the\n // correct table identifier.\n const baseReg = ObjectRegistry.getClass(stiBaseName);\n tableName =\n baseReg?.schema?.tableName ??\n classnameToTablename(baseReg?.name ?? stiBaseName);\n } else {\n // This is the actual STI base - use its own table name\n tableName = classnameToTablename(ctor.name);\n }\n } else {\n // Fallback: Check if any parent uses STI (implicit STI inheritance)\n // Same caveats as above - used only when manifest data unavailable.\n let proto = Object.getPrototypeOf(ctor);\n let stiBaseName: string | null = null;\n\n while (proto?.name && proto.name !== 'SmrtObject') {\n // Use getTableStrategy() to properly detect inherited STI strategy.\n // R5-canon: walk via constructor identity (qualified name\n // from registration) rather than `proto.name`, so a\n // colliding simple name in another package can't yield the\n // wrong STI base. Falls through to simple `proto.name` for\n // unregistered prototypes. Mirrors the sibling branch above.\n const protoReg = ObjectRegistry.getClassByConstructor(proto as any);\n const protoKey = protoReg?.qualifiedName ?? proto.name;\n if (ObjectRegistry.getTableStrategy(protoKey) === 'sti') {\n // Get the actual STI base (may be higher up the chain)\n stiBaseName = ObjectRegistry.getSTIBase(protoKey);\n break;\n }\n proto = Object.getPrototypeOf(proto);\n }\n\n if (stiBaseName) {\n // Use STI base's table name. (R5-canon: see above — qualified\n // stiBaseName resolves to its registration's tableName.)\n const baseReg = ObjectRegistry.getClass(stiBaseName);\n tableName =\n baseReg?.schema?.tableName ??\n classnameToTablename(baseReg?.name ?? stiBaseName);\n } else {\n // CTI: Use own table name\n tableName = classnameToTablename(ctor.name);\n }\n }\n }\n\n ObjectRegistry.register(ctor as any, { ...config, tableName });\n\n // R10: install a consistent `getX()` child accessor for every\n // `@oneToMany` field, delegating to `loadRelatedMany`. Runs after\n // registration so the relationship metadata is populated. Additive —\n // never overrides a hand-rolled accessor of the same name.\n applyOneToManyChildAccessors(\n ctor as any,\n ObjectRegistry.getRelationships(ctor.name),\n );\n }\n\n return ctor;\n };\n}\n"],"names":["_getCanonicalClassName","_hasClassCaseInsensitive","_register","_registerCollection","_registerFromManifest","_findClass","_getClass","_getClassByConstructor","_getClassByQualifiedName","_getClassInPackage","_findClassesByName","_resolveType","_getClassesByPackage","_getClassesByVisibility","_getPublicClasses","_getAllClasses","_getClassNames","_getQualifiedClassNames","packageName","manifest","objectDef","_hasClass","_invalidateInheritanceEntries","_compileValidators","_getSchema","_getSchemaDDL","_getTableName","_getAllSchemas","_getAllSchemasAsDefinitions","_getDependencyGraph","_getRelationshipMap","_getInheritanceChain","_getAllFields","_mergeFieldConfigs","_getAllMethods","_getEmbeddingConfig","_hasEmbeddings","_getEmbeddingClasses","_getProjectEmbeddingConfig","_resolveEmbeddingConfig","_resolveCollectionCacheConfig"],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sources":["../src/registry.ts"],"sourcesContent":["/**\n * Global object registry for SMRT classes\n *\n * Maintains a central registry of all @smrt decorated classes, enabling\n * module awareness, automatic API generation, and runtime introspection.\n * The registry tracks class definitions, field metadata, and configuration\n * options for code generation and runtime operations.\n *\n * @example Registering a class manually\n * ```typescript\n * import { ObjectRegistry } from '@happyvertical/smrt-core';\n *\n * ObjectRegistry.register(MyClass, {\n * api: { exclude: ['delete'] },\n * cli: true\n * });\n * ```\n *\n * @example Using the decorator (recommended)\n * ```typescript\n * import { smrt, field } from '@happyvertical/smrt-core';\n *\n * @smrt({ api: { exclude: ['delete'] } })\n * class Product extends SmrtObject {\n * @field({ required: true })\n * name: string = '';\n * }\n * ```\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { applyOneToManyChildAccessors } from './child-accessors';\nimport {\n SmrtCollection,\n type SmrtCollectionItemClass,\n type SmrtCollectionOptions,\n} from './collection';\nimport type { CollectionCacheConfig } from './collection-cache';\nimport { applyPendingDecoratorRegistrations } from './decorators/compatibility.js';\nimport type { FieldOptions } from './decorators/index.js';\nimport type {\n ClassEmbeddingConfig,\n ProjectEmbeddingConfig,\n ResolvedEmbeddingConfig,\n} from './embeddings/types';\nimport type { ValidationError } from './errors';\nimport { ConfigurationError } from './errors';\nimport { getDefaultCompositeSource } from './manifest/sources/composite.js';\nimport { ExplicitPathsManifestSource } from './manifest/sources/explicit-paths.js';\nimport {\n cloneManifestSchemaColumns,\n discoverCachedManifestSync,\n getNodeBuiltins,\n loadExternalManifestSyncWithNode,\n} from './manifest/store.js';\nimport type { SmrtObject } from './object';\n// ── Extracted modules (Issue #1006) ──────────────────────────────────────\nimport { resolveCollectionCacheConfig as _resolveCollectionCacheConfig } from './registry/cache-config';\nimport {\n invalidateInheritanceEntries as _invalidateInheritanceEntries,\n register as _register,\n registerCollection as _registerCollection,\n registerFromManifest as _registerFromManifest,\n} from './registry/class-registration';\nimport {\n clearRegistryDiagnostics,\n flushRegistryDiagnostics,\n getRegistryDiagnostics,\n type RegistryDiagnostic,\n recordRegistryDiagnostic,\n} from './registry/diagnostics';\nimport {\n getEmbeddingClasses as _getEmbeddingClasses,\n getEmbeddingConfig as _getEmbeddingConfig,\n getProjectEmbeddingConfig as _getProjectEmbeddingConfig,\n hasEmbeddings as _hasEmbeddings,\n resolveEmbeddingConfig as _resolveEmbeddingConfig,\n} from './registry/embedding-manager';\nimport {\n getAllFields as _getAllFields,\n getAllMethods as _getAllMethods,\n getInheritanceChain as _getInheritanceChain,\n mergeFieldConfigs as _mergeFieldConfigs,\n} from './registry/inheritance-resolver';\nimport {\n createFieldFromManifest,\n manifestFieldDiffers,\n mergeManifestField,\n} from './registry/manifest-field-merge.js';\nimport {\n findClass as _findClass,\n findClassesByName as _findClassesByName,\n getAllClasses as _getAllClasses,\n getCanonicalClassName as _getCanonicalClassName,\n getClass as _getClass,\n getClassByConstructor as _getClassByConstructor,\n getClassByQualifiedName as _getClassByQualifiedName,\n getClassesByPackage as _getClassesByPackage,\n getClassesByVisibility as _getClassesByVisibility,\n getClassInPackage as _getClassInPackage,\n getClassNames as _getClassNames,\n getPublicClasses as _getPublicClasses,\n getQualifiedClassNames as _getQualifiedClassNames,\n hasClass as _hasClass,\n hasClassCaseInsensitive as _hasClassCaseInsensitive,\n resolveType as _resolveType,\n} from './registry/name-resolver';\nimport {\n getDependencyGraph as _getDependencyGraph,\n getRelationshipMap as _getRelationshipMap,\n} from './registry/relationship-graph';\nimport {\n getAllSchemas as _getAllSchemas,\n getAllSchemasAsDefinitions as _getAllSchemasAsDefinitions,\n getSchema as _getSchema,\n getSchemaDDL as _getSchemaDDL,\n getTableName as _getTableName,\n} from './registry/schema-builder';\nimport {\n getClasses,\n getCollectionCache,\n getCollections,\n getCollectionTableNames,\n getDbInstanceIds,\n getDiscoveryAttemptCache,\n getFieldDecorators,\n getInheritanceCache,\n getNextDbId,\n getStiSiblingsLoaded,\n setNextDbId,\n verboseLog,\n} from './registry/shared-state';\nimport type {\n RegisteredClass,\n RegisteredField,\n RelationshipMetadata,\n SmartObjectConfig,\n SmrtObjectConstructor,\n ValidatorFunction,\n} from './registry/types';\nimport { compileValidators as _compileValidators } from './registry/validator';\nimport type {\n MethodDefinition,\n QualifiedClassName,\n SmartObjectDefinition,\n SmartObjectManifest,\n SmrtVisibility,\n ValidationRule,\n} from './scanner/types.js';\nimport type { ColumnDefinition, SchemaDefinition } from './schema/types.js';\nimport { classnameToTablename, toSnakeCase } from './utils';\nimport { LRUCache } from './utils/lru-cache';\nimport {\n createQualifiedName,\n isQualifiedName,\n parseQualifiedName,\n} from './utils/qualified-names.js';\n\nconst logger = createLogger({ level: 'info' });\n\n// Re-export the canonical collection-base detector so downstream tooling\n// (e.g. @happyvertical/smrt-vitest's manifest-based test-db builder) can share\n// the single source of truth instead of maintaining a drift-prone copy. The\n// junction-collection schema-drop bug (#1342) half-survived precisely because\n// a second copy of this detector existed; exporting it publicly kills that\n// drift class. See `./registry/collection-resolution.ts`.\nexport {\n isSmrtCollectionExtendsName,\n SMRT_COLLECTION_BASE_NAMES,\n} from './registry/collection-resolution';\n// Re-export types for backward compatibility\nexport type {\n RelationshipMetadata,\n RelationshipType,\n SmartObjectConfig,\n} from './registry/types';\n\n// Types, utility functions, and globalThis declarations have been extracted\n// to registry/types.ts and registry/shared-state.ts (Issue #1006).\n// The SmartObjectConfig, RelationshipType, and RelationshipMetadata types\n// are re-exported above for backward compatibility.\n\ntype ManifestLoaderModule = typeof import('./manifest/index.js');\n\nfunction getManifestLoaderSpecifier(): string {\n return import.meta.url.endsWith('.ts')\n ? './manifest/index.ts'\n : './manifest/index.js';\n}\n\nasync function importManifestLoader(): Promise<ManifestLoaderModule> {\n return (await import(getManifestLoaderSpecifier())) as ManifestLoaderModule;\n}\n\n/**\n * Loose view of a stored field's option bag. Field entries are heterogeneous\n * (decorator options, manifest-derived shapes, tenancy markers), so the\n * accessed members are narrowed individually rather than asserting a single\n * concrete type.\n */\ninterface FieldOptionsView {\n type?: string;\n sqlType?: unknown;\n __tenancy?: { isTenantIdField?: boolean };\n _meta?: {\n sqlType?: unknown;\n __tenancy?: { isTenantIdField?: boolean };\n };\n}\n\n/**\n * Decorator-supplied field metadata bag (from `@field()`, `@foreignKey()`,\n * `@oneToMany()`, `@manyToMany()`, etc.). All concrete decorator option\n * interfaces extend `FieldOptions`; this adds the relationship/junction members\n * that the relationship and cross-package decorators store and that downstream\n * consumers (`SmrtObject` relationship resolution, schema builder) read back.\n */\ninterface FieldDecoratorOptions extends FieldOptions {\n /** Related class name (foreignKey / crossPackageRef / oneToMany / manyToMany). */\n related?: string;\n /** Inverse foreign-key field name for relationship resolution. */\n foreignKey?: string;\n /** Join table name for many-to-many relationships. */\n through?: string;\n /** Source-side join column override for many-to-many relationships. */\n sourceKey?: string;\n /** Target-side join column override for many-to-many relationships. */\n targetKey?: string;\n // Opaque framework marker bags set by cross-package decorators\n // (`@TenantScoped` → __tenancy, `@report` → __report). Their concrete\n // shapes live in the downstream packages (e.g. reports' ReportFieldMetadata),\n // so the registry-input type stays `unknown` — core never reads these off the\n // decorator-options bag, it only stores/forwards them.\n __tenancy?: unknown;\n __report?: unknown;\n}\n\n/**\n * Constructor shape for a registered collection class.\n *\n * The `SmrtCollection<any>` type argument is an intentional heterogeneous-\n * storage leave: the registry maps many different item types onto a single\n * constructor-map shape and invokes invariant methods (`create()`), so it\n * cannot be narrowed to `SmrtCollection<SmrtObject>`. The `options` param is\n * `any` (not `unknown`): consumers register CONCRETE collection constructors\n * (`new (options: ChatRoomCollectionOptions) => …`), and constructor params are\n * contravariant — `unknown` would reject those, `any` (like `SmrtObjectConstructor`)\n * stays assignable from any concrete options shape.\n */\n// biome-ignore lint/suspicious/noExplicitAny: registers CONCRETE collection constructors whose contravariant `options` reject `unknown`, and `SmrtCollection` is invariant in `ModelType` so the type arg cannot narrow to `SmrtObject`. Mirrors `SmrtObjectConstructor`. S4 #1579.\ntype CollectionConstructor = new (options: any) => SmrtCollection<any>;\n\n/**\n * AI-callable tool descriptor surfaced alongside class metadata. Mirrors the\n * `tools` shape on {@link RegisteredClass}.\n */\ninterface ObjectMetadataTool {\n type: 'function';\n function: {\n name: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n}\n\n/**\n * Aggregated, read-only metadata snapshot for a single registered class.\n * Returned by `getObjectMetadata` / `getAllObjectMetadata`.\n */\ninterface ObjectMetadata {\n name: string;\n constructor: typeof SmrtObject;\n collectionConstructor?: CollectionConstructor;\n config: SmartObjectConfig;\n fields: Map<string, RegisteredField>;\n methods: Map<string, MethodDefinition>;\n schema: SchemaDefinition | undefined;\n validators: ValidatorFunction[];\n relationships: RelationshipMetadata[];\n inverseRelationships: RelationshipMetadata[];\n tools?: ObjectMetadataTool[];\n}\n\nfunction getReferenceKindFromFieldOptions(\n fieldOptions: FieldOptionsView | undefined,\n): ColumnDefinition['referenceKind'] | undefined {\n if (\n fieldOptions?.__tenancy?.isTenantIdField ||\n fieldOptions?._meta?.__tenancy?.isTenantIdField\n ) {\n return 'tenantId';\n }\n\n if (fieldOptions?.type === 'foreignKey') {\n return 'foreignKey';\n }\n\n if (fieldOptions?.type === 'crossPackageRef') {\n return 'crossPackageRef';\n }\n\n return undefined;\n}\n\nfunction applyManifestFieldColumnMetadata(\n columns: Record<string, ColumnDefinition>,\n fieldEntries: Iterable<[string, FieldOptionsView]> | undefined,\n): void {\n if (!fieldEntries) {\n return;\n }\n\n for (const [fieldName, fieldOptions] of fieldEntries) {\n const sqlType = fieldOptions?.sqlType ?? fieldOptions?._meta?.sqlType;\n const referenceKind = getReferenceKindFromFieldOptions(fieldOptions);\n if (!sqlType && !referenceKind) {\n continue;\n }\n\n const columnName = toSnakeCase(fieldName);\n const existingColumn = columns[columnName];\n if (!existingColumn) {\n continue;\n }\n\n columns[columnName] = {\n ...existingColumn,\n ...(sqlType\n ? { type: String(sqlType).toUpperCase() as ColumnDefinition['type'] }\n : {}),\n ...(referenceKind ? { referenceKind } : {}),\n };\n }\n}\n\nasync function discoverInstalledSmrtPackages(): Promise<string[]> {\n const discoverSpecifier = import.meta.url.endsWith('.ts')\n ? './manifest/discover-smrt-packages.ts'\n : './manifest/discover-smrt-packages.js';\n\n const { discoverSmrtPackages } = await import(discoverSpecifier);\n return discoverSmrtPackages();\n}\n\n/**\n * Recover a package's `manifest.json` when the path derived from the\n * `__smrt-register__` shim's `import.meta.url` does not exist.\n *\n * The shim resolves the manifest with `new URL('./manifest.json',\n * import.meta.url)`, which assumes the compiled side-effect sits directly\n * next to `dist/manifest.json`. Vite chunk-splitting is non-deterministic and\n * occasionally hoists that side-effect into a `dist/chunks/<hash>.js` chunk,\n * so the URL resolves to a non-existent `dist/chunks/manifest.json`. This\n * walks up a bounded number of parent directories looking for a sibling\n * `manifest.json`, keeping self-registration working regardless of where the\n * bundler placed the shim (#1331).\n *\n * @param builtins - Node fs/path/url modules from `getNodeBuiltins()`.\n * @param missingPath - The non-existent manifest path the shim derived.\n * @returns The recovered manifest path, or `null` if none was found.\n */\nfunction resolveManifestByUpwardSearch(\n builtins: NonNullable<ReturnType<typeof getNodeBuiltins>>,\n missingPath: string,\n): string | null {\n const { fs, path } = builtins;\n const fileName = path.basename(missingPath);\n // Bound the walk so a stray, deeply-nested path can never trigger a slow or\n // unbounded filesystem crawl. Chunks are normally one directory deep\n // (`dist/chunks/`), so a handful of levels is comfortably sufficient. The\n // package-root stop below is the authoritative guard; this is just a backstop.\n const MAX_LEVELS = 4;\n let dir = path.dirname(missingPath);\n for (let level = 0; level < MAX_LEVELS; level++) {\n const parent = path.dirname(dir);\n // Reached the filesystem root — `dirname` is now idempotent.\n if (parent === dir) {\n break;\n }\n const candidate = path.join(parent, fileName);\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n // Never search above the package root. The real manifest is always at\n // `<pkg>/dist/manifest.json`; once we have checked the directory that holds\n // `package.json` (the package root), stop. Otherwise a chunk whose\n // `dist/manifest.json` is genuinely absent could match an unrelated\n // `manifest.json` from a parent package, the monorepo root, or a\n // `node_modules` ancestor — registering the WRONG package's schema, which\n // is worse than a clean no-op.\n if (fs.existsSync(path.join(parent, 'package.json'))) {\n break;\n }\n dir = parent;\n }\n return null;\n}\n\n/**\n * Central registry for all SMRT objects\n *\n * Uses globalThis for cross-module state sharing, ensuring all module instances\n * (even from different package resolution paths) share the same registry state.\n */\nexport class ObjectRegistry {\n /**\n * Get the classes map from globalThis, initializing if needed\n */\n private static get classes(): Map<string, RegisteredClass> {\n return getClasses();\n }\n\n /**\n * Get the collections map from globalThis, initializing if needed\n */\n private static get collections(): Map<string, typeof SmrtCollection> {\n return getCollections();\n }\n\n /**\n * Get the collection table names map from globalThis, initializing if needed\n * Maps collection class name -> tableName for getTableName lookups\n */\n private static get collectionTableNames(): Map<string, string> {\n return getCollectionTableNames();\n }\n\n /**\n * Set the table name for a collection class\n * Used by @smrt() decorator to enable getTableName lookups for collections\n */\n static setCollectionTableName(\n collectionName: string,\n tableName: string,\n ): void {\n ObjectRegistry.collectionTableNames.set(collectionName, tableName);\n }\n\n /**\n * Get the collection cache from globalThis, initializing if needed\n */\n // biome-ignore lint/suspicious/noExplicitAny: heterogeneous cache of concrete collections; `SmrtCollection` is invariant in `ModelType`, so the type arg cannot narrow to `SmrtObject` (read sites cast back). S4 #1579.\n private static get collectionCache(): LRUCache<string, SmrtCollection<any>> {\n return getCollectionCache();\n }\n\n /**\n * Configure the collection cache size (for testing purposes)\n *\n * Resets the collection cache with a new maximum size.\n * Use this in tests to avoid creating many database files.\n *\n * @param maxSize - Maximum number of collections to cache (system default is 100)\n * @throws Error if maxSize is not a positive finite number\n * @example\n * ```typescript\n * // In test setup, use a small cache to test LRU eviction with fewer DBs\n * ObjectRegistry.configureCollectionCache(5);\n * ```\n */\n static configureCollectionCache(maxSize: number): void {\n if (!Number.isFinite(maxSize) || maxSize <= 0) {\n throw new Error(`maxSize must be a positive number, got: ${maxSize}`);\n }\n globalThis.__smrtRegistryCollectionCache = new LRUCache<\n string,\n // biome-ignore lint/suspicious/noExplicitAny: heterogeneous cache of concrete collections; `SmrtCollection` is invariant in `ModelType` so the type arg cannot narrow to `SmrtObject`. S4 #1579.\n SmrtCollection<any>\n >(maxSize);\n }\n\n /**\n * WeakMap to assign unique IDs to database instances for cache keys\n * Prevents cache key collisions when different db instances are used\n */\n private static get dbInstanceIds(): WeakMap<object, number> {\n return getDbInstanceIds();\n }\n\n /**\n * Get/set the next database ID counter\n */\n private static get nextDbId(): number {\n return getNextDbId();\n }\n\n private static set nextDbId(value: number) {\n setNextDbId(value);\n }\n\n /**\n * Storage for field decorator metadata (decorator pattern)\n * Maps className → Map<propertyKey, FieldOptions>\n * Used by @field(), @foreignKey(), @oneToMany(), @manyToMany() decorators\n */\n private static get fieldDecorators(): Map<\n string,\n Map<string, FieldDecoratorOptions>\n > {\n // Shared state stores these as the looser `Record<string, unknown>` (it\n // can't import the registry-local `FieldDecoratorOptions`); this getter\n // exposes the precise decorator-options view. Documented narrowing cast.\n return getFieldDecorators() as Map<\n string,\n Map<string, FieldDecoratorOptions>\n >;\n }\n\n /**\n * Track collections that have been processed for STI siblings\n * Prevents infinite recursion when loading siblings\n */\n private static get stiSiblingsLoaded(): Set<string> {\n return getStiSiblingsLoaded();\n }\n\n /**\n * Check if a class is already registered (case-insensitive)\n * Returns the canonical name if found, undefined otherwise.\n *\n * Release B (#1133): iteration over `classes` replaces the old eagerly-\n * maintained classNameMap index. Negligible cost at production scale and\n * removes an entire class of cache-sync bugs.\n */\n static getCanonicalClassName(name: string): string | undefined {\n return _getCanonicalClassName(name);\n }\n\n /**\n * Check if a class exists by name (case-insensitive)\n */\n static hasClassCaseInsensitive(name: string): boolean {\n return _hasClassCaseInsensitive(name);\n }\n\n /**\n * Global cache for inheritance chains (shared across all instances)\n * Maps className → full inheritance chain (base to child)\n * Performance optimization: ~100x faster than re-walking prototype chain\n * Cache size is configurable via smrt.inheritance.cacheSize (default: 200)\n */\n private static getInheritanceCache(): LRUCache<string, string[]> {\n return getInheritanceCache();\n }\n\n /**\n * Global cache for manifest discovery attempts (Issue #735 optimization)\n * Maps className → boolean (true = found and registered, false = not found)\n * Prevents repeated discoverManifestSync calls for the same class name\n */\n private static getDiscoveryAttemptCache(): Map<string, boolean> {\n return getDiscoveryAttemptCache();\n }\n\n /**\n * Register field decorator metadata\n *\n * Called by property decorators (@field, @foreignKey, etc.) to store\n * field configuration metadata. This enables the decorator pattern\n * where field metadata is attached at class definition time.\n *\n * @param className - Name of the class containing the field\n * @param propertyKey - Name of the property being decorated\n * @param options - Field options (type, constraints, etc.)\n * @example\n * ```typescript\n * // Called internally by decorators\n * ObjectRegistry.registerFieldDecorator('Product', 'name', {\n * type: 'text',\n * required: true\n * });\n * ```\n */\n static registerFieldDecorator(\n className: string,\n propertyKey: string,\n options: FieldDecoratorOptions,\n ): void {\n if (!ObjectRegistry.fieldDecorators.has(className)) {\n ObjectRegistry.fieldDecorators.set(className, new Map());\n }\n\n // Merge with existing decorator options to support multiple decorators on same field\n const classDecorators = ObjectRegistry.fieldDecorators.get(className);\n if (!classDecorators) {\n // Should not happen since we just set it above, but TypeScript doesn't know that\n return;\n }\n const existing = classDecorators.get(propertyKey);\n\n if (existing) {\n // Merge options, with new options taking precedence\n classDecorators.set(propertyKey, { ...existing, ...options });\n } else {\n classDecorators.set(propertyKey, options);\n }\n }\n\n /**\n * Get field decorator metadata for a specific field\n *\n * @param className - Name of the class\n * @param propertyKey - Name of the property\n * @returns Field options or undefined if not decorated\n * @example\n * ```typescript\n * const options = ObjectRegistry.getFieldDecorator('Product', 'name');\n * // { type: 'text', required: true }\n * ```\n */\n static getFieldDecorator(\n className: string,\n propertyKey: string,\n ): FieldDecoratorOptions | undefined {\n return ObjectRegistry.fieldDecorators.get(className)?.get(propertyKey);\n }\n\n /**\n * Get all field decorator metadata for a class\n *\n * @param className - Name of the class\n * @returns Map of property names to field options\n * @example\n * ```typescript\n * const fields = ObjectRegistry.getFieldDecorators('Product');\n * // Map { 'name' => { type: 'text', required: true }, ... }\n * ```\n */\n static getFieldDecorators(\n className: string,\n ): Map<string, FieldDecoratorOptions> {\n return ObjectRegistry.fieldDecorators.get(className) || new Map();\n }\n\n /**\n * Check if a class has any field decorators registered\n *\n * @param className - Name of the class\n * @returns True if the class has field decorators, false otherwise\n * @example\n * ```typescript\n * if (ObjectRegistry.hasFieldDecorators('Product')) {\n * // Class uses decorators - skip legacy field initialization\n * }\n * ```\n */\n static hasFieldDecorators(className: string): boolean {\n const decorators = ObjectRegistry.fieldDecorators.get(className);\n return decorators !== undefined && decorators.size > 0;\n }\n\n /**\n * Register a new SMRT object class with the global registry\n *\n * @param constructor - The class constructor extending SmrtObject\n * @param config - Configuration options for API/CLI/MCP generation\n * @throws {Error} If the class cannot be introspected for field definitions\n * @example\n * ```typescript\n * ObjectRegistry.register(Product, {\n * api: { exclude: ['delete'] },\n * cli: true,\n * mcp: { include: ['list', 'get'] }\n * });\n * ```\n */\n static register(\n ctor: typeof SmrtObject,\n config: SmartObjectConfig = {},\n ): void {\n _register(ctor, config);\n }\n\n /**\n * Register a collection class for an object\n *\n * @param objectName - Name of the object class this collection manages\n * @param collectionConstructor - The collection class constructor\n * @example\n * ```typescript\n * ObjectRegistry.registerCollection('Product', ProductCollection);\n * ```\n */\n static registerCollection(\n objectName: string,\n collectionConstructor: CollectionConstructor,\n ): void {\n _registerCollection(objectName, collectionConstructor);\n }\n static registerFromManifest(\n name: string,\n objectDef: SmartObjectDefinition,\n packageName?: string,\n ): void {\n _registerFromManifest(name, objectDef, packageName);\n }\n\n /**\n * Helper method for class lookup with qualified name support.\n *\n * Lookup priority:\n * 1. Direct hit on classes map (works for qualified names as keys)\n * 2. If input contains ':', treat as qualified name — direct only, no fallback\n * 3. classNameMap lookup by simple name (lowercase)\n * - Unambiguous (1 entry) → return it\n * - Ambiguous (>1 entry) → throw descriptive error\n * 4. Case-insensitive iteration fallback (backward compat)\n *\n * @param name - Name of the class to find (simple or qualified)\n * @returns Registered class information or undefined if not found\n * @remarks When a simple name is ambiguous (multiple packages define it),\n * logs a warning and returns the first match. Use qualified names\n * or resolveType() for strict disambiguation.\n * @private\n */\n private static findClass(name: string): RegisteredClass | undefined {\n return _findClass(name);\n }\n\n // The private `findClassStrict` wrapper that used to live here was removed\n // with the inline inheritance-chain copy (#1378); strict, package-aware\n // resolution now lives solely in registry/inheritance-resolver, which calls\n // the name-resolver helper directly.\n\n /**\n * Get a registered class by name (case-insensitive)\n *\n * @param name - Name of the registered class\n * @returns Registered class information or undefined if not found\n * @example\n * ```typescript\n * const productInfo = ObjectRegistry.getClass('Product');\n * // Also works with: 'product', 'PRODUCT', etc.\n * if (productInfo) {\n * console.log(productInfo.config.api?.exclude);\n * }\n * ```\n */\n static getClass(name: string): RegisteredClass | undefined {\n return _getClass(name);\n }\n\n /**\n * Get a registered class by its constructor reference.\n * This is the most reliable lookup method as it avoids name collision issues\n * that can occur when multiple packages define classes with the same name.\n *\n * Uses a WeakMap index for O(1) lookups.\n *\n * @param ctor - The class constructor to look up\n * @returns Registered class information or undefined if not found\n * @example\n * ```typescript\n * import { Meeting } from '@happyvertical/praeco';\n *\n * const info = ObjectRegistry.getClassByConstructor(Meeting);\n * if (info) {\n * console.log(info.qualifiedName); // '@happyvertical/praeco:Meeting'\n * }\n * ```\n */\n static getClassByConstructor(\n ctor: SmrtObjectConstructor,\n ): RegisteredClass | undefined {\n return _getClassByConstructor(ctor);\n }\n\n /**\n * Get a registered class by its qualified name.\n * Qualified names are in format \"@package/name:ClassName\".\n *\n * @param qualifiedName - The fully qualified class name\n * @returns Registered class information or undefined if not found\n * @example\n * ```typescript\n * const product = ObjectRegistry.getClassByQualifiedName('@happyvertical/smrt-products:Product');\n * if (product) {\n * console.log(`Found: ${product.name} from ${product.packageName}`);\n * }\n * ```\n */\n static getClassByQualifiedName(\n qualifiedName: string,\n ): RegisteredClass | undefined {\n return _getClassByQualifiedName(qualifiedName);\n }\n\n /**\n * Get a registered class by package name and class name.\n * This is a convenience method for looking up classes by their namespace components.\n *\n * @param packageName - The package name (e.g., \"@happyvertical/smrt-products\")\n * @param className - The class name (e.g., \"Product\")\n * @returns Registered class information or undefined if not found\n * @example\n * ```typescript\n * const product = ObjectRegistry.getClassInPackage('@happyvertical/smrt-products', 'Product');\n * ```\n */\n static getClassInPackage(\n packageName: string,\n className: string,\n ): RegisteredClass | undefined {\n return _getClassInPackage(packageName, className);\n }\n\n /**\n * Find all registered classes with a given simple class name.\n * Useful for detecting collisions or when multiple packages have the same class name.\n *\n * @param className - The simple class name to search for\n * @returns Array of registered classes with matching name\n * @example\n * ```typescript\n * const products = ObjectRegistry.findClassesByName('Product');\n * if (products.length > 1) {\n * console.log(`Found ${products.length} classes named \"Product\":`);\n * for (const p of products) {\n * console.log(` - ${p.qualifiedName} from ${p.packageName}`);\n * }\n * }\n * ```\n */\n static findClassesByName(className: string): RegisteredClass[] {\n return _findClassesByName(className);\n }\n\n /**\n * Resolve a short class name to its qualified name.\n * Throws an error if the name is ambiguous (multiple packages define the same class name).\n *\n * @param shortName - The simple class name to resolve (e.g., 'MeetingRecap')\n * @returns The qualified class name (e.g., '@happyvertical/praeco:MeetingRecap')\n * @throws {Error} If no class with that name is registered\n * @throws {Error} If multiple classes with that name exist (ambiguous)\n *\n * @example\n * ```typescript\n * // Unambiguous resolution\n * const qualified = ObjectRegistry.resolveType('MeetingRecap');\n * // Returns: '@happyvertical/praeco:MeetingRecap'\n *\n * // Already qualified names pass through\n * const same = ObjectRegistry.resolveType('@happyvertical/praeco:MeetingRecap');\n * // Returns: '@happyvertical/praeco:MeetingRecap'\n *\n * // Ambiguous names throw\n * ObjectRegistry.resolveType('Event');\n * // Error: \"Event\" is ambiguous. Found in multiple packages:\n * // - @happyvertical/smrt-events:Event\n * // - @happyvertical/calendar:Event\n * // Use the fully qualified name instead.\n * ```\n */\n static resolveType(shortName: string): QualifiedClassName {\n return _resolveType(shortName);\n }\n\n /**\n * Get all registered classes from a specific package.\n *\n * @param packageName - The package name to filter by\n * @returns Map of class names to registered class information\n * @example\n * ```typescript\n * const coreClasses = ObjectRegistry.getClassesByPackage('@happyvertical/smrt-core');\n * for (const [name, info] of coreClasses) {\n * console.log(` ${name}: ${info.qualifiedName}`);\n * }\n * ```\n */\n static getClassesByPackage(\n packageName: string,\n ): Map<string, RegisteredClass> {\n return _getClassesByPackage(packageName);\n }\n\n /**\n * Get all registered classes with a specific visibility level.\n *\n * @param visibility - The visibility level to filter by\n * @returns Map of class names to registered class information\n * @example\n * ```typescript\n * const publicClasses = ObjectRegistry.getClassesByVisibility('public');\n * console.log(`Found ${publicClasses.size} public classes`);\n * ```\n */\n static getClassesByVisibility(\n visibility: SmrtVisibility,\n ): Map<string, RegisteredClass> {\n return _getClassesByVisibility(visibility);\n }\n\n /**\n * Get all public registered classes (excludes 'internal' and 'test' visibility).\n * Useful for generating published manifests or public APIs.\n *\n * @returns Map of class names to registered class information\n * @example\n * ```typescript\n * const publicClasses = ObjectRegistry.getPublicClasses();\n * console.log(`Publishing ${publicClasses.size} public classes to manifest`);\n * ```\n */\n static getPublicClasses(): Map<string, RegisteredClass> {\n return _getPublicClasses();\n }\n\n /**\n * Get all registered classes\n *\n * @returns Map of class names to registered class information\n * @example\n * ```typescript\n * const allClasses = ObjectRegistry.getAllClasses();\n * for (const [name, info] of allClasses) {\n * console.log(`Class: ${name}, Fields: ${info.fields.size}`);\n * }\n * ```\n */\n static getAllClasses(): Map<string, RegisteredClass> {\n return _getAllClasses();\n }\n\n /**\n * Get class names, deduplicated by simple class name.\n *\n * This is useful for display and backwards compatibility. Use\n * `getQualifiedClassNames()` for schema/bootstrap loops that must preserve\n * cross-package collisions.\n */\n static getClassNames(): string[] {\n return _getClassNames();\n }\n\n /**\n * Get one lookup name per registered class, preserving cross-package\n * collisions by preferring qualified class names where available.\n */\n static getQualifiedClassNames(): string[] {\n return _getQualifiedClassNames();\n }\n\n /**\n * Try to load and register a class from external SMRT packages\n *\n * This method attempts to auto-discover classes from @happyvertical/smrt-* packages\n * when they're referenced but not yet registered. Solves issue #343 where STI classes\n * from external packages (e.g., Person from smrt-profiles) weren't loading correctly.\n *\n * @param className - Name of the class to load\n * @returns Promise<boolean> - True if successfully loaded and registered, false otherwise\n * @private\n */\n static async tryLoadFromExternalPackage(className: string): Promise<boolean> {\n const requestedQualifiedName = isQualifiedName(className)\n ? parseQualifiedName(className)\n : null;\n const requestedClassName = requestedQualifiedName?.className || className;\n const requestedPackageName = requestedQualifiedName?.packageName;\n const smrtPackages = requestedPackageName\n ? [requestedPackageName]\n : await discoverInstalledSmrtPackages();\n const { loadExternalManifest } = await importManifestLoader();\n\n verboseLog(\n `[ObjectRegistry] Attempting to auto-load ${className} from ${smrtPackages.length} external packages...`,\n );\n\n const matches: Array<{\n manifest: SmartObjectManifest;\n packageName: string;\n objectDef: SmartObjectDefinition;\n }> = [];\n\n // Try each package\n for (const packageName of smrtPackages) {\n const manifest = await loadExternalManifest(packageName);\n\n if (!manifest || !manifest.objects) {\n continue;\n }\n\n // Look for the class in this manifest (case-insensitive)\n // Support both qualified keys (@pkg:Class) and simple class names\n const lowerClassName = requestedClassName.toLowerCase();\n let objectDef =\n manifest.objects[lowerClassName] ||\n manifest.objects[requestedClassName] ||\n (requestedPackageName\n ? manifest.objects[\n `${requestedPackageName}:${requestedClassName}` as string\n ]\n : undefined);\n\n // If not found by direct key lookup, search by className field (Issue #713)\n // This handles manifests with qualified keys while allowing simple name lookups\n if (!objectDef) {\n for (const [_key, def] of Object.entries(manifest.objects)) {\n if (\n def.className?.toLowerCase() === lowerClassName ||\n def.className === requestedClassName\n ) {\n objectDef = def;\n break;\n }\n }\n }\n\n if (!objectDef) {\n continue;\n }\n\n matches.push({\n manifest,\n packageName: manifest.packageName || packageName,\n objectDef,\n });\n }\n\n if (matches.length === 0) {\n verboseLog(\n `[ObjectRegistry] ❌ Could not find ${className} in any SMRT package`,\n );\n return false;\n }\n\n if (!requestedPackageName && matches.length > 1) {\n throw new ConfigurationError(\n `Ambiguous class name \"${className}\" — found in multiple external SMRT packages: ` +\n `${matches.map((match) => match.packageName).join(', ')}. ` +\n 'Preserve package identity or use a qualified class name to disambiguate.',\n 'CONFIG_AMBIGUOUS_CLASS',\n {\n className,\n candidates: matches.map((match) => match.packageName),\n },\n );\n }\n\n const { manifest, packageName, objectDef } = matches[0];\n\n verboseLog(\n `[ObjectRegistry] ✅ Found ${className} in ${packageName} manifest`,\n );\n\n // Register the class from manifest\n ObjectRegistry.registerFromManifest(\n objectDef.className || requestedClassName,\n objectDef,\n manifest.packageName,\n );\n\n // If this is an STI class, also register the parent class\n // Skip if extends points to the same className (self-referential):\n // This happens when a child class in one package extends a parent with the\n // same name from another package (e.g., histrio:Performer extends smrt-video:Performer)\n // and only the child package is installed\n const childClassName = objectDef.className || requestedClassName;\n if (objectDef.extends && objectDef.extends !== childClassName) {\n const parentName = objectDef.extends;\n const lowerParentName = parentName.toLowerCase();\n let parentDef =\n manifest.objects[lowerParentName] || manifest.objects[parentName];\n\n // Search by className field if not found by key (Issue #713)\n if (!parentDef) {\n for (const [_key, def] of Object.entries(manifest.objects)) {\n if (\n def.className?.toLowerCase() === lowerParentName ||\n def.className === parentName\n ) {\n parentDef = def;\n break;\n }\n }\n }\n\n if (parentDef && !ObjectRegistry.hasClass(objectDef.extends)) {\n verboseLog(\n `[ObjectRegistry] Also registering parent class ${objectDef.extends} for STI`,\n );\n ObjectRegistry.registerFromManifest(\n parentDef.className || objectDef.extends,\n parentDef,\n manifest.packageName,\n );\n }\n\n // Merge inherited fields from parent into child\n // This ensures STI child classes get all parent fields\n verboseLog(\n `[ObjectRegistry] Merging inherited fields for ${className}...`,\n );\n await ObjectRegistry.getAllFields(requestedClassName);\n const registered = ObjectRegistry.findClass(requestedClassName);\n if (registered?.inheritedFields) {\n verboseLog(\n `[ObjectRegistry] ✅ ${className} now has ${registered.inheritedFields.size} total fields (including inherited)`,\n );\n }\n }\n\n return true;\n }\n\n /**\n * Load all manifests upfront so inheritance queries are pure lookups.\n *\n * After this method completes, every class across all packages is\n * registered and `getInheritanceChain()` will never need to mutate\n * registry state.\n *\n * @param options - Optional configuration\n * @param options.manifestPaths - Explicit list of manifest.json file paths to load.\n * When omitted the method discovers packages via `loadExternalManifestSync()`\n * for every `@happyvertical` package found in `node_modules`.\n * @returns Summary statistics about the load operation\n *\n * @example\n * ```typescript\n * // At CLI / server startup\n * ObjectRegistry.loadAllManifests();\n * // All classes are now registered — inheritance lookups are side-effect free\n * ```\n *\n * @see https://github.com/happyvertical/smrt/issues/1007\n */\n static loadAllManifests(options?: { manifestPaths?: string[] }): {\n packagesLoaded: number;\n objectsRegistered: number;\n } {\n let packagesLoaded = 0;\n let objectsRegistered = 0;\n\n if (options?.manifestPaths) {\n // Explicit paths → ExplicitPathsManifestSource. Preserves the\n // full-registry-integration.test.ts:72-76 contract.\n const source = new ExplicitPathsManifestSource(options.manifestPaths);\n for (const entry of source.entries()) {\n if (!ObjectRegistry.hasClassCaseInsensitive(entry.className)) {\n ObjectRegistry.registerFromManifest(\n entry.className,\n entry.def,\n entry.packageName,\n );\n objectsRegistered++;\n }\n }\n // Preserve historical semantics: packagesLoaded counts each\n // successfully-read manifest path (not distinct packageName values).\n // Two paths pointing at the same package counted as two before Release\n // B and must continue to do so.\n packagesLoaded = source.loadedCount;\n } else {\n // Auto-discover: seed the embedded cache from every installed\n // @happyvertical/smrt-* package, then iterate composite.entries() —\n // LocalTest/Test sources gate themselves on isTestEnvironment() and\n // NodeModulesFallback is a no-op on `.lookup()`, so the iteration\n // yields exactly the same set of entries as the old manual scan.\n const packagePrefixes = ['@happyvertical/smrt-'];\n try {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return { packagesLoaded, objectsRegistered };\n }\n\n const scopeDir = builtins.path.join(\n process.cwd(),\n 'node_modules',\n '@happyvertical',\n );\n if (!builtins.fs.existsSync(scopeDir)) {\n return { packagesLoaded, objectsRegistered };\n }\n\n const packages = builtins.fs\n .readdirSync(scopeDir)\n .filter((name) =>\n packagePrefixes.some((prefix) =>\n `@happyvertical/${name}`.startsWith(prefix),\n ),\n );\n\n const seenPackages = new Set<string>();\n for (const pkgDir of packages) {\n const packageName = `@happyvertical/${pkgDir}`;\n const manifest = loadExternalManifestSyncWithNode(packageName);\n if (!manifest?.objects) continue;\n seenPackages.add(packageName);\n }\n\n const composite = getDefaultCompositeSource();\n for (const entry of composite.entries()) {\n if (!entry.packageName || !seenPackages.has(entry.packageName)) {\n continue;\n }\n if (!ObjectRegistry.hasClassCaseInsensitive(entry.className)) {\n ObjectRegistry.registerFromManifest(\n entry.className,\n entry.def,\n entry.packageName,\n );\n objectsRegistered++;\n }\n }\n packagesLoaded = seenPackages.size;\n } catch (err) {\n verboseLog(\n `[ObjectRegistry] Auto-discovery of manifests failed: ${err}`,\n );\n }\n }\n\n verboseLog(\n `[ObjectRegistry] loadAllManifests complete: ${packagesLoaded} packages, ${objectsRegistered} objects registered`,\n );\n\n return { packagesLoaded, objectsRegistered };\n }\n\n /**\n * Register a package's own bundled manifest, called by the package itself at\n * import time to eliminate the consumer-runtime field-drop bug (issue #1132).\n *\n * Packages ship a `dist/manifest.json` next to their compiled entry. A small\n * `__smrt-register__.js` side-effect module imports that file URL and calls\n * this method *before* any `@smrt()` decorator in the package fires, so the\n * decorator's synchronous manifest lookup hits a populated cache instead of\n * registering classes with zero fields.\n *\n * Silently no-ops if the URL can't be read — in dev/test the vitest plugin\n * populates manifests through a different path, and this fallback is expected\n * to miss in those contexts.\n *\n * @param manifestUrl - File URL (or string) pointing to the package's\n * manifest.json. Typical call site:\n * `new URL('./manifest.json', import.meta.url)`\n * @returns Summary with loaded status, package name, and object count\n *\n * @example\n * ```typescript\n * // packages/smrt-places/src/__smrt-register__.ts\n * import { ObjectRegistry } from '@happyvertical/smrt-core';\n * ObjectRegistry.registerPackageManifest(\n * new URL('./manifest.json', import.meta.url),\n * );\n * ```\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\n static registerPackageManifest(manifestUrl: string | URL): {\n loaded: boolean;\n packageName?: string;\n objectsRegistered: number;\n } {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return { loaded: false, objectsRegistered: 0 };\n }\n\n let manifest: SmartObjectManifest | null = null;\n try {\n // Decode file URLs via fileURLToPath() rather than `new URL(...).pathname`:\n // pathname leaves percent-encoding intact and on Windows yields paths like\n // `/C:/foo` that fs rejects. Either failure mode would otherwise make\n // self-registration silently no-op and reintroduce #1132.\n const urlString =\n manifestUrl instanceof URL ? manifestUrl.href : manifestUrl;\n let filePath: string;\n if (manifestUrl instanceof URL) {\n filePath = builtins.url.fileURLToPath(manifestUrl);\n } else if (urlString.startsWith('file:')) {\n filePath = builtins.url.fileURLToPath(urlString);\n } else {\n filePath = urlString;\n }\n\n // The `__smrt-register__` shim resolves the manifest via\n // `new URL('./manifest.json', import.meta.url)`, which assumes the\n // compiled side-effect sits directly next to `dist/manifest.json`.\n // Vite chunk-splitting is non-deterministic and sometimes hoists that\n // side-effect into a `dist/chunks/<hash>.js` chunk (observed for\n // smrt-users / smrt-profiles), so the shim's URL resolves to a\n // non-existent `dist/chunks/manifest.json` and self-registration\n // silently no-ops — dropping every plain (undecorated) field from the\n // package's models in consumer runtimes (#1331). When the direct path\n // is missing, walk up a bounded number of parent directories to locate\n // the real `manifest.json`. This keeps resolution deterministic\n // regardless of where the bundler places the shim.\n if (!builtins.fs.existsSync(filePath)) {\n const recovered = resolveManifestByUpwardSearch(builtins, filePath);\n if (!recovered) {\n recordRegistryDiagnostic(\n 'warn',\n 'PACKAGE_MANIFEST_NOT_FOUND',\n `Package manifest not found at ${filePath}. Self-registration is a no-op; the vitest plugin may still populate this manifest via its own path.`,\n { manifestUrl: String(manifestUrl), filePath },\n );\n return { loaded: false, objectsRegistered: 0 };\n }\n filePath = recovered;\n }\n\n const parsed = JSON.parse(\n builtins.fs.readFileSync(filePath, 'utf-8'),\n ) as SmartObjectManifest;\n\n if (!parsed?.objects || typeof parsed.objects !== 'object') {\n recordRegistryDiagnostic(\n 'warn',\n 'PACKAGE_MANIFEST_INVALID_SHAPE',\n `Package manifest at ${String(manifestUrl)} is missing an \"objects\" record`,\n { manifestUrl: String(manifestUrl) },\n );\n return { loaded: false, objectsRegistered: 0 };\n }\n\n manifest = parsed;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n recordRegistryDiagnostic(\n 'error',\n 'PACKAGE_MANIFEST_READ_FAILED',\n `registerPackageManifest: failed to read manifest at ${String(manifestUrl)}: ${errorMessage}`,\n { manifestUrl: String(manifestUrl), errorMessage },\n );\n verboseLog(\n `[ObjectRegistry] registerPackageManifest: failed to read manifest at ${String(manifestUrl)}: ${errorMessage}`,\n );\n return { loaded: false, objectsRegistered: 0 };\n }\n\n const packageName = manifest.packageName;\n\n // Seed the manifest cache so discoverManifestSync() finds entries when\n // @smrt() decorators run for classes in this package.\n const manifestGlobals = globalThis as typeof globalThis & {\n __smrtManifestCache?: Map<string, SmartObjectManifest>;\n };\n if (!manifestGlobals.__smrtManifestCache) {\n manifestGlobals.__smrtManifestCache = new Map();\n }\n const cacheKey = packageName || String(manifestUrl);\n manifestGlobals.__smrtManifestCache.set(cacheKey, manifest);\n\n // Merge manifest fields into any already-registered classes. This covers\n // the case where class modules were evaluated before the package's\n // self-register shim (e.g., a consumer imported a deep subpath that\n // bypassed the main entry).\n let objectsRegistered = 0;\n for (const [key, def] of Object.entries(manifest.objects)) {\n const className = def.className || key;\n ObjectRegistry.registerFromManifest(className, def, packageName);\n objectsRegistered++;\n }\n\n verboseLog(\n `[ObjectRegistry] registerPackageManifest: loaded ${objectsRegistered} objects from ${packageName || String(manifestUrl)}`,\n );\n\n return { loaded: true, packageName, objectsRegistered };\n }\n\n /**\n * Snapshot of diagnostics collected from registry load paths.\n *\n * Registry paths that previously `console.warn(...); return null` also\n * record a structured diagnostic. Apps can inspect this buffer at startup\n * or from an error route to surface failures that would otherwise be silent.\n *\n * Strict mode is **on by default** since Release C (#1134): severity\n * `'error'` diagnostics throw at record time. Set\n * `SMRT_STRICT_REGISTRY=false` to restore the pre-Release-C permissive\n * behavior where only the diagnostic is recorded and nothing throws.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n * @see https://github.com/happyvertical/smrt/issues/1134\n */\n static getDiagnostics(): readonly RegistryDiagnostic[] {\n return getRegistryDiagnostics();\n }\n\n /** Clear the diagnostic buffer. Primarily for tests. */\n static clearDiagnostics(): void {\n clearRegistryDiagnostics();\n }\n\n /**\n * Pretty-print the diagnostic buffer via `console.warn` / `console.error`.\n * No-op when the buffer is empty.\n */\n static flushDiagnostics(): void {\n flushRegistryDiagnostics();\n }\n\n /**\n * Check if a class is registered (case-insensitive)\n */\n static hasClass(name: string): boolean {\n return _hasClass(name);\n }\n\n /**\n * Clear all registered classes (mainly for testing)\n */\n static clear(): void {\n ObjectRegistry.classes.clear();\n ObjectRegistry.collections.clear();\n ObjectRegistry.collectionCache.clear();\n ObjectRegistry.collectionTableNames.clear();\n ObjectRegistry.getInheritanceCache().clear();\n ObjectRegistry.getDiscoveryAttemptCache().clear();\n ObjectRegistry.fieldDecorators.clear();\n ObjectRegistry.stiSiblingsLoaded.clear();\n // Release B (#1133) dropped classNameMap — case-insensitive lookups\n // iterate the classes Map directly, so there's no secondary index to\n // clear here.\n // Note: dbInstanceIds WeakMap and constructorIndex WeakMap will be\n // garbage collected automatically when classes are no longer referenced\n // Reset the counter for clean test state\n ObjectRegistry.nextDbId = 1;\n }\n\n /**\n * Invalidate inheritance cache for a specific class\n *\n * Clears cached inheritance chain and merged fields/methods for the given class.\n * Call this when a class definition changes at runtime (e.g., hot module reload).\n *\n * @param className - The class name to invalidate cache for\n * @example\n * ```typescript\n * // After hot module reload of a parent class\n * ObjectRegistry.invalidateInheritanceCache('BentleyContent');\n * ```\n */\n static invalidateInheritanceCache(className: string): void {\n // Delegate to the stronger sweep in class-registration.ts. The previous\n // implementation here recursed via `childClass.extends === className`\n // — a simple-string exact match — so qualified-extends descendants\n // (e.g. a child whose `extends` is stored as `@pkg:Parent` after\n // `qualifyExtendsName`) were silently missed. The shared sweep checks\n // both `extends === existing.name` and `extends === existing.qualifiedName`,\n // plus transitive descendants via the inheritance-chain cache. See\n // #1139 Gap 1.\n const registered = ObjectRegistry.findClass(className);\n if (!registered) {\n // Class not found: still clear any stray chain-cache entry keyed on\n // this name so a future lookup rebuilds from scratch.\n ObjectRegistry.getInheritanceCache().delete(className);\n return;\n }\n _invalidateInheritanceEntries(registered);\n }\n\n /**\n * Invalidate all inheritance caches\n *\n * Clears all cached inheritance chains and merged fields/methods.\n * Call this when multiple classes change at runtime.\n *\n * @example\n * ```typescript\n * // After hot module reload of multiple classes\n * ObjectRegistry.invalidateAllInheritanceCaches();\n * ```\n */\n static invalidateAllInheritanceCaches(): void {\n ObjectRegistry.getInheritanceCache().clear();\n ObjectRegistry.getDiscoveryAttemptCache().clear();\n\n for (const registered of ObjectRegistry.classes.values()) {\n registered.inheritedFields = undefined;\n registered.inheritedMethods = undefined;\n }\n }\n\n /**\n * Resolve a collection lookup name to the registered object metadata and\n * collection constructor that should back it.\n *\n * Accepts any supported collection identifier:\n * - simple class name (`FactRecord`)\n * - qualified class name (`@pkg:FactRecord`)\n * - explicit collection alias (`fact_records`) when registered\n *\n * Returns a canonical class identity so cache keys remain stable across\n * aliases that refer to the same underlying collection.\n */\n private static resolveCollectionRegistration(className: string): {\n canonicalName: string;\n registered?: RegisteredClass;\n // biome-ignore lint/suspicious/noExplicitAny: concrete collection constructor with contravariant `options` and invariant `ModelType`; mirrors `CollectionConstructor`. S4 #1579.\n collectionConstructor?: new (options: any) => SmrtCollection<any>;\n } {\n let registered = ObjectRegistry.findClass(className);\n let collectionConstructor = registered?.collectionConstructor;\n\n if (!collectionConstructor) {\n collectionConstructor = ObjectRegistry.collections.get(className);\n }\n\n if (!registered && collectionConstructor) {\n const itemClass = (\n collectionConstructor as unknown as {\n _itemClass?: SmrtObjectConstructor;\n }\n )._itemClass;\n if (itemClass) {\n registered =\n ObjectRegistry.getClassByConstructor(itemClass) ||\n ObjectRegistry.findClass(itemClass.name);\n }\n }\n\n const canonicalName =\n registered?.qualifiedName || registered?.name || className;\n\n return {\n canonicalName,\n registered,\n collectionConstructor,\n };\n }\n\n /**\n * Get or create a cached collection instance (Singleton pattern - Phase 4 optimization)\n *\n * Returns a cached collection if one exists for the given class and options,\n * otherwise creates, initializes, and caches a new instance. This significantly\n * improves performance by avoiding repeated collection initialization.\n *\n * **Performance Impact**: 60-80% reduction in collection initialization overhead\n *\n * **Cache Key Strategy**: Collections are cached based on:\n * - className\n * - persistence configuration (type, url, baseUrl)\n * - db presence (not full config)\n * - ai presence (not full config)\n *\n * Different persistence configurations create separate cached instances.\n *\n * @param className - Name of the object class\n * @param options - Configuration options for the collection\n * @returns Cached or newly created collection instance\n * @throws {Error} If the class is not registered or has no collection\n *\n * @example\n * ```typescript\n * // First call creates and caches the collection\n * const orders1 = await ObjectRegistry.getCollection('Order', {\n * persistence: { type: 'sql', url: 'orders.db' }\n * });\n *\n * // Subsequent calls return the cached instance (much faster)\n * const orders2 = await ObjectRegistry.getCollection('Order', {\n * persistence: { type: 'sql', url: 'orders.db' }\n * });\n * console.log(orders1 === orders2); // true (same instance)\n *\n * // Different configuration creates new instance\n * const orders3 = await ObjectRegistry.getCollection('Order', {\n * persistence: { type: 'sql', url: 'orders-copy.db' }\n * });\n * console.log(orders1 === orders3); // false (different config)\n * ```\n *\n * @see {@link https://github.com/happyvertical/sdk/blob/main/packages/core/CLAUDE.md#singleton-collection-management-phase-4|Phase 4 Documentation}\n */\n static async getCollection<T extends SmrtObject>(\n className: string,\n options: SmrtCollectionOptions = {},\n ): Promise<SmrtCollection<T>> {\n let { canonicalName, registered, collectionConstructor } =\n ObjectRegistry.resolveCollectionRegistration(className);\n\n if (!registered && !collectionConstructor) {\n // Try to auto-load from external SMRT packages before throwing error\n // This handles cases where classes from @happyvertical/smrt-* packages\n // are used without explicitly importing them (e.g., Person from smrt-profiles)\n const loaded = await ObjectRegistry.tryLoadFromExternalPackage(className);\n\n if (loaded) {\n ({ canonicalName, registered, collectionConstructor } =\n ObjectRegistry.resolveCollectionRegistration(className));\n }\n\n if (!registered && !collectionConstructor) {\n throw new Error(\n `Class ${className} not found in ObjectRegistry. Make sure to register it with @smrt() decorator or ObjectRegistry.register()`,\n );\n }\n }\n\n // Create a cache key from className and relevant options\n // We use a simplified key that includes only persistence config\n // to avoid cache misses from transient options\n\n // CRITICAL FIX for issue #384: Use unique db instance ID for cache key\n // Without this, different tests with different db instances would share\n // the same cached collection, causing queries to hit the wrong database\n let dbId: number | undefined;\n if (options.db && typeof options.db === 'object') {\n // Get or assign unique ID for this db instance\n if (!ObjectRegistry.dbInstanceIds.has(options.db)) {\n ObjectRegistry.dbInstanceIds.set(options.db, ObjectRegistry.nextDbId++);\n }\n dbId = ObjectRegistry.dbInstanceIds.get(options.db);\n }\n\n const cacheKey = `${canonicalName}:${JSON.stringify({\n persistence: options.persistence,\n db: dbId !== undefined ? `db:${dbId}` : undefined,\n ai: options.ai ? 'present' : undefined,\n })}`;\n\n // Return cached instance if available\n if (ObjectRegistry.collectionCache.has(cacheKey)) {\n return ObjectRegistry.collectionCache.get(cacheKey) as SmrtCollection<T>;\n }\n\n // Auto-create default collection if not registered\n if (!collectionConstructor) {\n if (!registered) {\n throw new Error(\n `Collection ${className} is registered without a backing object class, which is not supported.`,\n );\n }\n\n // Lazy-load SmrtCollection to avoid circular dependency\n const { SmrtCollection: SmrtCollectionClass } = await import(\n './collection'\n );\n\n // Create a default collection class dynamically. The item class is the\n // registered object constructor; it is structurally an\n // `SmrtCollectionItemClass<T>` (a constructor plus the inherited static\n // `create()` factory) but TypeScript can't see that statically, so the\n // backing constructor is narrowed through an `unknown` view.\n const itemConstructor =\n registered.constructor as unknown as SmrtCollectionItemClass<T>;\n class DefaultCollection extends SmrtCollectionClass<T> {\n static readonly _itemClass = itemConstructor;\n }\n\n // Register it for future use. The `collections` map is keyed to the\n // abstract `typeof SmrtCollection`; the concrete generic subclass differs\n // only in its invariant `_itemClass` static, so it is stored through a\n // documented `unknown` view.\n collectionConstructor = DefaultCollection;\n registered.collectionConstructor = DefaultCollection;\n ObjectRegistry.collections.set(\n canonicalName,\n DefaultCollection as unknown as typeof SmrtCollection,\n );\n }\n\n // Create and initialize new collection instance using static factory method.\n // collectionConstructor is guaranteed to be defined here. The constructor\n // carries an inherited static `create()` factory that the constructor-map\n // type does not surface, so it is reached through a documented `unknown`\n // view rather than `any`.\n const collection = (await (\n collectionConstructor as unknown as {\n create(options: SmrtCollectionOptions): Promise<SmrtCollection<T>>;\n }\n ).create(options)) as SmrtCollection<T>;\n\n // Cache the initialized instance\n ObjectRegistry.collectionCache.set(cacheKey, collection);\n\n return collection;\n }\n\n /**\n * Get field definitions for a registered class.\n * Supports both qualified names and simple class names.\n */\n static getFields(name: string): Map<string, RegisteredField> {\n // Issue #951: Use findClass for multi-strategy lookup (qualified key, classNameMap, case-insensitive)\n const registered = ObjectRegistry.findClass(name);\n return registered ? registered.fields : new Map();\n }\n\n /**\n * Get method definitions for a registered class\n *\n * Returns method metadata extracted from the manifest during AST scanning.\n * This enables code generators (CLI, API, MCP) to discover custom methods\n * and automatically generate corresponding commands/endpoints/tools.\n *\n * @param name - Name of the registered class\n * @returns Map of method names to MethodDefinition objects\n * @example\n * ```typescript\n * const methods = ObjectRegistry.getMethods('Agent');\n * for (const [name, methodDef] of methods) {\n * console.log(`Method: ${name}`);\n * console.log(` Async: ${methodDef.async}`);\n * console.log(` Public: ${methodDef.isPublic}`);\n * console.log(` Params: ${methodDef.parameters.map(p => p.name).join(', ')}`);\n * }\n * ```\n */\n static getMethods(name: string): Map<string, MethodDefinition> {\n // Issue #951: Use findClass for multi-strategy lookup (qualified key, classNameMap, case-insensitive)\n const registered = ObjectRegistry.findClass(name);\n if (registered) {\n return registered.methods;\n }\n\n return new Map();\n }\n\n static compileValidators(\n className: string,\n fields: Map<string, RegisteredField>,\n ): ValidatorFunction[] {\n return _compileValidators(className, fields);\n }\n\n /**\n * Ensure manifest is loaded for external package classes\n *\n * For classes from external packages, the manifest may not be loaded during\n * initial registration (which must be synchronous for decorator support).\n * This method loads the manifest asynchronously when needed.\n *\n * @param className - Name of the class to ensure manifest is loaded for\n * @returns Promise that resolves when manifest is loaded (or already loaded)\n * @throws {Error} If manifest cannot be found\n *\n * @example\n * ```typescript\n * // Before using fields from external package\n * await ObjectRegistry.ensureManifestLoaded('Place');\n * const fields = ObjectRegistry.getFields('Place'); // Now has fields\n * ```\n */\n static async ensureManifestLoaded(className: string): Promise<void> {\n let registered = ObjectRegistry.findClass(className);\n if (!registered) {\n const loaded = await ObjectRegistry.tryLoadFromExternalPackage(className);\n if (loaded) {\n registered = ObjectRegistry.findClass(className);\n }\n }\n\n if (!registered) {\n // Detect if running in test environment. `describe`/`it` are injected by\n // the test runner onto the global, so they are read through a documented\n // structural view rather than `any`.\n const testGlobals = globalThis as unknown as {\n describe?: unknown;\n it?: unknown;\n };\n const isTestEnv =\n process.env.NODE_ENV === 'test' ||\n process.env.VITEST === 'true' ||\n typeof testGlobals.describe !== 'undefined' ||\n typeof testGlobals.it !== 'undefined';\n\n const testHint = isTestEnv\n ? `\\n\\n⚠️ Are you using 'smrt test'? ` +\n `Tests require manifest generation.\\n` +\n ` ✅ Use: smrt test\\n` +\n ` ❌ NOT: npx vitest\\n`\n : '';\n\n throw new Error(\n `Class '${className}' is not registered. ` +\n `Ensure the class is decorated with @smrt() before using it.` +\n testHint,\n );\n }\n\n // Try to load manifest from external package (even if some fields exist)\n // This handles cases where AST scanner missed optional fields without initializers\n const existingFieldCount = registered.fields.size;\n\n const { discoverManifestEntry } = await importManifestLoader();\n const manifestEntry = await discoverManifestEntry(\n registered.constructor,\n className,\n );\n\n if (!manifestEntry) {\n // Bundled consumers can register external classes without preserving the\n // package identity we normally use for direct manifest discovery. In\n // that case, fall back to class-name package scans and merge any fields\n // found into the existing registration instead of leaving a sparse entry.\n if (!registered.packageName || !registered.qualifiedName) {\n const loaded =\n await ObjectRegistry.tryLoadFromExternalPackage(className);\n if (loaded) {\n ObjectRegistry.invalidateInheritanceCache(className);\n }\n }\n return;\n }\n\n if (manifestEntry?.fields) {\n const manifestFieldCount = Object.keys(manifestEntry.fields).length;\n let didHydrate = false;\n const needsFieldHydration = Object.entries(manifestEntry.fields).some(\n ([fieldName, fieldDef]) => {\n const existingField = registered.fields.get(fieldName);\n if (!existingField) {\n return true;\n }\n\n return manifestFieldDiffers(existingField, fieldDef);\n },\n );\n const needsMethodHydration =\n !!manifestEntry.methods &&\n Object.entries(manifestEntry.methods).some(\n ([methodName, methodDef]) => {\n return (\n JSON.stringify(registered.methods.get(methodName)) !==\n JSON.stringify(methodDef)\n );\n },\n );\n const needsRegistrationHydration =\n (!!manifestEntry.packageName &&\n registered.packageName !== manifestEntry.packageName) ||\n (!!manifestEntry.extends &&\n registered.extends !== manifestEntry.extends);\n\n if (\n existingFieldCount > 0 &&\n existingFieldCount >= manifestFieldCount &&\n !needsFieldHydration &&\n !needsMethodHydration &&\n !needsRegistrationHydration\n ) {\n return;\n }\n\n // Convert FieldDefinition to Field objects and merge with existing\n for (const [fieldName, fieldDef] of Object.entries(\n manifestEntry.fields,\n )) {\n const existingField = registered.fields.get(fieldName);\n\n if (!existingField) {\n registered.fields.set(fieldName, createFieldFromManifest(fieldDef));\n didHydrate = true;\n continue;\n }\n\n if (manifestFieldDiffers(existingField, fieldDef)) {\n registered.fields.set(\n fieldName,\n mergeManifestField(existingField, fieldDef),\n );\n didHydrate = true;\n }\n }\n\n // Load method definitions from manifest\n if (manifestEntry.methods) {\n for (const [methodName, methodDef] of Object.entries(\n manifestEntry.methods,\n )) {\n registered.methods.set(methodName, methodDef);\n }\n didHydrate = true;\n }\n\n if (manifestEntry.schema) {\n const columns = cloneManifestSchemaColumns(\n manifestEntry.schema.columns,\n );\n applyManifestFieldColumnMetadata(columns, registered.fields.entries());\n\n registered.schema = {\n ddl: manifestEntry.schema.ddl,\n tableName:\n manifestEntry.schema.tableName ||\n registered.schema?.tableName ||\n classnameToTablename(registered.name),\n columns,\n indexes:\n manifestEntry.schema.indexes?.map((indexDef) => ({\n ...indexDef,\n columns: [...(indexDef.columns || [])],\n })) || [],\n triggers: [],\n foreignKeys: [],\n dependencies: [],\n version: manifestEntry.schema.version || '',\n packageName: manifestEntry.packageName,\n baseClass: registered.schema?.baseClass,\n };\n didHydrate = true;\n }\n\n // Extract and store package name from manifest entry (for getPackageName() lookup)\n if (manifestEntry.packageName) {\n registered.packageName = manifestEntry.packageName;\n registered.qualifiedName = createQualifiedName(\n manifestEntry.packageName,\n registered.name,\n ) as QualifiedClassName;\n didHydrate = true;\n }\n\n // Store extends info for getAllFields() to use (if present)\n if (manifestEntry.extends) {\n registered.extends = manifestEntry.extends;\n didHydrate = true;\n }\n\n if (didHydrate) {\n ObjectRegistry.invalidateInheritanceCache(className);\n }\n\n verboseLog(\n `📦 Loaded manifest for external package class: ${className} (${registered.fields.size} fields, ${registered.methods.size} methods)`,\n );\n } else {\n // Manifest not found - throw helpful error\n throw new Error(\n `Cannot find manifest for class '${className}'.\\n\\n` +\n `SMRT classes require a manifest generated at build time by the AST scanner.\\n\\n` +\n `If this is an external package class, verify:\\n` +\n ` 1. Package exports manifest: Check package.json has:\\n` +\n ` \"exports\": { \"./manifest\": \"./dist/manifest.json\" }\\n` +\n ` 2. Package is built: Run npm run build in the package\\n` +\n ` 3. Manifest exists: Confirm dist/manifest.json exists\\n\\n` +\n `See: https://github.com/happyvertical/smrt/issues/131`,\n );\n }\n }\n\n /**\n * Get configuration for a registered class\n */\n static getConfig(name: string): SmartObjectConfig {\n // Issue #951: Use findClass for multi-strategy lookup\n const registered = ObjectRegistry.findClass(name);\n return registered ? registered.config : {};\n }\n\n /**\n * Get cached schema definition for a registered class\n */\n static getSchema(name: string): SchemaDefinition | undefined {\n return _getSchema(name);\n }\n\n /**\n * Get SQL DDL statement for a registered class\n */\n static getSchemaDDL(name: string): string | undefined {\n return _getSchemaDDL(name);\n }\n\n /**\n * Get table name for a registered class\n */\n static getTableName(name: string): string | undefined {\n return _getTableName(name);\n }\n\n /**\n * Get all pre-generated schemas for passing to database adapters\n */\n static getAllSchemas(): Record<\n string,\n { tableName: string; ddl: string; indexes?: string[] }\n > {\n return _getAllSchemas();\n }\n\n /**\n * Get all registered schemas as SchemaDefinition objects\n */\n static getAllSchemasAsDefinitions(): Record<string, SchemaDefinition> {\n return _getAllSchemasAsDefinitions();\n }\n /**\n * Get compiled validation functions for a registered class\n *\n * Returns pre-compiled validation functions that can be executed\n * at runtime for efficient validation without repeated setup.\n *\n * @param name - Name of the registered class\n * @returns Array of validation functions or undefined if not found\n * @example\n * ```typescript\n * const validators = ObjectRegistry.getValidators('Product');\n * for (const validator of validators || []) {\n * const error = await validator(productInstance);\n * if (error) console.error(error);\n * }\n * ```\n */\n static getValidators(name: string): ValidatorFunction[] | undefined {\n // Issue #951: Use findClass for multi-strategy lookup\n const registered = ObjectRegistry.findClass(name);\n return registered?.validators;\n }\n\n /**\n * Get pre-computed validation rules for a registered class\n *\n * Returns serializable validation rules that can be evaluated at runtime\n * without needing pre-compiled validator closures. This significantly\n * reduces CLI startup time for projects with many SMRT objects.\n *\n * @param name - Name of the registered class\n * @returns Array of validation rules or undefined if not found\n * @see https://github.com/happyvertical/smrt/issues/782\n */\n static getValidationRules(name: string): ValidationRule[] | undefined {\n // Issue #951: Use findClass for multi-strategy lookup\n const registered = ObjectRegistry.findClass(name);\n return registered?.validationRules;\n }\n\n /**\n * Validate an instance using pre-computed validation rules\n *\n * This method evaluates validation rules without creating closures,\n * providing faster validation than compiled validator functions.\n *\n * @param instance - The object instance to validate\n * @param rules - Array of validation rules to apply\n * @param className - Name of the class for error messages\n * @returns Array of validation errors (empty if valid)\n * @see https://github.com/happyvertical/smrt/issues/782\n */\n static async validateWithRules(\n instance: object,\n rules: ValidationRule[],\n className: string,\n ): Promise<ValidationError[]> {\n // Import ValidationError lazily to avoid circular dependency at module load\n const { ValidationError } = await import('./errors');\n const errors: ValidationError[] = [];\n // Field values are read by dynamic key; the instance may be a SmrtObject\n // (no string index signature) or a plain record, so it is viewed as a\n // string-keyed record for the lookup.\n const record = instance as Record<string, unknown>;\n\n for (const rule of rules) {\n const value = record[rule.field];\n\n switch (rule.rule) {\n case 'required':\n if (value === null || value === undefined || value === '') {\n errors.push(ValidationError.requiredField(rule.field, className));\n }\n break;\n\n case 'min':\n // Casts mirror the historical loose comparison: the runtime relies on\n // JS abstract relational comparison, so casting only narrows types.\n if (\n value !== null &&\n value !== undefined &&\n (value as number) < (rule.value as number)\n ) {\n errors.push(\n ValidationError.rangeError(\n rule.field,\n value as number,\n rule.value as number,\n undefined,\n ),\n );\n }\n break;\n\n case 'max':\n if (\n value !== null &&\n value !== undefined &&\n (value as number) > (rule.value as number)\n ) {\n errors.push(\n ValidationError.rangeError(\n rule.field,\n value as number,\n undefined,\n rule.value as number,\n ),\n );\n }\n break;\n\n case 'minLength':\n if (\n value &&\n typeof value === 'string' &&\n value.length < (rule.value as number)\n ) {\n errors.push(\n ValidationError.invalidValue(\n rule.field,\n value,\n `string with minimum length ${rule.value}`,\n ),\n );\n }\n break;\n\n case 'maxLength':\n if (\n value &&\n typeof value === 'string' &&\n value.length > (rule.value as number)\n ) {\n errors.push(\n ValidationError.invalidValue(\n rule.field,\n value,\n `string with maximum length ${rule.value}`,\n ),\n );\n }\n break;\n\n case 'pattern':\n // Note: Creates regex on each validation call, trading runtime efficiency\n // for faster startup time (no closure compilation needed)\n if (value && typeof value === 'string') {\n const regex = new RegExp(rule.value as string);\n if (!regex.test(value)) {\n errors.push(\n ValidationError.invalidValue(\n rule.field,\n value,\n `string matching pattern ${rule.value}`,\n ),\n );\n }\n }\n break;\n }\n }\n\n return errors;\n }\n\n /**\n * Build dependency graph from foreignKey relationships\n *\n * Returns a map where keys are class names and values are arrays\n * of class names that the key depends on (via foreignKey fields).\n *\n * @returns Map of class name to array of dependency class names\n * @example\n * ```typescript\n * const deps = ObjectRegistry.getDependencyGraph();\n * // { 'Order': ['Customer', 'Product'], 'Customer': [], 'Product': ['Category'] }\n * ```\n */\n static getDependencyGraph(): Map<string, string[]> {\n return _getDependencyGraph();\n }\n\n /**\n * Get initialization order for classes based on dependency graph\n *\n * Uses topological sort to ensure that classes are initialized in\n * an order that respects foreignKey dependencies (dependencies first).\n *\n * Foreign-key cycles (e.g. smrt-chat's ChatMessage.threadId -> ChatThread\n * and ChatThread.rootMessageId -> ChatMessage) are BROKEN rather than\n * treated as a fatal error: when a back-edge is encountered the recursion\n * stops there, so every class still appears in the returned order. SMRT does\n * not emit real DB `FOREIGN KEY` constraints in its generated CREATE TABLE\n * DDL, so a table can be created before its cyclic reference target exists —\n * the reference is satisfied once both tables are present. This mirrors the\n * standard RDBMS approach (create tables first, wire cyclic references\n * afterward) and matches SchemaManager.sortByDependencies, which already\n * tolerates cycles. See issue #1333.\n *\n * @returns Array of class names in initialization order. Every registered\n * class appears exactly once; cycle back-edges are dropped from the\n * ordering constraints.\n * @example\n * ```typescript\n * const order = ObjectRegistry.getInitializationOrder();\n * // ['Category', 'Product', 'Customer', 'Order']\n * // Tables are created in this order to avoid foreign key errors\n * ```\n */\n static getInitializationOrder(): string[] {\n const graph = ObjectRegistry.getDependencyGraph();\n const visited = new Set<string>();\n const visiting = new Set<string>();\n const order: string[] = [];\n const cycleMembers = new Set<string>();\n\n function visit(className: string): void {\n // Back-edge: this class is already on the current DFS path, so following\n // it would close a foreign-key cycle. Break the cycle by stopping here\n // instead of throwing — the class is created earlier on the path and the\n // cyclic reference resolves once both tables exist (#1333).\n if (visiting.has(className)) {\n cycleMembers.add(className);\n return;\n }\n\n // Already processed\n if (visited.has(className)) {\n return;\n }\n\n visiting.add(className);\n\n // Visit all dependencies first\n const dependencies = graph.get(className) || [];\n for (const dep of dependencies) {\n visit(dep);\n }\n\n visiting.delete(className);\n visited.add(className);\n order.push(className);\n }\n\n // Visit all classes\n for (const className of graph.keys()) {\n if (!visited.has(className)) {\n visit(className);\n }\n }\n\n if (cycleMembers.size > 0) {\n // Informational only — cycles are handled, not fatal. Surfacing the\n // involved classes helps operators understand why strict FK ordering\n // could not be honored for these tables.\n logger.warn(\n `[ObjectRegistry] Foreign-key cycle(s) detected and broken for ordering: ${[\n ...cycleMembers,\n ].join(', ')}. Tables are created without strict cyclic ordering; ` +\n 'SMRT does not emit DB-level FOREIGN KEY constraints, so this is safe.',\n );\n }\n\n return order;\n }\n\n /**\n * Build comprehensive relationship map from all field types\n *\n * Returns a map containing all relationships (foreignKey, oneToMany, manyToMany)\n * discovered in registered classes. This enables runtime relationship traversal\n * and eager/lazy loading of related objects.\n *\n * @returns Map of class name to array of relationship metadata\n * @example\n * ```typescript\n * const relationships = ObjectRegistry.getRelationshipMap();\n * // {\n * // 'Order': [\n * // { sourceClass: 'Order', fieldName: 'customerId', targetClass: 'Customer',\n * // type: 'foreignKey', options: { onDelete: 'restrict' } }\n * // ],\n * // 'Customer': [\n * // { sourceClass: 'Customer', fieldName: 'orders', targetClass: 'Order',\n * // type: 'oneToMany', options: {} }\n * // ]\n * // }\n * ```\n */\n static getRelationshipMap(): Map<string, RelationshipMetadata[]> {\n return _getRelationshipMap();\n }\n\n /**\n * Get relationships for a specific class\n *\n * @param className - Name of the class to get relationships for\n * @returns Array of relationship metadata for the class\n * @example\n * ```typescript\n * const orderRelationships = ObjectRegistry.getRelationships('Order');\n * // [{ sourceClass: 'Order', fieldName: 'customerId', ... }]\n * ```\n */\n static getRelationships(className: string): RelationshipMetadata[] {\n return ObjectRegistry.getRelationshipMap().get(className) || [];\n }\n\n /**\n * Get full inheritance chain for a class\n *\n * Returns array of registered ancestor class names from the oldest\n * registered ancestor down to the input class. Framework base classes\n * (`SmrtObject`, `SmrtClass`, `SmrtCollection`) are **NOT** included\n * because they are never registered — the walk terminates one step\n * before them.\n *\n * Chain entries are **qualified names** (`@package/name:ClassName`)\n * whenever the corresponding registration has one — i.e. for every\n * class loaded via a manifest or `@smrt()` decorator with a package\n * context. Classes registered without a package (some tests) fall\n * back to their simple name.\n *\n * Results are cached globally for performance (~100x faster than re-walking).\n *\n * @param className - Name of the registered class (simple or qualified)\n * @returns Array of class names from oldest registered ancestor to\n * the input class, or empty array if not found\n * @example\n * ```typescript\n * const chain = ObjectRegistry.getInheritanceChain(\n * '@happyvertical/smrt-content:BentleyContent',\n * );\n * // [\n * // '@happyvertical/smrt-content:Content',\n * // '@happyvertical/smrt-content:PraecoContent',\n * // '@happyvertical/smrt-content:BentleyContent',\n * // ]\n * ```\n */\n static getInheritanceChain(className: string): string[] {\n // Delegate to the single source of truth in registry/inheritance-resolver.\n // The inline copy that used to live here drifted from the module (it lacked\n // the SmrtHierarchical `parentId` normalization in field merging), so the\n // duplication was removed (#1378). The module shares the same name-resolver\n // and shared-state helpers this class delegates to, so behavior is\n // identical aside from the drift fix.\n return _getInheritanceChain(className);\n }\n\n /**\n * Get all fields including inherited ones from parent classes\n *\n * **Hybrid approach (v0.17+):**\n * - External packages: Use build-time merged fields from manifests\n * - Local classes: Use runtime merging by walking inheritance chain\n *\n * @param className - Name of the registered class\n * @returns Map of all fields (including inherited)\n */\n static async getAllFields(\n className: string,\n ): Promise<Map<string, RegisteredField>> {\n // Delegate to registry/inheritance-resolver (#1378). The inline copy\n // omitted the SmrtHierarchical `parentId` normalization the module applies,\n // so inherited self-FK fields could surface with the wrong shape. Removing\n // the duplicate keeps field merging consistent everywhere.\n return _getAllFields(className);\n }\n\n /**\n * Merge field configurations from parent and child.\n *\n * Thin wrapper around the single shared implementation in\n * registry/inheritance-resolver (#1378). The previous inline copy here had\n * drifted from the module; both paths now run the same code. Kept as a\n * private static so existing reach-in tests (issue #841 field-merge coverage)\n * still resolve it.\n *\n * @param parentField - Field config from parent class\n * @param childField - Field config from child class\n * @param fieldName - Name of the field (for warning messages)\n * @returns Merged field configuration\n */\n // biome-ignore lint/correctness/noUnusedPrivateClassMembers: reached in by issue #841 field-merge tests via `(ObjectRegistry as any).mergeFieldConfigs`; kept as the registry-side surface delegating to the shared resolver impl.\n private static mergeFieldConfigs(\n parentField: RegisteredField,\n childField: RegisteredField,\n fieldName: string,\n ): RegisteredField {\n return _mergeFieldConfigs(parentField, childField, fieldName);\n }\n\n /**\n * Get all methods including inherited ones from parent classes\n *\n * Walks the full inheritance chain and merges methods:\n * - Parent methods are added first\n * - Child methods override parent methods (no config merging for methods)\n *\n * Results are cached per-class for performance.\n *\n * **Note:** This is an async method that ensures manifests are loaded for external package classes.\n *\n * @param className - Name of the registered class\n * @returns Promise resolving to Map of all methods (own + inherited)\n * @example\n * ```typescript\n * // Given: Content → PraecoContent → BentleyContent\n * const allMethods = await ObjectRegistry.getAllMethods('BentleyContent');\n * // Includes: generateSummary() (from PraecoContent) + analyzeLocal() (from BentleyContent)\n * ```\n */\n static async getAllMethods(\n className: string,\n ): Promise<Map<string, MethodDefinition>> {\n // Delegate to registry/inheritance-resolver (#1378) — single source of\n // truth for inheritance-chain method merging.\n return _getAllMethods(className);\n }\n\n /**\n * Get complete metadata for a single object (convenience method)\n *\n * Returns all available metadata for an object in a single call, including:\n * - Class information\n * - Field definitions\n * - Configuration\n * - Schema definition\n * - Validators\n * - Relationships\n * - Tools (AI-callable methods)\n *\n * This is a convenience method that aggregates multiple registry queries\n * into a single comprehensive metadata object.\n *\n * @param className - Name of the class to get metadata for\n * @returns Complete metadata object or null if class not found\n * @example\n * ```typescript\n * const productMeta = ObjectRegistry.getObjectMetadata('Product');\n * if (productMeta) {\n * console.log('Name:', productMeta.name);\n * console.log('Table:', productMeta.schema.tableName);\n * console.log('Fields:', productMeta.fields.size);\n * console.log('API config:', productMeta.config.api);\n * console.log('Relationships:', productMeta.relationships.length);\n * }\n * ```\n */\n static getObjectMetadata(className: string): ObjectMetadata | null {\n const registered = ObjectRegistry.findClass(className);\n if (!registered) {\n return null;\n }\n\n return {\n name: registered.name,\n constructor: registered.constructor,\n collectionConstructor: registered.collectionConstructor,\n config: registered.config,\n fields: new Map(registered.fields), // Return copy to prevent mutations\n methods: new Map(registered.methods), // Return copy to prevent mutations\n schema: registered.schema,\n validators: registered.validators || [],\n relationships: ObjectRegistry.getRelationships(className),\n inverseRelationships: ObjectRegistry.getInverseRelationships(className),\n tools: registered.tools,\n };\n }\n\n /**\n * Get metadata for all registered objects (convenience method)\n *\n * Returns comprehensive metadata for every registered object, combining\n * multiple registry queries into a single convenient data structure.\n *\n * This is particularly useful for:\n * - Admin dashboards showing all objects\n * - Documentation generation\n * - Schema visualization\n * - Debugging and introspection\n *\n * @returns Array of complete metadata objects for all registered classes\n * @example\n * ```typescript\n * const allMetadata = ObjectRegistry.getAllObjectMetadata();\n *\n * // Generate admin dashboard\n * for (const meta of allMetadata) {\n * console.log(`${meta.name}:`);\n * console.log(` Table: ${meta.schema?.tableName}`);\n * console.log(` Fields: ${meta.fields.size}`);\n * console.log(` API: ${meta.config.api ? 'enabled' : 'disabled'}`);\n * console.log(` Relationships: ${meta.relationships.length}`);\n * }\n *\n * // Generate schema documentation\n * const schemaDoc = allMetadata.map(meta => ({\n * name: meta.name,\n * table: meta.schema?.tableName,\n * fields: Array.from(meta.fields.entries()).map(([name, field]) => ({\n * name,\n * type: field.type,\n * required: field._meta?.required || false\n * })),\n * relationships: meta.relationships.map(rel => ({\n * field: rel.fieldName,\n * target: rel.targetClass,\n * type: rel.type\n * }))\n * }));\n * ```\n */\n static getAllObjectMetadata(): ObjectMetadata[] {\n const allMetadata: ObjectMetadata[] = [];\n\n // Issue #951: Use simple names (map keys may be qualified)\n for (const [_key, entry] of ObjectRegistry.classes) {\n const metadata = ObjectRegistry.getObjectMetadata(entry.name || _key);\n if (metadata) {\n allMetadata.push(metadata);\n }\n }\n\n return allMetadata;\n }\n\n /**\n * Get inverse relationships (relationships where this class is the target)\n *\n * @param className - Name of the class to find inverse relationships for\n * @returns Array of relationship metadata where this class is the target\n * @example\n * ```typescript\n * const customerInverseRels = ObjectRegistry.getInverseRelationships('Customer');\n * // [{ sourceClass: 'Order', fieldName: 'customerId', targetClass: 'Customer', ... }]\n * ```\n */\n static getInverseRelationships(className: string): RelationshipMetadata[] {\n const allRelationships = ObjectRegistry.getRelationshipMap();\n const inverseRelationships: RelationshipMetadata[] = [];\n\n for (const [_sourceClass, relationships] of allRelationships) {\n for (const rel of relationships) {\n if (rel.targetClass === className) {\n inverseRelationships.push(rel);\n }\n }\n }\n\n return inverseRelationships;\n }\n\n /**\n * Names by which an instance of `className` can be referenced by an inverse\n * foreign key: its own (simple) class name plus every registered ancestor in\n * its inheritance chain.\n *\n * Used by oneToMany resolution so an STI subclass can resolve a relationship\n * declared on its base — the inverse `@foreignKey` is declared against the\n * base class name, while the runtime instance may be a subclass.\n *\n * @param className - Simple or qualified class name\n * @returns Set of names (simple and, where available, qualified) the\n * instance is assignable to\n */\n static getSelfReferableNames(className: string): Set<string> {\n const names = new Set<string>([className]);\n for (const ancestor of ObjectRegistry.getInheritanceChain(className)) {\n names.add(ancestor);\n const simple = ObjectRegistry.getClass(ancestor)?.name;\n if (simple) {\n names.add(simple);\n }\n }\n return names;\n }\n\n /**\n * Inverse relationships targeting `className` OR any (STI) ancestor it\n * inherits from.\n *\n * `getInverseRelationships` matches the target class name exactly. This\n * variant also matches inverse foreign keys declared against an ancestor,\n * so an STI subclass instance can resolve a `@oneToMany` declared on its\n * base — whose inverse `@foreignKey` points at the base class name.\n *\n * @param className - Name of the class to find inverse relationships for\n * @returns Relationship metadata whose target is the class or one of its\n * registered ancestors\n */\n static getInverseRelationshipsForSelf(\n className: string,\n ): RelationshipMetadata[] {\n const names = ObjectRegistry.getSelfReferableNames(className);\n const result: RelationshipMetadata[] = [];\n for (const [, relationships] of ObjectRegistry.getRelationshipMap()) {\n for (const rel of relationships) {\n if (names.has(rel.targetClass)) {\n result.push(rel);\n }\n }\n }\n return result;\n }\n\n /**\n * Get table inheritance strategy for a class\n *\n * Returns the table strategy (CTI or STI) for a class, with automatic\n * inheritance from parent classes. If not explicitly configured,\n * walks up the inheritance chain to find the strategy.\n *\n * **Strategy Inheritance:**\n * - Set once on base class, children inherit automatically\n * - Children can explicitly override (not recommended)\n * - Default is 'cti' if not found in hierarchy\n *\n * @param className - Name of the class to get strategy for\n * @returns 'cti' (Class Table Inheritance) or 'sti' (Single Table Inheritance)\n * @example\n * ```typescript\n * @smrt({ tableStrategy: 'sti' })\n * class Event extends SmrtObject { }\n *\n * @smrt() // Inherits 'sti'\n * class Meeting extends Event { }\n *\n * ObjectRegistry.getTableStrategy('Meeting'); // 'sti'\n * ObjectRegistry.getTableStrategy('Event'); // 'sti'\n * ```\n */\n static getTableStrategy(className: string): 'cti' | 'sti' {\n const registered = ObjectRegistry.findClass(className);\n if (!registered) {\n return 'cti'; // Default for unregistered classes\n }\n\n // Explicit config wins\n if (registered.config?.tableStrategy) {\n return registered.config.tableStrategy;\n }\n\n // Inherit from ancestors\n const chain = ObjectRegistry.getInheritanceChain(className);\n for (const ancestorName of chain) {\n const ancestor = ObjectRegistry.findClass(ancestorName);\n if (ancestor?.config?.tableStrategy) {\n return ancestor.config.tableStrategy;\n }\n }\n\n return 'cti'; // Default strategy\n }\n\n /**\n * Get the conflict columns for UPSERT operations on a class\n *\n * Returns custom conflict columns if specified, otherwise defaults based on\n * table strategy:\n * - CTI: ['slug', 'context']\n * - STI: ['slug', 'context', '_meta_type']\n *\n * STI subclasses share a table, so the discriminator participates in\n * identity — two subtypes can coexist with the same (slug, context). The\n * matching unique constraint on `(slug, context, _meta_type)` must exist\n * in the live schema; if a deployment carries a stale 2-column unique\n * instead, run `smrt db:migrate` to repair it (see issue #1165).\n *\n * @param className - Name of the class to get conflict columns for\n * @returns Array of column names to use for conflict detection\n *\n * @example\n * ```typescript\n * // Junction table with custom conflict columns\n * @smrt({ conflictColumns: ['event_id', 'profile_id'] })\n * class EventParticipant extends SmrtObject {}\n *\n * ObjectRegistry.getConflictColumns('EventParticipant');\n * // Returns: ['event_id', 'profile_id']\n * ```\n */\n static getConflictColumns(className: string): string[] {\n const registered = ObjectRegistry.findClass(className);\n if (!registered) {\n return ['slug', 'context']; // Default for unregistered classes\n }\n\n // Explicit config wins\n if (registered.config?.conflictColumns) {\n return registered.config.conflictColumns;\n }\n\n if (registered.config?.report) {\n const tenantField = registered.tenantScopedConfig?.field;\n const tenantColumn =\n tenantField && registered.fields.has(tenantField)\n ? toSnakeCase(tenantField)\n : '';\n const reportConflictColumns = Array.from(registered.fields.entries())\n .filter(([, field]) => {\n const kind = field?._meta?.__report?.kind ?? field?.__report?.kind;\n return kind === 'group' || kind === 'bucket';\n })\n .map(([fieldName]) => toSnakeCase(fieldName));\n\n return reportConflictColumns.length > 0\n ? [...(tenantColumn ? [tenantColumn] : []), ...reportConflictColumns]\n : ['id'];\n }\n\n // Fall back to table strategy-based defaults\n const tableStrategy = ObjectRegistry.getTableStrategy(className);\n return tableStrategy === 'sti'\n ? ['slug', 'context', '_meta_type']\n : ['slug', 'context'];\n }\n\n /**\n * Get the tenant scoping configuration for a class (Issue #688)\n *\n * Returns the normalized tenant scoping configuration if the class\n * was registered with `tenantScoped: true` or a tenantScoped config object.\n *\n * @param className - Name of the class to check\n * @returns Tenant scoping config or undefined if not tenant-scoped\n *\n * @example\n * ```typescript\n * @smrt({ tenantScoped: true })\n * class Document extends SmrtObject { }\n *\n * const config = ObjectRegistry.getTenantScopedConfig('Document');\n * // { mode: 'required', field: 'tenantId', autoFilter: true, autoPopulate: true, allowSuperAdminBypass: false }\n * ```\n */\n static getTenantScopedConfig(\n className: string,\n ): RegisteredClass['tenantScopedConfig'] | undefined {\n const registered = ObjectRegistry.findClass(className);\n return registered?.tenantScopedConfig;\n }\n\n /**\n * Check if a class is tenant-scoped (Issue #688)\n *\n * @param className - Name of the class to check\n * @returns true if the class has tenantScoped configuration\n */\n static isTenantScoped(className: string): boolean {\n return ObjectRegistry.getTenantScopedConfig(className) !== undefined;\n }\n\n /**\n * Get the base class for an STI hierarchy\n *\n * Walks up the inheritance chain to find the first class configured\n * with `tableStrategy: 'sti'`. This is the class that owns the shared table.\n *\n * **Returns:**\n * - The base class's **qualified name** (`@package/name:ClassName`) when\n * the registration has one — same convention as\n * `getInheritanceChain`. Falls back to the simple name only for\n * registrations without a package context (some test classes).\n * - `null` if the class uses CTI strategy.\n *\n * Accepts either a simple or a qualified name on input.\n *\n * @param className - Name of the class to find STI base for\n * @returns Qualified base class name or null if CTI\n * @example\n * ```typescript\n * @smrt({ tableStrategy: 'sti' })\n * class Event extends SmrtObject { }\n *\n * @smrt()\n * class Meeting extends Event { }\n *\n * ObjectRegistry.getSTIBase('@happyvertical/smrt-events:Meeting');\n * // '@happyvertical/smrt-events:Event'\n * ObjectRegistry.getSTIBase('@happyvertical/smrt-events:Event');\n * // '@happyvertical/smrt-events:Event'\n * ```\n */\n static getSTIBase(className: string): string | null {\n const strategy = ObjectRegistry.getTableStrategy(className);\n if (strategy === 'cti') {\n return null; // Not using STI\n }\n\n // Find the OLDEST/ROOT class in the chain with explicit tableStrategy: 'sti'\n // (Issue #703 fix: don't rely on tableName matching)\n //\n // In multi-level STI hierarchies (e.g., Council → Organization → Profile),\n // we need to return the oldest ancestor (Profile), not the first one found (Organization)\n //\n // IMPORTANT: Don't rely on tableName matching because:\n // 1. STI subclasses loaded from external manifests may have tableName: null\n // 2. registerFromManifest() derives a tableName from class name when null\n // 3. This causes tableName mismatch ('meetings' vs 'events')\n // 4. Instead, find the oldest ancestor with EXPLICIT tableStrategy: 'sti'\n //\n // R5-canon: chain entries are qualified names (when the class has a\n // package context), so the returned STI base is also qualified —\n // ambiguity across packages with same-simple-name STI roots is gone.\n const chain = ObjectRegistry.getInheritanceChain(className);\n\n // Walk the chain (ordered [root, ..., className]) to find oldest STI base\n for (const ancestorName of chain) {\n const ancestor = ObjectRegistry.findClass(ancestorName);\n if (!ancestor) continue;\n\n // Check if this ancestor EXPLICITLY declares tableStrategy: 'sti'\n // (not inherited via getTableStrategy(), but set directly in config)\n if (ancestor.config?.tableStrategy === 'sti') {\n // Found the OLDEST ancestor with explicit STI - this is the base\n // All descendants inherit from this table regardless of their tableName\n return ancestor.qualifiedName ?? ancestor.name;\n }\n }\n\n // If no explicit STI ancestor found but we detected STI strategy,\n // this class is its own STI base (it must have declared tableStrategy: 'sti').\n // Return its qualified name when available.\n const self = ObjectRegistry.findClass(className);\n return self?.qualifiedName ?? self?.name ?? className;\n }\n\n /**\n * Get all descendant classes of a base class\n *\n * Returns all registered classes that inherit from the specified base class.\n * Uses the `extends` field from manifest to build the descendant tree.\n *\n * **Use cases:**\n * - Schema generation: Aggregate fields from all children for STI table\n * - Polymorphic queries: Find all types to instantiate\n * - Documentation: Show class hierarchy\n *\n * Accepts either a simple or a qualified name on input. The returned\n * descendant names are **qualified** (`@package/name:ClassName`) when\n * the registration has one — same convention as `getInheritanceChain`\n * and `getSTIBase`.\n *\n * @param className - Name of the base class (simple or qualified)\n * @returns Array of qualified descendant class names (direct and indirect)\n * @example\n * ```typescript\n * @smrt({ tableStrategy: 'sti' })\n * class Event extends SmrtObject { }\n *\n * @smrt()\n * class Meeting extends Event { }\n *\n * @smrt()\n * class HockeyGame extends Event { }\n *\n * ObjectRegistry.getDescendants('@happyvertical/smrt-events:Event');\n * // [\n * // '@happyvertical/smrt-events:Meeting',\n * // '@happyvertical/smrt-events:HockeyGame',\n * // ]\n * ```\n */\n static getDescendants(className: string): string[] {\n const descendants: string[] = [];\n // main: dedup by RegisteredClass identity so a class registered under\n // multiple map keys (simple + qualified) is only emitted once.\n const seenRegistrations = new Set<RegisteredClass>();\n\n // R5-canon: inheritance chains are emitted with qualified names when\n // available, so the comparison against `className` must accept either\n // a qualified or simple input from the caller. Resolve once up-front\n // to whichever form actually appears in the chain.\n const target = ObjectRegistry.findClass(className);\n const targetKey = target?.qualifiedName ?? target?.name ?? className;\n\n // Find all classes that extend the given class\n for (const [_key, childClass] of ObjectRegistry.classes) {\n // main: skip classes already visited under another map key so the same\n // descendant isn't pushed twice (simple + qualified registrations point\n // at the same RegisteredClass object).\n if (seenRegistrations.has(childClass)) {\n continue;\n }\n seenRegistrations.add(childClass);\n\n // R5-canon: compare and emit qualified-when-available names so the\n // chain membership test (the chain holds qualified names) and the\n // returned descendants stay unambiguous across packages.\n const childKey = childClass.qualifiedName ?? childClass.name ?? _key;\n if (childKey === targetKey) continue;\n\n const chain = ObjectRegistry.getInheritanceChain(childKey);\n if (chain.includes(targetKey)) {\n descendants.push(childKey);\n }\n }\n\n return descendants;\n }\n\n /**\n * Persist registry state to system tables\n *\n * Saves all registered class metadata to the _smrt_registry system table\n * for runtime introspection and debugging. This enables applications to\n * query what SMRT objects exist and their configurations.\n *\n * @param db - Database interface to persist to\n * @returns Promise that resolves when persistence is complete\n * @example\n * ```typescript\n * // After registering all classes\n * await ObjectRegistry.persistToDatabase(db);\n *\n * // Later, query the system table\n * const rows = await db.all('SELECT * FROM _smrt_registry');\n * console.log('Registered classes:', rows.map(r => r.class_name));\n * ```\n */\n static async persistToDatabase(\n db: import('@happyvertical/sql').DatabaseInterface,\n ): Promise<void> {\n for (const [className, registered] of ObjectRegistry.classes.entries()) {\n const fieldsData: Record<string, { type: unknown; options: unknown }> =\n {};\n for (const [key, value] of registered.fields) {\n fieldsData[key] = {\n type: value.type,\n options: value.options,\n };\n }\n\n // Use upsert() for database-agnostic INSERT OR REPLACE\n // SQLite: INSERT OR REPLACE\n // Postgres/DuckDB: INSERT ... ON CONFLICT ... DO UPDATE\n await db.upsert(\n '_smrt_registry',\n ['class_name'], // PRIMARY KEY for conflict detection\n {\n class_name: className,\n schema_version: '1.0.0', // Could be derived from package version\n fields: JSON.stringify(fieldsData),\n relationships: JSON.stringify(\n ObjectRegistry.getRelationships(className),\n ),\n config: JSON.stringify(registered.config),\n manifest: JSON.stringify({\n name: registered.name,\n tableName: registered.schema?.tableName,\n tools: registered.tools,\n }),\n last_updated: new Date(),\n },\n );\n }\n }\n\n /**\n * Load registry metadata from system tables\n *\n * Reads the _smrt_registry system table to inspect what classes\n * have been registered. This is primarily for introspection and\n * debugging - actual class registration happens via @smrt() decorator.\n *\n * @param db - Database interface to load from\n * @returns Promise resolving to array of class metadata\n * @example\n * ```typescript\n * const metadata = await ObjectRegistry.loadFromDatabase(db);\n * for (const meta of metadata) {\n * console.log(`Class: ${meta.class_name}`);\n * console.log(`Table: ${JSON.parse(meta.manifest).tableName}`);\n * }\n * ```\n */\n static async loadFromDatabase(\n db: import('@happyvertical/sql').DatabaseInterface,\n ): Promise<Record<string, unknown>[]> {\n const { rows } = await db.query(\n 'SELECT * FROM _smrt_registry ORDER BY class_name',\n );\n return rows;\n }\n\n // ============================================================================\n // Embedding Configuration Methods\n // ============================================================================\n\n /**\n * Get embedding configuration for a class\n *\n * Returns the class-specific embedding config if embeddings are enabled.\n * This includes the fields to embed, provider override, and generation options.\n *\n * @param className - Name of the class to get embedding config for\n * @returns Class embedding config or undefined if not configured\n * @example\n * ```typescript\n * @smrt({\n * embeddings: {\n * fields: ['title', 'body'],\n * autoGenerate: true\n * }\n * })\n * class Article extends SmrtObject { }\n *\n * const config = ObjectRegistry.getEmbeddingConfig('Article');\n * // { fields: ['title', 'body'], autoGenerate: true }\n * ```\n */\n static getEmbeddingConfig(\n className: string,\n ): ClassEmbeddingConfig | undefined {\n return _getEmbeddingConfig(className);\n }\n\n /**\n * Check if a class has embeddings enabled\n *\n * @param className - Name of the class to check\n * @returns True if the class has embedding configuration\n * @example\n * ```typescript\n * if (ObjectRegistry.hasEmbeddings('Article')) {\n * await article.generateEmbeddings();\n * }\n * ```\n */\n static hasEmbeddings(className: string): boolean {\n return _hasEmbeddings(className);\n }\n\n /**\n * Get all registered classes that have embeddings enabled\n *\n * @returns Array of class names with embedding configuration\n * @example\n * ```typescript\n * const embeddableClasses = ObjectRegistry.getEmbeddingClasses();\n * // ['Article', 'Profile', 'Event']\n * ```\n */\n static getEmbeddingClasses(): string[] {\n return _getEmbeddingClasses();\n }\n\n /**\n * Get project-level embedding configuration\n *\n * Returns the global embedding settings from smrt.config (or defaults).\n * These settings apply to all classes unless overridden at the class level.\n *\n * @returns Project embedding configuration with defaults applied\n * @example\n * ```typescript\n * const projectConfig = ObjectRegistry.getProjectEmbeddingConfig();\n * // {\n * // dimensions: 768,\n * // provider: 'local',\n * // localModel: 'Xenova/bge-base-en-v1.5',\n * // aiModel: 'text-embedding-3-small',\n * // fallbackToAI: false\n * // }\n * ```\n */\n static getProjectEmbeddingConfig(): ProjectEmbeddingConfig {\n return _getProjectEmbeddingConfig();\n }\n\n /**\n * Resolve complete embedding configuration for a class\n *\n * Merges project-level config with class-level overrides.\n * Returns undefined if the class doesn't have embeddings enabled.\n *\n * @param className - Name of the class to resolve config for\n * @returns Fully resolved embedding config or undefined\n * @example\n * ```typescript\n * const config = ObjectRegistry.resolveEmbeddingConfig('Article');\n * // Merges project defaults with class-specific settings\n * // {\n * // fields: ['title', 'body'],\n * // dimensions: 768,\n * // provider: 'local',\n * // localModel: 'Xenova/bge-base-en-v1.5',\n * // autoGenerate: true,\n * // regenerateOnChange: true,\n * // ...\n * // }\n * ```\n */\n static resolveEmbeddingConfig(\n className: string,\n ): ResolvedEmbeddingConfig | undefined {\n return _resolveEmbeddingConfig(className);\n }\n\n /**\n * Resolve the effective collection read-cache config for a class (issue #1498)\n *\n * Walks the inheritance chain nearest-first so an STI base class opt-in\n * covers its children, while a child can opt back out with `cache: false`.\n *\n * @param className - Simple or qualified class name\n * @returns Effective cache config, or undefined when caching is not opted in\n */\n static resolveCollectionCacheConfig(\n className: string,\n ): CollectionCacheConfig | undefined {\n return _resolveCollectionCacheConfig(className);\n }\n}\n\n/**\n * Registers a `SmrtObject` or `SmrtCollection` subclass with the global `ObjectRegistry`.\n *\n * This decorator is the primary entry point for the SMRT framework. Applying it to a class:\n *\n * 1. Captures the original class name before minification and stores it as the\n * `SMRT_TABLE_NAME` static property — ensuring table names are stable in production builds.\n * 2. Registers class metadata (fields, schema, config) in the singleton `ObjectRegistry`.\n * 3. Enables automatic code generation: REST API endpoints (`api`), CLI commands (`cli`),\n * and MCP server tools (`mcp`) are generated at build time from the registered config.\n * 4. Activates lifecycle hooks (`hooks.beforeSave`, `hooks.afterDelete`, etc.).\n * 5. Configures AI-callable methods exposed to `is()` / `do()` via function calling (`ai`).\n * 6. Enables automatic vector embedding generation (`embeddings`).\n *\n * Apply to `SmrtCollection` subclasses as well — the decorator uses `_itemClass` to\n * register the collection under the correct table name and creates a collection-to-table\n * lookup used by the CLI and introspection tools.\n *\n * For Single Table Inheritance (STI), set `tableStrategy: 'sti'` on the base class only.\n * Child classes inherit the strategy automatically.\n *\n * @param config - Optional configuration for the class. All fields are optional; defaults\n * are derived from the class name and framework conventions.\n * @returns A class decorator that registers the class and returns the original constructor\n *\n * @example\n * ```typescript\n * // Basic usage — convention-based defaults\n * @smrt()\n * class Product extends SmrtObject {\n * @field({ required: true })\n * name: string = '';\n * price: number = 0.0; // 0.0 → DECIMAL column\n * }\n *\n * // Paired collection (required for collection.create())\n * @smrt()\n * class Products extends SmrtCollection<Product> {\n * static readonly _itemClass = Product;\n * }\n *\n * // STI base class\n * @smrt({ tableStrategy: 'sti' })\n * class Content extends SmrtObject {\n * title: string = '';\n * }\n *\n * // STI child — inherits strategy, adds @meta() fields stored in _meta_data JSON\n * @smrt()\n * class Article extends Content {\n * @meta() wordCount: number = 0;\n * }\n *\n * // Restrict generated API surface\n * @smrt({ api: { exclude: ['delete'] }, mcp: true, cli: false })\n * class Invoice extends SmrtObject {}\n *\n * // Junction/upsert table with natural key\n * @smrt({ conflictColumns: ['event_id', 'profile_id'] })\n * class EventParticipant extends SmrtObject {\n * eventId: string = '';\n * profileId: string = '';\n * }\n * ```\n *\n * @see {@link SmartObjectConfig} for all available configuration options\n * @see {@link field} / {@link meta} / {@link foreignKey} for field decorators\n */\nexport function smrt(config: SmartObjectConfig = {}) {\n // The `(...args: any[])` spread is the idiomatic class-decorator constraint\n // (every class constructor — including ones with specific parameter lists —\n // must satisfy it), so it is left as-is. Only the instance/return type is\n // narrowed from `any` to `object`.\n // biome-ignore lint/suspicious/noExplicitAny: `(...args: any[])` is the idiomatic class-decorator constraint — every class constructor (incl. specific param lists) must satisfy it; `unknown[]`/`never[]` would reject concrete ctors. S4 #1579.\n return <T extends abstract new (...args: any[]) => object>(\n ctor: T,\n decoratorContext?: ClassDecoratorContext<T>,\n ): T => {\n applyPendingDecoratorRegistrations(ctor, decoratorContext);\n\n // Check if this is a SmrtCollection class\n const isCollection = ctor.prototype instanceof SmrtCollection;\n\n if (isCollection) {\n // Handle SmrtCollection registration. `_itemClass` is the paired model\n // constructor declared statically on the collection subclass; it is read\n // through a documented `unknown` view since the decorator's generic\n // constructor type does not surface it.\n const itemClass = (ctor as unknown as { _itemClass?: typeof SmrtObject })\n ._itemClass;\n if (itemClass) {\n // Register the item class (SmrtObject) with metadata\n // For STI: Check if this class uses STI and get the base class's table name\n let tableName = config.tableName;\n\n if (!tableName) {\n // Check if this class or any parent uses STI.\n // R5-canon: resolve the item class to its qualified\n // registration first, then pass that qualified key to\n // `getSTIBase` / `getTableStrategy` so a colliding simple\n // name in another package can't yield the wrong base.\n // Falls back to the simple name when no registration exists\n // yet. Feeding a qualified string straight into\n // `classnameToTablename` would yield a garbled identifier —\n // route through the registered class's actual `schema.tableName`\n // when present.\n const itemClassName = itemClass.name;\n const itemReg = ObjectRegistry.getClassByConstructor(itemClass);\n const itemQualified = itemReg?.qualifiedName ?? itemClassName;\n const stiBase = ObjectRegistry.getSTIBase(itemQualified);\n\n if (stiBase && stiBase !== itemQualified) {\n // Use STI base's table name\n const baseReg = ObjectRegistry.getClass(stiBase);\n tableName =\n baseReg?.schema?.tableName ??\n classnameToTablename(baseReg?.name ?? stiBase);\n } else if (ObjectRegistry.getTableStrategy(itemQualified) === 'sti') {\n // This is the STI base - use its own table name\n tableName = classnameToTablename(itemClassName);\n } else {\n // CTI: Use own table name\n tableName = classnameToTablename(itemClassName);\n }\n }\n\n ObjectRegistry.register(itemClass, { ...config, tableName });\n\n const registeredItemClass = ObjectRegistry.getClass(itemClass.name);\n\n // Register the collection constructor under the item class identity first.\n // This ensures ObjectRegistry.getCollection('ItemClass') uses the explicit\n // collection subclass rather than falling back to a generated default.\n // The decorator target is typed as an abstract constructor; coerce it\n // through `unknown` to the concrete collection-constructor shape the\n // registry stores.\n const collectionCtor = ctor as unknown as CollectionConstructor;\n ObjectRegistry.registerCollection(itemClass.name, collectionCtor);\n if (registeredItemClass?.qualifiedName) {\n ObjectRegistry.registerCollection(\n registeredItemClass.qualifiedName,\n collectionCtor,\n );\n }\n\n // Also register the collection constructor using tableName.\n // This preserves existing CLI/introspection lookups by table name\n // (e.g., \"meetings\") and keeps backward compatibility.\n ObjectRegistry.registerCollection(tableName, collectionCtor);\n\n // Store collection class name -> tableName mapping for getTableName lookups\n // This enables ObjectRegistry.getTableName('CollectionClassName') to work\n ObjectRegistry.setCollectionTableName(ctor.name, tableName);\n }\n } else {\n // Handle SmrtObject registration (existing behavior)\n let tableName = config.tableName;\n\n if (!tableName) {\n // First, check manifest for tableName (manifest generator correctly handles STI inheritance)\n // This handles the case where a child class sets tableStrategy: 'sti' explicitly\n // but should still inherit the parent's table name\n const manifestEntry = discoverCachedManifestSync(ctor.name);\n if (manifestEntry?.decoratorConfig?.tableName) {\n tableName = manifestEntry.decoratorConfig.tableName;\n } else if (config.tableStrategy === 'sti') {\n // Fallback: Runtime prototype chain walking for STI detection\n // This is used when:\n // 1. Class is dynamically registered (not in manifest)\n // 2. Development mode without a build\n // 3. Test scenarios without manifest generation\n // Note: This relies on parents being registered first, which is why\n // the manifest check above is preferred (it has correct build-time data).\n //\n // R5-canon: `getSTIBase` now returns the qualified name. We\n // resolve back to the registered class and prefer its actual\n // `schema.tableName` when present; otherwise fall back to the\n // simple-name-derived table name. Deriving directly from a\n // qualified string would produce a garbled identifier.\n let proto = Object.getPrototypeOf(ctor);\n let stiBaseName: string | null = null;\n\n while (proto?.name && proto.name !== 'SmrtObject') {\n // R5-canon: walk via constructor identity (qualified name\n // from registration) rather than `proto.name`, so a\n // colliding simple name in another package can't yield the\n // wrong STI base. Falls through to simple `proto.name` for\n // unregistered prototypes.\n const protoReg = ObjectRegistry.getClassByConstructor(\n proto as SmrtObjectConstructor,\n );\n const protoKey = protoReg?.qualifiedName ?? proto.name;\n if (ObjectRegistry.getTableStrategy(protoKey) === 'sti') {\n stiBaseName = ObjectRegistry.getSTIBase(protoKey);\n break;\n }\n proto = Object.getPrototypeOf(proto);\n }\n\n if (stiBaseName) {\n // This is an STI child - use parent's table name. Resolve the\n // qualified stiBaseName to its registration to pick the\n // correct table identifier.\n const baseReg = ObjectRegistry.getClass(stiBaseName);\n tableName =\n baseReg?.schema?.tableName ??\n classnameToTablename(baseReg?.name ?? stiBaseName);\n } else {\n // This is the actual STI base - use its own table name\n tableName = classnameToTablename(ctor.name);\n }\n } else {\n // Fallback: Check if any parent uses STI (implicit STI inheritance)\n // Same caveats as above - used only when manifest data unavailable.\n let proto = Object.getPrototypeOf(ctor);\n let stiBaseName: string | null = null;\n\n while (proto?.name && proto.name !== 'SmrtObject') {\n // Use getTableStrategy() to properly detect inherited STI strategy.\n // R5-canon: walk via constructor identity (qualified name\n // from registration) rather than `proto.name`, so a\n // colliding simple name in another package can't yield the\n // wrong STI base. Falls through to simple `proto.name` for\n // unregistered prototypes. Mirrors the sibling branch above.\n const protoReg = ObjectRegistry.getClassByConstructor(\n proto as SmrtObjectConstructor,\n );\n const protoKey = protoReg?.qualifiedName ?? proto.name;\n if (ObjectRegistry.getTableStrategy(protoKey) === 'sti') {\n // Get the actual STI base (may be higher up the chain)\n stiBaseName = ObjectRegistry.getSTIBase(protoKey);\n break;\n }\n proto = Object.getPrototypeOf(proto);\n }\n\n if (stiBaseName) {\n // Use STI base's table name. (R5-canon: see above — qualified\n // stiBaseName resolves to its registration's tableName.)\n const baseReg = ObjectRegistry.getClass(stiBaseName);\n tableName =\n baseReg?.schema?.tableName ??\n classnameToTablename(baseReg?.name ?? stiBaseName);\n } else {\n // CTI: Use own table name\n tableName = classnameToTablename(ctor.name);\n }\n }\n }\n\n // The decorator target is typed as an abstract constructor; coerce it\n // through `unknown` to the concrete `SmrtObject` constructor `register`\n // expects.\n ObjectRegistry.register(ctor as unknown as typeof SmrtObject, {\n ...config,\n tableName,\n });\n\n // R10: install a consistent `getX()` child accessor for every\n // `@oneToMany` field, delegating to `loadRelatedMany`. Runs after\n // registration so the relationship metadata is populated. Additive —\n // never overrides a hand-rolled accessor of the same name. The decorator\n // target's abstract constructor type does not surface `.prototype`\n // structurally, so it is passed through a documented prototype view.\n applyOneToManyChildAccessors(\n ctor as unknown as { prototype?: unknown },\n ObjectRegistry.getRelationships(ctor.name),\n );\n }\n\n return ctor;\n };\n}\n"],"names":["_getCanonicalClassName","_hasClassCaseInsensitive","_register","_registerCollection","_registerFromManifest","_findClass","_getClass","_getClassByConstructor","_getClassByQualifiedName","_getClassInPackage","_findClassesByName","_resolveType","_getClassesByPackage","_getClassesByVisibility","_getPublicClasses","_getAllClasses","_getClassNames","_getQualifiedClassNames","packageName","manifest","objectDef","_hasClass","_invalidateInheritanceEntries","_compileValidators","_getSchema","_getSchemaDDL","_getTableName","_getAllSchemas","_getAllSchemasAsDefinitions","_getDependencyGraph","_getRelationshipMap","_getInheritanceChain","_getAllFields","_mergeFieldConfigs","_getAllMethods","_getEmbeddingConfig","_hasEmbeddings","_getEmbeddingClasses","_getProjectEmbeddingConfig","_resolveEmbeddingConfig","_resolveCollectionCacheConfig"],"mappings":"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"}