@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.
- package/LICENSE +21 -0
- package/README.md +427 -0
- package/dist/blueprint/blueprint-parser.d.ts +130 -0
- package/dist/blueprint/blueprint-parser.js +276 -0
- package/dist/blueprint/blueprint-parser.js.map +1 -0
- package/dist/blueprint/blueprint-runner.d.ts +51 -0
- package/dist/blueprint/blueprint-runner.js +238 -0
- package/dist/blueprint/blueprint-runner.js.map +1 -0
- package/dist/blueprint/blueprint-validator.d.ts +19 -0
- package/dist/blueprint/blueprint-validator.js +163 -0
- package/dist/blueprint/blueprint-validator.js.map +1 -0
- package/dist/blueprint/generators/policy-generator.d.ts +40 -0
- package/dist/blueprint/generators/policy-generator.js +157 -0
- package/dist/blueprint/generators/policy-generator.js.map +1 -0
- package/dist/blueprint/generators/prisma-schema-generator.d.ts +43 -0
- package/dist/blueprint/generators/prisma-schema-generator.js +197 -0
- package/dist/blueprint/generators/prisma-schema-generator.js.map +1 -0
- package/dist/blueprint/generators/resource-definition-generator.d.ts +52 -0
- package/dist/blueprint/generators/resource-definition-generator.js +229 -0
- package/dist/blueprint/generators/resource-definition-generator.js.map +1 -0
- package/dist/blueprint/generators/seeder-generator.d.ts +21 -0
- package/dist/blueprint/generators/seeder-generator.js +135 -0
- package/dist/blueprint/generators/seeder-generator.js.map +1 -0
- package/dist/blueprint/generators/test-generator.d.ts +28 -0
- package/dist/blueprint/generators/test-generator.js +275 -0
- package/dist/blueprint/generators/test-generator.js.map +1 -0
- package/dist/blueprint/manifest-manager.d.ts +58 -0
- package/dist/blueprint/manifest-manager.js +137 -0
- package/dist/blueprint/manifest-manager.js.map +1 -0
- package/dist/cli/commands/blueprint.command.d.ts +16 -0
- package/dist/cli/commands/blueprint.command.js +35 -0
- package/dist/cli/commands/blueprint.command.js.map +1 -0
- package/dist/cli/commands/export-postman.command.d.ts +5 -0
- package/dist/cli/commands/export-postman.command.js +39 -0
- package/dist/cli/commands/export-postman.command.js.map +1 -0
- package/dist/cli/commands/export-types.command.d.ts +4 -0
- package/dist/cli/commands/export-types.command.js +36 -0
- package/dist/cli/commands/export-types.command.js.map +1 -0
- package/dist/cli/commands/generate.command.d.ts +6 -0
- package/dist/cli/commands/generate.command.js +212 -0
- package/dist/cli/commands/generate.command.js.map +1 -0
- package/dist/cli/commands/install.command.d.ts +8 -0
- package/dist/cli/commands/install.command.js +205 -0
- package/dist/cli/commands/install.command.js.map +1 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.js +123 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils/io.d.ts +12 -0
- package/dist/cli/utils/io.js +74 -0
- package/dist/cli/utils/io.js.map +1 -0
- package/dist/cli/utils/prompt.d.ts +12 -0
- package/dist/cli/utils/prompt.js +78 -0
- package/dist/cli/utils/prompt.js.map +1 -0
- package/dist/constants/tokens.d.ts +3 -0
- package/dist/constants/tokens.js +7 -0
- package/dist/constants/tokens.js.map +1 -0
- package/dist/controllers/auth.controller.d.ts +59 -0
- package/dist/controllers/auth.controller.js +121 -0
- package/dist/controllers/auth.controller.js.map +1 -0
- package/dist/controllers/global.controller.d.ts +44 -0
- package/dist/controllers/global.controller.js +357 -0
- package/dist/controllers/global.controller.js.map +1 -0
- package/dist/controllers/invitation.controller.d.ts +30 -0
- package/dist/controllers/invitation.controller.js +111 -0
- package/dist/controllers/invitation.controller.js.map +1 -0
- package/dist/controllers/nested.controller.d.ts +12 -0
- package/dist/controllers/nested.controller.js +69 -0
- package/dist/controllers/nested.controller.js.map +1 -0
- package/dist/decorators/index.d.ts +33 -0
- package/dist/decorators/index.js +79 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/errors/rhino-exception.d.ts +24 -0
- package/dist/errors/rhino-exception.js +47 -0
- package/dist/errors/rhino-exception.js.map +1 -0
- package/dist/exporters/postman-exporter.d.ts +21 -0
- package/dist/exporters/postman-exporter.js +396 -0
- package/dist/exporters/postman-exporter.js.map +1 -0
- package/dist/exporters/typescript-exporter.d.ts +23 -0
- package/dist/exporters/typescript-exporter.js +129 -0
- package/dist/exporters/typescript-exporter.js.map +1 -0
- package/dist/guards/jwt-auth.guard.d.ts +16 -0
- package/dist/guards/jwt-auth.guard.js +61 -0
- package/dist/guards/jwt-auth.guard.js.map +1 -0
- package/dist/guards/resource-policy.guard.d.ts +12 -0
- package/dist/guards/resource-policy.guard.js +111 -0
- package/dist/guards/resource-policy.guard.js.map +1 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +171 -0
- package/dist/index.js.map +1 -0
- package/dist/interceptors/hidden-columns.interceptor.d.ts +18 -0
- package/dist/interceptors/hidden-columns.interceptor.js +66 -0
- package/dist/interceptors/hidden-columns.interceptor.js.map +1 -0
- package/dist/interceptors/response.interceptor.d.ts +19 -0
- package/dist/interceptors/response.interceptor.js +47 -0
- package/dist/interceptors/response.interceptor.js.map +1 -0
- package/dist/interfaces/rhino-config.interface.d.ts +103 -0
- package/dist/interfaces/rhino-config.interface.js +3 -0
- package/dist/interfaces/rhino-config.interface.js.map +1 -0
- package/dist/interfaces/rhino-request.interface.d.ts +12 -0
- package/dist/interfaces/rhino-request.interface.js +3 -0
- package/dist/interfaces/rhino-request.interface.js.map +1 -0
- package/dist/middleware/resolve-organization.middleware.d.ts +15 -0
- package/dist/middleware/resolve-organization.middleware.js +38 -0
- package/dist/middleware/resolve-organization.middleware.js.map +1 -0
- package/dist/middleware/route-group.middleware.d.ts +17 -0
- package/dist/middleware/route-group.middleware.js +60 -0
- package/dist/middleware/route-group.middleware.js.map +1 -0
- package/dist/middleware/tenant-route-rewrite.d.ts +76 -0
- package/dist/middleware/tenant-route-rewrite.js +124 -0
- package/dist/middleware/tenant-route-rewrite.js.map +1 -0
- package/dist/policies/resource-policy.d.ts +25 -0
- package/dist/policies/resource-policy.js +77 -0
- package/dist/policies/resource-policy.js.map +1 -0
- package/dist/prisma/prisma-soft-delete.extension.d.ts +16 -0
- package/dist/prisma/prisma-soft-delete.extension.js +57 -0
- package/dist/prisma/prisma-soft-delete.extension.js.map +1 -0
- package/dist/prisma/prisma-uuid.extension.d.ts +9 -0
- package/dist/prisma/prisma-uuid.extension.js +28 -0
- package/dist/prisma/prisma-uuid.extension.js.map +1 -0
- package/dist/prisma/prisma.service.d.ts +38 -0
- package/dist/prisma/prisma.service.js +100 -0
- package/dist/prisma/prisma.service.js.map +1 -0
- package/dist/rhino.config.d.ts +43 -0
- package/dist/rhino.config.js +130 -0
- package/dist/rhino.config.js.map +1 -0
- package/dist/rhino.module.d.ts +61 -0
- package/dist/rhino.module.js +268 -0
- package/dist/rhino.module.js.map +1 -0
- package/dist/services/audit.service.d.ts +35 -0
- package/dist/services/audit.service.js +92 -0
- package/dist/services/audit.service.js.map +1 -0
- package/dist/services/auth.service.d.ts +33 -0
- package/dist/services/auth.service.js +157 -0
- package/dist/services/auth.service.js.map +1 -0
- package/dist/services/invitation.service.d.ts +37 -0
- package/dist/services/invitation.service.js +143 -0
- package/dist/services/invitation.service.js.map +1 -0
- package/dist/services/nested.service.d.ts +34 -0
- package/dist/services/nested.service.js +163 -0
- package/dist/services/nested.service.js.map +1 -0
- package/dist/services/organization.service.d.ts +13 -0
- package/dist/services/organization.service.js +60 -0
- package/dist/services/organization.service.js.map +1 -0
- package/dist/services/query-builder.service.d.ts +31 -0
- package/dist/services/query-builder.service.js +151 -0
- package/dist/services/query-builder.service.js.map +1 -0
- package/dist/services/resource.service.d.ts +38 -0
- package/dist/services/resource.service.js +230 -0
- package/dist/services/resource.service.js.map +1 -0
- package/dist/services/route-registration.service.d.ts +40 -0
- package/dist/services/route-registration.service.js +68 -0
- package/dist/services/route-registration.service.js.map +1 -0
- package/dist/services/scope.service.d.ts +16 -0
- package/dist/services/scope.service.js +32 -0
- package/dist/services/scope.service.js.map +1 -0
- package/dist/services/serializer.service.d.ts +36 -0
- package/dist/services/serializer.service.js +90 -0
- package/dist/services/serializer.service.js.map +1 -0
- package/dist/services/validation.service.d.ts +50 -0
- package/dist/services/validation.service.js +203 -0
- package/dist/services/validation.service.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/utils/fk-chain-walker.d.ts +30 -0
- package/dist/utils/fk-chain-walker.js +23 -0
- package/dist/utils/fk-chain-walker.js.map +1 -0
- package/dist/utils/format.d.ts +7 -0
- package/dist/utils/format.js +28 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/model-builder.d.ts +64 -0
- package/dist/utils/model-builder.js +67 -0
- package/dist/utils/model-builder.js.map +1 -0
- package/dist/utils/permission-matcher.d.ts +46 -0
- package/dist/utils/permission-matcher.js +120 -0
- package/dist/utils/permission-matcher.js.map +1 -0
- package/dist/utils/scope-discovery.d.ts +34 -0
- package/dist/utils/scope-discovery.js +102 -0
- package/dist/utils/scope-discovery.js.map +1 -0
- package/package.json +64 -0
- package/stubs/skills/rhino-audit.md +184 -0
- package/stubs/skills/rhino-bugfix.md +117 -0
- package/stubs/skills/rhino-deploy.md +5 -0
- package/stubs/skills/rhino-docs.md +147 -0
- package/stubs/skills/rhino-feature.md +146 -0
- package/stubs/skills/rhino-migrate.md +181 -0
- package/stubs/skills/rhino-model.md +180 -0
- package/stubs/skills/rhino-plan.md +5 -0
- package/stubs/skills/rhino-policy.md +183 -0
- package/stubs/skills/rhino-refactor.md +147 -0
- package/stubs/skills/rhino-review.md +113 -0
- package/stubs/skills/rhino-scope.md +140 -0
- package/stubs/skills/rhino-test.md +233 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BlueprintValidator = void 0;
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Valid values
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
const VALID_COLUMN_TYPES = [
|
|
8
|
+
'string', 'text', 'integer', 'bigInteger', 'boolean',
|
|
9
|
+
'date', 'datetime', 'timestamp', 'decimal', 'float',
|
|
10
|
+
'json', 'uuid', 'foreignId', 'enum',
|
|
11
|
+
];
|
|
12
|
+
const VALID_ACTIONS = [
|
|
13
|
+
'index', 'show', 'store', 'update', 'destroy',
|
|
14
|
+
'trashed', 'restore', 'forceDelete',
|
|
15
|
+
];
|
|
16
|
+
const VALID_RELATIONSHIP_TYPES = ['belongsTo', 'hasMany', 'hasOne', 'belongsToMany'];
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Validator
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
class BlueprintValidator {
|
|
21
|
+
/**
|
|
22
|
+
* Validate a parsed Blueprint. Returns errors and warnings.
|
|
23
|
+
*
|
|
24
|
+
* @param blueprint Parsed blueprint from BlueprintParser.parseModel()
|
|
25
|
+
* @param validRoles Optional array of known role slugs — enables stricter role checks
|
|
26
|
+
*/
|
|
27
|
+
validate(blueprint, validRoles = []) {
|
|
28
|
+
const errors = [];
|
|
29
|
+
const warnings = [];
|
|
30
|
+
// -- model name ----------------------------------------------------------
|
|
31
|
+
if (!blueprint.model) {
|
|
32
|
+
errors.push('Model name is required.');
|
|
33
|
+
}
|
|
34
|
+
else if (!/^[A-Z][a-zA-Z0-9]*$/.test(blueprint.model)) {
|
|
35
|
+
errors.push(`Model name '${blueprint.model}' must be PascalCase (e.g., 'Post', 'BlogPost').`);
|
|
36
|
+
}
|
|
37
|
+
// -- slug ----------------------------------------------------------------
|
|
38
|
+
if (blueprint.slug && !/^[a-z][a-z0-9_-]*$/.test(blueprint.slug)) {
|
|
39
|
+
errors.push(`Slug '${blueprint.slug}' must be lowercase alphanumeric with hyphens/underscores.`);
|
|
40
|
+
}
|
|
41
|
+
// -- columns -------------------------------------------------------------
|
|
42
|
+
const colErrors = this.validateColumns(blueprint.columns ?? []);
|
|
43
|
+
errors.push(...colErrors);
|
|
44
|
+
// -- permissions ---------------------------------------------------------
|
|
45
|
+
const columnNames = (blueprint.columns ?? []).map((c) => c.name);
|
|
46
|
+
const permResult = this.validatePermissions(blueprint.permissions ?? {}, validRoles, columnNames);
|
|
47
|
+
errors.push(...permResult.errors);
|
|
48
|
+
warnings.push(...permResult.warnings);
|
|
49
|
+
// -- options -------------------------------------------------------------
|
|
50
|
+
const optErrors = this.validateOptions(blueprint.options);
|
|
51
|
+
errors.push(...optErrors);
|
|
52
|
+
// -- relationships -------------------------------------------------------
|
|
53
|
+
const relErrors = this.validateRelationships(blueprint.relationships ?? []);
|
|
54
|
+
errors.push(...relErrors);
|
|
55
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
56
|
+
}
|
|
57
|
+
// -------------------------------------------------------------------------
|
|
58
|
+
// Section validators
|
|
59
|
+
// -------------------------------------------------------------------------
|
|
60
|
+
validateColumns(columns) {
|
|
61
|
+
const errors = [];
|
|
62
|
+
const seen = new Set();
|
|
63
|
+
for (const col of columns) {
|
|
64
|
+
if (!col.name) {
|
|
65
|
+
errors.push('Column name cannot be empty.');
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (seen.has(col.name)) {
|
|
69
|
+
errors.push(`Duplicate column name: '${col.name}'.`);
|
|
70
|
+
}
|
|
71
|
+
seen.add(col.name);
|
|
72
|
+
if (!VALID_COLUMN_TYPES.includes(col.type)) {
|
|
73
|
+
errors.push(`Column '${col.name}' has invalid type '${col.type}'. Valid types: ${VALID_COLUMN_TYPES.join(', ')}.`);
|
|
74
|
+
}
|
|
75
|
+
if (col.type === 'foreignId' && !col.foreignModel) {
|
|
76
|
+
errors.push(`Column '${col.name}' has type foreignId but is missing 'foreign_model'.`);
|
|
77
|
+
}
|
|
78
|
+
if (col.type === 'enum' && (!col.values || col.values.length === 0)) {
|
|
79
|
+
errors.push(`Column '${col.name}' has type enum but is missing 'values'.`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return errors;
|
|
83
|
+
}
|
|
84
|
+
validatePermissions(permissions, validRoles, columnNames) {
|
|
85
|
+
const errors = [];
|
|
86
|
+
const warnings = [];
|
|
87
|
+
for (const [role, def] of Object.entries(permissions)) {
|
|
88
|
+
// Validate role exists (if roles list provided)
|
|
89
|
+
if (validRoles.length > 0 && !validRoles.includes(role)) {
|
|
90
|
+
errors.push(`Permission defined for unknown role '${role}'. Define it in your roles list first.`);
|
|
91
|
+
}
|
|
92
|
+
// Validate actions
|
|
93
|
+
for (const action of def.actions ?? []) {
|
|
94
|
+
if (!VALID_ACTIONS.includes(action)) {
|
|
95
|
+
errors.push(`Role '${role}' has invalid action '${action}'. Valid actions: ${VALID_ACTIONS.join(', ')}.`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Warn about unknown fields in show_fields
|
|
99
|
+
const showFields = def.show_fields ?? [];
|
|
100
|
+
if (showFields[0] !== '*' && columnNames.length > 0) {
|
|
101
|
+
for (const field of showFields) {
|
|
102
|
+
if (field !== 'id' && !columnNames.includes(field)) {
|
|
103
|
+
warnings.push(`Role '${role}' references unknown field '${field}' in show_fields.`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Conflicts: field in both show_fields and hidden_fields
|
|
108
|
+
const hiddenFields = def.hidden_fields ?? [];
|
|
109
|
+
if (showFields[0] !== '*' && hiddenFields.length > 0) {
|
|
110
|
+
const conflicts = showFields.filter((f) => hiddenFields.includes(f));
|
|
111
|
+
if (conflicts.length > 0) {
|
|
112
|
+
warnings.push(`Role '${role}' has fields in both show_fields and hidden_fields: ${conflicts.join(', ')}.`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Warn if create_fields defined without store action
|
|
116
|
+
const createFields = def.create_fields;
|
|
117
|
+
const hasCreateFields = createFields &&
|
|
118
|
+
!(Array.isArray(createFields) && createFields[0] === '*') &&
|
|
119
|
+
(Array.isArray(createFields) ? createFields.length > 0 : Object.keys(createFields).length > 0);
|
|
120
|
+
if (hasCreateFields && !def.actions.includes('store')) {
|
|
121
|
+
warnings.push(`Role '${role}' has create_fields but no 'store' action.`);
|
|
122
|
+
}
|
|
123
|
+
// Warn if update_fields defined without update action
|
|
124
|
+
const updateFields = def.update_fields;
|
|
125
|
+
const hasUpdateFields = updateFields &&
|
|
126
|
+
!(Array.isArray(updateFields) && updateFields[0] === '*') &&
|
|
127
|
+
(Array.isArray(updateFields) ? updateFields.length > 0 : Object.keys(updateFields).length > 0);
|
|
128
|
+
if (hasUpdateFields && !def.actions.includes('update')) {
|
|
129
|
+
warnings.push(`Role '${role}' has update_fields but no 'update' action.`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { errors, warnings };
|
|
133
|
+
}
|
|
134
|
+
validateOptions(options) {
|
|
135
|
+
const errors = [];
|
|
136
|
+
if (!options)
|
|
137
|
+
return errors;
|
|
138
|
+
for (const action of options.except_actions ?? []) {
|
|
139
|
+
if (!VALID_ACTIONS.includes(action)) {
|
|
140
|
+
errors.push(`Invalid except_action: '${action}'.`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return errors;
|
|
144
|
+
}
|
|
145
|
+
validateRelationships(relationships) {
|
|
146
|
+
const errors = [];
|
|
147
|
+
for (const rel of relationships) {
|
|
148
|
+
if (!rel.type) {
|
|
149
|
+
errors.push('Relationship is missing type.');
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (!VALID_RELATIONSHIP_TYPES.includes(rel.type)) {
|
|
153
|
+
errors.push(`Invalid relationship type '${rel.type}'. Valid: ${VALID_RELATIONSHIP_TYPES.join(', ')}.`);
|
|
154
|
+
}
|
|
155
|
+
if (!rel.model) {
|
|
156
|
+
errors.push(`Relationship '${rel.name}' of type '${rel.type}' is missing model.`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return errors;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.BlueprintValidator = BlueprintValidator;
|
|
163
|
+
//# sourceMappingURL=blueprint-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprint-validator.js","sourceRoot":"","sources":["../../src/blueprint/blueprint-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Blueprint, BlueprintPermission } from '../blueprint-parser';
|
|
2
|
+
/**
|
|
3
|
+
* Generates a TypeScript Policy class extending `ResourcePolicy`.
|
|
4
|
+
*
|
|
5
|
+
* The generated class overrides:
|
|
6
|
+
* - `permittedAttributesForShow` — from `show_fields`
|
|
7
|
+
* - `hiddenAttributesForShow` — from `hidden_fields`
|
|
8
|
+
* - `permittedAttributesForCreate` — from `create_fields`
|
|
9
|
+
* - `permittedAttributesForUpdate` — from `update_fields`
|
|
10
|
+
*
|
|
11
|
+
* Each method uses `this.hasRole(user, '<role>', org)` guards identical to the
|
|
12
|
+
* Laravel reference implementation.
|
|
13
|
+
*/
|
|
14
|
+
export declare class PolicyGenerator {
|
|
15
|
+
generate(blueprint: Blueprint): string;
|
|
16
|
+
/**
|
|
17
|
+
* Build a `permittedAttributesFor*` method.
|
|
18
|
+
* Groups roles with identical field sets to avoid repetitive if-branches.
|
|
19
|
+
*/
|
|
20
|
+
buildPermittedMethod(methodName: string, permissions: Record<string, BlueprintPermission>, fieldKey: 'show_fields' | 'create_fields' | 'update_fields'): string;
|
|
21
|
+
buildHiddenMethod(permissions: Record<string, BlueprintPermission>): string;
|
|
22
|
+
/**
|
|
23
|
+
* Group roles that share the same field set for a given field key.
|
|
24
|
+
*/
|
|
25
|
+
groupRolesByFields(permissions: Record<string, BlueprintPermission>, fieldKey: 'show_fields' | 'create_fields' | 'update_fields'): Array<{
|
|
26
|
+
fields: unknown;
|
|
27
|
+
roles: string[];
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Normalise `fields` to a string array or null.
|
|
31
|
+
* - ['*'] / '*' → ['*']
|
|
32
|
+
* - string[] → as-is
|
|
33
|
+
* - Record<string, string> → Object.keys(…)
|
|
34
|
+
* - [] / {} / null → null (skip)
|
|
35
|
+
*/
|
|
36
|
+
private toFieldsArray;
|
|
37
|
+
buildCondition(roles: string[]): string;
|
|
38
|
+
fieldsToTsArray(fields: string[]): string;
|
|
39
|
+
private wrapMethod;
|
|
40
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PolicyGenerator = void 0;
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// PolicyGenerator
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
/**
|
|
8
|
+
* Generates a TypeScript Policy class extending `ResourcePolicy`.
|
|
9
|
+
*
|
|
10
|
+
* The generated class overrides:
|
|
11
|
+
* - `permittedAttributesForShow` — from `show_fields`
|
|
12
|
+
* - `hiddenAttributesForShow` — from `hidden_fields`
|
|
13
|
+
* - `permittedAttributesForCreate` — from `create_fields`
|
|
14
|
+
* - `permittedAttributesForUpdate` — from `update_fields`
|
|
15
|
+
*
|
|
16
|
+
* Each method uses `this.hasRole(user, '<role>', org)` guards identical to the
|
|
17
|
+
* Laravel reference implementation.
|
|
18
|
+
*/
|
|
19
|
+
class PolicyGenerator {
|
|
20
|
+
generate(blueprint) {
|
|
21
|
+
const { model, slug, permissions } = blueprint;
|
|
22
|
+
const policyName = `${model}Policy`;
|
|
23
|
+
const showMethod = this.buildPermittedMethod('permittedAttributesForShow', permissions, 'show_fields');
|
|
24
|
+
const hiddenMethod = this.buildHiddenMethod(permissions);
|
|
25
|
+
const createMethod = this.buildPermittedMethod('permittedAttributesForCreate', permissions, 'create_fields');
|
|
26
|
+
const updateMethod = this.buildPermittedMethod('permittedAttributesForUpdate', permissions, 'update_fields');
|
|
27
|
+
return [
|
|
28
|
+
`// Generated by Rhino Blueprint — do not edit directly.`,
|
|
29
|
+
`// Source: .rhino/blueprints/${blueprint.source_file}`,
|
|
30
|
+
`import { ResourcePolicy } from '@rhino-dev/rhino-nestjs';`,
|
|
31
|
+
``,
|
|
32
|
+
`/**`,
|
|
33
|
+
` * Authorization policy for the ${model} resource.`,
|
|
34
|
+
` * Regenerate with: npx rhino blueprint`,
|
|
35
|
+
` */`,
|
|
36
|
+
`export class ${policyName} extends ResourcePolicy {`,
|
|
37
|
+
` override resourceSlug = '${slug}';`,
|
|
38
|
+
``,
|
|
39
|
+
showMethod,
|
|
40
|
+
``,
|
|
41
|
+
hiddenMethod,
|
|
42
|
+
``,
|
|
43
|
+
createMethod,
|
|
44
|
+
``,
|
|
45
|
+
updateMethod,
|
|
46
|
+
`}`,
|
|
47
|
+
``,
|
|
48
|
+
].join('\n');
|
|
49
|
+
}
|
|
50
|
+
// -------------------------------------------------------------------------
|
|
51
|
+
// Method builders
|
|
52
|
+
// -------------------------------------------------------------------------
|
|
53
|
+
/**
|
|
54
|
+
* Build a `permittedAttributesFor*` method.
|
|
55
|
+
* Groups roles with identical field sets to avoid repetitive if-branches.
|
|
56
|
+
*/
|
|
57
|
+
buildPermittedMethod(methodName, permissions, fieldKey) {
|
|
58
|
+
if (Object.keys(permissions).length === 0) {
|
|
59
|
+
return this.wrapMethod(methodName, ` return ['*'];`);
|
|
60
|
+
}
|
|
61
|
+
const groups = this.groupRolesByFields(permissions, fieldKey);
|
|
62
|
+
const bodyLines = [];
|
|
63
|
+
for (const { fields, roles } of groups) {
|
|
64
|
+
const fieldArr = this.toFieldsArray(fields);
|
|
65
|
+
if (!fieldArr || fieldArr.length === 0)
|
|
66
|
+
continue; // skip roles with no fields
|
|
67
|
+
const condition = this.buildCondition(roles);
|
|
68
|
+
bodyLines.push(` if (${condition}) {`);
|
|
69
|
+
bodyLines.push(` return ${this.fieldsToTsArray(fieldArr)};`);
|
|
70
|
+
bodyLines.push(` }`);
|
|
71
|
+
}
|
|
72
|
+
bodyLines.push(` return [];`);
|
|
73
|
+
return this.wrapMethod(methodName, bodyLines.join('\n'));
|
|
74
|
+
}
|
|
75
|
+
buildHiddenMethod(permissions) {
|
|
76
|
+
const rolesWithHidden = {};
|
|
77
|
+
for (const [role, def] of Object.entries(permissions)) {
|
|
78
|
+
if (def.hidden_fields?.length > 0) {
|
|
79
|
+
rolesWithHidden[role] = def.hidden_fields;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (Object.keys(rolesWithHidden).length === 0) {
|
|
83
|
+
return this.wrapMethod('hiddenAttributesForShow', ` return [];`);
|
|
84
|
+
}
|
|
85
|
+
// Group by field set
|
|
86
|
+
const groups = new Map();
|
|
87
|
+
for (const [role, fields] of Object.entries(rolesWithHidden)) {
|
|
88
|
+
const key = JSON.stringify(fields);
|
|
89
|
+
if (!groups.has(key))
|
|
90
|
+
groups.set(key, { fields, roles: [] });
|
|
91
|
+
groups.get(key).roles.push(role);
|
|
92
|
+
}
|
|
93
|
+
const bodyLines = [];
|
|
94
|
+
for (const { fields, roles } of groups.values()) {
|
|
95
|
+
const condition = this.buildCondition(roles);
|
|
96
|
+
bodyLines.push(` if (${condition}) {`);
|
|
97
|
+
bodyLines.push(` return ${this.fieldsToTsArray(fields)};`);
|
|
98
|
+
bodyLines.push(` }`);
|
|
99
|
+
}
|
|
100
|
+
bodyLines.push(` return [];`);
|
|
101
|
+
return this.wrapMethod('hiddenAttributesForShow', bodyLines.join('\n'));
|
|
102
|
+
}
|
|
103
|
+
// -------------------------------------------------------------------------
|
|
104
|
+
// Helpers
|
|
105
|
+
// -------------------------------------------------------------------------
|
|
106
|
+
/**
|
|
107
|
+
* Group roles that share the same field set for a given field key.
|
|
108
|
+
*/
|
|
109
|
+
groupRolesByFields(permissions, fieldKey) {
|
|
110
|
+
const groups = new Map();
|
|
111
|
+
for (const [role, def] of Object.entries(permissions)) {
|
|
112
|
+
const fields = def[fieldKey];
|
|
113
|
+
const key = JSON.stringify(fields);
|
|
114
|
+
if (!groups.has(key))
|
|
115
|
+
groups.set(key, { fields, roles: [] });
|
|
116
|
+
groups.get(key).roles.push(role);
|
|
117
|
+
}
|
|
118
|
+
return Array.from(groups.values());
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Normalise `fields` to a string array or null.
|
|
122
|
+
* - ['*'] / '*' → ['*']
|
|
123
|
+
* - string[] → as-is
|
|
124
|
+
* - Record<string, string> → Object.keys(…)
|
|
125
|
+
* - [] / {} / null → null (skip)
|
|
126
|
+
*/
|
|
127
|
+
toFieldsArray(fields) {
|
|
128
|
+
if (fields === '*' || (Array.isArray(fields) && fields[0] === '*'))
|
|
129
|
+
return ['*'];
|
|
130
|
+
if (Array.isArray(fields))
|
|
131
|
+
return fields.length > 0 ? fields : null;
|
|
132
|
+
if (fields && typeof fields === 'object') {
|
|
133
|
+
const keys = Object.keys(fields);
|
|
134
|
+
return keys.length > 0 ? keys : null;
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
buildCondition(roles) {
|
|
139
|
+
const parts = roles.map((r) => `this.hasRole(user, '${r}', org)`);
|
|
140
|
+
return parts.join(' ||\n ');
|
|
141
|
+
}
|
|
142
|
+
fieldsToTsArray(fields) {
|
|
143
|
+
if (fields[0] === '*')
|
|
144
|
+
return `['*']`;
|
|
145
|
+
const items = fields.map((f) => `'${f}'`).join(', ');
|
|
146
|
+
return `[${items}]`;
|
|
147
|
+
}
|
|
148
|
+
wrapMethod(name, body) {
|
|
149
|
+
return [
|
|
150
|
+
` override ${name}(user: any, org?: any): string[] {`,
|
|
151
|
+
body,
|
|
152
|
+
` }`,
|
|
153
|
+
].join('\n');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.PolicyGenerator = PolicyGenerator;
|
|
157
|
+
//# sourceMappingURL=policy-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-generator.js","sourceRoot":"","sources":["../../../src/blueprint/generators/policy-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Blueprint } from '../blueprint-parser';
|
|
2
|
+
export type PrismaProvider = 'sqlite' | 'postgresql' | 'mysql' | 'sqlserver' | 'mongodb';
|
|
3
|
+
export interface PrismaSchemaGenerateOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Target datasource provider. SQLite has no native Decimal; `decimal`
|
|
6
|
+
* columns map to `Float` for SQLite and `Decimal` elsewhere. Defaults to
|
|
7
|
+
* `postgresql`.
|
|
8
|
+
*/
|
|
9
|
+
provider?: PrismaProvider;
|
|
10
|
+
/**
|
|
11
|
+
* Existing `prisma/schema.prisma` content. When provided, any model whose
|
|
12
|
+
* name already appears is SKIPPED — the generator returns an empty string
|
|
13
|
+
* for that model block. Consumer's hand-authored schemas are preserved.
|
|
14
|
+
* (BP-002 — no more duplicate `model Foo { ... }` blocks.)
|
|
15
|
+
*/
|
|
16
|
+
existingSchema?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generates a Prisma `model` block (plus any required enum declarations)
|
|
20
|
+
* from a Blueprint.
|
|
21
|
+
*
|
|
22
|
+
* BP-002 corrections:
|
|
23
|
+
* - Skip generation when the model already exists in `existingSchema`
|
|
24
|
+
* - Emit proper `@relation(fields, references)` for `foreignId` columns
|
|
25
|
+
* that name a `foreign_model`
|
|
26
|
+
* - Switch `decimal` → `Float` on SQLite; keep `Decimal` on other providers
|
|
27
|
+
* - Honor `has_uuid` for the primary key (already in place via BP-005)
|
|
28
|
+
*/
|
|
29
|
+
export declare class PrismaSchemaGenerator {
|
|
30
|
+
generate(blueprint: Blueprint, options?: PrismaSchemaGenerateOptions): string;
|
|
31
|
+
private generateEnum;
|
|
32
|
+
private generateModelBlock;
|
|
33
|
+
private generateRelationship;
|
|
34
|
+
private generateField;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Return true when the given schema text declares `model <name> { ... }`.
|
|
38
|
+
* Matches the canonical Prisma syntax; doesn't try to parse comments or
|
|
39
|
+
* unusual whitespace — just a pragmatic check for "is this name taken".
|
|
40
|
+
*/
|
|
41
|
+
export declare function modelExistsInSchema(schema: string, modelName: string): boolean;
|
|
42
|
+
/** Same, for top-level `enum <Name> { ... }` declarations. */
|
|
43
|
+
export declare function enumExistsInSchema(schema: string, enumName: string): boolean;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PrismaSchemaGenerator = void 0;
|
|
4
|
+
exports.modelExistsInSchema = modelExistsInSchema;
|
|
5
|
+
exports.enumExistsInSchema = enumExistsInSchema;
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Prisma type mapping
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
const BASE_TYPE_MAP = {
|
|
10
|
+
string: 'String',
|
|
11
|
+
text: 'String',
|
|
12
|
+
integer: 'Int',
|
|
13
|
+
bigInteger: 'BigInt',
|
|
14
|
+
boolean: 'Boolean',
|
|
15
|
+
date: 'DateTime',
|
|
16
|
+
datetime: 'DateTime',
|
|
17
|
+
timestamp: 'DateTime',
|
|
18
|
+
float: 'Float',
|
|
19
|
+
json: 'Json',
|
|
20
|
+
uuid: 'String',
|
|
21
|
+
foreignId: 'Int',
|
|
22
|
+
// decimal — provider-dependent (see typeFor)
|
|
23
|
+
// enum — handled specially
|
|
24
|
+
};
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// PrismaSchemaGenerator
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
/**
|
|
29
|
+
* Generates a Prisma `model` block (plus any required enum declarations)
|
|
30
|
+
* from a Blueprint.
|
|
31
|
+
*
|
|
32
|
+
* BP-002 corrections:
|
|
33
|
+
* - Skip generation when the model already exists in `existingSchema`
|
|
34
|
+
* - Emit proper `@relation(fields, references)` for `foreignId` columns
|
|
35
|
+
* that name a `foreign_model`
|
|
36
|
+
* - Switch `decimal` → `Float` on SQLite; keep `Decimal` on other providers
|
|
37
|
+
* - Honor `has_uuid` for the primary key (already in place via BP-005)
|
|
38
|
+
*/
|
|
39
|
+
class PrismaSchemaGenerator {
|
|
40
|
+
generate(blueprint, options = {}) {
|
|
41
|
+
const provider = options.provider ?? 'postgresql';
|
|
42
|
+
// BP-002: if the model already exists in the consumer's schema, produce
|
|
43
|
+
// NOTHING. This is the safe default — don't duplicate, don't overwrite.
|
|
44
|
+
if (options.existingSchema && modelExistsInSchema(options.existingSchema, blueprint.model)) {
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
const parts = [];
|
|
48
|
+
const existing = options.existingSchema ?? '';
|
|
49
|
+
for (const col of blueprint.columns) {
|
|
50
|
+
if (col.type === 'enum' && col.values?.length) {
|
|
51
|
+
const enumName = `${blueprint.model}${pascalCase(col.name)}`;
|
|
52
|
+
// Don't redeclare enums that already exist
|
|
53
|
+
if (!enumExistsInSchema(existing, enumName)) {
|
|
54
|
+
parts.push(this.generateEnum(enumName, col));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
parts.push(this.generateModelBlock(blueprint, provider));
|
|
59
|
+
return parts.join('\n\n');
|
|
60
|
+
}
|
|
61
|
+
// -------------------------------------------------------------------------
|
|
62
|
+
// Private helpers
|
|
63
|
+
// -------------------------------------------------------------------------
|
|
64
|
+
generateEnum(enumName, col) {
|
|
65
|
+
const values = (col.values ?? []).map((v) => ` ${v.toUpperCase()}`).join('\n');
|
|
66
|
+
return `enum ${enumName} {\n${values}\n}`;
|
|
67
|
+
}
|
|
68
|
+
generateModelBlock(blueprint, provider) {
|
|
69
|
+
const lines = [];
|
|
70
|
+
// -- id ---------------------------------------------------------------
|
|
71
|
+
if (blueprint.options.has_uuid) {
|
|
72
|
+
lines.push(' id String @id @default(uuid())');
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
lines.push(' id Int @id @default(autoincrement())');
|
|
76
|
+
}
|
|
77
|
+
// -- organizationId FK ------------------------------------------------
|
|
78
|
+
if (blueprint.options.belongs_to_organization) {
|
|
79
|
+
lines.push(' organizationId Int');
|
|
80
|
+
lines.push(' organization Organization @relation(fields: [organizationId], references: [id])');
|
|
81
|
+
}
|
|
82
|
+
// -- user-defined columns --------------------------------------------
|
|
83
|
+
// For `foreignId` columns with a `foreign_model`, emit the FK column
|
|
84
|
+
// immediately followed by the @relation field. Dedupe the relation fields
|
|
85
|
+
// emitted by `relationships:` so we don't generate both.
|
|
86
|
+
const fkColumnsWithRelation = new Set();
|
|
87
|
+
for (const col of blueprint.columns) {
|
|
88
|
+
lines.push(this.generateField(blueprint.model, col, provider));
|
|
89
|
+
if (col.type === 'foreignId' && col.foreignModel) {
|
|
90
|
+
fkColumnsWithRelation.add(col.name);
|
|
91
|
+
const relName = stripIdSuffix(col.name); // projectId → project
|
|
92
|
+
const modelRef = col.nullable ? `${col.foreignModel}?` : col.foreignModel;
|
|
93
|
+
lines.push(` ${relName.padEnd(12)} ${modelRef} @relation(fields: [${col.name}], references: [id])`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// -- relationships ----------------------------------------------------
|
|
97
|
+
for (const rel of blueprint.relationships) {
|
|
98
|
+
this.generateRelationship(rel, fkColumnsWithRelation, lines);
|
|
99
|
+
}
|
|
100
|
+
// -- timestamps -------------------------------------------------------
|
|
101
|
+
lines.push(' createdAt DateTime @default(now())');
|
|
102
|
+
lines.push(' updatedAt DateTime @updatedAt');
|
|
103
|
+
if (blueprint.options.soft_deletes) {
|
|
104
|
+
lines.push(' deletedAt DateTime?');
|
|
105
|
+
}
|
|
106
|
+
// -- @@map ------------------------------------------------------------
|
|
107
|
+
lines.push('');
|
|
108
|
+
lines.push(` @@map("${blueprint.table}")`);
|
|
109
|
+
return `model ${blueprint.model} {\n${lines.join('\n')}\n}`;
|
|
110
|
+
}
|
|
111
|
+
generateRelationship(rel, alreadyEmitted, lines) {
|
|
112
|
+
if (rel.type === 'belongsTo') {
|
|
113
|
+
// Skip when we already emitted this FK + @relation from a `foreignId`
|
|
114
|
+
// column (avoids duplicate relation fields).
|
|
115
|
+
const fkField = `${rel.name}Id`;
|
|
116
|
+
if (alreadyEmitted.has(fkField))
|
|
117
|
+
return;
|
|
118
|
+
lines.push(` ${fkField.padEnd(12)} Int`);
|
|
119
|
+
lines.push(` ${rel.name.padEnd(12)} ${rel.model} @relation(fields: [${fkField}], references: [id])`);
|
|
120
|
+
}
|
|
121
|
+
else if (rel.type === 'hasMany') {
|
|
122
|
+
lines.push(` ${rel.name.padEnd(12)} ${rel.model}[]`);
|
|
123
|
+
}
|
|
124
|
+
else if (rel.type === 'hasOne') {
|
|
125
|
+
lines.push(` ${rel.name.padEnd(12)} ${rel.model}?`);
|
|
126
|
+
}
|
|
127
|
+
// belongsToMany: join-table generation is deliberately out of scope;
|
|
128
|
+
// consumers declare the pivot model themselves.
|
|
129
|
+
}
|
|
130
|
+
generateField(modelName, col, provider) {
|
|
131
|
+
let prismaType;
|
|
132
|
+
let modifiers = '';
|
|
133
|
+
if (col.type === 'enum') {
|
|
134
|
+
prismaType = `${modelName}${pascalCase(col.name)}`;
|
|
135
|
+
}
|
|
136
|
+
else if (col.type === 'decimal') {
|
|
137
|
+
prismaType = provider === 'sqlite' ? 'Float' : 'Decimal';
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
prismaType = BASE_TYPE_MAP[col.type] ?? 'String';
|
|
141
|
+
}
|
|
142
|
+
if (col.nullable)
|
|
143
|
+
prismaType += '?';
|
|
144
|
+
// @default
|
|
145
|
+
if (col.default !== null && col.default !== undefined) {
|
|
146
|
+
if (col.type === 'boolean') {
|
|
147
|
+
modifiers += ` @default(${col.default})`;
|
|
148
|
+
}
|
|
149
|
+
else if (col.type === 'enum') {
|
|
150
|
+
modifiers += ` @default(${String(col.default).toUpperCase()})`;
|
|
151
|
+
}
|
|
152
|
+
else if (typeof col.default === 'string') {
|
|
153
|
+
modifiers += ` @default("${col.default}")`;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
modifiers += ` @default(${col.default})`;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// @unique
|
|
160
|
+
if (col.unique)
|
|
161
|
+
modifiers += ' @unique';
|
|
162
|
+
const paddedName = col.name.padEnd(12);
|
|
163
|
+
const paddedType = prismaType.padEnd(10);
|
|
164
|
+
return ` ${paddedName} ${paddedType}${modifiers}`;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.PrismaSchemaGenerator = PrismaSchemaGenerator;
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// Schema introspection helpers (tiny — no full AST needed)
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
/**
|
|
172
|
+
* Return true when the given schema text declares `model <name> { ... }`.
|
|
173
|
+
* Matches the canonical Prisma syntax; doesn't try to parse comments or
|
|
174
|
+
* unusual whitespace — just a pragmatic check for "is this name taken".
|
|
175
|
+
*/
|
|
176
|
+
function modelExistsInSchema(schema, modelName) {
|
|
177
|
+
const re = new RegExp(`^\\s*model\\s+${escapeRegex(modelName)}\\s*\\{`, 'm');
|
|
178
|
+
return re.test(schema);
|
|
179
|
+
}
|
|
180
|
+
/** Same, for top-level `enum <Name> { ... }` declarations. */
|
|
181
|
+
function enumExistsInSchema(schema, enumName) {
|
|
182
|
+
const re = new RegExp(`^\\s*enum\\s+${escapeRegex(enumName)}\\s*\\{`, 'm');
|
|
183
|
+
return re.test(schema);
|
|
184
|
+
}
|
|
185
|
+
function pascalCase(str) {
|
|
186
|
+
return str
|
|
187
|
+
.split(/[_\s-]+/)
|
|
188
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
189
|
+
.join('');
|
|
190
|
+
}
|
|
191
|
+
function stripIdSuffix(name) {
|
|
192
|
+
return name.endsWith('Id') ? name.slice(0, -2) : name;
|
|
193
|
+
}
|
|
194
|
+
function escapeRegex(s) {
|
|
195
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=prisma-schema-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prisma-schema-generator.js","sourceRoot":"","sources":["../../../src/blueprint/generators/prisma-schema-generator.ts"],"names":[],"mappings":"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"}
|