@dexto/image-bundler 1.7.1 → 1.8.0

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/index.js CHANGED
@@ -101,16 +101,7 @@ function generateImports(definition, discoveredFactories) {
101
101
  const compactionProviders = [...discoveredFactories.compaction].sort(
102
102
  (a, b) => a.type.localeCompare(b.type)
103
103
  );
104
- const blobProviders = [...discoveredFactories.storage.blob].sort(
105
- (a, b) => a.type.localeCompare(b.type)
106
- );
107
- const databaseProviders = [...discoveredFactories.storage.database].sort(
108
- (a, b) => a.type.localeCompare(b.type)
109
- );
110
- const cacheProviders = [...discoveredFactories.storage.cache].sort(
111
- (a, b) => a.type.localeCompare(b.type)
112
- );
113
- if (toolProviders.length > 0 || hookProviders.length > 0 || compactionProviders.length > 0 || blobProviders.length > 0 || databaseProviders.length > 0 || cacheProviders.length > 0) {
104
+ if (toolProviders.length > 0 || hookProviders.length > 0 || compactionProviders.length > 0) {
114
105
  imports.push("");
115
106
  imports.push("// Factories (convention folders; each must `export const factory = ...`)");
116
107
  }
@@ -126,18 +117,6 @@ function generateImports(definition, discoveredFactories) {
126
117
  const symbol = toFactoryImportSymbol("compaction", entry.type);
127
118
  imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);
128
119
  }
129
- for (const entry of blobProviders) {
130
- const symbol = toFactoryImportSymbol("storage_blob", entry.type);
131
- imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);
132
- }
133
- for (const entry of databaseProviders) {
134
- const symbol = toFactoryImportSymbol("storage_database", entry.type);
135
- imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);
136
- }
137
- for (const entry of cacheProviders) {
138
- const symbol = toFactoryImportSymbol("storage_cache", entry.type);
139
- imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);
140
- }
141
120
  return imports.join("\n");
142
121
  }
143
122
  function generateHelpers() {
@@ -206,18 +185,6 @@ function generateImageModule(definition, discoveredFactories) {
206
185
  const symbol = toFactoryImportSymbol("compaction", entry.type);
207
186
  return ` ${JSON.stringify(entry.type)}: ${symbol},`;
208
187
  });
209
- const blobEntries = discoveredFactories.storage.blob.slice().sort((a, b) => a.type.localeCompare(b.type)).map((entry) => {
210
- const symbol = toFactoryImportSymbol("storage_blob", entry.type);
211
- return ` ${JSON.stringify(entry.type)}: ${symbol},`;
212
- });
213
- const databaseEntries = discoveredFactories.storage.database.slice().sort((a, b) => a.type.localeCompare(b.type)).map((entry) => {
214
- const symbol = toFactoryImportSymbol("storage_database", entry.type);
215
- return ` ${JSON.stringify(entry.type)}: ${symbol},`;
216
- });
217
- const cacheEntries = discoveredFactories.storage.cache.slice().sort((a, b) => a.type.localeCompare(b.type)).map((entry) => {
218
- const symbol = toFactoryImportSymbol("storage_cache", entry.type);
219
- return ` ${JSON.stringify(entry.type)}: ${symbol},`;
220
- });
221
188
  const metadataLines = [];
222
189
  metadataLines.push(` name: ${JSON.stringify(definition.name)},`);
223
190
  metadataLines.push(` version: ${JSON.stringify(definition.version)},`);
@@ -242,12 +209,12 @@ function generateImageModule(definition, discoveredFactories) {
242
209
  ` : "";
243
210
  const compactionSpread = definition.extends ? ` ...baseImage.compaction,
244
211
  ` : "";
245
- const blobSpread = definition.extends ? ` ...baseImage.storage.blob,
246
- ` : "";
247
- const databaseSpread = definition.extends ? ` ...baseImage.storage.database,
248
- ` : "";
249
- const cacheSpread = definition.extends ? ` ...baseImage.storage.cache,
250
- ` : "";
212
+ const storageExpression = definition.extends ? `baseImage.storage` : `{
213
+ configSchema: { parse: (config) => config },
214
+ createStores: () => {
215
+ throw new Error('This generated image does not define storage. Extend an image with storage or provide a storage implementation.');
216
+ },
217
+ }`;
251
218
  const loggerExpression = definition.extends ? `baseImage.logger ?? defaultLoggerFactory` : `defaultLoggerFactory`;
252
219
  return `const image = {
253
220
  metadata: {
@@ -257,17 +224,7 @@ ${metadataLines.join("\n")}
257
224
  tools: {
258
225
  ${toolsSpread}${toolsEntries.join("\n")}
259
226
  },
260
- storage: {
261
- blob: {
262
- ${blobSpread}${blobEntries.join("\n")}
263
- },
264
- database: {
265
- ${databaseSpread}${databaseEntries.join("\n")}
266
- },
267
- cache: {
268
- ${cacheSpread}${cacheEntries.join("\n")}
269
- },
270
- },
227
+ storage: ${storageExpression},
271
228
  hooks: {
272
229
  ${hooksSpread}${hookEntries.join("\n")}
273
230
  },
@@ -358,21 +315,6 @@ async function bundle(options) {
358
315
  compileSourceFiles(compactionDir, join(outDir, "compaction"));
359
316
  compiledCount++;
360
317
  }
361
- const storageBlobDir = join(imageDir, "storage", "blob");
362
- if (existsSync(storageBlobDir)) {
363
- compileSourceFiles(storageBlobDir, join(outDir, "storage", "blob"));
364
- compiledCount++;
365
- }
366
- const storageDatabaseDir = join(imageDir, "storage", "database");
367
- if (existsSync(storageDatabaseDir)) {
368
- compileSourceFiles(storageDatabaseDir, join(outDir, "storage", "database"));
369
- compiledCount++;
370
- }
371
- const storageCacheDir = join(imageDir, "storage", "cache");
372
- if (existsSync(storageCacheDir)) {
373
- compileSourceFiles(storageCacheDir, join(outDir, "storage", "cache"));
374
- compiledCount++;
375
- }
376
318
  if (compiledCount > 0) {
377
319
  console.log(
378
320
  `\u2705 Compiled ${compiledCount} factory categor${compiledCount === 1 ? "y" : "ies"}`
@@ -538,11 +480,6 @@ function findTypeScriptFiles(dir) {
538
480
  function discoverFactories(imageDir, warnings) {
539
481
  const result = {
540
482
  tools: [],
541
- storage: {
542
- blob: [],
543
- database: [],
544
- cache: []
545
- },
546
483
  hooks: [],
547
484
  compaction: [],
548
485
  totalCount: 0
@@ -584,25 +521,10 @@ function discoverFactories(imageDir, warnings) {
584
521
  importBase: "compaction",
585
522
  label: "compaction/"
586
523
  });
587
- result.storage.blob = discoverFolder({
588
- srcDir: join(imageDir, "storage", "blob"),
589
- importBase: "storage/blob",
590
- label: "storage/blob/"
591
- });
592
- result.storage.database = discoverFolder({
593
- srcDir: join(imageDir, "storage", "database"),
594
- importBase: "storage/database",
595
- label: "storage/database/"
596
- });
597
- result.storage.cache = discoverFolder({
598
- srcDir: join(imageDir, "storage", "cache"),
599
- importBase: "storage/cache",
600
- label: "storage/cache/"
601
- });
602
- result.totalCount = result.tools.length + result.hooks.length + result.compaction.length + result.storage.blob.length + result.storage.database.length + result.storage.cache.length;
524
+ result.totalCount = result.tools.length + result.hooks.length + result.compaction.length;
603
525
  if (result.totalCount === 0) {
604
526
  warnings.push(
605
- "No factories discovered from convention folders. This image will not be able to resolve tools/storage unless it extends a base image."
527
+ "No factories discovered from convention folders. This image will not be able to resolve tools/hooks/compaction unless it extends a base image."
606
528
  );
607
529
  }
608
530
  return result;
@@ -656,15 +578,6 @@ async function validateDiscoveredFactories(outDir, discovered) {
656
578
  for (const entry of discovered.compaction) {
657
579
  validations.push(validateFactoryExport({ outDir, kind: "compaction", entry }));
658
580
  }
659
- for (const entry of discovered.storage.blob) {
660
- validations.push(validateFactoryExport({ outDir, kind: "storage.blob", entry }));
661
- }
662
- for (const entry of discovered.storage.database) {
663
- validations.push(validateFactoryExport({ outDir, kind: "storage.database", entry }));
664
- }
665
- for (const entry of discovered.storage.cache) {
666
- validations.push(validateFactoryExport({ outDir, kind: "storage.cache", entry }));
667
- }
668
581
  await Promise.all(validations);
669
582
  }
670
583
  export {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bundler.ts","../src/image-definition/validate-image-definition.ts","../src/generator.ts"],"sourcesContent":["/**\n * Main bundler logic\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, statSync } from 'node:fs';\nimport { mkdtemp, rm } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { dirname, join, resolve, extname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { validateImageDefinition } from './image-definition/validate-image-definition.js';\nimport type { ImageDefinition } from './image-definition/types.js';\nimport type { BundleOptions, BundleResult } from './types.js';\nimport { generateEntryPoint } from './generator.js';\nimport { build } from 'esbuild';\nimport ts from 'typescript';\n\n/**\n * Bundle a Dexto base image\n */\nexport async function bundle(options: BundleOptions): Promise<BundleResult> {\n const warnings: string[] = [];\n\n // 1. Load and validate image definition\n console.log(`📦 Loading image definition from ${options.imagePath}`);\n const definition = await loadImageDefinition(options.imagePath);\n\n console.log(`✅ Loaded image: ${definition.name} v${definition.version}`);\n\n // 2. Validate definition\n console.log(`🔍 Validating image definition...`);\n try {\n validateImageDefinition(definition);\n console.log(`✅ Image definition is valid`);\n } catch (error) {\n throw new Error(`Image validation failed: ${error}`);\n }\n\n // 3. Get core version (from package.json)\n const coreVersion = getCoreVersion();\n\n // 3.5. Discover factories from convention-based folders\n console.log(`🔍 Discovering factories from folders...`);\n const imageDir = dirname(options.imagePath);\n const discoveredFactories = discoverFactories(imageDir, warnings);\n console.log(`✅ Discovered ${discoveredFactories.totalCount} factory(ies)`);\n\n // 4. Generate code\n console.log(`🔨 Generating entry point...`);\n const generated = generateEntryPoint(definition, discoveredFactories);\n\n // 5. Ensure output directory exists\n const outDir = resolve(options.outDir);\n if (!existsSync(outDir)) {\n mkdirSync(outDir, { recursive: true });\n }\n\n // 5.5. Compile factory folders\n console.log(`🔨 Compiling factory source files...`);\n let compiledCount = 0;\n\n // tools/\n const toolsDir = join(imageDir, 'tools');\n if (existsSync(toolsDir)) {\n compileSourceFiles(toolsDir, join(outDir, 'tools'));\n compiledCount++;\n }\n\n // hooks/\n const hooksDir = join(imageDir, 'hooks');\n if (existsSync(hooksDir)) {\n compileSourceFiles(hooksDir, join(outDir, 'hooks'));\n compiledCount++;\n }\n\n // compaction/\n const compactionDir = join(imageDir, 'compaction');\n if (existsSync(compactionDir)) {\n compileSourceFiles(compactionDir, join(outDir, 'compaction'));\n compiledCount++;\n }\n\n // storage/blob/\n const storageBlobDir = join(imageDir, 'storage', 'blob');\n if (existsSync(storageBlobDir)) {\n compileSourceFiles(storageBlobDir, join(outDir, 'storage', 'blob'));\n compiledCount++;\n }\n\n // storage/database/\n const storageDatabaseDir = join(imageDir, 'storage', 'database');\n if (existsSync(storageDatabaseDir)) {\n compileSourceFiles(storageDatabaseDir, join(outDir, 'storage', 'database'));\n compiledCount++;\n }\n\n // storage/cache/\n const storageCacheDir = join(imageDir, 'storage', 'cache');\n if (existsSync(storageCacheDir)) {\n compileSourceFiles(storageCacheDir, join(outDir, 'storage', 'cache'));\n compiledCount++;\n }\n\n if (compiledCount > 0) {\n console.log(\n `✅ Compiled ${compiledCount} factory categor${compiledCount === 1 ? 'y' : 'ies'}`\n );\n }\n\n // 5.6. Validate discovered factories export the required contract\n console.log(`🔍 Validating factory exports...`);\n await validateDiscoveredFactories(outDir, discoveredFactories);\n\n // 6. Write generated files\n const entryFile = join(outDir, 'index.js');\n const typesFile = join(outDir, 'index.d.ts');\n\n console.log(`📝 Writing ${entryFile}...`);\n writeFileSync(entryFile, generated.js, 'utf-8');\n\n console.log(`📝 Writing ${typesFile}...`);\n writeFileSync(typesFile, generated.dts, 'utf-8');\n\n // 7. Generate package.json exports\n updatePackageJson(dirname(options.imagePath), outDir);\n\n console.log(`✨ Build complete!`);\n console.log(` Entry: ${entryFile}`);\n console.log(` Types: ${typesFile}`);\n\n const metadata = {\n name: definition.name,\n version: definition.version,\n description: definition.description,\n target: definition.target || 'custom',\n constraints: definition.constraints || [],\n builtAt: new Date().toISOString(),\n coreVersion,\n };\n\n return {\n entryFile,\n typesFile,\n metadata,\n warnings,\n };\n}\n\n/**\n * Load image definition from file\n */\nasync function loadImageDefinition(imagePath: string): Promise<ImageDefinition> {\n const absolutePath = resolve(imagePath);\n\n if (!existsSync(absolutePath)) {\n throw new Error(`Image file not found: ${absolutePath}`);\n }\n\n try {\n const imageDir = dirname(absolutePath);\n const tempDir = await mkdtemp(join(imageDir, '.dexto-image-definition-'));\n const compiledPath = join(tempDir, 'dexto.image.mjs');\n\n try {\n await build({\n entryPoints: [absolutePath],\n outfile: compiledPath,\n bundle: true,\n platform: 'node',\n format: 'esm',\n target: 'node20',\n packages: 'external',\n logLevel: 'silent',\n });\n\n const module = await import(pathToFileURL(compiledPath).href);\n\n // Get default export\n const definition = module.default as ImageDefinition;\n\n if (!definition) {\n throw new Error('Image file must have a default export');\n }\n\n return definition;\n } finally {\n await rm(tempDir, { recursive: true, force: true });\n }\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to load image definition: ${error.message}`);\n }\n throw error;\n }\n}\n\n/**\n * Get @dexto/core version\n */\nfunction getCoreVersion(): string {\n try {\n const require = createRequire(import.meta.url);\n const pkg = require('@dexto/core/package.json') as { version?: unknown };\n return typeof pkg.version === 'string' ? pkg.version : '1.0.0';\n } catch {\n return '1.0.0';\n }\n}\n\n/**\n * Update or create package.json with proper exports\n */\nfunction updatePackageJson(imageDir: string, outDir: string): void {\n const packageJsonPath = join(imageDir, 'package.json');\n\n if (!existsSync(packageJsonPath)) {\n console.log(`⚠️ No package.json found, skipping exports update`);\n return;\n }\n\n try {\n const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n\n // Update exports\n pkg.exports = {\n '.': {\n types: './dist/index.d.ts',\n import: './dist/index.js',\n },\n };\n\n // Update main and types fields\n pkg.main = './dist/index.js';\n pkg.types = './dist/index.d.ts';\n\n writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2), 'utf-8');\n console.log(`✅ Updated package.json exports`);\n } catch (error) {\n console.warn(`⚠️ Failed to update package.json: ${error}`);\n }\n}\n\n/**\n * Compile TypeScript source files to JavaScript\n */\nfunction compileSourceFiles(srcDir: string, outDir: string): void {\n // Find all .ts files\n const tsFiles = findTypeScriptFiles(srcDir);\n\n if (tsFiles.length === 0) {\n console.log(` No TypeScript files found in ${srcDir}`);\n return;\n }\n\n console.log(` Found ${tsFiles.length} TypeScript file(s) to compile`);\n\n // TypeScript compiler options\n const compilerOptions: ts.CompilerOptions = {\n target: ts.ScriptTarget.ES2022,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n outDir: outDir,\n rootDir: srcDir, // Use srcDir as root\n declaration: true,\n esModuleInterop: true,\n skipLibCheck: true,\n strict: true,\n resolveJsonModule: true,\n };\n\n // Create program\n const program = ts.createProgram(tsFiles, compilerOptions);\n\n // Emit compiled files\n const emitResult = program.emit();\n\n // Check for errors\n const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);\n\n if (allDiagnostics.length > 0) {\n allDiagnostics.forEach((diagnostic) => {\n if (diagnostic.file) {\n const { line, character } = ts.getLineAndCharacterOfPosition(\n diagnostic.file,\n diagnostic.start!\n );\n const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\\n');\n console.error(\n ` ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`\n );\n } else {\n console.error(\n ` ${ts.flattenDiagnosticMessageText(diagnostic.messageText, '\\n')}`\n );\n }\n });\n\n if (emitResult.emitSkipped) {\n throw new Error('TypeScript compilation failed');\n }\n }\n}\n\n/**\n * Recursively find all TypeScript files in a directory\n */\nfunction findTypeScriptFiles(dir: string): string[] {\n const files: string[] = [];\n\n function walk(currentDir: string) {\n const entries = readdirSync(currentDir);\n\n for (const entry of entries) {\n const fullPath = join(currentDir, entry);\n const stat = statSync(fullPath);\n\n if (stat.isDirectory()) {\n walk(fullPath);\n } else if (stat.isFile() && extname(entry) === '.ts') {\n files.push(fullPath);\n }\n }\n }\n\n walk(dir);\n return files;\n}\n\n/**\n * Factory discovery result for a single category\n */\nexport interface DiscoveredFactory {\n type: string;\n importPath: string;\n}\n\nexport interface DiscoveredFactories {\n tools: DiscoveredFactory[];\n storage: {\n blob: DiscoveredFactory[];\n database: DiscoveredFactory[];\n cache: DiscoveredFactory[];\n };\n hooks: DiscoveredFactory[];\n compaction: DiscoveredFactory[];\n totalCount: number;\n}\n\n/**\n * Discover factories from convention-based folder structure\n *\n * Convention (folder-based with index.ts):\n * tools/ - ToolFactory folders\n * weather/ - Factory folder\n * index.ts - Factory implementation (auto-discovered)\n * helpers.ts - Optional helper files\n * types.ts - Optional type definitions\n * compaction/ - CompactionFactory folders\n * hooks/ - HookFactory folders\n * storage/blob/ - BlobStoreFactory folders\n * storage/cache/ - CacheFactory folders\n * storage/database/ - DatabaseFactory folders\n *\n * Naming Convention (Node.js standard):\n * <folder>/index.ts - Auto-discovered and registered\n * <folder>/other.ts - Ignored unless imported by index.ts\n */\nfunction discoverFactories(imageDir: string, warnings: string[]): DiscoveredFactories {\n const result: DiscoveredFactories = {\n tools: [],\n storage: {\n blob: [],\n database: [],\n cache: [],\n },\n hooks: [],\n compaction: [],\n totalCount: 0,\n };\n\n const discoverFolder = (options: {\n srcDir: string;\n importBase: string;\n label: string;\n }): DiscoveredFactory[] => {\n const { srcDir, importBase, label } = options;\n\n if (!existsSync(srcDir)) {\n return [];\n }\n\n const factoryFolders = readdirSync(srcDir).filter((entry) => {\n const entryPath = join(srcDir, entry);\n const stat = statSync(entryPath);\n if (!stat.isDirectory()) {\n return false;\n }\n\n const indexPath = join(entryPath, 'index.ts');\n return existsSync(indexPath);\n });\n\n if (factoryFolders.length > 0) {\n console.log(` Found ${factoryFolders.length} factory(ies) in ${label}`);\n }\n\n return factoryFolders.map((type) => ({\n type,\n importPath: `./${importBase}/${type}/index.js`,\n }));\n };\n\n // tools/\n result.tools = discoverFolder({\n srcDir: join(imageDir, 'tools'),\n importBase: 'tools',\n label: 'tools/',\n });\n\n // hooks/\n result.hooks = discoverFolder({\n srcDir: join(imageDir, 'hooks'),\n importBase: 'hooks',\n label: 'hooks/',\n });\n\n // compaction/\n result.compaction = discoverFolder({\n srcDir: join(imageDir, 'compaction'),\n importBase: 'compaction',\n label: 'compaction/',\n });\n\n // storage/blob/\n result.storage.blob = discoverFolder({\n srcDir: join(imageDir, 'storage', 'blob'),\n importBase: 'storage/blob',\n label: 'storage/blob/',\n });\n\n // storage/database/\n result.storage.database = discoverFolder({\n srcDir: join(imageDir, 'storage', 'database'),\n importBase: 'storage/database',\n label: 'storage/database/',\n });\n\n // storage/cache/\n result.storage.cache = discoverFolder({\n srcDir: join(imageDir, 'storage', 'cache'),\n importBase: 'storage/cache',\n label: 'storage/cache/',\n });\n\n result.totalCount =\n result.tools.length +\n result.hooks.length +\n result.compaction.length +\n result.storage.blob.length +\n result.storage.database.length +\n result.storage.cache.length;\n\n if (result.totalCount === 0) {\n warnings.push(\n 'No factories discovered from convention folders. This image will not be able to resolve tools/storage unless it extends a base image.'\n );\n }\n\n return result;\n}\n\nasync function validateFactoryExport(options: {\n outDir: string;\n kind: string;\n entry: DiscoveredFactory;\n}): Promise<void> {\n const { outDir, kind, entry } = options;\n\n const absolutePath = resolve(outDir, entry.importPath);\n const fileUrl = pathToFileURL(absolutePath).href;\n\n let module: unknown;\n try {\n module = await import(fileUrl);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Failed to import ${kind} factory '${entry.type}' (${entry.importPath}): ${message}`\n );\n }\n\n if (!module || typeof module !== 'object') {\n throw new Error(\n `Invalid ${kind} factory '${entry.type}' (${entry.importPath}): expected an object module export`\n );\n }\n\n const factory = (module as Record<string, unknown>).factory;\n if (!factory || typeof factory !== 'object') {\n throw new Error(\n `Invalid ${kind} factory '${entry.type}' (${entry.importPath}): missing 'factory' export`\n );\n }\n\n const configSchema = (factory as Record<string, unknown>).configSchema;\n const create = (factory as Record<string, unknown>).create;\n\n const parse = (configSchema as { parse?: unknown } | null | undefined)?.parse;\n if (!configSchema || typeof configSchema !== 'object' || typeof parse !== 'function') {\n throw new Error(\n `Invalid ${kind} factory '${entry.type}' (${entry.importPath}): factory.configSchema must be a Zod schema`\n );\n }\n\n if (typeof create !== 'function') {\n throw new Error(\n `Invalid ${kind} factory '${entry.type}' (${entry.importPath}): factory.create must be a function`\n );\n }\n}\n\nasync function validateDiscoveredFactories(\n outDir: string,\n discovered: DiscoveredFactories\n): Promise<void> {\n const validations: Array<Promise<void>> = [];\n\n for (const entry of discovered.tools) {\n validations.push(validateFactoryExport({ outDir, kind: 'tool', entry }));\n }\n for (const entry of discovered.hooks) {\n validations.push(validateFactoryExport({ outDir, kind: 'hook', entry }));\n }\n for (const entry of discovered.compaction) {\n validations.push(validateFactoryExport({ outDir, kind: 'compaction', entry }));\n }\n for (const entry of discovered.storage.blob) {\n validations.push(validateFactoryExport({ outDir, kind: 'storage.blob', entry }));\n }\n for (const entry of discovered.storage.database) {\n validations.push(validateFactoryExport({ outDir, kind: 'storage.database', entry }));\n }\n for (const entry of discovered.storage.cache) {\n validations.push(validateFactoryExport({ outDir, kind: 'storage.cache', entry }));\n }\n\n await Promise.all(validations);\n}\n","import type { ImageDefinition } from './types.js';\n\n/**\n * Validate an image definition.\n * Throws if the definition is invalid.\n *\n * Used by bundler to validate images before building.\n */\nexport function validateImageDefinition(definition: ImageDefinition): void {\n // Basic validation\n if (!definition.name || typeof definition.name !== 'string') {\n throw new Error('Image name must be a non-empty string');\n }\n\n if (!definition.version || typeof definition.version !== 'string') {\n throw new Error('Image version must be a non-empty string');\n }\n\n if (!definition.description || typeof definition.description !== 'string') {\n throw new Error('Image description must be a non-empty string');\n }\n\n // Validate version format (basic semver check)\n const versionRegex = /^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$/;\n if (!versionRegex.test(definition.version)) {\n throw new Error(\n `Image version '${definition.version}' is not valid semver. Expected format: x.y.z`\n );\n }\n\n // Validate target if provided\n if (definition.target !== undefined) {\n if (typeof definition.target !== 'string' || definition.target.trim().length === 0) {\n throw new Error(`Image target must be a non-empty string when provided`);\n }\n }\n\n if (definition.constraints) {\n if (!Array.isArray(definition.constraints)) {\n throw new Error('Image constraints must be an array');\n }\n\n for (const constraint of definition.constraints) {\n if (typeof constraint !== 'string' || constraint.trim().length === 0) {\n throw new Error(`Image constraint must be a non-empty string`);\n }\n }\n }\n\n // Validate utils if provided\n if (definition.utils) {\n for (const [name, path] of Object.entries(definition.utils)) {\n if (typeof path !== 'string') {\n throw new Error(`Utility '${name}' path must be a string`);\n }\n if (!path.startsWith('./')) {\n throw new Error(\n `Utility '${name}' path must be relative (start with './'). Got: ${path}`\n );\n }\n }\n }\n\n // Validate extends if provided\n if (definition.extends) {\n if (typeof definition.extends !== 'string') {\n throw new Error('Image extends must be a string (parent image name)');\n }\n }\n}\n","/**\n * Code generator for images\n *\n * Transforms image definitions + convention folders into importable packages with:\n * - A typed `DextoImage` default export (no side effects)\n * - Optional utility re-exports\n */\n\nimport type { ImageDefinition } from './image-definition/types.js';\nimport type { GeneratedCode } from './types.js';\nimport type { DiscoveredFactories } from './bundler.js';\n\n/**\n * Generate JavaScript entry point for an image\n */\nexport function generateEntryPoint(\n definition: ImageDefinition,\n discoveredFactories: DiscoveredFactories\n): GeneratedCode {\n const imports = generateImports(definition, discoveredFactories);\n const helpers = definition.extends ? generateHelpers() : '';\n const imageModule = generateImageModule(definition, discoveredFactories);\n const utilityExports = generateUtilityExports(definition);\n\n const js = `// AUTO-GENERATED by @dexto/image-bundler\n// Do not edit this file directly. Edit dexto.image.ts instead.\n\n${imports}\n\n${helpers}\n\n${imageModule}\n\n${utilityExports}\n`;\n\n // Generate TypeScript definitions\n const dts = generateTypeDefinitions(definition);\n\n return { js, dts };\n}\n\nfunction sanitizeIdentifier(value: string): string {\n const sanitized = value.replace(/[^a-zA-Z0-9_$]/g, '_');\n if (/^[a-zA-Z_$]/.test(sanitized)) {\n return sanitized;\n }\n return `_${sanitized}`;\n}\n\nfunction toFactoryImportSymbol(prefix: string, type: string): string {\n return sanitizeIdentifier(`${prefix}_${type}`);\n}\n\nfunction generateImports(\n definition: ImageDefinition,\n discoveredFactories: DiscoveredFactories\n): string {\n const imports: string[] = [];\n\n if (definition.extends) {\n imports.push(`import baseImage from '${definition.extends}';`);\n }\n\n imports.push(`import { defaultLoggerFactory } from '@dexto/core';`);\n\n const toolProviders = [...discoveredFactories.tools].sort((a, b) =>\n a.type.localeCompare(b.type)\n );\n const hookProviders = [...discoveredFactories.hooks].sort((a, b) =>\n a.type.localeCompare(b.type)\n );\n const compactionProviders = [...discoveredFactories.compaction].sort((a, b) =>\n a.type.localeCompare(b.type)\n );\n const blobProviders = [...discoveredFactories.storage.blob].sort((a, b) =>\n a.type.localeCompare(b.type)\n );\n const databaseProviders = [...discoveredFactories.storage.database].sort((a, b) =>\n a.type.localeCompare(b.type)\n );\n const cacheProviders = [...discoveredFactories.storage.cache].sort((a, b) =>\n a.type.localeCompare(b.type)\n );\n\n if (\n toolProviders.length > 0 ||\n hookProviders.length > 0 ||\n compactionProviders.length > 0 ||\n blobProviders.length > 0 ||\n databaseProviders.length > 0 ||\n cacheProviders.length > 0\n ) {\n imports.push('');\n imports.push('// Factories (convention folders; each must `export const factory = ...`)');\n }\n\n for (const entry of toolProviders) {\n const symbol = toFactoryImportSymbol('tools', entry.type);\n imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);\n }\n for (const entry of hookProviders) {\n const symbol = toFactoryImportSymbol('hooks', entry.type);\n imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);\n }\n for (const entry of compactionProviders) {\n const symbol = toFactoryImportSymbol('compaction', entry.type);\n imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);\n }\n for (const entry of blobProviders) {\n const symbol = toFactoryImportSymbol('storage_blob', entry.type);\n imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);\n }\n for (const entry of databaseProviders) {\n const symbol = toFactoryImportSymbol('storage_database', entry.type);\n imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);\n }\n for (const entry of cacheProviders) {\n const symbol = toFactoryImportSymbol('storage_cache', entry.type);\n imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);\n }\n\n return imports.join('\\n');\n}\n\nfunction generateHelpers(): string {\n return `function isPlainObject(value) {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction mergeImageDefaults(baseDefaults, overrideDefaults) {\n if (!baseDefaults) return overrideDefaults;\n if (!overrideDefaults) return baseDefaults;\n\n const merged = { ...baseDefaults, ...overrideDefaults };\n for (const [key, baseValue] of Object.entries(baseDefaults)) {\n const overrideValue = overrideDefaults[key];\n if (!isPlainObject(baseValue) || !isPlainObject(overrideValue)) {\n continue;\n }\n merged[key] = {\n ...baseValue,\n ...overrideValue,\n };\n }\n return merged;\n}`;\n}\n\nfunction generateUtilityExports(definition: ImageDefinition): string {\n const sections: string[] = [];\n\n // Generate wildcard utility exports\n if (definition.utils && Object.keys(definition.utils).length > 0) {\n sections.push('// Utility exports');\n for (const [name, path] of Object.entries(definition.utils)) {\n sections.push(`export * from '${path}';`);\n }\n }\n\n // Generate selective named exports (filter out type-only exports for runtime JS)\n if (definition.exports && Object.keys(definition.exports).length > 0) {\n if (sections.length > 0) sections.push('');\n sections.push('// Selective package re-exports');\n for (const [packageName, exports] of Object.entries(definition.exports)) {\n // Check for wildcard re-export\n if (exports.length === 1 && exports[0] === '*') {\n sections.push(`export * from '${packageName}';`);\n continue;\n }\n\n // Filter out type-only exports (those starting with 'type ')\n const runtimeExports = exports.filter((exp) => !exp.startsWith('type '));\n if (runtimeExports.length > 0) {\n sections.push(`export {`);\n sections.push(` ${runtimeExports.join(',\\n ')}`);\n sections.push(`} from '${packageName}';`);\n }\n }\n }\n\n if (sections.length === 0) {\n return '// No utilities or exports defined for this image';\n }\n\n return sections.join('\\n');\n}\n\nfunction generateImageModule(\n definition: ImageDefinition,\n discoveredFactories: DiscoveredFactories\n): string {\n const derivedDefaults =\n definition.defaults !== undefined\n ? JSON.stringify(definition.defaults, null, 4)\n : 'undefined';\n\n const toolsEntries = discoveredFactories.tools\n .slice()\n .sort((a, b) => a.type.localeCompare(b.type))\n .map((entry) => {\n const symbol = toFactoryImportSymbol('tools', entry.type);\n return ` ${JSON.stringify(entry.type)}: ${symbol},`;\n });\n\n const hookEntries = discoveredFactories.hooks\n .slice()\n .sort((a, b) => a.type.localeCompare(b.type))\n .map((entry) => {\n const symbol = toFactoryImportSymbol('hooks', entry.type);\n return ` ${JSON.stringify(entry.type)}: ${symbol},`;\n });\n\n const compactionEntries = discoveredFactories.compaction\n .slice()\n .sort((a, b) => a.type.localeCompare(b.type))\n .map((entry) => {\n const symbol = toFactoryImportSymbol('compaction', entry.type);\n return ` ${JSON.stringify(entry.type)}: ${symbol},`;\n });\n\n const blobEntries = discoveredFactories.storage.blob\n .slice()\n .sort((a, b) => a.type.localeCompare(b.type))\n .map((entry) => {\n const symbol = toFactoryImportSymbol('storage_blob', entry.type);\n return ` ${JSON.stringify(entry.type)}: ${symbol},`;\n });\n\n const databaseEntries = discoveredFactories.storage.database\n .slice()\n .sort((a, b) => a.type.localeCompare(b.type))\n .map((entry) => {\n const symbol = toFactoryImportSymbol('storage_database', entry.type);\n return ` ${JSON.stringify(entry.type)}: ${symbol},`;\n });\n\n const cacheEntries = discoveredFactories.storage.cache\n .slice()\n .sort((a, b) => a.type.localeCompare(b.type))\n .map((entry) => {\n const symbol = toFactoryImportSymbol('storage_cache', entry.type);\n return ` ${JSON.stringify(entry.type)}: ${symbol},`;\n });\n\n const metadataLines: string[] = [];\n metadataLines.push(` name: ${JSON.stringify(definition.name)},`);\n metadataLines.push(` version: ${JSON.stringify(definition.version)},`);\n metadataLines.push(` description: ${JSON.stringify(definition.description)},`);\n\n if (definition.target !== undefined) {\n metadataLines.push(` target: ${JSON.stringify(definition.target)},`);\n } else if (definition.extends) {\n metadataLines.push(` target: baseImage.metadata.target,`);\n }\n\n if (definition.extends) {\n const derivedConstraints = JSON.stringify(definition.constraints ?? []);\n metadataLines.push(\n ` constraints: Array.from(new Set([...(baseImage.metadata.constraints ?? []), ...${derivedConstraints}])),`\n );\n } else if (definition.constraints !== undefined) {\n metadataLines.push(` constraints: ${JSON.stringify(definition.constraints)},`);\n }\n\n const defaultsExpression = definition.extends\n ? `mergeImageDefaults(baseImage.defaults, ${derivedDefaults})`\n : derivedDefaults;\n\n const toolsSpread = definition.extends ? ` ...baseImage.tools,\\n` : '';\n const hooksSpread = definition.extends ? ` ...baseImage.hooks,\\n` : '';\n const compactionSpread = definition.extends ? ` ...baseImage.compaction,\\n` : '';\n\n const blobSpread = definition.extends ? ` ...baseImage.storage.blob,\\n` : '';\n const databaseSpread = definition.extends ? ` ...baseImage.storage.database,\\n` : '';\n const cacheSpread = definition.extends ? ` ...baseImage.storage.cache,\\n` : '';\n\n const loggerExpression = definition.extends\n ? `baseImage.logger ?? defaultLoggerFactory`\n : `defaultLoggerFactory`;\n\n return `const image = {\n metadata: {\n${metadataLines.join('\\n')}\n },\n defaults: ${defaultsExpression},\n tools: {\n${toolsSpread}${toolsEntries.join('\\n')}\n },\n storage: {\n blob: {\n${blobSpread}${blobEntries.join('\\n')}\n },\n database: {\n${databaseSpread}${databaseEntries.join('\\n')}\n },\n cache: {\n${cacheSpread}${cacheEntries.join('\\n')}\n },\n },\n hooks: {\n${hooksSpread}${hookEntries.join('\\n')}\n },\n compaction: {\n${compactionSpread}${compactionEntries.join('\\n')}\n },\n logger: ${loggerExpression},\n};\n\nexport default image;`;\n}\n\nfunction generateTypeDefinitions(definition: ImageDefinition): string {\n const sections: string[] = [];\n\n // Wildcard utility exports\n if (definition.utils && Object.keys(definition.utils).length > 0) {\n sections.push('// Utility re-exports');\n for (const path of Object.values(definition.utils)) {\n sections.push(`export * from '${path}';`);\n }\n }\n\n // Selective named exports\n if (definition.exports && Object.keys(definition.exports).length > 0) {\n if (sections.length > 0) sections.push('');\n sections.push('// Selective package re-exports');\n for (const [packageName, exports] of Object.entries(definition.exports)) {\n // Check for wildcard re-export\n if (exports.length === 1 && exports[0] === '*') {\n sections.push(`export * from '${packageName}';`);\n continue;\n }\n\n sections.push(`export {`);\n sections.push(` ${exports.join(',\\n ')}`);\n sections.push(`} from '${packageName}';`);\n }\n }\n\n const utilityExports = sections.length > 0 ? '\\n\\n' + sections.join('\\n') : '';\n\n return `// AUTO-GENERATED TypeScript definitions\n// Do not edit this file directly\n\n\timport type { DextoImage } from '@dexto/agent-config';\n\n\t/**\n\t * Typed image module (no side effects)\n\t */\n\t\tdeclare const image: DextoImage;\n\t\texport default image;\n${utilityExports}\n\t`;\n}\n"],"mappings":"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","names":["require"]}
1
+ {"version":3,"sources":["../src/bundler.ts","../src/image-definition/validate-image-definition.ts","../src/generator.ts"],"sourcesContent":["/**\n * Main bundler logic\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, statSync } from 'node:fs';\nimport { mkdtemp, rm } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { dirname, join, resolve, extname } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { validateImageDefinition } from './image-definition/validate-image-definition.js';\nimport type { ImageDefinition } from './image-definition/types.js';\nimport type { BundleOptions, BundleResult } from './types.js';\nimport { generateEntryPoint } from './generator.js';\nimport { build } from 'esbuild';\nimport ts from 'typescript';\n\n/**\n * Bundle a Dexto base image\n */\nexport async function bundle(options: BundleOptions): Promise<BundleResult> {\n const warnings: string[] = [];\n\n // 1. Load and validate image definition\n console.log(`📦 Loading image definition from ${options.imagePath}`);\n const definition = await loadImageDefinition(options.imagePath);\n\n console.log(`✅ Loaded image: ${definition.name} v${definition.version}`);\n\n // 2. Validate definition\n console.log(`🔍 Validating image definition...`);\n try {\n validateImageDefinition(definition);\n console.log(`✅ Image definition is valid`);\n } catch (error) {\n throw new Error(`Image validation failed: ${error}`);\n }\n\n // 3. Get core version (from package.json)\n const coreVersion = getCoreVersion();\n\n // 3.5. Discover factories from convention-based folders\n console.log(`🔍 Discovering factories from folders...`);\n const imageDir = dirname(options.imagePath);\n const discoveredFactories = discoverFactories(imageDir, warnings);\n console.log(`✅ Discovered ${discoveredFactories.totalCount} factory(ies)`);\n\n // 4. Generate code\n console.log(`🔨 Generating entry point...`);\n const generated = generateEntryPoint(definition, discoveredFactories);\n\n // 5. Ensure output directory exists\n const outDir = resolve(options.outDir);\n if (!existsSync(outDir)) {\n mkdirSync(outDir, { recursive: true });\n }\n\n // 5.5. Compile factory folders\n console.log(`🔨 Compiling factory source files...`);\n let compiledCount = 0;\n\n // tools/\n const toolsDir = join(imageDir, 'tools');\n if (existsSync(toolsDir)) {\n compileSourceFiles(toolsDir, join(outDir, 'tools'));\n compiledCount++;\n }\n\n // hooks/\n const hooksDir = join(imageDir, 'hooks');\n if (existsSync(hooksDir)) {\n compileSourceFiles(hooksDir, join(outDir, 'hooks'));\n compiledCount++;\n }\n\n // compaction/\n const compactionDir = join(imageDir, 'compaction');\n if (existsSync(compactionDir)) {\n compileSourceFiles(compactionDir, join(outDir, 'compaction'));\n compiledCount++;\n }\n\n if (compiledCount > 0) {\n console.log(\n `✅ Compiled ${compiledCount} factory categor${compiledCount === 1 ? 'y' : 'ies'}`\n );\n }\n\n // 5.6. Validate discovered factories export the required contract\n console.log(`🔍 Validating factory exports...`);\n await validateDiscoveredFactories(outDir, discoveredFactories);\n\n // 6. Write generated files\n const entryFile = join(outDir, 'index.js');\n const typesFile = join(outDir, 'index.d.ts');\n\n console.log(`📝 Writing ${entryFile}...`);\n writeFileSync(entryFile, generated.js, 'utf-8');\n\n console.log(`📝 Writing ${typesFile}...`);\n writeFileSync(typesFile, generated.dts, 'utf-8');\n\n // 7. Generate package.json exports\n updatePackageJson(dirname(options.imagePath), outDir);\n\n console.log(`✨ Build complete!`);\n console.log(` Entry: ${entryFile}`);\n console.log(` Types: ${typesFile}`);\n\n const metadata = {\n name: definition.name,\n version: definition.version,\n description: definition.description,\n target: definition.target || 'custom',\n constraints: definition.constraints || [],\n builtAt: new Date().toISOString(),\n coreVersion,\n };\n\n return {\n entryFile,\n typesFile,\n metadata,\n warnings,\n };\n}\n\n/**\n * Load image definition from file\n */\nasync function loadImageDefinition(imagePath: string): Promise<ImageDefinition> {\n const absolutePath = resolve(imagePath);\n\n if (!existsSync(absolutePath)) {\n throw new Error(`Image file not found: ${absolutePath}`);\n }\n\n try {\n const imageDir = dirname(absolutePath);\n const tempDir = await mkdtemp(join(imageDir, '.dexto-image-definition-'));\n const compiledPath = join(tempDir, 'dexto.image.mjs');\n\n try {\n await build({\n entryPoints: [absolutePath],\n outfile: compiledPath,\n bundle: true,\n platform: 'node',\n format: 'esm',\n target: 'node20',\n packages: 'external',\n logLevel: 'silent',\n });\n\n const module = await import(pathToFileURL(compiledPath).href);\n\n // Get default export\n const definition = module.default as ImageDefinition;\n\n if (!definition) {\n throw new Error('Image file must have a default export');\n }\n\n return definition;\n } finally {\n await rm(tempDir, { recursive: true, force: true });\n }\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to load image definition: ${error.message}`);\n }\n throw error;\n }\n}\n\n/**\n * Get @dexto/core version\n */\nfunction getCoreVersion(): string {\n try {\n const require = createRequire(import.meta.url);\n const pkg = require('@dexto/core/package.json') as { version?: unknown };\n return typeof pkg.version === 'string' ? pkg.version : '1.0.0';\n } catch {\n return '1.0.0';\n }\n}\n\n/**\n * Update or create package.json with proper exports\n */\nfunction updatePackageJson(imageDir: string, outDir: string): void {\n const packageJsonPath = join(imageDir, 'package.json');\n\n if (!existsSync(packageJsonPath)) {\n console.log(`⚠️ No package.json found, skipping exports update`);\n return;\n }\n\n try {\n const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n\n // Update exports\n pkg.exports = {\n '.': {\n types: './dist/index.d.ts',\n import: './dist/index.js',\n },\n };\n\n // Update main and types fields\n pkg.main = './dist/index.js';\n pkg.types = './dist/index.d.ts';\n\n writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2), 'utf-8');\n console.log(`✅ Updated package.json exports`);\n } catch (error) {\n console.warn(`⚠️ Failed to update package.json: ${error}`);\n }\n}\n\n/**\n * Compile TypeScript source files to JavaScript\n */\nfunction compileSourceFiles(srcDir: string, outDir: string): void {\n // Find all .ts files\n const tsFiles = findTypeScriptFiles(srcDir);\n\n if (tsFiles.length === 0) {\n console.log(` No TypeScript files found in ${srcDir}`);\n return;\n }\n\n console.log(` Found ${tsFiles.length} TypeScript file(s) to compile`);\n\n // TypeScript compiler options\n const compilerOptions: ts.CompilerOptions = {\n target: ts.ScriptTarget.ES2022,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n outDir: outDir,\n rootDir: srcDir, // Use srcDir as root\n declaration: true,\n esModuleInterop: true,\n skipLibCheck: true,\n strict: true,\n resolveJsonModule: true,\n };\n\n // Create program\n const program = ts.createProgram(tsFiles, compilerOptions);\n\n // Emit compiled files\n const emitResult = program.emit();\n\n // Check for errors\n const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);\n\n if (allDiagnostics.length > 0) {\n allDiagnostics.forEach((diagnostic) => {\n if (diagnostic.file) {\n const { line, character } = ts.getLineAndCharacterOfPosition(\n diagnostic.file,\n diagnostic.start!\n );\n const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\\n');\n console.error(\n ` ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`\n );\n } else {\n console.error(\n ` ${ts.flattenDiagnosticMessageText(diagnostic.messageText, '\\n')}`\n );\n }\n });\n\n if (emitResult.emitSkipped) {\n throw new Error('TypeScript compilation failed');\n }\n }\n}\n\n/**\n * Recursively find all TypeScript files in a directory\n */\nfunction findTypeScriptFiles(dir: string): string[] {\n const files: string[] = [];\n\n function walk(currentDir: string) {\n const entries = readdirSync(currentDir);\n\n for (const entry of entries) {\n const fullPath = join(currentDir, entry);\n const stat = statSync(fullPath);\n\n if (stat.isDirectory()) {\n walk(fullPath);\n } else if (stat.isFile() && extname(entry) === '.ts') {\n files.push(fullPath);\n }\n }\n }\n\n walk(dir);\n return files;\n}\n\n/**\n * Factory discovery result for a single category\n */\nexport interface DiscoveredFactory {\n type: string;\n importPath: string;\n}\n\nexport interface DiscoveredFactories {\n tools: DiscoveredFactory[];\n hooks: DiscoveredFactory[];\n compaction: DiscoveredFactory[];\n totalCount: number;\n}\n\n/**\n * Discover factories from convention-based folder structure\n *\n * Convention (folder-based with index.ts):\n * tools/ - ToolFactory folders\n * weather/ - Factory folder\n * index.ts - Factory implementation (auto-discovered)\n * helpers.ts - Optional helper files\n * types.ts - Optional type definitions\n * compaction/ - CompactionFactory folders\n * hooks/ - HookFactory folders\n * storage is an image-level createStores implementation, not convention-discovered\n *\n * Naming Convention (Node.js standard):\n * <folder>/index.ts - Auto-discovered and registered\n * <folder>/other.ts - Ignored unless imported by index.ts\n */\nfunction discoverFactories(imageDir: string, warnings: string[]): DiscoveredFactories {\n const result: DiscoveredFactories = {\n tools: [],\n hooks: [],\n compaction: [],\n totalCount: 0,\n };\n\n const discoverFolder = (options: {\n srcDir: string;\n importBase: string;\n label: string;\n }): DiscoveredFactory[] => {\n const { srcDir, importBase, label } = options;\n\n if (!existsSync(srcDir)) {\n return [];\n }\n\n const factoryFolders = readdirSync(srcDir).filter((entry) => {\n const entryPath = join(srcDir, entry);\n const stat = statSync(entryPath);\n if (!stat.isDirectory()) {\n return false;\n }\n\n const indexPath = join(entryPath, 'index.ts');\n return existsSync(indexPath);\n });\n\n if (factoryFolders.length > 0) {\n console.log(` Found ${factoryFolders.length} factory(ies) in ${label}`);\n }\n\n return factoryFolders.map((type) => ({\n type,\n importPath: `./${importBase}/${type}/index.js`,\n }));\n };\n\n // tools/\n result.tools = discoverFolder({\n srcDir: join(imageDir, 'tools'),\n importBase: 'tools',\n label: 'tools/',\n });\n\n // hooks/\n result.hooks = discoverFolder({\n srcDir: join(imageDir, 'hooks'),\n importBase: 'hooks',\n label: 'hooks/',\n });\n\n // compaction/\n result.compaction = discoverFolder({\n srcDir: join(imageDir, 'compaction'),\n importBase: 'compaction',\n label: 'compaction/',\n });\n\n result.totalCount = result.tools.length + result.hooks.length + result.compaction.length;\n\n if (result.totalCount === 0) {\n warnings.push(\n 'No factories discovered from convention folders. This image will not be able to resolve tools/hooks/compaction unless it extends a base image.'\n );\n }\n\n return result;\n}\n\nasync function validateFactoryExport(options: {\n outDir: string;\n kind: string;\n entry: DiscoveredFactory;\n}): Promise<void> {\n const { outDir, kind, entry } = options;\n\n const absolutePath = resolve(outDir, entry.importPath);\n const fileUrl = pathToFileURL(absolutePath).href;\n\n let module: unknown;\n try {\n module = await import(fileUrl);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Failed to import ${kind} factory '${entry.type}' (${entry.importPath}): ${message}`\n );\n }\n\n if (!module || typeof module !== 'object') {\n throw new Error(\n `Invalid ${kind} factory '${entry.type}' (${entry.importPath}): expected an object module export`\n );\n }\n\n const factory = (module as Record<string, unknown>).factory;\n if (!factory || typeof factory !== 'object') {\n throw new Error(\n `Invalid ${kind} factory '${entry.type}' (${entry.importPath}): missing 'factory' export`\n );\n }\n\n const configSchema = (factory as Record<string, unknown>).configSchema;\n const create = (factory as Record<string, unknown>).create;\n\n const parse = (configSchema as { parse?: unknown } | null | undefined)?.parse;\n if (!configSchema || typeof configSchema !== 'object' || typeof parse !== 'function') {\n throw new Error(\n `Invalid ${kind} factory '${entry.type}' (${entry.importPath}): factory.configSchema must be a Zod schema`\n );\n }\n\n if (typeof create !== 'function') {\n throw new Error(\n `Invalid ${kind} factory '${entry.type}' (${entry.importPath}): factory.create must be a function`\n );\n }\n}\n\nasync function validateDiscoveredFactories(\n outDir: string,\n discovered: DiscoveredFactories\n): Promise<void> {\n const validations: Array<Promise<void>> = [];\n\n for (const entry of discovered.tools) {\n validations.push(validateFactoryExport({ outDir, kind: 'tool', entry }));\n }\n for (const entry of discovered.hooks) {\n validations.push(validateFactoryExport({ outDir, kind: 'hook', entry }));\n }\n for (const entry of discovered.compaction) {\n validations.push(validateFactoryExport({ outDir, kind: 'compaction', entry }));\n }\n await Promise.all(validations);\n}\n","import type { ImageDefinition } from './types.js';\n\n/**\n * Validate an image definition.\n * Throws if the definition is invalid.\n *\n * Used by bundler to validate images before building.\n */\nexport function validateImageDefinition(definition: ImageDefinition): void {\n // Basic validation\n if (!definition.name || typeof definition.name !== 'string') {\n throw new Error('Image name must be a non-empty string');\n }\n\n if (!definition.version || typeof definition.version !== 'string') {\n throw new Error('Image version must be a non-empty string');\n }\n\n if (!definition.description || typeof definition.description !== 'string') {\n throw new Error('Image description must be a non-empty string');\n }\n\n // Validate version format (basic semver check)\n const versionRegex = /^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?$/;\n if (!versionRegex.test(definition.version)) {\n throw new Error(\n `Image version '${definition.version}' is not valid semver. Expected format: x.y.z`\n );\n }\n\n // Validate target if provided\n if (definition.target !== undefined) {\n if (typeof definition.target !== 'string' || definition.target.trim().length === 0) {\n throw new Error(`Image target must be a non-empty string when provided`);\n }\n }\n\n if (definition.constraints) {\n if (!Array.isArray(definition.constraints)) {\n throw new Error('Image constraints must be an array');\n }\n\n for (const constraint of definition.constraints) {\n if (typeof constraint !== 'string' || constraint.trim().length === 0) {\n throw new Error(`Image constraint must be a non-empty string`);\n }\n }\n }\n\n // Validate utils if provided\n if (definition.utils) {\n for (const [name, path] of Object.entries(definition.utils)) {\n if (typeof path !== 'string') {\n throw new Error(`Utility '${name}' path must be a string`);\n }\n if (!path.startsWith('./')) {\n throw new Error(\n `Utility '${name}' path must be relative (start with './'). Got: ${path}`\n );\n }\n }\n }\n\n // Validate extends if provided\n if (definition.extends) {\n if (typeof definition.extends !== 'string') {\n throw new Error('Image extends must be a string (parent image name)');\n }\n }\n}\n","/**\n * Code generator for images\n *\n * Transforms image definitions + convention folders into importable packages with:\n * - A typed `DextoImage` default export (no side effects)\n * - Optional utility re-exports\n */\n\nimport type { ImageDefinition } from './image-definition/types.js';\nimport type { GeneratedCode } from './types.js';\nimport type { DiscoveredFactories } from './bundler.js';\n\n/**\n * Generate JavaScript entry point for an image\n */\nexport function generateEntryPoint(\n definition: ImageDefinition,\n discoveredFactories: DiscoveredFactories\n): GeneratedCode {\n const imports = generateImports(definition, discoveredFactories);\n const helpers = definition.extends ? generateHelpers() : '';\n const imageModule = generateImageModule(definition, discoveredFactories);\n const utilityExports = generateUtilityExports(definition);\n\n const js = `// AUTO-GENERATED by @dexto/image-bundler\n// Do not edit this file directly. Edit dexto.image.ts instead.\n\n${imports}\n\n${helpers}\n\n${imageModule}\n\n${utilityExports}\n`;\n\n // Generate TypeScript definitions\n const dts = generateTypeDefinitions(definition);\n\n return { js, dts };\n}\n\nfunction sanitizeIdentifier(value: string): string {\n const sanitized = value.replace(/[^a-zA-Z0-9_$]/g, '_');\n if (/^[a-zA-Z_$]/.test(sanitized)) {\n return sanitized;\n }\n return `_${sanitized}`;\n}\n\nfunction toFactoryImportSymbol(prefix: string, type: string): string {\n return sanitizeIdentifier(`${prefix}_${type}`);\n}\n\nfunction generateImports(\n definition: ImageDefinition,\n discoveredFactories: DiscoveredFactories\n): string {\n const imports: string[] = [];\n\n if (definition.extends) {\n imports.push(`import baseImage from '${definition.extends}';`);\n }\n\n imports.push(`import { defaultLoggerFactory } from '@dexto/core';`);\n\n const toolProviders = [...discoveredFactories.tools].sort((a, b) =>\n a.type.localeCompare(b.type)\n );\n const hookProviders = [...discoveredFactories.hooks].sort((a, b) =>\n a.type.localeCompare(b.type)\n );\n const compactionProviders = [...discoveredFactories.compaction].sort((a, b) =>\n a.type.localeCompare(b.type)\n );\n if (toolProviders.length > 0 || hookProviders.length > 0 || compactionProviders.length > 0) {\n imports.push('');\n imports.push('// Factories (convention folders; each must `export const factory = ...`)');\n }\n\n for (const entry of toolProviders) {\n const symbol = toFactoryImportSymbol('tools', entry.type);\n imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);\n }\n for (const entry of hookProviders) {\n const symbol = toFactoryImportSymbol('hooks', entry.type);\n imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);\n }\n for (const entry of compactionProviders) {\n const symbol = toFactoryImportSymbol('compaction', entry.type);\n imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);\n }\n return imports.join('\\n');\n}\n\nfunction generateHelpers(): string {\n return `function isPlainObject(value) {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction mergeImageDefaults(baseDefaults, overrideDefaults) {\n if (!baseDefaults) return overrideDefaults;\n if (!overrideDefaults) return baseDefaults;\n\n const merged = { ...baseDefaults, ...overrideDefaults };\n for (const [key, baseValue] of Object.entries(baseDefaults)) {\n const overrideValue = overrideDefaults[key];\n if (!isPlainObject(baseValue) || !isPlainObject(overrideValue)) {\n continue;\n }\n merged[key] = {\n ...baseValue,\n ...overrideValue,\n };\n }\n return merged;\n}`;\n}\n\nfunction generateUtilityExports(definition: ImageDefinition): string {\n const sections: string[] = [];\n\n // Generate wildcard utility exports\n if (definition.utils && Object.keys(definition.utils).length > 0) {\n sections.push('// Utility exports');\n for (const [name, path] of Object.entries(definition.utils)) {\n sections.push(`export * from '${path}';`);\n }\n }\n\n // Generate selective named exports (filter out type-only exports for runtime JS)\n if (definition.exports && Object.keys(definition.exports).length > 0) {\n if (sections.length > 0) sections.push('');\n sections.push('// Selective package re-exports');\n for (const [packageName, exports] of Object.entries(definition.exports)) {\n // Check for wildcard re-export\n if (exports.length === 1 && exports[0] === '*') {\n sections.push(`export * from '${packageName}';`);\n continue;\n }\n\n // Filter out type-only exports (those starting with 'type ')\n const runtimeExports = exports.filter((exp) => !exp.startsWith('type '));\n if (runtimeExports.length > 0) {\n sections.push(`export {`);\n sections.push(` ${runtimeExports.join(',\\n ')}`);\n sections.push(`} from '${packageName}';`);\n }\n }\n }\n\n if (sections.length === 0) {\n return '// No utilities or exports defined for this image';\n }\n\n return sections.join('\\n');\n}\n\nfunction generateImageModule(\n definition: ImageDefinition,\n discoveredFactories: DiscoveredFactories\n): string {\n const derivedDefaults =\n definition.defaults !== undefined\n ? JSON.stringify(definition.defaults, null, 4)\n : 'undefined';\n\n const toolsEntries = discoveredFactories.tools\n .slice()\n .sort((a, b) => a.type.localeCompare(b.type))\n .map((entry) => {\n const symbol = toFactoryImportSymbol('tools', entry.type);\n return ` ${JSON.stringify(entry.type)}: ${symbol},`;\n });\n\n const hookEntries = discoveredFactories.hooks\n .slice()\n .sort((a, b) => a.type.localeCompare(b.type))\n .map((entry) => {\n const symbol = toFactoryImportSymbol('hooks', entry.type);\n return ` ${JSON.stringify(entry.type)}: ${symbol},`;\n });\n\n const compactionEntries = discoveredFactories.compaction\n .slice()\n .sort((a, b) => a.type.localeCompare(b.type))\n .map((entry) => {\n const symbol = toFactoryImportSymbol('compaction', entry.type);\n return ` ${JSON.stringify(entry.type)}: ${symbol},`;\n });\n\n const metadataLines: string[] = [];\n metadataLines.push(` name: ${JSON.stringify(definition.name)},`);\n metadataLines.push(` version: ${JSON.stringify(definition.version)},`);\n metadataLines.push(` description: ${JSON.stringify(definition.description)},`);\n\n if (definition.target !== undefined) {\n metadataLines.push(` target: ${JSON.stringify(definition.target)},`);\n } else if (definition.extends) {\n metadataLines.push(` target: baseImage.metadata.target,`);\n }\n\n if (definition.extends) {\n const derivedConstraints = JSON.stringify(definition.constraints ?? []);\n metadataLines.push(\n ` constraints: Array.from(new Set([...(baseImage.metadata.constraints ?? []), ...${derivedConstraints}])),`\n );\n } else if (definition.constraints !== undefined) {\n metadataLines.push(` constraints: ${JSON.stringify(definition.constraints)},`);\n }\n\n const defaultsExpression = definition.extends\n ? `mergeImageDefaults(baseImage.defaults, ${derivedDefaults})`\n : derivedDefaults;\n\n const toolsSpread = definition.extends ? ` ...baseImage.tools,\\n` : '';\n const hooksSpread = definition.extends ? ` ...baseImage.hooks,\\n` : '';\n const compactionSpread = definition.extends ? ` ...baseImage.compaction,\\n` : '';\n\n const storageExpression = definition.extends\n ? `baseImage.storage`\n : `{\n configSchema: { parse: (config) => config },\n createStores: () => {\n throw new Error('This generated image does not define storage. Extend an image with storage or provide a storage implementation.');\n },\n }`;\n\n const loggerExpression = definition.extends\n ? `baseImage.logger ?? defaultLoggerFactory`\n : `defaultLoggerFactory`;\n\n return `const image = {\n metadata: {\n${metadataLines.join('\\n')}\n },\n defaults: ${defaultsExpression},\n tools: {\n${toolsSpread}${toolsEntries.join('\\n')}\n },\n storage: ${storageExpression},\n hooks: {\n${hooksSpread}${hookEntries.join('\\n')}\n },\n compaction: {\n${compactionSpread}${compactionEntries.join('\\n')}\n },\n logger: ${loggerExpression},\n};\n\nexport default image;`;\n}\n\nfunction generateTypeDefinitions(definition: ImageDefinition): string {\n const sections: string[] = [];\n\n // Wildcard utility exports\n if (definition.utils && Object.keys(definition.utils).length > 0) {\n sections.push('// Utility re-exports');\n for (const path of Object.values(definition.utils)) {\n sections.push(`export * from '${path}';`);\n }\n }\n\n // Selective named exports\n if (definition.exports && Object.keys(definition.exports).length > 0) {\n if (sections.length > 0) sections.push('');\n sections.push('// Selective package re-exports');\n for (const [packageName, exports] of Object.entries(definition.exports)) {\n // Check for wildcard re-export\n if (exports.length === 1 && exports[0] === '*') {\n sections.push(`export * from '${packageName}';`);\n continue;\n }\n\n sections.push(`export {`);\n sections.push(` ${exports.join(',\\n ')}`);\n sections.push(`} from '${packageName}';`);\n }\n }\n\n const utilityExports = sections.length > 0 ? '\\n\\n' + sections.join('\\n') : '';\n\n return `// AUTO-GENERATED TypeScript definitions\n// Do not edit this file directly\n\n\timport type { DextoImage } from '@dexto/agent-config';\n\n\t/**\n\t * Typed image module (no side effects)\n\t */\n\t\tdeclare const image: DextoImage;\n\t\texport default image;\n${utilityExports}\n\t`;\n}\n"],"mappings":"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","names":["require"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dexto/image-bundler",
3
- "version": "1.7.1",
3
+ "version": "1.8.0",
4
4
  "description": "Bundler for Dexto base images",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,8 +18,8 @@
18
18
  "commander": "^12.0.0",
19
19
  "esbuild": "^0.27.0",
20
20
  "picocolors": "^1.0.0",
21
- "@dexto/agent-config": "1.7.1",
22
- "@dexto/core": "1.7.1"
21
+ "@dexto/agent-config": "1.8.0",
22
+ "@dexto/core": "1.8.0"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/node": "^20.11.5",
package/src/bundler.ts CHANGED
@@ -79,27 +79,6 @@ export async function bundle(options: BundleOptions): Promise<BundleResult> {
79
79
  compiledCount++;
80
80
  }
81
81
 
82
- // storage/blob/
83
- const storageBlobDir = join(imageDir, 'storage', 'blob');
84
- if (existsSync(storageBlobDir)) {
85
- compileSourceFiles(storageBlobDir, join(outDir, 'storage', 'blob'));
86
- compiledCount++;
87
- }
88
-
89
- // storage/database/
90
- const storageDatabaseDir = join(imageDir, 'storage', 'database');
91
- if (existsSync(storageDatabaseDir)) {
92
- compileSourceFiles(storageDatabaseDir, join(outDir, 'storage', 'database'));
93
- compiledCount++;
94
- }
95
-
96
- // storage/cache/
97
- const storageCacheDir = join(imageDir, 'storage', 'cache');
98
- if (existsSync(storageCacheDir)) {
99
- compileSourceFiles(storageCacheDir, join(outDir, 'storage', 'cache'));
100
- compiledCount++;
101
- }
102
-
103
82
  if (compiledCount > 0) {
104
83
  console.log(
105
84
  `✅ Compiled ${compiledCount} factory categor${compiledCount === 1 ? 'y' : 'ies'}`
@@ -335,11 +314,6 @@ export interface DiscoveredFactory {
335
314
 
336
315
  export interface DiscoveredFactories {
337
316
  tools: DiscoveredFactory[];
338
- storage: {
339
- blob: DiscoveredFactory[];
340
- database: DiscoveredFactory[];
341
- cache: DiscoveredFactory[];
342
- };
343
317
  hooks: DiscoveredFactory[];
344
318
  compaction: DiscoveredFactory[];
345
319
  totalCount: number;
@@ -356,9 +330,7 @@ export interface DiscoveredFactories {
356
330
  * types.ts - Optional type definitions
357
331
  * compaction/ - CompactionFactory folders
358
332
  * hooks/ - HookFactory folders
359
- * storage/blob/ - BlobStoreFactory folders
360
- * storage/cache/ - CacheFactory folders
361
- * storage/database/ - DatabaseFactory folders
333
+ * storage is an image-level createStores implementation, not convention-discovered
362
334
  *
363
335
  * Naming Convention (Node.js standard):
364
336
  * <folder>/index.ts - Auto-discovered and registered
@@ -367,11 +339,6 @@ export interface DiscoveredFactories {
367
339
  function discoverFactories(imageDir: string, warnings: string[]): DiscoveredFactories {
368
340
  const result: DiscoveredFactories = {
369
341
  tools: [],
370
- storage: {
371
- blob: [],
372
- database: [],
373
- cache: [],
374
- },
375
342
  hooks: [],
376
343
  compaction: [],
377
344
  totalCount: 0,
@@ -430,38 +397,11 @@ function discoverFactories(imageDir: string, warnings: string[]): DiscoveredFact
430
397
  label: 'compaction/',
431
398
  });
432
399
 
433
- // storage/blob/
434
- result.storage.blob = discoverFolder({
435
- srcDir: join(imageDir, 'storage', 'blob'),
436
- importBase: 'storage/blob',
437
- label: 'storage/blob/',
438
- });
439
-
440
- // storage/database/
441
- result.storage.database = discoverFolder({
442
- srcDir: join(imageDir, 'storage', 'database'),
443
- importBase: 'storage/database',
444
- label: 'storage/database/',
445
- });
446
-
447
- // storage/cache/
448
- result.storage.cache = discoverFolder({
449
- srcDir: join(imageDir, 'storage', 'cache'),
450
- importBase: 'storage/cache',
451
- label: 'storage/cache/',
452
- });
453
-
454
- result.totalCount =
455
- result.tools.length +
456
- result.hooks.length +
457
- result.compaction.length +
458
- result.storage.blob.length +
459
- result.storage.database.length +
460
- result.storage.cache.length;
400
+ result.totalCount = result.tools.length + result.hooks.length + result.compaction.length;
461
401
 
462
402
  if (result.totalCount === 0) {
463
403
  warnings.push(
464
- 'No factories discovered from convention folders. This image will not be able to resolve tools/storage unless it extends a base image.'
404
+ 'No factories discovered from convention folders. This image will not be able to resolve tools/hooks/compaction unless it extends a base image.'
465
405
  );
466
406
  }
467
407
 
@@ -533,15 +473,5 @@ async function validateDiscoveredFactories(
533
473
  for (const entry of discovered.compaction) {
534
474
  validations.push(validateFactoryExport({ outDir, kind: 'compaction', entry }));
535
475
  }
536
- for (const entry of discovered.storage.blob) {
537
- validations.push(validateFactoryExport({ outDir, kind: 'storage.blob', entry }));
538
- }
539
- for (const entry of discovered.storage.database) {
540
- validations.push(validateFactoryExport({ outDir, kind: 'storage.database', entry }));
541
- }
542
- for (const entry of discovered.storage.cache) {
543
- validations.push(validateFactoryExport({ outDir, kind: 'storage.cache', entry }));
544
- }
545
-
546
476
  await Promise.all(validations);
547
477
  }
package/src/generator.ts CHANGED
@@ -73,24 +73,7 @@ function generateImports(
73
73
  const compactionProviders = [...discoveredFactories.compaction].sort((a, b) =>
74
74
  a.type.localeCompare(b.type)
75
75
  );
76
- const blobProviders = [...discoveredFactories.storage.blob].sort((a, b) =>
77
- a.type.localeCompare(b.type)
78
- );
79
- const databaseProviders = [...discoveredFactories.storage.database].sort((a, b) =>
80
- a.type.localeCompare(b.type)
81
- );
82
- const cacheProviders = [...discoveredFactories.storage.cache].sort((a, b) =>
83
- a.type.localeCompare(b.type)
84
- );
85
-
86
- if (
87
- toolProviders.length > 0 ||
88
- hookProviders.length > 0 ||
89
- compactionProviders.length > 0 ||
90
- blobProviders.length > 0 ||
91
- databaseProviders.length > 0 ||
92
- cacheProviders.length > 0
93
- ) {
76
+ if (toolProviders.length > 0 || hookProviders.length > 0 || compactionProviders.length > 0) {
94
77
  imports.push('');
95
78
  imports.push('// Factories (convention folders; each must `export const factory = ...`)');
96
79
  }
@@ -107,19 +90,6 @@ function generateImports(
107
90
  const symbol = toFactoryImportSymbol('compaction', entry.type);
108
91
  imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);
109
92
  }
110
- for (const entry of blobProviders) {
111
- const symbol = toFactoryImportSymbol('storage_blob', entry.type);
112
- imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);
113
- }
114
- for (const entry of databaseProviders) {
115
- const symbol = toFactoryImportSymbol('storage_database', entry.type);
116
- imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);
117
- }
118
- for (const entry of cacheProviders) {
119
- const symbol = toFactoryImportSymbol('storage_cache', entry.type);
120
- imports.push(`import { factory as ${symbol} } from '${entry.importPath}';`);
121
- }
122
-
123
93
  return imports.join('\n');
124
94
  }
125
95
 
@@ -219,30 +189,6 @@ function generateImageModule(
219
189
  return ` ${JSON.stringify(entry.type)}: ${symbol},`;
220
190
  });
221
191
 
222
- const blobEntries = discoveredFactories.storage.blob
223
- .slice()
224
- .sort((a, b) => a.type.localeCompare(b.type))
225
- .map((entry) => {
226
- const symbol = toFactoryImportSymbol('storage_blob', entry.type);
227
- return ` ${JSON.stringify(entry.type)}: ${symbol},`;
228
- });
229
-
230
- const databaseEntries = discoveredFactories.storage.database
231
- .slice()
232
- .sort((a, b) => a.type.localeCompare(b.type))
233
- .map((entry) => {
234
- const symbol = toFactoryImportSymbol('storage_database', entry.type);
235
- return ` ${JSON.stringify(entry.type)}: ${symbol},`;
236
- });
237
-
238
- const cacheEntries = discoveredFactories.storage.cache
239
- .slice()
240
- .sort((a, b) => a.type.localeCompare(b.type))
241
- .map((entry) => {
242
- const symbol = toFactoryImportSymbol('storage_cache', entry.type);
243
- return ` ${JSON.stringify(entry.type)}: ${symbol},`;
244
- });
245
-
246
192
  const metadataLines: string[] = [];
247
193
  metadataLines.push(` name: ${JSON.stringify(definition.name)},`);
248
194
  metadataLines.push(` version: ${JSON.stringify(definition.version)},`);
@@ -271,9 +217,14 @@ function generateImageModule(
271
217
  const hooksSpread = definition.extends ? ` ...baseImage.hooks,\n` : '';
272
218
  const compactionSpread = definition.extends ? ` ...baseImage.compaction,\n` : '';
273
219
 
274
- const blobSpread = definition.extends ? ` ...baseImage.storage.blob,\n` : '';
275
- const databaseSpread = definition.extends ? ` ...baseImage.storage.database,\n` : '';
276
- const cacheSpread = definition.extends ? ` ...baseImage.storage.cache,\n` : '';
220
+ const storageExpression = definition.extends
221
+ ? `baseImage.storage`
222
+ : `{
223
+ configSchema: { parse: (config) => config },
224
+ createStores: () => {
225
+ throw new Error('This generated image does not define storage. Extend an image with storage or provide a storage implementation.');
226
+ },
227
+ }`;
277
228
 
278
229
  const loggerExpression = definition.extends
279
230
  ? `baseImage.logger ?? defaultLoggerFactory`
@@ -287,17 +238,7 @@ ${metadataLines.join('\n')}
287
238
  tools: {
288
239
  ${toolsSpread}${toolsEntries.join('\n')}
289
240
  },
290
- storage: {
291
- blob: {
292
- ${blobSpread}${blobEntries.join('\n')}
293
- },
294
- database: {
295
- ${databaseSpread}${databaseEntries.join('\n')}
296
- },
297
- cache: {
298
- ${cacheSpread}${cacheEntries.join('\n')}
299
- },
300
- },
241
+ storage: ${storageExpression},
301
242
  hooks: {
302
243
  ${hooksSpread}${hookEntries.join('\n')}
303
244
  },