@rhino-dev/rhino-nestjs 0.2.5

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 (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +427 -0
  3. package/dist/blueprint/blueprint-parser.d.ts +130 -0
  4. package/dist/blueprint/blueprint-parser.js +276 -0
  5. package/dist/blueprint/blueprint-parser.js.map +1 -0
  6. package/dist/blueprint/blueprint-runner.d.ts +51 -0
  7. package/dist/blueprint/blueprint-runner.js +238 -0
  8. package/dist/blueprint/blueprint-runner.js.map +1 -0
  9. package/dist/blueprint/blueprint-validator.d.ts +19 -0
  10. package/dist/blueprint/blueprint-validator.js +163 -0
  11. package/dist/blueprint/blueprint-validator.js.map +1 -0
  12. package/dist/blueprint/generators/policy-generator.d.ts +40 -0
  13. package/dist/blueprint/generators/policy-generator.js +157 -0
  14. package/dist/blueprint/generators/policy-generator.js.map +1 -0
  15. package/dist/blueprint/generators/prisma-schema-generator.d.ts +43 -0
  16. package/dist/blueprint/generators/prisma-schema-generator.js +197 -0
  17. package/dist/blueprint/generators/prisma-schema-generator.js.map +1 -0
  18. package/dist/blueprint/generators/resource-definition-generator.d.ts +52 -0
  19. package/dist/blueprint/generators/resource-definition-generator.js +229 -0
  20. package/dist/blueprint/generators/resource-definition-generator.js.map +1 -0
  21. package/dist/blueprint/generators/seeder-generator.d.ts +21 -0
  22. package/dist/blueprint/generators/seeder-generator.js +135 -0
  23. package/dist/blueprint/generators/seeder-generator.js.map +1 -0
  24. package/dist/blueprint/generators/test-generator.d.ts +28 -0
  25. package/dist/blueprint/generators/test-generator.js +275 -0
  26. package/dist/blueprint/generators/test-generator.js.map +1 -0
  27. package/dist/blueprint/manifest-manager.d.ts +58 -0
  28. package/dist/blueprint/manifest-manager.js +137 -0
  29. package/dist/blueprint/manifest-manager.js.map +1 -0
  30. package/dist/cli/commands/blueprint.command.d.ts +16 -0
  31. package/dist/cli/commands/blueprint.command.js +35 -0
  32. package/dist/cli/commands/blueprint.command.js.map +1 -0
  33. package/dist/cli/commands/export-postman.command.d.ts +5 -0
  34. package/dist/cli/commands/export-postman.command.js +39 -0
  35. package/dist/cli/commands/export-postman.command.js.map +1 -0
  36. package/dist/cli/commands/export-types.command.d.ts +4 -0
  37. package/dist/cli/commands/export-types.command.js +36 -0
  38. package/dist/cli/commands/export-types.command.js.map +1 -0
  39. package/dist/cli/commands/generate.command.d.ts +6 -0
  40. package/dist/cli/commands/generate.command.js +212 -0
  41. package/dist/cli/commands/generate.command.js.map +1 -0
  42. package/dist/cli/commands/install.command.d.ts +8 -0
  43. package/dist/cli/commands/install.command.js +205 -0
  44. package/dist/cli/commands/install.command.js.map +1 -0
  45. package/dist/cli/index.d.ts +17 -0
  46. package/dist/cli/index.js +123 -0
  47. package/dist/cli/index.js.map +1 -0
  48. package/dist/cli/utils/io.d.ts +12 -0
  49. package/dist/cli/utils/io.js +74 -0
  50. package/dist/cli/utils/io.js.map +1 -0
  51. package/dist/cli/utils/prompt.d.ts +12 -0
  52. package/dist/cli/utils/prompt.js +78 -0
  53. package/dist/cli/utils/prompt.js.map +1 -0
  54. package/dist/constants/tokens.d.ts +3 -0
  55. package/dist/constants/tokens.js +7 -0
  56. package/dist/constants/tokens.js.map +1 -0
  57. package/dist/controllers/auth.controller.d.ts +59 -0
  58. package/dist/controllers/auth.controller.js +121 -0
  59. package/dist/controllers/auth.controller.js.map +1 -0
  60. package/dist/controllers/global.controller.d.ts +44 -0
  61. package/dist/controllers/global.controller.js +357 -0
  62. package/dist/controllers/global.controller.js.map +1 -0
  63. package/dist/controllers/invitation.controller.d.ts +30 -0
  64. package/dist/controllers/invitation.controller.js +111 -0
  65. package/dist/controllers/invitation.controller.js.map +1 -0
  66. package/dist/controllers/nested.controller.d.ts +12 -0
  67. package/dist/controllers/nested.controller.js +69 -0
  68. package/dist/controllers/nested.controller.js.map +1 -0
  69. package/dist/decorators/index.d.ts +33 -0
  70. package/dist/decorators/index.js +79 -0
  71. package/dist/decorators/index.js.map +1 -0
  72. package/dist/errors/rhino-exception.d.ts +24 -0
  73. package/dist/errors/rhino-exception.js +47 -0
  74. package/dist/errors/rhino-exception.js.map +1 -0
  75. package/dist/exporters/postman-exporter.d.ts +21 -0
  76. package/dist/exporters/postman-exporter.js +396 -0
  77. package/dist/exporters/postman-exporter.js.map +1 -0
  78. package/dist/exporters/typescript-exporter.d.ts +23 -0
  79. package/dist/exporters/typescript-exporter.js +129 -0
  80. package/dist/exporters/typescript-exporter.js.map +1 -0
  81. package/dist/guards/jwt-auth.guard.d.ts +16 -0
  82. package/dist/guards/jwt-auth.guard.js +61 -0
  83. package/dist/guards/jwt-auth.guard.js.map +1 -0
  84. package/dist/guards/resource-policy.guard.d.ts +12 -0
  85. package/dist/guards/resource-policy.guard.js +111 -0
  86. package/dist/guards/resource-policy.guard.js.map +1 -0
  87. package/dist/index.d.ts +60 -0
  88. package/dist/index.js +171 -0
  89. package/dist/index.js.map +1 -0
  90. package/dist/interceptors/hidden-columns.interceptor.d.ts +18 -0
  91. package/dist/interceptors/hidden-columns.interceptor.js +66 -0
  92. package/dist/interceptors/hidden-columns.interceptor.js.map +1 -0
  93. package/dist/interceptors/response.interceptor.d.ts +19 -0
  94. package/dist/interceptors/response.interceptor.js +47 -0
  95. package/dist/interceptors/response.interceptor.js.map +1 -0
  96. package/dist/interfaces/rhino-config.interface.d.ts +103 -0
  97. package/dist/interfaces/rhino-config.interface.js +3 -0
  98. package/dist/interfaces/rhino-config.interface.js.map +1 -0
  99. package/dist/interfaces/rhino-request.interface.d.ts +12 -0
  100. package/dist/interfaces/rhino-request.interface.js +3 -0
  101. package/dist/interfaces/rhino-request.interface.js.map +1 -0
  102. package/dist/middleware/resolve-organization.middleware.d.ts +15 -0
  103. package/dist/middleware/resolve-organization.middleware.js +38 -0
  104. package/dist/middleware/resolve-organization.middleware.js.map +1 -0
  105. package/dist/middleware/route-group.middleware.d.ts +17 -0
  106. package/dist/middleware/route-group.middleware.js +60 -0
  107. package/dist/middleware/route-group.middleware.js.map +1 -0
  108. package/dist/middleware/tenant-route-rewrite.d.ts +76 -0
  109. package/dist/middleware/tenant-route-rewrite.js +124 -0
  110. package/dist/middleware/tenant-route-rewrite.js.map +1 -0
  111. package/dist/policies/resource-policy.d.ts +25 -0
  112. package/dist/policies/resource-policy.js +77 -0
  113. package/dist/policies/resource-policy.js.map +1 -0
  114. package/dist/prisma/prisma-soft-delete.extension.d.ts +16 -0
  115. package/dist/prisma/prisma-soft-delete.extension.js +57 -0
  116. package/dist/prisma/prisma-soft-delete.extension.js.map +1 -0
  117. package/dist/prisma/prisma-uuid.extension.d.ts +9 -0
  118. package/dist/prisma/prisma-uuid.extension.js +28 -0
  119. package/dist/prisma/prisma-uuid.extension.js.map +1 -0
  120. package/dist/prisma/prisma.service.d.ts +38 -0
  121. package/dist/prisma/prisma.service.js +100 -0
  122. package/dist/prisma/prisma.service.js.map +1 -0
  123. package/dist/rhino.config.d.ts +43 -0
  124. package/dist/rhino.config.js +130 -0
  125. package/dist/rhino.config.js.map +1 -0
  126. package/dist/rhino.module.d.ts +61 -0
  127. package/dist/rhino.module.js +268 -0
  128. package/dist/rhino.module.js.map +1 -0
  129. package/dist/services/audit.service.d.ts +35 -0
  130. package/dist/services/audit.service.js +92 -0
  131. package/dist/services/audit.service.js.map +1 -0
  132. package/dist/services/auth.service.d.ts +33 -0
  133. package/dist/services/auth.service.js +157 -0
  134. package/dist/services/auth.service.js.map +1 -0
  135. package/dist/services/invitation.service.d.ts +37 -0
  136. package/dist/services/invitation.service.js +143 -0
  137. package/dist/services/invitation.service.js.map +1 -0
  138. package/dist/services/nested.service.d.ts +34 -0
  139. package/dist/services/nested.service.js +163 -0
  140. package/dist/services/nested.service.js.map +1 -0
  141. package/dist/services/organization.service.d.ts +13 -0
  142. package/dist/services/organization.service.js +60 -0
  143. package/dist/services/organization.service.js.map +1 -0
  144. package/dist/services/query-builder.service.d.ts +31 -0
  145. package/dist/services/query-builder.service.js +151 -0
  146. package/dist/services/query-builder.service.js.map +1 -0
  147. package/dist/services/resource.service.d.ts +38 -0
  148. package/dist/services/resource.service.js +230 -0
  149. package/dist/services/resource.service.js.map +1 -0
  150. package/dist/services/route-registration.service.d.ts +40 -0
  151. package/dist/services/route-registration.service.js +68 -0
  152. package/dist/services/route-registration.service.js.map +1 -0
  153. package/dist/services/scope.service.d.ts +16 -0
  154. package/dist/services/scope.service.js +32 -0
  155. package/dist/services/scope.service.js.map +1 -0
  156. package/dist/services/serializer.service.d.ts +36 -0
  157. package/dist/services/serializer.service.js +90 -0
  158. package/dist/services/serializer.service.js.map +1 -0
  159. package/dist/services/validation.service.d.ts +50 -0
  160. package/dist/services/validation.service.js +203 -0
  161. package/dist/services/validation.service.js.map +1 -0
  162. package/dist/tsconfig.build.tsbuildinfo +1 -0
  163. package/dist/utils/fk-chain-walker.d.ts +30 -0
  164. package/dist/utils/fk-chain-walker.js +23 -0
  165. package/dist/utils/fk-chain-walker.js.map +1 -0
  166. package/dist/utils/format.d.ts +7 -0
  167. package/dist/utils/format.js +28 -0
  168. package/dist/utils/format.js.map +1 -0
  169. package/dist/utils/model-builder.d.ts +64 -0
  170. package/dist/utils/model-builder.js +67 -0
  171. package/dist/utils/model-builder.js.map +1 -0
  172. package/dist/utils/permission-matcher.d.ts +46 -0
  173. package/dist/utils/permission-matcher.js +120 -0
  174. package/dist/utils/permission-matcher.js.map +1 -0
  175. package/dist/utils/scope-discovery.d.ts +34 -0
  176. package/dist/utils/scope-discovery.js +102 -0
  177. package/dist/utils/scope-discovery.js.map +1 -0
  178. package/package.json +64 -0
  179. package/stubs/skills/rhino-audit.md +184 -0
  180. package/stubs/skills/rhino-bugfix.md +117 -0
  181. package/stubs/skills/rhino-deploy.md +5 -0
  182. package/stubs/skills/rhino-docs.md +147 -0
  183. package/stubs/skills/rhino-feature.md +146 -0
  184. package/stubs/skills/rhino-migrate.md +181 -0
  185. package/stubs/skills/rhino-model.md +180 -0
  186. package/stubs/skills/rhino-plan.md +5 -0
  187. package/stubs/skills/rhino-policy.md +183 -0
  188. package/stubs/skills/rhino-refactor.md +147 -0
  189. package/stubs/skills/rhino-review.md +113 -0
  190. package/stubs/skills/rhino-scope.md +140 -0
  191. package/stubs/skills/rhino-test.md +233 -0
@@ -0,0 +1,276 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.BlueprintParser = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const crypto = __importStar(require("crypto"));
39
+ const yaml = __importStar(require("js-yaml"));
40
+ // ---------------------------------------------------------------------------
41
+ // Parser
42
+ // ---------------------------------------------------------------------------
43
+ class BlueprintParser {
44
+ /**
45
+ * Parse a model blueprint YAML file into a normalised Blueprint object.
46
+ * Throws on missing/invalid structure.
47
+ */
48
+ parseModel(filePath) {
49
+ const raw = this.loadYaml(filePath);
50
+ if (!raw['model']) {
51
+ throw new Error(`Invalid blueprint file: missing 'model' key in ${filePath}`);
52
+ }
53
+ const modelName = String(raw['model']);
54
+ const slug = raw['slug'] ?? this.toSlug(modelName);
55
+ const tableName = raw['table'] ?? slug;
56
+ return {
57
+ model: modelName,
58
+ slug,
59
+ table: tableName,
60
+ options: this.normalizeOptions(raw['options'] ?? {}),
61
+ columns: this.normalizeColumns(raw['columns'] ?? {}),
62
+ relationships: this.normalizeRelationships(raw['relationships'] ?? {}),
63
+ permissions: this.normalizePermissions(raw['permissions'] ?? {}),
64
+ fk_constraints: this.normalizeFkConstraints(raw['fk_constraints'] ?? []),
65
+ source_file: require('path').basename(filePath),
66
+ };
67
+ }
68
+ /**
69
+ * Compute SHA-256 hash of a file's content for manifest tracking.
70
+ */
71
+ computeFileHash(filePath) {
72
+ const content = fs.readFileSync(filePath, 'utf8');
73
+ return crypto.createHash('sha256').update(content).digest('hex');
74
+ }
75
+ // -------------------------------------------------------------------------
76
+ // Private helpers
77
+ // -------------------------------------------------------------------------
78
+ loadYaml(filePath) {
79
+ if (!fs.existsSync(filePath)) {
80
+ throw new Error(`Blueprint file not found: ${filePath}`);
81
+ }
82
+ const content = fs.readFileSync(filePath, 'utf8');
83
+ if (!content || content.trim() === '') {
84
+ throw new Error(`Blueprint file is empty: ${filePath}`);
85
+ }
86
+ let data;
87
+ try {
88
+ data = yaml.load(content);
89
+ }
90
+ catch (err) {
91
+ throw new Error(`Invalid YAML in ${filePath}: ${err.message}`);
92
+ }
93
+ if (!data || typeof data !== 'object' || Array.isArray(data)) {
94
+ throw new Error(`YAML file must contain an associative mapping: ${filePath}`);
95
+ }
96
+ return data;
97
+ }
98
+ normalizeOptions(raw) {
99
+ const opts = (raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {});
100
+ return {
101
+ belongs_to_organization: Boolean(opts['belongs_to_organization'] ?? false),
102
+ soft_deletes: Boolean(opts['soft_deletes'] ?? true),
103
+ audit_trail: Boolean(opts['audit_trail'] ?? false),
104
+ has_uuid: Boolean(opts['has_uuid'] ?? false),
105
+ owner: opts['owner'] ?? null,
106
+ owner_chain: this.normalizeOwnerChain(opts['owner_chain']),
107
+ except_actions: Array.isArray(opts['except_actions']) ? opts['except_actions'] : [],
108
+ pagination: Boolean(opts['pagination'] ?? false),
109
+ per_page: Number(opts['per_page'] ?? 25),
110
+ };
111
+ }
112
+ /**
113
+ * Normalize various `owner_chain` YAML shapes into a single dot-notated
114
+ * string or null. Supports:
115
+ *
116
+ * owner_chain: task.project → 'task.project'
117
+ * owner_chain: [task, project] → 'task.project'
118
+ * owner_chain: null / absent → null
119
+ * owner_chain: '' → null
120
+ */
121
+ normalizeOwnerChain(raw) {
122
+ if (raw == null)
123
+ return null;
124
+ if (typeof raw === 'string') {
125
+ const trimmed = raw.trim();
126
+ return trimmed.length > 0 ? trimmed : null;
127
+ }
128
+ if (Array.isArray(raw)) {
129
+ const parts = raw.map((s) => String(s).trim()).filter((s) => s.length > 0);
130
+ return parts.length > 0 ? parts.join('.') : null;
131
+ }
132
+ return null;
133
+ }
134
+ /**
135
+ * Normalize the `fk_constraints:` YAML section into a flat array of
136
+ * { field, model } tuples. Accepts two shapes:
137
+ *
138
+ * fk_constraints:
139
+ * - field: projectId
140
+ * model: project
141
+ * - field: assignedTo
142
+ * model: user
143
+ *
144
+ * fk_constraints:
145
+ * projectId: project ← object shorthand
146
+ * assignedTo: user
147
+ */
148
+ normalizeFkConstraints(raw) {
149
+ if (Array.isArray(raw)) {
150
+ const out = [];
151
+ for (const entry of raw) {
152
+ if (!entry || typeof entry !== 'object')
153
+ continue;
154
+ const e = entry;
155
+ const field = e['field'] ?? '';
156
+ const model = e['model'] ?? '';
157
+ if (field && model)
158
+ out.push({ field, model });
159
+ }
160
+ return out;
161
+ }
162
+ if (raw && typeof raw === 'object') {
163
+ const out = [];
164
+ for (const [field, model] of Object.entries(raw)) {
165
+ if (field && typeof model === 'string' && model.length > 0) {
166
+ out.push({ field, model });
167
+ }
168
+ }
169
+ return out;
170
+ }
171
+ return [];
172
+ }
173
+ normalizeColumns(raw) {
174
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
175
+ return [];
176
+ const columns = [];
177
+ for (const [name, definition] of Object.entries(raw)) {
178
+ // Short syntax: "title: string"
179
+ const def = typeof definition === 'string'
180
+ ? { type: definition }
181
+ : definition ?? {};
182
+ columns.push({
183
+ name,
184
+ type: String(def['type'] ?? 'string'),
185
+ nullable: Boolean(def['nullable'] ?? false),
186
+ unique: Boolean(def['unique'] ?? false),
187
+ index: Boolean(def['index'] ?? false),
188
+ default: def['default'] ?? null,
189
+ filterable: Boolean(def['filterable'] ?? false),
190
+ sortable: Boolean(def['sortable'] ?? false),
191
+ searchable: Boolean(def['searchable'] ?? false),
192
+ precision: def['precision'] != null ? Number(def['precision']) : null,
193
+ scale: def['scale'] != null ? Number(def['scale']) : null,
194
+ foreignModel: def['foreign_model'] ?? null,
195
+ values: Array.isArray(def['values']) ? def['values'] : undefined,
196
+ });
197
+ }
198
+ return columns;
199
+ }
200
+ normalizeRelationships(raw) {
201
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
202
+ return [];
203
+ const rels = [];
204
+ for (const [name, definition] of Object.entries(raw)) {
205
+ const def = (definition ?? {});
206
+ rels.push({
207
+ name,
208
+ type: String(def['type'] ?? 'belongsTo'),
209
+ model: String(def['model'] ?? ''),
210
+ });
211
+ }
212
+ return rels;
213
+ }
214
+ normalizePermissions(raw) {
215
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
216
+ return {};
217
+ const result = {};
218
+ for (const [role, definition] of Object.entries(raw)) {
219
+ const def = (definition ?? {});
220
+ // actions: ["*"] → ['index','show','store','update','destroy'] or keep as-is
221
+ const rawActions = Array.isArray(def['actions']) ? def['actions'] : [];
222
+ const actions = rawActions.includes('*')
223
+ ? ['index', 'show', 'store', 'update', 'destroy', 'trashed', 'restore', 'forceDelete']
224
+ : rawActions;
225
+ result[role] = {
226
+ actions,
227
+ show_fields: this.normalizeFieldList(def['show_fields'] ?? '*'),
228
+ create_fields: this.normalizeFieldMap(def['create_fields'] ?? {}),
229
+ update_fields: this.normalizeFieldMap(def['update_fields'] ?? {}),
230
+ hidden_fields: Array.isArray(def['hidden_fields']) ? def['hidden_fields'] : [],
231
+ };
232
+ }
233
+ return result;
234
+ }
235
+ /**
236
+ * Normalize show_fields: '*' → ['*'], array → array as-is.
237
+ */
238
+ normalizeFieldList(fields) {
239
+ if (fields === '*')
240
+ return ['*'];
241
+ if (Array.isArray(fields))
242
+ return fields;
243
+ if (typeof fields === 'string')
244
+ return [fields];
245
+ return [];
246
+ }
247
+ /**
248
+ * Normalize create_fields / update_fields.
249
+ * These can be either:
250
+ * { title: required, content: nullable } (object)
251
+ * [title, content] (array)
252
+ * '*' (wildcard string)
253
+ * We keep the object form as-is (a Record<string, string>) and convert
254
+ * arrays/wildcards to the same shape for uniform downstream handling.
255
+ */
256
+ normalizeFieldMap(fields) {
257
+ if (fields === '*')
258
+ return ['*'];
259
+ if (Array.isArray(fields))
260
+ return fields;
261
+ if (fields && typeof fields === 'object')
262
+ return fields;
263
+ return {};
264
+ }
265
+ /**
266
+ * Convert PascalCase model name to plural snake_case slug.
267
+ * e.g. BlogPost → blog_posts
268
+ */
269
+ toSlug(model) {
270
+ const snake = model.replace(/([A-Z])/g, (m, c, i) => (i === 0 ? c.toLowerCase() : `_${c.toLowerCase()}`));
271
+ // naive plural: append s (good enough for generator context)
272
+ return snake.endsWith('s') ? snake : `${snake}s`;
273
+ }
274
+ }
275
+ exports.BlueprintParser = BlueprintParser;
276
+ //# sourceMappingURL=blueprint-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blueprint-parser.js","sourceRoot":"","sources":["../../src/blueprint/blueprint-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ export interface RunnerOptions {
2
+ /** Root directory of the consuming project (defaults to cwd) */
3
+ projectRoot?: string;
4
+ /** Only process a blueprint whose model name matches (e.g. 'Post') */
5
+ model?: string;
6
+ /** Validate + report without writing any files */
7
+ dryRun?: boolean;
8
+ /** Ignore the manifest and re-generate all blueprints */
9
+ force?: boolean;
10
+ /** Silence progress output */
11
+ silent?: boolean;
12
+ }
13
+ export interface RunnerResult {
14
+ processed: string[];
15
+ skipped: string[];
16
+ errors: Array<{
17
+ file: string;
18
+ error: string;
19
+ }>;
20
+ generatedFiles: string[];
21
+ }
22
+ /**
23
+ * Orchestrator: discovers `*.yaml` files in `.rhino/blueprints/`,
24
+ * validates them, skips unchanged ones (via ManifestManager), and runs all
25
+ * five generators per blueprint.
26
+ *
27
+ * Flags:
28
+ * --dry-run → validate + plan without writing
29
+ * --force → ignore manifest, re-generate everything
30
+ * --model=Foo → only process the blueprint whose `model:` is 'Foo'
31
+ */
32
+ export declare class BlueprintRunner {
33
+ private readonly parser;
34
+ private readonly validator;
35
+ private readonly prismaGen;
36
+ private readonly resourceGen;
37
+ private readonly policyGen;
38
+ private readonly testGen;
39
+ private readonly seederGen;
40
+ run(options?: RunnerOptions): Promise<RunnerResult>;
41
+ private generateAll;
42
+ private writeFile;
43
+ private appendToFile;
44
+ private log;
45
+ }
46
+ /**
47
+ * Parse the Prisma datasource provider out of an existing schema. Defaults
48
+ * to `postgresql` when the block is missing or unrecognised. Used so that
49
+ * the schema generator emits `Float` instead of `Decimal` on SQLite.
50
+ */
51
+ export declare function detectPrismaProvider(schema: string): 'sqlite' | 'postgresql' | 'mysql' | 'sqlserver' | 'mongodb';
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.BlueprintRunner = void 0;
37
+ exports.detectPrismaProvider = detectPrismaProvider;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const blueprint_parser_1 = require("./blueprint-parser");
41
+ const blueprint_validator_1 = require("./blueprint-validator");
42
+ const manifest_manager_1 = require("./manifest-manager");
43
+ const prisma_schema_generator_1 = require("./generators/prisma-schema-generator");
44
+ const resource_definition_generator_1 = require("./generators/resource-definition-generator");
45
+ const policy_generator_1 = require("./generators/policy-generator");
46
+ const test_generator_1 = require("./generators/test-generator");
47
+ const seeder_generator_1 = require("./generators/seeder-generator");
48
+ // ---------------------------------------------------------------------------
49
+ // BlueprintRunner
50
+ // ---------------------------------------------------------------------------
51
+ /**
52
+ * Orchestrator: discovers `*.yaml` files in `.rhino/blueprints/`,
53
+ * validates them, skips unchanged ones (via ManifestManager), and runs all
54
+ * five generators per blueprint.
55
+ *
56
+ * Flags:
57
+ * --dry-run → validate + plan without writing
58
+ * --force → ignore manifest, re-generate everything
59
+ * --model=Foo → only process the blueprint whose `model:` is 'Foo'
60
+ */
61
+ class BlueprintRunner {
62
+ parser = new blueprint_parser_1.BlueprintParser();
63
+ validator = new blueprint_validator_1.BlueprintValidator();
64
+ prismaGen = new prisma_schema_generator_1.PrismaSchemaGenerator();
65
+ resourceGen = new resource_definition_generator_1.ResourceDefinitionGenerator();
66
+ policyGen = new policy_generator_1.PolicyGenerator();
67
+ testGen = new test_generator_1.TestGenerator();
68
+ seederGen = new seeder_generator_1.SeederGenerator();
69
+ async run(options = {}) {
70
+ const projectRoot = options.projectRoot ?? process.cwd();
71
+ const blueprintsDir = path.join(projectRoot, '.rhino', 'blueprints');
72
+ const manifestDir = path.join(projectRoot, '.rhino');
73
+ const result = {
74
+ processed: [],
75
+ skipped: [],
76
+ errors: [],
77
+ generatedFiles: [],
78
+ };
79
+ // Discover YAML files
80
+ if (!fs.existsSync(blueprintsDir)) {
81
+ this.log(`No blueprints directory found at ${blueprintsDir}`, options);
82
+ return result;
83
+ }
84
+ // Filter rules:
85
+ // - .yaml / .yml only
86
+ // - Skip files whose basename starts with `_` — those are shared anchor /
87
+ // partial files (e.g. `_roles.yaml`) that are imported into other
88
+ // blueprints but are not themselves model definitions. See BP-009.
89
+ const yamlFiles = fs
90
+ .readdirSync(blueprintsDir)
91
+ .filter((f) => (f.endsWith('.yaml') || f.endsWith('.yml')) && !f.startsWith('_'))
92
+ .sort();
93
+ if (yamlFiles.length === 0) {
94
+ this.log('No blueprint YAML files found.', options);
95
+ return result;
96
+ }
97
+ const manifest = new manifest_manager_1.ManifestManager(manifestDir);
98
+ for (const filename of yamlFiles) {
99
+ const filePath = path.join(blueprintsDir, filename);
100
+ try {
101
+ // Parse
102
+ const blueprint = this.parser.parseModel(filePath);
103
+ // Filter by --model flag
104
+ if (options.model && blueprint.model.toLowerCase() !== options.model.toLowerCase()) {
105
+ result.skipped.push(filename);
106
+ continue;
107
+ }
108
+ // Validate
109
+ const validation = this.validator.validate(blueprint);
110
+ if (!validation.valid) {
111
+ const msg = validation.errors.join('; ');
112
+ result.errors.push({ file: filename, error: msg });
113
+ this.log(` ✗ ${filename}: ${msg}`, options);
114
+ continue;
115
+ }
116
+ if (validation.warnings.length > 0) {
117
+ this.log(` ⚠ ${filename} warnings: ${validation.warnings.join('; ')}`, options);
118
+ }
119
+ // Check manifest (skip unchanged unless --force)
120
+ const hash = this.parser.computeFileHash(filePath);
121
+ if (!options.force && !manifest.hasChanged(filename, hash)) {
122
+ result.skipped.push(filename);
123
+ this.log(` → ${filename} unchanged, skipping`, options);
124
+ continue;
125
+ }
126
+ // Generate
127
+ this.log(` ↻ ${filename} (${blueprint.model})`, options);
128
+ const generated = this.generateAll(blueprint, projectRoot, options.dryRun ?? false);
129
+ result.generatedFiles.push(...generated);
130
+ result.processed.push(filename);
131
+ // Record in manifest
132
+ if (!options.dryRun) {
133
+ manifest.recordGeneration(filename, hash, generated);
134
+ }
135
+ }
136
+ catch (err) {
137
+ result.errors.push({ file: filename, error: err.message });
138
+ this.log(` ✗ ${filename}: ${err.message}`, options);
139
+ }
140
+ }
141
+ // Save manifest
142
+ if (!options.dryRun && result.processed.length > 0) {
143
+ manifest.save();
144
+ }
145
+ this.log(`\nBlueprint run complete: ${result.processed.length} processed, ` +
146
+ `${result.skipped.length} skipped, ${result.errors.length} errors.`, options);
147
+ return result;
148
+ }
149
+ // -------------------------------------------------------------------------
150
+ // Private
151
+ // -------------------------------------------------------------------------
152
+ generateAll(blueprint, projectRoot, dryRun) {
153
+ const generated = [];
154
+ const model = blueprint.model;
155
+ // 1. Prisma schema fragment — appended to prisma/schema.prisma.
156
+ // BP-002: skip when the model already exists in the consumer's
157
+ // schema (hand-authored). Detect SQLite provider so decimals map to
158
+ // Float instead of unsupported Decimal.
159
+ const prismaPath = path.join(projectRoot, 'prisma', 'schema.prisma');
160
+ const existingSchema = fs.existsSync(prismaPath) ? fs.readFileSync(prismaPath, 'utf8') : '';
161
+ const provider = detectPrismaProvider(existingSchema);
162
+ const prismaFragment = this.prismaGen.generate(blueprint, { existingSchema, provider });
163
+ if (prismaFragment && !dryRun) {
164
+ this.appendToFile(prismaPath, `\n${prismaFragment}\n`);
165
+ }
166
+ if (prismaFragment)
167
+ generated.push(prismaPath);
168
+ // 2. Resource definition file
169
+ const resourcePath = path.join(projectRoot, 'src', 'resources', `${model}Resource.ts`);
170
+ const resourceContent = this.resourceGen.generate(blueprint);
171
+ if (!dryRun) {
172
+ this.writeFile(resourcePath, resourceContent);
173
+ }
174
+ generated.push(resourcePath);
175
+ // 3. Policy class
176
+ const policyPath = path.join(projectRoot, 'src', 'policies', `${model}Policy.ts`);
177
+ const policyContent = this.policyGen.generate(blueprint);
178
+ if (!dryRun) {
179
+ this.writeFile(policyPath, policyContent);
180
+ }
181
+ generated.push(policyPath);
182
+ // 4. Jest test file
183
+ const testPath = path.join(projectRoot, 'test', 'generated', `${model}.spec.ts`);
184
+ const testContent = this.testGen.generate(blueprint);
185
+ if (!dryRun) {
186
+ this.writeFile(testPath, testContent);
187
+ }
188
+ generated.push(testPath);
189
+ // 5. Seeder
190
+ const seederPath = path.join(projectRoot, 'src', 'seeders', `${model}Seeder.ts`);
191
+ const seederContent = this.seederGen.generate(blueprint);
192
+ if (!dryRun) {
193
+ this.writeFile(seederPath, seederContent);
194
+ }
195
+ generated.push(seederPath);
196
+ return generated;
197
+ }
198
+ writeFile(filePath, content) {
199
+ const dir = path.dirname(filePath);
200
+ if (!fs.existsSync(dir)) {
201
+ fs.mkdirSync(dir, { recursive: true });
202
+ }
203
+ fs.writeFileSync(filePath, content, 'utf8');
204
+ }
205
+ appendToFile(filePath, content) {
206
+ const dir = path.dirname(filePath);
207
+ if (!fs.existsSync(dir)) {
208
+ fs.mkdirSync(dir, { recursive: true });
209
+ }
210
+ fs.appendFileSync(filePath, content, 'utf8');
211
+ }
212
+ log(message, options) {
213
+ if (!options.silent) {
214
+ console.log(message);
215
+ }
216
+ }
217
+ }
218
+ exports.BlueprintRunner = BlueprintRunner;
219
+ /**
220
+ * Parse the Prisma datasource provider out of an existing schema. Defaults
221
+ * to `postgresql` when the block is missing or unrecognised. Used so that
222
+ * the schema generator emits `Float` instead of `Decimal` on SQLite.
223
+ */
224
+ function detectPrismaProvider(schema) {
225
+ const m = schema.match(/datasource\s+\w+\s*\{[^}]*provider\s*=\s*"([^"]+)"/m);
226
+ const found = (m?.[1] ?? '').toLowerCase();
227
+ switch (found) {
228
+ case 'sqlite':
229
+ case 'postgresql':
230
+ case 'mysql':
231
+ case 'sqlserver':
232
+ case 'mongodb':
233
+ return found;
234
+ default:
235
+ return 'postgresql';
236
+ }
237
+ }
238
+ //# sourceMappingURL=blueprint-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blueprint-runner.js","sourceRoot":"","sources":["../../src/blueprint/blueprint-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { Blueprint } from './blueprint-parser';
2
+ export interface ValidationResult {
3
+ valid: boolean;
4
+ errors: string[];
5
+ warnings: string[];
6
+ }
7
+ export declare class BlueprintValidator {
8
+ /**
9
+ * Validate a parsed Blueprint. Returns errors and warnings.
10
+ *
11
+ * @param blueprint Parsed blueprint from BlueprintParser.parseModel()
12
+ * @param validRoles Optional array of known role slugs — enables stricter role checks
13
+ */
14
+ validate(blueprint: Blueprint, validRoles?: string[]): ValidationResult;
15
+ private validateColumns;
16
+ private validatePermissions;
17
+ private validateOptions;
18
+ private validateRelationships;
19
+ }