@happyvertical/smrt-core 0.40.55 → 0.40.56
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/dist/consumer-plugin/index.d.ts.map +1 -1
- package/dist/consumer-plugin/index.js +4 -3
- package/dist/consumer-plugin/index.js.map +1 -1
- package/dist/manifest/generator.d.ts.map +1 -1
- package/dist/manifest/generator.js +2 -1
- package/dist/manifest/generator.js.map +1 -1
- package/dist/manifest/manifest-loader.d.ts.map +1 -1
- package/dist/manifest/manifest-loader.js +2 -1
- package/dist/manifest/manifest-loader.js.map +1 -1
- package/dist/manifest/static-manifest.js +2 -2
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.d.ts.map +1 -1
- package/dist/manifest/store.js +3 -2
- package/dist/manifest/store.js.map +1 -1
- package/dist/manifest/test-manifest-stub.js +2 -2
- package/dist/manifest/test-manifest-stub.js.map +1 -1
- package/dist/manifest.json +2 -2
- package/dist/scanner/manifest-generator.d.ts.map +1 -1
- package/dist/scanner/manifest-generator.js +2 -1
- package/dist/scanner/manifest-generator.js.map +1 -1
- package/dist/scanner/types.d.ts +33 -0
- package/dist/scanner/types.d.ts.map +1 -1
- package/dist/scanner/types.js +37 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/schema/code-generator.d.ts.map +1 -1
- package/dist/schema/code-generator.js +2 -1
- package/dist/schema/code-generator.js.map +1 -1
- package/dist/scripts/generate-manifest.js +14 -2
- package/dist/smrt-knowledge.json +4 -4
- package/dist/vite-plugin/index.d.ts +1 -1
- package/dist/vite-plugin/index.d.ts.map +1 -1
- package/dist/vite-plugin/index.js +18 -4
- package/dist/vite-plugin/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/consumer-plugin/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/consumer-plugin/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAwDnC,MAAM,WAAW,mBAAmB;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,uCAAuC;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oDAAoD;IACpD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4BAA4B;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAiBD;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,MAAM,CA0GtE"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "../scanner/types.js";
|
|
1
2
|
import { generateClientModule } from "../vite-plugin/generated-client.js";
|
|
2
3
|
import { generateDeclarations } from "../prebuild/index.js";
|
|
3
4
|
import * as fs from "node:fs";
|
|
@@ -41,7 +42,7 @@ function smrtConsumer(options = {}) {
|
|
|
41
42
|
console.log("[smrt:consumer] No SMRT packages found");
|
|
42
43
|
typeManifest = {
|
|
43
44
|
version: "1.0.0",
|
|
44
|
-
timestamp:
|
|
45
|
+
timestamp: 0,
|
|
45
46
|
objects: {}
|
|
46
47
|
};
|
|
47
48
|
}
|
|
@@ -59,7 +60,7 @@ function smrtConsumer(options = {}) {
|
|
|
59
60
|
const cleanId = id.startsWith("\0") ? id.slice(1) : id;
|
|
60
61
|
if (!typeManifest) typeManifest = {
|
|
61
62
|
version: "1.0.0",
|
|
62
|
-
timestamp:
|
|
63
|
+
timestamp: 0,
|
|
63
64
|
objects: {}
|
|
64
65
|
};
|
|
65
66
|
switch (cleanId) {
|
|
@@ -118,7 +119,7 @@ async function hasSmrtManifest(nodeModulesPath, packageName) {
|
|
|
118
119
|
async function aggregateTypeManifests(packages, projectRoot) {
|
|
119
120
|
const aggregatedManifest = {
|
|
120
121
|
version: "1.0.0",
|
|
121
|
-
timestamp:
|
|
122
|
+
timestamp: 0,
|
|
122
123
|
objects: {}
|
|
123
124
|
};
|
|
124
125
|
for (const packageName of packages) try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/consumer-plugin/index.ts"],"sourcesContent":["/**\n * Vite plugin for consuming SMRT packages\n * Solves virtual module resolution in downstream projects\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { Plugin } from 'vite';\nimport { generateDeclarations } from '../prebuild/index.js';\nimport type { SmartObjectManifest } from '../scanner/types.js';\nimport { generateClientModule } from '../vite-plugin/generated-client.js';\n\n/**\n * Loosely-typed view of an object definition as carried by an external\n * package's static manifest. The static manifests are read from JSON at the\n * package boundary, so only the fields this plugin consumes are typed; the\n * index signature preserves any additional fields (e.g. for spreads). This is\n * a structural superset of a manifest `SmartObjectDefinition` plus the\n * consumer-only `hasCollection` marker.\n */\ninterface ConsumerObjectDefinition {\n className?: string;\n packageName?: string;\n packageVersion?: string;\n qualifiedName?: string;\n importPath?: string;\n exportName?: string;\n collectionExportName?: string;\n hasCollection?: boolean;\n collection?: string;\n extends?: string;\n extendsQualified?: string;\n extendsTypeArg?: string;\n [key: string]: unknown;\n}\n\n/**\n * Aggregated manifest assembled by the consumer plugin from one or more\n * external package manifests. Loosely typed because the inputs originate from\n * JSON read at the package boundary.\n */\ninterface ConsumerManifest {\n version: string;\n timestamp: number;\n packageName?: string;\n packageVersion?: string;\n objects: Record<string, ConsumerObjectDefinition>;\n}\n\n/**\n * Minimal structural shape of a parsed `package.json` consumed here (name,\n * version, and the export map used to derive import paths). The index\n * signature keeps the remaining fields accessible.\n */\ninterface ConsumerPackageJson {\n name?: string;\n version?: string;\n main?: string;\n exports?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface SmrtConsumerOptions {\n /** SMRT packages to scan (e.g., ['@my-org/products', '@my-org/content']) */\n packages?: string[];\n /** Generate TypeScript declarations */\n generateTypes?: boolean;\n /** Output directory for generated types */\n typesDir?: string;\n /** Project root path */\n projectRoot?: string;\n /** SvelteKit integration mode */\n svelteKit?: boolean;\n /**\n * Apply kebab-case to generated custom-method URL segments. This must match\n * the producer plugin's `svelteKit.kebabRoutes` setting.\n */\n kebabRoutes?: boolean;\n /** Use static types only (for federation builds) */\n staticTypes?: boolean;\n /** Disable file scanning */\n disableScanning?: boolean;\n}\n\n// Distinct resolved ids per plugin (#1795). smrtPlugin resolves\n// `@happyvertical/smrt-virt-*` to `\\0smrt:*`; if this consumer plugin also\n// resolved its `@smrt/*` specifiers to `\\0smrt:*` the two virtual modules would\n// share a rollup id, and in standalone/federation builds the consumer's\n// fallback `load` would non-deterministically win and shadow smrtPlugin's real\n// module. Namespacing the consumer ids (`\\0smrt-consumer:*`) keeps them\n// separate so each plugin only ever loads its own module.\nconst VIRTUAL_MODULES = {\n '@smrt/routes': 'smrt-consumer:routes',\n '@smrt/client': 'smrt-consumer:client',\n '@smrt/mcp': 'smrt-consumer:mcp',\n '@smrt/types': 'smrt-consumer:types',\n '@smrt/manifest': 'smrt-consumer:manifest',\n};\n\n/**\n * Consumer plugin for projects that use SMRT packages\n */\nexport function smrtConsumer(options: SmrtConsumerOptions = {}): Plugin {\n const {\n packages = [],\n generateTypes = true,\n typesDir = 'src/types/smrt-generated',\n projectRoot = process.cwd(),\n disableScanning = false,\n kebabRoutes = false,\n } = options;\n\n let smrtPackages: string[] = [];\n let typeManifest: ConsumerManifest | null = null;\n let typesGenerated = false;\n\n return {\n name: 'smrt-consumer',\n\n async buildStart() {\n console.log('[smrt:consumer] Initializing SMRT consumer plugin');\n\n // Discover SMRT packages if not explicitly specified\n if (packages.length === 0 && !disableScanning) {\n smrtPackages = await discoverSmrtPackages(projectRoot);\n } else {\n smrtPackages = packages;\n }\n\n if (smrtPackages.length > 0) {\n console.log(\n `[smrt:consumer] Found SMRT packages: ${smrtPackages.join(', ')}`,\n );\n\n // Aggregate type manifests from discovered packages\n typeManifest = await aggregateTypeManifests(smrtPackages, projectRoot);\n\n // Save aggregated manifest for CLI discovery\n await saveAggregatedManifest(typeManifest, projectRoot);\n\n // Generate registration file for CLI class loading\n await generateRegistrationFile(typeManifest, projectRoot);\n\n // Generate types if requested\n if (generateTypes && !typesGenerated) {\n await generateProjectTypes(typeManifest, typesDir, projectRoot);\n typesGenerated = true;\n }\n } else {\n console.log('[smrt:consumer] No SMRT packages found');\n typeManifest = { version: '1.0.0', timestamp: Date.now(), objects: {} };\n }\n },\n\n resolveId(id, _importer) {\n // Resolve virtual modules to generated type declarations\n if (id in VIRTUAL_MODULES) {\n const typeFileName = getTypeFileName(id);\n const typePath = path.join(projectRoot, typesDir, typeFileName);\n\n // If types file exists, resolve to it\n if (fs.existsSync(typePath)) {\n return typePath;\n }\n\n // Otherwise use virtual module ID for runtime resolution\n return `\\0${VIRTUAL_MODULES[id as keyof typeof VIRTUAL_MODULES]}`;\n }\n return null;\n },\n\n async load(id) {\n // Handle virtual modules if types aren't available\n const cleanId = id.startsWith('\\0') ? id.slice(1) : id;\n\n if (!typeManifest) {\n typeManifest = { version: '1.0.0', timestamp: Date.now(), objects: {} };\n }\n\n switch (cleanId) {\n case 'smrt-consumer:routes':\n return generateFallbackRoutesModule();\n\n case 'smrt-consumer:client':\n return generateFallbackClientModule(typeManifest, { kebabRoutes });\n\n case 'smrt-consumer:mcp':\n return generateFallbackMcpModule();\n\n case 'smrt-consumer:types':\n return generateFallbackTypesModule(typeManifest);\n\n case 'smrt-consumer:manifest':\n return generateFallbackManifestModule(typeManifest);\n\n default:\n return null;\n }\n },\n };\n}\n\n/**\n * Discover SMRT packages from a consumer app's dependencies.\n *\n * Intentional split (#1579): this **consumer-plugin** path is async and\n * resolves SMRT packages from the downstream app's `package.json` dependency\n * names (`@have/`/`smrt` heuristic + `hasSmrtManifest` probe) inside the Vite\n * consumer plugin. It is deliberately separate from the build-time\n * `discoverSmrtPackages()` in `src/manifest/discover-smrt-packages.ts` — a\n * synchronous, lockfile-cached `node_modules` manifest scan used for manifest\n * generation. Different inputs, contexts, and lifecycles, not duplicated logic.\n */\nasync function discoverSmrtPackages(projectRoot: string): Promise<string[]> {\n const packages: string[] = [];\n const nodeModulesPath = path.join(projectRoot, 'node_modules');\n\n if (!fs.existsSync(nodeModulesPath)) {\n return packages;\n }\n\n try {\n // Check package.json for workspace dependencies\n const packageJsonPath = path.join(projectRoot, 'package.json');\n if (fs.existsSync(packageJsonPath)) {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const allDeps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n ...packageJson.peerDependencies,\n };\n\n // Look for packages that likely contain SMRT objects\n for (const [name, version] of Object.entries(allDeps)) {\n if (\n typeof version === 'string' &&\n (name.includes('smrt') ||\n name.includes('@have/') ||\n (await hasSmrtManifest(nodeModulesPath, name)))\n ) {\n packages.push(name);\n }\n }\n }\n } catch (error) {\n console.warn('[smrt:consumer] Error discovering packages:', error);\n }\n\n return packages;\n}\n\n/**\n * Check if a package has SMRT manifest\n */\nasync function hasSmrtManifest(\n nodeModulesPath: string,\n packageName: string,\n): Promise<boolean> {\n const packagePath = path.join(nodeModulesPath, packageName);\n const manifestPath = path.join(\n packagePath,\n 'dist',\n 'manifest',\n 'static-manifest.js',\n );\n return fs.existsSync(manifestPath);\n}\n\n/**\n * Aggregate type manifests from multiple packages\n */\nasync function aggregateTypeManifests(\n packages: string[],\n projectRoot: string,\n): Promise<ConsumerManifest> {\n const aggregatedManifest: ConsumerManifest = {\n version: '1.0.0',\n timestamp: Date.now(),\n objects: {},\n };\n\n for (const packageName of packages) {\n try {\n const packageDir = path.join(projectRoot, 'node_modules', packageName);\n\n // Load package.json for version and export information\n const packageJsonPath = path.join(packageDir, 'package.json');\n let packageJson: ConsumerPackageJson;\n try {\n const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf-8');\n packageJson = JSON.parse(packageJsonContent) as ConsumerPackageJson;\n } catch {\n console.warn(\n `[smrt:consumer] Could not read package.json for ${packageName}`,\n );\n continue;\n }\n\n // Try multiple manifest locations\n const manifestCandidates = [\n path.join(packageDir, 'dist', 'manifest', 'static-manifest.js'),\n path.join(packageDir, 'dist', 'manifest.json'),\n path.join(packageDir, 'manifest.json'),\n ];\n\n for (const manifestPath of manifestCandidates) {\n if (fs.existsSync(manifestPath)) {\n // Import or read the manifest\n let manifest: Partial<ConsumerManifest> | undefined;\n if (manifestPath.endsWith('.js')) {\n const manifestModule = await import(manifestPath);\n manifest = manifestModule.staticManifest || manifestModule.default;\n } else {\n const manifestContent = fs.readFileSync(manifestPath, 'utf-8');\n manifest = JSON.parse(manifestContent) as Partial<ConsumerManifest>;\n }\n\n if (manifest?.objects) {\n console.log(\n `[smrt:consumer] Loaded manifest from ${packageName} (${Object.keys(manifest.objects).length} objects)`,\n );\n\n // ENHANCED: Preserve package metadata for each object\n for (const [objectName, objectDef] of Object.entries(\n manifest.objects,\n )) {\n const def = objectDef;\n\n aggregatedManifest.objects[objectName] = {\n ...def,\n // Ensure package metadata is preserved/set\n packageName:\n def.packageName || manifest.packageName || packageName,\n packageVersion:\n def.packageVersion ||\n manifest.packageVersion ||\n packageJson.version,\n // Add fallback import paths if missing\n importPath: def.importPath || determineImportPath(packageJson),\n exportName: def.exportName || def.className || objectName,\n collectionExportName:\n def.collectionExportName ||\n `${def.className || objectName}Collection`,\n };\n }\n\n break; // Use first found manifest for this package\n }\n }\n }\n } catch (error) {\n console.warn(\n `[smrt:consumer] Error loading manifest from ${packageName}:`,\n error,\n );\n }\n }\n\n return aggregatedManifest;\n}\n\n/**\n * Determine import path from package.json\n */\nfunction determineImportPath(packageJson: ConsumerPackageJson): string {\n const packageName = packageJson.name;\n\n if (!packageName) {\n throw new Error('Package name not found in package.json');\n }\n\n // Strategy 1: Check for specific exports\n if (packageJson.exports) {\n // Check for objects export\n if (packageJson.exports['./objects']) {\n return `${packageName}/objects`;\n }\n\n // Check for main export\n const mainExport = packageJson.exports['.'];\n if (mainExport) {\n // Handle conditional exports\n if (typeof mainExport === 'object' && mainExport !== null) {\n const conditional = mainExport as Record<string, unknown>;\n if (conditional.import) {\n return packageName;\n }\n if (conditional.default) {\n return packageName;\n }\n }\n return packageName;\n }\n }\n\n // Strategy 2: Check main field\n if (packageJson.main) {\n return packageName;\n }\n\n // Strategy 3: Fallback to package name\n return packageName;\n}\n\n/**\n * Save aggregated manifest to .smrt/manifest.json for CLI discovery.\n *\n * Merge-preserving: `smrtPlugin()` writes the project's own scanned objects\n * to the same file (`writeLocalManifest`, issue #963), and both writes happen\n * in parallel `buildStart` hooks — so a plain overwrite here would clobber\n * the local objects whenever this plugin's write lands last (issue #1760\n * review). Local field metadata would then silently vanish from CLI schema\n * commands and from server runtimes that seed `.smrt/manifest.json`, dropping\n * domain columns on write. This function therefore only ADDS/refreshes the\n * external-package entries it owns and preserves everything else already in\n * the file (including the top-level `packageName` the local write sets).\n */\nasync function saveAggregatedManifest(\n manifest: ConsumerManifest,\n projectRoot: string,\n): Promise<void> {\n const smrtDir = path.join(projectRoot, '.smrt');\n const manifestPath = path.join(smrtDir, 'manifest.json');\n\n try {\n // Create .smrt directory if it doesn't exist\n if (!fs.existsSync(smrtDir)) {\n fs.mkdirSync(smrtDir, { recursive: true });\n }\n\n // Merge with whatever is on disk: existing entries (typically the local\n // project's objects written by smrtPlugin) are preserved; aggregated\n // external entries win for the qualified names this plugin owns.\n let merged: ConsumerManifest = manifest;\n if (fs.existsSync(manifestPath)) {\n try {\n const existing = JSON.parse(\n fs.readFileSync(manifestPath, 'utf-8'),\n ) as Partial<ConsumerManifest>;\n if (existing && typeof existing.objects === 'object') {\n merged = {\n ...existing,\n ...manifest,\n // The aggregated manifest carries no packageName; keep the local\n // project's (used as the manifest cache key at runtime).\n ...(existing.packageName\n ? { packageName: existing.packageName }\n : {}),\n objects: { ...existing.objects, ...manifest.objects },\n };\n }\n } catch {\n // Unreadable/corrupt existing file — fall back to a plain write.\n }\n }\n\n // Write manifest\n fs.writeFileSync(manifestPath, JSON.stringify(merged, null, 2), 'utf-8');\n\n console.log(\n `[smrt:consumer] Saved aggregated manifest to .smrt/manifest.json (${Object.keys(merged.objects).length} objects)`,\n );\n } catch (error) {\n console.warn('[smrt:consumer] Failed to save aggregated manifest:', error);\n }\n}\n\n/**\n * Generate registration file for CLI class loading\n *\n * Creates .smrt/register.js with static imports and registrations\n * for all external SMRT objects discovered during build.\n */\nasync function generateRegistrationFile(\n manifest: ConsumerManifest,\n projectRoot: string,\n): Promise<void> {\n const smrtDir = path.join(projectRoot, '.smrt');\n const registerPath = path.join(smrtDir, 'register.js');\n\n // Build import statements and registrations\n const imports: string[] = [];\n const registrations: string[] = [];\n let importedEntryCount = 0;\n let registeredObjectCount = 0;\n\n const manifestObjects = manifest.objects;\n const manifestObjectLookup = new Map<string, ConsumerObjectDefinition>();\n for (const [key, def] of Object.entries(manifestObjects)) {\n const candidate = def;\n const lookupKeys = [\n key,\n key.includes(':') ? key.split(':').pop() : undefined,\n candidate.qualifiedName,\n candidate.className,\n candidate.exportName,\n ];\n\n for (const lookupKey of lookupKeys) {\n if (lookupKey && !manifestObjectLookup.has(lookupKey)) {\n manifestObjectLookup.set(lookupKey, candidate);\n }\n }\n }\n\n const collectionClassMemo = new WeakMap<object, boolean>();\n\n const isCollectionClass = (\n def: ConsumerObjectDefinition | undefined,\n seen = new Set<string>(),\n ): boolean => {\n if (!def || typeof def !== 'object') {\n return false;\n }\n\n const cached = collectionClassMemo.get(def);\n if (cached !== undefined) {\n return cached;\n }\n\n if (\n def?.extends === 'SmrtCollection' ||\n def?.extendsTypeArg !== undefined\n ) {\n collectionClassMemo.set(def, true);\n return true;\n }\n\n const parentName = def?.extendsQualified || def?.extends;\n if (!parentName || seen.has(parentName)) {\n collectionClassMemo.set(def, false);\n return false;\n }\n seen.add(parentName);\n\n const parentDef = manifestObjectLookup.get(parentName);\n const isCollection = parentDef ? isCollectionClass(parentDef, seen) : false;\n collectionClassMemo.set(def, isCollection);\n\n return isCollection;\n };\n\n for (const [objectName, objectDef] of Object.entries(manifestObjects)) {\n const def = objectDef;\n\n // Skip local objects (they're imported from local entry point)\n if (!def.packageName || def.packageName === manifest.packageName) {\n continue;\n }\n\n const importPath = def.importPath || def.packageName;\n const exportName = def.exportName || def.className || objectName;\n const collectionExportName = def.collectionExportName;\n const hasCollection = def.hasCollection; // Check if collection class actually exists\n const tableName = def.collection || objectName.toLowerCase();\n\n // Generate import statement\n // Only import collection if it exists (hasCollection is truthy)\n if (hasCollection && collectionExportName) {\n imports.push(\n `import { ${exportName}, ${collectionExportName} } from '${importPath}';`,\n );\n } else {\n imports.push(`import { ${exportName} } from '${importPath}';`);\n }\n importedEntryCount++;\n\n if (isCollectionClass(def)) {\n continue;\n }\n\n // Generate registration calls\n // The import above already triggers the @smrt() decorator which registers the class\n // properly with its simple name and qualified name. We call register() again with\n // an empty config just to ensure the class is registered (in case it lacks a decorator).\n // Do NOT pass { name: qualifiedName } as that creates a separate registry entry.\n registrations.push(\n `ObjectRegistry.register(${exportName}, { name: ${JSON.stringify(exportName)}, packageName: ${JSON.stringify(def.packageName)} });`,\n );\n\n // Only register collection if it exists\n if (hasCollection && collectionExportName) {\n registrations.push(\n `ObjectRegistry.registerCollection('${tableName}', ${collectionExportName});`,\n );\n }\n\n registeredObjectCount++;\n }\n\n // Skip generation if no external entries\n if (importedEntryCount === 0) {\n console.log('[smrt:consumer] No external entries - skipping register.js');\n return;\n }\n\n const registeredObjectLabel =\n registeredObjectCount === 1 ? 'object' : 'objects';\n\n // Generate file content\n const content = `/**\n * Auto-generated by @happyvertical/smrt-core/consumer-plugin\n * DO NOT EDIT - This file is regenerated on every build\n *\n * Registers SMRT objects from external packages for CLI discovery.\n * Generated at: ${new Date().toISOString()}\n */\n\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n${imports.join('\\n')}\n\n// Register all objects (executed during module evaluation)\n${registrations.join('\\n')}\n\nexport function registerAll() {\n // Objects are already registered during module evaluation\n console.log('[smrt:register] Registered ${registeredObjectCount} external ${registeredObjectLabel}');\n}\n`;\n\n // Create .smrt directory if needed\n if (!fs.existsSync(smrtDir)) {\n fs.mkdirSync(smrtDir, { recursive: true });\n }\n\n // Write registration file\n fs.writeFileSync(registerPath, content, 'utf-8');\n\n console.log(\n `[smrt:consumer] Generated .smrt/register.js with ${importedEntryCount} external entries (${registeredObjectCount} registered ${registeredObjectLabel})`,\n );\n}\n\n/**\n * Generate project-specific types\n */\nasync function generateProjectTypes(\n typeManifest: ConsumerManifest,\n typesDir: string,\n projectRoot: string,\n): Promise<void> {\n if (!typeManifest || Object.keys(typeManifest.objects).length === 0) {\n console.log(\n '[smrt:consumer] No SMRT objects found, skipping type generation',\n );\n return;\n }\n\n await generateDeclarations({\n // The aggregated manifest is a runtime SMRT manifest assembled from external\n // package manifests; it is intentionally typed loosely at the JSON boundary,\n // so narrow it to the declaration generator's strict manifest shape here.\n manifest: typeManifest as unknown as SmartObjectManifest,\n outDir: typesDir,\n projectRoot,\n includeVirtualModules: true,\n includeObjectTypes: true,\n });\n\n console.log(\n `[smrt:consumer] Generated types for ${Object.keys(typeManifest.objects).length} objects`,\n );\n}\n\n/**\n * Get type file name for virtual module\n */\nfunction getTypeFileName(virtualModule: string): string {\n const moduleMap: Record<string, string> = {\n '@smrt/routes': 'smrt-routes.d.ts',\n '@smrt/client': 'smrt-client.d.ts',\n '@smrt/mcp': 'smrt-mcp.d.ts',\n '@smrt/types': 'smrt-types.d.ts',\n '@smrt/manifest': 'smrt-manifest.d.ts',\n };\n return moduleMap[virtualModule] || 'smrt-unknown.d.ts';\n}\n\n/**\n * Fallback modules for when types aren't available\n */\nfunction generateFallbackRoutesModule(): string {\n return `\n// Fallback routes module\nexport function setupRoutes(app) {\n console.warn('[smrt:consumer] No routes available - SMRT packages may not be properly configured');\n}\nexport default setupRoutes;\n`;\n}\n\nfunction generateFallbackClientModule(\n manifest: ConsumerManifest,\n options: { kebabRoutes?: boolean } = {},\n): string {\n const objects = Object.entries(manifest?.objects || {});\n if (objects.length === 0) {\n return `\n// Fallback client module\nexport function createClient(basePath = '/api/v1') {\n console.warn('[smrt:consumer] No API client available - SMRT packages may not be properly configured');\n return {};\n}\nexport default createClient;\n`;\n }\n\n return generateClientModule(manifest as unknown as SmartObjectManifest, {\n kebabRoutes: options.kebabRoutes,\n });\n}\n\nfunction generateFallbackMcpModule(): string {\n return `\n// Fallback MCP module\nexport const tools = [];\nexport function createMCPServer() {\n console.warn('[smrt:consumer] No MCP tools available - SMRT packages may not be properly configured');\n return { name: 'smrt-consumer', version: '1.0.0', tools: [] };\n}\nexport default createMCPServer;\n`;\n}\n\nfunction generateFallbackTypesModule(manifest: ConsumerManifest): string {\n const objects = Object.entries(manifest?.objects || {});\n if (objects.length === 0) {\n return `// No types available`;\n }\n\n // Generate basic interfaces\n const interfaces = objects.map(([_name, obj]) => {\n return `export interface ${obj.className}Data {\n id?: string;\n created_at?: string;\n updated_at?: string;\n [key: string]: any;\n}`;\n });\n\n return interfaces.join('\\n\\n');\n}\n\nfunction generateFallbackManifestModule(manifest: ConsumerManifest): string {\n return `\n// Auto-generated manifest from SMRT consumer\nexport const manifest = ${JSON.stringify(manifest, null, 2)};\nexport default manifest;\n`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/consumer-plugin/index.ts"],"sourcesContent":["/**\n * Vite plugin for consuming SMRT packages\n * Solves virtual module resolution in downstream projects\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { Plugin } from 'vite';\nimport { generateDeclarations } from '../prebuild/index.js';\nimport type { SmartObjectManifest } from '../scanner/types.js';\nimport { MANIFEST_TIMESTAMP } from '../scanner/types.js';\nimport { generateClientModule } from '../vite-plugin/generated-client.js';\n\n/**\n * Loosely-typed view of an object definition as carried by an external\n * package's static manifest. The static manifests are read from JSON at the\n * package boundary, so only the fields this plugin consumes are typed; the\n * index signature preserves any additional fields (e.g. for spreads). This is\n * a structural superset of a manifest `SmartObjectDefinition` plus the\n * consumer-only `hasCollection` marker.\n */\ninterface ConsumerObjectDefinition {\n className?: string;\n packageName?: string;\n packageVersion?: string;\n qualifiedName?: string;\n importPath?: string;\n exportName?: string;\n collectionExportName?: string;\n hasCollection?: boolean;\n collection?: string;\n extends?: string;\n extendsQualified?: string;\n extendsTypeArg?: string;\n [key: string]: unknown;\n}\n\n/**\n * Aggregated manifest assembled by the consumer plugin from one or more\n * external package manifests. Loosely typed because the inputs originate from\n * JSON read at the package boundary.\n */\ninterface ConsumerManifest {\n version: string;\n timestamp: number;\n packageName?: string;\n packageVersion?: string;\n objects: Record<string, ConsumerObjectDefinition>;\n}\n\n/**\n * Minimal structural shape of a parsed `package.json` consumed here (name,\n * version, and the export map used to derive import paths). The index\n * signature keeps the remaining fields accessible.\n */\ninterface ConsumerPackageJson {\n name?: string;\n version?: string;\n main?: string;\n exports?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface SmrtConsumerOptions {\n /** SMRT packages to scan (e.g., ['@my-org/products', '@my-org/content']) */\n packages?: string[];\n /** Generate TypeScript declarations */\n generateTypes?: boolean;\n /** Output directory for generated types */\n typesDir?: string;\n /** Project root path */\n projectRoot?: string;\n /** SvelteKit integration mode */\n svelteKit?: boolean;\n /**\n * Apply kebab-case to generated custom-method URL segments. This must match\n * the producer plugin's `svelteKit.kebabRoutes` setting.\n */\n kebabRoutes?: boolean;\n /** Use static types only (for federation builds) */\n staticTypes?: boolean;\n /** Disable file scanning */\n disableScanning?: boolean;\n}\n\n// Distinct resolved ids per plugin (#1795). smrtPlugin resolves\n// `@happyvertical/smrt-virt-*` to `\\0smrt:*`; if this consumer plugin also\n// resolved its `@smrt/*` specifiers to `\\0smrt:*` the two virtual modules would\n// share a rollup id, and in standalone/federation builds the consumer's\n// fallback `load` would non-deterministically win and shadow smrtPlugin's real\n// module. Namespacing the consumer ids (`\\0smrt-consumer:*`) keeps them\n// separate so each plugin only ever loads its own module.\nconst VIRTUAL_MODULES = {\n '@smrt/routes': 'smrt-consumer:routes',\n '@smrt/client': 'smrt-consumer:client',\n '@smrt/mcp': 'smrt-consumer:mcp',\n '@smrt/types': 'smrt-consumer:types',\n '@smrt/manifest': 'smrt-consumer:manifest',\n};\n\n/**\n * Consumer plugin for projects that use SMRT packages\n */\nexport function smrtConsumer(options: SmrtConsumerOptions = {}): Plugin {\n const {\n packages = [],\n generateTypes = true,\n typesDir = 'src/types/smrt-generated',\n projectRoot = process.cwd(),\n disableScanning = false,\n kebabRoutes = false,\n } = options;\n\n let smrtPackages: string[] = [];\n let typeManifest: ConsumerManifest | null = null;\n let typesGenerated = false;\n\n return {\n name: 'smrt-consumer',\n\n async buildStart() {\n console.log('[smrt:consumer] Initializing SMRT consumer plugin');\n\n // Discover SMRT packages if not explicitly specified\n if (packages.length === 0 && !disableScanning) {\n smrtPackages = await discoverSmrtPackages(projectRoot);\n } else {\n smrtPackages = packages;\n }\n\n if (smrtPackages.length > 0) {\n console.log(\n `[smrt:consumer] Found SMRT packages: ${smrtPackages.join(', ')}`,\n );\n\n // Aggregate type manifests from discovered packages\n typeManifest = await aggregateTypeManifests(smrtPackages, projectRoot);\n\n // Save aggregated manifest for CLI discovery\n await saveAggregatedManifest(typeManifest, projectRoot);\n\n // Generate registration file for CLI class loading\n await generateRegistrationFile(typeManifest, projectRoot);\n\n // Generate types if requested\n if (generateTypes && !typesGenerated) {\n await generateProjectTypes(typeManifest, typesDir, projectRoot);\n typesGenerated = true;\n }\n } else {\n console.log('[smrt:consumer] No SMRT packages found');\n typeManifest = {\n version: '1.0.0',\n timestamp: MANIFEST_TIMESTAMP,\n objects: {},\n };\n }\n },\n\n resolveId(id, _importer) {\n // Resolve virtual modules to generated type declarations\n if (id in VIRTUAL_MODULES) {\n const typeFileName = getTypeFileName(id);\n const typePath = path.join(projectRoot, typesDir, typeFileName);\n\n // If types file exists, resolve to it\n if (fs.existsSync(typePath)) {\n return typePath;\n }\n\n // Otherwise use virtual module ID for runtime resolution\n return `\\0${VIRTUAL_MODULES[id as keyof typeof VIRTUAL_MODULES]}`;\n }\n return null;\n },\n\n async load(id) {\n // Handle virtual modules if types aren't available\n const cleanId = id.startsWith('\\0') ? id.slice(1) : id;\n\n if (!typeManifest) {\n typeManifest = {\n version: '1.0.0',\n timestamp: MANIFEST_TIMESTAMP,\n objects: {},\n };\n }\n\n switch (cleanId) {\n case 'smrt-consumer:routes':\n return generateFallbackRoutesModule();\n\n case 'smrt-consumer:client':\n return generateFallbackClientModule(typeManifest, { kebabRoutes });\n\n case 'smrt-consumer:mcp':\n return generateFallbackMcpModule();\n\n case 'smrt-consumer:types':\n return generateFallbackTypesModule(typeManifest);\n\n case 'smrt-consumer:manifest':\n return generateFallbackManifestModule(typeManifest);\n\n default:\n return null;\n }\n },\n };\n}\n\n/**\n * Discover SMRT packages from a consumer app's dependencies.\n *\n * Intentional split (#1579): this **consumer-plugin** path is async and\n * resolves SMRT packages from the downstream app's `package.json` dependency\n * names (`@have/`/`smrt` heuristic + `hasSmrtManifest` probe) inside the Vite\n * consumer plugin. It is deliberately separate from the build-time\n * `discoverSmrtPackages()` in `src/manifest/discover-smrt-packages.ts` — a\n * synchronous, lockfile-cached `node_modules` manifest scan used for manifest\n * generation. Different inputs, contexts, and lifecycles, not duplicated logic.\n */\nasync function discoverSmrtPackages(projectRoot: string): Promise<string[]> {\n const packages: string[] = [];\n const nodeModulesPath = path.join(projectRoot, 'node_modules');\n\n if (!fs.existsSync(nodeModulesPath)) {\n return packages;\n }\n\n try {\n // Check package.json for workspace dependencies\n const packageJsonPath = path.join(projectRoot, 'package.json');\n if (fs.existsSync(packageJsonPath)) {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const allDeps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n ...packageJson.peerDependencies,\n };\n\n // Look for packages that likely contain SMRT objects\n for (const [name, version] of Object.entries(allDeps)) {\n if (\n typeof version === 'string' &&\n (name.includes('smrt') ||\n name.includes('@have/') ||\n (await hasSmrtManifest(nodeModulesPath, name)))\n ) {\n packages.push(name);\n }\n }\n }\n } catch (error) {\n console.warn('[smrt:consumer] Error discovering packages:', error);\n }\n\n return packages;\n}\n\n/**\n * Check if a package has SMRT manifest\n */\nasync function hasSmrtManifest(\n nodeModulesPath: string,\n packageName: string,\n): Promise<boolean> {\n const packagePath = path.join(nodeModulesPath, packageName);\n const manifestPath = path.join(\n packagePath,\n 'dist',\n 'manifest',\n 'static-manifest.js',\n );\n return fs.existsSync(manifestPath);\n}\n\n/**\n * Aggregate type manifests from multiple packages\n */\nasync function aggregateTypeManifests(\n packages: string[],\n projectRoot: string,\n): Promise<ConsumerManifest> {\n const aggregatedManifest: ConsumerManifest = {\n version: '1.0.0',\n timestamp: MANIFEST_TIMESTAMP,\n objects: {},\n };\n\n for (const packageName of packages) {\n try {\n const packageDir = path.join(projectRoot, 'node_modules', packageName);\n\n // Load package.json for version and export information\n const packageJsonPath = path.join(packageDir, 'package.json');\n let packageJson: ConsumerPackageJson;\n try {\n const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf-8');\n packageJson = JSON.parse(packageJsonContent) as ConsumerPackageJson;\n } catch {\n console.warn(\n `[smrt:consumer] Could not read package.json for ${packageName}`,\n );\n continue;\n }\n\n // Try multiple manifest locations\n const manifestCandidates = [\n path.join(packageDir, 'dist', 'manifest', 'static-manifest.js'),\n path.join(packageDir, 'dist', 'manifest.json'),\n path.join(packageDir, 'manifest.json'),\n ];\n\n for (const manifestPath of manifestCandidates) {\n if (fs.existsSync(manifestPath)) {\n // Import or read the manifest\n let manifest: Partial<ConsumerManifest> | undefined;\n if (manifestPath.endsWith('.js')) {\n const manifestModule = await import(manifestPath);\n manifest = manifestModule.staticManifest || manifestModule.default;\n } else {\n const manifestContent = fs.readFileSync(manifestPath, 'utf-8');\n manifest = JSON.parse(manifestContent) as Partial<ConsumerManifest>;\n }\n\n if (manifest?.objects) {\n console.log(\n `[smrt:consumer] Loaded manifest from ${packageName} (${Object.keys(manifest.objects).length} objects)`,\n );\n\n // ENHANCED: Preserve package metadata for each object\n for (const [objectName, objectDef] of Object.entries(\n manifest.objects,\n )) {\n const def = objectDef;\n\n aggregatedManifest.objects[objectName] = {\n ...def,\n // Ensure package metadata is preserved/set\n packageName:\n def.packageName || manifest.packageName || packageName,\n packageVersion:\n def.packageVersion ||\n manifest.packageVersion ||\n packageJson.version,\n // Add fallback import paths if missing\n importPath: def.importPath || determineImportPath(packageJson),\n exportName: def.exportName || def.className || objectName,\n collectionExportName:\n def.collectionExportName ||\n `${def.className || objectName}Collection`,\n };\n }\n\n break; // Use first found manifest for this package\n }\n }\n }\n } catch (error) {\n console.warn(\n `[smrt:consumer] Error loading manifest from ${packageName}:`,\n error,\n );\n }\n }\n\n return aggregatedManifest;\n}\n\n/**\n * Determine import path from package.json\n */\nfunction determineImportPath(packageJson: ConsumerPackageJson): string {\n const packageName = packageJson.name;\n\n if (!packageName) {\n throw new Error('Package name not found in package.json');\n }\n\n // Strategy 1: Check for specific exports\n if (packageJson.exports) {\n // Check for objects export\n if (packageJson.exports['./objects']) {\n return `${packageName}/objects`;\n }\n\n // Check for main export\n const mainExport = packageJson.exports['.'];\n if (mainExport) {\n // Handle conditional exports\n if (typeof mainExport === 'object' && mainExport !== null) {\n const conditional = mainExport as Record<string, unknown>;\n if (conditional.import) {\n return packageName;\n }\n if (conditional.default) {\n return packageName;\n }\n }\n return packageName;\n }\n }\n\n // Strategy 2: Check main field\n if (packageJson.main) {\n return packageName;\n }\n\n // Strategy 3: Fallback to package name\n return packageName;\n}\n\n/**\n * Save aggregated manifest to .smrt/manifest.json for CLI discovery.\n *\n * Merge-preserving: `smrtPlugin()` writes the project's own scanned objects\n * to the same file (`writeLocalManifest`, issue #963), and both writes happen\n * in parallel `buildStart` hooks — so a plain overwrite here would clobber\n * the local objects whenever this plugin's write lands last (issue #1760\n * review). Local field metadata would then silently vanish from CLI schema\n * commands and from server runtimes that seed `.smrt/manifest.json`, dropping\n * domain columns on write. This function therefore only ADDS/refreshes the\n * external-package entries it owns and preserves everything else already in\n * the file (including the top-level `packageName` the local write sets).\n */\nasync function saveAggregatedManifest(\n manifest: ConsumerManifest,\n projectRoot: string,\n): Promise<void> {\n const smrtDir = path.join(projectRoot, '.smrt');\n const manifestPath = path.join(smrtDir, 'manifest.json');\n\n try {\n // Create .smrt directory if it doesn't exist\n if (!fs.existsSync(smrtDir)) {\n fs.mkdirSync(smrtDir, { recursive: true });\n }\n\n // Merge with whatever is on disk: existing entries (typically the local\n // project's objects written by smrtPlugin) are preserved; aggregated\n // external entries win for the qualified names this plugin owns.\n let merged: ConsumerManifest = manifest;\n if (fs.existsSync(manifestPath)) {\n try {\n const existing = JSON.parse(\n fs.readFileSync(manifestPath, 'utf-8'),\n ) as Partial<ConsumerManifest>;\n if (existing && typeof existing.objects === 'object') {\n merged = {\n ...existing,\n ...manifest,\n // The aggregated manifest carries no packageName; keep the local\n // project's (used as the manifest cache key at runtime).\n ...(existing.packageName\n ? { packageName: existing.packageName }\n : {}),\n objects: { ...existing.objects, ...manifest.objects },\n };\n }\n } catch {\n // Unreadable/corrupt existing file — fall back to a plain write.\n }\n }\n\n // Write manifest\n fs.writeFileSync(manifestPath, JSON.stringify(merged, null, 2), 'utf-8');\n\n console.log(\n `[smrt:consumer] Saved aggregated manifest to .smrt/manifest.json (${Object.keys(merged.objects).length} objects)`,\n );\n } catch (error) {\n console.warn('[smrt:consumer] Failed to save aggregated manifest:', error);\n }\n}\n\n/**\n * Generate registration file for CLI class loading\n *\n * Creates .smrt/register.js with static imports and registrations\n * for all external SMRT objects discovered during build.\n */\nasync function generateRegistrationFile(\n manifest: ConsumerManifest,\n projectRoot: string,\n): Promise<void> {\n const smrtDir = path.join(projectRoot, '.smrt');\n const registerPath = path.join(smrtDir, 'register.js');\n\n // Build import statements and registrations\n const imports: string[] = [];\n const registrations: string[] = [];\n let importedEntryCount = 0;\n let registeredObjectCount = 0;\n\n const manifestObjects = manifest.objects;\n const manifestObjectLookup = new Map<string, ConsumerObjectDefinition>();\n for (const [key, def] of Object.entries(manifestObjects)) {\n const candidate = def;\n const lookupKeys = [\n key,\n key.includes(':') ? key.split(':').pop() : undefined,\n candidate.qualifiedName,\n candidate.className,\n candidate.exportName,\n ];\n\n for (const lookupKey of lookupKeys) {\n if (lookupKey && !manifestObjectLookup.has(lookupKey)) {\n manifestObjectLookup.set(lookupKey, candidate);\n }\n }\n }\n\n const collectionClassMemo = new WeakMap<object, boolean>();\n\n const isCollectionClass = (\n def: ConsumerObjectDefinition | undefined,\n seen = new Set<string>(),\n ): boolean => {\n if (!def || typeof def !== 'object') {\n return false;\n }\n\n const cached = collectionClassMemo.get(def);\n if (cached !== undefined) {\n return cached;\n }\n\n if (\n def?.extends === 'SmrtCollection' ||\n def?.extendsTypeArg !== undefined\n ) {\n collectionClassMemo.set(def, true);\n return true;\n }\n\n const parentName = def?.extendsQualified || def?.extends;\n if (!parentName || seen.has(parentName)) {\n collectionClassMemo.set(def, false);\n return false;\n }\n seen.add(parentName);\n\n const parentDef = manifestObjectLookup.get(parentName);\n const isCollection = parentDef ? isCollectionClass(parentDef, seen) : false;\n collectionClassMemo.set(def, isCollection);\n\n return isCollection;\n };\n\n for (const [objectName, objectDef] of Object.entries(manifestObjects)) {\n const def = objectDef;\n\n // Skip local objects (they're imported from local entry point)\n if (!def.packageName || def.packageName === manifest.packageName) {\n continue;\n }\n\n const importPath = def.importPath || def.packageName;\n const exportName = def.exportName || def.className || objectName;\n const collectionExportName = def.collectionExportName;\n const hasCollection = def.hasCollection; // Check if collection class actually exists\n const tableName = def.collection || objectName.toLowerCase();\n\n // Generate import statement\n // Only import collection if it exists (hasCollection is truthy)\n if (hasCollection && collectionExportName) {\n imports.push(\n `import { ${exportName}, ${collectionExportName} } from '${importPath}';`,\n );\n } else {\n imports.push(`import { ${exportName} } from '${importPath}';`);\n }\n importedEntryCount++;\n\n if (isCollectionClass(def)) {\n continue;\n }\n\n // Generate registration calls\n // The import above already triggers the @smrt() decorator which registers the class\n // properly with its simple name and qualified name. We call register() again with\n // an empty config just to ensure the class is registered (in case it lacks a decorator).\n // Do NOT pass { name: qualifiedName } as that creates a separate registry entry.\n registrations.push(\n `ObjectRegistry.register(${exportName}, { name: ${JSON.stringify(exportName)}, packageName: ${JSON.stringify(def.packageName)} });`,\n );\n\n // Only register collection if it exists\n if (hasCollection && collectionExportName) {\n registrations.push(\n `ObjectRegistry.registerCollection('${tableName}', ${collectionExportName});`,\n );\n }\n\n registeredObjectCount++;\n }\n\n // Skip generation if no external entries\n if (importedEntryCount === 0) {\n console.log('[smrt:consumer] No external entries - skipping register.js');\n return;\n }\n\n const registeredObjectLabel =\n registeredObjectCount === 1 ? 'object' : 'objects';\n\n // Generate file content\n const content = `/**\n * Auto-generated by @happyvertical/smrt-core/consumer-plugin\n * DO NOT EDIT - This file is regenerated on every build\n *\n * Registers SMRT objects from external packages for CLI discovery.\n * Generated at: ${new Date().toISOString()}\n */\n\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n${imports.join('\\n')}\n\n// Register all objects (executed during module evaluation)\n${registrations.join('\\n')}\n\nexport function registerAll() {\n // Objects are already registered during module evaluation\n console.log('[smrt:register] Registered ${registeredObjectCount} external ${registeredObjectLabel}');\n}\n`;\n\n // Create .smrt directory if needed\n if (!fs.existsSync(smrtDir)) {\n fs.mkdirSync(smrtDir, { recursive: true });\n }\n\n // Write registration file\n fs.writeFileSync(registerPath, content, 'utf-8');\n\n console.log(\n `[smrt:consumer] Generated .smrt/register.js with ${importedEntryCount} external entries (${registeredObjectCount} registered ${registeredObjectLabel})`,\n );\n}\n\n/**\n * Generate project-specific types\n */\nasync function generateProjectTypes(\n typeManifest: ConsumerManifest,\n typesDir: string,\n projectRoot: string,\n): Promise<void> {\n if (!typeManifest || Object.keys(typeManifest.objects).length === 0) {\n console.log(\n '[smrt:consumer] No SMRT objects found, skipping type generation',\n );\n return;\n }\n\n await generateDeclarations({\n // The aggregated manifest is a runtime SMRT manifest assembled from external\n // package manifests; it is intentionally typed loosely at the JSON boundary,\n // so narrow it to the declaration generator's strict manifest shape here.\n manifest: typeManifest as unknown as SmartObjectManifest,\n outDir: typesDir,\n projectRoot,\n includeVirtualModules: true,\n includeObjectTypes: true,\n });\n\n console.log(\n `[smrt:consumer] Generated types for ${Object.keys(typeManifest.objects).length} objects`,\n );\n}\n\n/**\n * Get type file name for virtual module\n */\nfunction getTypeFileName(virtualModule: string): string {\n const moduleMap: Record<string, string> = {\n '@smrt/routes': 'smrt-routes.d.ts',\n '@smrt/client': 'smrt-client.d.ts',\n '@smrt/mcp': 'smrt-mcp.d.ts',\n '@smrt/types': 'smrt-types.d.ts',\n '@smrt/manifest': 'smrt-manifest.d.ts',\n };\n return moduleMap[virtualModule] || 'smrt-unknown.d.ts';\n}\n\n/**\n * Fallback modules for when types aren't available\n */\nfunction generateFallbackRoutesModule(): string {\n return `\n// Fallback routes module\nexport function setupRoutes(app) {\n console.warn('[smrt:consumer] No routes available - SMRT packages may not be properly configured');\n}\nexport default setupRoutes;\n`;\n}\n\nfunction generateFallbackClientModule(\n manifest: ConsumerManifest,\n options: { kebabRoutes?: boolean } = {},\n): string {\n const objects = Object.entries(manifest?.objects || {});\n if (objects.length === 0) {\n return `\n// Fallback client module\nexport function createClient(basePath = '/api/v1') {\n console.warn('[smrt:consumer] No API client available - SMRT packages may not be properly configured');\n return {};\n}\nexport default createClient;\n`;\n }\n\n return generateClientModule(manifest as unknown as SmartObjectManifest, {\n kebabRoutes: options.kebabRoutes,\n });\n}\n\nfunction generateFallbackMcpModule(): string {\n return `\n// Fallback MCP module\nexport const tools = [];\nexport function createMCPServer() {\n console.warn('[smrt:consumer] No MCP tools available - SMRT packages may not be properly configured');\n return { name: 'smrt-consumer', version: '1.0.0', tools: [] };\n}\nexport default createMCPServer;\n`;\n}\n\nfunction generateFallbackTypesModule(manifest: ConsumerManifest): string {\n const objects = Object.entries(manifest?.objects || {});\n if (objects.length === 0) {\n return `// No types available`;\n }\n\n // Generate basic interfaces\n const interfaces = objects.map(([_name, obj]) => {\n return `export interface ${obj.className}Data {\n id?: string;\n created_at?: string;\n updated_at?: string;\n [key: string]: any;\n}`;\n });\n\n return interfaces.join('\\n\\n');\n}\n\nfunction generateFallbackManifestModule(manifest: ConsumerManifest): string {\n return `\n// Auto-generated manifest from SMRT consumer\nexport const manifest = ${JSON.stringify(manifest, null, 2)};\nexport default manifest;\n`;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/manifest/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/manifest/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAwB/D;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IAErC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAG/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC;CACrC;AAuCD;;;;;GAKG;AACH,qBAAa,eAAe;IAC1B;;OAEG;IACG,QAAQ,CACZ,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC;IAkC/B,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,iBAAiB;IAmBzB;;OAEG;IACH,OAAO,CAAC,aAAa;IAUrB;;OAEG;YACW,gBAAgB;IAoD9B;;;;;OAKG;YACW,oBAAoB;IAyElC;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAiCtB;;OAEG;YACW,WAAW;IAyCzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuCxB;;OAEG;YACW,yBAAyB;IA6EvC;;OAEG;YACW,uBAAuB;IAwCrC;;OAEG;IACH,OAAO,CAAC,eAAe;IAavB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAuB5B"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "../scanner/types.js";
|
|
1
2
|
import { ManifestGenerator } from "../scanner/manifest-generator.js";
|
|
2
3
|
import { ManifestManager } from "./manager.js";
|
|
3
4
|
import { importWorkspaceModule } from "../utils/import-workspace-module.js";
|
|
@@ -319,7 +320,7 @@ export default ${exportName};
|
|
|
319
320
|
createEmptyManifest(options) {
|
|
320
321
|
const manifest = {
|
|
321
322
|
version: "1.0.0",
|
|
322
|
-
timestamp:
|
|
323
|
+
timestamp: 0,
|
|
323
324
|
objects: {},
|
|
324
325
|
moduleType: options.moduleType || "smrt"
|
|
325
326
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.js","names":[],"sources":["../../src/manifest/generator.ts"],"sourcesContent":["/**\n * Manifest generation orchestrator\n * Consolidates manifest generation logic for both build and test manifests\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, isAbsolute, relative, resolve } from 'node:path';\nimport { createLogger } from '@happyvertical/logger';\nimport fg from 'fast-glob';\nimport { ManifestGenerator } from '../scanner/manifest-generator.js';\nimport type { SmartObjectManifest } from '../scanner/types.js';\nimport { importWorkspaceModule } from '../utils/import-workspace-module.js';\nimport type { ScannerModule } from '../utils/scanner-module.js';\nimport {\n discoverSmrtPackages,\n resolveManifestPath,\n} from './discover-smrt-packages.js';\nimport { ManifestManager } from './manager.js';\n\n// Build-time manifest-generation diagnostics route through the shared logger\n// (S14 / dim-9, #1579) so consumers can control verbosity instead of receiving\n// unconditional stdout writes.\nconst logger = createLogger({ level: 'info' });\n\nasync function importScanner() {\n return importWorkspaceModule<ScannerModule>({\n packageName: '@happyvertical/smrt-scanner',\n distEntry: 'packages/scanner/dist/index.js',\n sourceEntry: 'packages/scanner/src/index.ts',\n purpose: 'manifest generation',\n });\n}\n\n/**\n * Options for ManifestBuilder.generate()\n *\n * Controls file discovery, scanner configuration, output generation, and metadata injection\n */\nexport interface ManifestBuilderOptions {\n // File Discovery\n include?: string[];\n exclude?: string[];\n followImports?: boolean;\n\n // Scanner Configuration\n baseClasses?: string[];\n loadViteConfig?: boolean;\n discoverExternalPackages?: boolean;\n includeExternalBaseClasses?: boolean;\n includePrivateMethods?: boolean;\n includeStaticMethods?: boolean;\n\n // Output Configuration\n outputDir?: string;\n outputName?: string;\n generateTypeStub?: boolean;\n stubName?: string;\n\n // Metadata\n injectPackageInfo?: boolean;\n moduleType?: string;\n\n // Tree Shaking (External Object Filtering)\n /**\n * @deprecated Tree shaking is no longer needed. The AST scanner no longer includes external objects in the manifest by default.\n */\n treeShake?: boolean;\n\n /**\n * @deprecated Whitelists are no longer needed. The AST scanner no longer includes external objects in the manifest by default.\n */\n externalObjectsWhitelist?: string[];\n}\n\ninterface ScannerConfig {\n baseClasses: string[];\n includePrivateMethods: boolean;\n includeStaticMethods: boolean;\n followImports: boolean;\n smrtDependencies?: string[];\n}\n\ninterface PackageInfo {\n name?: string;\n version?: string;\n}\n\n/**\n * Subset of the smrt-auto-service Vite plugin options we probe when reading\n * baseClasses out of a project's vite.config.ts.\n */\ninterface VitePluginOptions {\n baseClasses?: string[];\n followImports?: boolean;\n}\n\n/**\n * Structural shape of a loaded Vite plugin entry as probed by\n * loadViteConfigBaseClasses(). The plugin may expose its options directly, on\n * `_options`, or via an `api` object/function — all optional and discovered at\n * runtime, so each is modeled as optional here.\n */\ninterface VitePluginProbe {\n name?: string;\n options?: VitePluginOptions;\n _options?: VitePluginOptions;\n api?:\n | { options?: VitePluginOptions }\n | (() => { options?: VitePluginOptions });\n}\n\n/**\n * Orchestrates manifest generation with configurable options\n *\n * Consolidates logic from generate-manifest.js and generate-test-manifest.js\n * into a single, testable, and maintainable service.\n */\nexport class ManifestBuilder {\n /**\n * Generate manifest with specified options\n */\n async generate(\n options: ManifestBuilderOptions = {},\n ): Promise<SmartObjectManifest> {\n // 1. Discover files to scan\n const files = this.discoverFiles(options);\n\n if (files.length === 0) {\n logger.info('[smrt] No source files found');\n return this.createEmptyManifest(options);\n }\n\n logger.info(`[smrt] Scanning ${files.length} source file(s)...`);\n\n // 2. Configure scanner (baseClasses, external packages, vite config)\n const scannerConfig = await this.configureScanner(options);\n\n // 3. Scan files with OXC scanner\n const scannedManifest = await this.scanAndBuildManifest(\n scannerConfig,\n options,\n );\n\n // 4. Enrich manifest with metadata (smrtDependencies, packageInfo)\n const manifest = this.enrichManifest(\n scannedManifest,\n options,\n scannerConfig,\n );\n\n // 5. Write output files\n this.normalizeFilePaths(manifest);\n await this.writeOutput(manifest, options);\n\n return manifest;\n }\n\n private normalizeFilePaths(manifest: SmartObjectManifest): void {\n const workspaceRoot = this.findWorkspaceRoot(process.cwd());\n\n for (const obj of Object.values(manifest.objects || {})) {\n if (obj.filePath && isAbsolute(obj.filePath)) {\n obj.filePath = relative(workspaceRoot, obj.filePath).replace(\n /\\\\/g,\n '/',\n );\n }\n }\n }\n\n private findWorkspaceRoot(startDir: string): string {\n let current = resolve(startDir);\n\n while (true) {\n if (\n existsSync(resolve(current, 'pnpm-workspace.yaml')) ||\n existsSync(resolve(current, '.git'))\n ) {\n return current;\n }\n\n const parent = dirname(current);\n if (parent === current) {\n return resolve(startDir);\n }\n current = parent;\n }\n }\n\n /**\n * Discover source files based on include/exclude patterns\n */\n private discoverFiles(options: ManifestBuilderOptions): string[] {\n const include = options.include || ['src/**/*.ts'];\n const exclude = options.exclude || ['src/**/*.d.ts', 'node_modules/**'];\n\n return fg.sync(include, {\n absolute: true,\n ignore: exclude,\n });\n }\n\n /**\n * Configure AST scanner with baseClasses, external packages, and vite config\n */\n private async configureScanner(\n options: ManifestBuilderOptions,\n ): Promise<ScannerConfig> {\n let baseClasses = options.baseClasses || [\n 'SmrtObject',\n 'SmrtClass',\n 'SmrtCollection',\n ];\n\n // Load from vite.config.ts if requested\n if (options.loadViteConfig) {\n const viteBaseClasses = await this.loadViteConfigBaseClasses();\n if (viteBaseClasses && viteBaseClasses.length > 0) {\n baseClasses = viteBaseClasses;\n logger.info(\n `[smrt] Using baseClasses from vite.config.ts: ${baseClasses.join(', ')}`,\n );\n }\n }\n\n // Discover external SMRT packages\n let smrtDependencies: string[] = [];\n if (options.discoverExternalPackages) {\n logger.info('[smrt] Discovering external SMRT packages...');\n smrtDependencies = discoverSmrtPackages();\n logger.info(\n `[smrt] Found ${smrtDependencies.length} SMRT package(s): ${smrtDependencies.join(', ')}`,\n );\n\n // Optionally add external base classes\n if (options.includeExternalBaseClasses) {\n const externalClasses =\n await this.loadExternalBaseClasses(smrtDependencies);\n if (externalClasses.length > 0) {\n baseClasses = [...baseClasses, ...externalClasses];\n logger.info(\n `[smrt] Added ${externalClasses.length} external base class(es) to scanner`,\n );\n logger.info(`[smrt] Total baseClasses: ${baseClasses.length}`);\n }\n }\n }\n\n return {\n baseClasses,\n includePrivateMethods: options.includePrivateMethods ?? false,\n includeStaticMethods: options.includeStaticMethods ?? true,\n followImports: options.followImports ?? false,\n smrtDependencies,\n };\n }\n\n /**\n * Scan files using OxcScanner and build manifest via ManifestAdapter.\n *\n * This replaces the old ASTScanner-based scanFiles() method.\n * Uses the same OXC pipeline as the Vite plugin's scanWithOxc().\n */\n private async scanAndBuildManifest(\n config: ScannerConfig,\n options: ManifestBuilderOptions,\n ): Promise<SmartObjectManifest> {\n const { OxcScanner, ManifestAdapter } = await importScanner();\n\n const scanner = new OxcScanner({\n cwd: process.cwd(),\n include: options.include || ['src/**/*.ts'],\n exclude: options.exclude || ['src/**/*.d.ts', 'node_modules/**'],\n baseClasses: config.baseClasses,\n includePrivateMethods: config.includePrivateMethods,\n includeStaticMethods: config.includeStaticMethods,\n followImports: config.followImports,\n });\n\n const { results, resolved } = await scanner.scanAndResolve();\n const scanErrors = results.errors.filter(\n (diagnostic) => diagnostic.severity === 'error',\n );\n if (scanErrors.length > 0) {\n const detail = scanErrors\n .map((diagnostic) => {\n const where = diagnostic.line\n ? `${diagnostic.filePath}:${diagnostic.line}`\n : diagnostic.filePath;\n return `${where} — ${diagnostic.message}`;\n })\n .join('; ');\n throw new Error(\n `[smrt] Build aborted due to ${scanErrors.length} scan error(s): ${detail}`,\n );\n }\n\n // Read package.json for metadata\n let packageName: string | undefined;\n let packageVersion: string | undefined;\n let packageJson: { name?: string; version?: string } | undefined;\n try {\n const pkgPath = resolve(process.cwd(), 'package.json');\n const pkgContent = readFileSync(pkgPath, 'utf-8');\n packageJson = JSON.parse(pkgContent);\n packageName = packageJson?.name || undefined;\n packageVersion = packageJson?.version || undefined;\n } catch {\n // package.json not found - continue without packageName\n }\n\n // Convert to manifest format\n const adapter = new ManifestAdapter();\n const manifest = adapter.toManifest(resolved, {\n packageName,\n packageVersion,\n typeAliases: results.typeAliases,\n });\n\n // Set smrtDependencies BEFORE mergeInheritedFields so external packages can be loaded\n if (config.smrtDependencies && config.smrtDependencies.length > 0) {\n manifest.smrtDependencies = config.smrtDependencies;\n }\n\n // Run manifest generation passes (same as Vite plugin path)\n const manifestGen = new ManifestGenerator();\n manifestGen.injectTenantScopedFields(manifest);\n manifestGen.mergeInheritedFields(manifest);\n manifestGen.generateValidationRules(manifest);\n manifestGen.generateSchemas(manifest);\n manifestGen.assertTenantScopedSchemaContract(manifest);\n manifestGen.generateAgentManifests(manifest, packageName, packageJson);\n\n return manifest;\n }\n\n /**\n * Enrich manifest with metadata (moduleType, smrtDependencies, packageInfo).\n *\n * Note: As of Issue #1013, this method no longer merges external package\n * objects into the manifest. Dependencies are referenced via\n * `smrtDependencies` and resolved at runtime by manifest-loader.ts.\n */\n private enrichManifest(\n manifest: SmartObjectManifest,\n options: ManifestBuilderOptions,\n scannerConfig: ScannerConfig,\n ): SmartObjectManifest {\n // Add module type\n manifest.moduleType = options.moduleType || 'smrt';\n\n // Record dependency references (not their objects) so runtime\n // manifest-loader.ts can discover and load them on demand.\n if (\n scannerConfig.smrtDependencies &&\n scannerConfig.smrtDependencies.length > 0\n ) {\n manifest.smrtDependencies = scannerConfig.smrtDependencies;\n }\n\n // Inject package info\n if (options.injectPackageInfo) {\n const packageInfo = this.readPackageJson();\n if (packageInfo.name) {\n manifest.packageName = packageInfo.name;\n logger.info(`[smrt] Injected package name: ${packageInfo.name}`);\n } else {\n logger.warn(\n '[smrt] Warning: Could not read package.json, packageName will be undefined',\n );\n }\n }\n\n return manifest;\n }\n\n /**\n * Write manifest JSON and optional TypeScript stub\n */\n private async writeOutput(\n manifest: SmartObjectManifest,\n options: ManifestBuilderOptions,\n ): Promise<void> {\n const manager = new ManifestManager(process.cwd());\n const isTest =\n options.outputName?.includes('test') ||\n options.stubName?.includes('test');\n const mode = isTest ? 'dev' : 'build';\n\n // 1. Always write to the unified location via ManifestManager\n manager.write(manifest, mode);\n\n // 2. Legacy/Explicit Output (if requested or for stubs)\n const outputDir = options.outputDir || 'src/manifest';\n const outputName = options.outputName || 'manifest.json';\n\n // Ensure output directory exists for legacy/stubs\n mkdirSync(outputDir, { recursive: true });\n\n // Write JSON manifest to legacy location if different from unified path\n const manifestPath = resolve(outputDir, outputName);\n const unifiedPath = manager.getOutputPath(mode);\n\n if (resolve(manifestPath) !== resolve(unifiedPath)) {\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));\n }\n\n // Write TypeScript stub if requested\n if (options.generateTypeStub) {\n const stubName = options.stubName || 'manifest.ts';\n const tsContent = this.generateTypeStub(manifest, stubName);\n const stubPath = resolve(outputDir, stubName);\n writeFileSync(stubPath, tsContent);\n }\n\n const objectCount = Object.keys(manifest.objects).length;\n logger.info(`[smrt] ✅ Generated manifest with ${objectCount} object(s)`);\n logger.info(`[smrt] Unified: ${unifiedPath}`);\n }\n\n /**\n * Generate TypeScript stub file with manifest constant\n */\n private generateTypeStub(\n manifest: SmartObjectManifest,\n filename: string,\n ): string {\n const isTestManifest = filename.includes('test');\n\n const comment = isTestManifest\n ? `/**\n * Test manifest stub\n * This file is replaced by generate-test-manifest.js during pretest\n * If tests run without pretest, this empty manifest is used\n *\n * DO NOT EDIT MANUALLY - This file is automatically generated\n */`\n : `/**\n * Auto-generated static manifest\n * Generated at build time from SMRT object scanning\n * DO NOT EDIT - This file is automatically generated\n */`;\n\n const exportName = isTestManifest ? 'testManifest' : 'staticManifest';\n\n // Use relative import for core package (to avoid self-reference during build),\n // package import for all other packages\n const isCorePackage = manifest.packageName === '@happyvertical/smrt-core';\n const importPath = isCorePackage\n ? '../scanner/types.js'\n : '@happyvertical/smrt-core/scanner/types';\n\n return `${comment}\n\nimport type { SmartObjectManifest } from '${importPath}';\n\nexport const ${exportName}: SmartObjectManifest = ${JSON.stringify(manifest, null, 2)} as const;\n\nexport default ${exportName};\n`;\n }\n\n /**\n * Load baseClasses from vite.config.ts\n */\n private async loadViteConfigBaseClasses(): Promise<string[] | null> {\n try {\n const viteConfigPath = resolve(process.cwd(), 'vite.config.ts');\n if (!existsSync(viteConfigPath)) {\n logger.info('[smrt] vite.config.ts not found');\n return null;\n }\n\n logger.info('[smrt] Found vite.config.ts, attempting to load...');\n\n // Use vite to load config which handles TypeScript\n const { loadConfigFromFile } = await import('vite');\n const loaded = await loadConfigFromFile(\n { command: 'build', mode: 'test' },\n viteConfigPath,\n );\n\n if (!loaded?.config?.plugins) {\n logger.info('[smrt] No plugins found in vite config');\n return null;\n }\n\n // Vite's loaded plugins are a recursive PluginOption[] (plugins, arrays,\n // falsy values, promises). We only probe a few optional fields, so model\n // them structurally and narrow defensively instead of using `any`.\n const plugins = loaded.config.plugins as readonly VitePluginProbe[];\n\n logger.info('[smrt] Vite config loaded', {\n plugins: plugins.map((p) => p?.name),\n });\n\n // Find smrtPlugin in plugins array\n const smrtPlugin = plugins.find((p) => p?.name === 'smrt-auto-service');\n\n if (!smrtPlugin) {\n logger.info(\n '[smrt] smrt-auto-service plugin not found in plugins array',\n );\n return null;\n }\n\n logger.info('[smrt] Found smrt-auto-service plugin');\n\n // Try different ways to access options\n const api = smrtPlugin.api;\n let opts: VitePluginOptions | undefined =\n (typeof api === 'object' && api !== null ? api.options : undefined) ||\n smrtPlugin.options ||\n smrtPlugin._options;\n\n if (!opts && typeof api === 'function') {\n try {\n opts = api().options;\n } catch (e) {\n logger.info('[smrt] Could not call plugin.api()');\n }\n }\n\n if (opts?.baseClasses) {\n logger.info('[smrt] Plugin options', {\n baseClasses: opts.baseClasses,\n followImports: opts.followImports,\n });\n return opts.baseClasses;\n }\n\n logger.info('[smrt] Could not access plugin options');\n return null;\n } catch (error) {\n logger.warn('[smrt] Error loading vite.config.ts', {\n error: error instanceof Error ? error.message : String(error),\n });\n logger.info('[smrt] Using default baseClasses');\n return null;\n }\n }\n\n /**\n * Load base classes from external SMRT package manifests\n */\n private async loadExternalBaseClasses(packages: string[]): Promise<string[]> {\n const externalBaseClasses: string[] = [];\n\n for (const pkgName of packages) {\n // Resolve the manifest the same way discovery does (honors `.smrt/` and\n // `src/manifest/`, not just `dist/`) so source-only workspace packages\n // still contribute base classes (#1378).\n const manifestPath = resolveManifestPath(pkgName, process.cwd());\n if (!manifestPath) {\n logger.info(`[smrt] ${pkgName}: no SMRT manifest resolved`);\n continue;\n }\n\n try {\n const manifestContent = readFileSync(manifestPath, 'utf-8');\n const manifest: SmartObjectManifest = JSON.parse(manifestContent);\n\n // Extract all class names from this package\n const foundClassNames: string[] = [];\n for (const objDef of Object.values(manifest.objects)) {\n if (objDef.className) {\n const className = objDef.className;\n foundClassNames.push(className);\n externalBaseClasses.push(className);\n }\n }\n\n logger.info(\n `[smrt] ${pkgName}: found ${foundClassNames.length} class(es) - ${foundClassNames.join(', ')}`,\n );\n } catch (error) {\n logger.info(\n `[smrt] ${pkgName}: manifest not found or invalid - ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n return externalBaseClasses;\n }\n\n /**\n * Read package.json from current working directory\n */\n private readPackageJson(): PackageInfo {\n try {\n const packageJsonPath = resolve(process.cwd(), 'package.json');\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n return {\n name: packageJson.name,\n version: packageJson.version,\n };\n } catch (error) {\n return {};\n }\n }\n\n /**\n * Create empty manifest when no files found\n */\n private createEmptyManifest(\n options: ManifestBuilderOptions,\n ): SmartObjectManifest {\n const manifest: SmartObjectManifest = {\n version: '1.0.0',\n timestamp: Date.now(),\n objects: {},\n moduleType: options.moduleType || 'smrt',\n };\n\n if (options.discoverExternalPackages) {\n manifest.smrtDependencies = discoverSmrtPackages();\n }\n\n if (options.injectPackageInfo) {\n const packageInfo = this.readPackageJson();\n if (packageInfo.name) {\n manifest.packageName = packageInfo.name;\n }\n }\n\n return manifest;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generator.js","names":[],"sources":["../../src/manifest/generator.ts"],"sourcesContent":["/**\n * Manifest generation orchestrator\n * Consolidates manifest generation logic for both build and test manifests\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, isAbsolute, relative, resolve } from 'node:path';\nimport { createLogger } from '@happyvertical/logger';\nimport fg from 'fast-glob';\nimport { ManifestGenerator } from '../scanner/manifest-generator.js';\nimport type { SmartObjectManifest } from '../scanner/types.js';\nimport { MANIFEST_TIMESTAMP } from '../scanner/types.js';\nimport { importWorkspaceModule } from '../utils/import-workspace-module.js';\nimport type { ScannerModule } from '../utils/scanner-module.js';\nimport {\n discoverSmrtPackages,\n resolveManifestPath,\n} from './discover-smrt-packages.js';\nimport { ManifestManager } from './manager.js';\n\n// Build-time manifest-generation diagnostics route through the shared logger\n// (S14 / dim-9, #1579) so consumers can control verbosity instead of receiving\n// unconditional stdout writes.\nconst logger = createLogger({ level: 'info' });\n\nasync function importScanner() {\n return importWorkspaceModule<ScannerModule>({\n packageName: '@happyvertical/smrt-scanner',\n distEntry: 'packages/scanner/dist/index.js',\n sourceEntry: 'packages/scanner/src/index.ts',\n purpose: 'manifest generation',\n });\n}\n\n/**\n * Options for ManifestBuilder.generate()\n *\n * Controls file discovery, scanner configuration, output generation, and metadata injection\n */\nexport interface ManifestBuilderOptions {\n // File Discovery\n include?: string[];\n exclude?: string[];\n followImports?: boolean;\n\n // Scanner Configuration\n baseClasses?: string[];\n loadViteConfig?: boolean;\n discoverExternalPackages?: boolean;\n includeExternalBaseClasses?: boolean;\n includePrivateMethods?: boolean;\n includeStaticMethods?: boolean;\n\n // Output Configuration\n outputDir?: string;\n outputName?: string;\n generateTypeStub?: boolean;\n stubName?: string;\n\n // Metadata\n injectPackageInfo?: boolean;\n moduleType?: string;\n\n // Tree Shaking (External Object Filtering)\n /**\n * @deprecated Tree shaking is no longer needed. The AST scanner no longer includes external objects in the manifest by default.\n */\n treeShake?: boolean;\n\n /**\n * @deprecated Whitelists are no longer needed. The AST scanner no longer includes external objects in the manifest by default.\n */\n externalObjectsWhitelist?: string[];\n}\n\ninterface ScannerConfig {\n baseClasses: string[];\n includePrivateMethods: boolean;\n includeStaticMethods: boolean;\n followImports: boolean;\n smrtDependencies?: string[];\n}\n\ninterface PackageInfo {\n name?: string;\n version?: string;\n}\n\n/**\n * Subset of the smrt-auto-service Vite plugin options we probe when reading\n * baseClasses out of a project's vite.config.ts.\n */\ninterface VitePluginOptions {\n baseClasses?: string[];\n followImports?: boolean;\n}\n\n/**\n * Structural shape of a loaded Vite plugin entry as probed by\n * loadViteConfigBaseClasses(). The plugin may expose its options directly, on\n * `_options`, or via an `api` object/function — all optional and discovered at\n * runtime, so each is modeled as optional here.\n */\ninterface VitePluginProbe {\n name?: string;\n options?: VitePluginOptions;\n _options?: VitePluginOptions;\n api?:\n | { options?: VitePluginOptions }\n | (() => { options?: VitePluginOptions });\n}\n\n/**\n * Orchestrates manifest generation with configurable options\n *\n * Consolidates logic from generate-manifest.js and generate-test-manifest.js\n * into a single, testable, and maintainable service.\n */\nexport class ManifestBuilder {\n /**\n * Generate manifest with specified options\n */\n async generate(\n options: ManifestBuilderOptions = {},\n ): Promise<SmartObjectManifest> {\n // 1. Discover files to scan\n const files = this.discoverFiles(options);\n\n if (files.length === 0) {\n logger.info('[smrt] No source files found');\n return this.createEmptyManifest(options);\n }\n\n logger.info(`[smrt] Scanning ${files.length} source file(s)...`);\n\n // 2. Configure scanner (baseClasses, external packages, vite config)\n const scannerConfig = await this.configureScanner(options);\n\n // 3. Scan files with OXC scanner\n const scannedManifest = await this.scanAndBuildManifest(\n scannerConfig,\n options,\n );\n\n // 4. Enrich manifest with metadata (smrtDependencies, packageInfo)\n const manifest = this.enrichManifest(\n scannedManifest,\n options,\n scannerConfig,\n );\n\n // 5. Write output files\n this.normalizeFilePaths(manifest);\n await this.writeOutput(manifest, options);\n\n return manifest;\n }\n\n private normalizeFilePaths(manifest: SmartObjectManifest): void {\n const workspaceRoot = this.findWorkspaceRoot(process.cwd());\n\n for (const obj of Object.values(manifest.objects || {})) {\n if (obj.filePath && isAbsolute(obj.filePath)) {\n obj.filePath = relative(workspaceRoot, obj.filePath).replace(\n /\\\\/g,\n '/',\n );\n }\n }\n }\n\n private findWorkspaceRoot(startDir: string): string {\n let current = resolve(startDir);\n\n while (true) {\n if (\n existsSync(resolve(current, 'pnpm-workspace.yaml')) ||\n existsSync(resolve(current, '.git'))\n ) {\n return current;\n }\n\n const parent = dirname(current);\n if (parent === current) {\n return resolve(startDir);\n }\n current = parent;\n }\n }\n\n /**\n * Discover source files based on include/exclude patterns\n */\n private discoverFiles(options: ManifestBuilderOptions): string[] {\n const include = options.include || ['src/**/*.ts'];\n const exclude = options.exclude || ['src/**/*.d.ts', 'node_modules/**'];\n\n return fg.sync(include, {\n absolute: true,\n ignore: exclude,\n });\n }\n\n /**\n * Configure AST scanner with baseClasses, external packages, and vite config\n */\n private async configureScanner(\n options: ManifestBuilderOptions,\n ): Promise<ScannerConfig> {\n let baseClasses = options.baseClasses || [\n 'SmrtObject',\n 'SmrtClass',\n 'SmrtCollection',\n ];\n\n // Load from vite.config.ts if requested\n if (options.loadViteConfig) {\n const viteBaseClasses = await this.loadViteConfigBaseClasses();\n if (viteBaseClasses && viteBaseClasses.length > 0) {\n baseClasses = viteBaseClasses;\n logger.info(\n `[smrt] Using baseClasses from vite.config.ts: ${baseClasses.join(', ')}`,\n );\n }\n }\n\n // Discover external SMRT packages\n let smrtDependencies: string[] = [];\n if (options.discoverExternalPackages) {\n logger.info('[smrt] Discovering external SMRT packages...');\n smrtDependencies = discoverSmrtPackages();\n logger.info(\n `[smrt] Found ${smrtDependencies.length} SMRT package(s): ${smrtDependencies.join(', ')}`,\n );\n\n // Optionally add external base classes\n if (options.includeExternalBaseClasses) {\n const externalClasses =\n await this.loadExternalBaseClasses(smrtDependencies);\n if (externalClasses.length > 0) {\n baseClasses = [...baseClasses, ...externalClasses];\n logger.info(\n `[smrt] Added ${externalClasses.length} external base class(es) to scanner`,\n );\n logger.info(`[smrt] Total baseClasses: ${baseClasses.length}`);\n }\n }\n }\n\n return {\n baseClasses,\n includePrivateMethods: options.includePrivateMethods ?? false,\n includeStaticMethods: options.includeStaticMethods ?? true,\n followImports: options.followImports ?? false,\n smrtDependencies,\n };\n }\n\n /**\n * Scan files using OxcScanner and build manifest via ManifestAdapter.\n *\n * This replaces the old ASTScanner-based scanFiles() method.\n * Uses the same OXC pipeline as the Vite plugin's scanWithOxc().\n */\n private async scanAndBuildManifest(\n config: ScannerConfig,\n options: ManifestBuilderOptions,\n ): Promise<SmartObjectManifest> {\n const { OxcScanner, ManifestAdapter } = await importScanner();\n\n const scanner = new OxcScanner({\n cwd: process.cwd(),\n include: options.include || ['src/**/*.ts'],\n exclude: options.exclude || ['src/**/*.d.ts', 'node_modules/**'],\n baseClasses: config.baseClasses,\n includePrivateMethods: config.includePrivateMethods,\n includeStaticMethods: config.includeStaticMethods,\n followImports: config.followImports,\n });\n\n const { results, resolved } = await scanner.scanAndResolve();\n const scanErrors = results.errors.filter(\n (diagnostic) => diagnostic.severity === 'error',\n );\n if (scanErrors.length > 0) {\n const detail = scanErrors\n .map((diagnostic) => {\n const where = diagnostic.line\n ? `${diagnostic.filePath}:${diagnostic.line}`\n : diagnostic.filePath;\n return `${where} — ${diagnostic.message}`;\n })\n .join('; ');\n throw new Error(\n `[smrt] Build aborted due to ${scanErrors.length} scan error(s): ${detail}`,\n );\n }\n\n // Read package.json for metadata\n let packageName: string | undefined;\n let packageVersion: string | undefined;\n let packageJson: { name?: string; version?: string } | undefined;\n try {\n const pkgPath = resolve(process.cwd(), 'package.json');\n const pkgContent = readFileSync(pkgPath, 'utf-8');\n packageJson = JSON.parse(pkgContent);\n packageName = packageJson?.name || undefined;\n packageVersion = packageJson?.version || undefined;\n } catch {\n // package.json not found - continue without packageName\n }\n\n // Convert to manifest format\n const adapter = new ManifestAdapter();\n const manifest = adapter.toManifest(resolved, {\n packageName,\n packageVersion,\n typeAliases: results.typeAliases,\n });\n\n // Set smrtDependencies BEFORE mergeInheritedFields so external packages can be loaded\n if (config.smrtDependencies && config.smrtDependencies.length > 0) {\n manifest.smrtDependencies = config.smrtDependencies;\n }\n\n // Run manifest generation passes (same as Vite plugin path)\n const manifestGen = new ManifestGenerator();\n manifestGen.injectTenantScopedFields(manifest);\n manifestGen.mergeInheritedFields(manifest);\n manifestGen.generateValidationRules(manifest);\n manifestGen.generateSchemas(manifest);\n manifestGen.assertTenantScopedSchemaContract(manifest);\n manifestGen.generateAgentManifests(manifest, packageName, packageJson);\n\n return manifest;\n }\n\n /**\n * Enrich manifest with metadata (moduleType, smrtDependencies, packageInfo).\n *\n * Note: As of Issue #1013, this method no longer merges external package\n * objects into the manifest. Dependencies are referenced via\n * `smrtDependencies` and resolved at runtime by manifest-loader.ts.\n */\n private enrichManifest(\n manifest: SmartObjectManifest,\n options: ManifestBuilderOptions,\n scannerConfig: ScannerConfig,\n ): SmartObjectManifest {\n // Add module type\n manifest.moduleType = options.moduleType || 'smrt';\n\n // Record dependency references (not their objects) so runtime\n // manifest-loader.ts can discover and load them on demand.\n if (\n scannerConfig.smrtDependencies &&\n scannerConfig.smrtDependencies.length > 0\n ) {\n manifest.smrtDependencies = scannerConfig.smrtDependencies;\n }\n\n // Inject package info\n if (options.injectPackageInfo) {\n const packageInfo = this.readPackageJson();\n if (packageInfo.name) {\n manifest.packageName = packageInfo.name;\n logger.info(`[smrt] Injected package name: ${packageInfo.name}`);\n } else {\n logger.warn(\n '[smrt] Warning: Could not read package.json, packageName will be undefined',\n );\n }\n }\n\n return manifest;\n }\n\n /**\n * Write manifest JSON and optional TypeScript stub\n */\n private async writeOutput(\n manifest: SmartObjectManifest,\n options: ManifestBuilderOptions,\n ): Promise<void> {\n const manager = new ManifestManager(process.cwd());\n const isTest =\n options.outputName?.includes('test') ||\n options.stubName?.includes('test');\n const mode = isTest ? 'dev' : 'build';\n\n // 1. Always write to the unified location via ManifestManager\n manager.write(manifest, mode);\n\n // 2. Legacy/Explicit Output (if requested or for stubs)\n const outputDir = options.outputDir || 'src/manifest';\n const outputName = options.outputName || 'manifest.json';\n\n // Ensure output directory exists for legacy/stubs\n mkdirSync(outputDir, { recursive: true });\n\n // Write JSON manifest to legacy location if different from unified path\n const manifestPath = resolve(outputDir, outputName);\n const unifiedPath = manager.getOutputPath(mode);\n\n if (resolve(manifestPath) !== resolve(unifiedPath)) {\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));\n }\n\n // Write TypeScript stub if requested\n if (options.generateTypeStub) {\n const stubName = options.stubName || 'manifest.ts';\n const tsContent = this.generateTypeStub(manifest, stubName);\n const stubPath = resolve(outputDir, stubName);\n writeFileSync(stubPath, tsContent);\n }\n\n const objectCount = Object.keys(manifest.objects).length;\n logger.info(`[smrt] ✅ Generated manifest with ${objectCount} object(s)`);\n logger.info(`[smrt] Unified: ${unifiedPath}`);\n }\n\n /**\n * Generate TypeScript stub file with manifest constant\n */\n private generateTypeStub(\n manifest: SmartObjectManifest,\n filename: string,\n ): string {\n const isTestManifest = filename.includes('test');\n\n const comment = isTestManifest\n ? `/**\n * Test manifest stub\n * This file is replaced by generate-test-manifest.js during pretest\n * If tests run without pretest, this empty manifest is used\n *\n * DO NOT EDIT MANUALLY - This file is automatically generated\n */`\n : `/**\n * Auto-generated static manifest\n * Generated at build time from SMRT object scanning\n * DO NOT EDIT - This file is automatically generated\n */`;\n\n const exportName = isTestManifest ? 'testManifest' : 'staticManifest';\n\n // Use relative import for core package (to avoid self-reference during build),\n // package import for all other packages\n const isCorePackage = manifest.packageName === '@happyvertical/smrt-core';\n const importPath = isCorePackage\n ? '../scanner/types.js'\n : '@happyvertical/smrt-core/scanner/types';\n\n return `${comment}\n\nimport type { SmartObjectManifest } from '${importPath}';\n\nexport const ${exportName}: SmartObjectManifest = ${JSON.stringify(manifest, null, 2)} as const;\n\nexport default ${exportName};\n`;\n }\n\n /**\n * Load baseClasses from vite.config.ts\n */\n private async loadViteConfigBaseClasses(): Promise<string[] | null> {\n try {\n const viteConfigPath = resolve(process.cwd(), 'vite.config.ts');\n if (!existsSync(viteConfigPath)) {\n logger.info('[smrt] vite.config.ts not found');\n return null;\n }\n\n logger.info('[smrt] Found vite.config.ts, attempting to load...');\n\n // Use vite to load config which handles TypeScript\n const { loadConfigFromFile } = await import('vite');\n const loaded = await loadConfigFromFile(\n { command: 'build', mode: 'test' },\n viteConfigPath,\n );\n\n if (!loaded?.config?.plugins) {\n logger.info('[smrt] No plugins found in vite config');\n return null;\n }\n\n // Vite's loaded plugins are a recursive PluginOption[] (plugins, arrays,\n // falsy values, promises). We only probe a few optional fields, so model\n // them structurally and narrow defensively instead of using `any`.\n const plugins = loaded.config.plugins as readonly VitePluginProbe[];\n\n logger.info('[smrt] Vite config loaded', {\n plugins: plugins.map((p) => p?.name),\n });\n\n // Find smrtPlugin in plugins array\n const smrtPlugin = plugins.find((p) => p?.name === 'smrt-auto-service');\n\n if (!smrtPlugin) {\n logger.info(\n '[smrt] smrt-auto-service plugin not found in plugins array',\n );\n return null;\n }\n\n logger.info('[smrt] Found smrt-auto-service plugin');\n\n // Try different ways to access options\n const api = smrtPlugin.api;\n let opts: VitePluginOptions | undefined =\n (typeof api === 'object' && api !== null ? api.options : undefined) ||\n smrtPlugin.options ||\n smrtPlugin._options;\n\n if (!opts && typeof api === 'function') {\n try {\n opts = api().options;\n } catch (e) {\n logger.info('[smrt] Could not call plugin.api()');\n }\n }\n\n if (opts?.baseClasses) {\n logger.info('[smrt] Plugin options', {\n baseClasses: opts.baseClasses,\n followImports: opts.followImports,\n });\n return opts.baseClasses;\n }\n\n logger.info('[smrt] Could not access plugin options');\n return null;\n } catch (error) {\n logger.warn('[smrt] Error loading vite.config.ts', {\n error: error instanceof Error ? error.message : String(error),\n });\n logger.info('[smrt] Using default baseClasses');\n return null;\n }\n }\n\n /**\n * Load base classes from external SMRT package manifests\n */\n private async loadExternalBaseClasses(packages: string[]): Promise<string[]> {\n const externalBaseClasses: string[] = [];\n\n for (const pkgName of packages) {\n // Resolve the manifest the same way discovery does (honors `.smrt/` and\n // `src/manifest/`, not just `dist/`) so source-only workspace packages\n // still contribute base classes (#1378).\n const manifestPath = resolveManifestPath(pkgName, process.cwd());\n if (!manifestPath) {\n logger.info(`[smrt] ${pkgName}: no SMRT manifest resolved`);\n continue;\n }\n\n try {\n const manifestContent = readFileSync(manifestPath, 'utf-8');\n const manifest: SmartObjectManifest = JSON.parse(manifestContent);\n\n // Extract all class names from this package\n const foundClassNames: string[] = [];\n for (const objDef of Object.values(manifest.objects)) {\n if (objDef.className) {\n const className = objDef.className;\n foundClassNames.push(className);\n externalBaseClasses.push(className);\n }\n }\n\n logger.info(\n `[smrt] ${pkgName}: found ${foundClassNames.length} class(es) - ${foundClassNames.join(', ')}`,\n );\n } catch (error) {\n logger.info(\n `[smrt] ${pkgName}: manifest not found or invalid - ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n return externalBaseClasses;\n }\n\n /**\n * Read package.json from current working directory\n */\n private readPackageJson(): PackageInfo {\n try {\n const packageJsonPath = resolve(process.cwd(), 'package.json');\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n return {\n name: packageJson.name,\n version: packageJson.version,\n };\n } catch (error) {\n return {};\n }\n }\n\n /**\n * Create empty manifest when no files found\n */\n private createEmptyManifest(\n options: ManifestBuilderOptions,\n ): SmartObjectManifest {\n const manifest: SmartObjectManifest = {\n version: '1.0.0',\n timestamp: MANIFEST_TIMESTAMP,\n objects: {},\n moduleType: options.moduleType || 'smrt',\n };\n\n if (options.discoverExternalPackages) {\n manifest.smrtDependencies = discoverSmrtPackages();\n }\n\n if (options.injectPackageInfo) {\n const packageInfo = this.readPackageJson();\n if (packageInfo.name) {\n manifest.packageName = packageInfo.name;\n }\n }\n\n return manifest;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-loader.d.ts","sourceRoot":"","sources":["../../src/manifest/manifest-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAMH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElE,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"manifest-loader.d.ts","sourceRoot":"","sources":["../../src/manifest/manifest-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "../scanner/types.js";
|
|
1
2
|
import { createQualifiedName, isQualifiedName, parseQualifiedName } from "../utils/qualified-names.js";
|
|
2
3
|
import { getLocalTestManifestCache as getLocalTestManifestCache$1, getManifestCache, getStaticManifestCache as getStaticManifestCache$1, getTestManifestCache as getTestManifestCache$1, isTestEnvironment as isTestEnvironment$1, shouldLoadCoreTestManifest } from "./store.js";
|
|
3
4
|
import { getDefaultCompositeSource } from "./sources/composite.js";
|
|
@@ -147,7 +148,7 @@ function getStaticManifest() {
|
|
|
147
148
|
} catch {
|
|
148
149
|
setStaticManifestCache({
|
|
149
150
|
version: "1.0.0",
|
|
150
|
-
timestamp:
|
|
151
|
+
timestamp: 0,
|
|
151
152
|
objects: {},
|
|
152
153
|
packageName: "@happyvertical/smrt-core"
|
|
153
154
|
});
|