@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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +20 -0
- package/README.md +7 -5
- package/dist/cli.js +10 -97
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +10 -97
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/bundler.ts +3 -73
- package/src/generator.ts +10 -69
- package/src/image-definition/types.ts +2 -1
- package/test/bundle.integration.test.ts +4 -44
- package/tsconfig.tsbuildinfo +1 -1
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
|
-
|
|
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
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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.
|
|
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/
|
|
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.
|
|
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.
|
|
22
|
-
"@dexto/core": "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
|
|
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
|
-
|
|
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/
|
|
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
|
-
|
|
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
|
|
275
|
-
|
|
276
|
-
|
|
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
|
},
|