@dexto/image-bundler 1.5.8 → 1.6.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 +52 -0
- package/README.md +45 -0
- package/dist/cli.js +411 -221
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +66 -2
- package/dist/index.js +407 -210
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/bundler.ts +278 -92
- package/src/cli.ts +4 -12
- package/src/generator.ts +223 -204
- package/src/image-definition/types.ts +72 -0
- package/src/image-definition/validate-image-definition.ts +70 -0
- package/src/index.ts +2 -1
- package/src/types.ts +1 -1
- package/test/bundle.integration.test.ts +253 -0
- package/tsconfig.json +5 -1
- package/tsup.config.ts +6 -1
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { bundle } from '../src/index.js';
|
|
3
|
+
import { loadImage } from '@dexto/agent-config';
|
|
4
|
+
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
|
|
8
|
+
async function writeFileEnsuringDir(filePath: string, contents: string): Promise<void> {
|
|
9
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
10
|
+
await writeFile(filePath, contents, 'utf-8');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe('@dexto/image-bundler - bundle (integration)', () => {
|
|
14
|
+
it('bundles a convention-based image into a loadable DextoImage', async () => {
|
|
15
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
|
16
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined);
|
|
17
|
+
|
|
18
|
+
const tempDir = await mkdtemp(
|
|
19
|
+
path.join(process.cwd(), 'packages/image-bundler', '.tmp-bundle-test-')
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
await writeFileEnsuringDir(
|
|
24
|
+
path.join(tempDir, 'package.json'),
|
|
25
|
+
JSON.stringify(
|
|
26
|
+
{
|
|
27
|
+
name: '@dexto/test-image',
|
|
28
|
+
version: '1.0.0',
|
|
29
|
+
type: 'module',
|
|
30
|
+
},
|
|
31
|
+
null,
|
|
32
|
+
2
|
|
33
|
+
)
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
await writeFileEnsuringDir(
|
|
37
|
+
path.join(tempDir, 'dexto.image.ts'),
|
|
38
|
+
`import type { ImageDefinition } from '@dexto/image-bundler';
|
|
39
|
+
|
|
40
|
+
const image = {
|
|
41
|
+
name: 'test-image',
|
|
42
|
+
version: '1.0.0',
|
|
43
|
+
description: 'Test image for bundler integration',
|
|
44
|
+
target: 'local-development',
|
|
45
|
+
constraints: ['offline-capable'],
|
|
46
|
+
} satisfies ImageDefinition;
|
|
47
|
+
|
|
48
|
+
export default image;
|
|
49
|
+
`
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
await writeFileEnsuringDir(
|
|
53
|
+
path.join(tempDir, 'tools', 'example-tool', 'index.ts'),
|
|
54
|
+
`const configSchema = {
|
|
55
|
+
parse: (value: unknown) => value,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const inputSchema = {
|
|
59
|
+
parse: (value: unknown) => value,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const factory = {
|
|
63
|
+
configSchema,
|
|
64
|
+
create: (_config: unknown) => {
|
|
65
|
+
const tool = {
|
|
66
|
+
id: 'example-tool',
|
|
67
|
+
description: 'Example tool from bundler integration test',
|
|
68
|
+
inputSchema,
|
|
69
|
+
execute: async (_input: unknown) => {
|
|
70
|
+
return { ok: true };
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return [tool];
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
`
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const distDir = path.join(tempDir, 'dist');
|
|
81
|
+
const result = await bundle({
|
|
82
|
+
imagePath: path.join(tempDir, 'dexto.image.ts'),
|
|
83
|
+
outDir: distDir,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
expect(result.entryFile).toBe(path.join(distDir, 'index.js'));
|
|
87
|
+
expect(result.typesFile).toBe(path.join(distDir, 'index.d.ts'));
|
|
88
|
+
|
|
89
|
+
const image = await loadImage(pathToFileURL(result.entryFile).href);
|
|
90
|
+
expect(image.metadata.name).toBe('test-image');
|
|
91
|
+
expect(image.tools['example-tool']).toBeDefined();
|
|
92
|
+
} finally {
|
|
93
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
94
|
+
logSpy.mockRestore();
|
|
95
|
+
warnSpy.mockRestore();
|
|
96
|
+
}
|
|
97
|
+
}, 20000);
|
|
98
|
+
|
|
99
|
+
it('bundles an image with tools/storage/hooks/compaction factories', async () => {
|
|
100
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
|
101
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined);
|
|
102
|
+
|
|
103
|
+
const tempDir = await mkdtemp(
|
|
104
|
+
path.join(process.cwd(), 'packages/image-bundler', '.tmp-bundle-test-')
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
await writeFileEnsuringDir(
|
|
109
|
+
path.join(tempDir, 'package.json'),
|
|
110
|
+
JSON.stringify(
|
|
111
|
+
{
|
|
112
|
+
name: '@dexto/test-image-full',
|
|
113
|
+
version: '1.0.0',
|
|
114
|
+
type: 'module',
|
|
115
|
+
},
|
|
116
|
+
null,
|
|
117
|
+
2
|
|
118
|
+
)
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
await writeFileEnsuringDir(
|
|
122
|
+
path.join(tempDir, 'dexto.image.ts'),
|
|
123
|
+
`import type { ImageDefinition } from '@dexto/image-bundler';
|
|
124
|
+
|
|
125
|
+
const image = {
|
|
126
|
+
name: 'test-image-full',
|
|
127
|
+
version: '1.0.0',
|
|
128
|
+
description: 'Test image with tools/storage/hooks/compaction factories',
|
|
129
|
+
target: 'local-development',
|
|
130
|
+
} satisfies ImageDefinition;
|
|
131
|
+
|
|
132
|
+
export default image;
|
|
133
|
+
`
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
await writeFileEnsuringDir(
|
|
137
|
+
path.join(tempDir, 'tools', 'sample-tools', 'index.ts'),
|
|
138
|
+
`const configSchema = {
|
|
139
|
+
parse: (value: unknown) => value,
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const inputSchema = {
|
|
143
|
+
parse: (value: unknown) => value,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export const factory = {
|
|
147
|
+
configSchema,
|
|
148
|
+
create: (_config: unknown) => {
|
|
149
|
+
return [
|
|
150
|
+
{
|
|
151
|
+
id: 'sample-echo',
|
|
152
|
+
description: 'Echo tool (bundler integration test)',
|
|
153
|
+
inputSchema,
|
|
154
|
+
execute: async (input: unknown) => input,
|
|
155
|
+
},
|
|
156
|
+
];
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
`
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
await writeFileEnsuringDir(
|
|
163
|
+
path.join(tempDir, 'hooks', 'sample-hook', 'index.ts'),
|
|
164
|
+
`const configSchema = {
|
|
165
|
+
parse: (value: unknown) => value,
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export const factory = {
|
|
169
|
+
configSchema,
|
|
170
|
+
create: (_config: unknown) => {
|
|
171
|
+
return {
|
|
172
|
+
beforeResponse: async () => ({ ok: true }),
|
|
173
|
+
};
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
`
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
await writeFileEnsuringDir(
|
|
180
|
+
path.join(tempDir, 'compaction', 'noop', 'index.ts'),
|
|
181
|
+
`const configSchema = {
|
|
182
|
+
parse: (value: unknown) => value,
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export const factory = {
|
|
186
|
+
configSchema,
|
|
187
|
+
create: (_config: unknown) => ({}),
|
|
188
|
+
};
|
|
189
|
+
`
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
await writeFileEnsuringDir(
|
|
193
|
+
path.join(tempDir, 'storage', 'blob', 'in-memory', 'index.ts'),
|
|
194
|
+
`const configSchema = {
|
|
195
|
+
parse: (value: unknown) => value,
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
export const factory = {
|
|
199
|
+
configSchema,
|
|
200
|
+
create: (_config: unknown, _logger: unknown) => ({}),
|
|
201
|
+
};
|
|
202
|
+
`
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
await writeFileEnsuringDir(
|
|
206
|
+
path.join(tempDir, 'storage', 'database', 'in-memory', 'index.ts'),
|
|
207
|
+
`const configSchema = {
|
|
208
|
+
parse: (value: unknown) => value,
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
export const factory = {
|
|
212
|
+
configSchema,
|
|
213
|
+
create: (_config: unknown, _logger: unknown) => ({}),
|
|
214
|
+
};
|
|
215
|
+
`
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
await writeFileEnsuringDir(
|
|
219
|
+
path.join(tempDir, 'storage', 'cache', 'in-memory', 'index.ts'),
|
|
220
|
+
`const configSchema = {
|
|
221
|
+
parse: (value: unknown) => value,
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export const factory = {
|
|
225
|
+
configSchema,
|
|
226
|
+
create: (_config: unknown, _logger: unknown) => ({}),
|
|
227
|
+
};
|
|
228
|
+
`
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
const distDir = path.join(tempDir, 'dist');
|
|
232
|
+
const result = await bundle({
|
|
233
|
+
imagePath: path.join(tempDir, 'dexto.image.ts'),
|
|
234
|
+
outDir: distDir,
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const image = await loadImage(pathToFileURL(result.entryFile).href);
|
|
238
|
+
expect(image.metadata.name).toBe('test-image-full');
|
|
239
|
+
|
|
240
|
+
expect(image.tools['sample-tools']).toBeDefined();
|
|
241
|
+
expect(image.hooks['sample-hook']).toBeDefined();
|
|
242
|
+
expect(image.compaction['noop']).toBeDefined();
|
|
243
|
+
|
|
244
|
+
expect(image.storage.blob['in-memory']).toBeDefined();
|
|
245
|
+
expect(image.storage.database['in-memory']).toBeDefined();
|
|
246
|
+
expect(image.storage.cache['in-memory']).toBeDefined();
|
|
247
|
+
} finally {
|
|
248
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
249
|
+
logSpy.mockRestore();
|
|
250
|
+
warnSpy.mockRestore();
|
|
251
|
+
}
|
|
252
|
+
}, 60000);
|
|
253
|
+
});
|
package/tsconfig.json
CHANGED
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
"rootDir": "./src",
|
|
9
9
|
"strict": true,
|
|
10
10
|
"esModuleInterop": true,
|
|
11
|
+
"composite": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
11
14
|
"skipLibCheck": true,
|
|
12
15
|
"forceConsistentCasingInFileNames": true,
|
|
13
16
|
"resolveJsonModule": true,
|
|
@@ -15,5 +18,6 @@
|
|
|
15
18
|
"noEmit": true
|
|
16
19
|
},
|
|
17
20
|
"include": ["src/**/*.ts"],
|
|
18
|
-
"exclude": ["node_modules", "dist"]
|
|
21
|
+
"exclude": ["node_modules", "dist"],
|
|
22
|
+
"references": [{ "path": "../agent-config" }, { "path": "../core" }]
|
|
19
23
|
}
|
package/tsup.config.ts
CHANGED
|
@@ -3,7 +3,12 @@ import { defineConfig } from 'tsup';
|
|
|
3
3
|
export default defineConfig({
|
|
4
4
|
entry: ['src/index.ts', 'src/cli.ts'],
|
|
5
5
|
format: ['esm'],
|
|
6
|
-
dts:
|
|
6
|
+
dts: {
|
|
7
|
+
compilerOptions: {
|
|
8
|
+
skipLibCheck: true,
|
|
9
|
+
composite: false,
|
|
10
|
+
},
|
|
11
|
+
},
|
|
7
12
|
clean: true,
|
|
8
13
|
sourcemap: true,
|
|
9
14
|
splitting: false,
|