vonosan-cli 0.1.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.
Files changed (121) hide show
  1. package/dist/__tests__/env-parity.pbt.test.d.ts +15 -0
  2. package/dist/__tests__/env-parity.pbt.test.d.ts.map +1 -0
  3. package/dist/__tests__/env-parity.pbt.test.js +125 -0
  4. package/dist/__tests__/env-parity.pbt.test.js.map +1 -0
  5. package/dist/__tests__/module-generator.pbt.test.d.ts +15 -0
  6. package/dist/__tests__/module-generator.pbt.test.d.ts.map +1 -0
  7. package/dist/__tests__/module-generator.pbt.test.js +130 -0
  8. package/dist/__tests__/module-generator.pbt.test.js.map +1 -0
  9. package/dist/commands/add.d.ts +21 -0
  10. package/dist/commands/add.d.ts.map +1 -0
  11. package/dist/commands/add.js +128 -0
  12. package/dist/commands/add.js.map +1 -0
  13. package/dist/commands/audit.d.ts +18 -0
  14. package/dist/commands/audit.d.ts.map +1 -0
  15. package/dist/commands/audit.js +73 -0
  16. package/dist/commands/audit.js.map +1 -0
  17. package/dist/commands/branch-finish.d.ts +19 -0
  18. package/dist/commands/branch-finish.d.ts.map +1 -0
  19. package/dist/commands/branch-finish.js +80 -0
  20. package/dist/commands/branch-finish.js.map +1 -0
  21. package/dist/commands/branch-new.d.ts +17 -0
  22. package/dist/commands/branch-new.d.ts.map +1 -0
  23. package/dist/commands/branch-new.js +70 -0
  24. package/dist/commands/branch-new.js.map +1 -0
  25. package/dist/commands/commit.d.ts +21 -0
  26. package/dist/commands/commit.d.ts.map +1 -0
  27. package/dist/commands/commit.js +79 -0
  28. package/dist/commands/commit.js.map +1 -0
  29. package/dist/commands/db.d.ts +28 -0
  30. package/dist/commands/db.d.ts.map +1 -0
  31. package/dist/commands/db.js +83 -0
  32. package/dist/commands/db.js.map +1 -0
  33. package/dist/commands/env-add.d.ts +17 -0
  34. package/dist/commands/env-add.d.ts.map +1 -0
  35. package/dist/commands/env-add.js +73 -0
  36. package/dist/commands/env-add.js.map +1 -0
  37. package/dist/commands/fix-headers.d.ts +15 -0
  38. package/dist/commands/fix-headers.d.ts.map +1 -0
  39. package/dist/commands/fix-headers.js +37 -0
  40. package/dist/commands/fix-headers.js.map +1 -0
  41. package/dist/commands/fix-logs.d.ts +15 -0
  42. package/dist/commands/fix-logs.d.ts.map +1 -0
  43. package/dist/commands/fix-logs.js +87 -0
  44. package/dist/commands/fix-logs.js.map +1 -0
  45. package/dist/commands/jobs.d.ts +17 -0
  46. package/dist/commands/jobs.d.ts.map +1 -0
  47. package/dist/commands/jobs.js +107 -0
  48. package/dist/commands/jobs.js.map +1 -0
  49. package/dist/commands/lint.d.ts +15 -0
  50. package/dist/commands/lint.d.ts.map +1 -0
  51. package/dist/commands/lint.js +49 -0
  52. package/dist/commands/lint.js.map +1 -0
  53. package/dist/commands/make.d.ts +31 -0
  54. package/dist/commands/make.d.ts.map +1 -0
  55. package/dist/commands/make.js +176 -0
  56. package/dist/commands/make.js.map +1 -0
  57. package/dist/commands/migrate.d.ts +43 -0
  58. package/dist/commands/migrate.d.ts.map +1 -0
  59. package/dist/commands/migrate.js +120 -0
  60. package/dist/commands/migrate.js.map +1 -0
  61. package/dist/commands/schema-sync.d.ts +17 -0
  62. package/dist/commands/schema-sync.d.ts.map +1 -0
  63. package/dist/commands/schema-sync.js +48 -0
  64. package/dist/commands/schema-sync.js.map +1 -0
  65. package/dist/commands/test.d.ts +19 -0
  66. package/dist/commands/test.d.ts.map +1 -0
  67. package/dist/commands/test.js +113 -0
  68. package/dist/commands/test.js.map +1 -0
  69. package/dist/commands/upgrade.d.ts +24 -0
  70. package/dist/commands/upgrade.d.ts.map +1 -0
  71. package/dist/commands/upgrade.js +177 -0
  72. package/dist/commands/upgrade.js.map +1 -0
  73. package/dist/generators/deployment/docker-compose.d.ts +20 -0
  74. package/dist/generators/deployment/docker-compose.d.ts.map +1 -0
  75. package/dist/generators/deployment/docker-compose.js +95 -0
  76. package/dist/generators/deployment/docker-compose.js.map +1 -0
  77. package/dist/generators/deployment/dockerfile.d.ts +18 -0
  78. package/dist/generators/deployment/dockerfile.d.ts.map +1 -0
  79. package/dist/generators/deployment/dockerfile.js +99 -0
  80. package/dist/generators/deployment/dockerfile.js.map +1 -0
  81. package/dist/generators/deployment/pm2.d.ts +17 -0
  82. package/dist/generators/deployment/pm2.d.ts.map +1 -0
  83. package/dist/generators/deployment/pm2.js +59 -0
  84. package/dist/generators/deployment/pm2.js.map +1 -0
  85. package/dist/generators/deployment/secrets.d.ts +19 -0
  86. package/dist/generators/deployment/secrets.d.ts.map +1 -0
  87. package/dist/generators/deployment/secrets.js +41 -0
  88. package/dist/generators/deployment/secrets.js.map +1 -0
  89. package/dist/generators/deployment/shutdown.d.ts +17 -0
  90. package/dist/generators/deployment/shutdown.d.ts.map +1 -0
  91. package/dist/generators/deployment/shutdown.js +61 -0
  92. package/dist/generators/deployment/shutdown.js.map +1 -0
  93. package/dist/generators/deployment/wrangler.d.ts +25 -0
  94. package/dist/generators/deployment/wrangler.d.ts.map +1 -0
  95. package/dist/generators/deployment/wrangler.js +93 -0
  96. package/dist/generators/deployment/wrangler.js.map +1 -0
  97. package/dist/generators/file-generators.d.ts +38 -0
  98. package/dist/generators/file-generators.d.ts.map +1 -0
  99. package/dist/generators/file-generators.js +546 -0
  100. package/dist/generators/file-generators.js.map +1 -0
  101. package/dist/generators/module-generator.d.ts +33 -0
  102. package/dist/generators/module-generator.d.ts.map +1 -0
  103. package/dist/generators/module-generator.js +61 -0
  104. package/dist/generators/module-generator.js.map +1 -0
  105. package/dist/header-generator.d.ts +34 -0
  106. package/dist/header-generator.d.ts.map +1 -0
  107. package/dist/header-generator.js +77 -0
  108. package/dist/header-generator.js.map +1 -0
  109. package/dist/index.d.ts +12 -0
  110. package/dist/index.d.ts.map +1 -0
  111. package/dist/index.js +177 -0
  112. package/dist/index.js.map +1 -0
  113. package/dist/linter/env-parity.d.ts +28 -0
  114. package/dist/linter/env-parity.d.ts.map +1 -0
  115. package/dist/linter/env-parity.js +59 -0
  116. package/dist/linter/env-parity.js.map +1 -0
  117. package/dist/linter.d.ts +23 -0
  118. package/dist/linter.d.ts.map +1 -0
  119. package/dist/linter.js +207 -0
  120. package/dist/linter.js.map +1 -0
  121. package/package.json +32 -0
@@ -0,0 +1,546 @@
1
+ /**
2
+ * ──────────────────────────────────────────────────────────────────
3
+ * 🏢 Company Name: Bonifade Technologies
4
+ * 👨‍💻 Developer: Bowofade Oyerinde
5
+ * 🐙 GitHub: oyenet1
6
+ * 📅 Created Date: 2026-04-05
7
+ * 🔄 Updated Date: 2026-04-05
8
+ * ──────────────────────────────────────────────────────────────────
9
+ */
10
+ import { generateHeader } from '../header-generator.js';
11
+ // ─── Naming helpers ───────────────────────────────────────────────────────────
12
+ /** "user-profile" → "UserProfile" */
13
+ export function toPascalCase(name) {
14
+ return name
15
+ .split(/[-_\s]+/)
16
+ .map(w => w.charAt(0).toUpperCase() + w.slice(1))
17
+ .join('');
18
+ }
19
+ /** "user-profile" → "userProfile" */
20
+ export function toCamelCase(name) {
21
+ const pascal = toPascalCase(name);
22
+ return pascal.charAt(0).toLowerCase() + pascal.slice(1);
23
+ }
24
+ /** "UserProfile" → "user_profiles" (simple pluralisation) */
25
+ export function toTableName(name) {
26
+ return name
27
+ .replace(/([A-Z])/g, '_$1')
28
+ .toLowerCase()
29
+ .replace(/^_/, '') + 's';
30
+ }
31
+ // ─── Individual file generators ───────────────────────────────────────────────
32
+ export function generateService(name) {
33
+ const pascal = toPascalCase(name);
34
+ const camel = toCamelCase(name);
35
+ const header = generateHeader(`src/modules/${name}/${name}.service.ts`);
36
+ return `${header}
37
+
38
+ import type { AppVariables } from 'vonosan/types'
39
+ import type { Context } from 'hono'
40
+
41
+ export class ${pascal}Service {
42
+ constructor(private readonly c: Context<{ Variables: AppVariables }>) {}
43
+
44
+ async findAll() {
45
+ // TODO: implement findAll
46
+ return []
47
+ }
48
+
49
+ async findById(id: string) {
50
+ // TODO: implement findById
51
+ return null
52
+ }
53
+
54
+ async create(data: unknown) {
55
+ // TODO: implement create
56
+ return data
57
+ }
58
+
59
+ async update(id: string, data: unknown) {
60
+ // TODO: implement update
61
+ return { id, ...data as object }
62
+ }
63
+
64
+ async delete(id: string) {
65
+ // TODO: implement delete
66
+ return { id }
67
+ }
68
+ }
69
+
70
+ export const ${camel}Service = (c: Context<{ Variables: AppVariables }>) =>
71
+ new ${pascal}Service(c)
72
+ `;
73
+ }
74
+ export function generateController(name) {
75
+ const pascal = toPascalCase(name);
76
+ const camel = toCamelCase(name);
77
+ const header = generateHeader(`src/modules/${name}/${name}.controller.ts`);
78
+ return `${header}
79
+
80
+ import type { Context } from 'hono'
81
+ import type { AppVariables } from 'vonosan/types'
82
+ import { success, error } from 'vonosan/server'
83
+ import { ${camel}Service } from './${name}.service.js'
84
+
85
+ export const ${pascal}Controller = {
86
+ async index(c: Context<{ Variables: AppVariables }>) {
87
+ const items = await ${camel}Service(c).findAll()
88
+ return c.json(success('${pascal} list', items))
89
+ },
90
+
91
+ async show(c: Context<{ Variables: AppVariables }>) {
92
+ const { id } = c.req.param()
93
+ const item = await ${camel}Service(c).findById(id)
94
+ if (!item) return c.json(error('${pascal} not found'), 404)
95
+ return c.json(success('${pascal} retrieved', item))
96
+ },
97
+
98
+ async store(c: Context<{ Variables: AppVariables }>) {
99
+ const body = await c.req.json()
100
+ const item = await ${camel}Service(c).create(body)
101
+ return c.json(success('${pascal} created', item), 201)
102
+ },
103
+
104
+ async update(c: Context<{ Variables: AppVariables }>) {
105
+ const { id } = c.req.param()
106
+ const body = await c.req.json()
107
+ const item = await ${camel}Service(c).update(id, body)
108
+ return c.json(success('${pascal} updated', item))
109
+ },
110
+
111
+ async destroy(c: Context<{ Variables: AppVariables }>) {
112
+ const { id } = c.req.param()
113
+ await ${camel}Service(c).delete(id)
114
+ return c.json(success('${pascal} deleted'))
115
+ },
116
+ }
117
+ `;
118
+ }
119
+ export function generateDto(name) {
120
+ const pascal = toPascalCase(name);
121
+ const header = generateHeader(`src/modules/${name}/${name}.dto.ts`);
122
+ return `${header}
123
+
124
+ import { z } from 'zod'
125
+
126
+ export const Create${pascal}Schema = z.object({
127
+ // TODO: define create fields
128
+ })
129
+
130
+ export const Update${pascal}Schema = Create${pascal}Schema.partial()
131
+
132
+ export type Create${pascal}Dto = z.infer<typeof Create${pascal}Schema>
133
+ export type Update${pascal}Dto = z.infer<typeof Update${pascal}Schema>
134
+ `;
135
+ }
136
+ export function generateRoutes(name) {
137
+ const pascal = toPascalCase(name);
138
+ const header = generateHeader(`src/modules/${name}/${name}.routes.ts`);
139
+ return `${header}
140
+
141
+ import { Hono } from 'hono'
142
+ import type { AppVariables } from 'vonosan/types'
143
+ import { ${pascal}Controller } from './${name}.controller.js'
144
+
145
+ const router = new Hono<{ Variables: AppVariables }>()
146
+
147
+ router.get('/api/v1/${name}', ${pascal}Controller.index)
148
+ router.get('/api/v1/${name}/:id', ${pascal}Controller.show)
149
+ router.post('/api/v1/${name}', ${pascal}Controller.store)
150
+ router.put('/api/v1/${name}/:id', ${pascal}Controller.update)
151
+ router.delete('/api/v1/${name}/:id', ${pascal}Controller.destroy)
152
+
153
+ export default router
154
+ `;
155
+ }
156
+ export function generateSchema(name, saas = false) {
157
+ const tableName = toTableName(toPascalCase(name));
158
+ const header = generateHeader(`src/modules/${name}/${name}.schema.ts`);
159
+ const softDeleteCol = saas ? `\n deleted_at: timestamp('deleted_at'),` : '';
160
+ return `${header}
161
+
162
+ import { pgTable, uuid, varchar, timestamp } from 'drizzle-orm/pg-core'
163
+
164
+ export const ${tableName} = pgTable('${tableName}', {
165
+ id: uuid('id').primaryKey().defaultRandom(),
166
+ // TODO: add columns
167
+ created_at: timestamp('created_at').defaultNow().notNull(),
168
+ updated_at: timestamp('updated_at').defaultNow().notNull(),${softDeleteCol}
169
+ })
170
+
171
+ export type ${toPascalCase(name)} = typeof ${tableName}.$inferSelect
172
+ export type New${toPascalCase(name)} = typeof ${tableName}.$inferInsert
173
+ `;
174
+ }
175
+ export function generateResource(name) {
176
+ const pascal = toPascalCase(name);
177
+ const header = generateHeader(`src/modules/${name}/${name}.resource.ts`);
178
+ return `${header}
179
+
180
+ import { buildPaginationMeta } from 'vonosan/server'
181
+
182
+ export class ${pascal}Resource {
183
+ static toResource(item: Record<string, unknown>, fields?: string[]) {
184
+ if (fields && fields.length > 0) {
185
+ return Object.fromEntries(
186
+ Object.entries(item).filter(([k]) => fields.includes(k)),
187
+ )
188
+ }
189
+ return item
190
+ }
191
+
192
+ static toCollection(
193
+ items: Record<string, unknown>[],
194
+ total: number,
195
+ page: number,
196
+ limit: number,
197
+ ) {
198
+ return {
199
+ ${name}s: items.map(i => ${pascal}Resource.toResource(i)),
200
+ meta: buildPaginationMeta(page, limit, total),
201
+ }
202
+ }
203
+ }
204
+ `;
205
+ }
206
+ export function generatePolicy(name) {
207
+ const pascal = toPascalCase(name);
208
+ const header = generateHeader(`src/modules/${name}/${name}.policy.ts`);
209
+ return `${header}
210
+
211
+ import type { AuthAccount } from 'vonosan/types'
212
+
213
+ export class ${pascal}Policy {
214
+ static view(_user: AuthAccount, _resource?: unknown): boolean {
215
+ return true
216
+ }
217
+
218
+ static create(_user: AuthAccount): boolean {
219
+ return true
220
+ }
221
+
222
+ static update(user: AuthAccount, resource?: Record<string, unknown>): boolean {
223
+ // Example: only the owner or admin can update
224
+ if (user.currentRole === 'admin' || user.currentRole === 'superadmin') return true
225
+ return resource?.ownerId === user.id
226
+ }
227
+
228
+ static delete(user: AuthAccount, resource?: Record<string, unknown>): boolean {
229
+ if (user.currentRole === 'admin' || user.currentRole === 'superadmin') return true
230
+ return resource?.ownerId === user.id
231
+ }
232
+ }
233
+ `;
234
+ }
235
+ export function generateScopes(name) {
236
+ const pascal = toPascalCase(name);
237
+ const header = generateHeader(`src/modules/${name}/${name}.scopes.ts`);
238
+ return `${header}
239
+
240
+ /**
241
+ * ${pascal} permission scopes.
242
+ * Register these in your auth module's scope registry.
243
+ */
244
+ export const ${name.toUpperCase().replace(/-/g, '_')}_SCOPES = [
245
+ '${name}:read',
246
+ '${name}:write',
247
+ '${name}:delete',
248
+ '${name}:admin',
249
+ ] as const
250
+
251
+ export type ${pascal}Scope = (typeof ${name.toUpperCase().replace(/-/g, '_')}_SCOPES)[number]
252
+ `;
253
+ }
254
+ export function generateMiddleware(name) {
255
+ const pascal = toPascalCase(name);
256
+ const header = generateHeader(`src/modules/${name}/${name}.middleware.ts`);
257
+ return `${header}
258
+
259
+ import type { Context, Next } from 'hono'
260
+ import type { AppVariables } from 'vonosan/types'
261
+ import { Logger } from 'vonosan/server'
262
+
263
+ /**
264
+ * ${pascal} middleware — add your logic here.
265
+ */
266
+ export async function ${toCamelCase(name)}Middleware(
267
+ c: Context<{ Variables: AppVariables }>,
268
+ next: Next,
269
+ ): Promise<void> {
270
+ Logger.debug('${pascal} middleware', { path: c.req.path })
271
+ await next()
272
+ }
273
+ `;
274
+ }
275
+ export function generatePage(name) {
276
+ const pascal = toPascalCase(name);
277
+ const header = generateHeader(`src/modules/${name}/index.page.vue`);
278
+ return `<!--
279
+ ${header.replace(/^\/\*\*/, '').replace(/\s*\*\/$/, '').replace(/^\s*\* ?/gm, '').trim()}
280
+ -->
281
+ <script setup lang="ts">
282
+ import { use${pascal} } from './composables/use${pascal}.js'
283
+
284
+ const { items, loading, fetchAll } = use${pascal}()
285
+
286
+ onMounted(() => fetchAll())
287
+ </script>
288
+
289
+ <template>
290
+ <div>
291
+ <h1>${pascal}</h1>
292
+ <div v-if="loading">Loading…</div>
293
+ <ul v-else>
294
+ <li v-for="item in items" :key="(item as any).id">{{ item }}</li>
295
+ </ul>
296
+ </div>
297
+ </template>
298
+ `;
299
+ }
300
+ export function generateComposable(name) {
301
+ const pascal = toPascalCase(name);
302
+ const camel = toCamelCase(name);
303
+ const header = generateHeader(`src/modules/${name}/composables/use${pascal}.ts`);
304
+ return `${header}
305
+
306
+ import { ref } from 'vue'
307
+ import { useVonosanFetch } from 'vonosan/client'
308
+
309
+ export function use${pascal}() {
310
+ const items = ref<unknown[]>([])
311
+ const loading = ref(false)
312
+ const error = ref<string | null>(null)
313
+
314
+ async function fetchAll() {
315
+ loading.value = true
316
+ error.value = null
317
+ try {
318
+ const { data } = await useVonosanFetch('/api/v1/${name}')
319
+ items.value = (data as any)?.data ?? []
320
+ } catch (e) {
321
+ error.value = String(e)
322
+ } finally {
323
+ loading.value = false
324
+ }
325
+ }
326
+
327
+ async function create(payload: unknown) {
328
+ const { data } = await useVonosanFetch('/api/v1/${name}', {
329
+ method: 'POST',
330
+ body: JSON.stringify(payload),
331
+ })
332
+ return (data as any)?.data
333
+ }
334
+
335
+ return { items, loading, error, fetchAll, create }
336
+ }
337
+ `;
338
+ }
339
+ export function generateStore(name) {
340
+ const pascal = toPascalCase(name);
341
+ const header = generateHeader(`src/modules/${name}/stores/${name}.store.ts`);
342
+ return `${header}
343
+
344
+ import { defineStore } from 'pinia'
345
+ import { ref } from 'vue'
346
+
347
+ export const use${pascal}Store = defineStore('${name}', () => {
348
+ const items = ref<unknown[]>([])
349
+ const current = ref<unknown | null>(null)
350
+
351
+ function setItems(data: unknown[]) {
352
+ items.value = data
353
+ }
354
+
355
+ function setCurrent(data: unknown | null) {
356
+ current.value = data
357
+ }
358
+
359
+ return { items, current, setItems, setCurrent }
360
+ })
361
+ `;
362
+ }
363
+ export function generateMigration(name) {
364
+ const header = generateHeader(`src/db/migrations/${name}.sql`);
365
+ return `-- ${header.replace(/\/\*\*|\*\/|\* ?/g, '').trim()}
366
+
367
+ -- Migration: ${name}
368
+ -- Created: ${new Date().toISOString()}
369
+
370
+ -- TODO: write your migration SQL here
371
+ -- Example:
372
+ -- CREATE TABLE IF NOT EXISTS example (
373
+ -- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
374
+ -- created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
375
+ -- updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
376
+ -- );
377
+ `;
378
+ }
379
+ export function generateSeed(name) {
380
+ const header = generateHeader(`src/db/seeds/${name}.ts`);
381
+ return `${header}
382
+
383
+ import { Logger } from 'vonosan/server'
384
+
385
+ /**
386
+ * Seed: ${name}
387
+ * Run with: vonosan db:seed ${name}
388
+ */
389
+ export async function seed() {
390
+ Logger.info('Running seed: ${name}')
391
+ // TODO: insert seed data
392
+ Logger.info('Seed complete: ${name}')
393
+ }
394
+
395
+ // Allow direct execution: bun run src/db/seeds/${name}.ts
396
+ seed().catch((err) => {
397
+ Logger.error('Seed failed', { error: String(err) })
398
+ process.exit(1)
399
+ })
400
+ `;
401
+ }
402
+ export function generateTest(name) {
403
+ const pascal = toPascalCase(name);
404
+ const header = generateHeader(`src/modules/${name}/tests/${name}.unit.test.ts`);
405
+ return `${header}
406
+
407
+ import { describe, it, expect } from 'bun:test'
408
+
409
+ describe('${pascal} unit tests', () => {
410
+ it('should be defined', () => {
411
+ expect(true).toBe(true)
412
+ })
413
+
414
+ // TODO: add unit tests for ${pascal}Service, ${pascal}Controller, etc.
415
+ })
416
+ `;
417
+ }
418
+ export function generateIntegrationTest(name) {
419
+ const pascal = toPascalCase(name);
420
+ const header = generateHeader(`src/modules/${name}/tests/${name}.integration.test.ts`);
421
+ return `${header}
422
+
423
+ import { describe, it, expect } from 'bun:test'
424
+
425
+ describe('${pascal} integration tests', () => {
426
+ it('GET /api/v1/${name} returns 200', async () => {
427
+ // TODO: set up test app and make real HTTP requests
428
+ expect(true).toBe(true)
429
+ })
430
+ })
431
+ `;
432
+ }
433
+ export function generateE2ETest(name) {
434
+ const pascal = toPascalCase(name);
435
+ const header = generateHeader(`src/modules/${name}/tests/${name}.e2e.test.ts`);
436
+ return `${header}
437
+
438
+ import { describe, it, expect } from 'bun:test'
439
+
440
+ describe('${pascal} e2e tests', () => {
441
+ it('full CRUD flow', async () => {
442
+ // TODO: implement end-to-end test
443
+ expect(true).toBe(true)
444
+ })
445
+ })
446
+ `;
447
+ }
448
+ export function generateNotification(name) {
449
+ const pascal = toPascalCase(name);
450
+ const header = generateHeader(`src/modules/${name}/notifications/${name}.notification.ts`);
451
+ return `${header}
452
+
453
+ import { defineEmail } from 'vonosan/server'
454
+
455
+ export const ${toCamelCase(name)}Notification = defineEmail({
456
+ subject: '${pascal} Notification',
457
+ html: (data: Record<string, unknown>) => \`
458
+ <h1>${pascal}</h1>
459
+ <p>\${JSON.stringify(data)}</p>
460
+ \`,
461
+ text: (data: Record<string, unknown>) => \`${pascal}: \${JSON.stringify(data)}\`,
462
+ })
463
+ `;
464
+ }
465
+ export function generateJob(name) {
466
+ const pascal = toPascalCase(name);
467
+ const header = generateHeader(`src/jobs/${name}.job.ts`);
468
+ return `${header}
469
+
470
+ import { defineJob } from 'vonosan/server'
471
+ import { Logger } from 'vonosan/server'
472
+
473
+ export const ${toCamelCase(name)}Job = defineJob({
474
+ name: '${name}',
475
+ schedule: '0 * * * *', // every hour — adjust as needed
476
+ description: '${pascal} scheduled job',
477
+ async handler() {
478
+ Logger.info('Running job: ${name}')
479
+ // TODO: implement job logic
480
+ Logger.info('Job complete: ${name}')
481
+ },
482
+ })
483
+ `;
484
+ }
485
+ export function generateEmail(name) {
486
+ const pascal = toPascalCase(name);
487
+ const header = generateHeader(`src/emails/${name}.email.ts`);
488
+ return `${header}
489
+
490
+ import { defineEmail } from 'vonosan/server'
491
+
492
+ export const ${toCamelCase(name)}Email = defineEmail({
493
+ subject: '${pascal}',
494
+ html: (data: Record<string, unknown>) => \`
495
+ <!DOCTYPE html>
496
+ <html>
497
+ <body>
498
+ <h1>${pascal}</h1>
499
+ <p>Hello, \${data.name ?? 'there'}!</p>
500
+ <!-- TODO: add email content -->
501
+ </body>
502
+ </html>
503
+ \`,
504
+ text: (data: Record<string, unknown>) => \`Hello, \${data.name ?? 'there'}!\`,
505
+ })
506
+ `;
507
+ }
508
+ export function generateHelper(name) {
509
+ const pascal = toPascalCase(name);
510
+ const header = generateHeader(`src/shared/utils/${name}.ts`);
511
+ return `${header}
512
+
513
+ /**
514
+ * ${pascal} helper utilities.
515
+ * Extracted shared logic — used in 2+ places.
516
+ */
517
+
518
+ /**
519
+ * TODO: implement ${name} helper
520
+ */
521
+ export function ${toCamelCase(name)}(input: unknown): unknown {
522
+ return input
523
+ }
524
+ `;
525
+ }
526
+ export function generateComponent(name) {
527
+ const pascal = toPascalCase(name);
528
+ const header = generateHeader(`src/modules/${name}/components/${pascal}.vue`);
529
+ return `<!--
530
+ ${header.replace(/^\/\*\*/, '').replace(/\s*\*\/$/, '').replace(/^\s*\* ?/gm, '').trim()}
531
+ -->
532
+ <script setup lang="ts">
533
+ defineProps<{
534
+ // TODO: define props
535
+ }>()
536
+ </script>
537
+
538
+ <template>
539
+ <div class="${name}">
540
+ <!-- TODO: implement ${pascal} component -->
541
+ <slot />
542
+ </div>
543
+ </template>
544
+ `;
545
+ }
546
+ //# sourceMappingURL=file-generators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-generators.js","sourceRoot":"","sources":["../../src/generators/file-generators.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * ──────────────────────────────────────────────────────────────────
3
+ * 🏢 Company Name: Bonifade Technologies
4
+ * 👨‍💻 Developer: Bowofade Oyerinde
5
+ * 🐙 GitHub: oyenet1
6
+ * 📅 Created Date: 2026-04-05
7
+ * 🔄 Updated Date: 2026-04-05
8
+ * ──────────────────────────────────────────────────────────────────
9
+ */
10
+ export interface ModuleGeneratorOptions {
11
+ /** Generate API files (routes, controller, service, dto, schema) */
12
+ api: boolean;
13
+ /** Generate frontend files (page, composable) */
14
+ frontend: boolean;
15
+ /** SaaS mode — adds deleted_at to schema */
16
+ saas: boolean;
17
+ }
18
+ export interface GeneratedFile {
19
+ path: string;
20
+ content: string;
21
+ }
22
+ /**
23
+ * Generates all module files for `name` according to `options`.
24
+ * Returns the list of files that would be written (does NOT write to disk).
25
+ * Use `writeModule()` to persist them.
26
+ */
27
+ export declare function generateModule(name: string, options: ModuleGeneratorOptions): GeneratedFile[];
28
+ /**
29
+ * Writes all generated files to disk.
30
+ * Throws if the module directory already exists (prevents overwriting).
31
+ */
32
+ export declare function writeModule(name: string, files: GeneratedFile[], projectRoot?: string): void;
33
+ //# sourceMappingURL=module-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-generator.d.ts","sourceRoot":"","sources":["../../src/generators/module-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuBH,MAAM,WAAW,sBAAsB;IACrC,oEAAoE;IACpE,GAAG,EAAE,OAAO,CAAA;IACZ,iDAAiD;IACjD,QAAQ,EAAE,OAAO,CAAA;IACjB,4CAA4C;IAC5C,IAAI,EAAE,OAAO,CAAA;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAID;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,sBAAsB,GAC9B,aAAa,EAAE,CA6BjB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,aAAa,EAAE,EACtB,WAAW,SAAgB,GAC1B,IAAI,CAeN"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * ──────────────────────────────────────────────────────────────────
3
+ * 🏢 Company Name: Bonifade Technologies
4
+ * 👨‍💻 Developer: Bowofade Oyerinde
5
+ * 🐙 GitHub: oyenet1
6
+ * 📅 Created Date: 2026-04-05
7
+ * 🔄 Updated Date: 2026-04-05
8
+ * ──────────────────────────────────────────────────────────────────
9
+ */
10
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import { generateService, generateController, generateDto, generateRoutes, generateSchema, generateResource, generatePolicy, generateScopes, generatePage, generateComposable, generateTest, generateIntegrationTest, generateE2ETest, toPascalCase, } from './file-generators.js';
13
+ // ─── Module generator ─────────────────────────────────────────────────────────
14
+ /**
15
+ * Generates all module files for `name` according to `options`.
16
+ * Returns the list of files that would be written (does NOT write to disk).
17
+ * Use `writeModule()` to persist them.
18
+ */
19
+ export function generateModule(name, options) {
20
+ const files = [];
21
+ const moduleDir = `src/modules/${name}`;
22
+ if (options.api) {
23
+ files.push({ path: `${moduleDir}/${name}.routes.ts`, content: generateRoutes(name) });
24
+ files.push({ path: `${moduleDir}/${name}.controller.ts`, content: generateController(name) });
25
+ files.push({ path: `${moduleDir}/${name}.service.ts`, content: generateService(name) });
26
+ files.push({ path: `${moduleDir}/${name}.dto.ts`, content: generateDto(name) });
27
+ files.push({ path: `${moduleDir}/${name}.schema.ts`, content: generateSchema(name, options.saas) });
28
+ files.push({ path: `${moduleDir}/${name}.resource.ts`, content: generateResource(name) });
29
+ files.push({ path: `${moduleDir}/${name}.policy.ts`, content: generatePolicy(name) });
30
+ files.push({ path: `${moduleDir}/${name}.scopes.ts`, content: generateScopes(name) });
31
+ // Tests
32
+ files.push({ path: `${moduleDir}/tests/${name}.unit.test.ts`, content: generateTest(name) });
33
+ files.push({ path: `${moduleDir}/tests/${name}.integration.test.ts`, content: generateIntegrationTest(name) });
34
+ files.push({ path: `${moduleDir}/tests/${name}.e2e.test.ts`, content: generateE2ETest(name) });
35
+ }
36
+ if (options.frontend) {
37
+ files.push({ path: `${moduleDir}/index.page.vue`, content: generatePage(name) });
38
+ files.push({
39
+ path: `${moduleDir}/composables/use${toPascalCase(name)}.ts`,
40
+ content: generateComposable(name),
41
+ });
42
+ }
43
+ return files;
44
+ }
45
+ /**
46
+ * Writes all generated files to disk.
47
+ * Throws if the module directory already exists (prevents overwriting).
48
+ */
49
+ export function writeModule(name, files, projectRoot = process.cwd()) {
50
+ const moduleDir = join(projectRoot, 'src', 'modules', name);
51
+ if (existsSync(moduleDir)) {
52
+ throw new Error(`Module "${name}" already exists at ${moduleDir}. Remove it first or choose a different name.`);
53
+ }
54
+ for (const { path: filePath, content } of files) {
55
+ const absPath = join(projectRoot, filePath);
56
+ const dir = absPath.substring(0, absPath.lastIndexOf('/'));
57
+ mkdirSync(dir, { recursive: true });
58
+ writeFileSync(absPath, content, 'utf8');
59
+ }
60
+ }
61
+ //# sourceMappingURL=module-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-generator.js","sourceRoot":"","sources":["../../src/generators/module-generator.ts"],"names":[],"mappings":"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"}