@output.ai/cli 0.8.2 â 0.8.4
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/assets/docker/docker-compose-dev.yml +4 -17
- package/dist/commands/dev/index.d.ts +0 -1
- package/dist/commands/dev/index.js +2 -12
- package/dist/commands/dev/index.spec.js +11 -37
- package/dist/generated/framework_version.json +1 -1
- package/dist/services/docker.d.ts +1 -1
- package/dist/services/docker.js +1 -4
- package/dist/templates/project/package.json.template +1 -0
- package/package.json +2 -3
|
@@ -79,7 +79,7 @@ services:
|
|
|
79
79
|
depends_on:
|
|
80
80
|
temporal:
|
|
81
81
|
condition: service_healthy
|
|
82
|
-
image: growthxteam/output-api
|
|
82
|
+
image: growthxteam/output-api:${OUTPUT_API_VERSION:-1.9}
|
|
83
83
|
init: true
|
|
84
84
|
networks:
|
|
85
85
|
- main
|
|
@@ -117,30 +117,17 @@ services:
|
|
|
117
117
|
sh -c "
|
|
118
118
|
npm run output:worker:install &&
|
|
119
119
|
echo 'Installed dependencies' &&
|
|
120
|
-
npm run output:worker:build &&
|
|
121
|
-
echo 'Built worker' &&
|
|
122
|
-
npm run output:worker:start &&
|
|
123
|
-
echo 'Started worker'
|
|
120
|
+
npx nodemon --watch src --watch package.json --ext ts,js,json,prompt --ignore 'dist/**' --ignore '**/*.test.ts' --ignore '**/*.spec.ts' --exec 'npm run output:worker:install && npm run output:worker:build && npm run output:worker:start'
|
|
124
121
|
"
|
|
125
122
|
working_dir: /app
|
|
126
123
|
volumes:
|
|
127
124
|
- ./:/app
|
|
128
|
-
|
|
129
|
-
watch:
|
|
130
|
-
- path: ./src
|
|
131
|
-
target: /app/src
|
|
132
|
-
action: restart
|
|
133
|
-
ignore:
|
|
134
|
-
- node_modules/
|
|
135
|
-
- '**/*.test.ts'
|
|
136
|
-
- '**/*.spec.ts'
|
|
137
|
-
- path: ./package.json
|
|
138
|
-
target: /app/package.json
|
|
139
|
-
action: restart
|
|
125
|
+
- worker_node_modules:/app/node_modules
|
|
140
126
|
|
|
141
127
|
volumes:
|
|
142
128
|
postgres:
|
|
143
129
|
redis:
|
|
130
|
+
worker_node_modules:
|
|
144
131
|
|
|
145
132
|
networks:
|
|
146
133
|
main:
|
|
@@ -5,7 +5,6 @@ export default class Dev extends Command {
|
|
|
5
5
|
static args: {};
|
|
6
6
|
static flags: {
|
|
7
7
|
'compose-file': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
8
|
-
'no-watch': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
8
|
'image-pull-policy': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
9
|
};
|
|
11
10
|
private dockerProcess;
|
|
@@ -73,7 +73,6 @@ export default class Dev extends Command {
|
|
|
73
73
|
static description = 'Start Output development services (auto-restarts worker on file changes)';
|
|
74
74
|
static examples = [
|
|
75
75
|
'<%= config.bin %> <%= command.id %>',
|
|
76
|
-
'<%= config.bin %> <%= command.id %> --no-watch',
|
|
77
76
|
'<%= config.bin %> <%= command.id %> --compose-file ./custom-docker-compose.yml',
|
|
78
77
|
'<%= config.bin %> <%= command.id %> --image-pull-policy missing'
|
|
79
78
|
];
|
|
@@ -84,10 +83,6 @@ export default class Dev extends Command {
|
|
|
84
83
|
required: false,
|
|
85
84
|
char: 'f'
|
|
86
85
|
}),
|
|
87
|
-
'no-watch': Flags.boolean({
|
|
88
|
-
description: 'Disable automatic container restart on file changes',
|
|
89
|
-
default: false
|
|
90
|
-
}),
|
|
91
86
|
'image-pull-policy': Flags.string({
|
|
92
87
|
description: 'Image pull policy for docker compose (always, missing, never)',
|
|
93
88
|
options: ['always', 'missing', 'never'],
|
|
@@ -113,12 +108,7 @@ export default class Dev extends Command {
|
|
|
113
108
|
if (flags['compose-file']) {
|
|
114
109
|
this.log(`Using custom docker-compose file: ${flags['compose-file']}\n`);
|
|
115
110
|
}
|
|
116
|
-
|
|
117
|
-
this.log('đ File watching enabled - worker will restart automatically on changes\n');
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
this.log('âšī¸ File watching disabled (--no-watch flag used)\n');
|
|
121
|
-
}
|
|
111
|
+
this.log('File watching enabled - worker will restart automatically on changes\n');
|
|
122
112
|
const cleanup = async () => {
|
|
123
113
|
this.log('\n');
|
|
124
114
|
if (this.dockerProcess) {
|
|
@@ -131,7 +121,7 @@ export default class Dev extends Command {
|
|
|
131
121
|
process.on('SIGTERM', cleanup);
|
|
132
122
|
const pullPolicy = flags['image-pull-policy'];
|
|
133
123
|
try {
|
|
134
|
-
const { process: dockerProc, waitForHealthy } = await startDockerCompose(dockerComposePath,
|
|
124
|
+
const { process: dockerProc, waitForHealthy } = await startDockerCompose(dockerComposePath, pullPolicy);
|
|
135
125
|
this.dockerProcess = dockerProc;
|
|
136
126
|
dockerProc.on('error', error => {
|
|
137
127
|
this.error(`Docker process error: ${getErrorMessage(error)}`, { exit: 1 });
|
|
@@ -72,11 +72,6 @@ describe('dev command', () => {
|
|
|
72
72
|
expect(Dev.args).toBeDefined();
|
|
73
73
|
expect(Object.keys(Dev.args)).toHaveLength(0);
|
|
74
74
|
});
|
|
75
|
-
it('should have no-watch flag defined', () => {
|
|
76
|
-
expect(Dev.flags).toBeDefined();
|
|
77
|
-
expect(Dev.flags['no-watch']).toBeDefined();
|
|
78
|
-
expect(Dev.flags['no-watch'].description).toContain('Disable automatic container restart');
|
|
79
|
-
});
|
|
80
75
|
it('should have compose-file flag defined', () => {
|
|
81
76
|
expect(Dev.flags).toBeDefined();
|
|
82
77
|
expect(Dev.flags['compose-file']).toBeDefined();
|
|
@@ -110,7 +105,7 @@ describe('dev command', () => {
|
|
|
110
105
|
cmd.log = vi.fn();
|
|
111
106
|
// Mock parse to return flags
|
|
112
107
|
Object.defineProperty(cmd, 'parse', {
|
|
113
|
-
value: vi.fn().mockResolvedValue({ flags: { '
|
|
108
|
+
value: vi.fn().mockResolvedValue({ flags: { 'compose-file': undefined }, args: {} }),
|
|
114
109
|
configurable: true
|
|
115
110
|
});
|
|
116
111
|
const validationError = new Error('Docker is not installed');
|
|
@@ -140,7 +135,7 @@ describe('dev command', () => {
|
|
|
140
135
|
cmd.log = vi.fn();
|
|
141
136
|
cmd.error = vi.fn();
|
|
142
137
|
Object.defineProperty(cmd, 'parse', {
|
|
143
|
-
value: vi.fn().mockResolvedValue({ flags: { '
|
|
138
|
+
value: vi.fn().mockResolvedValue({ flags: { 'compose-file': undefined, 'image-pull-policy': 'always' }, args: {} }),
|
|
144
139
|
configurable: true
|
|
145
140
|
});
|
|
146
141
|
const runPromise = cmd.run();
|
|
@@ -154,7 +149,7 @@ describe('dev command', () => {
|
|
|
154
149
|
cmd.log = vi.fn();
|
|
155
150
|
cmd.error = vi.fn();
|
|
156
151
|
Object.defineProperty(cmd, 'parse', {
|
|
157
|
-
value: vi.fn().mockResolvedValue({ flags: { '
|
|
152
|
+
value: vi.fn().mockResolvedValue({ flags: { 'compose-file': undefined, 'image-pull-policy': 'always' }, args: {} }),
|
|
158
153
|
configurable: true
|
|
159
154
|
});
|
|
160
155
|
const runPromise = cmd.run();
|
|
@@ -165,46 +160,25 @@ describe('dev command', () => {
|
|
|
165
160
|
});
|
|
166
161
|
});
|
|
167
162
|
describe('watch functionality', () => {
|
|
168
|
-
it('should
|
|
163
|
+
it('should start docker compose', async () => {
|
|
169
164
|
const cmd = new Dev([], {});
|
|
170
165
|
cmd.log = vi.fn();
|
|
171
166
|
cmd.error = vi.fn();
|
|
172
167
|
// Mock parse to return flags
|
|
173
168
|
Object.defineProperty(cmd, 'parse', {
|
|
174
|
-
value: vi.fn().mockResolvedValue({ flags: { '
|
|
169
|
+
value: vi.fn().mockResolvedValue({ flags: { 'compose-file': undefined, 'image-pull-policy': 'always' }, args: {} }),
|
|
175
170
|
configurable: true
|
|
176
171
|
});
|
|
177
172
|
// Run the command but don't await it since it waits forever after startup
|
|
178
173
|
const runPromise = cmd.run();
|
|
179
174
|
// Wait a tick for startDockerCompose to be called
|
|
180
175
|
await new Promise(resolve => setImmediate(resolve));
|
|
181
|
-
expect(dockerService.startDockerCompose).toHaveBeenCalledWith('/path/to/docker-compose-dev.yml',
|
|
182
|
-
'always' // default pull policy
|
|
176
|
+
expect(dockerService.startDockerCompose).toHaveBeenCalledWith('/path/to/docker-compose-dev.yml', 'always' // default pull policy
|
|
183
177
|
);
|
|
184
178
|
expect(cmd.log).toHaveBeenCalledWith(expect.stringContaining('File watching enabled'));
|
|
185
179
|
// Cancel the promise (it will be rejected but we don't care)
|
|
186
180
|
runPromise.catch(() => { });
|
|
187
181
|
});
|
|
188
|
-
it('should disable watch with --no-watch flag', async () => {
|
|
189
|
-
const cmd = new Dev(['--no-watch'], {});
|
|
190
|
-
cmd.log = vi.fn();
|
|
191
|
-
cmd.error = vi.fn();
|
|
192
|
-
// Mock parse to return flags
|
|
193
|
-
Object.defineProperty(cmd, 'parse', {
|
|
194
|
-
value: vi.fn().mockResolvedValue({ flags: { 'no-watch': true, 'compose-file': undefined, 'image-pull-policy': 'always' }, args: {} }),
|
|
195
|
-
configurable: true
|
|
196
|
-
});
|
|
197
|
-
// Run the command but don't await it since it waits forever after startup
|
|
198
|
-
const runPromise = cmd.run();
|
|
199
|
-
// Wait a tick for startDockerCompose to be called
|
|
200
|
-
await new Promise(resolve => setImmediate(resolve));
|
|
201
|
-
expect(dockerService.startDockerCompose).toHaveBeenCalledWith('/path/to/docker-compose-dev.yml', false, // enableWatch should be false
|
|
202
|
-
'always' // default pull policy
|
|
203
|
-
);
|
|
204
|
-
expect(cmd.log).toHaveBeenCalledWith(expect.stringContaining('File watching disabled'));
|
|
205
|
-
// Cancel the promise (it will be rejected but we don't care)
|
|
206
|
-
runPromise.catch(() => { });
|
|
207
|
-
});
|
|
208
182
|
it('should handle docker compose configuration not found', async () => {
|
|
209
183
|
vi.mocked(fs).access.mockRejectedValue(new Error('File not found'));
|
|
210
184
|
const cmd = new Dev([], {});
|
|
@@ -219,7 +193,7 @@ describe('dev command', () => {
|
|
|
219
193
|
cmd.error = vi.fn();
|
|
220
194
|
// Mock parse to return flags
|
|
221
195
|
Object.defineProperty(cmd, 'parse', {
|
|
222
|
-
value: vi.fn().mockResolvedValue({ flags: { '
|
|
196
|
+
value: vi.fn().mockResolvedValue({ flags: { 'compose-file': undefined, 'image-pull-policy': 'always' }, args: {} }),
|
|
223
197
|
configurable: true
|
|
224
198
|
});
|
|
225
199
|
await cmd.run();
|
|
@@ -233,14 +207,14 @@ describe('dev command', () => {
|
|
|
233
207
|
cmd.error = vi.fn();
|
|
234
208
|
// Mock parse to return flags with missing pull policy
|
|
235
209
|
Object.defineProperty(cmd, 'parse', {
|
|
236
|
-
value: vi.fn().mockResolvedValue({ flags: { '
|
|
210
|
+
value: vi.fn().mockResolvedValue({ flags: { 'compose-file': undefined, 'image-pull-policy': 'missing' }, args: {} }),
|
|
237
211
|
configurable: true
|
|
238
212
|
});
|
|
239
213
|
// Run the command but don't await it since it waits forever after startup
|
|
240
214
|
const runPromise = cmd.run();
|
|
241
215
|
// Wait a tick for startDockerCompose to be called
|
|
242
216
|
await new Promise(resolve => setImmediate(resolve));
|
|
243
|
-
expect(dockerService.startDockerCompose).toHaveBeenCalledWith('/path/to/docker-compose-dev.yml',
|
|
217
|
+
expect(dockerService.startDockerCompose).toHaveBeenCalledWith('/path/to/docker-compose-dev.yml', 'missing');
|
|
244
218
|
// Cancel the promise (it will be rejected but we don't care)
|
|
245
219
|
runPromise.catch(() => { });
|
|
246
220
|
});
|
|
@@ -250,14 +224,14 @@ describe('dev command', () => {
|
|
|
250
224
|
cmd.error = vi.fn();
|
|
251
225
|
// Mock parse to return flags with never pull policy
|
|
252
226
|
Object.defineProperty(cmd, 'parse', {
|
|
253
|
-
value: vi.fn().mockResolvedValue({ flags: { '
|
|
227
|
+
value: vi.fn().mockResolvedValue({ flags: { 'compose-file': undefined, 'image-pull-policy': 'never' }, args: {} }),
|
|
254
228
|
configurable: true
|
|
255
229
|
});
|
|
256
230
|
// Run the command but don't await it since it waits forever after startup
|
|
257
231
|
const runPromise = cmd.run();
|
|
258
232
|
// Wait a tick for startDockerCompose to be called
|
|
259
233
|
await new Promise(resolve => setImmediate(resolve));
|
|
260
|
-
expect(dockerService.startDockerCompose).toHaveBeenCalledWith('/path/to/docker-compose-dev.yml',
|
|
234
|
+
expect(dockerService.startDockerCompose).toHaveBeenCalledWith('/path/to/docker-compose-dev.yml', 'never');
|
|
261
235
|
// Cancel the promise (it will be rejected but we don't care)
|
|
262
236
|
runPromise.catch(() => { });
|
|
263
237
|
});
|
|
@@ -33,6 +33,6 @@ export interface DockerComposeProcess {
|
|
|
33
33
|
waitForHealthy: () => Promise<void>;
|
|
34
34
|
}
|
|
35
35
|
export type PullPolicy = 'always' | 'missing' | 'never';
|
|
36
|
-
export declare function startDockerCompose(dockerComposePath: string,
|
|
36
|
+
export declare function startDockerCompose(dockerComposePath: string, pullPolicy?: PullPolicy): Promise<DockerComposeProcess>;
|
|
37
37
|
export declare function stopDockerCompose(dockerComposePath: string): Promise<void>;
|
|
38
38
|
export { isDockerInstalled, isDockerComposeAvailable, isDockerDaemonRunning, DockerValidationError };
|
package/dist/services/docker.js
CHANGED
|
@@ -121,7 +121,7 @@ export async function waitForServicesHealthy(dockerComposePath, timeoutMs = 1200
|
|
|
121
121
|
logUpdate.done();
|
|
122
122
|
throw new Error('Timeout waiting for services to become healthy');
|
|
123
123
|
}
|
|
124
|
-
export async function startDockerCompose(dockerComposePath,
|
|
124
|
+
export async function startDockerCompose(dockerComposePath, pullPolicy) {
|
|
125
125
|
const args = [
|
|
126
126
|
'compose',
|
|
127
127
|
'-f', dockerComposePath,
|
|
@@ -131,9 +131,6 @@ export async function startDockerCompose(dockerComposePath, enableWatch = false,
|
|
|
131
131
|
if (pullPolicy) {
|
|
132
132
|
args.push('--pull', pullPolicy);
|
|
133
133
|
}
|
|
134
|
-
if (enableWatch) {
|
|
135
|
-
args.push('--watch');
|
|
136
|
-
}
|
|
137
134
|
ux.stdout('đŗ Starting Docker services...\n');
|
|
138
135
|
const dockerProcess = spawn('docker', args, {
|
|
139
136
|
cwd: process.cwd(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@output.ai/cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4",
|
|
4
4
|
"description": "CLI for Output.ai workflow generation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
"copy-assets": "./bin/copyassets.sh",
|
|
19
19
|
"test": "vitest run",
|
|
20
20
|
"generate:api": "orval --config ./orval.config.ts",
|
|
21
|
-
"
|
|
22
|
-
"prebuild": "npm run generate:api && npm run update:versions"
|
|
21
|
+
"prebuild": "npm run generate:api"
|
|
23
22
|
},
|
|
24
23
|
"dependencies": {
|
|
25
24
|
"@anthropic-ai/claude-agent-sdk": "0.1.71",
|