@happyvertical/smrt-core 0.55.24 → 0.56.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/collection-reads.md +6 -3
- package/agents/generators.md +53 -0
- package/agents/object-runtime.md +3 -0
- package/agents/recipes.md +7 -4
- package/dist/browser.d.ts +2 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +3 -1
- package/dist/collection.d.ts +4 -0
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +19 -9
- package/dist/collection.js.map +1 -1
- package/dist/consumer-plugin/hosted-sti-collections.d.ts.map +1 -1
- package/dist/consumer-plugin/hosted-sti-collections.js +4 -2
- package/dist/consumer-plugin/hosted-sti-collections.js.map +1 -1
- package/dist/cookbook/engine/commands.d.ts.map +1 -1
- package/dist/cookbook/engine/commands.js +12 -0
- package/dist/cookbook/engine/commands.js.map +1 -1
- package/dist/cookbook/engine/defaults.d.ts.map +1 -1
- package/dist/cookbook/engine/defaults.js +8 -0
- package/dist/cookbook/engine/defaults.js.map +1 -1
- package/dist/cookbook/engine/document.d.ts +4 -0
- package/dist/cookbook/engine/document.d.ts.map +1 -1
- package/dist/cookbook/engine/document.js +11 -3
- package/dist/cookbook/engine/document.js.map +1 -1
- package/dist/cookbook/engine/engine.d.ts.map +1 -1
- package/dist/cookbook/engine/engine.js +3 -1
- package/dist/cookbook/engine/engine.js.map +1 -1
- package/dist/cookbook/engine/schemas.d.ts.map +1 -1
- package/dist/cookbook/engine/schemas.js +8 -0
- package/dist/cookbook/engine/schemas.js.map +1 -1
- package/dist/cookbook/engine/types.d.ts +5 -1
- package/dist/cookbook/engine/types.d.ts.map +1 -1
- package/dist/cookbook/engine/types.js.map +1 -1
- package/dist/decorators/index.d.ts +2 -0
- package/dist/decorators/index.d.ts.map +1 -1
- package/dist/decorators/index.js.map +1 -1
- package/dist/generators/index.d.ts +1 -0
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +2 -1
- package/dist/generators/mcp-runtime-template.d.ts +3 -0
- package/dist/generators/mcp-runtime-template.d.ts.map +1 -1
- package/dist/generators/mcp-runtime-template.js +30 -4
- package/dist/generators/mcp-runtime-template.js.map +1 -1
- package/dist/generators/mcp.d.ts +5 -0
- package/dist/generators/mcp.d.ts.map +1 -1
- package/dist/generators/mcp.js +82 -9
- package/dist/generators/mcp.js.map +1 -1
- package/dist/generators/preflight-route.d.ts.map +1 -1
- package/dist/generators/preflight-route.js +3 -1
- package/dist/generators/preflight-route.js.map +1 -1
- package/dist/generators/rest.d.ts.map +1 -1
- package/dist/generators/rest.js +5 -0
- package/dist/generators/rest.js.map +1 -1
- package/dist/generators/swagger.d.ts.map +1 -1
- package/dist/generators/swagger.js +3 -1
- package/dist/generators/swagger.js.map +1 -1
- package/dist/generators.js +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/manifest/browser-capability.generated.js +34 -5
- package/dist/manifest/browser-capability.generated.js.map +1 -1
- package/dist/manifest/index.js +1 -1
- package/dist/manifest/static-manifest.d.ts.map +1 -1
- package/dist/manifest/static-manifest.js +9 -1
- 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 +9 -1
- package/dist/mcp-serializer.d.ts +38 -0
- package/dist/mcp-serializer.d.ts.map +1 -0
- package/dist/mcp-serializer.js +60 -0
- package/dist/mcp-serializer.js.map +1 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/index.js +34 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/index.js.map +1 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/lib/errors.js +343 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/lib/errors.js.map +1 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/lib/get-format.js +109 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/lib/get-format.js.map +1 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/lib/package-json-reader.js +102 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/lib/package-json-reader.js.map +1 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/lib/resolve.js +673 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/lib/resolve.js.map +1 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/lib/utils.js +32 -0
- package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/lib/utils.js.map +1 -0
- package/dist/object.d.ts +2 -0
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +51 -0
- package/dist/object.js.map +1 -1
- package/dist/operation-permission.d.ts +10 -0
- package/dist/operation-permission.d.ts.map +1 -0
- package/dist/operation-permission.js +36 -0
- package/dist/operation-permission.js.map +1 -0
- package/dist/registry/class-registration.d.ts.map +1 -1
- package/dist/registry/class-registration.js +12 -0
- package/dist/registry/class-registration.js.map +1 -1
- package/dist/registry/types.d.ts +18 -3
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/scanner/manifest-generator.d.ts.map +1 -1
- package/dist/scanner/manifest-generator.js +47 -0
- package/dist/scanner/manifest-generator.js.map +1 -1
- package/dist/scanner/types.d.ts +5 -0
- package/dist/scanner/types.d.ts.map +1 -1
- package/dist/scanner/types.js.map +1 -1
- package/dist/smrt-knowledge.json +18 -11
- package/dist/utils/import-project-vite.js +1 -1
- package/dist/utils/import-workspace-module.js +1 -1
- package/dist/vite-plugin/api-client-entries.d.ts.map +1 -1
- package/dist/vite-plugin/api-client-entries.js +1 -0
- package/dist/vite-plugin/api-client-entries.js.map +1 -1
- package/dist/vite-plugin/dev-plane-route.js +1 -1
- package/dist/vite-plugin/import-build-aware.js +1 -1
- package/dist/vite-plugin/index.js +1 -1
- package/dist/vite-plugin/resources-route.js +1 -1
- package/dist/vite-plugin/sveltekit-generator.d.ts +0 -4
- package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.js +37 -25
- package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
- package/package.json +16 -10
|
@@ -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.
|
|
5
|
+
"packageVersion": "0.56.1",
|
|
6
6
|
"objects": {
|
|
7
7
|
"@happyvertical/smrt-core:SmrtClass": {
|
|
8
8
|
"name": "smrtclass",
|
|
@@ -556,6 +556,14 @@
|
|
|
556
556
|
"isStatic": false,
|
|
557
557
|
"isPublic": true
|
|
558
558
|
},
|
|
559
|
+
"getStiChildMetaTypes": {
|
|
560
|
+
"name": "getStiChildMetaTypes",
|
|
561
|
+
"async": false,
|
|
562
|
+
"parameters": [],
|
|
563
|
+
"returnType": "string[]",
|
|
564
|
+
"isStatic": false,
|
|
565
|
+
"isPublic": true
|
|
566
|
+
},
|
|
559
567
|
"query": {
|
|
560
568
|
"name": "query",
|
|
561
569
|
"async": true,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { PublicJsonOptions, SmrtObject } from './object.js';
|
|
2
|
+
/** A named module export that projects an admitted MCP `get` result. */
|
|
3
|
+
export type McpGetSerializer = (item: SmrtObject, options: PublicJsonOptions) => unknown | Promise<unknown>;
|
|
4
|
+
/** Package-owned location of an MCP `get` result serializer. */
|
|
5
|
+
export interface McpGetSerializerReference {
|
|
6
|
+
importPath: string;
|
|
7
|
+
exportName: string;
|
|
8
|
+
}
|
|
9
|
+
export interface McpGetSerializerResolveOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Module URL that owns a relative serializer reference. Omit only when the
|
|
12
|
+
* resolver itself owns that relative reference.
|
|
13
|
+
*/
|
|
14
|
+
parentUrl?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Qualified registry key of the model that declared the serializer. Its
|
|
17
|
+
* loaded module is the default anchor for resolving a bare package.
|
|
18
|
+
*/
|
|
19
|
+
ownerRegistryKey?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Explicit application module URL for a host that resolves a serializer
|
|
22
|
+
* outside a registered MCP model.
|
|
23
|
+
*/
|
|
24
|
+
consumerAnchorUrl?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Resolve a serializer package from the running application's module graph.
|
|
28
|
+
*
|
|
29
|
+
* Model packages own serializer implementations but do not become dependencies
|
|
30
|
+
* of core or generic consumers such as Chat. Bare specifiers first use the
|
|
31
|
+
* active runtime module graph so workspace aliases keep one constructor
|
|
32
|
+
* identity. When the package is absent from Core's dependency graph, resolution
|
|
33
|
+
* continues from the module that registered the owning model (or an explicit
|
|
34
|
+
* host anchor), with ESM export conditions. Relative and URL references keep
|
|
35
|
+
* their declaring module's ordinary dynamic-import behavior.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveMcpGetSerializer(reference: McpGetSerializerReference, options?: McpGetSerializerResolveOptions): Promise<McpGetSerializer>;
|
|
38
|
+
//# sourceMappingURL=mcp-serializer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-serializer.d.ts","sourceRoot":"","sources":["../src/mcp-serializer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGjE,wEAAwE;AACxE,MAAM,MAAM,gBAAgB,GAAG,CAC7B,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,iBAAiB,KACvB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC,gEAAgE;AAChE,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAqCD;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,yBAAyB,EACpC,OAAO,GAAE,8BAAmC,GAC3C,OAAO,CAAC,gBAAgB,CAAC,CA+C3B"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ObjectRegistry } from "./registry.js";
|
|
2
|
+
import { resolve as resolve$1 } from "./node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/index.js";
|
|
3
|
+
import { isAbsolute } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
//#region src/mcp-serializer.ts
|
|
6
|
+
function resolvesFromConsumer(importPath) {
|
|
7
|
+
return !importPath.startsWith(".") && !isAbsolute(importPath) && !importPath.startsWith("file:") && !importPath.startsWith("data:") && !importPath.startsWith("node:");
|
|
8
|
+
}
|
|
9
|
+
function isUnresolvedPackage(error, importPath) {
|
|
10
|
+
if (!(error instanceof Error) || error.code !== "ERR_MODULE_NOT_FOUND") return false;
|
|
11
|
+
const packageName = importPath.startsWith("@") ? importPath.split("/").slice(0, 2).join("/") : importPath.split("/")[0];
|
|
12
|
+
return error.message.includes(`'${packageName}'`);
|
|
13
|
+
}
|
|
14
|
+
function registeredModuleUrl(ownerRegistryKey) {
|
|
15
|
+
if (!ownerRegistryKey) return void 0;
|
|
16
|
+
const sourceFilePath = ObjectRegistry.getClass(ownerRegistryKey)?.sourceFilePath;
|
|
17
|
+
if (!sourceFilePath) return void 0;
|
|
18
|
+
if (sourceFilePath.startsWith("file:")) return sourceFilePath;
|
|
19
|
+
return isAbsolute(sourceFilePath) ? pathToFileURL(sourceFilePath).href : void 0;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resolve a serializer package from the running application's module graph.
|
|
23
|
+
*
|
|
24
|
+
* Model packages own serializer implementations but do not become dependencies
|
|
25
|
+
* of core or generic consumers such as Chat. Bare specifiers first use the
|
|
26
|
+
* active runtime module graph so workspace aliases keep one constructor
|
|
27
|
+
* identity. When the package is absent from Core's dependency graph, resolution
|
|
28
|
+
* continues from the module that registered the owning model (or an explicit
|
|
29
|
+
* host anchor), with ESM export conditions. Relative and URL references keep
|
|
30
|
+
* their declaring module's ordinary dynamic-import behavior.
|
|
31
|
+
*/
|
|
32
|
+
async function resolveMcpGetSerializer(reference, options = {}) {
|
|
33
|
+
let module;
|
|
34
|
+
let missingPackageError;
|
|
35
|
+
if (resolvesFromConsumer(reference.importPath)) try {
|
|
36
|
+
module = await import(reference.importPath);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (!isUnresolvedPackage(error, reference.importPath)) throw error;
|
|
39
|
+
missingPackageError = error;
|
|
40
|
+
}
|
|
41
|
+
if (!module) {
|
|
42
|
+
const consumerAnchorUrl = options.consumerAnchorUrl ?? registeredModuleUrl(options.ownerRegistryKey);
|
|
43
|
+
let resolvedImportPath;
|
|
44
|
+
if (resolvesFromConsumer(reference.importPath)) {
|
|
45
|
+
if (!consumerAnchorUrl) throw missingPackageError ?? /* @__PURE__ */ new Error(`MCP get serializer '${reference.importPath}' requires a registered model or host module anchor`);
|
|
46
|
+
resolvedImportPath = resolve$1(reference.importPath, consumerAnchorUrl);
|
|
47
|
+
} else resolvedImportPath = resolve$1(reference.importPath, options.parentUrl ?? import.meta.url);
|
|
48
|
+
module = await import(
|
|
49
|
+
/* @vite-ignore */
|
|
50
|
+
resolvedImportPath
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
const serializer = module[reference.exportName];
|
|
54
|
+
if (typeof serializer !== "function") throw new Error(`MCP get serializer '${reference.exportName}' was not exported by '${reference.importPath}'`);
|
|
55
|
+
return serializer;
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
export { resolveMcpGetSerializer };
|
|
59
|
+
|
|
60
|
+
//# sourceMappingURL=mcp-serializer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-serializer.js","names":[],"sources":["../src/mcp-serializer.ts"],"sourcesContent":["import { isAbsolute } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { resolve as resolveImport } from 'import-meta-resolve';\nimport type { PublicJsonOptions, SmrtObject } from './object.js';\nimport { ObjectRegistry } from './registry.js';\n\n/** A named module export that projects an admitted MCP `get` result. */\nexport type McpGetSerializer = (\n item: SmrtObject,\n options: PublicJsonOptions,\n) => unknown | Promise<unknown>;\n\n/** Package-owned location of an MCP `get` result serializer. */\nexport interface McpGetSerializerReference {\n importPath: string;\n exportName: string;\n}\n\nexport interface McpGetSerializerResolveOptions {\n /**\n * Module URL that owns a relative serializer reference. Omit only when the\n * resolver itself owns that relative reference.\n */\n parentUrl?: string;\n\n /**\n * Qualified registry key of the model that declared the serializer. Its\n * loaded module is the default anchor for resolving a bare package.\n */\n ownerRegistryKey?: string;\n\n /**\n * Explicit application module URL for a host that resolves a serializer\n * outside a registered MCP model.\n */\n consumerAnchorUrl?: string;\n}\n\nfunction resolvesFromConsumer(importPath: string): boolean {\n return (\n !importPath.startsWith('.') &&\n !isAbsolute(importPath) &&\n !importPath.startsWith('file:') &&\n !importPath.startsWith('data:') &&\n !importPath.startsWith('node:')\n );\n}\n\nfunction isUnresolvedPackage(error: unknown, importPath: string): boolean {\n if (\n !(error instanceof Error) ||\n (error as Error & { code?: string }).code !== 'ERR_MODULE_NOT_FOUND'\n )\n return false;\n const packageName = importPath.startsWith('@')\n ? importPath.split('/').slice(0, 2).join('/')\n : importPath.split('/')[0];\n return error.message.includes(`'${packageName}'`);\n}\n\nfunction registeredModuleUrl(\n ownerRegistryKey: string | undefined,\n): string | undefined {\n if (!ownerRegistryKey) return undefined;\n const sourceFilePath =\n ObjectRegistry.getClass(ownerRegistryKey)?.sourceFilePath;\n if (!sourceFilePath) return undefined;\n if (sourceFilePath.startsWith('file:')) return sourceFilePath;\n return isAbsolute(sourceFilePath)\n ? pathToFileURL(sourceFilePath).href\n : undefined;\n}\n\n/**\n * Resolve a serializer package from the running application's module graph.\n *\n * Model packages own serializer implementations but do not become dependencies\n * of core or generic consumers such as Chat. Bare specifiers first use the\n * active runtime module graph so workspace aliases keep one constructor\n * identity. When the package is absent from Core's dependency graph, resolution\n * continues from the module that registered the owning model (or an explicit\n * host anchor), with ESM export conditions. Relative and URL references keep\n * their declaring module's ordinary dynamic-import behavior.\n */\nexport async function resolveMcpGetSerializer(\n reference: McpGetSerializerReference,\n options: McpGetSerializerResolveOptions = {},\n): Promise<McpGetSerializer> {\n let module: Record<string, unknown> | undefined;\n let missingPackageError: unknown;\n if (resolvesFromConsumer(reference.importPath)) {\n try {\n module = (await import(reference.importPath)) as Record<string, unknown>;\n } catch (error) {\n if (!isUnresolvedPackage(error, reference.importPath)) throw error;\n missingPackageError = error;\n }\n }\n if (!module) {\n const consumerAnchorUrl =\n options.consumerAnchorUrl ??\n registeredModuleUrl(options.ownerRegistryKey);\n let resolvedImportPath: string;\n if (resolvesFromConsumer(reference.importPath)) {\n if (!consumerAnchorUrl) {\n throw (\n missingPackageError ??\n new Error(\n `MCP get serializer '${reference.importPath}' requires a registered model or host module anchor`,\n )\n );\n }\n resolvedImportPath = resolveImport(\n reference.importPath,\n consumerAnchorUrl,\n );\n } else {\n resolvedImportPath = resolveImport(\n reference.importPath,\n options.parentUrl ?? import.meta.url,\n );\n }\n module = (await import(/* @vite-ignore */ resolvedImportPath)) as Record<\n string,\n unknown\n >;\n }\n const serializer = module[reference.exportName];\n if (typeof serializer !== 'function') {\n throw new Error(\n `MCP get serializer '${reference.exportName}' was not exported by '${reference.importPath}'`,\n );\n }\n return serializer as McpGetSerializer;\n}\n"],"mappings":";;;;;AAsCA,SAAS,qBAAqB,YAA6B;CACzD,OACE,CAAC,WAAW,WAAW,GAAG,KAC1B,CAAC,WAAW,UAAU,KACtB,CAAC,WAAW,WAAW,OAAO,KAC9B,CAAC,WAAW,WAAW,OAAO,KAC9B,CAAC,WAAW,WAAW,OAAO;AAElC;AAEA,SAAS,oBAAoB,OAAgB,YAA6B;CACxE,IACE,EAAE,iBAAiB,UAClB,MAAoC,SAAS,wBAE9C,OAAO;CACT,MAAM,cAAc,WAAW,WAAW,GAAG,IACzC,WAAW,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,IAC1C,WAAW,MAAM,GAAG,CAAC,CAAC;CAC1B,OAAO,MAAM,QAAQ,SAAS,IAAI,YAAY,EAAE;AAClD;AAEA,SAAS,oBACP,kBACoB;CACpB,IAAI,CAAC,kBAAkB,OAAO,KAAA;CAC9B,MAAM,iBACJ,eAAe,SAAS,gBAAgB,CAAC,EAAE;CAC7C,IAAI,CAAC,gBAAgB,OAAO,KAAA;CAC5B,IAAI,eAAe,WAAW,OAAO,GAAG,OAAO;CAC/C,OAAO,WAAW,cAAc,IAC5B,cAAc,cAAc,CAAC,CAAC,OAC9B,KAAA;AACN;;;;;;;;;;;;AAaA,eAAsB,wBACpB,WACA,UAA0C,CAAC,GAChB;CAC3B,IAAI;CACJ,IAAI;CACJ,IAAI,qBAAqB,UAAU,UAAU,GAC3C,IAAI;EACF,SAAU,MAAM,OAAO,UAAU;CACnC,SAAS,OAAO;EACd,IAAI,CAAC,oBAAoB,OAAO,UAAU,UAAU,GAAG,MAAM;EAC7D,sBAAsB;CACxB;CAEF,IAAI,CAAC,QAAQ;EACX,MAAM,oBACJ,QAAQ,qBACR,oBAAoB,QAAQ,gBAAgB;EAC9C,IAAI;EACJ,IAAI,qBAAqB,UAAU,UAAU,GAAG;GAC9C,IAAI,CAAC,mBACH,MACE,uCACA,IAAI,MACF,uBAAuB,UAAU,WAAW,oDAC9C;GAGJ,qBAAqB,UACnB,UAAU,YACV,iBACF;EACF,OACE,qBAAqB,UACnB,UAAU,YACV,QAAQ,aAAa,OAAO,KAAK,GACnC;EAEF,SAAU,MAAM;;GAA0B;;CAI5C;CACA,MAAM,aAAa,OAAO,UAAU;CACpC,IAAI,OAAO,eAAe,YACxB,MAAM,IAAI,MACR,uBAAuB,UAAU,WAAW,yBAAyB,UAAU,WAAW,EAC5F;CAEF,OAAO;AACT"}
|
package/dist/node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defaultResolve } from "./lib/resolve.js";
|
|
2
|
+
//#region ../../node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/index.js
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import('./lib/errors.js').ErrnoException} ErrnoException
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Match `import.meta.resolve` except that `parent` is required (you can pass
|
|
8
|
+
* `import.meta.url`).
|
|
9
|
+
*
|
|
10
|
+
* @param {string} specifier
|
|
11
|
+
* The module specifier to resolve relative to parent
|
|
12
|
+
* (`/example.js`, `./example.js`, `../example.js`, `some-package`, `fs`,
|
|
13
|
+
* etc).
|
|
14
|
+
* @param {string} parent
|
|
15
|
+
* The absolute parent module URL to resolve from.
|
|
16
|
+
* You must pass `import.meta.url` or something else.
|
|
17
|
+
* @returns {string}
|
|
18
|
+
* Returns a string to a full `file:`, `data:`, or `node:` URL
|
|
19
|
+
* to the found thing.
|
|
20
|
+
*/
|
|
21
|
+
function resolve(specifier, parent) {
|
|
22
|
+
if (!parent) throw new Error("Please pass `parent`: `import-meta-resolve` cannot ponyfill that");
|
|
23
|
+
try {
|
|
24
|
+
return defaultResolve(specifier, { parentURL: parent }).url;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
const exception = error;
|
|
27
|
+
if ((exception.code === "ERR_UNSUPPORTED_DIR_IMPORT" || exception.code === "ERR_MODULE_NOT_FOUND") && typeof exception.url === "string") return exception.url;
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { resolve };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../../../../../node_modules/.pnpm/import-meta-resolve@4.2.0/node_modules/import-meta-resolve/index.js"],"sourcesContent":["/**\n * @typedef {import('./lib/errors.js').ErrnoException} ErrnoException\n */\n\nimport {defaultResolve} from './lib/resolve.js'\n\nexport {moduleResolve} from './lib/resolve.js'\n\n/**\n * Match `import.meta.resolve` except that `parent` is required (you can pass\n * `import.meta.url`).\n *\n * @param {string} specifier\n * The module specifier to resolve relative to parent\n * (`/example.js`, `./example.js`, `../example.js`, `some-package`, `fs`,\n * etc).\n * @param {string} parent\n * The absolute parent module URL to resolve from.\n * You must pass `import.meta.url` or something else.\n * @returns {string}\n * Returns a string to a full `file:`, `data:`, or `node:` URL\n * to the found thing.\n */\nexport function resolve(specifier, parent) {\n if (!parent) {\n throw new Error(\n 'Please pass `parent`: `import-meta-resolve` cannot ponyfill that'\n )\n }\n\n try {\n return defaultResolve(specifier, {parentURL: parent}).url\n } catch (error) {\n // See: <https://github.com/nodejs/node/blob/45f5c9b/lib/internal/modules/esm/initialize_import_meta.js#L34>\n const exception = /** @type {ErrnoException} */ (error)\n\n if (\n (exception.code === 'ERR_UNSUPPORTED_DIR_IMPORT' ||\n exception.code === 'ERR_MODULE_NOT_FOUND') &&\n typeof exception.url === 'string'\n ) {\n return exception.url\n }\n\n throw error\n }\n}\n"],"x_google_ignoreList":[0],"mappings":";;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,QAAQ,WAAW,QAAQ;CACzC,IAAI,CAAC,QACH,MAAM,IAAI,MACR,kEACF;CAGF,IAAI;EACF,OAAO,eAAe,WAAW,EAAC,WAAW,OAAM,CAAC,CAAC,CAAC;CACxD,SAAS,OAAO;EAEd,MAAM,YAA2C;EAEjD,KACG,UAAU,SAAS,gCAClB,UAAU,SAAS,2BACrB,OAAO,UAAU,QAAQ,UAEzB,OAAO,UAAU;EAGnB,MAAM;CACR;AACF"}
|