@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,275 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TestGenerator = void 0;
4
+ /**
5
+ * Generates a Jest spec for a blueprint resource.
6
+ *
7
+ * Produces a self-contained file using the library's `buildEnv` helper, which
8
+ * the library ships under `test/helpers/make-controller.ts`. Consumer apps
9
+ * can copy that helper into their own test tree or replace the import path
10
+ * with their own equivalent — a comment in the generated file explains how.
11
+ *
12
+ * Tests produced:
13
+ * 1. CRUD happy-path (index / show / store / update / destroy)
14
+ * 2. 403 when a restricted role attempts a write action
15
+ * 3. 404 for cross-tenant access (when `belongs_to_organization: true`)
16
+ *
17
+ * Controller invocation uses the real `GlobalController` public method
18
+ * signatures: `index(modelSlug, query, req)`, `show(modelSlug, id, query, req)`,
19
+ * `store(modelSlug, body, req)`, `update(modelSlug, id, body, req)`,
20
+ * `destroy(modelSlug, id, req)`.
21
+ */
22
+ class TestGenerator {
23
+ generate(blueprint) {
24
+ const { model, slug, options, permissions } = blueprint;
25
+ const roles = Object.keys(permissions);
26
+ const adminRole = roles.find((r) => r === 'admin') ?? roles[0] ?? 'admin';
27
+ const restrictedRole = roles.find((r) => {
28
+ const actions = permissions[r]?.actions ?? [];
29
+ return !actions.includes('store') || !actions.includes('update') || !actions.includes('destroy');
30
+ });
31
+ const modelKey = this.camelCase(model);
32
+ const sampleRow = this.buildSampleRow(blueprint);
33
+ const createPayload = this.buildCreatePayload(blueprint);
34
+ const updatePayload = this.buildUpdatePayload(blueprint);
35
+ const adminPerms = this.permissionsFor(slug, permissions[adminRole]);
36
+ // BP-005: UUID-PK models use strings in Prisma `where: { id: '...' }`.
37
+ const sampleId = options.has_uuid
38
+ ? sampleRow.id // already UUID from buildSampleRow
39
+ : 1;
40
+ const idLiteral = options.has_uuid ? `'${sampleId}'` : '1';
41
+ const idRouteParam = options.has_uuid ? `'${sampleId}'` : "'1'";
42
+ const lines = [];
43
+ const push = (s = '') => lines.push(s);
44
+ push(`// Generated by Rhino Blueprint — do not edit directly.`);
45
+ push(`// Source: .rhino/blueprints/${blueprint.source_file}`);
46
+ push(`// NOTE: this spec imports \`buildEnv\` from the library test helper.`);
47
+ push(`// For your app, replace the import with your own test helper or the`);
48
+ push(`// published helper re-exported from \`@rhino-dev/rhino-nestjs/testing\`.`);
49
+ push(`import { buildEnv } from '../../test/helpers/make-controller';`);
50
+ push(`import type { RhinoConfig } from '@rhino-dev/rhino-nestjs';`);
51
+ push(``);
52
+ // Config helper
53
+ push(`function makeConfig(overrides: Partial<RhinoConfig> = {}): RhinoConfig {`);
54
+ push(` return {`);
55
+ push(` models: {`);
56
+ push(` ${slug}: {`);
57
+ push(` model: '${modelKey}',`);
58
+ push(` belongsToOrganization: ${options.belongs_to_organization},`);
59
+ push(` softDeletes: ${options.soft_deletes},`);
60
+ push(` hasAuditTrail: ${options.audit_trail},`);
61
+ push(` },`);
62
+ push(` },`);
63
+ push(` ...overrides,`);
64
+ push(` };`);
65
+ push(`}`);
66
+ push(``);
67
+ // User helper — matches the shape consumed by permission-matcher.ts
68
+ push(`/** Build a user with a role + permissions for the target organization. */`);
69
+ push(`function makeUser(role: string, perms: string[] = [], orgId = 1) {`);
70
+ push(` return {`);
71
+ push(` id: 1,`);
72
+ push(` userRoles: [`);
73
+ push(` { organizationId: orgId, permissions: perms, role: { slug: role } },`);
74
+ push(` ],`);
75
+ push(` };`);
76
+ push(`}`);
77
+ push(``);
78
+ push(`const sampleRow = ${JSON.stringify(sampleRow, null, 2)};`);
79
+ push(`const adminPerms = ${JSON.stringify(adminPerms)};`);
80
+ push(``);
81
+ push(`describe('${model} resource', () => {`);
82
+ // Happy path
83
+ push(` // -----------------------------------------------------------------`);
84
+ push(` // CRUD happy path`);
85
+ push(` // -----------------------------------------------------------------`);
86
+ push(``);
87
+ push(` it('index returns records for the current org', async () => {`);
88
+ push(` const env = buildEnv(makeConfig(), { ${modelKey}: [sampleRow] });`);
89
+ push(` const user = makeUser('${adminRole}', adminPerms);`);
90
+ push(` const req = { user, organization: { id: 1 } } as any;`);
91
+ push(` const res: any = await env.controllers.global.index('${slug}', {}, req);`);
92
+ push(` expect(res).toBeDefined();`);
93
+ push(` });`);
94
+ push(``);
95
+ push(` it('show returns a single record by id', async () => {`);
96
+ push(` const env = buildEnv(makeConfig(), { ${modelKey}: [{ ...sampleRow, id: ${idLiteral} }] });`);
97
+ push(` const user = makeUser('${adminRole}', adminPerms);`);
98
+ push(` const req = { user, organization: { id: 1 } } as any;`);
99
+ push(` const res: any = await env.controllers.global.show('${slug}', ${idRouteParam}, {}, req);`);
100
+ push(` expect(res).toMatchObject({ id: ${idLiteral} });`);
101
+ push(` });`);
102
+ push(``);
103
+ push(` it('store persists a new record', async () => {`);
104
+ push(` const env = buildEnv(makeConfig());`);
105
+ push(` const user = makeUser('${adminRole}', adminPerms);`);
106
+ push(` const req = { user, organization: { id: 1 } } as any;`);
107
+ push(` const body = ${JSON.stringify(createPayload)};`);
108
+ push(` await env.controllers.global.store('${slug}', body, req);`);
109
+ push(` const rows = env.client._data.${modelKey} ?? [];`);
110
+ push(` expect(rows.length).toBeGreaterThan(0);`);
111
+ push(` });`);
112
+ push(``);
113
+ push(` it('update modifies an existing record', async () => {`);
114
+ push(` const env = buildEnv(makeConfig(), { ${modelKey}: [{ ...sampleRow, id: ${idLiteral} }] });`);
115
+ push(` const user = makeUser('${adminRole}', adminPerms);`);
116
+ push(` const req = { user, organization: { id: 1 } } as any;`);
117
+ push(` const body = ${JSON.stringify(updatePayload)};`);
118
+ push(` const res: any = await env.controllers.global.update('${slug}', ${idRouteParam}, body, req);`);
119
+ push(` expect(res).toBeDefined();`);
120
+ push(` });`);
121
+ push(``);
122
+ push(` it('destroy removes (or soft-deletes) the record', async () => {`);
123
+ push(` const env = buildEnv(makeConfig(), { ${modelKey}: [{ ...sampleRow, id: ${idLiteral} }] });`);
124
+ push(` const user = makeUser('${adminRole}', adminPerms);`);
125
+ push(` const req = { user, organization: { id: 1 } } as any;`);
126
+ push(` await env.controllers.global.destroy('${slug}', ${idRouteParam}, req);`);
127
+ push(` const rows = env.client._data.${modelKey} ?? [];`);
128
+ push(` const active = rows.filter((r: any) => !r.deletedAt);`);
129
+ push(` expect(active).toHaveLength(0);`);
130
+ push(` });`);
131
+ push(``);
132
+ // 403 restricted role
133
+ if (restrictedRole) {
134
+ const restrictedPerms = this.permissionsFor(slug, permissions[restrictedRole]);
135
+ push(` // -----------------------------------------------------------------`);
136
+ push(` // 403 — role without store permission`);
137
+ push(` // -----------------------------------------------------------------`);
138
+ push(``);
139
+ push(` it('rejects store from a role without store permission', async () => {`);
140
+ push(` const env = buildEnv(makeConfig());`);
141
+ push(` const user = makeUser('${restrictedRole}', ${JSON.stringify(restrictedPerms)});`);
142
+ push(` const req = { user, organization: { id: 1 } } as any;`);
143
+ push(` const body = ${JSON.stringify(createPayload)};`);
144
+ push(` // Without \`${slug}.store\` in permissions, the policy check will reject.`);
145
+ push(` // The exact exception type depends on how the route is guarded;`);
146
+ push(` // here we assert store throws (not persists).`);
147
+ push(` await expect(`);
148
+ push(` env.controllers.global.store('${slug}', body, req),`);
149
+ push(` ).rejects.toBeDefined();`);
150
+ push(` });`);
151
+ push(``);
152
+ }
153
+ // 404 cross-tenant
154
+ if (options.belongs_to_organization) {
155
+ push(` // -----------------------------------------------------------------`);
156
+ push(` // 404 — cross-tenant access`);
157
+ push(` // -----------------------------------------------------------------`);
158
+ push(``);
159
+ push(` it('does not return records belonging to another organization', async () => {`);
160
+ push(` const env = buildEnv(makeConfig(), {`);
161
+ push(` ${modelKey}: [{ ...sampleRow, id: ${idLiteral}, organizationId: 99 }],`);
162
+ push(` });`);
163
+ push(` const user = makeUser('${adminRole}', adminPerms, 1);`);
164
+ push(` const req = { user, organization: { id: 1 } } as any;`);
165
+ push(` await expect(`);
166
+ push(` env.controllers.global.show('${slug}', ${idRouteParam}, {}, req),`);
167
+ push(` ).rejects.toMatchObject({ code: 'NOT_FOUND' });`);
168
+ push(` });`);
169
+ push(``);
170
+ }
171
+ push(`});`);
172
+ push(``);
173
+ return lines.join('\n');
174
+ }
175
+ // -------------------------------------------------------------------------
176
+ // Helpers
177
+ // -------------------------------------------------------------------------
178
+ permissionsFor(slug, perm) {
179
+ if (!perm?.actions)
180
+ return [];
181
+ if (perm.actions.includes('*'))
182
+ return [`${slug}.*`];
183
+ return perm.actions.map((a) => `${slug}.${a}`);
184
+ }
185
+ buildSampleRow(blueprint) {
186
+ // BP-005: UUID-PK models emit a deterministic UUID sample so generated
187
+ // tests pass Prisma's `where: { id: '...' }` validation.
188
+ const id = blueprint.options.has_uuid
189
+ ? '00000000-0000-0000-0000-000000000001'
190
+ : 1;
191
+ const row = { id };
192
+ for (const col of blueprint.columns) {
193
+ row[col.name] = this.sampleValue(col.type, col.values);
194
+ }
195
+ if (blueprint.options.belongs_to_organization)
196
+ row['organizationId'] = 1;
197
+ return row;
198
+ }
199
+ buildCreatePayload(blueprint) {
200
+ const payload = {};
201
+ const adminPerm = Object.values(blueprint.permissions)[0];
202
+ if (!adminPerm) {
203
+ for (const col of blueprint.columns)
204
+ payload[col.name] = this.sampleValue(col.type, col.values);
205
+ return payload;
206
+ }
207
+ const createFields = adminPerm.create_fields;
208
+ if (!createFields || (Array.isArray(createFields) && createFields[0] === '*')) {
209
+ for (const col of blueprint.columns)
210
+ payload[col.name] = this.sampleValue(col.type, col.values);
211
+ return payload;
212
+ }
213
+ const fieldNames = Array.isArray(createFields) ? createFields : Object.keys(createFields);
214
+ for (const name of fieldNames) {
215
+ const col = blueprint.columns.find((c) => c.name === name);
216
+ payload[name] = this.sampleValue(col?.type ?? 'string', col?.values);
217
+ }
218
+ return payload;
219
+ }
220
+ buildUpdatePayload(blueprint) {
221
+ const payload = {};
222
+ const firstPerm = Object.values(blueprint.permissions)[0];
223
+ if (!firstPerm)
224
+ return payload;
225
+ const updateFields = firstPerm.update_fields;
226
+ if (!updateFields || (Array.isArray(updateFields) && updateFields[0] === '*')) {
227
+ const col = blueprint.columns[0];
228
+ if (col)
229
+ payload[col.name] = this.sampleValue(col.type, col.values);
230
+ return payload;
231
+ }
232
+ const fieldNames = Array.isArray(updateFields) ? updateFields : Object.keys(updateFields);
233
+ const name = fieldNames[0];
234
+ if (name) {
235
+ const col = blueprint.columns.find((c) => c.name === name);
236
+ payload[name] = this.sampleValue(col?.type ?? 'string', col?.values);
237
+ }
238
+ return payload;
239
+ }
240
+ sampleValue(type, enumValues) {
241
+ switch (type) {
242
+ case 'string':
243
+ case 'text':
244
+ return 'sample text';
245
+ case 'integer':
246
+ case 'bigInteger':
247
+ case 'foreignId':
248
+ return 1;
249
+ case 'float':
250
+ case 'decimal':
251
+ return 1.5;
252
+ case 'boolean':
253
+ return true;
254
+ case 'date':
255
+ case 'datetime':
256
+ case 'timestamp':
257
+ return '2024-01-01T00:00:00Z';
258
+ case 'json':
259
+ return {};
260
+ case 'uuid':
261
+ return '00000000-0000-0000-0000-000000000000';
262
+ case 'enum':
263
+ return enumValues?.[0] ?? 'draft';
264
+ default:
265
+ return 'value';
266
+ }
267
+ }
268
+ camelCase(str) {
269
+ if (!str)
270
+ return str;
271
+ return str.charAt(0).toLowerCase() + str.slice(1).replace(/[-_](.)/g, (_, c) => c.toUpperCase());
272
+ }
273
+ }
274
+ exports.TestGenerator = TestGenerator;
275
+ //# sourceMappingURL=test-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-generator.js","sourceRoot":"","sources":["../../../src/blueprint/generators/test-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ interface ManifestEntry {
2
+ content_hash: string;
3
+ generated_files: string[];
4
+ generated_at: string;
5
+ }
6
+ interface ManifestData {
7
+ version: number;
8
+ generated_at: string | null;
9
+ files: Record<string, ManifestEntry>;
10
+ }
11
+ /**
12
+ * Tracks SHA-256 hashes of blueprint files in `.rhino/manifest.json`
13
+ * so unchanged files are skipped on re-generation.
14
+ */
15
+ export declare class ManifestManager {
16
+ private readonly manifestPath;
17
+ private manifest;
18
+ constructor(blueprintsDir: string);
19
+ /**
20
+ * Check whether a blueprint file has changed since the last generation run.
21
+ *
22
+ * @param filename The blueprint filename (e.g. 'post.yaml')
23
+ * @param currentHash SHA-256 of the current file contents
24
+ * @returns true if the file is new or its hash differs from the stored one
25
+ */
26
+ hasChanged(filename: string, currentHash: string): boolean;
27
+ /**
28
+ * Record a successful generation run for a blueprint file.
29
+ *
30
+ * @param filename The blueprint filename
31
+ * @param contentHash SHA-256 of the file at generation time
32
+ * @param generatedFiles Paths to all files produced by the generators
33
+ */
34
+ recordGeneration(filename: string, contentHash: string, generatedFiles: string[]): void;
35
+ /**
36
+ * Return the list of files that were generated the last time a blueprint was processed.
37
+ */
38
+ getGeneratedFiles(filename: string): string[];
39
+ /**
40
+ * Return all blueprint filenames currently tracked in the manifest.
41
+ */
42
+ getTrackedFiles(): string[];
43
+ /**
44
+ * Remove a blueprint entry from the manifest (use when the source YAML is deleted).
45
+ */
46
+ removeTracking(filename: string): void;
47
+ /**
48
+ * Persist the manifest to disk.
49
+ * Creates the parent directory if it does not exist.
50
+ */
51
+ save(): void;
52
+ /**
53
+ * Return the full in-memory manifest (useful for testing / debugging).
54
+ */
55
+ getManifest(): ManifestData;
56
+ private load;
57
+ }
58
+ export {};
@@ -0,0 +1,137 @@
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.ManifestManager = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ // ---------------------------------------------------------------------------
40
+ // ManifestManager
41
+ // ---------------------------------------------------------------------------
42
+ /**
43
+ * Tracks SHA-256 hashes of blueprint files in `.rhino/manifest.json`
44
+ * so unchanged files are skipped on re-generation.
45
+ */
46
+ class ManifestManager {
47
+ manifestPath;
48
+ manifest;
49
+ constructor(blueprintsDir) {
50
+ // Store manifest alongside blueprints under .rhino/manifest.json
51
+ this.manifestPath = path.join(blueprintsDir, 'manifest.json');
52
+ this.manifest = this.load();
53
+ }
54
+ /**
55
+ * Check whether a blueprint file has changed since the last generation run.
56
+ *
57
+ * @param filename The blueprint filename (e.g. 'post.yaml')
58
+ * @param currentHash SHA-256 of the current file contents
59
+ * @returns true if the file is new or its hash differs from the stored one
60
+ */
61
+ hasChanged(filename, currentHash) {
62
+ const entry = this.manifest.files[filename];
63
+ if (!entry)
64
+ return true; // new file
65
+ return entry.content_hash !== currentHash;
66
+ }
67
+ /**
68
+ * Record a successful generation run for a blueprint file.
69
+ *
70
+ * @param filename The blueprint filename
71
+ * @param contentHash SHA-256 of the file at generation time
72
+ * @param generatedFiles Paths to all files produced by the generators
73
+ */
74
+ recordGeneration(filename, contentHash, generatedFiles) {
75
+ this.manifest.files[filename] = {
76
+ content_hash: contentHash,
77
+ generated_files: generatedFiles,
78
+ generated_at: new Date().toISOString(),
79
+ };
80
+ this.manifest.generated_at = new Date().toISOString();
81
+ }
82
+ /**
83
+ * Return the list of files that were generated the last time a blueprint was processed.
84
+ */
85
+ getGeneratedFiles(filename) {
86
+ return this.manifest.files[filename]?.generated_files ?? [];
87
+ }
88
+ /**
89
+ * Return all blueprint filenames currently tracked in the manifest.
90
+ */
91
+ getTrackedFiles() {
92
+ return Object.keys(this.manifest.files);
93
+ }
94
+ /**
95
+ * Remove a blueprint entry from the manifest (use when the source YAML is deleted).
96
+ */
97
+ removeTracking(filename) {
98
+ delete this.manifest.files[filename];
99
+ }
100
+ /**
101
+ * Persist the manifest to disk.
102
+ * Creates the parent directory if it does not exist.
103
+ */
104
+ save() {
105
+ const dir = path.dirname(this.manifestPath);
106
+ if (!fs.existsSync(dir)) {
107
+ fs.mkdirSync(dir, { recursive: true });
108
+ }
109
+ fs.writeFileSync(this.manifestPath, JSON.stringify(this.manifest, null, 2) + '\n', 'utf8');
110
+ }
111
+ /**
112
+ * Return the full in-memory manifest (useful for testing / debugging).
113
+ */
114
+ getManifest() {
115
+ return this.manifest;
116
+ }
117
+ // -------------------------------------------------------------------------
118
+ // Private
119
+ // -------------------------------------------------------------------------
120
+ load() {
121
+ const empty = { version: 1, generated_at: null, files: {} };
122
+ if (!fs.existsSync(this.manifestPath))
123
+ return empty;
124
+ try {
125
+ const raw = fs.readFileSync(this.manifestPath, 'utf8');
126
+ const parsed = JSON.parse(raw);
127
+ if (typeof parsed === 'object' && parsed !== null)
128
+ return parsed;
129
+ }
130
+ catch {
131
+ // corrupt manifest — start fresh
132
+ }
133
+ return empty;
134
+ }
135
+ }
136
+ exports.ManifestManager = ManifestManager;
137
+ //# sourceMappingURL=manifest-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-manager.js","sourceRoot":"","sources":["../../src/blueprint/manifest-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * rhino blueprint [--force] [--dry-run] [--model=slug]
3
+ *
4
+ * Delegates to BlueprintRunner (src/blueprint/blueprint-runner.ts).
5
+ *
6
+ * NOTE: BlueprintRunner is loaded via a dynamic require() so that this CLI
7
+ * file compiles and runs even when blueprint-runner.ts has not yet been built.
8
+ * When the runner is absent, the command exits with code 1 and prints a
9
+ * helpful message.
10
+ */
11
+ export interface BlueprintOptions {
12
+ force?: boolean;
13
+ dryRun?: boolean;
14
+ model?: string;
15
+ }
16
+ export declare function runBlueprint(opts: BlueprintOptions): Promise<void>;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /**
3
+ * rhino blueprint [--force] [--dry-run] [--model=slug]
4
+ *
5
+ * Delegates to BlueprintRunner (src/blueprint/blueprint-runner.ts).
6
+ *
7
+ * NOTE: BlueprintRunner is loaded via a dynamic require() so that this CLI
8
+ * file compiles and runs even when blueprint-runner.ts has not yet been built.
9
+ * When the runner is absent, the command exits with code 1 and prints a
10
+ * helpful message.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.runBlueprint = runBlueprint;
14
+ async function runBlueprint(opts) {
15
+ // Lazy-load the runner so the CLI still compiles without the dependency.
16
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
17
+ let runner;
18
+ try {
19
+ // Try compiled dist first, then fall back to ts source path.
20
+ // The runner module must export a default object or a named `BlueprintRunner`
21
+ // with a `run(opts)` method — or itself be the function.
22
+ const mod = require('../../blueprint/blueprint-runner');
23
+ const RunnerClass = mod.BlueprintRunner ?? mod.default;
24
+ runner = typeof RunnerClass === 'function' ? new RunnerClass() : RunnerClass;
25
+ }
26
+ catch {
27
+ console.error(' Error: BlueprintRunner not found.\n' +
28
+ ' Make sure src/blueprint/blueprint-runner.ts exists and the project is built.\n' +
29
+ ' Expected export: class BlueprintRunner { async run(opts) { ... } }');
30
+ process.exit(1);
31
+ return;
32
+ }
33
+ await runner.run(opts);
34
+ }
35
+ //# sourceMappingURL=blueprint.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blueprint.command.js","sourceRoot":"","sources":["../../../src/cli/commands/blueprint.command.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AAQH,oCAuBC;AAvBM,KAAK,UAAU,YAAY,CAAC,IAAsB;IACvD,yEAAyE;IACzE,iEAAiE;IACjE,IAAI,MAA0D,CAAC;IAE/D,IAAI,CAAC;QACH,6DAA6D;QAC7D,8EAA8E;QAC9E,yDAAyD;QACzD,MAAM,GAAG,GAAG,OAAO,CAAC,kCAAkC,CAAC,CAAC;QACxD,MAAM,WAAW,GAAG,GAAG,CAAC,eAAe,IAAI,GAAG,CAAC,OAAO,CAAC;QACvD,MAAM,GAAG,OAAO,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IAC/E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CACX,uCAAuC;YACrC,kFAAkF;YAClF,sEAAsE,CACzE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface ExportPostmanOptions {
2
+ output?: string;
3
+ baseUrl?: string;
4
+ }
5
+ export declare function runExportPostman(opts: ExportPostmanOptions): Promise<void>;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runExportPostman = runExportPostman;
4
+ /**
5
+ * rhino export-postman [--output=file.json] [--base-url=http://localhost:3000/api]
6
+ *
7
+ * Delegates to PostmanExporter (src/exporters/postman-exporter.ts).
8
+ *
9
+ * NOTE: PostmanExporter is loaded via a dynamic require() so that this CLI
10
+ * file compiles and runs even when the exporter has not yet been built.
11
+ */
12
+ const io_1 = require("../utils/io");
13
+ async function runExportPostman(opts) {
14
+ const outputPath = opts.output ?? 'postman_collection.json';
15
+ const baseUrl = opts.baseUrl ?? 'http://localhost:3000/api';
16
+ // Lazy-load the exporter.
17
+ // Expected export: function generate(config, opts): string
18
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
19
+ let generate;
20
+ try {
21
+ const mod = require('../../exporters/postman-exporter');
22
+ generate = mod.generate ?? mod.default?.generate;
23
+ if (typeof generate !== 'function')
24
+ throw new Error('generate not a function');
25
+ }
26
+ catch {
27
+ console.error(' Error: PostmanExporter not found.\n' +
28
+ ' Make sure src/exporters/postman-exporter.ts exists and the project is built.\n' +
29
+ ' Expected export: function generate(config, opts): string');
30
+ process.exit(1);
31
+ return;
32
+ }
33
+ // PostmanExporter reads the live config — pass empty config here;
34
+ // the exporter itself will load rhino.config or equivalent.
35
+ const json = generate({}, { output: outputPath, baseUrl });
36
+ (0, io_1.writeFileSafely)(outputPath, json);
37
+ console.log(` Postman collection written to: ${outputPath}`);
38
+ }
39
+ //# sourceMappingURL=export-postman.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-postman.command.js","sourceRoot":"","sources":["../../../src/cli/commands/export-postman.command.ts"],"names":[],"mappings":";;AAeA,4CA+BC;AA9CD;;;;;;;GAOG;AACH,oCAA8C;AAOvC,KAAK,UAAU,gBAAgB,CACpC,IAA0B;IAE1B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,IAAI,yBAAyB,CAAC;IAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,2BAA2B,CAAC;IAE5D,0BAA0B;IAC1B,2DAA2D;IAC3D,iEAAiE;IACjE,IAAI,QAAiF,CAAC;IAEtF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,kCAAkC,CAAC,CAAC;QACxD,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC;QACjD,IAAI,OAAO,QAAQ,KAAK,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACjF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CACX,uCAAuC;YACrC,kFAAkF;YAClF,4DAA4D,CAC/D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,kEAAkE;IAClE,4DAA4D;IAC5D,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;IAE3D,IAAA,oBAAe,EAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,oCAAoC,UAAU,EAAE,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export interface ExportTypesOptions {
2
+ output?: string;
3
+ }
4
+ export declare function runExportTypes(opts: ExportTypesOptions): Promise<void>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runExportTypes = runExportTypes;
4
+ /**
5
+ * rhino export-types [--output=path/to/types.d.ts]
6
+ *
7
+ * Delegates to TypeScriptExporter (src/exporters/typescript-exporter.ts).
8
+ *
9
+ * NOTE: TypeScriptExporter is loaded via a dynamic require() so that this CLI
10
+ * file compiles and runs even when the exporter has not yet been built.
11
+ */
12
+ const io_1 = require("../utils/io");
13
+ async function runExportTypes(opts) {
14
+ const outputPath = opts.output ?? 'src/types/rhino.d.ts';
15
+ // Lazy-load the exporter.
16
+ // Expected export: function generate(config, opts): string
17
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
18
+ let generate;
19
+ try {
20
+ const mod = require('../../exporters/typescript-exporter');
21
+ generate = mod.generate ?? mod.default?.generate;
22
+ if (typeof generate !== 'function')
23
+ throw new Error('generate not a function');
24
+ }
25
+ catch {
26
+ console.error(' Error: TypeScriptExporter not found.\n' +
27
+ ' Make sure src/exporters/typescript-exporter.ts exists and the project is built.\n' +
28
+ ' Expected export: function generate(config, opts): string');
29
+ process.exit(1);
30
+ return;
31
+ }
32
+ const dts = generate({}, { output: outputPath });
33
+ (0, io_1.writeFileSafely)(outputPath, dts);
34
+ console.log(` TypeScript types written to: ${outputPath}`);
35
+ }
36
+ //# sourceMappingURL=export-types.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-types.command.js","sourceRoot":"","sources":["../../../src/cli/commands/export-types.command.ts"],"names":[],"mappings":";;AAcA,wCA4BC;AA1CD;;;;;;;GAOG;AACH,oCAA8C;AAMvC,KAAK,UAAU,cAAc,CAClC,IAAwB;IAExB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,IAAI,sBAAsB,CAAC;IAEzD,0BAA0B;IAC1B,2DAA2D;IAC3D,iEAAiE;IACjE,IAAI,QAA+E,CAAC;IAEpF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,qCAAqC,CAAC,CAAC;QAC3D,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC;QACjD,IAAI,OAAO,QAAQ,KAAK,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACjF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CACX,0CAA0C;YACxC,qFAAqF;YACrF,4DAA4D,CAC/D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IAEjD,IAAA,oBAAe,EAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,kCAAkC,UAAU,EAAE,CAAC,CAAC;AAC9D,CAAC"}