@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,411 @@
1
+ /**
2
+ * Mail Template
3
+ *
4
+ * Generates email template files for VeloxTS applications.
5
+ */
6
+ // ============================================================================
7
+ // Path Helpers
8
+ // ============================================================================
9
+ /**
10
+ * Get the path for a mail template file
11
+ */
12
+ export function getMailPath(entityName, _project, options) {
13
+ const extension = options.text ? 'ts' : 'tsx';
14
+ return `src/mail/${entityName.toLowerCase()}.${extension}`;
15
+ }
16
+ // ============================================================================
17
+ // Templates
18
+ // ============================================================================
19
+ /**
20
+ * Generate plain text email template
21
+ */
22
+ function generateTextMail(ctx) {
23
+ const { entity } = ctx;
24
+ return `/**
25
+ * ${entity.pascal} Email (Plain Text)
26
+ *
27
+ * Plain text email template for ${entity.humanReadable}.
28
+ */
29
+
30
+ import { defineMail } from '@veloxts/mail';
31
+ import { z } from 'zod';
32
+
33
+ // ============================================================================
34
+ // Schema
35
+ // ============================================================================
36
+
37
+ const ${entity.pascal}EmailSchema = z.object({
38
+ name: z.string(),
39
+ // TODO: Add your email data fields
40
+ });
41
+
42
+ export type ${entity.pascal}EmailData = z.infer<typeof ${entity.pascal}EmailSchema>;
43
+
44
+ // ============================================================================
45
+ // Email Definition
46
+ // ============================================================================
47
+
48
+ /**
49
+ * ${entity.pascal} email template
50
+ *
51
+ * Plain text email for ${entity.humanReadable}.
52
+ *
53
+ * @example
54
+ * \`\`\`typescript
55
+ * import { ${entity.camel}Email } from '@/mail/${entity.kebab}';
56
+ * import { mail } from '@/mail';
57
+ *
58
+ * await mail.send(${entity.camel}Email, {
59
+ * to: 'user@example.com',
60
+ * data: { name: 'John' },
61
+ * });
62
+ * \`\`\`
63
+ */
64
+ export const ${entity.camel}Email = defineMail({
65
+ name: '${entity.kebab}',
66
+ schema: ${entity.pascal}EmailSchema,
67
+ subject: ({ name }) => \`${entity.humanReadable}: \${name}\`,
68
+ text: ({ name }) => \`
69
+ Hello \${name},
70
+
71
+ This is your ${entity.humanReadable} email.
72
+
73
+ TODO: Add your email content here.
74
+
75
+ Best regards,
76
+ The Team
77
+ \`.trim(),
78
+ template: () => {
79
+ throw new Error('Text-only email - template should not be called');
80
+ },
81
+ });
82
+ `;
83
+ }
84
+ /**
85
+ * Generate email with attachment support
86
+ */
87
+ function generateAttachmentMail(ctx) {
88
+ const { entity } = ctx;
89
+ return `/**
90
+ * ${entity.pascal} Email
91
+ *
92
+ * Email template for ${entity.humanReadable} with attachment support.
93
+ */
94
+
95
+ import { defineMail } from '@veloxts/mail';
96
+ import { Body, Button, Container, Head, Heading, Html, Preview, Text } from '@react-email/components';
97
+ import { z } from 'zod';
98
+
99
+ // ============================================================================
100
+ // Schema
101
+ // ============================================================================
102
+
103
+ const ${entity.pascal}EmailSchema = z.object({
104
+ name: z.string(),
105
+ downloadUrl: z.string().url(),
106
+ // TODO: Add your email data fields
107
+ });
108
+
109
+ export type ${entity.pascal}EmailData = z.infer<typeof ${entity.pascal}EmailSchema>;
110
+
111
+ // ============================================================================
112
+ // Email Definition
113
+ // ============================================================================
114
+
115
+ /**
116
+ * ${entity.pascal} email template
117
+ *
118
+ * Sends ${entity.humanReadable} with downloadable attachment.
119
+ *
120
+ * @example
121
+ * \`\`\`typescript
122
+ * import { ${entity.camel}Email } from '@/mail/${entity.kebab}';
123
+ * import { mail } from '@/mail';
124
+ *
125
+ * await mail.send(${entity.camel}Email, {
126
+ * to: 'user@example.com',
127
+ * data: { name: 'John', downloadUrl: 'https://...' },
128
+ * attachments: [{
129
+ * filename: 'document.pdf',
130
+ * content: pdfBuffer,
131
+ * contentType: 'application/pdf',
132
+ * }],
133
+ * });
134
+ * \`\`\`
135
+ */
136
+ export const ${entity.camel}Email = defineMail({
137
+ name: '${entity.kebab}',
138
+ schema: ${entity.pascal}EmailSchema,
139
+ subject: ({ name }) => \`${entity.humanReadable} for \${name}\`,
140
+ template: ({ name, downloadUrl }) => (
141
+ <Html>
142
+ <Head />
143
+ <Preview>${entity.humanReadable} is ready to download</Preview>
144
+ <Body style={main}>
145
+ <Container style={container}>
146
+ <Heading style={h1}>Hello, {name}!</Heading>
147
+
148
+ <Text style={text}>
149
+ Your ${entity.humanReadable} is ready. Click the button below to download it.
150
+ </Text>
151
+
152
+ <Button href={downloadUrl} style={button}>
153
+ Download Now
154
+ </Button>
155
+
156
+ <Text style={text}>
157
+ Or copy and paste this URL into your browser:
158
+ <br />
159
+ {downloadUrl}
160
+ </Text>
161
+
162
+ <Text style={footer}>
163
+ This email was sent automatically. Please do not reply.
164
+ </Text>
165
+ </Container>
166
+ </Body>
167
+ </Html>
168
+ ),
169
+ });
170
+
171
+ // ============================================================================
172
+ // Styles
173
+ // ============================================================================
174
+
175
+ const main = {
176
+ backgroundColor: '#f6f9fc',
177
+ fontFamily: '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif',
178
+ };
179
+
180
+ const container = {
181
+ backgroundColor: '#ffffff',
182
+ margin: '0 auto',
183
+ padding: '20px 0 48px',
184
+ marginBottom: '64px',
185
+ };
186
+
187
+ const h1 = {
188
+ color: '#333',
189
+ fontSize: '24px',
190
+ fontWeight: 'bold',
191
+ margin: '40px 0',
192
+ padding: '0',
193
+ textAlign: 'center' as const,
194
+ };
195
+
196
+ const text = {
197
+ color: '#333',
198
+ fontSize: '16px',
199
+ lineHeight: '26px',
200
+ textAlign: 'center' as const,
201
+ };
202
+
203
+ const button = {
204
+ backgroundColor: '#5469d4',
205
+ borderRadius: '4px',
206
+ color: '#fff',
207
+ fontSize: '16px',
208
+ textDecoration: 'none',
209
+ textAlign: 'center' as const,
210
+ display: 'block',
211
+ width: '200px',
212
+ padding: '12px',
213
+ margin: '24px auto',
214
+ };
215
+
216
+ const footer = {
217
+ color: '#8898aa',
218
+ fontSize: '12px',
219
+ lineHeight: '16px',
220
+ textAlign: 'center' as const,
221
+ marginTop: '32px',
222
+ };
223
+ `;
224
+ }
225
+ /**
226
+ * Generate simple React Email template
227
+ */
228
+ function generateReactMail(ctx) {
229
+ const { entity } = ctx;
230
+ return `/**
231
+ * ${entity.pascal} Email
232
+ *
233
+ * Email template for ${entity.humanReadable}.
234
+ */
235
+
236
+ import { defineMail } from '@veloxts/mail';
237
+ import { Body, Button, Container, Head, Heading, Html, Preview, Text } from '@react-email/components';
238
+ import { z } from 'zod';
239
+
240
+ // ============================================================================
241
+ // Schema
242
+ // ============================================================================
243
+
244
+ const ${entity.pascal}EmailSchema = z.object({
245
+ name: z.string(),
246
+ actionUrl: z.string().url(),
247
+ // TODO: Add your email data fields
248
+ });
249
+
250
+ export type ${entity.pascal}EmailData = z.infer<typeof ${entity.pascal}EmailSchema>;
251
+
252
+ // ============================================================================
253
+ // Email Definition
254
+ // ============================================================================
255
+
256
+ /**
257
+ * ${entity.pascal} email template
258
+ *
259
+ * Sends ${entity.humanReadable} notification to users.
260
+ *
261
+ * @example
262
+ * \`\`\`typescript
263
+ * import { ${entity.camel}Email } from '@/mail/${entity.kebab}';
264
+ * import { mail } from '@/mail';
265
+ *
266
+ * await mail.send(${entity.camel}Email, {
267
+ * to: 'user@example.com',
268
+ * data: {
269
+ * name: 'John Doe',
270
+ * actionUrl: 'https://example.com/action',
271
+ * },
272
+ * });
273
+ * \`\`\`
274
+ */
275
+ export const ${entity.camel}Email = defineMail({
276
+ name: '${entity.kebab}',
277
+ schema: ${entity.pascal}EmailSchema,
278
+ subject: ({ name }) => \`${entity.humanReadable} for \${name}\`,
279
+ template: ({ name, actionUrl }) => (
280
+ <Html>
281
+ <Head />
282
+ <Preview>${entity.humanReadable} notification</Preview>
283
+ <Body style={main}>
284
+ <Container style={container}>
285
+ <Heading style={h1}>Hello, {name}!</Heading>
286
+
287
+ <Text style={text}>
288
+ TODO: Add your email content here.
289
+ </Text>
290
+
291
+ <Button href={actionUrl} style={button}>
292
+ Take Action
293
+ </Button>
294
+
295
+ <Text style={footer}>
296
+ If you did not expect this email, you can safely ignore it.
297
+ </Text>
298
+ </Container>
299
+ </Body>
300
+ </Html>
301
+ ),
302
+ text: ({ name }) => \`
303
+ Hello \${name},
304
+
305
+ TODO: Add your plain text email content here.
306
+
307
+ Best regards,
308
+ The Team
309
+ \`.trim(),
310
+ });
311
+
312
+ // ============================================================================
313
+ // Styles
314
+ // ============================================================================
315
+
316
+ const main = {
317
+ backgroundColor: '#f6f9fc',
318
+ fontFamily: '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif',
319
+ };
320
+
321
+ const container = {
322
+ backgroundColor: '#ffffff',
323
+ margin: '0 auto',
324
+ padding: '20px 0 48px',
325
+ marginBottom: '64px',
326
+ };
327
+
328
+ const h1 = {
329
+ color: '#333',
330
+ fontSize: '24px',
331
+ fontWeight: 'bold',
332
+ margin: '40px 0',
333
+ padding: '0',
334
+ textAlign: 'center' as const,
335
+ };
336
+
337
+ const text = {
338
+ color: '#333',
339
+ fontSize: '16px',
340
+ lineHeight: '26px',
341
+ textAlign: 'center' as const,
342
+ };
343
+
344
+ const button = {
345
+ backgroundColor: '#5469d4',
346
+ borderRadius: '4px',
347
+ color: '#fff',
348
+ fontSize: '16px',
349
+ textDecoration: 'none',
350
+ textAlign: 'center' as const,
351
+ display: 'block',
352
+ width: '200px',
353
+ padding: '12px',
354
+ margin: '24px auto',
355
+ };
356
+
357
+ const footer = {
358
+ color: '#8898aa',
359
+ fontSize: '12px',
360
+ lineHeight: '16px',
361
+ textAlign: 'center' as const,
362
+ marginTop: '32px',
363
+ };
364
+ `;
365
+ }
366
+ // ============================================================================
367
+ // Main Template
368
+ // ============================================================================
369
+ /**
370
+ * Mail template function
371
+ */
372
+ export const mailTemplate = (ctx) => {
373
+ if (ctx.options.text) {
374
+ return generateTextMail(ctx);
375
+ }
376
+ if (ctx.options.attachment) {
377
+ return generateAttachmentMail(ctx);
378
+ }
379
+ return generateReactMail(ctx);
380
+ };
381
+ // ============================================================================
382
+ // Post-generation Instructions
383
+ // ============================================================================
384
+ export function getMailInstructions(entityName, options) {
385
+ const lines = [`Your ${entityName} email template has been created.`, '', 'Next steps:'];
386
+ lines.push(' 1. Update the Zod schema with your email data fields');
387
+ lines.push(' 2. Customize the email content and styling');
388
+ lines.push(' 3. Send the email from your procedures:');
389
+ lines.push('');
390
+ lines.push(" import { mail } from '@/mail';");
391
+ lines.push(` import { ${entityName}Email } from '@/mail/${entityName.toLowerCase()}';`);
392
+ lines.push('');
393
+ lines.push(` await mail.send(${entityName}Email, {`);
394
+ lines.push(" to: 'user@example.com',");
395
+ lines.push(" data: { name: '...' },");
396
+ lines.push(' });');
397
+ if (options.text) {
398
+ lines.push('');
399
+ lines.push(' 4. This is a plain text email - no HTML rendering');
400
+ }
401
+ else if (options.attachment) {
402
+ lines.push('');
403
+ lines.push(' 4. Add attachments when sending:');
404
+ lines.push(" attachments: [{ filename: '...', content: buffer }]");
405
+ }
406
+ else {
407
+ lines.push('');
408
+ lines.push(' 4. Preview your email: npx react-email dev');
409
+ }
410
+ return lines.join('\n');
411
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Storage Template
3
+ *
4
+ * Generates storage configuration and upload handler files for VeloxTS applications.
5
+ */
6
+ import type { ProjectContext, TemplateFunction } from '../types.js';
7
+ export interface StorageOptions {
8
+ /** Generate local filesystem storage configuration */
9
+ local: boolean;
10
+ /** Generate S3/R2/MinIO storage configuration */
11
+ s3: boolean;
12
+ /** Generate file upload handler with storage */
13
+ upload: boolean;
14
+ }
15
+ /**
16
+ * Get the path for a storage configuration file
17
+ */
18
+ export declare function getStoragePath(entityName: string, _project: ProjectContext, options: StorageOptions): string;
19
+ /**
20
+ * Storage template function
21
+ */
22
+ export declare const storageTemplate: TemplateFunction<StorageOptions>;
23
+ export declare function getStorageInstructions(entityName: string, options: StorageOptions): string;