@happyvertical/smrt-core 0.57.1 → 0.57.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -0
- package/agents/generators.md +23 -0
- package/agents/object-runtime.md +8 -0
- package/dist/browser.d.ts +1 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/manifest/static-manifest.d.ts.map +1 -1
- package/dist/manifest/static-manifest.js +7 -2
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest/store.js.map +1 -1
- package/dist/manifest.json +11 -2
- package/dist/object.d.ts +7 -2
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +8 -3
- package/dist/object.js.map +1 -1
- package/dist/registry/subclass-exposure.d.ts +84 -0
- package/dist/registry/subclass-exposure.d.ts.map +1 -0
- package/dist/registry/subclass-exposure.js +119 -0
- package/dist/registry/subclass-exposure.js.map +1 -0
- package/dist/registry/types.d.ts +22 -0
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +56 -14
- package/dist/registry.js.map +1 -1
- package/dist/scanner/manifest-generator.d.ts +27 -0
- package/dist/scanner/manifest-generator.d.ts.map +1 -1
- package/dist/scanner/manifest-generator.js +91 -0
- package/dist/scanner/manifest-generator.js.map +1 -1
- package/dist/smrt-knowledge.json +12 -9
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","names":[],"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 {\n bumpRegistryGeneration,\n createGenerationTrackedMap,\n isGenerationTrackedMap,\n} from '../registry/generation.js';\nimport type {\n SmartObjectDefinition,\n SmartObjectManifest,\n} from '../scanner/types.js';\nimport { MANIFEST_TIMESTAMP } 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`/`module` 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 // A browser bundle has no `process` global at all; reading a property of it\n // would throw rather than report \"no Node host\" (#2838).\n if (typeof process === 'undefined') {\n return null;\n }\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 const module = getBuiltinModule('node:module') as\n | typeof import('node:module')\n | undefined;\n\n if (!fs || !path || !url || !module) {\n return null;\n }\n\n return { fs, path, url, module };\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 */\n/**\n * Whether the package's stored manifest declares that its library build\n * stamps each decorated class with its package (`stampsConstructors`,\n * #3490). Read from the manifest record itself, so every path that stores a\n * manifest carries the capability and every path that clears or replaces it\n * drops it.\n */\nexport function packageStampsConstructors(packageName: string): boolean {\n return getManifestCache().get(packageName)?.stampsConstructors === true;\n}\n\nexport function getManifestCache(): Map<string, SmartObjectManifest> {\n const globals = getManifestGlobals();\n const current = globals.__smrtManifestCache;\n if (current && isGenerationTrackedMap(current)) {\n return current;\n }\n // A newly cached manifest can change what manifest discovery returns, so\n // it invalidates the generation-keyed registry memos (#3047).\n const tracked = createGenerationTrackedMap<string, SmartObjectManifest>(\n current,\n );\n globals.__smrtManifestCache = tracked;\n return tracked;\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: MANIFEST_TIMESTAMP,\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 // A qualified request names one package's class. Another package's\n // manifest can only answer it by an exact qualified key (aggregated\n // manifests); a simple-name hit there is a different class (#3098).\n const requestedPackage = requestedQualifiedName\n ? parseQualifiedName(requestedQualifiedName).packageName\n : undefined;\n if (\n requestedQualifiedName &&\n packageName !== undefined &&\n packageName !== requestedPackage\n ) {\n const direct = manifest.objects[requestedQualifiedName];\n return direct &&\n (direct.packageName === undefined ||\n direct.packageName === requestedPackage)\n ? direct\n : undefined;\n }\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 bumpRegistryGeneration();\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 bumpRegistryGeneration();\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 bumpRegistryGeneration();\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"store.js","names":[],"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 {\n bumpRegistryGeneration,\n createGenerationTrackedMap,\n isGenerationTrackedMap,\n} from '../registry/generation.js';\nimport type {\n SmartObjectDefinition,\n SmartObjectManifest,\n} from '../scanner/types.js';\nimport { MANIFEST_TIMESTAMP } 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`/`module` 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 // A browser bundle has no `process` global at all; reading a property of it\n // would throw rather than report \"no Node host\" (#2838).\n if (typeof process === 'undefined') {\n return null;\n }\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 const module = getBuiltinModule('node:module') as\n | typeof import('node:module')\n | undefined;\n\n if (!fs || !path || !url || !module) {\n return null;\n }\n\n return { fs, path, url, module };\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 */\n/**\n * Whether the package's stored manifest declares that its library build\n * stamps each decorated class with its package (`stampsConstructors`,\n * #3490). Read from the manifest record itself, so every path that stores a\n * manifest carries the capability and every path that clears or replaces it\n * drops it.\n */\nexport function packageStampsConstructors(packageName: string): boolean {\n return getManifestCache().get(packageName)?.stampsConstructors === true;\n}\n\nexport function getManifestCache(): Map<string, SmartObjectManifest> {\n const globals = getManifestGlobals();\n const current = globals.__smrtManifestCache;\n if (current && isGenerationTrackedMap(current)) {\n return current;\n }\n // A newly cached manifest can change what manifest discovery returns, so\n // it invalidates the generation-keyed registry memos (#3047).\n const tracked = createGenerationTrackedMap<string, SmartObjectManifest>(\n current,\n );\n globals.__smrtManifestCache = tracked;\n return tracked;\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: MANIFEST_TIMESTAMP,\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 // A qualified request names one package's class. Another package's\n // manifest can only answer it by an exact qualified key (aggregated\n // manifests); a simple-name hit there is a different class (#3098).\n const requestedPackage = requestedQualifiedName\n ? parseQualifiedName(requestedQualifiedName).packageName\n : undefined;\n if (\n requestedQualifiedName &&\n packageName !== undefined &&\n packageName !== requestedPackage\n ) {\n const direct = manifest.objects[requestedQualifiedName];\n return direct &&\n (direct.packageName === undefined ||\n direct.packageName === requestedPackage)\n ? direct\n : undefined;\n }\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 bumpRegistryGeneration();\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 bumpRegistryGeneration();\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 bumpRegistryGeneration();\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"],"mappings":"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"}
|
package/dist/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"version": "1.0.0",
|
|
3
3
|
"timestamp": 0,
|
|
4
4
|
"packageName": "@happyvertical/smrt-core",
|
|
5
|
-
"packageVersion": "0.57.
|
|
5
|
+
"packageVersion": "0.57.3",
|
|
6
6
|
"objects": {
|
|
7
7
|
"@happyvertical/smrt-core:SmrtClass": {
|
|
8
8
|
"name": "smrtclass",
|
|
@@ -1166,7 +1166,16 @@
|
|
|
1166
1166
|
"requireInsertOnSave": {
|
|
1167
1167
|
"name": "requireInsertOnSave",
|
|
1168
1168
|
"async": false,
|
|
1169
|
-
"parameters": [
|
|
1169
|
+
"parameters": [
|
|
1170
|
+
{
|
|
1171
|
+
"name": "options",
|
|
1172
|
+
"type": "object",
|
|
1173
|
+
"optional": true,
|
|
1174
|
+
"memberTypes": [
|
|
1175
|
+
"boolean"
|
|
1176
|
+
]
|
|
1177
|
+
}
|
|
1178
|
+
],
|
|
1170
1179
|
"returnType": "void",
|
|
1171
1180
|
"isStatic": false,
|
|
1172
1181
|
"isPublic": true
|
package/dist/object.d.ts
CHANGED
|
@@ -181,6 +181,7 @@ export declare class SmrtObject extends SmrtClass {
|
|
|
181
181
|
* is true.
|
|
182
182
|
*/
|
|
183
183
|
private _insertOnly;
|
|
184
|
+
private _insertOnlyPreserveDerivedSlug;
|
|
184
185
|
/**
|
|
185
186
|
* The slug {@link getSlug} derived from a human value (`name`, `title` or
|
|
186
187
|
* `label`), or `null` when the slug was set explicitly or derived from the
|
|
@@ -261,10 +262,14 @@ export declare class SmrtObject extends SmrtClass {
|
|
|
261
262
|
* instead of upsert-adopting an existing row. Set via
|
|
262
263
|
* `collection.create({ _insertOnly: true })` for write paths where row
|
|
263
264
|
* identity is an explicit client-supplied id (sync-apply, #1759).
|
|
264
|
-
*
|
|
265
|
+
* With `preserveDerivedSlug`, automatically derived names retain safe slug
|
|
266
|
+
* disambiguation. Explicit keys and getOrUpsert's adoption path still INSERT
|
|
267
|
+
* strictly; neither can replace an existing identity. No effect once persisted.
|
|
265
268
|
* @internal
|
|
266
269
|
*/
|
|
267
|
-
requireInsertOnSave(
|
|
270
|
+
requireInsertOnSave(options?: {
|
|
271
|
+
preserveDerivedSlug?: boolean;
|
|
272
|
+
}): void;
|
|
268
273
|
/**
|
|
269
274
|
* Makes the initial `save()` update the row its natural key names in place
|
|
270
275
|
* — even when the slug was derived from `name`/`title`/`label` — instead of
|
package/dist/object.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAWzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAS,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAS,CAAC;AAOpC,OAAO,EAGL,KAAK,2BAA2B,EACjC,MAAM,gBAAa,CAAC;AACrB,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,gBAAa,CAAC;AAWrB,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,uBAAoB,CAAC;AA6BpE,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,cAAc,EACpB,MAAM,0BAAuB,CAAC;AAsM/B,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CACnC;AAED,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CACnC;AAoGD;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,UAAU,CAAC,EAAE,IAAI,CAAC;IAElB;;OAEG;IACH,UAAU,CAAC,EAAE,IAAI,CAAC;IAElB;;OAEG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;;;;;;;OASG;IAEH,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;CACvC;AAqBD;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;OASG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IACjE;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,UAAW,SAAQ,SAAS;IACvC;;OAEG;IACI,UAAU,EAAG,MAAM,CAAC;IAE3B;;;OAGG;IACH,OAAO,CAAC,oBAAoB,CAAmC;IAE/D;;;;;;;;;OASG;IACH,OAAO,CAAC,UAAU,CAAS;IAE3B;;;;;;;OAOG;IACH,OAAO,CAAC,WAAW,CAAS;
|
|
1
|
+
{"version":3,"file":"object.d.ts","sourceRoot":"","sources":["../src/object.ts"],"names":[],"mappings":"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"}
|
package/dist/object.js
CHANGED
|
@@ -240,6 +240,7 @@ var SmrtObject = class SmrtObject extends SmrtClass {
|
|
|
240
240
|
* is true.
|
|
241
241
|
*/
|
|
242
242
|
_insertOnly = false;
|
|
243
|
+
_insertOnlyPreserveDerivedSlug = false;
|
|
243
244
|
/**
|
|
244
245
|
* The slug {@link getSlug} derived from a human value (`name`, `title` or
|
|
245
246
|
* `label`), or `null` when the slug was set explicitly or derived from the
|
|
@@ -392,11 +393,15 @@ var SmrtObject = class SmrtObject extends SmrtClass {
|
|
|
392
393
|
* instead of upsert-adopting an existing row. Set via
|
|
393
394
|
* `collection.create({ _insertOnly: true })` for write paths where row
|
|
394
395
|
* identity is an explicit client-supplied id (sync-apply, #1759).
|
|
395
|
-
*
|
|
396
|
+
* With `preserveDerivedSlug`, automatically derived names retain safe slug
|
|
397
|
+
* disambiguation. Explicit keys and getOrUpsert's adoption path still INSERT
|
|
398
|
+
* strictly; neither can replace an existing identity. No effect once persisted.
|
|
396
399
|
* @internal
|
|
397
400
|
*/
|
|
398
|
-
requireInsertOnSave() {
|
|
401
|
+
requireInsertOnSave(options = {}) {
|
|
402
|
+
if (this._insertOnly && !this._insertOnlyPreserveDerivedSlug) return;
|
|
399
403
|
this._insertOnly = true;
|
|
404
|
+
this._insertOnlyPreserveDerivedSlug = options.preserveDerivedSlug ?? false;
|
|
400
405
|
}
|
|
401
406
|
/**
|
|
402
407
|
* Makes the initial `save()` update the row its natural key names in place
|
|
@@ -1533,7 +1538,7 @@ var SmrtObject = class SmrtObject extends SmrtClass {
|
|
|
1533
1538
|
const upsertConflictColumns = this._persisted && data.id ? ["id"] : conflictColumns;
|
|
1534
1539
|
const useEmbeddedRevisionFallback = revisionGuard !== void 0 && usesEmbeddedRevisionFallback(this.db);
|
|
1535
1540
|
const serializeEmbeddedWrite = isEmbeddedDatabase(this.db);
|
|
1536
|
-
const naturalKeyUpsert = writePlan.type === "upsert" && revisionGuard === void 0 && !(this._insertOnly && !this._persisted) && !(upsertConflictColumns.length === 1 && upsertConflictColumns[0] === "id");
|
|
1541
|
+
const naturalKeyUpsert = writePlan.type === "upsert" && revisionGuard === void 0 && (!(this._insertOnly && !this._persisted) || this._insertOnlyPreserveDerivedSlug && !this._adoptNaturalKey && upsertConflictColumns.includes("slug") && this._derivedSlug !== null && data.slug === this._derivedSlug) && !(upsertConflictColumns.length === 1 && upsertConflictColumns[0] === "id");
|
|
1537
1542
|
let revisionMatched = true;
|
|
1538
1543
|
let naturalKeyWrite = "upsert";
|
|
1539
1544
|
const adopted = {};
|