@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":"manifest-loader.js","sources":["../../src/manifest/manifest-loader.ts"],"sourcesContent":["/**\n * Manifest Loader - Automatic discovery of external package manifests\n *\n * This module provides automatic loading of SMRT manifests from external packages,\n * solving issue #131 where external package schemas weren't being detected.\n *\n * Architecture:\n * - Build-time: AST scanner generates manifests in dist/manifest.json\n * - Run-time: This module discovers and loads those manifests automatically\n * - Caching: Loaded manifests are cached to avoid repeated imports\n *\n * Flow:\n * 1. Check testManifest (for test classes)\n * 2. Check staticManifest (for core framework classes)\n * 3. Resolve external package manifests from explicit JSON exports\n * 4. Return manifest entry or undefined\n *\n * External manifest loading intentionally follows a pure-ESM JSON contract.\n * Packages are expected to publish a JSON manifest via \"./manifest\" and/or\n * \"./manifest.json\" exports. Runtime discovery does not guess sibling workspace\n * paths or load JavaScript manifest modules.\n */\n\nimport { existsSync, readdirSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { createLogger } from '@happyvertical/logger';\nimport type { SmrtObjectConstructor } from '../registry/types.js';\nimport { ObjectRegistry } from '../registry.js';\nimport type {\n FieldDefinition,\n MethodDefinition,\n SmartObjectDefinition,\n SmartObjectManifest,\n} from '../scanner/types.js';\nimport { parse } from '../utils/json.js';\nimport {\n createQualifiedName,\n isQualifiedName,\n parseQualifiedName,\n} from '../utils/qualified-names.js';\nimport { ManifestManager } from './manager.js';\nimport { getDefaultCompositeSource } from './sources/composite.js';\nimport {\n getLocalTestManifestCache as getLocalTestManifestCacheFromStore,\n getManifestCache as getManifestCacheFromStore,\n getStaticManifestCache as getStaticManifestCacheFromStore,\n getTestManifestCache as getTestManifestCacheFromStore,\n isTestEnvironment as isTestEnvFromStore,\n shouldLoadCoreTestManifest,\n} from './store.js';\n\n/**\n * Extend globalThis to include manifest loader state.\n * Using globalThis ensures all module instances share the same manifest caches,\n * which is critical in monorepos where the same package can be loaded\n * from different paths (e.g., pnpm store vs workspace symlink).\n *\n * @see https://github.com/happyvertical/smrt/issues/543\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtManifestStatic: SmartObjectManifest | null | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestStaticLoadAttempted: boolean | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestTest: SmartObjectManifest | null | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestTestLoadAttempted: boolean | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestCache: Map<string, SmartObjectManifest> | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestLocalTest: SmartObjectManifest | null | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestCollisions:\n | Map<\n string,\n Array<{\n packageName: string;\n filePath?: string;\n manifestSource: string;\n }>\n >\n | undefined;\n // eslint-disable-next-line no-var\n var __smrtSTISiblingCache:\n | Map<\n string,\n Array<{ className: string; entry: ManifestEntry; packageName?: string }>\n >\n | undefined;\n}\n\n// Use globalThis for cross-module state sharing\n// This ensures loadConfig() in one module instance affects all packages\n\n// ── Cache access (delegates to manifest/store.ts — the single source of\n// truth added in Release B #1133 for globalThis manifest state).\n// manifest-loader.ts keeps its own setters + load-attempted flags below\n// because those are internal to this module's async loader state machine;\n// the read-only getters just forward to store.ts to eliminate drift.\n\nconst getStaticManifestCache = getStaticManifestCacheFromStore;\nconst getTestManifestCache = getTestManifestCacheFromStore;\nconst getLocalTestManifestCache = getLocalTestManifestCacheFromStore;\nconst getManifestCacheMap = getManifestCacheFromStore;\n\nfunction setStaticManifestCache(\n manifest: SmartObjectManifest | null | undefined,\n): void {\n globalThis.__smrtManifestStatic = manifest;\n}\n\nfunction getStaticManifestLoadAttempted(): boolean {\n return globalThis.__smrtManifestStaticLoadAttempted ?? false;\n}\n\nfunction setStaticManifestLoadAttempted(value: boolean): void {\n globalThis.__smrtManifestStaticLoadAttempted = value;\n}\n\nfunction setTestManifestCache(\n manifest: SmartObjectManifest | null | undefined,\n): void {\n globalThis.__smrtManifestTest = manifest;\n}\n\nfunction getTestManifestLoadAttempted(): boolean {\n return globalThis.__smrtManifestTestLoadAttempted ?? false;\n}\n\nfunction setTestManifestLoadAttempted(value: boolean): void {\n globalThis.__smrtManifestTestLoadAttempted = value;\n}\n\nfunction setLocalTestManifestCache(\n manifest: SmartObjectManifest | null | undefined,\n): void {\n globalThis.__smrtManifestLocalTest = manifest;\n}\n\n/**\n * Get the manifest collisions Map from globalThis\n */\nfunction getManifestCollisionsMap(): Map<\n string,\n Array<{ packageName: string; filePath?: string; manifestSource: string }>\n> {\n if (!globalThis.__smrtManifestCollisions) {\n globalThis.__smrtManifestCollisions = new Map();\n }\n return globalThis.__smrtManifestCollisions;\n}\n\n/**\n * Get the STI sibling cache Map from globalThis\n * Caches discoverSTISiblingsSync results per collection to avoid repeated scans\n */\nfunction getSTISiblingCache(): Map<\n string,\n Array<{ className: string; entry: ManifestEntry; packageName?: string }>\n> {\n if (!globalThis.__smrtSTISiblingCache) {\n globalThis.__smrtSTISiblingCache = new Map();\n }\n return globalThis.__smrtSTISiblingCache;\n}\n\n// Create require function once for reuse\nconst require = createRequire(import.meta.url);\n\n/**\n * Cached debug flag evaluated once at module load time.\n * Environment variables don't change at runtime, so this is safe.\n * @see https://github.com/happyvertical/smrt/issues/729\n */\nconst DEBUG_ENABLED =\n process.env.DEBUG_MANIFEST === 'true' ||\n process.env.DEBUG_MANIFEST === '1' ||\n process.env.DEBUG?.includes('manifest') ||\n false;\n\n// The debug traces below are gated by DEBUG_MANIFEST / DEBUG_TEST_ENV, so the\n// logger level must allow debug when either is set (a fixed 'info' would filter\n// them out and silently break those debug switches).\nconst logger = createLogger({\n level: DEBUG_ENABLED || process.env.DEBUG_TEST_ENV ? 'debug' : 'info',\n});\n\n/**\n * Log a debug message only if DEBUG_MANIFEST is enabled.\n * Uses cached boolean check instead of repeated env var access.\n */\nfunction debugLog(message: string): void {\n if (DEBUG_ENABLED) {\n logger.debug(message);\n }\n}\n\n/**\n * Cache for className-to-entry index per manifest.\n * This enables O(1) lookup by className instead of O(n) iteration.\n * @see https://github.com/happyvertical/smrt/issues/729\n */\nconst classNameIndexCache = new WeakMap<\n SmartObjectManifest,\n Map<string, SmartObjectDefinition>\n>();\n\n/**\n * Get or build the className index for a manifest.\n * Index maps lowercase className to entry for O(1) lookup.\n */\nfunction getClassNameIndex(\n manifest: SmartObjectManifest,\n): Map<string, SmartObjectDefinition> {\n let index = classNameIndexCache.get(manifest);\n if (!index) {\n index = new Map<string, SmartObjectDefinition>();\n for (const [key, entry] of Object.entries(manifest.objects)) {\n const name = (entry.className || key).toLowerCase();\n if (!index.has(name)) {\n index.set(name, entry);\n } else {\n const existing = index.get(name)!;\n const existingName = (existing.className || '').toLowerCase();\n const newExtends = (entry.extends || '').toLowerCase();\n const existingExtends = (existing.extends || '').toLowerCase();\n\n // Issue #950: STI child-wins — if new entry extends existing, replace\n if (\n newExtends &&\n (newExtends === existingName || newExtends === name)\n ) {\n index.set(name, entry);\n debugLog(\n `Manifest className '${name}': child '${key}' replaces parent`,\n );\n } else if (\n existingExtends &&\n (existingExtends === (entry.className || key).toLowerCase() ||\n existingExtends === name)\n ) {\n // Existing is already the child, keep it\n debugLog(\n `Manifest className '${name}': keeping child, ignoring parent '${key}'`,\n );\n } else {\n debugLog(\n `Manifest className collision for '${name}': keeping first, ignoring key '${key}'`,\n );\n }\n }\n }\n classNameIndexCache.set(manifest, index);\n }\n return index;\n}\n\n/**\n * Test-environment detection with optional DEBUG_TEST_ENV logging.\n *\n * Delegates to the single source of truth in `store.ts` so the\n * ManifestSource implementations (which also gate on test-env) cannot\n * drift from the legacy sync loader. The logging wrapper stays here\n * because the trace is specific to this module's loader state machine.\n */\nfunction isTestEnvironment(): boolean {\n const result = isTestEnvFromStore();\n\n if (process.env.DEBUG_TEST_ENV) {\n logger.debug('[manifest-loader] isTestEnvironment check', {\n NODE_ENV: process.env.NODE_ENV,\n VITEST: process.env.VITEST,\n JEST_WORKER_ID: process.env.JEST_WORKER_ID,\n result,\n });\n }\n\n return result;\n}\n\nfunction getStaticManifest(): SmartObjectManifest {\n if (!getStaticManifestLoadAttempted()) {\n setStaticManifestLoadAttempted(true);\n try {\n // Try to import the generated static manifest\n const imported = require('./static-manifest.js');\n setStaticManifestCache(imported.staticManifest || imported.default);\n } catch {\n // Fallback to empty manifest if file doesn't exist yet (during build)\n setStaticManifestCache({\n version: '1.0.0',\n timestamp: Date.now(),\n objects: {},\n packageName: '@happyvertical/smrt-core',\n });\n }\n }\n return getStaticManifestCache()!;\n}\n\n/**\n * Lazy-load smrt-core's internal test manifest only for smrt-core's own tests.\n * Consumer packages should never see these fixtures, or they can collide with\n * real external classes during downstream test runs.\n */\nfunction getTestManifest(): SmartObjectManifest | null {\n if (!getTestManifestLoadAttempted()) {\n setTestManifestLoadAttempted(true);\n\n // CRITICAL: Scope the core test manifest to smrt-core's own test suite.\n if (!shouldLoadCoreTestManifest()) {\n if (process.env.DEBUG_TEST_ENV) {\n logger.debug(\n '[manifest-loader] ⚠️ Skipping core test manifest load (not smrt-core test environment)',\n );\n }\n setTestManifestCache(null);\n return null;\n }\n\n try {\n // Dynamically import test manifest to avoid loading in production\n const imported = require('./test-manifest-stub.js');\n const manifest = imported.testManifest || imported.default;\n setTestManifestCache(manifest);\n if (process.env.DEBUG_TEST_ENV) {\n logger.debug(\n `[manifest-loader] ✅ Loaded test manifest (${Object.keys(manifest?.objects || {}).length} objects)`,\n );\n }\n } catch (error) {\n if (process.env.DEBUG_TEST_ENV) {\n logger.debug(\n '[manifest-loader] ⚠️ Test manifest not found (this is normal in production)',\n );\n }\n setTestManifestCache(null);\n }\n }\n return getTestManifestCache();\n}\n\n// Re-export types for convenience\nexport type Manifest = SmartObjectManifest;\nexport type ManifestEntry = SmartObjectDefinition;\nexport type { FieldDefinition, MethodDefinition };\n\n// Note: manifestCache and localTestManifest are now accessed via globalThis helper functions\n// getManifestCacheMap() and getLocalTestManifestCache()/setLocalTestManifestCache()\n\n/**\n * Load local test manifest from current package (synchronous)\n *\n * During test runs, packages can have manifests in two locations:\n * 1. src/manifest/test-manifest.json - Domain packages during development\n * 2. dist/manifest.json - Built packages (consuming apps like praeco)\n *\n * This function attempts to load the manifest from either location.\n *\n * @returns Loaded manifest or null if not found or undefined if not yet attempted\n */\nexport function loadLocalTestManifestSync(): Manifest | null | undefined {\n // Only return cached manifest if it was successfully loaded\n // Don't cache null (failed loads) - allow retries\n const cached = getLocalTestManifestCache();\n if (cached !== undefined && cached !== null) {\n return cached;\n }\n\n // Use ManifestManager for unified local loading\n // This checks: .smrt/manifest.json -> dist/manifest.json\n const manager = new ManifestManager(process.cwd());\n const manifest = manager.loadLocal();\n\n // Fallback location: src/manifest/test-manifest.json\n // This is still used by smrt-core and other packages that generate test manifests here\n const testManifestPath = join(\n process.cwd(),\n 'src/manifest/test-manifest.json',\n );\n\n // If ManifestManager found a manifest, check if it has objects\n // If it has 0 objects but the fallback exists with objects, use the fallback instead\n // This handles the case where dist/manifest.json is the static-manifest.json (0 objects)\n // but src/manifest/test-manifest.json has the real test classes\n if (manifest) {\n const objectCount = Object.keys(manifest.objects).length;\n\n // If manifest has objects, use it\n if (objectCount > 0) {\n setLocalTestManifestCache(manifest);\n debugLog(\n `[manifest-loader] ✅ Loaded local manifest via ManifestManager (${objectCount} objects)`,\n );\n return manifest;\n }\n\n // Manifest has 0 objects - check if fallback has more\n if (existsSync(testManifestPath)) {\n try {\n const testManifest: Manifest = parse(\n readFileSync(testManifestPath, 'utf-8'),\n );\n const testObjectCount = Object.keys(testManifest.objects).length;\n\n if (testObjectCount > 0) {\n setLocalTestManifestCache(testManifest);\n debugLog(\n `[manifest-loader] ✅ Loaded test manifest from ${testManifestPath} (${testObjectCount} objects) - preferred over empty ManifestManager result`,\n );\n return testManifest;\n }\n } catch {\n // Fallback also failed, use the empty manifest\n }\n }\n\n // No better option, cache and use the empty manifest\n setLocalTestManifestCache(manifest);\n debugLog(\n `[manifest-loader] ✅ Loaded local manifest via ManifestManager (${objectCount} objects)`,\n );\n return manifest;\n }\n\n // ManifestManager returned null - check fallback\n if (existsSync(testManifestPath)) {\n try {\n const testManifest: Manifest = parse(\n readFileSync(testManifestPath, 'utf-8'),\n );\n setLocalTestManifestCache(testManifest);\n const objectCount = Object.keys(testManifest.objects).length;\n debugLog(\n `[manifest-loader] ✅ Loaded test manifest from ${testManifestPath} (${objectCount} objects)`,\n );\n return testManifest;\n } catch (error) {\n debugLog(\n `[manifest-loader] ✗ Failed to load test manifest from ${testManifestPath}: ${error instanceof Error ? error.message : 'unknown'}`,\n );\n }\n }\n\n // No manifest found - DON'T cache null, allow retries\n // This is important because the manifest may be generated later\n debugLog(\n '[manifest-loader] ⚠️ No local manifest found (will retry on next call)',\n );\n return null;\n}\n\n/**\n * Extract package name from class constructor\n *\n * Uses the ObjectRegistry (preferred) or fallback methods to determine\n * which package the class belongs to.\n *\n * Search order:\n * 1. ObjectRegistry (packageName injected at build time from manifest) - SKIPPED during initial registration\n * 2. __package__ metadata (build tooling can inject this)\n * 3. require.resolve() (resolves package.json from constructor file location)\n * 4. Error stack trace parsing (fallback, fragile in pnpm workspaces)\n *\n * @param ctor - Class constructor\n * @param skipRegistry - If true, skip checking ObjectRegistry (used during initial registration to avoid circular dependency)\n * @returns Package name (e.g., '@happyvertical/smrt-places') or null\n */\nexport function getPackageName(\n ctor: SmrtObjectConstructor,\n skipRegistry: boolean = false,\n): string | null {\n try {\n // 1. Try ObjectRegistry first (most reliable - from build-time manifest)\n // This solves issue #143 where pnpm workspace symlinks break stack trace parsing\n // CRITICAL: Skip during initial registration to avoid circular dependency (issue #159)\n if (!skipRegistry) {\n const className = ctor.name;\n if (className) {\n const registered = ObjectRegistry.getClass(className);\n if (registered?.packageName) {\n return registered.packageName;\n }\n }\n }\n\n // 2. Check if class has __package__ metadata (could be added by build tooling)\n const packageMeta = (ctor as { __package__?: string }).__package__;\n if (packageMeta) {\n return packageMeta;\n }\n\n // 3. Try require.resolve() to find package.json from constructor location\n // This is more reliable than stack trace parsing for published packages\n try {\n const error = new Error();\n const stack = error.stack || '';\n const stackLines = stack.split('\\n');\n\n // Find the first line with a file path that's NOT from smrt-core\n // Skip manifest-loader, registry, and other smrt-core files\n for (const line of stackLines) {\n const fileMatch = line.match(/\\(([^)]+\\.(?:js|ts))/);\n if (fileMatch) {\n const filePath = fileMatch[1];\n // Skip smrt-core internal files\n if (\n filePath.includes('manifest-loader') ||\n filePath.includes('registry') ||\n filePath.includes('/smrt-core/dist/')\n ) {\n continue; // Skip smrt-core files, look for external package\n }\n\n // Try to resolve package.json from this file\n try {\n // Handle file:// URLs\n const cleanPath = filePath.replace(/^file:\\/\\//, '');\n let dir = dirname(cleanPath);\n // Walk up until we find a package.json\n for (let i = 0; i < 10; i++) {\n const pkgPath = join(dir, 'package.json');\n try {\n if (existsSync(pkgPath)) {\n const pkg = parse<{ name?: string }>(\n readFileSync(pkgPath, 'utf-8'),\n );\n if (pkg.name?.startsWith('@')) {\n return pkg.name;\n }\n }\n } catch {\n // Keep walking up\n }\n const parent = dirname(dir);\n if (parent === dir) break; // Reached root\n dir = parent;\n }\n } catch {\n // Fall through to next method\n }\n break;\n }\n }\n } catch {\n // Fall through to next method\n }\n\n // 4. Final fallback: Try to extract from Error stack trace with node_modules pattern\n // This method is fragile and fails in pnpm workspaces, but kept for backward compatibility\n const error = new Error();\n const stack = error.stack || '';\n const stackLines = stack.split('\\n');\n\n // Look for line with 'node_modules/@scope/package' pattern\n for (const line of stackLines) {\n const match = line.match(/node_modules\\/(@[^/]+\\/[^/]+)/);\n if (match) {\n return match[1];\n }\n }\n\n // Package name is now injected at build time into the manifest and stored in ObjectRegistry\n // If we reach here, the class is likely not from an external package\n return null;\n } catch {\n return null;\n }\n}\n\ninterface ManifestExportConditions {\n default?: string;\n import?: string;\n require?: string;\n}\n\ninterface ExternalPackageJson {\n exports?: Record<string, string | ManifestExportConditions>;\n}\n\nfunction findWorkspaceRoot(startDir: string): string | null {\n let currentDir = startDir;\n\n while (true) {\n if (existsSync(join(currentDir, 'pnpm-workspace.yaml'))) {\n return currentDir;\n }\n\n const parentDir = dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n}\n\nfunction resolveInstalledPackageJsonPath(packageName: string): string | null {\n let currentDir = process.cwd();\n\n while (true) {\n const packageJsonPath = join(\n currentDir,\n 'node_modules',\n packageName,\n 'package.json',\n );\n\n if (existsSync(packageJsonPath)) {\n return packageJsonPath;\n }\n\n const parentDir = dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n}\n\nfunction resolveWorkspacePackageJsonPath(packageName: string): string | null {\n const workspaceRoot = findWorkspaceRoot(process.cwd());\n if (!workspaceRoot) {\n return null;\n }\n\n const workspacePackagesDir = join(workspaceRoot, 'packages');\n if (!existsSync(workspacePackagesDir)) {\n return null;\n }\n\n for (const packageDirName of readdirSync(workspacePackagesDir)) {\n const packageJsonPath = join(\n workspacePackagesDir,\n packageDirName,\n 'package.json',\n );\n if (!existsSync(packageJsonPath)) {\n continue;\n }\n\n try {\n const packageJson = parse<{ name?: string }>(\n readFileSync(packageJsonPath, 'utf-8'),\n );\n if (packageJson.name === packageName) {\n return packageJsonPath;\n }\n } catch {\n // Ignore unreadable workspace package metadata and continue scanning.\n }\n }\n\n return null;\n}\n\nfunction resolveWorkspaceSourceManifestPath(packageDir: string): string | null {\n const candidates = [\n join(packageDir, 'src', 'manifest', 'manifest.json'),\n join(packageDir, '.smrt', 'manifest.json'),\n ];\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\ninterface ManifestLoadOptions {\n warn?: boolean;\n}\n\nfunction resolveManifestExportPath(\n packageName: string,\n options: ManifestLoadOptions = {},\n): string | null {\n const shouldWarn = options.warn ?? true;\n const packageJsonPath =\n resolveInstalledPackageJsonPath(packageName) ||\n resolveWorkspacePackageJsonPath(packageName);\n\n if (!packageJsonPath) {\n return null;\n }\n\n const packageDir = dirname(packageJsonPath);\n const packageJson = parse<ExternalPackageJson>(\n readFileSync(packageJsonPath, 'utf-8'),\n );\n const manifestExports = ['./manifest.json', './manifest'];\n\n for (const exportKey of manifestExports) {\n const manifestExport = packageJson.exports?.[exportKey];\n if (!manifestExport) {\n continue;\n }\n\n const manifestRelativePath =\n typeof manifestExport === 'string'\n ? manifestExport\n : manifestExport.import ||\n manifestExport.default ||\n manifestExport.require;\n\n if (!manifestRelativePath) {\n if (shouldWarn) {\n logger.warn(\n `Package ${packageName} has invalid manifest export configuration for ${exportKey}`,\n );\n }\n return null;\n }\n\n if (!manifestRelativePath.endsWith('.json')) {\n if (shouldWarn) {\n logger.warn(\n `Package ${packageName} must export a JSON manifest for ${exportKey}, received ${manifestRelativePath}`,\n );\n }\n return null;\n }\n\n const manifestPath = join(packageDir, manifestRelativePath);\n if (existsSync(manifestPath)) {\n return manifestPath;\n }\n\n const workspaceSourceManifest =\n resolveWorkspaceSourceManifestPath(packageDir);\n if (workspaceSourceManifest) {\n return workspaceSourceManifest;\n }\n\n if (shouldWarn) {\n logger.warn(\n `Package ${packageName} declares manifest export ${manifestRelativePath}, but no manifest file was found.`,\n );\n }\n return null;\n }\n\n return null;\n}\n\nfunction collectDeclaredSmrtDependencies(\n manifests: Array<Manifest | null | undefined>,\n): string[] {\n const dependencies = new Set<string>();\n\n for (const manifest of manifests) {\n for (const pkg of manifest?.smrtDependencies || []) {\n dependencies.add(pkg);\n }\n }\n\n return Array.from(dependencies);\n}\n\n/**\n * Load manifest from external package\n *\n * Uses createRequire from process.cwd() to resolve packages from the calling\n * application's context, not from smrt-core's context. This allows finding\n * packages that are dependencies of the app but not of smrt-core.\n *\n * External packages export manifests via package.json:\n * \"exports\": { \"./manifest\": \"./dist/manifest.json\" }\n *\n * @param packageName - Package name (e.g., '@happyvertical/smrt-places')\n * @returns Manifest object or null if not found\n */\n/**\n * Load external package manifest synchronously\n * This is the synchronous version of loadExternalManifest for use during class registration\n */\nexport function loadExternalManifestSync(\n packageName: string,\n options: ManifestLoadOptions = {},\n): Manifest | null {\n // Check cache first\n if (getManifestCacheMap().has(packageName)) {\n debugLog(`[manifest-loader] Using cached manifest for ${packageName}`);\n return getManifestCacheMap().get(packageName)!;\n }\n\n debugLog(\n `[manifest-loader] Attempting to load external manifest for ${packageName}`,\n );\n\n const manifestPath = resolveManifestExportPath(packageName, options);\n\n if (!manifestPath) {\n debugLog(\n `[manifest-loader] Package ${packageName} does not expose a JSON manifest export`,\n );\n return null;\n }\n\n try {\n const manifest = parse<Manifest>(readFileSync(manifestPath, 'utf-8'));\n\n if (!manifest.objects || typeof manifest.objects !== 'object') {\n if (options.warn ?? true) {\n logger.warn(`Invalid manifest structure for package ${packageName}`);\n }\n return null;\n }\n\n const cachedManifest = manifest.packageName\n ? manifest\n : { ...manifest, packageName };\n\n getManifestCacheMap().set(packageName, cachedManifest);\n debugLog(\n `[manifest-loader] ✅ Loaded external manifest for ${packageName} (${Object.keys(cachedManifest.objects).length} objects)`,\n );\n\n return cachedManifest;\n } catch (error) {\n if (options.warn ?? true) {\n logger.warn(\n `Failed to load manifest for package ${packageName}: ${error instanceof Error ? error.message : error}`,\n );\n }\n return null;\n }\n}\n\nexport async function loadExternalManifest(\n packageName: string,\n options: ManifestLoadOptions = {},\n): Promise<Manifest | null> {\n // Delegate to synchronous version since all operations are sync anyway\n return loadExternalManifestSync(packageName, options);\n}\n\n/**\n * Load a manifest directly from a known file path and cache it by package name.\n *\n * This is used by workspace/dev flows where sibling packages may not be\n * installed into node_modules yet, but their generated manifests are still\n * available on disk.\n */\nexport function loadManifestFromPathSync(\n manifestPath: string,\n): Manifest | null {\n try {\n const manifestJson = readFileSync(manifestPath, 'utf-8');\n const manifest: Manifest = parse(manifestJson);\n\n if (!manifest.objects || typeof manifest.objects !== 'object') {\n logger.warn(`Invalid manifest structure at ${manifestPath}`);\n return null;\n }\n\n const cacheKey = manifest.packageName || manifestPath;\n getManifestCacheMap().set(cacheKey, manifest);\n debugLog(\n `[manifest-loader] ✅ Loaded manifest from path ${manifestPath} (${Object.keys(manifest.objects).length} objects)`,\n );\n\n return manifest;\n } catch (error) {\n logger.warn(\n `Failed to load manifest from path ${manifestPath}: ${error instanceof Error ? error.message : error}`,\n );\n return null;\n }\n}\n\n/**\n * Discover manifest entry synchronously (checks only loaded manifests)\n *\n * Search order:\n * 1. localTestManifest (for domain package test classes)\n * 2. testManifest (for core test classes)\n * 3. staticManifest (for core framework classes)\n * 4. Cached external manifests\n *\n * @param className - Class name (for lookup)\n * @returns ManifestEntry or undefined if not found\n */\nexport function discoverManifestSync(\n className: string,\n): ManifestEntry | undefined {\n debugLog(`[manifest-loader] discoverManifestSync called for: ${className}`);\n\n // Ensure test-env caches are seeded before the composite queries them.\n // Historically, steps 1-2 of discoverManifestSync did this inline. The\n // composite's TestManifestSource and LocalTestManifestSource read directly\n // from cache state — without this seeding the first sync lookup in a\n // clean test process would miss core test classes on their first access\n // (regression noted in #1138 review).\n if (isTestEnvironment()) {\n if (!getLocalTestManifestCache()) {\n loadLocalTestManifestSync();\n }\n if (!getTestManifestCache()) {\n getTestManifest();\n }\n }\n\n // Carry qualified-name / package context into the composite lookup so\n // multi-package same-simple-name scenarios (issue #951) resolve to the\n // right manifest even via the sync path.\n const query = isQualifiedName(className)\n ? (() => {\n const parsed = parseQualifiedName(className);\n return {\n className: parsed.className,\n packageName: parsed.packageName,\n qualifiedName: className,\n };\n })()\n : { className };\n\n // Steps 1-4 (local-test → test → static → embedded cache) now live in\n // CompositeManifestSource at the exact same priority order.\n const compositeHit = getDefaultCompositeSource().lookup(query);\n if (compositeHit) {\n debugLog(\n `[manifest-loader] ✅ Found ${className} via ${compositeHit.source} source`,\n );\n const entry = compositeHit.def;\n if (!entry.packageName && compositeHit.packageName) {\n return { ...entry, packageName: compositeHit.packageName };\n }\n return entry;\n }\n\n // 5. Try loading from explicitly declared external SMRT package dependencies.\n debugLog(\n `[manifest-loader] ${className} not found in cached manifests, trying external packages...`,\n );\n\n const pendingPackages = collectDeclaredSmrtDependencies([\n getLocalTestManifestCache(),\n isTestEnvironment() ? getTestManifest() : null,\n getStaticManifest(),\n ...getManifestCacheMap().values(),\n ]);\n\n if (pendingPackages.length === 0) {\n debugLog(\n '[manifest-loader] No SMRT dependencies discovered. Run manifest generation if external packages are expected.',\n );\n }\n\n const visitedPackages = new Set<string>();\n\n while (pendingPackages.length > 0) {\n const pkg = pendingPackages.shift();\n if (!pkg || visitedPackages.has(pkg)) {\n continue;\n }\n\n visitedPackages.add(pkg);\n const manifest = loadExternalManifestSync(pkg);\n if (!manifest) {\n continue;\n }\n\n for (const dependency of manifest.smrtDependencies || []) {\n if (!visitedPackages.has(dependency)) {\n pendingPackages.push(dependency);\n }\n }\n\n // Use lookupInManifest for qualified name support (Issue #713)\n const entry = lookupInManifest(manifest, className);\n if (entry) {\n debugLog(\n `[manifest-loader] ✅ Found ${className} in external package ${pkg}`,\n );\n // Enrich entry with packageName from manifest if not already present\n if (!entry.packageName && manifest.packageName) {\n return { ...entry, packageName: manifest.packageName };\n }\n return entry;\n }\n }\n\n debugLog(`[manifest-loader] ❌ ${className} not found in any manifest`);\n return undefined;\n}\n\n// Note: manifestCollisions is now accessed via globalThis helper function\n// getManifestCollisionsMap()\n\n/**\n * Look up a manifest entry in a manifest's objects map.\n * Supports both qualified names and simple class names.\n *\n * Lookup order:\n * 1. Direct qualified name lookup (e.g., \"@happyvertical/smrt-core:Product\")\n * 2. Constructed qualified name (packageName + className)\n * 3. Search by className property (case-insensitive)\n *\n * @param manifest - The manifest to search in\n * @param nameOrQualified - Either a qualified name or simple class name\n * @returns ManifestEntry or undefined if not found\n */\nexport function lookupInManifest(\n manifest: SmartObjectManifest,\n nameOrQualified: string,\n): ManifestEntry | undefined {\n // 1. First try direct lookup (handles both qualified names and exact matches)\n if (manifest.objects[nameOrQualified]) {\n return manifest.objects[nameOrQualified];\n }\n\n // 2. Get the className index for O(1) lookups (instead of O(n) iteration)\n // This is the key optimization for issue #729\n const classNameIndex = getClassNameIndex(manifest);\n\n // 3. If input is a qualified name, extract className and use index\n if (isQualifiedName(nameOrQualified)) {\n const { className } = parseQualifiedName(nameOrQualified);\n return classNameIndex.get(className.toLowerCase());\n }\n\n // 4. For simple class names, try constructing qualified name if manifest has packageName\n if (manifest.packageName) {\n const qualifiedKey = createQualifiedName(\n manifest.packageName,\n nameOrQualified,\n );\n if (manifest.objects[qualifiedKey]) {\n return manifest.objects[qualifiedKey];\n }\n }\n\n // 5. Use index for O(1) className lookup (instead of O(n) iteration)\n return classNameIndex.get(nameOrQualified.toLowerCase());\n}\n\n/**\n * Find a manifest entry by qualified name across all loaded manifests.\n *\n * @param qualifiedName - The fully qualified class name (e.g., \"@happyvertical/smrt-core:Product\")\n * @returns ManifestEntry or undefined if not found\n */\nexport function findManifestEntryByQualifiedName(\n qualifiedName: string,\n): ManifestEntry | undefined {\n if (!isQualifiedName(qualifiedName)) {\n return undefined;\n }\n\n const { packageName } = parseQualifiedName(qualifiedName);\n\n // Check if we have the package's manifest cached\n const manifest = getManifestCacheMap().get(packageName);\n if (manifest) {\n // Try qualified name first, then fallback to simple names\n return lookupInManifest(manifest, qualifiedName);\n }\n\n // Check static manifest\n const staticManifestData = getStaticManifest();\n if (staticManifestData.packageName === packageName) {\n return lookupInManifest(staticManifestData, qualifiedName);\n }\n\n // Check test manifest (if in test environment)\n if (isTestEnvironment()) {\n const testManifest = getTestManifest();\n if (testManifest?.packageName === packageName) {\n return lookupInManifest(testManifest, qualifiedName);\n }\n\n // Check local test manifest\n const localTest = getLocalTestManifestCache();\n if (localTest?.packageName === packageName) {\n return lookupInManifest(localTest, qualifiedName);\n }\n }\n\n return undefined;\n}\n\n/**\n * Discover manifest entry asynchronously (includes external package loading)\n *\n * Search order:\n * 1. External package manifest (for constructor's package) - PRIORITIZED\n * 2. testManifest (for test classes)\n * 3. staticManifest (for core framework classes)\n * 4. Cached external manifests\n *\n * This function now detects and reports class name collisions across packages.\n *\n * @param ctor - Class constructor\n * @param className - Class name (for lookup)\n * @returns ManifestEntry or undefined if not found\n * @throws {Error} If class name collision detected across different packages\n */\nexport async function discoverManifestEntry(\n ctor: SmrtObjectConstructor,\n className: string,\n): Promise<ManifestEntry | undefined> {\n // ✅ FAST PATH: O(1) constructor-based lookup for already-registered classes\n // Skip manifest scanning if we already know this constructor's qualified name via WeakMap\n // This provides instant resolution and prevents collisions (each constructor is unique in memory)\n if (!(ctor as { _isManifestStub?: boolean })._isManifestStub) {\n const registered = ObjectRegistry.getClassByConstructor(ctor);\n if (\n registered?.qualifiedName &&\n isQualifiedName(registered.qualifiedName)\n ) {\n // Parse package name from qualified name (format: \"@package/name:ClassName\")\n const { packageName } = parseQualifiedName(registered.qualifiedName);\n\n const cachedManifest = getManifestCacheMap().get(packageName);\n if (cachedManifest) {\n const cachedEntry = lookupInManifest(\n cachedManifest,\n registered.qualifiedName,\n );\n if (cachedEntry) {\n return !cachedEntry.packageName && cachedManifest.packageName\n ? { ...cachedEntry, packageName: cachedManifest.packageName }\n : cachedEntry;\n }\n }\n\n // Load the manifest for this specific package before trusting any\n // existing runtime field metadata. Imported external classes can be\n // registered with only a partial field set until their manifest is\n // hydrated, which is exactly what happens with STI parents like Event.\n const manifest = await loadExternalManifest(packageName, {\n warn: registered.fields.size === 0,\n });\n if (manifest) {\n // Look up the entry using the qualified name (exact match)\n const entry = lookupInManifest(manifest, registered.qualifiedName);\n if (entry) {\n // Enrich entry with package name if missing\n return !entry.packageName && manifest.packageName\n ? { ...entry, packageName: manifest.packageName }\n : entry;\n }\n }\n\n // Source-registered classes with explicit field metadata do not need a\n // second manifest probe from fallback discovery when the package did not\n // resolve to a manifest. This keeps workspace/dev runtimes from spamming\n // missing-dist-manifest warnings for packages that are already fully\n // usable from source.\n if (registered.fields.size > 0) {\n return undefined;\n }\n }\n }\n\n // FALLBACK: Original manifest scanning logic for:\n // - First-time registration (WeakMap not populated yet)\n // - Manifest stubs (not in WeakMap)\n // - Undecorated classes (never registered)\n const name = className.toLowerCase();\n const constructorPackage = getPackageName(ctor);\n\n // Track all manifest sources that define this class\n const foundEntries: Array<{\n entry: ManifestEntry;\n packageName: string;\n filePath?: string;\n manifestSource: string;\n }> = [];\n\n // Build qualified name for lookup if we have package context\n const qualifiedName = constructorPackage\n ? createQualifiedName(constructorPackage, className)\n : undefined;\n\n // 2. Check localTestManifest first (domain package test classes) - ONLY in test environment\n // Do this BEFORE loading external manifest to avoid duplicate loading\n let localEntry: SmartObjectDefinition | undefined;\n if (isTestEnvironment()) {\n if (getLocalTestManifestCache() === undefined) {\n loadLocalTestManifestSync();\n }\n const localManifest = getLocalTestManifestCache();\n if (localManifest) {\n // Use lookupInManifest for consistent qualified name handling\n localEntry = lookupInManifest(localManifest, qualifiedName || className);\n if (localEntry) {\n foundEntries.push({\n entry: localEntry,\n packageName: localManifest.packageName || 'local-test',\n filePath: localEntry.filePath,\n manifestSource: 'local test manifest',\n });\n }\n }\n }\n\n // 1. PRIORITY: Try loading from the constructor's package first\n // BUT skip if it's the same package as the local test manifest to avoid collisions\n if (constructorPackage) {\n const skipExternal =\n getLocalTestManifestCache()?.packageName &&\n constructorPackage === getLocalTestManifestCache()?.packageName;\n\n if (!skipExternal) {\n const manifest = await loadExternalManifest(constructorPackage);\n if (manifest) {\n // Use lookupInManifest for consistent qualified name handling\n const entry = lookupInManifest(manifest, qualifiedName || className);\n if (entry) {\n const enrichedEntry =\n !entry.packageName && manifest.packageName\n ? { ...entry, packageName: manifest.packageName }\n : entry;\n\n foundEntries.push({\n entry: enrichedEntry,\n packageName: manifest.packageName || constructorPackage,\n filePath: entry.filePath,\n manifestSource: `${manifest.packageName || constructorPackage}/manifest.json`,\n });\n }\n }\n }\n }\n\n // 3. Check testManifest (core test classes) - ONLY in test environment\n // Skip if we already loaded a local test manifest (avoids duplicate entries from same package)\n if (isTestEnvironment() && (!getLocalTestManifestCache() || !localEntry)) {\n const manifest = getTestManifest();\n if (manifest) {\n // Use lookupInManifest for consistent qualified name handling\n const testEntry = lookupInManifest(manifest, qualifiedName || className);\n if (testEntry) {\n foundEntries.push({\n entry: testEntry,\n packageName: manifest.packageName || '@happyvertical/smrt-core',\n filePath: testEntry.filePath,\n manifestSource: '@happyvertical/smrt-core test manifest',\n });\n }\n }\n }\n\n // 4. Check staticManifest (core framework classes)\n const staticManifestData = getStaticManifest();\n // Use lookupInManifest for consistent qualified name handling\n const staticEntry = lookupInManifest(\n staticManifestData,\n qualifiedName || className,\n );\n if (staticEntry) {\n foundEntries.push({\n entry: staticEntry,\n packageName: staticManifestData.packageName || '@happyvertical/smrt-core',\n filePath: staticEntry.filePath,\n manifestSource: '@happyvertical/smrt-core static manifest',\n });\n }\n\n // 5. Check other cached external manifests\n for (const [cachedPkgName, manifest] of getManifestCacheMap().entries()) {\n // Skip if this is the constructor's package (already checked above)\n if (cachedPkgName === constructorPackage) {\n continue;\n }\n\n // Use lookupInManifest for consistent qualified name handling\n const entry = lookupInManifest(manifest, qualifiedName || className);\n if (entry) {\n foundEntries.push({\n entry:\n !entry.packageName && manifest.packageName\n ? { ...entry, packageName: manifest.packageName }\n : entry,\n packageName: manifest.packageName || cachedPkgName,\n filePath: entry.filePath,\n manifestSource: `${manifest.packageName || cachedPkgName}/manifest.json`,\n });\n }\n }\n\n // Deduplicate entries that reference the same source file.\n // Consumer manifests (e.g. smrt-users, dashboard) re-export classes from\n // upstream packages (e.g. smrt-profiles). These appear in multiple manifests\n // but point to the same filePath — they are NOT real collisions.\n if (foundEntries.length > 1) {\n const uniqueByFile = new Map<string, (typeof foundEntries)[0]>();\n for (const entry of foundEntries) {\n // Normalize file paths so the same source file with different absolute\n // prefixes (local dev vs CI build) is recognized as identical.\n // Extract the relative path from the last \"packages/\" segment onward.\n let key = entry.filePath || `${entry.packageName}:${className}`;\n if (entry.filePath) {\n const pkgIdx = entry.filePath.lastIndexOf('packages/');\n if (pkgIdx !== -1) {\n key = entry.filePath.slice(pkgIdx);\n }\n }\n if (!uniqueByFile.has(key)) {\n uniqueByFile.set(key, entry);\n }\n }\n\n if (uniqueByFile.size === 1) {\n // All entries point to the same source file — not a real collision.\n // Use the first (highest priority) entry.\n foundEntries.splice(1);\n } else if (uniqueByFile.size > 1) {\n // True collision: different source files define the same class name\n const collisionInfo = foundEntries.map(\n (f) =>\n ` - ${f.packageName} (${f.filePath || 'unknown file'}) from ${f.manifestSource}`,\n );\n\n // Store collision info for reporting\n getManifestCollisionsMap().set(\n className,\n foundEntries.map((f) => ({\n packageName: f.packageName,\n filePath: f.filePath,\n manifestSource: f.manifestSource,\n })),\n );\n\n // Throw error on collision\n throw new Error(\n `SMRT Class Name Collision Detected: \"${className}\"\\n\\n` +\n `This class is defined in multiple packages:\\n${collisionInfo.join('\\n')}\\n\\n` +\n `The collision will cause the wrong field definitions to be used,\\n` +\n `leading to properties not being initialized correctly.\\n\\n` +\n `To fix:\\n` +\n ` 1. Use unique class names across packages (e.g., ${className}_${constructorPackage?.split('/').pop() || 'Unique'})\\n` +\n ` 2. Or use @smrt({ name: 'unique_name' }) to override the registration name\\n` +\n ` 3. Remove test classes with conflicting names from production manifests\\n\\n` +\n `If this is a test class collision, ensure test manifests are not included in production builds.`,\n );\n }\n }\n\n // Return the found entry (priority given to constructor's package)\n if (foundEntries.length === 1) {\n return foundEntries[0].entry;\n }\n\n return undefined;\n}\n\n/**\n * Get all detected manifest collisions\n *\n * @returns Map of class names to array of collision info\n */\nexport function getManifestCollisions(): Map<\n string,\n Array<{ packageName: string; filePath?: string; manifestSource: string }>\n> {\n return new Map(getManifestCollisionsMap());\n}\n\n/**\n * Clear manifest cache\n *\n * Useful for testing or when packages are updated at runtime.\n */\nexport function clearManifestCache(): void {\n // Reset all cached manifest state so tests/dev tooling can force a full\n // rediscovery pass on the next lookup.\n setStaticManifestCache(undefined);\n setStaticManifestLoadAttempted(false);\n setTestManifestCache(undefined);\n setTestManifestLoadAttempted(false);\n setLocalTestManifestCache(undefined);\n getManifestCacheMap().clear();\n getManifestCollisionsMap().clear();\n getSTISiblingCache().clear();\n}\n\n/**\n * Get all loaded manifests\n *\n * Returns a copy of the manifest cache for inspection.\n *\n * @returns Array of [packageName, manifest] entries\n */\nexport function getLoadedManifests(): Array<[string, Manifest]> {\n return Array.from(getManifestCacheMap().entries());\n}\n\n/**\n * Discover all STI sibling classes that share the same collection (table)\n *\n * This is critical for STI schema merging: when one subtype is accessed,\n * we need to discover ALL subtypes sharing the same table so that the\n * database adapter receives a complete schema with all columns.\n *\n * Scans all available manifests:\n * 1. Local test manifest (for test classes)\n * 2. Test manifest (for core test classes)\n * 3. Static manifest (for core framework classes)\n * 4. Cached external manifests\n * 5. SMRT dependencies from local test manifest\n *\n * @param collection - The collection/table name to find siblings for\n * @returns Array of manifest entries that share the same collection\n */\nexport function discoverSTISiblingsSync(\n collection: string,\n): Array<{ className: string; entry: ManifestEntry; packageName?: string }> {\n // Check cache first to avoid repeated scans (fixes #644)\n const cache = getSTISiblingCache();\n const cached = cache.get(collection);\n if (cached !== undefined) {\n return cached;\n }\n\n const siblings: Array<{\n className: string;\n entry: ManifestEntry;\n packageName?: string;\n }> = [];\n\n // Track already-found class names to avoid duplicates (case-insensitive)\n // Use lowercase keys to prevent both 'praeco' and 'Praeco' from being added\n const foundClasses = new Set<string>();\n\n debugLog(\n `[manifest-loader] discoverSTISiblingsSync called for collection: ${collection}`,\n );\n\n // Helper to add entries from a manifest\n const addFromManifest = (\n manifest: Manifest | null | undefined,\n source: string,\n ) => {\n if (!manifest?.objects) return;\n\n for (const [key, entry] of Object.entries(manifest.objects) as [\n string,\n ManifestEntry,\n ][]) {\n // Check if this entry uses the same collection (table)\n if (entry.collection === collection) {\n const className = entry.className || key;\n // Use case-insensitive check to prevent registering both 'praeco' and 'Praeco'\n const lowerClassName = className.toLowerCase();\n if (!foundClasses.has(lowerClassName)) {\n foundClasses.add(lowerClassName);\n siblings.push({\n className,\n entry,\n packageName: entry.packageName || manifest.packageName,\n });\n debugLog(\n `[manifest-loader] Found STI sibling: ${className} (collection: ${collection}) from ${source}`,\n );\n }\n }\n }\n };\n\n // 1. Check local test manifest (domain package test classes)\n if (isTestEnvironment()) {\n if (!getLocalTestManifestCache()) {\n loadLocalTestManifestSync();\n }\n addFromManifest(getLocalTestManifestCache(), 'localTestManifest');\n }\n\n // 2. Check test manifest (core test classes)\n const testManifestData = isTestEnvironment() ? getTestManifest() : null;\n if (testManifestData) {\n addFromManifest(testManifestData, 'testManifest');\n }\n\n // 3. Check static manifest (core framework classes)\n const staticManifestData = getStaticManifest();\n addFromManifest(staticManifestData, 'staticManifest');\n\n // 4. Check cached external manifests\n for (const [pkgName, manifest] of getManifestCacheMap().entries()) {\n addFromManifest(manifest, `manifestCache:${pkgName}`);\n }\n\n // 5. Try loading from SMRT dependencies from ALL manifests (not just localTestManifest)\n // This ensures production environments also discover STI siblings\n const pendingDependencies = collectDeclaredSmrtDependencies([\n getLocalTestManifestCache(),\n isTestEnvironment() ? testManifestData : null,\n staticManifestData,\n ...getManifestCacheMap().values(),\n ]);\n const visitedDependencies = new Set<string>();\n\n debugLog(\n `[manifest-loader] Scanning ${pendingDependencies.length} SMRT dependencies for STI siblings: ${pendingDependencies.join(', ')}`,\n );\n\n while (pendingDependencies.length > 0) {\n const pkg = pendingDependencies.shift();\n if (!pkg || visitedDependencies.has(pkg)) {\n continue;\n }\n\n visitedDependencies.add(pkg);\n\n const manifest = loadExternalManifestSync(pkg);\n if (manifest) {\n addFromManifest(manifest, `smrtDependency:${pkg}`);\n\n for (const dependency of manifest.smrtDependencies || []) {\n if (!visitedDependencies.has(dependency)) {\n pendingDependencies.push(dependency);\n }\n }\n }\n }\n\n debugLog(\n `[manifest-loader] discoverSTISiblingsSync found ${siblings.length} siblings for collection: ${collection}`,\n );\n\n // Cache the results for future calls (fixes #644)\n cache.set(collection, siblings);\n\n return siblings;\n}\n"],"names":["getStaticManifestCacheFromStore","getTestManifestCacheFromStore","getLocalTestManifestCacheFromStore","getManifestCacheFromStore","require","isTestEnvFromStore","error","stack","stackLines"],"mappings":"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"}
1
+ {"version":3,"file":"manifest-loader.js","sources":["../../src/manifest/manifest-loader.ts"],"sourcesContent":["/**\n * Manifest Loader - Automatic discovery of external package manifests\n *\n * This module provides automatic loading of SMRT manifests from external packages,\n * solving issue #131 where external package schemas weren't being detected.\n *\n * Architecture:\n * - Build-time: AST scanner generates manifests in dist/manifest.json\n * - Run-time: This module discovers and loads those manifests automatically\n * - Caching: Loaded manifests are cached to avoid repeated imports\n *\n * Flow:\n * 1. Check testManifest (for test classes)\n * 2. Check staticManifest (for core framework classes)\n * 3. Resolve external package manifests from explicit JSON exports\n * 4. Return manifest entry or undefined\n *\n * External manifest loading intentionally follows a pure-ESM JSON contract.\n * Packages are expected to publish a JSON manifest via \"./manifest\" and/or\n * \"./manifest.json\" exports. Runtime discovery does not guess sibling workspace\n * paths or load JavaScript manifest modules.\n */\n\nimport { existsSync, readdirSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { createLogger } from '@happyvertical/logger';\nimport type { SmrtObjectConstructor } from '../registry/types.js';\nimport { ObjectRegistry } from '../registry.js';\nimport type {\n FieldDefinition,\n MethodDefinition,\n SmartObjectDefinition,\n SmartObjectManifest,\n} from '../scanner/types.js';\nimport { parse } from '../utils/json.js';\nimport {\n createQualifiedName,\n isQualifiedName,\n parseQualifiedName,\n} from '../utils/qualified-names.js';\nimport { ManifestManager } from './manager.js';\nimport { getDefaultCompositeSource } from './sources/composite.js';\nimport {\n getLocalTestManifestCache as getLocalTestManifestCacheFromStore,\n getManifestCache as getManifestCacheFromStore,\n getStaticManifestCache as getStaticManifestCacheFromStore,\n getTestManifestCache as getTestManifestCacheFromStore,\n isTestEnvironment as isTestEnvFromStore,\n shouldLoadCoreTestManifest,\n} from './store.js';\n\n/**\n * Extend globalThis to include manifest loader state.\n * Using globalThis ensures all module instances share the same manifest caches,\n * which is critical in monorepos where the same package can be loaded\n * from different paths (e.g., pnpm store vs workspace symlink).\n *\n * @see https://github.com/happyvertical/smrt/issues/543\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtManifestStatic: SmartObjectManifest | null | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestStaticLoadAttempted: boolean | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestTest: SmartObjectManifest | null | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestTestLoadAttempted: boolean | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestCache: Map<string, SmartObjectManifest> | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestLocalTest: SmartObjectManifest | null | undefined;\n // eslint-disable-next-line no-var\n var __smrtManifestCollisions:\n | Map<\n string,\n Array<{\n packageName: string;\n filePath?: string;\n manifestSource: string;\n }>\n >\n | undefined;\n // eslint-disable-next-line no-var\n var __smrtSTISiblingCache:\n | Map<\n string,\n Array<{ className: string; entry: ManifestEntry; packageName?: string }>\n >\n | undefined;\n}\n\n// Use globalThis for cross-module state sharing\n// This ensures loadConfig() in one module instance affects all packages\n\n// ── Cache access (delegates to manifest/store.ts — the single source of\n// truth added in Release B #1133 for globalThis manifest state).\n// manifest-loader.ts keeps its own setters + load-attempted flags below\n// because those are internal to this module's async loader state machine;\n// the read-only getters just forward to store.ts to eliminate drift.\n\nconst getStaticManifestCache = getStaticManifestCacheFromStore;\nconst getTestManifestCache = getTestManifestCacheFromStore;\nconst getLocalTestManifestCache = getLocalTestManifestCacheFromStore;\nconst getManifestCacheMap = getManifestCacheFromStore;\n\nfunction setStaticManifestCache(\n manifest: SmartObjectManifest | null | undefined,\n): void {\n globalThis.__smrtManifestStatic = manifest;\n}\n\nfunction getStaticManifestLoadAttempted(): boolean {\n return globalThis.__smrtManifestStaticLoadAttempted ?? false;\n}\n\nfunction setStaticManifestLoadAttempted(value: boolean): void {\n globalThis.__smrtManifestStaticLoadAttempted = value;\n}\n\nfunction setTestManifestCache(\n manifest: SmartObjectManifest | null | undefined,\n): void {\n globalThis.__smrtManifestTest = manifest;\n}\n\nfunction getTestManifestLoadAttempted(): boolean {\n return globalThis.__smrtManifestTestLoadAttempted ?? false;\n}\n\nfunction setTestManifestLoadAttempted(value: boolean): void {\n globalThis.__smrtManifestTestLoadAttempted = value;\n}\n\nfunction setLocalTestManifestCache(\n manifest: SmartObjectManifest | null | undefined,\n): void {\n globalThis.__smrtManifestLocalTest = manifest;\n}\n\n/**\n * Get the manifest collisions Map from globalThis\n */\nfunction getManifestCollisionsMap(): Map<\n string,\n Array<{ packageName: string; filePath?: string; manifestSource: string }>\n> {\n if (!globalThis.__smrtManifestCollisions) {\n globalThis.__smrtManifestCollisions = new Map();\n }\n return globalThis.__smrtManifestCollisions;\n}\n\n/**\n * Get the STI sibling cache Map from globalThis\n * Caches discoverSTISiblingsSync results per collection to avoid repeated scans\n */\nfunction getSTISiblingCache(): Map<\n string,\n Array<{ className: string; entry: ManifestEntry; packageName?: string }>\n> {\n if (!globalThis.__smrtSTISiblingCache) {\n globalThis.__smrtSTISiblingCache = new Map();\n }\n return globalThis.__smrtSTISiblingCache;\n}\n\n// Create require function once for reuse\nconst require = createRequire(import.meta.url);\n\n/**\n * Cached debug flag evaluated once at module load time.\n * Environment variables don't change at runtime, so this is safe.\n * @see https://github.com/happyvertical/smrt/issues/729\n */\nconst DEBUG_ENABLED =\n process.env.DEBUG_MANIFEST === 'true' ||\n process.env.DEBUG_MANIFEST === '1' ||\n process.env.DEBUG?.includes('manifest') ||\n false;\n\n// The debug traces below are gated by DEBUG_MANIFEST / DEBUG_TEST_ENV, so the\n// logger level must allow debug when either is set (a fixed 'info' would filter\n// them out and silently break those debug switches).\nconst logger = createLogger({\n level: DEBUG_ENABLED || process.env.DEBUG_TEST_ENV ? 'debug' : 'info',\n});\n\n/**\n * Log a debug message only if DEBUG_MANIFEST is enabled.\n * Uses cached boolean check instead of repeated env var access.\n */\nfunction debugLog(message: string): void {\n if (DEBUG_ENABLED) {\n logger.debug(message);\n }\n}\n\n/**\n * Cache for className-to-entry index per manifest.\n * This enables O(1) lookup by className instead of O(n) iteration.\n * @see https://github.com/happyvertical/smrt/issues/729\n */\nconst classNameIndexCache = new WeakMap<\n SmartObjectManifest,\n Map<string, SmartObjectDefinition>\n>();\n\n/**\n * Get or build the className index for a manifest.\n * Index maps lowercase className to entry for O(1) lookup.\n */\nfunction getClassNameIndex(\n manifest: SmartObjectManifest,\n): Map<string, SmartObjectDefinition> {\n let index = classNameIndexCache.get(manifest);\n if (!index) {\n index = new Map<string, SmartObjectDefinition>();\n for (const [key, entry] of Object.entries(manifest.objects)) {\n const name = (entry.className || key).toLowerCase();\n if (!index.has(name)) {\n index.set(name, entry);\n } else {\n const existing = index.get(name)!;\n const existingName = (existing.className || '').toLowerCase();\n const newExtends = (entry.extends || '').toLowerCase();\n const existingExtends = (existing.extends || '').toLowerCase();\n\n // Issue #950: STI child-wins — if new entry extends existing, replace\n if (\n newExtends &&\n (newExtends === existingName || newExtends === name)\n ) {\n index.set(name, entry);\n debugLog(\n `Manifest className '${name}': child '${key}' replaces parent`,\n );\n } else if (\n existingExtends &&\n (existingExtends === (entry.className || key).toLowerCase() ||\n existingExtends === name)\n ) {\n // Existing is already the child, keep it\n debugLog(\n `Manifest className '${name}': keeping child, ignoring parent '${key}'`,\n );\n } else {\n debugLog(\n `Manifest className collision for '${name}': keeping first, ignoring key '${key}'`,\n );\n }\n }\n }\n classNameIndexCache.set(manifest, index);\n }\n return index;\n}\n\n/**\n * Test-environment detection with optional DEBUG_TEST_ENV logging.\n *\n * Delegates to the single source of truth in `store.ts` so the\n * ManifestSource implementations (which also gate on test-env) cannot\n * drift from the legacy sync loader. The logging wrapper stays here\n * because the trace is specific to this module's loader state machine.\n */\nfunction isTestEnvironment(): boolean {\n const result = isTestEnvFromStore();\n\n if (process.env.DEBUG_TEST_ENV) {\n logger.debug('[manifest-loader] isTestEnvironment check', {\n NODE_ENV: process.env.NODE_ENV,\n VITEST: process.env.VITEST,\n JEST_WORKER_ID: process.env.JEST_WORKER_ID,\n result,\n });\n }\n\n return result;\n}\n\nfunction getStaticManifest(): SmartObjectManifest {\n if (!getStaticManifestLoadAttempted()) {\n setStaticManifestLoadAttempted(true);\n try {\n // Try to import the generated static manifest\n const imported = require('./static-manifest.js');\n setStaticManifestCache(imported.staticManifest || imported.default);\n } catch {\n // Fallback to empty manifest if file doesn't exist yet (during build)\n setStaticManifestCache({\n version: '1.0.0',\n timestamp: Date.now(),\n objects: {},\n packageName: '@happyvertical/smrt-core',\n });\n }\n }\n return getStaticManifestCache()!;\n}\n\n/**\n * Lazy-load smrt-core's internal test manifest only for smrt-core's own tests.\n * Consumer packages should never see these fixtures, or they can collide with\n * real external classes during downstream test runs.\n */\nfunction getTestManifest(): SmartObjectManifest | null {\n if (!getTestManifestLoadAttempted()) {\n setTestManifestLoadAttempted(true);\n\n // CRITICAL: Scope the core test manifest to smrt-core's own test suite.\n if (!shouldLoadCoreTestManifest()) {\n if (process.env.DEBUG_TEST_ENV) {\n logger.debug(\n '[manifest-loader] ⚠️ Skipping core test manifest load (not smrt-core test environment)',\n );\n }\n setTestManifestCache(null);\n return null;\n }\n\n try {\n // Dynamically import test manifest to avoid loading in production\n const imported = require('./test-manifest-stub.js');\n const manifest = imported.testManifest || imported.default;\n setTestManifestCache(manifest);\n if (process.env.DEBUG_TEST_ENV) {\n logger.debug(\n `[manifest-loader] ✅ Loaded test manifest (${Object.keys(manifest?.objects || {}).length} objects)`,\n );\n }\n } catch (error) {\n if (process.env.DEBUG_TEST_ENV) {\n logger.debug(\n '[manifest-loader] ⚠️ Test manifest not found (this is normal in production)',\n );\n }\n setTestManifestCache(null);\n }\n }\n return getTestManifestCache();\n}\n\n// Re-export types for convenience\nexport type Manifest = SmartObjectManifest;\nexport type ManifestEntry = SmartObjectDefinition;\nexport type { FieldDefinition, MethodDefinition };\n\n// Note: manifestCache and localTestManifest are now accessed via globalThis helper functions\n// getManifestCacheMap() and getLocalTestManifestCache()/setLocalTestManifestCache()\n\n/**\n * Load local test manifest from current package (synchronous)\n *\n * During test runs, packages can have manifests in two locations:\n * 1. src/manifest/test-manifest.json - Domain packages during development\n * 2. dist/manifest.json - Built packages (consuming apps like praeco)\n *\n * This function attempts to load the manifest from either location.\n *\n * @returns Loaded manifest or null if not found or undefined if not yet attempted\n */\nexport function loadLocalTestManifestSync(): Manifest | null | undefined {\n // Only return cached manifest if it was successfully loaded\n // Don't cache null (failed loads) - allow retries\n const cached = getLocalTestManifestCache();\n if (cached !== undefined && cached !== null) {\n return cached;\n }\n\n // Use ManifestManager for unified local loading\n // This checks: .smrt/manifest.json -> dist/manifest.json\n const manager = new ManifestManager(process.cwd());\n const manifest = manager.loadLocal();\n\n // Fallback location: src/manifest/test-manifest.json\n // This is still used by smrt-core and other packages that generate test manifests here\n const testManifestPath = join(\n process.cwd(),\n 'src/manifest/test-manifest.json',\n );\n\n // If ManifestManager found a manifest, check if it has objects\n // If it has 0 objects but the fallback exists with objects, use the fallback instead\n // This handles the case where dist/manifest.json is the static-manifest.json (0 objects)\n // but src/manifest/test-manifest.json has the real test classes\n if (manifest) {\n const objectCount = Object.keys(manifest.objects).length;\n\n // If manifest has objects, use it\n if (objectCount > 0) {\n setLocalTestManifestCache(manifest);\n debugLog(\n `[manifest-loader] ✅ Loaded local manifest via ManifestManager (${objectCount} objects)`,\n );\n return manifest;\n }\n\n // Manifest has 0 objects - check if fallback has more\n if (existsSync(testManifestPath)) {\n try {\n const testManifest: Manifest = parse(\n readFileSync(testManifestPath, 'utf-8'),\n );\n const testObjectCount = Object.keys(testManifest.objects).length;\n\n if (testObjectCount > 0) {\n setLocalTestManifestCache(testManifest);\n debugLog(\n `[manifest-loader] ✅ Loaded test manifest from ${testManifestPath} (${testObjectCount} objects) - preferred over empty ManifestManager result`,\n );\n return testManifest;\n }\n } catch {\n // Fallback also failed, use the empty manifest\n }\n }\n\n // No better option, cache and use the empty manifest\n setLocalTestManifestCache(manifest);\n debugLog(\n `[manifest-loader] ✅ Loaded local manifest via ManifestManager (${objectCount} objects)`,\n );\n return manifest;\n }\n\n // ManifestManager returned null - check fallback\n if (existsSync(testManifestPath)) {\n try {\n const testManifest: Manifest = parse(\n readFileSync(testManifestPath, 'utf-8'),\n );\n setLocalTestManifestCache(testManifest);\n const objectCount = Object.keys(testManifest.objects).length;\n debugLog(\n `[manifest-loader] ✅ Loaded test manifest from ${testManifestPath} (${objectCount} objects)`,\n );\n return testManifest;\n } catch (error) {\n debugLog(\n `[manifest-loader] ✗ Failed to load test manifest from ${testManifestPath}: ${error instanceof Error ? error.message : 'unknown'}`,\n );\n }\n }\n\n // No manifest found - DON'T cache null, allow retries\n // This is important because the manifest may be generated later\n debugLog(\n '[manifest-loader] ⚠️ No local manifest found (will retry on next call)',\n );\n return null;\n}\n\n/**\n * Extract package name from class constructor\n *\n * Uses the ObjectRegistry (preferred) or fallback methods to determine\n * which package the class belongs to.\n *\n * Search order:\n * 1. ObjectRegistry (packageName injected at build time from manifest) - SKIPPED during initial registration\n * 2. __package__ metadata (build tooling can inject this)\n * 3. require.resolve() (resolves package.json from constructor file location)\n * 4. Error stack trace parsing (fallback, fragile in pnpm workspaces)\n *\n * @param ctor - Class constructor\n * @param skipRegistry - If true, skip checking ObjectRegistry (used during initial registration to avoid circular dependency)\n * @returns Package name (e.g., '@happyvertical/smrt-places') or null\n */\nexport function getPackageName(\n ctor: SmrtObjectConstructor,\n skipRegistry: boolean = false,\n): string | null {\n try {\n // 1. Try ObjectRegistry first (most reliable - from build-time manifest)\n // This solves issue #143 where pnpm workspace symlinks break stack trace parsing\n // CRITICAL: Skip during initial registration to avoid circular dependency (issue #159)\n if (!skipRegistry) {\n const className = ctor.name;\n if (className) {\n const registered = ObjectRegistry.getClass(className);\n if (registered?.packageName) {\n return registered.packageName;\n }\n }\n }\n\n // 2. Check if class has __package__ metadata (could be added by build tooling)\n const packageMeta = (ctor as { __package__?: string }).__package__;\n if (packageMeta) {\n return packageMeta;\n }\n\n // 3. Try require.resolve() to find package.json from constructor location\n // This is more reliable than stack trace parsing for published packages\n try {\n const error = new Error();\n const stack = error.stack || '';\n const stackLines = stack.split('\\n');\n\n // Find the first line with a file path that's NOT from smrt-core\n // Skip manifest-loader, registry, and other smrt-core files\n for (const line of stackLines) {\n const fileMatch = line.match(/\\(([^)]+\\.(?:js|ts))/);\n if (fileMatch) {\n const filePath = fileMatch[1];\n // Skip smrt-core internal files\n if (\n filePath.includes('manifest-loader') ||\n filePath.includes('registry') ||\n filePath.includes('/smrt-core/dist/')\n ) {\n continue; // Skip smrt-core files, look for external package\n }\n\n // Try to resolve package.json from this file\n try {\n // Handle file:// URLs\n const cleanPath = filePath.replace(/^file:\\/\\//, '');\n let dir = dirname(cleanPath);\n // Walk up until we find a package.json\n for (let i = 0; i < 10; i++) {\n const pkgPath = join(dir, 'package.json');\n try {\n if (existsSync(pkgPath)) {\n const pkg = parse<{ name?: string }>(\n readFileSync(pkgPath, 'utf-8'),\n );\n if (pkg.name?.startsWith('@')) {\n return pkg.name;\n }\n }\n } catch {\n // Keep walking up\n }\n const parent = dirname(dir);\n if (parent === dir) break; // Reached root\n dir = parent;\n }\n } catch {\n // Fall through to next method\n }\n break;\n }\n }\n } catch {\n // Fall through to next method\n }\n\n // 4. Final fallback: Try to extract from Error stack trace with node_modules pattern\n // This method is fragile and fails in pnpm workspaces, but kept for backward compatibility\n const error = new Error();\n const stack = error.stack || '';\n const stackLines = stack.split('\\n');\n\n // Look for line with 'node_modules/@scope/package' pattern\n for (const line of stackLines) {\n const match = line.match(/node_modules\\/(@[^/]+\\/[^/]+)/);\n if (match) {\n return match[1];\n }\n }\n\n // Package name is now injected at build time into the manifest and stored in ObjectRegistry\n // If we reach here, the class is likely not from an external package\n return null;\n } catch {\n return null;\n }\n}\n\ninterface ManifestExportConditions {\n default?: string;\n import?: string;\n require?: string;\n}\n\ninterface ExternalPackageJson {\n exports?: Record<string, string | ManifestExportConditions>;\n}\n\nfunction findWorkspaceRoot(startDir: string): string | null {\n let currentDir = startDir;\n\n while (true) {\n if (existsSync(join(currentDir, 'pnpm-workspace.yaml'))) {\n return currentDir;\n }\n\n const parentDir = dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n}\n\nfunction resolveInstalledPackageJsonPath(packageName: string): string | null {\n let currentDir = process.cwd();\n\n while (true) {\n const packageJsonPath = join(\n currentDir,\n 'node_modules',\n packageName,\n 'package.json',\n );\n\n if (existsSync(packageJsonPath)) {\n return packageJsonPath;\n }\n\n const parentDir = dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n}\n\nfunction resolveWorkspacePackageJsonPath(packageName: string): string | null {\n const workspaceRoot = findWorkspaceRoot(process.cwd());\n if (!workspaceRoot) {\n return null;\n }\n\n const workspacePackagesDir = join(workspaceRoot, 'packages');\n if (!existsSync(workspacePackagesDir)) {\n return null;\n }\n\n for (const packageDirName of readdirSync(workspacePackagesDir)) {\n const packageJsonPath = join(\n workspacePackagesDir,\n packageDirName,\n 'package.json',\n );\n if (!existsSync(packageJsonPath)) {\n continue;\n }\n\n try {\n const packageJson = parse<{ name?: string }>(\n readFileSync(packageJsonPath, 'utf-8'),\n );\n if (packageJson.name === packageName) {\n return packageJsonPath;\n }\n } catch {\n // Ignore unreadable workspace package metadata and continue scanning.\n }\n }\n\n return null;\n}\n\nfunction resolveWorkspaceSourceManifestPath(packageDir: string): string | null {\n const candidates = [\n join(packageDir, 'src', 'manifest', 'manifest.json'),\n join(packageDir, '.smrt', 'manifest.json'),\n ];\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\ninterface ManifestLoadOptions {\n warn?: boolean;\n}\n\nfunction resolveManifestExportPath(\n packageName: string,\n options: ManifestLoadOptions = {},\n): string | null {\n const shouldWarn = options.warn ?? true;\n const packageJsonPath =\n resolveInstalledPackageJsonPath(packageName) ||\n resolveWorkspacePackageJsonPath(packageName);\n\n if (!packageJsonPath) {\n return null;\n }\n\n const packageDir = dirname(packageJsonPath);\n const packageJson = parse<ExternalPackageJson>(\n readFileSync(packageJsonPath, 'utf-8'),\n );\n const manifestExports = ['./manifest.json', './manifest'];\n\n for (const exportKey of manifestExports) {\n const manifestExport = packageJson.exports?.[exportKey];\n if (!manifestExport) {\n continue;\n }\n\n const manifestRelativePath =\n typeof manifestExport === 'string'\n ? manifestExport\n : manifestExport.import ||\n manifestExport.default ||\n manifestExport.require;\n\n if (!manifestRelativePath) {\n if (shouldWarn) {\n logger.warn(\n `Package ${packageName} has invalid manifest export configuration for ${exportKey}`,\n );\n }\n return null;\n }\n\n if (!manifestRelativePath.endsWith('.json')) {\n if (shouldWarn) {\n logger.warn(\n `Package ${packageName} must export a JSON manifest for ${exportKey}, received ${manifestRelativePath}`,\n );\n }\n return null;\n }\n\n const manifestPath = join(packageDir, manifestRelativePath);\n if (existsSync(manifestPath)) {\n return manifestPath;\n }\n\n const workspaceSourceManifest =\n resolveWorkspaceSourceManifestPath(packageDir);\n if (workspaceSourceManifest) {\n return workspaceSourceManifest;\n }\n\n if (shouldWarn) {\n logger.warn(\n `Package ${packageName} declares manifest export ${manifestRelativePath}, but no manifest file was found.`,\n );\n }\n return null;\n }\n\n return null;\n}\n\nfunction collectDeclaredSmrtDependencies(\n manifests: Array<Manifest | null | undefined>,\n): string[] {\n const dependencies = new Set<string>();\n\n for (const manifest of manifests) {\n for (const pkg of manifest?.smrtDependencies || []) {\n dependencies.add(pkg);\n }\n }\n\n return Array.from(dependencies);\n}\n\n/**\n * Load manifest from external package\n *\n * Uses createRequire from process.cwd() to resolve packages from the calling\n * application's context, not from smrt-core's context. This allows finding\n * packages that are dependencies of the app but not of smrt-core.\n *\n * External packages export manifests via package.json:\n * \"exports\": { \"./manifest\": \"./dist/manifest.json\" }\n *\n * @param packageName - Package name (e.g., '@happyvertical/smrt-places')\n * @returns Manifest object or null if not found\n */\n/**\n * Load external package manifest synchronously\n * This is the synchronous version of loadExternalManifest for use during class registration\n */\nexport function loadExternalManifestSync(\n packageName: string,\n options: ManifestLoadOptions = {},\n): Manifest | null {\n // Check cache first\n if (getManifestCacheMap().has(packageName)) {\n debugLog(`[manifest-loader] Using cached manifest for ${packageName}`);\n return getManifestCacheMap().get(packageName)!;\n }\n\n debugLog(\n `[manifest-loader] Attempting to load external manifest for ${packageName}`,\n );\n\n const manifestPath = resolveManifestExportPath(packageName, options);\n\n if (!manifestPath) {\n debugLog(\n `[manifest-loader] Package ${packageName} does not expose a JSON manifest export`,\n );\n return null;\n }\n\n try {\n const manifest = parse<Manifest>(readFileSync(manifestPath, 'utf-8'));\n\n if (!manifest.objects || typeof manifest.objects !== 'object') {\n if (options.warn ?? true) {\n logger.warn(`Invalid manifest structure for package ${packageName}`);\n }\n return null;\n }\n\n const cachedManifest = manifest.packageName\n ? manifest\n : { ...manifest, packageName };\n\n getManifestCacheMap().set(packageName, cachedManifest);\n debugLog(\n `[manifest-loader] ✅ Loaded external manifest for ${packageName} (${Object.keys(cachedManifest.objects).length} objects)`,\n );\n\n return cachedManifest;\n } catch (error) {\n if (options.warn ?? true) {\n logger.warn(\n `Failed to load manifest for package ${packageName}: ${error instanceof Error ? error.message : error}`,\n );\n }\n return null;\n }\n}\n\nexport async function loadExternalManifest(\n packageName: string,\n options: ManifestLoadOptions = {},\n): Promise<Manifest | null> {\n // Delegate to synchronous version since all operations are sync anyway\n return loadExternalManifestSync(packageName, options);\n}\n\n/**\n * Load a manifest directly from a known file path and cache it by package name.\n *\n * This is used by workspace/dev flows where sibling packages may not be\n * installed into node_modules yet, but their generated manifests are still\n * available on disk.\n */\nexport function loadManifestFromPathSync(\n manifestPath: string,\n): Manifest | null {\n try {\n const manifestJson = readFileSync(manifestPath, 'utf-8');\n const manifest: Manifest = parse(manifestJson);\n\n if (!manifest.objects || typeof manifest.objects !== 'object') {\n logger.warn(`Invalid manifest structure at ${manifestPath}`);\n return null;\n }\n\n const cacheKey = manifest.packageName || manifestPath;\n getManifestCacheMap().set(cacheKey, manifest);\n debugLog(\n `[manifest-loader] ✅ Loaded manifest from path ${manifestPath} (${Object.keys(manifest.objects).length} objects)`,\n );\n\n return manifest;\n } catch (error) {\n logger.warn(\n `Failed to load manifest from path ${manifestPath}: ${error instanceof Error ? error.message : error}`,\n );\n return null;\n }\n}\n\n/**\n * Discover manifest entry synchronously (checks only loaded manifests)\n *\n * Search order:\n * 1. localTestManifest (for domain package test classes)\n * 2. testManifest (for core test classes)\n * 3. staticManifest (for core framework classes)\n * 4. Cached external manifests\n *\n * @param className - Class name (for lookup)\n * @returns ManifestEntry or undefined if not found\n */\nexport function discoverManifestSync(\n className: string,\n): ManifestEntry | undefined {\n debugLog(`[manifest-loader] discoverManifestSync called for: ${className}`);\n\n // Ensure test-env caches are seeded before the composite queries them.\n // Historically, steps 1-2 of discoverManifestSync did this inline. The\n // composite's TestManifestSource and LocalTestManifestSource read directly\n // from cache state — without this seeding the first sync lookup in a\n // clean test process would miss core test classes on their first access\n // (regression noted in #1138 review).\n if (isTestEnvironment()) {\n if (!getLocalTestManifestCache()) {\n loadLocalTestManifestSync();\n }\n if (!getTestManifestCache()) {\n getTestManifest();\n }\n }\n\n // Carry qualified-name / package context into the composite lookup so\n // multi-package same-simple-name scenarios (issue #951) resolve to the\n // right manifest even via the sync path.\n const query = isQualifiedName(className)\n ? (() => {\n const parsed = parseQualifiedName(className);\n return {\n className: parsed.className,\n packageName: parsed.packageName,\n qualifiedName: className,\n };\n })()\n : { className };\n\n // Steps 1-4 (local-test → test → static → embedded cache) now live in\n // CompositeManifestSource at the exact same priority order.\n const compositeHit = getDefaultCompositeSource().lookup(query);\n if (compositeHit) {\n debugLog(\n `[manifest-loader] ✅ Found ${className} via ${compositeHit.source} source`,\n );\n const entry = compositeHit.def;\n if (!entry.packageName && compositeHit.packageName) {\n return { ...entry, packageName: compositeHit.packageName };\n }\n return entry;\n }\n\n // 5. Try loading from explicitly declared external SMRT package dependencies.\n debugLog(\n `[manifest-loader] ${className} not found in cached manifests, trying external packages...`,\n );\n\n const pendingPackages = collectDeclaredSmrtDependencies([\n getLocalTestManifestCache(),\n isTestEnvironment() ? getTestManifest() : null,\n getStaticManifest(),\n ...getManifestCacheMap().values(),\n ]);\n\n if (pendingPackages.length === 0) {\n debugLog(\n '[manifest-loader] No SMRT dependencies discovered. Run manifest generation if external packages are expected.',\n );\n }\n\n const visitedPackages = new Set<string>();\n\n while (pendingPackages.length > 0) {\n const pkg = pendingPackages.shift();\n if (!pkg || visitedPackages.has(pkg)) {\n continue;\n }\n\n visitedPackages.add(pkg);\n const manifest = loadExternalManifestSync(pkg);\n if (!manifest) {\n continue;\n }\n\n for (const dependency of manifest.smrtDependencies || []) {\n if (!visitedPackages.has(dependency)) {\n pendingPackages.push(dependency);\n }\n }\n\n // Use lookupInManifest for qualified name support (Issue #713)\n const entry = lookupInManifest(manifest, className);\n if (entry) {\n debugLog(\n `[manifest-loader] ✅ Found ${className} in external package ${pkg}`,\n );\n // Enrich entry with packageName from manifest if not already present\n if (!entry.packageName && manifest.packageName) {\n return { ...entry, packageName: manifest.packageName };\n }\n return entry;\n }\n }\n\n debugLog(`[manifest-loader] ❌ ${className} not found in any manifest`);\n return undefined;\n}\n\n// Note: manifestCollisions is now accessed via globalThis helper function\n// getManifestCollisionsMap()\n\n/**\n * Look up a manifest entry in a manifest's objects map.\n * Supports both qualified names and simple class names.\n *\n * Lookup order:\n * 1. Direct qualified name lookup (e.g., \"@happyvertical/smrt-core:Product\")\n * 2. Constructed qualified name (packageName + className)\n * 3. Search by className property (case-insensitive)\n *\n * @param manifest - The manifest to search in\n * @param nameOrQualified - Either a qualified name or simple class name\n * @returns ManifestEntry or undefined if not found\n */\nexport function lookupInManifest(\n manifest: SmartObjectManifest,\n nameOrQualified: string,\n): ManifestEntry | undefined {\n // 1. First try direct lookup (handles both qualified names and exact matches)\n if (manifest.objects[nameOrQualified]) {\n return manifest.objects[nameOrQualified];\n }\n\n // 2. Get the className index for O(1) lookups (instead of O(n) iteration)\n // This is the key optimization for issue #729\n const classNameIndex = getClassNameIndex(manifest);\n\n // 3. If input is a qualified name, extract className and use index\n if (isQualifiedName(nameOrQualified)) {\n const { className } = parseQualifiedName(nameOrQualified);\n return classNameIndex.get(className.toLowerCase());\n }\n\n // 4. For simple class names, try constructing qualified name if manifest has packageName\n if (manifest.packageName) {\n const qualifiedKey = createQualifiedName(\n manifest.packageName,\n nameOrQualified,\n );\n if (manifest.objects[qualifiedKey]) {\n return manifest.objects[qualifiedKey];\n }\n }\n\n // 5. Use index for O(1) className lookup (instead of O(n) iteration)\n return classNameIndex.get(nameOrQualified.toLowerCase());\n}\n\n/**\n * Find a manifest entry by qualified name across all loaded manifests.\n *\n * @param qualifiedName - The fully qualified class name (e.g., \"@happyvertical/smrt-core:Product\")\n * @returns ManifestEntry or undefined if not found\n */\nexport function findManifestEntryByQualifiedName(\n qualifiedName: string,\n): ManifestEntry | undefined {\n if (!isQualifiedName(qualifiedName)) {\n return undefined;\n }\n\n const { packageName } = parseQualifiedName(qualifiedName);\n\n // Check if we have the package's manifest cached\n const manifest = getManifestCacheMap().get(packageName);\n if (manifest) {\n // Try qualified name first, then fallback to simple names\n return lookupInManifest(manifest, qualifiedName);\n }\n\n // Check static manifest\n const staticManifestData = getStaticManifest();\n if (staticManifestData.packageName === packageName) {\n return lookupInManifest(staticManifestData, qualifiedName);\n }\n\n // Check test manifest (if in test environment)\n if (isTestEnvironment()) {\n const testManifest = getTestManifest();\n if (testManifest?.packageName === packageName) {\n return lookupInManifest(testManifest, qualifiedName);\n }\n\n // Check local test manifest\n const localTest = getLocalTestManifestCache();\n if (localTest?.packageName === packageName) {\n return lookupInManifest(localTest, qualifiedName);\n }\n }\n\n return undefined;\n}\n\n/**\n * Discover manifest entry asynchronously (includes external package loading)\n *\n * Search order:\n * 1. External package manifest (for constructor's package) - PRIORITIZED\n * 2. testManifest (for test classes)\n * 3. staticManifest (for core framework classes)\n * 4. Cached external manifests\n *\n * This function now detects and reports class name collisions across packages.\n *\n * @param ctor - Class constructor\n * @param className - Class name (for lookup)\n * @returns ManifestEntry or undefined if not found\n * @throws {Error} If class name collision detected across different packages\n */\nexport async function discoverManifestEntry(\n ctor: SmrtObjectConstructor,\n className: string,\n): Promise<ManifestEntry | undefined> {\n // ✅ FAST PATH: O(1) constructor-based lookup for already-registered classes\n // Skip manifest scanning if we already know this constructor's qualified name via WeakMap\n // This provides instant resolution and prevents collisions (each constructor is unique in memory)\n if (!(ctor as { _isManifestStub?: boolean })._isManifestStub) {\n const registered = ObjectRegistry.getClassByConstructor(ctor);\n if (\n registered?.qualifiedName &&\n isQualifiedName(registered.qualifiedName)\n ) {\n // Parse package name from qualified name (format: \"@package/name:ClassName\")\n const { packageName } = parseQualifiedName(registered.qualifiedName);\n\n const cachedManifest = getManifestCacheMap().get(packageName);\n if (cachedManifest) {\n const cachedEntry = lookupInManifest(\n cachedManifest,\n registered.qualifiedName,\n );\n if (cachedEntry) {\n return !cachedEntry.packageName && cachedManifest.packageName\n ? { ...cachedEntry, packageName: cachedManifest.packageName }\n : cachedEntry;\n }\n }\n\n // Load the manifest for this specific package before trusting any\n // existing runtime field metadata. Imported external classes can be\n // registered with only a partial field set until their manifest is\n // hydrated, which is exactly what happens with STI parents like Event.\n const manifest = await loadExternalManifest(packageName, {\n warn: registered.fields.size === 0,\n });\n if (manifest) {\n // Look up the entry using the qualified name (exact match)\n const entry = lookupInManifest(manifest, registered.qualifiedName);\n if (entry) {\n // Enrich entry with package name if missing\n return !entry.packageName && manifest.packageName\n ? { ...entry, packageName: manifest.packageName }\n : entry;\n }\n }\n\n // Source-registered classes with explicit field metadata do not need a\n // second manifest probe from fallback discovery when the package did not\n // resolve to a manifest. This keeps workspace/dev runtimes from spamming\n // missing-dist-manifest warnings for packages that are already fully\n // usable from source.\n if (registered.fields.size > 0) {\n return undefined;\n }\n }\n }\n\n // FALLBACK: Original manifest scanning logic for:\n // - First-time registration (WeakMap not populated yet)\n // - Manifest stubs (not in WeakMap)\n // - Undecorated classes (never registered)\n const name = className.toLowerCase();\n const constructorPackage = getPackageName(ctor);\n\n // Track all manifest sources that define this class\n const foundEntries: Array<{\n entry: ManifestEntry;\n packageName: string;\n filePath?: string;\n manifestSource: string;\n }> = [];\n\n // Build qualified name for lookup if we have package context\n const qualifiedName = constructorPackage\n ? createQualifiedName(constructorPackage, className)\n : undefined;\n\n // 2. Check localTestManifest first (domain package test classes) - ONLY in test environment\n // Do this BEFORE loading external manifest to avoid duplicate loading\n let localEntry: SmartObjectDefinition | undefined;\n if (isTestEnvironment()) {\n if (getLocalTestManifestCache() === undefined) {\n loadLocalTestManifestSync();\n }\n const localManifest = getLocalTestManifestCache();\n if (localManifest) {\n // Use lookupInManifest for consistent qualified name handling\n localEntry = lookupInManifest(localManifest, qualifiedName || className);\n if (localEntry) {\n foundEntries.push({\n entry: localEntry,\n packageName: localManifest.packageName || 'local-test',\n filePath: localEntry.filePath,\n manifestSource: 'local test manifest',\n });\n }\n }\n }\n\n // 1. PRIORITY: Try loading from the constructor's package first\n // BUT skip if it's the same package as the local test manifest to avoid collisions\n if (constructorPackage) {\n const skipExternal =\n getLocalTestManifestCache()?.packageName &&\n constructorPackage === getLocalTestManifestCache()?.packageName;\n\n if (!skipExternal) {\n const manifest = await loadExternalManifest(constructorPackage);\n if (manifest) {\n // Use lookupInManifest for consistent qualified name handling\n const entry = lookupInManifest(manifest, qualifiedName || className);\n if (entry) {\n const enrichedEntry =\n !entry.packageName && manifest.packageName\n ? { ...entry, packageName: manifest.packageName }\n : entry;\n\n foundEntries.push({\n entry: enrichedEntry,\n packageName: manifest.packageName || constructorPackage,\n filePath: entry.filePath,\n manifestSource: `${manifest.packageName || constructorPackage}/manifest.json`,\n });\n }\n }\n }\n }\n\n // 3. Check testManifest (core test classes) - ONLY in test environment\n // Skip if we already loaded a local test manifest (avoids duplicate entries from same package)\n if (isTestEnvironment() && (!getLocalTestManifestCache() || !localEntry)) {\n const manifest = getTestManifest();\n if (manifest) {\n // Use lookupInManifest for consistent qualified name handling\n const testEntry = lookupInManifest(manifest, qualifiedName || className);\n if (testEntry) {\n foundEntries.push({\n entry: testEntry,\n packageName: manifest.packageName || '@happyvertical/smrt-core',\n filePath: testEntry.filePath,\n manifestSource: '@happyvertical/smrt-core test manifest',\n });\n }\n }\n }\n\n // 4. Check staticManifest (core framework classes)\n const staticManifestData = getStaticManifest();\n // Use lookupInManifest for consistent qualified name handling\n const staticEntry = lookupInManifest(\n staticManifestData,\n qualifiedName || className,\n );\n if (staticEntry) {\n foundEntries.push({\n entry: staticEntry,\n packageName: staticManifestData.packageName || '@happyvertical/smrt-core',\n filePath: staticEntry.filePath,\n manifestSource: '@happyvertical/smrt-core static manifest',\n });\n }\n\n // 5. Check other cached external manifests\n for (const [cachedPkgName, manifest] of getManifestCacheMap().entries()) {\n // Skip if this is the constructor's package (already checked above)\n if (cachedPkgName === constructorPackage) {\n continue;\n }\n\n // Use lookupInManifest for consistent qualified name handling\n const entry = lookupInManifest(manifest, qualifiedName || className);\n if (entry) {\n foundEntries.push({\n entry:\n !entry.packageName && manifest.packageName\n ? { ...entry, packageName: manifest.packageName }\n : entry,\n packageName: manifest.packageName || cachedPkgName,\n filePath: entry.filePath,\n manifestSource: `${manifest.packageName || cachedPkgName}/manifest.json`,\n });\n }\n }\n\n // Deduplicate entries that reference the same source file.\n // Consumer manifests (e.g. smrt-users, dashboard) re-export classes from\n // upstream packages (e.g. smrt-profiles). These appear in multiple manifests\n // but point to the same filePath — they are NOT real collisions.\n if (foundEntries.length > 1) {\n const uniqueByFile = new Map<string, (typeof foundEntries)[0]>();\n for (const entry of foundEntries) {\n // Normalize file paths so the same source file with different absolute\n // prefixes (local dev vs CI build) is recognized as identical.\n // Extract the relative path from the last \"packages/\" segment onward.\n let key = entry.filePath || `${entry.packageName}:${className}`;\n if (entry.filePath) {\n const pkgIdx = entry.filePath.lastIndexOf('packages/');\n if (pkgIdx !== -1) {\n key = entry.filePath.slice(pkgIdx);\n }\n }\n if (!uniqueByFile.has(key)) {\n uniqueByFile.set(key, entry);\n }\n }\n\n if (uniqueByFile.size === 1) {\n // All entries point to the same source file — not a real collision.\n // Use the first (highest priority) entry.\n foundEntries.splice(1);\n } else if (uniqueByFile.size > 1) {\n // True collision: different source files define the same class name\n const collisionInfo = foundEntries.map(\n (f) =>\n ` - ${f.packageName} (${f.filePath || 'unknown file'}) from ${f.manifestSource}`,\n );\n\n // Store collision info for reporting\n getManifestCollisionsMap().set(\n className,\n foundEntries.map((f) => ({\n packageName: f.packageName,\n filePath: f.filePath,\n manifestSource: f.manifestSource,\n })),\n );\n\n // Throw error on collision\n throw new Error(\n `SMRT Class Name Collision Detected: \"${className}\"\\n\\n` +\n `This class is defined in multiple packages:\\n${collisionInfo.join('\\n')}\\n\\n` +\n `The collision will cause the wrong field definitions to be used,\\n` +\n `leading to properties not being initialized correctly.\\n\\n` +\n `To fix:\\n` +\n ` 1. Use unique class names across packages (e.g., ${className}_${constructorPackage?.split('/').pop() || 'Unique'})\\n` +\n ` 2. Or use @smrt({ name: 'unique_name' }) to override the registration name\\n` +\n ` 3. Remove test classes with conflicting names from production manifests\\n\\n` +\n `If this is a test class collision, ensure test manifests are not included in production builds.`,\n );\n }\n }\n\n // Return the found entry (priority given to constructor's package)\n if (foundEntries.length === 1) {\n return foundEntries[0].entry;\n }\n\n return undefined;\n}\n\n/**\n * Get all detected manifest collisions\n *\n * @returns Map of class names to array of collision info\n */\nexport function getManifestCollisions(): Map<\n string,\n Array<{ packageName: string; filePath?: string; manifestSource: string }>\n> {\n return new Map(getManifestCollisionsMap());\n}\n\n/**\n * Clear manifest cache\n *\n * Useful for testing or when packages are updated at runtime.\n */\nexport function clearManifestCache(): void {\n // Reset all cached manifest state so tests/dev tooling can force a full\n // rediscovery pass on the next lookup.\n setStaticManifestCache(undefined);\n setStaticManifestLoadAttempted(false);\n setTestManifestCache(undefined);\n setTestManifestLoadAttempted(false);\n setLocalTestManifestCache(undefined);\n getManifestCacheMap().clear();\n getManifestCollisionsMap().clear();\n getSTISiblingCache().clear();\n}\n\n/**\n * Get all loaded manifests\n *\n * Returns a copy of the manifest cache for inspection.\n *\n * @returns Array of [packageName, manifest] entries\n */\nexport function getLoadedManifests(): Array<[string, Manifest]> {\n return Array.from(getManifestCacheMap().entries());\n}\n\n/**\n * Discover all STI sibling classes that share the same collection (table)\n *\n * This is critical for STI schema merging: when one subtype is accessed,\n * we need to discover ALL subtypes sharing the same table so that the\n * database adapter receives a complete schema with all columns.\n *\n * Scans all available manifests:\n * 1. Local test manifest (for test classes)\n * 2. Test manifest (for core test classes)\n * 3. Static manifest (for core framework classes)\n * 4. Cached external manifests\n * 5. SMRT dependencies from local test manifest\n *\n * @param collection - The collection/table name to find siblings for\n * @returns Array of manifest entries that share the same collection\n *\n * Known limitation (#1579, won't-fix): the per-collection result is cached on\n * `globalThis.__smrtSTISiblingCache` after the first call and is not invalidated\n * when a manifest is registered *afterwards* and isn't reachable via\n * `smrtDependencies` (the Release-A self-register path). A sibling registered\n * after first discovery for a given collection can therefore be missed until the\n * cache is cleared. Accepted as low-risk: STI manifests are registered at\n * startup before query traffic, and the few self-register flows that could hit\n * it can reset the cache. Fixing it properly means a registration→cache\n * invalidation hook, which is disproportionate to the exposure.\n */\nexport function discoverSTISiblingsSync(\n collection: string,\n): Array<{ className: string; entry: ManifestEntry; packageName?: string }> {\n // Check cache first to avoid repeated scans (fixes #644)\n const cache = getSTISiblingCache();\n const cached = cache.get(collection);\n if (cached !== undefined) {\n return cached;\n }\n\n const siblings: Array<{\n className: string;\n entry: ManifestEntry;\n packageName?: string;\n }> = [];\n\n // Track already-found class names to avoid duplicates (case-insensitive)\n // Use lowercase keys to prevent both 'praeco' and 'Praeco' from being added\n const foundClasses = new Set<string>();\n\n debugLog(\n `[manifest-loader] discoverSTISiblingsSync called for collection: ${collection}`,\n );\n\n // Helper to add entries from a manifest\n const addFromManifest = (\n manifest: Manifest | null | undefined,\n source: string,\n ) => {\n if (!manifest?.objects) return;\n\n for (const [key, entry] of Object.entries(manifest.objects) as [\n string,\n ManifestEntry,\n ][]) {\n // Check if this entry uses the same collection (table)\n if (entry.collection === collection) {\n const className = entry.className || key;\n // Use case-insensitive check to prevent registering both 'praeco' and 'Praeco'\n const lowerClassName = className.toLowerCase();\n if (!foundClasses.has(lowerClassName)) {\n foundClasses.add(lowerClassName);\n siblings.push({\n className,\n entry,\n packageName: entry.packageName || manifest.packageName,\n });\n debugLog(\n `[manifest-loader] Found STI sibling: ${className} (collection: ${collection}) from ${source}`,\n );\n }\n }\n }\n };\n\n // 1. Check local test manifest (domain package test classes)\n if (isTestEnvironment()) {\n if (!getLocalTestManifestCache()) {\n loadLocalTestManifestSync();\n }\n addFromManifest(getLocalTestManifestCache(), 'localTestManifest');\n }\n\n // 2. Check test manifest (core test classes)\n const testManifestData = isTestEnvironment() ? getTestManifest() : null;\n if (testManifestData) {\n addFromManifest(testManifestData, 'testManifest');\n }\n\n // 3. Check static manifest (core framework classes)\n const staticManifestData = getStaticManifest();\n addFromManifest(staticManifestData, 'staticManifest');\n\n // 4. Check cached external manifests\n for (const [pkgName, manifest] of getManifestCacheMap().entries()) {\n addFromManifest(manifest, `manifestCache:${pkgName}`);\n }\n\n // 5. Try loading from SMRT dependencies from ALL manifests (not just localTestManifest)\n // This ensures production environments also discover STI siblings\n const pendingDependencies = collectDeclaredSmrtDependencies([\n getLocalTestManifestCache(),\n isTestEnvironment() ? testManifestData : null,\n staticManifestData,\n ...getManifestCacheMap().values(),\n ]);\n const visitedDependencies = new Set<string>();\n\n debugLog(\n `[manifest-loader] Scanning ${pendingDependencies.length} SMRT dependencies for STI siblings: ${pendingDependencies.join(', ')}`,\n );\n\n while (pendingDependencies.length > 0) {\n const pkg = pendingDependencies.shift();\n if (!pkg || visitedDependencies.has(pkg)) {\n continue;\n }\n\n visitedDependencies.add(pkg);\n\n const manifest = loadExternalManifestSync(pkg);\n if (manifest) {\n addFromManifest(manifest, `smrtDependency:${pkg}`);\n\n for (const dependency of manifest.smrtDependencies || []) {\n if (!visitedDependencies.has(dependency)) {\n pendingDependencies.push(dependency);\n }\n }\n }\n }\n\n debugLog(\n `[manifest-loader] discoverSTISiblingsSync found ${siblings.length} siblings for collection: ${collection}`,\n );\n\n // Cache the results for future calls (fixes #644)\n cache.set(collection, siblings);\n\n return siblings;\n}\n"],"names":["getStaticManifestCacheFromStore","getTestManifestCacheFromStore","getLocalTestManifestCacheFromStore","getManifestCacheFromStore","require","isTestEnvFromStore","error","stack","stackLines"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"static-manifest.d.ts","sourceRoot":"","sources":["../../src/manifest/static-manifest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,eAAO,MAAM,cAAc,EAAE,mBAszCnB,CAAC;AAEX,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"static-manifest.d.ts","sourceRoot":"","sources":["../../src/manifest/static-manifest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,eAAO,MAAM,cAAc,EAAE,mBAy0CnB,CAAC;AAEX,eAAe,cAAc,CAAC"}
@@ -1,8 +1,8 @@
1
1
  const staticManifest = {
2
2
  "version": "1.0.0",
3
- "timestamp": 1782522843119,
3
+ "timestamp": 1782792357137,
4
4
  "packageName": "@happyvertical/smrt-core",
5
- "packageVersion": "0.36.8",
5
+ "packageVersion": "0.37.1",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-core:SmrtClass": {
8
8
  "name": "smrtclass",
@@ -241,7 +241,7 @@ const staticManifest = {
241
241
  "parameters": [
242
242
  {
243
243
  "name": "filter",
244
- "type": "string | Record<string, any>",
244
+ "type": "string | SmrtWhereClause<ModelType>",
245
245
  "optional": false
246
246
  },
247
247
  {
@@ -274,12 +274,12 @@ const staticManifest = {
274
274
  "parameters": [
275
275
  {
276
276
  "name": "data",
277
- "type": "any",
277
+ "type": "Record<string>",
278
278
  "optional": false
279
279
  },
280
280
  {
281
281
  "name": "defaults",
282
- "type": "any",
282
+ "type": "Record<string>",
283
283
  "optional": true
284
284
  }
285
285
  ],
@@ -293,16 +293,16 @@ const staticManifest = {
293
293
  "parameters": [
294
294
  {
295
295
  "name": "existing",
296
- "type": "Record<string, any>",
296
+ "type": "SmrtObject | Record<string>",
297
297
  "optional": false
298
298
  },
299
299
  {
300
300
  "name": "data",
301
- "type": "Record<string, any>",
301
+ "type": "Record<string>",
302
302
  "optional": false
303
303
  }
304
304
  ],
305
- "returnType": "Promise<Record<string, any> | null>",
305
+ "returnType": "Promise<Record<string> | null>",
306
306
  "isStatic": false,
307
307
  "isPublic": true
308
308
  },
@@ -310,7 +310,7 @@ const staticManifest = {
310
310
  "name": "getFields",
311
311
  "async": true,
312
312
  "parameters": [],
313
- "returnType": "any",
313
+ "returnType": "Promise<Record<string, CollectionFieldDefinition>>",
314
314
  "isStatic": false,
315
315
  "isPublic": true
316
316
  },
@@ -318,7 +318,7 @@ const staticManifest = {
318
318
  "name": "getFieldsSync",
319
319
  "async": false,
320
320
  "parameters": [],
321
- "returnType": "Record<string, any>",
321
+ "returnType": "Record<string, CollectionFieldDefinition>",
322
322
  "isStatic": false,
323
323
  "isPublic": true
324
324
  },
@@ -385,7 +385,7 @@ const staticManifest = {
385
385
  },
386
386
  {
387
387
  "name": "params",
388
- "type": "any[]",
388
+ "type": "any",
389
389
  "optional": true
390
390
  },
391
391
  {
@@ -422,7 +422,7 @@ const staticManifest = {
422
422
  "optional": false
423
423
  }
424
424
  ],
425
- "returnType": "Promise<any | null>",
425
+ "returnType": "Promise",
426
426
  "isStatic": false,
427
427
  "isPublic": true
428
428
  },
@@ -436,7 +436,7 @@ const staticManifest = {
436
436
  "optional": true
437
437
  }
438
438
  ],
439
- "returnType": "Promise<Map<string, any>>",
439
+ "returnType": "Promise<Map<string>>",
440
440
  "isStatic": false,
441
441
  "isPublic": true
442
442
  },
@@ -839,7 +839,7 @@ const staticManifest = {
839
839
  "parameters": [
840
840
  {
841
841
  "name": "data",
842
- "type": "any",
842
+ "type": "Record<string>",
843
843
  "optional": false
844
844
  }
845
845
  ],
@@ -851,7 +851,7 @@ const staticManifest = {
851
851
  "name": "getFields",
852
852
  "async": true,
853
853
  "parameters": [],
854
- "returnType": "any",
854
+ "returnType": "Promise<any>",
855
855
  "isStatic": false,
856
856
  "isPublic": true
857
857
  },
@@ -960,7 +960,7 @@ const staticManifest = {
960
960
  },
961
961
  {
962
962
  "name": "options",
963
- "type": "any",
963
+ "type": "AiOperationOptions",
964
964
  "optional": true
965
965
  }
966
966
  ],
@@ -979,7 +979,7 @@ const staticManifest = {
979
979
  },
980
980
  {
981
981
  "name": "options",
982
- "type": "any",
982
+ "type": "AiOperationOptions",
983
983
  "optional": true
984
984
  }
985
985
  ],
@@ -993,7 +993,7 @@ const staticManifest = {
993
993
  "parameters": [
994
994
  {
995
995
  "name": "options",
996
- "type": "any",
996
+ "type": "AiOperationOptions",
997
997
  "optional": true
998
998
  }
999
999
  ],
@@ -1023,6 +1023,25 @@ const staticManifest = {
1023
1023
  "isStatic": false,
1024
1024
  "isPublic": true
1025
1025
  },
1026
+ "_setLoadedRelationship": {
1027
+ "name": "_setLoadedRelationship",
1028
+ "async": false,
1029
+ "parameters": [
1030
+ {
1031
+ "name": "fieldName",
1032
+ "type": "string",
1033
+ "optional": false
1034
+ },
1035
+ {
1036
+ "name": "value",
1037
+ "type": "any",
1038
+ "optional": false
1039
+ }
1040
+ ],
1041
+ "returnType": "void",
1042
+ "isStatic": false,
1043
+ "isPublic": true
1044
+ },
1026
1045
  "loadRelated": {
1027
1046
  "name": "loadRelated",
1028
1047
  "async": true,
@@ -1126,7 +1145,7 @@ const staticManifest = {
1126
1145
  "optional": false
1127
1146
  }
1128
1147
  ],
1129
- "returnType": "Promise<any | null>",
1148
+ "returnType": "Promise",
1130
1149
  "isStatic": false,
1131
1150
  "isPublic": true
1132
1151
  },
@@ -1140,7 +1159,7 @@ const staticManifest = {
1140
1159
  "optional": true
1141
1160
  }
1142
1161
  ],
1143
- "returnType": "Promise<Map<string, any>>",
1162
+ "returnType": "Promise<Map<string>>",
1144
1163
  "isStatic": false,
1145
1164
  "isPublic": true
1146
1165
  },