@veloxts/cli 0.4.14 → 0.6.23

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 (203) hide show
  1. package/README.md +2 -48
  2. package/dist/cli.d.ts +5 -1
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +7 -1
  5. package/dist/cli.js.map +1 -1
  6. package/dist/commands/dev.d.ts.map +1 -1
  7. package/dist/commands/dev.js +71 -7
  8. package/dist/commands/dev.js.map +1 -1
  9. package/dist/commands/introspect.d.ts +16 -0
  10. package/dist/commands/introspect.d.ts.map +1 -0
  11. package/dist/commands/introspect.js +559 -0
  12. package/dist/commands/introspect.js.map +1 -0
  13. package/dist/commands/make.d.ts.map +1 -1
  14. package/dist/commands/make.js +18 -8
  15. package/dist/commands/make.js.map +1 -1
  16. package/dist/commands/procedures.d.ts.map +1 -1
  17. package/dist/commands/procedures.js +16 -0
  18. package/dist/commands/procedures.js.map +1 -1
  19. package/dist/dev/error-parser.d.ts.map +1 -1
  20. package/dist/dev/error-parser.js +24 -8
  21. package/dist/dev/error-parser.js.map +1 -1
  22. package/dist/dev/hmr-runner.d.ts.map +1 -1
  23. package/dist/dev/hmr-runner.js +6 -1
  24. package/dist/dev/hmr-runner.js.map +1 -1
  25. package/dist/dev/index.d.ts +3 -3
  26. package/dist/dev/index.d.ts.map +1 -1
  27. package/dist/dev/index.js +3 -3
  28. package/dist/dev/index.js.map +1 -1
  29. package/dist/dev/reload-reporter.d.ts +2 -2
  30. package/dist/dev/reload-reporter.d.ts.map +1 -1
  31. package/dist/dev/reload-reporter.js +2 -2
  32. package/dist/dev/reload-reporter.js.map +1 -1
  33. package/dist/errors/catalog.d.ts +48 -0
  34. package/dist/errors/catalog.d.ts.map +1 -0
  35. package/dist/errors/catalog.js +421 -0
  36. package/dist/errors/catalog.js.map +1 -0
  37. package/dist/errors/index.d.ts +26 -0
  38. package/dist/errors/index.d.ts.map +1 -0
  39. package/dist/errors/index.js +28 -0
  40. package/dist/errors/index.js.map +1 -0
  41. package/dist/errors/velox-error.d.ts +122 -0
  42. package/dist/errors/velox-error.d.ts.map +1 -0
  43. package/dist/errors/velox-error.js +216 -0
  44. package/dist/errors/velox-error.js.map +1 -0
  45. package/dist/generators/base.d.ts.map +1 -1
  46. package/dist/generators/base.js +26 -0
  47. package/dist/generators/base.js.map +1 -1
  48. package/dist/generators/fields/__tests__/helpers.d.ts +66 -0
  49. package/dist/generators/fields/__tests__/helpers.d.ts.map +1 -0
  50. package/dist/generators/fields/__tests__/helpers.js +142 -0
  51. package/dist/generators/fields/__tests__/helpers.js.map +1 -0
  52. package/dist/generators/fields/actions.d.ts +58 -0
  53. package/dist/generators/fields/actions.d.ts.map +1 -0
  54. package/dist/generators/fields/actions.js +230 -0
  55. package/dist/generators/fields/actions.js.map +1 -0
  56. package/dist/generators/fields/display.d.ts +28 -0
  57. package/dist/generators/fields/display.d.ts.map +1 -0
  58. package/dist/generators/fields/display.js +214 -0
  59. package/dist/generators/fields/display.js.map +1 -0
  60. package/dist/generators/fields/index.d.ts +12 -0
  61. package/dist/generators/fields/index.d.ts.map +1 -0
  62. package/dist/generators/fields/index.js +12 -0
  63. package/dist/generators/fields/index.js.map +1 -0
  64. package/dist/generators/fields/prompts.d.ts +31 -0
  65. package/dist/generators/fields/prompts.d.ts.map +1 -0
  66. package/dist/generators/fields/prompts.js +366 -0
  67. package/dist/generators/fields/prompts.js.map +1 -0
  68. package/dist/generators/fields/templates.d.ts +49 -0
  69. package/dist/generators/fields/templates.d.ts.map +1 -0
  70. package/dist/generators/fields/templates.js +230 -0
  71. package/dist/generators/fields/templates.js.map +1 -0
  72. package/dist/generators/fields/types.d.ts +95 -0
  73. package/dist/generators/fields/types.d.ts.map +1 -0
  74. package/dist/generators/fields/types.js +150 -0
  75. package/dist/generators/fields/types.js.map +1 -0
  76. package/dist/generators/generators/action.d.ts +37 -0
  77. package/dist/generators/generators/action.d.ts.map +1 -0
  78. package/dist/generators/generators/action.js +109 -0
  79. package/dist/generators/generators/action.js.map +1 -0
  80. package/dist/generators/generators/exception.d.ts +38 -0
  81. package/dist/generators/generators/exception.d.ts.map +1 -0
  82. package/dist/generators/generators/exception.js +109 -0
  83. package/dist/generators/generators/exception.js.map +1 -0
  84. package/dist/generators/generators/guard.d.ts +38 -0
  85. package/dist/generators/generators/guard.d.ts.map +1 -0
  86. package/dist/generators/generators/guard.js +109 -0
  87. package/dist/generators/generators/guard.js.map +1 -0
  88. package/dist/generators/generators/index.d.ts +8 -0
  89. package/dist/generators/generators/index.d.ts.map +1 -1
  90. package/dist/generators/generators/index.js +27 -0
  91. package/dist/generators/generators/index.js.map +1 -1
  92. package/dist/generators/generators/layout.d.ts +36 -0
  93. package/dist/generators/generators/layout.d.ts.map +1 -0
  94. package/dist/generators/generators/layout.js +111 -0
  95. package/dist/generators/generators/layout.js.map +1 -0
  96. package/dist/generators/generators/middleware.d.ts +38 -0
  97. package/dist/generators/generators/middleware.d.ts.map +1 -0
  98. package/dist/generators/generators/middleware.js +109 -0
  99. package/dist/generators/generators/middleware.js.map +1 -0
  100. package/dist/generators/generators/model.d.ts +16 -4
  101. package/dist/generators/generators/model.d.ts.map +1 -1
  102. package/dist/generators/generators/model.js +88 -7
  103. package/dist/generators/generators/model.js.map +1 -1
  104. package/dist/generators/generators/page.d.ts +36 -0
  105. package/dist/generators/generators/page.d.ts.map +1 -0
  106. package/dist/generators/generators/page.js +112 -0
  107. package/dist/generators/generators/page.js.map +1 -0
  108. package/dist/generators/generators/policy.d.ts +37 -0
  109. package/dist/generators/generators/policy.d.ts.map +1 -0
  110. package/dist/generators/generators/policy.js +100 -0
  111. package/dist/generators/generators/policy.js.map +1 -0
  112. package/dist/generators/generators/resource.d.ts +42 -4
  113. package/dist/generators/generators/resource.d.ts.map +1 -1
  114. package/dist/generators/generators/resource.js +450 -9
  115. package/dist/generators/generators/resource.js.map +1 -1
  116. package/dist/generators/generators/service.d.ts +38 -0
  117. package/dist/generators/generators/service.d.ts.map +1 -0
  118. package/dist/generators/generators/service.js +109 -0
  119. package/dist/generators/generators/service.js.map +1 -0
  120. package/dist/generators/registry.d.ts.map +1 -1
  121. package/dist/generators/registry.js +10 -1
  122. package/dist/generators/registry.js.map +1 -1
  123. package/dist/generators/templates/action.d.ts +28 -0
  124. package/dist/generators/templates/action.d.ts.map +1 -0
  125. package/dist/generators/templates/action.js +359 -0
  126. package/dist/generators/templates/action.js.map +1 -0
  127. package/dist/generators/templates/exception.d.ts +26 -0
  128. package/dist/generators/templates/exception.d.ts.map +1 -0
  129. package/dist/generators/templates/exception.js +671 -0
  130. package/dist/generators/templates/exception.js.map +1 -0
  131. package/dist/generators/templates/guard.d.ts +26 -0
  132. package/dist/generators/templates/guard.d.ts.map +1 -0
  133. package/dist/generators/templates/guard.js +555 -0
  134. package/dist/generators/templates/guard.js.map +1 -0
  135. package/dist/generators/templates/layout.d.ts +28 -0
  136. package/dist/generators/templates/layout.d.ts.map +1 -0
  137. package/dist/generators/templates/layout.js +147 -0
  138. package/dist/generators/templates/layout.js.map +1 -0
  139. package/dist/generators/templates/middleware.d.ts +26 -0
  140. package/dist/generators/templates/middleware.d.ts.map +1 -0
  141. package/dist/generators/templates/middleware.js +411 -0
  142. package/dist/generators/templates/middleware.js.map +1 -0
  143. package/dist/generators/templates/model.d.ts +3 -0
  144. package/dist/generators/templates/model.d.ts.map +1 -1
  145. package/dist/generators/templates/model.js +183 -28
  146. package/dist/generators/templates/model.js.map +1 -1
  147. package/dist/generators/templates/page.d.ts +36 -0
  148. package/dist/generators/templates/page.d.ts.map +1 -0
  149. package/dist/generators/templates/page.js +147 -0
  150. package/dist/generators/templates/page.js.map +1 -0
  151. package/dist/generators/templates/policy.d.ts +24 -0
  152. package/dist/generators/templates/policy.d.ts.map +1 -0
  153. package/dist/generators/templates/policy.js +499 -0
  154. package/dist/generators/templates/policy.js.map +1 -0
  155. package/dist/generators/templates/resource.d.ts +65 -0
  156. package/dist/generators/templates/resource.d.ts.map +1 -1
  157. package/dist/generators/templates/resource.js +228 -43
  158. package/dist/generators/templates/resource.js.map +1 -1
  159. package/dist/generators/templates/service.d.ts +26 -0
  160. package/dist/generators/templates/service.d.ts.map +1 -0
  161. package/dist/generators/templates/service.js +511 -0
  162. package/dist/generators/templates/service.js.map +1 -0
  163. package/dist/generators/types.d.ts +26 -14
  164. package/dist/generators/types.d.ts.map +1 -1
  165. package/dist/generators/types.js +8 -25
  166. package/dist/generators/types.js.map +1 -1
  167. package/dist/generators/utils/ast-helpers.d.ts +147 -0
  168. package/dist/generators/utils/ast-helpers.d.ts.map +1 -0
  169. package/dist/generators/utils/ast-helpers.js +350 -0
  170. package/dist/generators/utils/ast-helpers.js.map +1 -0
  171. package/dist/generators/utils/prisma-migration.d.ts +59 -0
  172. package/dist/generators/utils/prisma-migration.d.ts.map +1 -0
  173. package/dist/generators/utils/prisma-migration.js +161 -0
  174. package/dist/generators/utils/prisma-migration.js.map +1 -0
  175. package/dist/generators/utils/prisma-schema.d.ts +97 -0
  176. package/dist/generators/utils/prisma-schema.d.ts.map +1 -0
  177. package/dist/generators/utils/prisma-schema.js +235 -0
  178. package/dist/generators/utils/prisma-schema.js.map +1 -0
  179. package/dist/generators/utils/router-integration.d.ts +70 -0
  180. package/dist/generators/utils/router-integration.d.ts.map +1 -0
  181. package/dist/generators/utils/router-integration.js +305 -0
  182. package/dist/generators/utils/router-integration.js.map +1 -0
  183. package/dist/generators/utils/snapshot.d.ts +93 -0
  184. package/dist/generators/utils/snapshot.d.ts.map +1 -0
  185. package/dist/generators/utils/snapshot.js +178 -0
  186. package/dist/generators/utils/snapshot.js.map +1 -0
  187. package/dist/index.d.ts +6 -0
  188. package/dist/index.d.ts.map +1 -1
  189. package/dist/index.js +6 -0
  190. package/dist/index.js.map +1 -1
  191. package/dist/seeding/errors.d.ts +11 -24
  192. package/dist/seeding/errors.d.ts.map +1 -1
  193. package/dist/seeding/errors.js +11 -50
  194. package/dist/seeding/errors.js.map +1 -1
  195. package/dist/utils/paths.d.ts +19 -0
  196. package/dist/utils/paths.d.ts.map +1 -1
  197. package/dist/utils/paths.js +45 -0
  198. package/dist/utils/paths.js.map +1 -1
  199. package/dist/utils/schema-patterns.d.ts +26 -0
  200. package/dist/utils/schema-patterns.d.ts.map +1 -0
  201. package/dist/utils/schema-patterns.js +40 -0
  202. package/dist/utils/schema-patterns.js.map +1 -0
  203. package/package.json +12 -10
@@ -0,0 +1,499 @@
1
+ /**
2
+ * Policy Template
3
+ *
4
+ * Generates authorization policy files for VeloxTS applications.
5
+ */
6
+ // ============================================================================
7
+ // Path Helpers
8
+ // ============================================================================
9
+ /**
10
+ * Get the path for a policy file
11
+ */
12
+ export function getPolicyPath(entityName, _project) {
13
+ return `src/policies/${entityName.toLowerCase()}.ts`;
14
+ }
15
+ // ============================================================================
16
+ // Templates
17
+ // ============================================================================
18
+ /**
19
+ * Generate CRUD policy
20
+ */
21
+ function generateCrudPolicy(ctx) {
22
+ const { entity, options } = ctx;
23
+ const softDeleteMethods = options.softDelete
24
+ ? `
25
+ /**
26
+ * Can user restore this ${entity.humanReadable}?
27
+ */
28
+ async restore(user: User, ${entity.camel}: ${entity.pascal}): Promise<boolean> {
29
+ // Only admins can restore
30
+ return user.role === 'admin';
31
+ }
32
+
33
+ /**
34
+ * Can user force delete this ${entity.humanReadable}?
35
+ */
36
+ async forceDelete(user: User, ${entity.camel}: ${entity.pascal}): Promise<boolean> {
37
+ // Only admins can force delete
38
+ return user.role === 'admin';
39
+ }
40
+ `
41
+ : '';
42
+ return `/**
43
+ * ${entity.pascal} Policy
44
+ *
45
+ * Authorization rules for ${entity.humanReadable} operations.
46
+ */
47
+
48
+ import type { BaseContext } from '@veloxts/core';
49
+
50
+ // ============================================================================
51
+ // Types
52
+ // ============================================================================
53
+
54
+ interface User {
55
+ id: string;
56
+ role: string;
57
+ permissions?: string[];
58
+ }
59
+
60
+ interface ${entity.pascal} {
61
+ id: string;
62
+ userId: string;
63
+ // TODO: Add more fields
64
+ }
65
+
66
+ // ============================================================================
67
+ // Policy Class
68
+ // ============================================================================
69
+
70
+ /**
71
+ * ${entity.pascal} authorization policy
72
+ *
73
+ * Centralizes authorization logic for ${entity.humanReadable} resources.
74
+ *
75
+ * @example
76
+ * const policy = new ${entity.pascal}Policy();
77
+ * if (await policy.update(user, ${entity.camel})) {
78
+ * // Allow update
79
+ * }
80
+ */
81
+ export class ${entity.pascal}Policy {
82
+ /**
83
+ * Can user view any ${entity.humanReadable}?
84
+ */
85
+ async viewAny(user: User): Promise<boolean> {
86
+ // All authenticated users can list
87
+ return true;
88
+ }
89
+
90
+ /**
91
+ * Can user view this ${entity.humanReadable}?
92
+ */
93
+ async view(user: User, ${entity.camel}: ${entity.pascal}): Promise<boolean> {
94
+ // Owner or admin can view
95
+ return ${entity.camel}.userId === user.id || user.role === 'admin';
96
+ }
97
+
98
+ /**
99
+ * Can user create ${entity.humanReadable}?
100
+ */
101
+ async create(user: User): Promise<boolean> {
102
+ // All authenticated users can create
103
+ return true;
104
+ }
105
+
106
+ /**
107
+ * Can user update this ${entity.humanReadable}?
108
+ */
109
+ async update(user: User, ${entity.camel}: ${entity.pascal}): Promise<boolean> {
110
+ // Only owner or admin can update
111
+ return ${entity.camel}.userId === user.id || user.role === 'admin';
112
+ }
113
+
114
+ /**
115
+ * Can user delete this ${entity.humanReadable}?
116
+ */
117
+ async delete(user: User, ${entity.camel}: ${entity.pascal}): Promise<boolean> {
118
+ // Only owner or admin can delete
119
+ return ${entity.camel}.userId === user.id || user.role === 'admin';
120
+ }
121
+ ${softDeleteMethods}}
122
+
123
+ // ============================================================================
124
+ // Policy Instance
125
+ // ============================================================================
126
+
127
+ /**
128
+ * Singleton policy instance
129
+ */
130
+ export const ${entity.camel}Policy = new ${entity.pascal}Policy();
131
+
132
+ // ============================================================================
133
+ // Guard Integration
134
+ // ============================================================================
135
+
136
+ /**
137
+ * Create a guard from a policy method
138
+ *
139
+ * @example
140
+ * procedure.guard(policyGuard('update')).mutation(...)
141
+ */
142
+ export function ${entity.camel}PolicyGuard(
143
+ action: keyof ${entity.pascal}Policy
144
+ ) {
145
+ return async (ctx: BaseContext, input: unknown) => {
146
+ if (!ctx.user) return false;
147
+
148
+ const policy = new ${entity.pascal}Policy();
149
+ const method = policy[action] as (user: User, resource?: ${entity.pascal}) => Promise<boolean>;
150
+
151
+ // For methods that require a resource
152
+ if (action === 'view' || action === 'update' || action === 'delete') {
153
+ // TODO: Fetch the resource
154
+ // const ${entity.camel} = await ctx.db.${entity.camel}.findUnique({ where: { id: (input as { id: string }).id } });
155
+ // return method.call(policy, ctx.user as User, ${entity.camel});
156
+ throw new Error('Resource fetch not implemented');
157
+ }
158
+
159
+ // For methods that don't require a resource
160
+ return method.call(policy, ctx.user as User);
161
+ };
162
+ }
163
+ `;
164
+ }
165
+ /**
166
+ * Generate resource-based policy
167
+ */
168
+ function generateResourcePolicy(ctx) {
169
+ const { entity } = ctx;
170
+ return `/**
171
+ * ${entity.pascal} Resource Policy
172
+ *
173
+ * Attribute-based access control for ${entity.humanReadable} resources.
174
+ */
175
+
176
+ import type { BaseContext } from '@veloxts/core';
177
+
178
+ // ============================================================================
179
+ // Types
180
+ // ============================================================================
181
+
182
+ interface User {
183
+ id: string;
184
+ role: string;
185
+ teamId?: string;
186
+ permissions?: string[];
187
+ }
188
+
189
+ interface ${entity.pascal} {
190
+ id: string;
191
+ userId: string;
192
+ teamId?: string;
193
+ visibility: 'public' | 'private' | 'team';
194
+ status: 'draft' | 'published' | 'archived';
195
+ }
196
+
197
+ type Action = 'view' | 'create' | 'update' | 'delete' | 'publish' | 'archive';
198
+
199
+ // ============================================================================
200
+ // Policy Definition
201
+ // ============================================================================
202
+
203
+ /**
204
+ * Policy rules for ${entity.humanReadable}
205
+ */
206
+ interface PolicyRule {
207
+ /** Actions this rule applies to */
208
+ actions: Action[];
209
+ /** Condition that must be true */
210
+ condition: (user: User, resource?: ${entity.pascal}) => boolean;
211
+ /** Description for debugging */
212
+ description: string;
213
+ }
214
+
215
+ const ${entity.camel}Rules: PolicyRule[] = [
216
+ // Admin can do anything
217
+ {
218
+ actions: ['view', 'create', 'update', 'delete', 'publish', 'archive'],
219
+ condition: (user) => user.role === 'admin',
220
+ description: 'Admins have full access',
221
+ },
222
+
223
+ // Owners can manage their own resources
224
+ {
225
+ actions: ['view', 'update', 'delete'],
226
+ condition: (user, resource) => resource?.userId === user.id,
227
+ description: 'Owners can manage their resources',
228
+ },
229
+
230
+ // Team members can view team resources
231
+ {
232
+ actions: ['view'],
233
+ condition: (user, resource) =>
234
+ resource?.visibility === 'team' && resource?.teamId === user.teamId,
235
+ description: 'Team members can view team resources',
236
+ },
237
+
238
+ // Anyone can view public resources
239
+ {
240
+ actions: ['view'],
241
+ condition: (_, resource) =>
242
+ resource?.visibility === 'public' && resource?.status === 'published',
243
+ description: 'Public published resources are viewable by all',
244
+ },
245
+
246
+ // Authenticated users can create
247
+ {
248
+ actions: ['create'],
249
+ condition: (user) => !!user.id,
250
+ description: 'Authenticated users can create resources',
251
+ },
252
+
253
+ // Only owners can publish
254
+ {
255
+ actions: ['publish'],
256
+ condition: (user, resource) =>
257
+ resource?.userId === user.id && resource?.status === 'draft',
258
+ description: 'Owners can publish draft resources',
259
+ },
260
+ ];
261
+
262
+ // ============================================================================
263
+ // Policy Evaluation
264
+ // ============================================================================
265
+
266
+ /**
267
+ * Check if user can perform action on ${entity.humanReadable}
268
+ */
269
+ export function can${entity.pascal}(
270
+ user: User,
271
+ action: Action,
272
+ resource?: ${entity.pascal}
273
+ ): boolean {
274
+ for (const rule of ${entity.camel}Rules) {
275
+ if (rule.actions.includes(action) && rule.condition(user, resource)) {
276
+ return true;
277
+ }
278
+ }
279
+ return false;
280
+ }
281
+
282
+ /**
283
+ * Get all allowed actions for user on ${entity.humanReadable}
284
+ */
285
+ export function allowed${entity.pascal}Actions(
286
+ user: User,
287
+ resource?: ${entity.pascal}
288
+ ): Action[] {
289
+ const allActions: Action[] = ['view', 'create', 'update', 'delete', 'publish', 'archive'];
290
+ return allActions.filter((action) => can${entity.pascal}(user, action, resource));
291
+ }
292
+
293
+ /**
294
+ * Policy guard for procedures
295
+ */
296
+ export function ${entity.camel}PolicyGuard(action: Action) {
297
+ return async (ctx: BaseContext, input: unknown) => {
298
+ if (!ctx.user) return false;
299
+
300
+ // For resource-specific actions, fetch the resource
301
+ if (action !== 'create') {
302
+ // TODO: Fetch resource and check
303
+ // const ${entity.camel} = await ctx.db.${entity.camel}.findUnique({ where: { id: (input as { id: string }).id } });
304
+ // return can${entity.pascal}(ctx.user as User, action, ${entity.camel});
305
+ }
306
+
307
+ return can${entity.pascal}(ctx.user as User, action);
308
+ };
309
+ }
310
+
311
+ /**
312
+ * Assert user can perform action, throw if not
313
+ */
314
+ export function assert${entity.pascal}(
315
+ user: User,
316
+ action: Action,
317
+ resource?: ${entity.pascal}
318
+ ): void {
319
+ if (!can${entity.pascal}(user, action, resource)) {
320
+ throw new Error(\`Unauthorized: cannot \${action} ${entity.humanReadable}\`);
321
+ }
322
+ }
323
+ `;
324
+ }
325
+ /**
326
+ * Generate simple policy template
327
+ */
328
+ function generateSimplePolicy(ctx) {
329
+ const { entity } = ctx;
330
+ return `/**
331
+ * ${entity.pascal} Policy
332
+ *
333
+ * Authorization rules for ${entity.humanReadable} operations.
334
+ */
335
+
336
+ import type { BaseContext } from '@veloxts/core';
337
+
338
+ // ============================================================================
339
+ // Types
340
+ // ============================================================================
341
+
342
+ interface User {
343
+ id: string;
344
+ role: string;
345
+ permissions?: string[];
346
+ }
347
+
348
+ interface ${entity.pascal} {
349
+ id: string;
350
+ userId: string;
351
+ // TODO: Add your ${entity.humanReadable} fields
352
+ }
353
+
354
+ // ============================================================================
355
+ // Policy Functions
356
+ // ============================================================================
357
+
358
+ /**
359
+ * Can user view ${entity.humanReadable}?
360
+ */
361
+ export function canView${entity.pascal}(user: User, ${entity.camel}: ${entity.pascal}): boolean {
362
+ // TODO: Implement view authorization
363
+ return ${entity.camel}.userId === user.id || user.role === 'admin';
364
+ }
365
+
366
+ /**
367
+ * Can user create ${entity.humanReadable}?
368
+ */
369
+ export function canCreate${entity.pascal}(user: User): boolean {
370
+ // TODO: Implement create authorization
371
+ return true;
372
+ }
373
+
374
+ /**
375
+ * Can user update ${entity.humanReadable}?
376
+ */
377
+ export function canUpdate${entity.pascal}(user: User, ${entity.camel}: ${entity.pascal}): boolean {
378
+ // TODO: Implement update authorization
379
+ return ${entity.camel}.userId === user.id || user.role === 'admin';
380
+ }
381
+
382
+ /**
383
+ * Can user delete ${entity.humanReadable}?
384
+ */
385
+ export function canDelete${entity.pascal}(user: User, ${entity.camel}: ${entity.pascal}): boolean {
386
+ // TODO: Implement delete authorization
387
+ return ${entity.camel}.userId === user.id || user.role === 'admin';
388
+ }
389
+
390
+ // ============================================================================
391
+ // Guard Integration
392
+ // ============================================================================
393
+
394
+ /**
395
+ * Policy guard factory
396
+ *
397
+ * Creates guards from policy functions for use with procedures.
398
+ *
399
+ * @example
400
+ * procedure.guard(${entity.camel}Guard('update')).mutation(...)
401
+ */
402
+ export function ${entity.camel}Guard(action: 'view' | 'create' | 'update' | 'delete') {
403
+ return async (ctx: BaseContext, input: unknown) => {
404
+ if (!ctx.user) return false;
405
+
406
+ const user = ctx.user as User;
407
+
408
+ switch (action) {
409
+ case 'create':
410
+ return canCreate${entity.pascal}(user);
411
+
412
+ case 'view':
413
+ case 'update':
414
+ case 'delete': {
415
+ // TODO: Fetch the ${entity.humanReadable} from database
416
+ // const ${entity.camel} = await ctx.db.${entity.camel}.findUnique({
417
+ // where: { id: (input as { id: string }).id }
418
+ // });
419
+ // if (!${entity.camel}) return false;
420
+
421
+ // Placeholder - implement resource fetching
422
+ const ${entity.camel} = input as ${entity.pascal};
423
+
424
+ if (action === 'view') return canView${entity.pascal}(user, ${entity.camel});
425
+ if (action === 'update') return canUpdate${entity.pascal}(user, ${entity.camel});
426
+ if (action === 'delete') return canDelete${entity.pascal}(user, ${entity.camel});
427
+ return false;
428
+ }
429
+
430
+ default:
431
+ return false;
432
+ }
433
+ };
434
+ }
435
+
436
+ /**
437
+ * Assert policy, throw if unauthorized
438
+ */
439
+ export function authorize${entity.pascal}(
440
+ action: 'view' | 'create' | 'update' | 'delete',
441
+ user: User,
442
+ ${entity.camel}?: ${entity.pascal}
443
+ ): void {
444
+ let allowed = false;
445
+
446
+ switch (action) {
447
+ case 'create':
448
+ allowed = canCreate${entity.pascal}(user);
449
+ break;
450
+ case 'view':
451
+ allowed = ${entity.camel} ? canView${entity.pascal}(user, ${entity.camel}) : false;
452
+ break;
453
+ case 'update':
454
+ allowed = ${entity.camel} ? canUpdate${entity.pascal}(user, ${entity.camel}) : false;
455
+ break;
456
+ case 'delete':
457
+ allowed = ${entity.camel} ? canDelete${entity.pascal}(user, ${entity.camel}) : false;
458
+ break;
459
+ }
460
+
461
+ if (!allowed) {
462
+ throw new Error(\`Unauthorized: cannot \${action} ${entity.humanReadable}\`);
463
+ }
464
+ }
465
+ `;
466
+ }
467
+ // ============================================================================
468
+ // Main Template
469
+ // ============================================================================
470
+ /**
471
+ * Policy template function
472
+ */
473
+ export const policyTemplate = (ctx) => {
474
+ if (ctx.options.crud) {
475
+ return generateCrudPolicy(ctx);
476
+ }
477
+ if (ctx.options.resource) {
478
+ return generateResourcePolicy(ctx);
479
+ }
480
+ return generateSimplePolicy(ctx);
481
+ };
482
+ // ============================================================================
483
+ // Post-generation Instructions
484
+ // ============================================================================
485
+ export function getPolicyInstructions(entityName, options) {
486
+ const lines = [`Your ${entityName} policy has been created.`, '', 'Next steps:'];
487
+ lines.push(' 1. Update the policy functions with your authorization logic');
488
+ lines.push(' 2. Import and use in your procedures:');
489
+ lines.push(` import { ${entityName}Guard } from '@/policies/${entityName.toLowerCase()}';`);
490
+ lines.push(` procedure.guard(${entityName}Guard('update')).mutation(...)`);
491
+ if (options.crud) {
492
+ lines.push(' 3. Implement resource fetching in the guard');
493
+ }
494
+ else if (options.resource) {
495
+ lines.push(' 3. Customize the policy rules for your use case');
496
+ }
497
+ return lines.join('\n');
498
+ }
499
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/generators/templates/policy.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@
4
4
  * Generates a complete resource with model, schema, procedures, and tests.
5
5
  * This is the "full stack" generator for quickly scaffolding new entities.
6
6
  */
7
+ import type { FieldDefinition, FieldTypeInfo } from '../fields/types.js';
7
8
  import type { GeneratedFile, TemplateContext } from '../types.js';
8
9
  export interface ResourceOptions {
9
10
  /** Include CRUD operations */
@@ -22,7 +23,71 @@ export interface ResourceOptions {
22
23
  skipSchema: boolean;
23
24
  /** Skip procedure generation */
24
25
  skipProcedure: boolean;
26
+ /** Custom field definitions */
27
+ fields?: FieldDefinition[];
25
28
  }
29
+ /**
30
+ * Get field type info by type
31
+ */
32
+ export declare function getFieldTypeInfo(type: FieldDefinition['type']): FieldTypeInfo | undefined;
33
+ /** Database type for Prisma native type support */
34
+ export type DatabaseType = 'sqlite' | 'postgresql' | 'mysql';
35
+ /**
36
+ * Convert a field definition to Prisma field line
37
+ *
38
+ * @param field - Field definition to convert
39
+ * @param database - Optional database type for native type modifiers (default: 'sqlite')
40
+ */
41
+ export declare function fieldToPrisma(field: FieldDefinition, database?: DatabaseType): string;
42
+ /**
43
+ * Format default value for Prisma
44
+ *
45
+ * Different types require different formatting:
46
+ * - Strings: quoted ("value")
47
+ * - Numbers: unquoted (123, 3.14)
48
+ * - Booleans: unquoted (true, false)
49
+ * - Enums: unquoted (DRAFT, ACTIVE)
50
+ * - DateTime: function call (now())
51
+ * - JSON: not supported for defaults
52
+ */
53
+ export declare function formatPrismaDefault(type: FieldDefinition['type'], value: string): string;
54
+ /**
55
+ * Convert a field definition to Zod schema field
56
+ */
57
+ export declare function fieldToZod(field: FieldDefinition): string;
58
+ /**
59
+ * Generate Prisma enum definitions
60
+ */
61
+ export declare function generatePrismaEnums(fields: FieldDefinition[]): string;
62
+ /**
63
+ * Structured enum definition for injection
64
+ */
65
+ export interface InjectableEnumDef {
66
+ /** Enum name (PascalCase) */
67
+ readonly name: string;
68
+ /** Full enum content (including `enum Name { ... }`) */
69
+ readonly content: string;
70
+ }
71
+ /**
72
+ * Result of generating injectable Prisma content
73
+ */
74
+ export interface InjectablePrismaContent {
75
+ /** Full model definition (for injection into schema.prisma) */
76
+ readonly modelContent: string;
77
+ /** Model name (PascalCase) */
78
+ readonly modelName: string;
79
+ /** Structured enum definitions (for injection before model) */
80
+ readonly enums: InjectableEnumDef[];
81
+ }
82
+ /**
83
+ * Generate injectable Prisma content (model + enums without comments)
84
+ *
85
+ * This content can be directly injected into schema.prisma
86
+ */
87
+ export declare function generateInjectablePrismaContent(entity: {
88
+ pascal: string;
89
+ camel: string;
90
+ }, options: ResourceOptions, database?: DatabaseType): InjectablePrismaContent;
26
91
  /**
27
92
  * Generate all files for a resource
28
93
  */
@@ -1 +1 @@
1
- {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../../src/generators/templates/resource.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAMlE,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB,kCAAkC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,+BAA+B;IAC/B,UAAU,EAAE,OAAO,CAAC;IACpB,0BAA0B;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,6BAA6B;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,gCAAgC;IAChC,aAAa,EAAE,OAAO,CAAC;CACxB;AA2eD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,CAAC,eAAe,CAAC,GAAG,aAAa,EAAE,CAqC5F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM,CAsD5F"}
1
+ {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../../src/generators/templates/resource.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAMlE,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB,kCAAkC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,+BAA+B;IAC/B,UAAU,EAAE,OAAO,CAAC;IACpB,0BAA0B;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,6BAA6B;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,gCAAgC;IAChC,aAAa,EAAE,OAAO,CAAC;IACvB,+BAA+B;IAC/B,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;CAC5B;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,GAAG,aAAa,GAAG,SAAS,CAEzF;AAED,mDAAmD;AACnD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,GAAG,OAAO,CAAC;AAE7D;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,GAAE,YAAuB,GAAG,MAAM,CAqC/F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAuBxF;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAkBzD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAYrE;AAMD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,+DAA+D;IAC/D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,8BAA8B;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,iBAAiB,EAAE,CAAC;CACrC;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACzC,OAAO,EAAE,eAAe,EACxB,QAAQ,GAAE,YAAuB,GAChC,uBAAuB,CAwDzB;AAkeD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,CAAC,eAAe,CAAC,GAAG,aAAa,EAAE,CAqC5F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM,CA0E5F"}