@veloxts/cli 0.6.31 → 0.6.52
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/CHANGELOG.md +252 -0
- package/dist/cli.js +2 -0
- package/dist/commands/schedule.d.ts +14 -0
- package/dist/commands/schedule.js +324 -0
- package/dist/generators/generators/event.d.ts +35 -0
- package/dist/generators/generators/event.js +99 -0
- package/dist/generators/generators/index.d.ts +5 -0
- package/dist/generators/generators/index.js +15 -0
- package/dist/generators/generators/job.d.ts +36 -0
- package/dist/generators/generators/job.js +98 -0
- package/dist/generators/generators/mail.d.ts +36 -0
- package/dist/generators/generators/mail.js +90 -0
- package/dist/generators/generators/storage.d.ts +35 -0
- package/dist/generators/generators/storage.js +104 -0
- package/dist/generators/generators/task.d.ts +36 -0
- package/dist/generators/generators/task.js +99 -0
- package/dist/generators/templates/event.d.ts +21 -0
- package/dist/generators/templates/event.js +410 -0
- package/dist/generators/templates/job.d.ts +23 -0
- package/dist/generators/templates/job.js +352 -0
- package/dist/generators/templates/mail.d.ts +21 -0
- package/dist/generators/templates/mail.js +411 -0
- package/dist/generators/templates/storage.d.ts +23 -0
- package/dist/generators/templates/storage.js +556 -0
- package/dist/generators/templates/task.d.ts +33 -0
- package/dist/generators/templates/task.js +189 -0
- package/package.json +8 -6
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Job Template
|
|
3
|
+
*
|
|
4
|
+
* Generates background job files for VeloxTS applications.
|
|
5
|
+
*/
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Path Helpers
|
|
8
|
+
// ============================================================================
|
|
9
|
+
/**
|
|
10
|
+
* Get the path for a job file
|
|
11
|
+
*/
|
|
12
|
+
export function getJobPath(entityName, _project) {
|
|
13
|
+
return `src/jobs/${entityName.toLowerCase()}.ts`;
|
|
14
|
+
}
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Templates
|
|
17
|
+
// ============================================================================
|
|
18
|
+
/**
|
|
19
|
+
* Generate job with custom queue
|
|
20
|
+
*/
|
|
21
|
+
function generateQueueJob(ctx) {
|
|
22
|
+
const { entity } = ctx;
|
|
23
|
+
return `/**
|
|
24
|
+
* ${entity.pascal} Job
|
|
25
|
+
*
|
|
26
|
+
* Background job for ${entity.humanReadable} processing with custom queue.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { defineJob } from '@veloxts/queue';
|
|
30
|
+
import { z } from 'zod';
|
|
31
|
+
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Schema
|
|
34
|
+
// ============================================================================
|
|
35
|
+
|
|
36
|
+
const ${entity.pascal}JobSchema = z.object({
|
|
37
|
+
id: z.string().uuid(),
|
|
38
|
+
// TODO: Add your job payload fields
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export type ${entity.pascal}JobData = z.infer<typeof ${entity.pascal}JobSchema>;
|
|
42
|
+
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// Job Definition
|
|
45
|
+
// ============================================================================
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* ${entity.pascal} job
|
|
49
|
+
*
|
|
50
|
+
* Processes ${entity.humanReadable} tasks in the background.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* \`\`\`typescript
|
|
54
|
+
* import { ${entity.camel}Job } from '@/jobs/${entity.kebab}';
|
|
55
|
+
* import { queue } from '@/queue';
|
|
56
|
+
*
|
|
57
|
+
* await queue.dispatch(${entity.camel}Job, { id: '...' });
|
|
58
|
+
* \`\`\`
|
|
59
|
+
*/
|
|
60
|
+
export const ${entity.camel}Job = defineJob({
|
|
61
|
+
name: '${entity.kebab}',
|
|
62
|
+
schema: ${entity.pascal}JobSchema,
|
|
63
|
+
queue: '${entity.camel}', // Custom queue for this job type
|
|
64
|
+
handler: async ({ data, jobId, log }) => {
|
|
65
|
+
await log(\`Processing ${entity.humanReadable}: \${data.id}\`);
|
|
66
|
+
|
|
67
|
+
// TODO: Implement job logic
|
|
68
|
+
// Example: await sendEmail(data.id);
|
|
69
|
+
|
|
70
|
+
await log(\`${entity.pascal} job completed: \${jobId}\`);
|
|
71
|
+
},
|
|
72
|
+
options: {
|
|
73
|
+
attempts: 3,
|
|
74
|
+
backoff: {
|
|
75
|
+
type: 'exponential',
|
|
76
|
+
delay: 1000,
|
|
77
|
+
},
|
|
78
|
+
priority: 0,
|
|
79
|
+
removeOnComplete: true,
|
|
80
|
+
removeOnFail: false,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Generate job with retry configuration
|
|
87
|
+
*/
|
|
88
|
+
function generateRetryJob(ctx) {
|
|
89
|
+
const { entity } = ctx;
|
|
90
|
+
return `/**
|
|
91
|
+
* ${entity.pascal} Job
|
|
92
|
+
*
|
|
93
|
+
* Background job for ${entity.humanReadable} processing with retry configuration.
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
import { defineJob } from '@veloxts/queue';
|
|
97
|
+
import { z } from 'zod';
|
|
98
|
+
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// Schema
|
|
101
|
+
// ============================================================================
|
|
102
|
+
|
|
103
|
+
const ${entity.pascal}JobSchema = z.object({
|
|
104
|
+
id: z.string().uuid(),
|
|
105
|
+
// TODO: Add your job payload fields
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
export type ${entity.pascal}JobData = z.infer<typeof ${entity.pascal}JobSchema>;
|
|
109
|
+
|
|
110
|
+
// ============================================================================
|
|
111
|
+
// Job Definition
|
|
112
|
+
// ============================================================================
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* ${entity.pascal} job with advanced retry configuration
|
|
116
|
+
*
|
|
117
|
+
* Handles ${entity.humanReadable} tasks with exponential backoff on failure.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* \`\`\`typescript
|
|
121
|
+
* import { ${entity.camel}Job } from '@/jobs/${entity.kebab}';
|
|
122
|
+
* import { queue } from '@/queue';
|
|
123
|
+
*
|
|
124
|
+
* await queue.dispatch(${entity.camel}Job, { id: '...' });
|
|
125
|
+
* \`\`\`
|
|
126
|
+
*/
|
|
127
|
+
export const ${entity.camel}Job = defineJob({
|
|
128
|
+
name: '${entity.kebab}',
|
|
129
|
+
schema: ${entity.pascal}JobSchema,
|
|
130
|
+
handler: async ({ data, attemptNumber, log }) => {
|
|
131
|
+
await log(\`Attempt \${attemptNumber}: Processing ${entity.humanReadable} \${data.id}\`);
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
// TODO: Implement job logic
|
|
135
|
+
// Example: await externalApiCall(data.id);
|
|
136
|
+
|
|
137
|
+
await log(\`${entity.pascal} job completed successfully\`);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
await log(\`Error in ${entity.camel} job: \${error}\`);
|
|
140
|
+
throw error; // Re-throw to trigger retry
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
options: {
|
|
144
|
+
// Retry configuration
|
|
145
|
+
attempts: 5,
|
|
146
|
+
backoff: {
|
|
147
|
+
type: 'exponential', // Delay doubles each retry: 2s, 4s, 8s, 16s
|
|
148
|
+
delay: 2000,
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
// Job priority (lower = higher priority)
|
|
152
|
+
priority: 5,
|
|
153
|
+
|
|
154
|
+
// Cleanup configuration
|
|
155
|
+
removeOnComplete: true, // Auto-remove successful jobs
|
|
156
|
+
removeOnFail: false, // Keep failed jobs for debugging
|
|
157
|
+
|
|
158
|
+
// Optional: Set a timeout for the job
|
|
159
|
+
timeout: 60000, // 1 minute
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
`;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Generate job with progress tracking
|
|
166
|
+
*/
|
|
167
|
+
function generateProgressJob(ctx) {
|
|
168
|
+
const { entity } = ctx;
|
|
169
|
+
return `/**
|
|
170
|
+
* ${entity.pascal} Job
|
|
171
|
+
*
|
|
172
|
+
* Background job for ${entity.humanReadable} processing with progress tracking.
|
|
173
|
+
*/
|
|
174
|
+
|
|
175
|
+
import { defineJob } from '@veloxts/queue';
|
|
176
|
+
import { z } from 'zod';
|
|
177
|
+
|
|
178
|
+
// ============================================================================
|
|
179
|
+
// Schema
|
|
180
|
+
// ============================================================================
|
|
181
|
+
|
|
182
|
+
const ${entity.pascal}JobSchema = z.object({
|
|
183
|
+
items: z.array(z.string()),
|
|
184
|
+
// TODO: Add your job payload fields
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
export type ${entity.pascal}JobData = z.infer<typeof ${entity.pascal}JobSchema>;
|
|
188
|
+
|
|
189
|
+
// ============================================================================
|
|
190
|
+
// Job Definition
|
|
191
|
+
// ============================================================================
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* ${entity.pascal} job with progress tracking
|
|
195
|
+
*
|
|
196
|
+
* Processes ${entity.humanReadable} tasks with real-time progress updates.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* \`\`\`typescript
|
|
200
|
+
* import { ${entity.camel}Job } from '@/jobs/${entity.kebab}';
|
|
201
|
+
* import { queue } from '@/queue';
|
|
202
|
+
*
|
|
203
|
+
* await queue.dispatch(${entity.camel}Job, { items: ['a', 'b', 'c'] });
|
|
204
|
+
* \`\`\`
|
|
205
|
+
*/
|
|
206
|
+
export const ${entity.camel}Job = defineJob({
|
|
207
|
+
name: '${entity.kebab}',
|
|
208
|
+
schema: ${entity.pascal}JobSchema,
|
|
209
|
+
handler: async ({ data, progress, log }) => {
|
|
210
|
+
const total = data.items.length;
|
|
211
|
+
await log(\`Starting ${entity.camel} job with \${total} items\`);
|
|
212
|
+
|
|
213
|
+
// Report initial progress
|
|
214
|
+
await progress(0);
|
|
215
|
+
|
|
216
|
+
for (let i = 0; i < total; i++) {
|
|
217
|
+
const item = data.items[i];
|
|
218
|
+
|
|
219
|
+
// TODO: Process each item
|
|
220
|
+
// Example: await processItem(item);
|
|
221
|
+
await log(\`Processing item: \${item}\`);
|
|
222
|
+
|
|
223
|
+
// Update progress (0-100)
|
|
224
|
+
const percentComplete = Math.round(((i + 1) / total) * 100);
|
|
225
|
+
await progress(percentComplete);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
await log(\`${entity.pascal} job completed: processed \${total} items\`);
|
|
229
|
+
},
|
|
230
|
+
options: {
|
|
231
|
+
attempts: 3,
|
|
232
|
+
backoff: {
|
|
233
|
+
type: 'exponential',
|
|
234
|
+
delay: 1000,
|
|
235
|
+
},
|
|
236
|
+
removeOnComplete: true,
|
|
237
|
+
removeOnFail: false,
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
`;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Generate simple job template
|
|
244
|
+
*/
|
|
245
|
+
function generateSimpleJob(ctx) {
|
|
246
|
+
const { entity } = ctx;
|
|
247
|
+
return `/**
|
|
248
|
+
* ${entity.pascal} Job
|
|
249
|
+
*
|
|
250
|
+
* Background job for ${entity.humanReadable} processing.
|
|
251
|
+
*/
|
|
252
|
+
|
|
253
|
+
import { defineJob } from '@veloxts/queue';
|
|
254
|
+
import { z } from 'zod';
|
|
255
|
+
|
|
256
|
+
// ============================================================================
|
|
257
|
+
// Schema
|
|
258
|
+
// ============================================================================
|
|
259
|
+
|
|
260
|
+
const ${entity.pascal}JobSchema = z.object({
|
|
261
|
+
id: z.string().uuid(),
|
|
262
|
+
// TODO: Add your job payload fields
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
export type ${entity.pascal}JobData = z.infer<typeof ${entity.pascal}JobSchema>;
|
|
266
|
+
|
|
267
|
+
// ============================================================================
|
|
268
|
+
// Job Definition
|
|
269
|
+
// ============================================================================
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* ${entity.pascal} job
|
|
273
|
+
*
|
|
274
|
+
* Processes ${entity.humanReadable} tasks in the background.
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* \`\`\`typescript
|
|
278
|
+
* import { ${entity.camel}Job } from '@/jobs/${entity.kebab}';
|
|
279
|
+
* import { queue } from '@/queue';
|
|
280
|
+
*
|
|
281
|
+
* // Dispatch job for immediate processing
|
|
282
|
+
* await queue.dispatch(${entity.camel}Job, { id: '...' });
|
|
283
|
+
*
|
|
284
|
+
* // Dispatch with delay
|
|
285
|
+
* await queue.dispatch(${entity.camel}Job, { id: '...' }, { delay: '5m' });
|
|
286
|
+
* \`\`\`
|
|
287
|
+
*/
|
|
288
|
+
export const ${entity.camel}Job = defineJob({
|
|
289
|
+
name: '${entity.kebab}',
|
|
290
|
+
schema: ${entity.pascal}JobSchema,
|
|
291
|
+
handler: async ({ data, ctx }) => {
|
|
292
|
+
// TODO: Implement your job logic here
|
|
293
|
+
// Access database via ctx.db (if ORM plugin registered)
|
|
294
|
+
// Example: const item = await ctx.db.item.findUnique({ where: { id: data.id } });
|
|
295
|
+
|
|
296
|
+
console.log(\`Processing ${entity.humanReadable}:\`, data.id);
|
|
297
|
+
},
|
|
298
|
+
options: {
|
|
299
|
+
attempts: 3,
|
|
300
|
+
backoff: {
|
|
301
|
+
type: 'exponential',
|
|
302
|
+
delay: 1000,
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
`;
|
|
307
|
+
}
|
|
308
|
+
// ============================================================================
|
|
309
|
+
// Main Template
|
|
310
|
+
// ============================================================================
|
|
311
|
+
/**
|
|
312
|
+
* Job template function
|
|
313
|
+
*/
|
|
314
|
+
export const jobTemplate = (ctx) => {
|
|
315
|
+
if (ctx.options.queue) {
|
|
316
|
+
return generateQueueJob(ctx);
|
|
317
|
+
}
|
|
318
|
+
if (ctx.options.retry) {
|
|
319
|
+
return generateRetryJob(ctx);
|
|
320
|
+
}
|
|
321
|
+
if (ctx.options.progress) {
|
|
322
|
+
return generateProgressJob(ctx);
|
|
323
|
+
}
|
|
324
|
+
return generateSimpleJob(ctx);
|
|
325
|
+
};
|
|
326
|
+
// ============================================================================
|
|
327
|
+
// Post-generation Instructions
|
|
328
|
+
// ============================================================================
|
|
329
|
+
export function getJobInstructions(entityName, options) {
|
|
330
|
+
const lines = [`Your ${entityName} job has been created.`, '', 'Next steps:'];
|
|
331
|
+
lines.push(' 1. Update the Zod schema with your job payload fields');
|
|
332
|
+
lines.push(' 2. Implement the job handler logic');
|
|
333
|
+
lines.push(' 3. Dispatch the job from your procedures:');
|
|
334
|
+
lines.push('');
|
|
335
|
+
lines.push(" import { queue } from '@/queue';");
|
|
336
|
+
lines.push(` import { ${entityName}Job } from '@/jobs/${entityName.toLowerCase()}';`);
|
|
337
|
+
lines.push('');
|
|
338
|
+
lines.push(` await queue.dispatch(${entityName}Job, { id: '...' });`);
|
|
339
|
+
if (options.queue) {
|
|
340
|
+
lines.push('');
|
|
341
|
+
lines.push(` 4. Ensure the '${entityName}' queue is configured in your queue manager`);
|
|
342
|
+
}
|
|
343
|
+
else if (options.retry) {
|
|
344
|
+
lines.push('');
|
|
345
|
+
lines.push(' 4. Adjust retry attempts and backoff strategy as needed');
|
|
346
|
+
}
|
|
347
|
+
else if (options.progress) {
|
|
348
|
+
lines.push('');
|
|
349
|
+
lines.push(' 4. Monitor job progress in your queue dashboard');
|
|
350
|
+
}
|
|
351
|
+
return lines.join('\n');
|
|
352
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mail Template
|
|
3
|
+
*
|
|
4
|
+
* Generates email template files for VeloxTS applications.
|
|
5
|
+
*/
|
|
6
|
+
import type { ProjectContext, TemplateFunction } from '../types.js';
|
|
7
|
+
export interface MailOptions {
|
|
8
|
+
/** Plain text email (no React) */
|
|
9
|
+
text: boolean;
|
|
10
|
+
/** Email with attachment support */
|
|
11
|
+
attachment: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Get the path for a mail template file
|
|
15
|
+
*/
|
|
16
|
+
export declare function getMailPath(entityName: string, _project: ProjectContext, options: MailOptions): string;
|
|
17
|
+
/**
|
|
18
|
+
* Mail template function
|
|
19
|
+
*/
|
|
20
|
+
export declare const mailTemplate: TemplateFunction<MailOptions>;
|
|
21
|
+
export declare function getMailInstructions(entityName: string, options: MailOptions): string;
|