@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,38 @@
1
+ import { PrismaService } from '../prisma/prisma.service';
2
+ import { RhinoConfigService } from '../rhino.config';
3
+ import { QueryBuilderService } from './query-builder.service';
4
+ import { ScopeService } from './scope.service';
5
+ export interface FindAllResult {
6
+ items: any[];
7
+ total?: number;
8
+ page?: number;
9
+ perPage?: number;
10
+ lastPage?: number;
11
+ }
12
+ export interface ResourceContext {
13
+ user?: any;
14
+ organization?: any;
15
+ orgIdentifierColumn?: string;
16
+ includeTrashed?: boolean;
17
+ onlyTrashed?: boolean;
18
+ }
19
+ export declare class ResourceService {
20
+ private readonly prisma;
21
+ private readonly config;
22
+ private readonly queryBuilder;
23
+ private readonly scopes?;
24
+ constructor(prisma: PrismaService, config: RhinoConfigService, queryBuilder: QueryBuilderService, scopes?: ScopeService);
25
+ private applyScopes;
26
+ private delegate;
27
+ /** Resolve Prisma where filter for the current org context. */
28
+ protected orgFilter(modelSlug: string, org?: any): Record<string, any> | null;
29
+ findAll(modelSlug: string, rawQuery: Record<string, any>, ctx?: ResourceContext): Promise<FindAllResult>;
30
+ findOne(modelSlug: string, id: string | number, rawQuery: Record<string, any>, ctx?: ResourceContext): Promise<any>;
31
+ create(modelSlug: string, data: Record<string, any>, ctx?: ResourceContext): Promise<any>;
32
+ update(modelSlug: string, id: string | number, data: Record<string, any>, ctx?: ResourceContext): Promise<any>;
33
+ delete(modelSlug: string, id: string | number, ctx?: ResourceContext): Promise<boolean>;
34
+ restore(modelSlug: string, id: string | number, ctx?: ResourceContext): Promise<boolean>;
35
+ forceDelete(modelSlug: string, id: string | number, ctx?: ResourceContext): Promise<boolean>;
36
+ protected castId(id: string | number, hasUuid?: boolean): string | number;
37
+ protected mergeWhere(...parts: (Record<string, any> | null | undefined)[]): Record<string, any>;
38
+ }
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.ResourceService = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const prisma_service_1 = require("../prisma/prisma.service");
18
+ const rhino_config_1 = require("../rhino.config");
19
+ const query_builder_service_1 = require("./query-builder.service");
20
+ const scope_service_1 = require("./scope.service");
21
+ const permission_matcher_1 = require("../utils/permission-matcher");
22
+ let ResourceService = class ResourceService {
23
+ prisma;
24
+ config;
25
+ queryBuilder;
26
+ scopes;
27
+ constructor(prisma, config, queryBuilder, scopes) {
28
+ this.prisma = prisma;
29
+ this.config = config;
30
+ this.queryBuilder = queryBuilder;
31
+ this.scopes = scopes;
32
+ }
33
+ applyScopes(where, modelSlug, ctx) {
34
+ if (!this.scopes)
35
+ return where;
36
+ const reg = this.config.model(modelSlug);
37
+ if (!reg)
38
+ return where;
39
+ return this.scopes.apply(where, reg, {
40
+ user: ctx.user,
41
+ organization: ctx.organization,
42
+ userRole: (0, permission_matcher_1.resolveUserRoleSlug)(ctx.user, ctx.organization?.id),
43
+ });
44
+ }
45
+ delegate(modelSlug) {
46
+ const reg = this.config.model(modelSlug);
47
+ if (!reg)
48
+ throw new Error(`Unknown model: ${modelSlug}`);
49
+ return this.prisma.model(reg.model);
50
+ }
51
+ /** Resolve Prisma where filter for the current org context. */
52
+ orgFilter(modelSlug, org) {
53
+ if (!org)
54
+ return null;
55
+ const reg = this.config.model(modelSlug);
56
+ if (!reg?.belongsToOrganization)
57
+ return null;
58
+ return { organizationId: org.id };
59
+ }
60
+ async findAll(modelSlug, rawQuery, ctx = {}) {
61
+ const reg = this.config.model(modelSlug);
62
+ if (!reg)
63
+ throw new Error(`Unknown model: ${modelSlug}`);
64
+ const delegate = this.delegate(modelSlug);
65
+ const parsed = this.queryBuilder.build(rawQuery, reg);
66
+ let where = this.mergeWhere(parsed.where, this.orgFilter(modelSlug, ctx.organization));
67
+ where = this.applyScopes(where, modelSlug, ctx);
68
+ // soft delete visibility
69
+ if (reg.softDeletes) {
70
+ if (ctx.onlyTrashed) {
71
+ where.deletedAt = { not: null };
72
+ }
73
+ else if (!ctx.includeTrashed) {
74
+ where.deletedAt = null;
75
+ }
76
+ }
77
+ const paginate = reg.paginationEnabled !== false;
78
+ if (paginate) {
79
+ const perPage = parsed.perPage ?? reg.perPage ?? 25;
80
+ const page = parsed.page ?? 1;
81
+ const skip = (page - 1) * perPage;
82
+ const [items, total] = await Promise.all([
83
+ delegate.findMany({
84
+ where,
85
+ orderBy: parsed.orderBy,
86
+ include: parsed.include,
87
+ select: parsed.select,
88
+ skip,
89
+ take: perPage,
90
+ }),
91
+ delegate.count({ where }),
92
+ ]);
93
+ return {
94
+ items,
95
+ total,
96
+ page,
97
+ perPage,
98
+ lastPage: Math.max(1, Math.ceil(total / perPage)),
99
+ };
100
+ }
101
+ const items = await delegate.findMany({
102
+ where,
103
+ orderBy: parsed.orderBy,
104
+ include: parsed.include,
105
+ select: parsed.select,
106
+ });
107
+ return { items };
108
+ }
109
+ async findOne(modelSlug, id, rawQuery, ctx = {}) {
110
+ const reg = this.config.model(modelSlug);
111
+ if (!reg)
112
+ throw new Error(`Unknown model: ${modelSlug}`);
113
+ const delegate = this.delegate(modelSlug);
114
+ const parsed = this.queryBuilder.build(rawQuery, reg);
115
+ let where = { id: this.castId(id, reg.hasUuid) };
116
+ const orgScope = this.orgFilter(modelSlug, ctx.organization);
117
+ if (orgScope)
118
+ Object.assign(where, orgScope);
119
+ where = this.applyScopes(where, modelSlug, ctx);
120
+ if (reg.softDeletes && !ctx.includeTrashed)
121
+ where.deletedAt = null;
122
+ return delegate.findFirst({ where, include: parsed.include, select: parsed.select });
123
+ }
124
+ async create(modelSlug, data, ctx = {}) {
125
+ const reg = this.config.model(modelSlug);
126
+ if (!reg)
127
+ throw new Error(`Unknown model: ${modelSlug}`);
128
+ const delegate = this.delegate(modelSlug);
129
+ const payload = { ...data };
130
+ if (reg.belongsToOrganization && ctx.organization) {
131
+ payload.organizationId = ctx.organization.id;
132
+ }
133
+ return delegate.create({ data: payload });
134
+ }
135
+ async update(modelSlug, id, data, ctx = {}) {
136
+ const reg = this.config.model(modelSlug);
137
+ if (!reg)
138
+ throw new Error(`Unknown model: ${modelSlug}`);
139
+ const delegate = this.delegate(modelSlug);
140
+ const where = { id: this.castId(id, reg.hasUuid) };
141
+ const orgScope = this.orgFilter(modelSlug, ctx.organization);
142
+ if (orgScope)
143
+ Object.assign(where, orgScope);
144
+ // Reject attempts to change organizationId silently
145
+ const payload = { ...data };
146
+ delete payload.organizationId;
147
+ delete payload.organization_id;
148
+ // Prisma "update" doesn't allow extra where props; use updateMany + findFirst for org scope
149
+ if (orgScope) {
150
+ const res = await delegate.updateMany({ where, data: payload });
151
+ if (res.count === 0)
152
+ return null;
153
+ return delegate.findFirst({ where });
154
+ }
155
+ return delegate.update({ where: { id: this.castId(id, reg.hasUuid) }, data: payload });
156
+ }
157
+ async delete(modelSlug, id, ctx = {}) {
158
+ const reg = this.config.model(modelSlug);
159
+ if (!reg)
160
+ throw new Error(`Unknown model: ${modelSlug}`);
161
+ const delegate = this.delegate(modelSlug);
162
+ const where = { id: this.castId(id, reg.hasUuid) };
163
+ const orgScope = this.orgFilter(modelSlug, ctx.organization);
164
+ if (orgScope)
165
+ Object.assign(where, orgScope);
166
+ if (reg.softDeletes) {
167
+ const res = await delegate.updateMany({ where, data: { deletedAt: new Date() } });
168
+ return res.count > 0;
169
+ }
170
+ if (orgScope) {
171
+ const res = await delegate.deleteMany({ where });
172
+ return res.count > 0;
173
+ }
174
+ await delegate.delete({ where: { id: this.castId(id, reg.hasUuid) } });
175
+ return true;
176
+ }
177
+ async restore(modelSlug, id, ctx = {}) {
178
+ const reg = this.config.model(modelSlug);
179
+ if (!reg?.softDeletes)
180
+ throw new Error(`Model ${modelSlug} does not support soft deletes`);
181
+ const delegate = this.delegate(modelSlug);
182
+ const where = { id: this.castId(id, reg.hasUuid) };
183
+ const orgScope = this.orgFilter(modelSlug, ctx.organization);
184
+ if (orgScope)
185
+ Object.assign(where, orgScope);
186
+ const res = await delegate.updateMany({ where, data: { deletedAt: null } });
187
+ return res.count > 0;
188
+ }
189
+ async forceDelete(modelSlug, id, ctx = {}) {
190
+ const reg = this.config.model(modelSlug);
191
+ if (!reg)
192
+ throw new Error(`Unknown model: ${modelSlug}`);
193
+ const delegate = this.delegate(modelSlug);
194
+ const where = { id: this.castId(id, reg.hasUuid) };
195
+ const orgScope = this.orgFilter(modelSlug, ctx.organization);
196
+ if (orgScope)
197
+ Object.assign(where, orgScope);
198
+ if (orgScope) {
199
+ const res = await delegate.deleteMany({ where });
200
+ return res.count > 0;
201
+ }
202
+ await delegate.delete({ where: { id: this.castId(id, reg.hasUuid) } });
203
+ return true;
204
+ }
205
+ castId(id, hasUuid) {
206
+ if (hasUuid)
207
+ return String(id);
208
+ if (typeof id === 'string' && /^\d+$/.test(id))
209
+ return Number(id);
210
+ return id;
211
+ }
212
+ mergeWhere(...parts) {
213
+ const out = {};
214
+ for (const p of parts) {
215
+ if (p)
216
+ Object.assign(out, p);
217
+ }
218
+ return out;
219
+ }
220
+ };
221
+ exports.ResourceService = ResourceService;
222
+ exports.ResourceService = ResourceService = __decorate([
223
+ (0, common_1.Injectable)(),
224
+ __param(3, (0, common_1.Optional)()),
225
+ __metadata("design:paramtypes", [prisma_service_1.PrismaService,
226
+ rhino_config_1.RhinoConfigService,
227
+ query_builder_service_1.QueryBuilderService,
228
+ scope_service_1.ScopeService])
229
+ ], ResourceService);
230
+ //# sourceMappingURL=resource.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.service.js","sourceRoot":"","sources":["../../src/services/resource.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { INestApplication } from '@nestjs/common';
2
+ import { RhinoConfigService } from '../rhino.config';
3
+ export interface RegisterRoutesOptions {
4
+ /** Global prefix for all routes (default: "api"). */
5
+ prefix?: string;
6
+ /** Apply the authentication guard globally. Set `false` to skip. */
7
+ enableAuth?: boolean;
8
+ }
9
+ /**
10
+ * Utility helper invoked during `main.ts` bootstrap to wire up Rhino
11
+ * routing conventions that can't be expressed purely via @Controller decorators
12
+ * (route group prefixes, tenant resolution middleware, skip-auth for public groups).
13
+ *
14
+ * NestJS has no built-in "register the same controller at multiple prefixes" API,
15
+ * so the pattern here is:
16
+ *
17
+ * 1. Users register RhinoModule with their model + routeGroup config.
18
+ * 2. Users expose a single Global/Auth/Invitation/Nested controller set
19
+ * (either by re-exporting from this library or by subclassing).
20
+ * 3. The helper returns the metadata needed to install middleware chains.
21
+ *
22
+ * Route group expansion is done at request time by the `ResolveOrganization`
23
+ * middleware — the tenant group's `:organization` param is the discriminator.
24
+ */
25
+ export declare function applyRhinoRouting(app: INestApplication, options?: RegisterRoutesOptions): {
26
+ prefix: string;
27
+ enableAuth: boolean;
28
+ };
29
+ /**
30
+ * Describe the resolved route table for documentation / postman export.
31
+ */
32
+ export declare function describeRoutes(config: RhinoConfigService): Array<{
33
+ group: string;
34
+ slug: string;
35
+ prefix: string;
36
+ model: string;
37
+ softDeletes: boolean;
38
+ hasAuditTrail: boolean;
39
+ exceptActions: string[];
40
+ }>;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyRhinoRouting = applyRhinoRouting;
4
+ exports.describeRoutes = describeRoutes;
5
+ /**
6
+ * Utility helper invoked during `main.ts` bootstrap to wire up Rhino
7
+ * routing conventions that can't be expressed purely via @Controller decorators
8
+ * (route group prefixes, tenant resolution middleware, skip-auth for public groups).
9
+ *
10
+ * NestJS has no built-in "register the same controller at multiple prefixes" API,
11
+ * so the pattern here is:
12
+ *
13
+ * 1. Users register RhinoModule with their model + routeGroup config.
14
+ * 2. Users expose a single Global/Auth/Invitation/Nested controller set
15
+ * (either by re-exporting from this library or by subclassing).
16
+ * 3. The helper returns the metadata needed to install middleware chains.
17
+ *
18
+ * Route group expansion is done at request time by the `ResolveOrganization`
19
+ * middleware — the tenant group's `:organization` param is the discriminator.
20
+ */
21
+ function applyRhinoRouting(app, options = {}) {
22
+ const prefix = options.prefix ?? 'api';
23
+ app.setGlobalPrefix(prefix);
24
+ return { prefix, enableAuth: options.enableAuth ?? true };
25
+ }
26
+ /**
27
+ * Describe the resolved route table for documentation / postman export.
28
+ */
29
+ function describeRoutes(config) {
30
+ const routes = [];
31
+ const models = config.models();
32
+ const groups = config.routeGroups();
33
+ const groupNames = Object.keys(groups);
34
+ const fallback = groupNames.length === 0 ? [[undefined, undefined]] : [];
35
+ for (const name of groupNames) {
36
+ const group = groups[name];
37
+ const slugList = group.models === '*' ? Object.keys(models) : group.models;
38
+ for (const slug of slugList) {
39
+ const reg = models[slug];
40
+ if (!reg)
41
+ continue;
42
+ routes.push({
43
+ group: name,
44
+ slug,
45
+ prefix: group.prefix ?? '',
46
+ model: reg.model,
47
+ softDeletes: !!reg.softDeletes,
48
+ hasAuditTrail: !!reg.hasAuditTrail,
49
+ exceptActions: reg.exceptActions ?? [],
50
+ });
51
+ }
52
+ }
53
+ if (fallback.length > 0) {
54
+ for (const [slug, reg] of Object.entries(models)) {
55
+ routes.push({
56
+ group: '(default)',
57
+ slug,
58
+ prefix: '',
59
+ model: reg.model,
60
+ softDeletes: !!reg.softDeletes,
61
+ hasAuditTrail: !!reg.hasAuditTrail,
62
+ exceptActions: reg.exceptActions ?? [],
63
+ });
64
+ }
65
+ }
66
+ return routes;
67
+ }
68
+ //# sourceMappingURL=route-registration.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-registration.service.js","sourceRoot":"","sources":["../../src/services/route-registration.service.ts"],"names":[],"mappings":";;AA0BA,8CAOC;AAKD,wCA6CC;AAzED;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,iBAAiB,CAC/B,GAAqB,EACrB,UAAiC,EAAE;IAEnC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC;IACvC,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,MAA0B;IASvD,MAAM,MAAM,GAAU,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;QAC3E,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,IAAI;gBACX,IAAI;gBACJ,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;gBAC1B,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,WAAW;gBAC9B,aAAa,EAAE,CAAC,CAAC,GAAG,CAAC,aAAa;gBAClC,aAAa,EAAE,GAAG,CAAC,aAAa,IAAI,EAAE;aACvC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACjD,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,WAAW;gBAClB,IAAI;gBACJ,MAAM,EAAE,EAAE;gBACV,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,WAAW;gBAC9B,aAAa,EAAE,CAAC,CAAC,GAAG,CAAC,aAAa;gBAClC,aAAa,EAAE,GAAG,CAAC,aAAa,IAAI,EAAE;aACvC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { ModelRegistration } from '../interfaces/rhino-config.interface';
2
+ export interface ScopeContext {
3
+ user?: any;
4
+ organization?: any;
5
+ userRole?: string | null;
6
+ }
7
+ export interface RhinoScope {
8
+ apply(where: Record<string, any>, context: ScopeContext): Record<string, any>;
9
+ }
10
+ /**
11
+ * Applies all registered scopes for a model in order.
12
+ * Scopes are classes implementing `RhinoScope`.
13
+ */
14
+ export declare class ScopeService {
15
+ apply(where: Record<string, any>, reg: ModelRegistration, ctx: ScopeContext): Record<string, any>;
16
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ScopeService = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ /**
12
+ * Applies all registered scopes for a model in order.
13
+ * Scopes are classes implementing `RhinoScope`.
14
+ */
15
+ let ScopeService = class ScopeService {
16
+ apply(where, reg, ctx) {
17
+ const scopes = reg.scopes ?? [];
18
+ let merged = { ...where };
19
+ for (const ScopeClass of scopes) {
20
+ const scope = new ScopeClass();
21
+ if (typeof scope.apply === 'function') {
22
+ merged = scope.apply(merged, ctx) ?? merged;
23
+ }
24
+ }
25
+ return merged;
26
+ }
27
+ };
28
+ exports.ScopeService = ScopeService;
29
+ exports.ScopeService = ScopeService = __decorate([
30
+ (0, common_1.Injectable)()
31
+ ], ScopeService);
32
+ //# sourceMappingURL=scope.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.service.js","sourceRoot":"","sources":["../../src/services/scope.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAa5C;;;GAGG;AAEI,IAAM,YAAY,GAAlB,MAAM,YAAY;IACvB,KAAK,CAAC,KAA0B,EAAE,GAAsB,EAAE,GAAiB;QACzE,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC;QAChC,IAAI,MAAM,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;QAC1B,KAAK,MAAM,UAAU,IAAI,MAAM,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,IAAK,UAAkB,EAAE,CAAC;YACxC,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;gBACtC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC;YAC9C,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAA;AAZY,oCAAY;uBAAZ,YAAY;IADxB,IAAA,mBAAU,GAAE;GACA,YAAY,CAYxB"}
@@ -0,0 +1,36 @@
1
+ import type { ModelRegistration } from '../interfaces/rhino-config.interface';
2
+ export declare const BASE_HIDDEN_COLUMNS: string[];
3
+ /**
4
+ * Context object for serialization. `organization` is required for role-based
5
+ * policy attribute filtering — without it, `hasRole(user, role, org)` in
6
+ * consumer policies can never resolve the active role and every request
7
+ * would collapse to the "no role" fallback (BP-007).
8
+ *
9
+ * Legacy signature: `serializeOne(record, reg, user)` is still accepted for
10
+ * backwards compatibility. New callers should pass the object form.
11
+ */
12
+ export interface SerializeContext {
13
+ user?: any;
14
+ organization?: any;
15
+ }
16
+ /**
17
+ * Serializes a record according to the Laravel `asRhinoJson` contract:
18
+ *
19
+ * 1. Merge computed attributes
20
+ * 2. Remove base-hidden columns
21
+ * 3. Remove model-level `additionalHiddenColumns`
22
+ * 4. Apply policy blacklist (`hiddenAttributesForShow`)
23
+ * 5. Apply policy whitelist (`permittedAttributesForShow`) — `id` always kept
24
+ */
25
+ export declare class SerializerService {
26
+ /**
27
+ * @param record The raw record to serialize (from Prisma).
28
+ * @param reg The model registration driving policy + computed attrs.
29
+ * @param ctx Either a `SerializeContext` object (preferred) or a
30
+ * legacy `user` value (backwards-compat shim — org will
31
+ * be undefined and role-keyed policies will collapse).
32
+ */
33
+ serializeOne(record: Record<string, any> | null | undefined, reg: ModelRegistration, ctx?: SerializeContext | any): Record<string, any> | null;
34
+ serializeMany(records: any[], reg: ModelRegistration, ctx?: SerializeContext | any): any[];
35
+ private normalizeCtx;
36
+ }
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.SerializerService = exports.BASE_HIDDEN_COLUMNS = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ exports.BASE_HIDDEN_COLUMNS = [
12
+ 'password',
13
+ 'rememberToken',
14
+ 'remember_token',
15
+ 'hasTemporaryPassword',
16
+ 'has_temporary_password',
17
+ 'updatedAt',
18
+ 'updated_at',
19
+ 'createdAt',
20
+ 'created_at',
21
+ 'deletedAt',
22
+ 'deleted_at',
23
+ 'emailVerifiedAt',
24
+ 'email_verified_at',
25
+ ];
26
+ /**
27
+ * Serializes a record according to the Laravel `asRhinoJson` contract:
28
+ *
29
+ * 1. Merge computed attributes
30
+ * 2. Remove base-hidden columns
31
+ * 3. Remove model-level `additionalHiddenColumns`
32
+ * 4. Apply policy blacklist (`hiddenAttributesForShow`)
33
+ * 5. Apply policy whitelist (`permittedAttributesForShow`) — `id` always kept
34
+ */
35
+ let SerializerService = class SerializerService {
36
+ /**
37
+ * @param record The raw record to serialize (from Prisma).
38
+ * @param reg The model registration driving policy + computed attrs.
39
+ * @param ctx Either a `SerializeContext` object (preferred) or a
40
+ * legacy `user` value (backwards-compat shim — org will
41
+ * be undefined and role-keyed policies will collapse).
42
+ */
43
+ serializeOne(record, reg, ctx) {
44
+ if (!record)
45
+ return record;
46
+ const { user, organization } = this.normalizeCtx(ctx);
47
+ let result = { ...record };
48
+ if (reg.computedAttributes) {
49
+ Object.assign(result, reg.computedAttributes(record, user));
50
+ }
51
+ for (const col of exports.BASE_HIDDEN_COLUMNS) {
52
+ delete result[col];
53
+ }
54
+ if (reg.additionalHiddenColumns?.length) {
55
+ for (const col of reg.additionalHiddenColumns)
56
+ delete result[col];
57
+ }
58
+ if (reg.policy) {
59
+ const policy = new reg.policy();
60
+ // BP-007: pass organization as the second argument so policy methods
61
+ // that call `this.hasRole(user, 'admin', org)` can resolve the active
62
+ // role. Base ResourcePolicy signatures accept an optional org.
63
+ const hidden = policy.hiddenAttributesForShow(user, organization) ?? [];
64
+ for (const col of hidden)
65
+ delete result[col];
66
+ const permitted = policy.permittedAttributesForShow(user, organization) ?? ['*'];
67
+ if (!(permitted.length === 1 && permitted[0] === '*')) {
68
+ const keep = new Set([...permitted, 'id']);
69
+ result = Object.fromEntries(Object.entries(result).filter(([k]) => keep.has(k)));
70
+ }
71
+ }
72
+ return result;
73
+ }
74
+ serializeMany(records, reg, ctx) {
75
+ return records.map((r) => this.serializeOne(r, reg, ctx));
76
+ }
77
+ normalizeCtx(ctx) {
78
+ // New call shape: { user, organization }
79
+ if (ctx && typeof ctx === 'object' && ('user' in ctx || 'organization' in ctx)) {
80
+ return { user: ctx.user, organization: ctx.organization };
81
+ }
82
+ // Legacy call shape: a bare user (or null/undefined)
83
+ return { user: ctx, organization: undefined };
84
+ }
85
+ };
86
+ exports.SerializerService = SerializerService;
87
+ exports.SerializerService = SerializerService = __decorate([
88
+ (0, common_1.Injectable)()
89
+ ], SerializerService);
90
+ //# sourceMappingURL=serializer.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializer.service.js","sourceRoot":"","sources":["../../src/services/serializer.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { ModelRegistration } from '../interfaces/rhino-config.interface';
2
+ import { PrismaService } from '../prisma/prisma.service';
3
+ import { RhinoConfigService } from '../rhino.config';
4
+ export interface ValidationResult<T = Record<string, any>> {
5
+ valid: boolean;
6
+ data?: T;
7
+ errors?: Record<string, string[]>;
8
+ forbiddenFields?: string[];
9
+ }
10
+ export interface ValidationContext {
11
+ user?: any;
12
+ organization?: any;
13
+ action: 'store' | 'update';
14
+ }
15
+ /**
16
+ * Validates request data against a registered model's Zod schema.
17
+ *
18
+ * Responsibilities mirror Laravel's HasValidation trait:
19
+ * - Pick schema based on action (store/update), with role-keyed overrides
20
+ * - Intersect fields with policy's `permittedAttributesFor{Create,Update}`
21
+ * - Reject forbidden fields (HTTP 403 semantics; returned in errors)
22
+ * - Strip the `organizationId` field from user-supplied input when in tenant context
23
+ */
24
+ export interface FkConstraint {
25
+ field: string;
26
+ model: string;
27
+ }
28
+ export declare class ValidationService {
29
+ private readonly prisma?;
30
+ private readonly config?;
31
+ constructor(prisma?: PrismaService, config?: RhinoConfigService);
32
+ /**
33
+ * Verify that every foreign-key in `data` references a record that lives
34
+ * inside the current organization (directly or through an FK chain). This
35
+ * implements Laravel's `scopeExistsRulesToOrganization` semantics for Prisma.
36
+ *
37
+ * Constraints are declared per model via:
38
+ * ModelRegistration.fkConstraints?: Array<{ field: 'postId', model: 'post' }>
39
+ */
40
+ verifyTenantFks(data: Record<string, any>, reg: ModelRegistration, organization?: any): Promise<{
41
+ valid: boolean;
42
+ errors?: Record<string, string[]>;
43
+ }>;
44
+ private isFkInOrg;
45
+ private walkFkChainForRecord;
46
+ validateForAction<T = Record<string, any>>(data: Record<string, any>, reg: ModelRegistration, ctx: ValidationContext): ValidationResult<T>;
47
+ private pickSchema;
48
+ private resolvePermittedFields;
49
+ private formatErrors;
50
+ }