@happyvertical/smrt-core 0.36.4 → 0.36.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sources":["../../src/manifest/store.ts"],"sourcesContent":["/**\n * Leaf manifest storage + pure fs/URL helpers.\n *\n * This module has **no dependency on ObjectRegistry, registry.ts, or\n * class-registration.ts**. It owns the globalThis manifest caches and the\n * filesystem helpers that resolve and read manifest.json files from the\n * workspace, installed node_modules, and smrt-core's own bundle.\n *\n * Breaking the cycle: Before this module existed, `registry.ts` and\n * `manifest-loader.ts` both maintained their own copies of these helpers\n * (`registry.ts` had its own because `registerPackageManifest` needed them\n * and could not import `manifest-loader.ts` due to a module cycle —\n * `registry.ts → class-registration.ts → manifest-loader.ts → registry.ts`).\n * Centralizing them here lets both files import from a leaf, so the cycle\n * goes away and Release B's `ManifestSource` abstraction can live above\n * this leaf without re-creating it.\n *\n * @see https://github.com/happyvertical/smrt/issues/1133\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { recordRegistryDiagnostic } from '../registry/diagnostics.js';\nimport type {\n SmartObjectDefinition,\n SmartObjectManifest,\n} from '../scanner/types.js';\nimport type { ColumnDefinition } from '../schema/types.js';\nimport {\n createQualifiedName,\n isQualifiedName,\n parseQualifiedName,\n} from '../utils/qualified-names.js';\n\nconst logger = createLogger({ level: 'info' });\n\nexport type ManifestLoadOptions = {\n warn?: boolean;\n};\n\n// ── Runtime environment detection ────────────────────────────────────────\n\n/**\n * Detect whether we're running inside a test runner. Test manifests must\n * never load in production to avoid test classes colliding with real ones.\n */\nexport function isTestEnvironment(): boolean {\n return (\n process.env.NODE_ENV === 'test' ||\n process.env.VITEST === 'true' ||\n process.env.JEST_WORKER_ID !== undefined\n );\n}\n\n/**\n * Best-effort detection of the current package under test.\n *\n * In workspace consumers, `process.cwd()` points at the consuming app/package,\n * while in smrt-core's own tests it points at `packages/core`. We use that\n * distinction to keep smrt-core's internal test manifest scoped to its own\n * test suite instead of leaking those fixtures into every consumer test run.\n */\nexport function getCurrentPackageName(): string | null {\n const explicitPackageName = process.env.npm_package_name;\n if (explicitPackageName) {\n return explicitPackageName;\n }\n\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n let currentDir = process.cwd();\n\n while (true) {\n const packageJsonPath = builtins.path.join(currentDir, 'package.json');\n if (builtins.fs.existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(\n builtins.fs.readFileSync(packageJsonPath, 'utf-8'),\n ) as { name?: string };\n return packageJson.name ?? null;\n } catch {\n return null;\n }\n }\n\n const parentDir = builtins.path.dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n}\n\n/**\n * smrt-core's committed test manifest is for smrt-core's own tests only.\n * Consumer packages should expose only their local test manifest plus real\n * published manifests from dependencies.\n */\nexport function shouldLoadCoreTestManifest(): boolean {\n if (!isTestEnvironment()) {\n return false;\n }\n\n const currentPackageName = getCurrentPackageName();\n if (currentPackageName) {\n return currentPackageName === '@happyvertical/smrt-core';\n }\n\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return false;\n }\n\n const moduleDir = builtins.path.dirname(\n builtins.url.fileURLToPath(import.meta.url),\n );\n const workspaceRoot = findWorkspaceRootSync(moduleDir);\n if (!workspaceRoot) {\n return false;\n }\n\n const corePackageDir = builtins.path.join(workspaceRoot, 'packages', 'core');\n const relative = builtins.path.relative(corePackageDir, process.cwd());\n return (\n relative === '' ||\n (!relative.startsWith('..') && !builtins.path.isAbsolute(relative))\n );\n}\n\n// ── Node builtins access ─────────────────────────────────────────────────\n\n/**\n * Resolve Node's built-in `fs`/`path`/`url` modules without a static import.\n *\n * `process.getBuiltinModule()` is a Node 22+ API that returns the live\n * built-in without going through the module loader. This avoids Vite's\n * static-import analysis flagging these builtins and simulated\n * \"externalized for browser\" warnings in bundled browser builds.\n */\nexport function getNodeBuiltins() {\n const getBuiltinModule = (\n process as typeof process & {\n getBuiltinModule?: (id: string) => unknown;\n }\n ).getBuiltinModule;\n if (typeof getBuiltinModule !== 'function') {\n return null;\n }\n\n const fs = getBuiltinModule('node:fs') as\n | typeof import('node:fs')\n | undefined;\n const path = getBuiltinModule('node:path') as\n | typeof import('node:path')\n | undefined;\n const url = getBuiltinModule('node:url') as\n | typeof import('node:url')\n | undefined;\n\n if (!fs || !path || !url) {\n return null;\n }\n\n return { fs, path, url };\n}\n\n// ── globalThis cache accessors ───────────────────────────────────────────\n\ntype ManifestGlobals = typeof globalThis & {\n __smrtManifestStatic?: SmartObjectManifest | null;\n __smrtManifestStaticLoadAttempted?: boolean;\n __smrtManifestTest?: SmartObjectManifest | null;\n __smrtManifestLocalTest?: SmartObjectManifest | null;\n __smrtManifestCache?: Map<string, SmartObjectManifest>;\n};\n\nfunction getManifestGlobals(): ManifestGlobals {\n return globalThis as ManifestGlobals;\n}\n\n/**\n * Return the mutable external-manifest cache, creating it if absent.\n *\n * Writers: `registerPackageManifest()` (Release A, each package's shim),\n * `loadExternalManifestSyncWithNode()`, `loadManifestFromPathSyncWithNode()`.\n * Readers: all discovery paths.\n */\nexport function getManifestCache(): Map<string, SmartObjectManifest> {\n const globals = getManifestGlobals();\n if (!globals.__smrtManifestCache) {\n globals.__smrtManifestCache = new Map();\n }\n return globals.__smrtManifestCache;\n}\n\n/** Read-only snapshot of the static manifest, if cached. */\nexport function getStaticManifestCache(): SmartObjectManifest | null {\n return getManifestGlobals().__smrtManifestStatic ?? null;\n}\n\n/** Read-only snapshot of the core test manifest, if cached. */\nexport function getTestManifestCache(): SmartObjectManifest | null {\n return getManifestGlobals().__smrtManifestTest ?? null;\n}\n\n/**\n * Read-only snapshot of the local (domain package) test manifest.\n *\n * Preserves the three-state semantics that `discoverManifestEntry()` relies\n * on: `undefined` means \"never attempted to load\" and triggers the lazy\n * loader; `null` means \"attempted but no local test manifest in this\n * package\"; a manifest object means \"loaded\". Do not collapse `undefined`\n * to `null` here — the async-discovery lazy-load path keys off the\n * distinction (see manifest-loader.ts:`if (getLocalTestManifestCache() === undefined) loadLocalTestManifestSync()`).\n */\nexport function getLocalTestManifestCache():\n | SmartObjectManifest\n | null\n | undefined {\n return getManifestGlobals().__smrtManifestLocalTest;\n}\n\n// ── Manifest shape helpers ───────────────────────────────────────────────\n\nexport function createEmptyStaticManifest(): SmartObjectManifest {\n return {\n version: '1.0.0',\n timestamp: Date.now(),\n objects: {},\n packageName: '@happyvertical/smrt-core',\n };\n}\n\n/**\n * Deep-clone a manifest's schema column map so downstream mutators don't\n * corrupt the cached manifest. Foreign-key descriptors get their own copy\n * because manifest-loader.ts and registerFromManifest() both splice them\n * into live schema entries.\n */\nexport function cloneManifestSchemaColumns(\n columns: Record<string, unknown> | undefined,\n): Record<string, ColumnDefinition> {\n return Object.fromEntries(\n Object.entries(columns || {}).map(([columnName, column]) => {\n const clonedColumn = {\n ...(column as ColumnDefinition & Record<string, unknown>),\n } as ColumnDefinition;\n const manifestDefault = (\n clonedColumn as ColumnDefinition & {\n default?: unknown;\n }\n ).default;\n\n if (\n clonedColumn.defaultValue === undefined &&\n manifestDefault !== undefined\n ) {\n clonedColumn.defaultValue = manifestDefault;\n }\n\n if (clonedColumn.foreignKey) {\n clonedColumn.foreignKey = { ...clonedColumn.foreignKey };\n }\n\n return [columnName, clonedColumn];\n }),\n ) as Record<string, ColumnDefinition>;\n}\n\n/**\n * Look up a class definition inside a single manifest.\n *\n * Tries qualified-key, simple-name, and lowercase-name lookups, then falls\n * back to iterating every entry in the manifest comparing lowered names.\n * This is the low-level primitive used by every sync discovery path.\n */\nexport function lookupCachedManifestEntry(\n manifest: SmartObjectManifest | null | undefined,\n className: string,\n): SmartObjectDefinition | undefined {\n if (!manifest?.objects) {\n return undefined;\n }\n\n const requestedQualifiedName = isQualifiedName(className)\n ? className\n : undefined;\n const requestedClassName = requestedQualifiedName\n ? parseQualifiedName(requestedQualifiedName).className\n : className;\n const lowerClassName = requestedClassName.toLowerCase();\n const packageName = manifest.packageName;\n const qualifiedKey =\n requestedQualifiedName ||\n (packageName\n ? createQualifiedName(packageName, requestedClassName)\n : undefined);\n\n return (\n (qualifiedKey ? manifest.objects[qualifiedKey] : undefined) ||\n manifest.objects[requestedClassName] ||\n manifest.objects[lowerClassName] ||\n Object.values(manifest.objects).find((entry) => {\n if (!entry) {\n return false;\n }\n\n if (entry.className?.toLowerCase() === lowerClassName) {\n return true;\n }\n\n return (\n requestedQualifiedName !== undefined &&\n packageName !== undefined &&\n createQualifiedName(packageName, entry.className || '') ===\n requestedQualifiedName\n );\n })\n );\n}\n\n// ── Filesystem helpers ───────────────────────────────────────────────────\n\nexport function findWorkspaceRootSync(startDir: string): string | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n let currentDir = startDir;\n\n while (true) {\n if (\n builtins.fs.existsSync(\n builtins.path.join(currentDir, 'pnpm-workspace.yaml'),\n )\n ) {\n return currentDir;\n }\n\n const parentDir = builtins.path.dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n}\n\nexport function resolveInstalledPackageJsonPathSync(\n packageName: string,\n): string | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n let currentDir = process.cwd();\n\n while (true) {\n const packageJsonPath = builtins.path.join(\n currentDir,\n 'node_modules',\n packageName,\n 'package.json',\n );\n\n if (builtins.fs.existsSync(packageJsonPath)) {\n return packageJsonPath;\n }\n\n const parentDir = builtins.path.dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n}\n\nexport function resolveWorkspacePackageJsonPathSync(\n packageName: string,\n): string | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n const workspaceRoot = findWorkspaceRootSync(process.cwd());\n if (!workspaceRoot) {\n return null;\n }\n\n const workspacePackagesDir = builtins.path.join(workspaceRoot, 'packages');\n if (!builtins.fs.existsSync(workspacePackagesDir)) {\n return null;\n }\n\n for (const packageDirName of builtins.fs.readdirSync(workspacePackagesDir)) {\n const packageJsonPath = builtins.path.join(\n workspacePackagesDir,\n packageDirName,\n 'package.json',\n );\n if (!builtins.fs.existsSync(packageJsonPath)) {\n continue;\n }\n\n try {\n const packageJson = JSON.parse(\n builtins.fs.readFileSync(packageJsonPath, 'utf-8'),\n ) as { name?: string };\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\nexport function resolveWorkspaceSourceManifestPathSync(\n packageDir: string,\n): string | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n const candidates = [\n builtins.path.join(packageDir, 'src', 'manifest', 'manifest.json'),\n builtins.path.join(packageDir, '.smrt', 'manifest.json'),\n ];\n\n for (const candidate of candidates) {\n if (builtins.fs.existsSync(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\nexport function resolveManifestExportPathSync(\n packageName: string,\n options: ManifestLoadOptions = {},\n): string | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n const shouldWarn = options.warn ?? true;\n const packageJsonPath =\n resolveInstalledPackageJsonPathSync(packageName) ||\n resolveWorkspacePackageJsonPathSync(packageName);\n\n if (!packageJsonPath) {\n return null;\n }\n\n const packageDir = builtins.path.dirname(packageJsonPath);\n const packageJson = JSON.parse(\n builtins.fs.readFileSync(packageJsonPath, 'utf-8'),\n ) as {\n exports?: Record<\n string,\n string | { default?: string; import?: string; require?: string }\n >;\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 recordRegistryDiagnostic(\n 'error',\n 'MANIFEST_EXPORT_INVALID',\n `Package ${packageName} has invalid manifest export configuration for ${exportKey}`,\n { packageName, exportKey },\n );\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 recordRegistryDiagnostic(\n 'error',\n 'MANIFEST_EXPORT_NOT_JSON',\n `Package ${packageName} must export a JSON manifest for ${exportKey}, received ${manifestRelativePath}`,\n { packageName, exportKey, manifestRelativePath },\n );\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 = builtins.path.join(packageDir, manifestRelativePath);\n if (builtins.fs.existsSync(manifestPath)) {\n return manifestPath;\n }\n\n const workspaceSourceManifest =\n resolveWorkspaceSourceManifestPathSync(packageDir);\n if (workspaceSourceManifest) {\n return workspaceSourceManifest;\n }\n\n recordRegistryDiagnostic(\n 'error',\n 'MANIFEST_EXPORT_NOT_FOUND',\n `Package ${packageName} declares manifest export ${manifestRelativePath}, but no manifest file was found.`,\n { packageName, exportKey, manifestRelativePath },\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\n// ── Manifest reading (seeds caches) ──────────────────────────────────────\n\n/**\n * Load smrt-core's own bundled manifest from disk, caching in\n * `__smrtManifestStatic`. Resolves against this module's own `import.meta.url`\n * so paths work whether the code is running from `dist/` or `src/`.\n */\nexport function loadStaticManifestSyncWithNode(): SmartObjectManifest | null {\n const globals = getManifestGlobals();\n\n if (globals.__smrtManifestStatic !== undefined) {\n return globals.__smrtManifestStatic ?? null;\n }\n\n const builtins = getNodeBuiltins();\n globals.__smrtManifestStaticLoadAttempted = true;\n if (!builtins) {\n const fallbackManifest = createEmptyStaticManifest();\n globals.__smrtManifestStatic = fallbackManifest;\n return fallbackManifest;\n }\n\n // store.ts lives at src/manifest/store.ts (source) → dist/manifest/store.js\n // (compiled). In src, the static manifest is a sibling JSON; in dist, it is\n // the package's dist/manifest.json one level up.\n const candidates = import.meta.url.endsWith('.ts')\n ? [\n new URL('./static-manifest.json', import.meta.url),\n new URL('../../dist/manifest.json', import.meta.url),\n ]\n : [new URL('../manifest.json', import.meta.url)];\n\n for (const candidate of candidates) {\n try {\n if (!builtins.fs.existsSync(candidate)) {\n continue;\n }\n\n const manifest = JSON.parse(\n builtins.fs.readFileSync(candidate, 'utf-8'),\n ) as SmartObjectManifest;\n\n if (!manifest.objects || typeof manifest.objects !== 'object') {\n continue;\n }\n\n const cachedManifest = manifest.packageName\n ? manifest\n : { ...manifest, packageName: '@happyvertical/smrt-core' };\n globals.__smrtManifestStatic = cachedManifest;\n return cachedManifest;\n } catch {\n // Try the next candidate and fall back to the empty manifest if needed.\n }\n }\n\n const fallbackManifest = createEmptyStaticManifest();\n globals.__smrtManifestStatic = fallbackManifest;\n return fallbackManifest;\n}\n\n/**\n * Load a package's published manifest by package name, caching in\n * `__smrtManifestCache` under the package key. Returns null on miss or\n * invalid shape; records a diagnostic instead of throwing.\n */\nexport function loadExternalManifestSyncWithNode(\n packageName: string,\n options: ManifestLoadOptions = {},\n): SmartObjectManifest | null {\n const cache = getManifestCache();\n\n if (cache.has(packageName)) {\n return cache.get(packageName) || null;\n }\n\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n const manifestPath = resolveManifestExportPathSync(packageName, options);\n if (!manifestPath) {\n return null;\n }\n\n try {\n const manifest = JSON.parse(\n builtins.fs.readFileSync(manifestPath, 'utf-8'),\n ) as SmartObjectManifest;\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 cache.set(packageName, cachedManifest);\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\n/**\n * Load a manifest from an explicit filesystem path, caching in\n * `__smrtManifestCache` under the manifest's packageName (or the path as a\n * fallback key). Used by `loadAllManifests({ manifestPaths })` in registry.ts\n * and by the Release B `ExplicitPathsManifestSource`.\n */\nexport function loadManifestFromPathSyncWithNode(\n manifestPath: string,\n): SmartObjectManifest | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n try {\n const manifest = JSON.parse(\n builtins.fs.readFileSync(manifestPath, 'utf-8'),\n ) as SmartObjectManifest;\n\n if (!manifest.objects || typeof manifest.objects !== 'object') {\n logger.warn(`Invalid manifest structure at ${manifestPath}`);\n return null;\n }\n\n getManifestCache().set(manifest.packageName || manifestPath, manifest);\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 * Synchronous lookup across every cached manifest source, in priority order.\n *\n * Matches the historical order from manifest-loader.ts and registry.ts:\n * local test → core test → static (smrt-core bundled) → external cache.\n * The Release B `CompositeManifestSource` wraps the same priority behind a\n * higher-level abstraction.\n */\nexport function discoverCachedManifestSync(\n className: string,\n): SmartObjectDefinition | undefined {\n const manifests: Array<SmartObjectManifest | null | undefined> = [\n getLocalTestManifestCache(),\n getTestManifestCache(),\n loadStaticManifestSyncWithNode(),\n ...getManifestCache().values(),\n ];\n\n for (const manifest of manifests) {\n const entry = lookupCachedManifestEntry(manifest, className);\n if (entry) {\n return entry;\n }\n }\n\n return undefined;\n}\n"],"names":["fallbackManifest"],"mappings":"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"}
1
+ {"version":3,"file":"store.js","sources":["../../src/manifest/store.ts"],"sourcesContent":["/**\n * Leaf manifest storage + pure fs/URL helpers.\n *\n * This module has **no dependency on ObjectRegistry, registry.ts, or\n * class-registration.ts**. It owns the globalThis manifest caches and the\n * filesystem helpers that resolve and read manifest.json files from the\n * workspace, installed node_modules, and smrt-core's own bundle.\n *\n * Breaking the cycle: Before this module existed, `registry.ts` and\n * `manifest-loader.ts` both maintained their own copies of these helpers\n * (`registry.ts` had its own because `registerPackageManifest` needed them\n * and could not import `manifest-loader.ts` due to a module cycle —\n * `registry.ts → class-registration.ts → manifest-loader.ts → registry.ts`).\n * Centralizing them here lets both files import from a leaf, so the cycle\n * goes away and Release B's `ManifestSource` abstraction can live above\n * this leaf without re-creating it.\n *\n * @see https://github.com/happyvertical/smrt/issues/1133\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { recordRegistryDiagnostic } from '../registry/diagnostics.js';\nimport type {\n SmartObjectDefinition,\n SmartObjectManifest,\n} from '../scanner/types.js';\nimport type { ColumnDefinition } from '../schema/types.js';\nimport {\n createQualifiedName,\n isQualifiedName,\n parseQualifiedName,\n} from '../utils/qualified-names.js';\n\nconst logger = createLogger({ level: 'info' });\n\nexport type ManifestLoadOptions = {\n warn?: boolean;\n};\n\n// ── Runtime environment detection ────────────────────────────────────────\n\n/**\n * Detect whether we're running inside a test runner. Test manifests must\n * never load in production to avoid test classes colliding with real ones.\n */\nexport function isTestEnvironment(): boolean {\n return (\n process.env.NODE_ENV === 'test' ||\n process.env.VITEST === 'true' ||\n process.env.JEST_WORKER_ID !== undefined\n );\n}\n\n/**\n * Best-effort detection of the current package under test.\n *\n * In workspace consumers, `process.cwd()` points at the consuming app/package,\n * while in smrt-core's own tests it points at `packages/core`. We use that\n * distinction to keep smrt-core's internal test manifest scoped to its own\n * test suite instead of leaking those fixtures into every consumer test run.\n */\nexport function getCurrentPackageName(): string | null {\n const explicitPackageName = process.env.npm_package_name;\n if (explicitPackageName) {\n return explicitPackageName;\n }\n\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n let currentDir = process.cwd();\n\n while (true) {\n const packageJsonPath = builtins.path.join(currentDir, 'package.json');\n if (builtins.fs.existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(\n builtins.fs.readFileSync(packageJsonPath, 'utf-8'),\n ) as { name?: string };\n return packageJson.name ?? null;\n } catch {\n return null;\n }\n }\n\n const parentDir = builtins.path.dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n}\n\n/**\n * smrt-core's committed test manifest is for smrt-core's own tests only.\n * Consumer packages should expose only their local test manifest plus real\n * published manifests from dependencies.\n */\nexport function shouldLoadCoreTestManifest(): boolean {\n if (!isTestEnvironment()) {\n return false;\n }\n\n const currentPackageName = getCurrentPackageName();\n if (currentPackageName) {\n return currentPackageName === '@happyvertical/smrt-core';\n }\n\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return false;\n }\n\n const moduleDir = builtins.path.dirname(\n builtins.url.fileURLToPath(import.meta.url),\n );\n const workspaceRoot = findWorkspaceRootSync(moduleDir);\n if (!workspaceRoot) {\n return false;\n }\n\n const corePackageDir = builtins.path.join(workspaceRoot, 'packages', 'core');\n const relative = builtins.path.relative(corePackageDir, process.cwd());\n return (\n relative === '' ||\n (!relative.startsWith('..') && !builtins.path.isAbsolute(relative))\n );\n}\n\n// ── Node builtins access ─────────────────────────────────────────────────\n\n/**\n * Resolve Node's built-in `fs`/`path`/`url` modules without a static import.\n *\n * `process.getBuiltinModule()` is a Node 22+ API that returns the live\n * built-in without going through the module loader. This avoids Vite's\n * static-import analysis flagging these builtins and simulated\n * \"externalized for browser\" warnings in bundled browser builds.\n */\nexport function getNodeBuiltins() {\n const getBuiltinModule = (\n process as typeof process & {\n getBuiltinModule?: (id: string) => unknown;\n }\n ).getBuiltinModule;\n if (typeof getBuiltinModule !== 'function') {\n return null;\n }\n\n const fs = getBuiltinModule('node:fs') as\n | typeof import('node:fs')\n | undefined;\n const path = getBuiltinModule('node:path') as\n | typeof import('node:path')\n | undefined;\n const url = getBuiltinModule('node:url') as\n | typeof import('node:url')\n | undefined;\n\n if (!fs || !path || !url) {\n return null;\n }\n\n return { fs, path, url };\n}\n\n// ── globalThis cache accessors ───────────────────────────────────────────\n\ntype ManifestGlobals = typeof globalThis & {\n __smrtManifestStatic?: SmartObjectManifest | null;\n __smrtManifestStaticLoadAttempted?: boolean;\n __smrtManifestTest?: SmartObjectManifest | null;\n __smrtManifestLocalTest?: SmartObjectManifest | null;\n __smrtManifestCache?: Map<string, SmartObjectManifest>;\n};\n\nfunction getManifestGlobals(): ManifestGlobals {\n return globalThis as ManifestGlobals;\n}\n\n/**\n * Return the mutable external-manifest cache, creating it if absent.\n *\n * Writers: `registerPackageManifest()` (Release A, each package's shim),\n * `loadExternalManifestSyncWithNode()`, `loadManifestFromPathSyncWithNode()`.\n * Readers: all discovery paths.\n */\nexport function getManifestCache(): Map<string, SmartObjectManifest> {\n const globals = getManifestGlobals();\n if (!globals.__smrtManifestCache) {\n globals.__smrtManifestCache = new Map();\n }\n return globals.__smrtManifestCache;\n}\n\n/** Read-only snapshot of the static manifest, if cached. */\nexport function getStaticManifestCache(): SmartObjectManifest | null {\n return getManifestGlobals().__smrtManifestStatic ?? null;\n}\n\n/** Read-only snapshot of the core test manifest, if cached. */\nexport function getTestManifestCache(): SmartObjectManifest | null {\n return getManifestGlobals().__smrtManifestTest ?? null;\n}\n\n/**\n * Read-only snapshot of the local (domain package) test manifest.\n *\n * Preserves the three-state semantics that `discoverManifestEntry()` relies\n * on: `undefined` means \"never attempted to load\" and triggers the lazy\n * loader; `null` means \"attempted but no local test manifest in this\n * package\"; a manifest object means \"loaded\". Do not collapse `undefined`\n * to `null` here — the async-discovery lazy-load path keys off the\n * distinction (see manifest-loader.ts:`if (getLocalTestManifestCache() === undefined) loadLocalTestManifestSync()`).\n */\nexport function getLocalTestManifestCache():\n | SmartObjectManifest\n | null\n | undefined {\n return getManifestGlobals().__smrtManifestLocalTest;\n}\n\n// ── Manifest shape helpers ───────────────────────────────────────────────\n\nexport function createEmptyStaticManifest(): SmartObjectManifest {\n return {\n version: '1.0.0',\n timestamp: Date.now(),\n objects: {},\n packageName: '@happyvertical/smrt-core',\n };\n}\n\n/**\n * Deep-clone a manifest's schema column map so downstream mutators don't\n * corrupt the cached manifest. Foreign-key descriptors get their own copy\n * because manifest-loader.ts and registerFromManifest() both splice them\n * into live schema entries.\n */\nexport function cloneManifestSchemaColumns(\n columns: Record<string, unknown> | undefined,\n): Record<string, ColumnDefinition> {\n return Object.fromEntries(\n Object.entries(columns || {}).map(([columnName, column]) => {\n const clonedColumn = {\n ...(column as ColumnDefinition & Record<string, unknown>),\n } as ColumnDefinition;\n const manifestDefault = (\n clonedColumn as ColumnDefinition & {\n default?: unknown;\n }\n ).default;\n\n if (\n clonedColumn.defaultValue === undefined &&\n manifestDefault !== undefined\n ) {\n clonedColumn.defaultValue = manifestDefault;\n }\n\n if (clonedColumn.foreignKey) {\n clonedColumn.foreignKey = { ...clonedColumn.foreignKey };\n }\n\n return [columnName, clonedColumn];\n }),\n ) as Record<string, ColumnDefinition>;\n}\n\n/**\n * Look up a class definition inside a single manifest.\n *\n * Tries qualified-key, simple-name, and lowercase-name lookups, then falls\n * back to iterating every entry in the manifest comparing lowered names.\n * This is the low-level primitive used by every sync discovery path.\n */\nexport function lookupCachedManifestEntry(\n manifest: SmartObjectManifest | null | undefined,\n className: string,\n): SmartObjectDefinition | undefined {\n if (!manifest?.objects) {\n return undefined;\n }\n\n const requestedQualifiedName = isQualifiedName(className)\n ? className\n : undefined;\n const requestedClassName = requestedQualifiedName\n ? parseQualifiedName(requestedQualifiedName).className\n : className;\n const lowerClassName = requestedClassName.toLowerCase();\n const packageName = manifest.packageName;\n const qualifiedKey =\n requestedQualifiedName ||\n (packageName\n ? createQualifiedName(packageName, requestedClassName)\n : undefined);\n\n return (\n (qualifiedKey ? manifest.objects[qualifiedKey] : undefined) ||\n manifest.objects[requestedClassName] ||\n manifest.objects[lowerClassName] ||\n Object.values(manifest.objects).find((entry) => {\n if (!entry) {\n return false;\n }\n\n if (entry.className?.toLowerCase() === lowerClassName) {\n return true;\n }\n\n return (\n requestedQualifiedName !== undefined &&\n packageName !== undefined &&\n createQualifiedName(packageName, entry.className || '') ===\n requestedQualifiedName\n );\n })\n );\n}\n\n// ── Filesystem helpers ───────────────────────────────────────────────────\n\nexport function findWorkspaceRootSync(startDir: string): string | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n let currentDir = startDir;\n\n while (true) {\n if (\n builtins.fs.existsSync(\n builtins.path.join(currentDir, 'pnpm-workspace.yaml'),\n )\n ) {\n return currentDir;\n }\n\n const parentDir = builtins.path.dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n}\n\nexport function resolveInstalledPackageJsonPathSync(\n packageName: string,\n): string | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n let currentDir = process.cwd();\n\n while (true) {\n const packageJsonPath = builtins.path.join(\n currentDir,\n 'node_modules',\n packageName,\n 'package.json',\n );\n\n if (builtins.fs.existsSync(packageJsonPath)) {\n return packageJsonPath;\n }\n\n const parentDir = builtins.path.dirname(currentDir);\n if (parentDir === currentDir) {\n return null;\n }\n\n currentDir = parentDir;\n }\n}\n\nexport function resolveWorkspacePackageJsonPathSync(\n packageName: string,\n): string | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n const workspaceRoot = findWorkspaceRootSync(process.cwd());\n if (!workspaceRoot) {\n return null;\n }\n\n const workspacePackagesDir = builtins.path.join(workspaceRoot, 'packages');\n if (!builtins.fs.existsSync(workspacePackagesDir)) {\n return null;\n }\n\n for (const packageDirName of builtins.fs.readdirSync(workspacePackagesDir)) {\n const packageJsonPath = builtins.path.join(\n workspacePackagesDir,\n packageDirName,\n 'package.json',\n );\n if (!builtins.fs.existsSync(packageJsonPath)) {\n continue;\n }\n\n try {\n const packageJson = JSON.parse(\n builtins.fs.readFileSync(packageJsonPath, 'utf-8'),\n ) as { name?: string };\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\nexport function resolveWorkspaceSourceManifestPathSync(\n packageDir: string,\n): string | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n const candidates = [\n builtins.path.join(packageDir, 'src', 'manifest', 'manifest.json'),\n builtins.path.join(packageDir, '.smrt', 'manifest.json'),\n ];\n\n for (const candidate of candidates) {\n if (builtins.fs.existsSync(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\nexport function resolveManifestExportPathSync(\n packageName: string,\n options: ManifestLoadOptions = {},\n): string | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n const shouldWarn = options.warn ?? true;\n const packageJsonPath =\n resolveInstalledPackageJsonPathSync(packageName) ||\n resolveWorkspacePackageJsonPathSync(packageName);\n\n if (!packageJsonPath) {\n return null;\n }\n\n const packageDir = builtins.path.dirname(packageJsonPath);\n const packageJson = JSON.parse(\n builtins.fs.readFileSync(packageJsonPath, 'utf-8'),\n ) as {\n exports?: Record<\n string,\n string | { default?: string; import?: string; require?: string }\n >;\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 recordRegistryDiagnostic(\n 'error',\n 'MANIFEST_EXPORT_INVALID',\n `Package ${packageName} has invalid manifest export configuration for ${exportKey}`,\n { packageName, exportKey },\n );\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 recordRegistryDiagnostic(\n 'error',\n 'MANIFEST_EXPORT_NOT_JSON',\n `Package ${packageName} must export a JSON manifest for ${exportKey}, received ${manifestRelativePath}`,\n { packageName, exportKey, manifestRelativePath },\n );\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 = builtins.path.join(packageDir, manifestRelativePath);\n if (builtins.fs.existsSync(manifestPath)) {\n return manifestPath;\n }\n\n const workspaceSourceManifest =\n resolveWorkspaceSourceManifestPathSync(packageDir);\n if (workspaceSourceManifest) {\n return workspaceSourceManifest;\n }\n\n recordRegistryDiagnostic(\n 'error',\n 'MANIFEST_EXPORT_NOT_FOUND',\n `Package ${packageName} declares manifest export ${manifestRelativePath}, but no manifest file was found.`,\n { packageName, exportKey, manifestRelativePath },\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\n// ── Manifest reading (seeds caches) ──────────────────────────────────────\n\n/**\n * Load smrt-core's own bundled manifest from disk, caching in\n * `__smrtManifestStatic`. Resolves against this module's own `import.meta.url`\n * so paths work whether the code is running from `dist/` or `src/`.\n */\nexport function loadStaticManifestSyncWithNode(): SmartObjectManifest | null {\n const globals = getManifestGlobals();\n\n if (globals.__smrtManifestStatic !== undefined) {\n return globals.__smrtManifestStatic ?? null;\n }\n\n const builtins = getNodeBuiltins();\n globals.__smrtManifestStaticLoadAttempted = true;\n if (!builtins) {\n const fallbackManifest = createEmptyStaticManifest();\n globals.__smrtManifestStatic = fallbackManifest;\n return fallbackManifest;\n }\n\n // store.ts lives at src/manifest/store.ts (source) → dist/manifest/store.js\n // (compiled). In src, the static manifest is a sibling JSON; in dist, it is\n // the package's dist/manifest.json one level up.\n const candidates = import.meta.url.endsWith('.ts')\n ? [\n new URL('./static-manifest.json', import.meta.url),\n new URL('../../dist/manifest.json', import.meta.url),\n ]\n : [new URL('../manifest.json', import.meta.url)];\n\n for (const candidate of candidates) {\n try {\n if (!builtins.fs.existsSync(candidate)) {\n continue;\n }\n\n const manifest = JSON.parse(\n builtins.fs.readFileSync(candidate, 'utf-8'),\n ) as SmartObjectManifest;\n\n if (!manifest.objects || typeof manifest.objects !== 'object') {\n continue;\n }\n\n const cachedManifest = manifest.packageName\n ? manifest\n : { ...manifest, packageName: '@happyvertical/smrt-core' };\n globals.__smrtManifestStatic = cachedManifest;\n return cachedManifest;\n } catch {\n // Try the next candidate and fall back to the empty manifest if needed.\n }\n }\n\n const fallbackManifest = createEmptyStaticManifest();\n globals.__smrtManifestStatic = fallbackManifest;\n return fallbackManifest;\n}\n\n/**\n * Load a package's published manifest by package name, caching in\n * `__smrtManifestCache` under the package key. Returns null on miss or\n * invalid shape; records a diagnostic instead of throwing.\n */\nexport function loadExternalManifestSyncWithNode(\n packageName: string,\n options: ManifestLoadOptions = {},\n): SmartObjectManifest | null {\n const cache = getManifestCache();\n\n if (cache.has(packageName)) {\n return cache.get(packageName) || null;\n }\n\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n const manifestPath = resolveManifestExportPathSync(packageName, options);\n if (!manifestPath) {\n return null;\n }\n\n try {\n const manifest = JSON.parse(\n builtins.fs.readFileSync(manifestPath, 'utf-8'),\n ) as SmartObjectManifest;\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 cache.set(packageName, cachedManifest);\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\n/**\n * Load a manifest from an explicit filesystem path, caching in\n * `__smrtManifestCache` under the manifest's packageName (or the path as a\n * fallback key). Used by `loadAllManifests({ manifestPaths })` in registry.ts\n * and by the Release B `ExplicitPathsManifestSource`.\n */\nexport function loadManifestFromPathSyncWithNode(\n manifestPath: string,\n): SmartObjectManifest | null {\n const builtins = getNodeBuiltins();\n if (!builtins) {\n return null;\n }\n\n try {\n const manifest = JSON.parse(\n builtins.fs.readFileSync(manifestPath, 'utf-8'),\n ) as SmartObjectManifest;\n\n if (!manifest.objects || typeof manifest.objects !== 'object') {\n logger.warn(`Invalid manifest structure at ${manifestPath}`);\n return null;\n }\n\n getManifestCache().set(manifest.packageName || manifestPath, manifest);\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 * Synchronous lookup across every cached manifest source, in priority order.\n *\n * Matches the historical order from manifest-loader.ts and registry.ts:\n * local test → core test → static (smrt-core bundled) → external cache.\n * The Release B `CompositeManifestSource` wraps the same priority behind a\n * higher-level abstraction.\n */\nexport function discoverCachedManifestSync(\n className: string,\n): SmartObjectDefinition | undefined {\n const manifests: Array<SmartObjectManifest | null | undefined> = [\n getLocalTestManifestCache(),\n getTestManifestCache(),\n loadStaticManifestSyncWithNode(),\n ...getManifestCache().values(),\n ];\n\n for (const manifest of manifests) {\n const entry = lookupCachedManifestEntry(manifest, className);\n if (entry) {\n return entry;\n }\n }\n\n return undefined;\n}\n"],"names":["fallbackManifest"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"test-manifest-stub.d.ts","sourceRoot":"","sources":["../../src/manifest/test-manifest-stub.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,eAAO,MAAM,YAAY,EAAE,mBAqx2EjB,CAAC;AAEX,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"test-manifest-stub.d.ts","sourceRoot":"","sources":["../../src/manifest/test-manifest-stub.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,eAAO,MAAM,YAAY,EAAE,mBAmn2EjB,CAAC;AAEX,eAAe,YAAY,CAAC"}
@@ -1,8 +1,8 @@
1
1
  const testManifest = {
2
2
  "version": "1.0.0",
3
- "timestamp": 1782481647647,
3
+ "timestamp": 1782485413637,
4
4
  "packageName": "@happyvertical/smrt-core",
5
- "packageVersion": "0.36.4",
5
+ "packageVersion": "0.36.5",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-core:SmrtClass": {
8
8
  "name": "smrtclass",
@@ -133,6 +133,14 @@ const testManifest = {
133
133
  "packageName": "@happyvertical/smrt-core",
134
134
  "fields": {},
135
135
  "methods": {
136
+ "getItemClass": {
137
+ "name": "getItemClass",
138
+ "async": false,
139
+ "parameters": [],
140
+ "returnType": "SmrtCollectionItemClass<ModelType>",
141
+ "isStatic": false,
142
+ "isPublic": true
143
+ },
136
144
  "validate": {
137
145
  "name": "validate",
138
146
  "async": false,
@@ -663,67 +671,7 @@ const testManifest = {
663
671
  "decoratorConfig": {},
664
672
  "extends": "SmrtObject",
665
673
  "exportName": "SmrtHierarchical",
666
- "collectionExportName": "SmrtHierarchicalCollection",
667
- "schema": {
668
- "tableName": "smrt_hierarchicals",
669
- "ddl": `CREATE TABLE IF NOT EXISTS "smrt_hierarchicals" (
670
- "id" UUID PRIMARY KEY NOT NULL,
671
- "slug" TEXT NOT NULL,
672
- "context" TEXT NOT NULL DEFAULT '',
673
- "created_at" TIMESTAMP NOT NULL DEFAULT current_timestamp,
674
- "updated_at" TIMESTAMP NOT NULL DEFAULT current_timestamp,
675
- "parent_id" TEXT
676
- );`,
677
- "columns": {
678
- "id": {
679
- "type": "UUID",
680
- "primaryKey": true,
681
- "referenceKind": "id",
682
- "notNull": true
683
- },
684
- "slug": {
685
- "type": "TEXT",
686
- "notNull": true
687
- },
688
- "context": {
689
- "type": "TEXT",
690
- "notNull": true,
691
- "default": ""
692
- },
693
- "created_at": {
694
- "type": "TIMESTAMP",
695
- "notNull": true,
696
- "default": "current_timestamp"
697
- },
698
- "updated_at": {
699
- "type": "TIMESTAMP",
700
- "notNull": true,
701
- "default": "current_timestamp"
702
- },
703
- "parent_id": {
704
- "type": "TEXT",
705
- "notNull": false,
706
- "unique": false
707
- }
708
- },
709
- "indexes": [
710
- {
711
- "name": "smrt_hierarchicals_id_idx",
712
- "columns": [
713
- "id"
714
- ]
715
- },
716
- {
717
- "name": "smrt_hierarchicals_slug_context_idx",
718
- "columns": [
719
- "slug",
720
- "context"
721
- ],
722
- "unique": true
723
- }
724
- ],
725
- "version": "d805e5fa"
726
- }
674
+ "collectionExportName": "SmrtHierarchicalCollection"
727
675
  },
728
676
  "@happyvertical/smrt-core:SmrtJunction": {
729
677
  "name": "smrtjunction",
@@ -849,61 +797,7 @@ const testManifest = {
849
797
  "extends": "SmrtCollection",
850
798
  "extendsTypeArg": "TItem",
851
799
  "exportName": "SmrtJunction",
852
- "collectionExportName": "SmrtJunctionCollection",
853
- "schema": {
854
- "tableName": "smrt_junctions",
855
- "ddl": `CREATE TABLE IF NOT EXISTS "smrt_junctions" (
856
- "id" UUID PRIMARY KEY NOT NULL,
857
- "slug" TEXT NOT NULL,
858
- "context" TEXT NOT NULL DEFAULT '',
859
- "created_at" TIMESTAMP NOT NULL DEFAULT current_timestamp,
860
- "updated_at" TIMESTAMP NOT NULL DEFAULT current_timestamp
861
- );`,
862
- "columns": {
863
- "id": {
864
- "type": "UUID",
865
- "primaryKey": true,
866
- "referenceKind": "id",
867
- "notNull": true
868
- },
869
- "slug": {
870
- "type": "TEXT",
871
- "notNull": true
872
- },
873
- "context": {
874
- "type": "TEXT",
875
- "notNull": true,
876
- "default": ""
877
- },
878
- "created_at": {
879
- "type": "TIMESTAMP",
880
- "notNull": true,
881
- "default": "current_timestamp"
882
- },
883
- "updated_at": {
884
- "type": "TIMESTAMP",
885
- "notNull": true,
886
- "default": "current_timestamp"
887
- }
888
- },
889
- "indexes": [
890
- {
891
- "name": "smrt_junctions_id_idx",
892
- "columns": [
893
- "id"
894
- ]
895
- },
896
- {
897
- "name": "smrt_junctions_slug_context_idx",
898
- "columns": [
899
- "slug",
900
- "context"
901
- ],
902
- "unique": true
903
- }
904
- ],
905
- "version": "48da04af"
906
- }
800
+ "collectionExportName": "SmrtJunctionCollection"
907
801
  },
908
802
  "@happyvertical/smrt-core:SmrtObject": {
909
803
  "name": "smrtobject",
@@ -1694,86 +1588,7 @@ const testManifest = {
1694
1588
  "rule": "required",
1695
1589
  "fieldType": "text"
1696
1590
  }
1697
- ],
1698
- "schema": {
1699
- "tableName": "smrt_polymorphic_associations",
1700
- "ddl": `CREATE TABLE IF NOT EXISTS "smrt_polymorphic_associations" (
1701
- "id" UUID PRIMARY KEY NOT NULL,
1702
- "slug" TEXT NOT NULL,
1703
- "context" TEXT NOT NULL DEFAULT '',
1704
- "created_at" TIMESTAMP NOT NULL DEFAULT current_timestamp,
1705
- "updated_at" TIMESTAMP NOT NULL DEFAULT current_timestamp,
1706
- "meta_type" TEXT NOT NULL,
1707
- "meta_id" TEXT NOT NULL,
1708
- "role" TEXT NOT NULL,
1709
- "sort_order" INTEGER DEFAULT 0
1710
- );`,
1711
- "columns": {
1712
- "id": {
1713
- "type": "UUID",
1714
- "primaryKey": true,
1715
- "referenceKind": "id",
1716
- "notNull": true
1717
- },
1718
- "slug": {
1719
- "type": "TEXT",
1720
- "notNull": true
1721
- },
1722
- "context": {
1723
- "type": "TEXT",
1724
- "notNull": true,
1725
- "default": ""
1726
- },
1727
- "created_at": {
1728
- "type": "TIMESTAMP",
1729
- "notNull": true,
1730
- "default": "current_timestamp"
1731
- },
1732
- "updated_at": {
1733
- "type": "TIMESTAMP",
1734
- "notNull": true,
1735
- "default": "current_timestamp"
1736
- },
1737
- "meta_type": {
1738
- "type": "TEXT",
1739
- "notNull": true,
1740
- "unique": false
1741
- },
1742
- "meta_id": {
1743
- "type": "TEXT",
1744
- "notNull": true,
1745
- "unique": false
1746
- },
1747
- "role": {
1748
- "type": "TEXT",
1749
- "notNull": true,
1750
- "unique": false
1751
- },
1752
- "sort_order": {
1753
- "type": "INTEGER",
1754
- "notNull": false,
1755
- "unique": false,
1756
- "default": 0
1757
- }
1758
- },
1759
- "indexes": [
1760
- {
1761
- "name": "smrt_polymorphic_associations_id_idx",
1762
- "columns": [
1763
- "id"
1764
- ]
1765
- },
1766
- {
1767
- "name": "smrt_polymorphic_associations_slug_context_idx",
1768
- "columns": [
1769
- "slug",
1770
- "context"
1771
- ],
1772
- "unique": true
1773
- }
1774
- ],
1775
- "version": "73c67637"
1776
- }
1591
+ ]
1777
1592
  },
1778
1593
  "@happyvertical/smrt-core:TestClass": {
1779
1594
  "name": "testclass",