@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.
@@ -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;