@rapidd/build 1.2.3 → 2.0.1
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/README.md +219 -68
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +31 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/src/commands/build.d.ts +17 -0
- package/dist/src/commands/build.d.ts.map +1 -0
- package/dist/src/commands/build.js +236 -0
- package/dist/src/commands/build.js.map +1 -0
- package/dist/src/generators/aclGenerator.d.ts +6 -0
- package/dist/src/generators/aclGenerator.d.ts.map +1 -0
- package/dist/src/generators/aclGenerator.js +384 -0
- package/dist/src/generators/aclGenerator.js.map +1 -0
- package/dist/src/generators/index.d.ts +4 -0
- package/dist/src/generators/index.d.ts.map +1 -0
- package/dist/src/generators/index.js +13 -0
- package/dist/src/generators/index.js.map +1 -0
- package/dist/src/generators/modelGenerator.d.ts +10 -0
- package/dist/src/generators/modelGenerator.d.ts.map +1 -0
- package/dist/src/generators/modelGenerator.js +143 -0
- package/dist/src/generators/modelGenerator.js.map +1 -0
- package/dist/src/generators/routeGenerator.d.ts +10 -0
- package/dist/src/generators/routeGenerator.d.ts.map +1 -0
- package/dist/src/generators/routeGenerator.js +148 -0
- package/dist/src/generators/routeGenerator.js.map +1 -0
- package/dist/src/parsers/datasourceParser.d.ts +11 -0
- package/dist/src/parsers/datasourceParser.d.ts.map +1 -0
- package/dist/src/parsers/datasourceParser.js +131 -0
- package/dist/src/parsers/datasourceParser.js.map +1 -0
- package/dist/src/parsers/deepSQLAnalyzer.d.ts +85 -0
- package/dist/src/parsers/deepSQLAnalyzer.d.ts.map +1 -0
- package/dist/src/parsers/deepSQLAnalyzer.js +482 -0
- package/dist/src/parsers/deepSQLAnalyzer.js.map +1 -0
- package/dist/src/parsers/enhancedRLSConverter.d.ts +14 -0
- package/dist/src/parsers/enhancedRLSConverter.d.ts.map +1 -0
- package/dist/src/parsers/enhancedRLSConverter.js +168 -0
- package/dist/src/parsers/enhancedRLSConverter.js.map +1 -0
- package/dist/src/parsers/functionAnalyzer.d.ts +55 -0
- package/dist/src/parsers/functionAnalyzer.d.ts.map +1 -0
- package/dist/src/parsers/functionAnalyzer.js +274 -0
- package/dist/src/parsers/functionAnalyzer.js.map +1 -0
- package/dist/src/parsers/index.d.ts +13 -0
- package/dist/src/parsers/index.d.ts.map +1 -0
- package/dist/src/parsers/index.js +20 -0
- package/dist/src/parsers/index.js.map +1 -0
- package/dist/src/parsers/prismaFilterBuilder.d.ts +79 -0
- package/dist/src/parsers/prismaFilterBuilder.d.ts.map +1 -0
- package/dist/src/parsers/prismaFilterBuilder.js +322 -0
- package/dist/src/parsers/prismaFilterBuilder.js.map +1 -0
- package/dist/src/parsers/prismaParser.d.ts +14 -0
- package/dist/src/parsers/prismaParser.d.ts.map +1 -0
- package/dist/src/parsers/prismaParser.js +263 -0
- package/dist/src/parsers/prismaParser.js.map +1 -0
- package/package.json +21 -13
- package/bin/cli.js +0 -33
- package/index.js +0 -11
- package/src/commands/build.js +0 -638
- package/src/generators/aclGenerator.js +0 -394
- package/src/generators/modelGenerator.js +0 -174
- package/src/generators/relationshipsGenerator.js +0 -200
- package/src/generators/routeGenerator.js +0 -119
- package/src/parsers/datasourceParser.js +0 -121
- package/src/parsers/deepSQLAnalyzer.js +0 -554
- package/src/parsers/enhancedRLSConverter.js +0 -181
- package/src/parsers/functionAnalyzer.js +0 -302
- package/src/parsers/prismaFilterBuilder.js +0 -422
- package/src/parsers/prismaParser.js +0 -287
|
@@ -0,0 +1,236 @@
|
|
|
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.buildModels = buildModels;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const child_process_1 = require("child_process");
|
|
40
|
+
const prismaParser_1 = require("../parsers/prismaParser");
|
|
41
|
+
const datasourceParser_1 = require("../parsers/datasourceParser");
|
|
42
|
+
const modelGenerator_1 = require("../generators/modelGenerator");
|
|
43
|
+
const routeGenerator_1 = require("../generators/routeGenerator");
|
|
44
|
+
const aclGenerator_1 = require("../generators/aclGenerator");
|
|
45
|
+
/**
|
|
46
|
+
* Update acl.ts for a specific model
|
|
47
|
+
*/
|
|
48
|
+
async function updateACLForModel(filteredModels, allModels, aclPath, datasource, userTable, debug = false) {
|
|
49
|
+
// Generate ACL for the filtered model (but pass all models for user table detection)
|
|
50
|
+
const tempPath = aclPath + '.tmp';
|
|
51
|
+
await (0, aclGenerator_1.generateACL)(filteredModels, tempPath, datasource.url, datasource.isPostgreSQL, userTable, {}, debug, allModels);
|
|
52
|
+
// Read the generated ACL for the specific model
|
|
53
|
+
const tempContent = fs.readFileSync(tempPath, 'utf8');
|
|
54
|
+
fs.unlinkSync(tempPath);
|
|
55
|
+
// Extract the model's ACL configuration
|
|
56
|
+
const modelName = Object.keys(filteredModels)[0];
|
|
57
|
+
// Find the start of the model definition
|
|
58
|
+
const modelStart = tempContent.indexOf(`${modelName}:`);
|
|
59
|
+
if (modelStart === -1) {
|
|
60
|
+
throw new Error(`Could not find model ${modelName} in generated RLS`);
|
|
61
|
+
}
|
|
62
|
+
// Find the matching closing brace by counting braces
|
|
63
|
+
let braceCount = 0;
|
|
64
|
+
let inString = false;
|
|
65
|
+
let stringChar = null;
|
|
66
|
+
let i = tempContent.indexOf('{', modelStart);
|
|
67
|
+
for (; i < tempContent.length; i++) {
|
|
68
|
+
const char = tempContent[i];
|
|
69
|
+
const prevChar = i > 0 ? tempContent[i - 1] : '';
|
|
70
|
+
// Handle string literals
|
|
71
|
+
if ((char === '"' || char === "'" || char === '`') && prevChar !== '\\') {
|
|
72
|
+
if (!inString) {
|
|
73
|
+
inString = true;
|
|
74
|
+
stringChar = char;
|
|
75
|
+
}
|
|
76
|
+
else if (char === stringChar) {
|
|
77
|
+
inString = false;
|
|
78
|
+
stringChar = null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (!inString) {
|
|
82
|
+
if (char === '{')
|
|
83
|
+
braceCount++;
|
|
84
|
+
if (char === '}')
|
|
85
|
+
braceCount--;
|
|
86
|
+
if (braceCount === 0) {
|
|
87
|
+
// Found the closing brace
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (braceCount !== 0) {
|
|
93
|
+
throw new Error(`Could not extract ACL for model ${modelName} - unmatched braces`);
|
|
94
|
+
}
|
|
95
|
+
const modelAcl = tempContent.substring(modelStart, i + 1);
|
|
96
|
+
// Read existing acl.ts
|
|
97
|
+
if (fs.existsSync(aclPath)) {
|
|
98
|
+
let existingContent = fs.readFileSync(aclPath, 'utf8');
|
|
99
|
+
// Check if model already exists in ACL
|
|
100
|
+
const existingModelPattern = new RegExp(`${modelName}:\\s*\\{[\\s\\S]*?\\n \\}(?=,|\\n)`);
|
|
101
|
+
if (existingModelPattern.test(existingContent)) {
|
|
102
|
+
// Replace existing model ACL
|
|
103
|
+
existingContent = existingContent.replace(existingModelPattern, modelAcl);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
// Add new model ACL before the closing of acl.model
|
|
107
|
+
existingContent = existingContent.replace(/(\n \})\n(\s*\},)/, `$1,\n ${modelAcl}\n$2`);
|
|
108
|
+
}
|
|
109
|
+
fs.writeFileSync(aclPath, existingContent);
|
|
110
|
+
console.log(`Updated ACL for model: ${modelName}`);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// If acl.ts doesn't exist, create it with just this model
|
|
114
|
+
await (0, aclGenerator_1.generateACL)(filteredModels, aclPath, datasource.url, datasource.isPostgreSQL, userTable, {}, debug, allModels);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Build models from Prisma schema
|
|
119
|
+
*/
|
|
120
|
+
async function buildModels(options) {
|
|
121
|
+
const schemaPath = path.resolve(process.cwd(), options.schema);
|
|
122
|
+
const outputBase = path.resolve(process.cwd(), options.output);
|
|
123
|
+
// If output is "/", use process.cwd() as the base
|
|
124
|
+
const baseDir = options.output === '/' ? process.cwd() : outputBase;
|
|
125
|
+
// Construct paths - TypeScript output structure
|
|
126
|
+
const srcDir = path.join(baseDir, 'src');
|
|
127
|
+
const modelDir = path.join(srcDir, 'models');
|
|
128
|
+
const configDir = path.join(srcDir, 'config');
|
|
129
|
+
const aclPath = path.join(configDir, 'acl.ts');
|
|
130
|
+
const routesDir = path.join(baseDir, 'routes', 'api', 'v1');
|
|
131
|
+
console.log('Building Rapidd models...');
|
|
132
|
+
console.log(`Schema: ${schemaPath}`);
|
|
133
|
+
console.log(`Output: ${baseDir}`);
|
|
134
|
+
// Check if schema file exists
|
|
135
|
+
if (!fs.existsSync(schemaPath)) {
|
|
136
|
+
throw new Error(`Prisma schema file not found at: ${schemaPath}`);
|
|
137
|
+
}
|
|
138
|
+
// Run npx prisma generate first
|
|
139
|
+
console.log('\nRunning npx prisma generate...');
|
|
140
|
+
try {
|
|
141
|
+
(0, child_process_1.execSync)(`npx prisma generate --schema=${schemaPath}`, {
|
|
142
|
+
stdio: 'inherit',
|
|
143
|
+
cwd: process.cwd()
|
|
144
|
+
});
|
|
145
|
+
console.log('Prisma client generated successfully\n');
|
|
146
|
+
}
|
|
147
|
+
catch (_error) {
|
|
148
|
+
console.warn('Warning: Failed to generate Prisma client');
|
|
149
|
+
console.warn('Continuing with schema parsing fallback...\n');
|
|
150
|
+
}
|
|
151
|
+
// Try to use Prisma DMMF first (using @prisma/internals getDMMF)
|
|
152
|
+
let parsedData = null;
|
|
153
|
+
try {
|
|
154
|
+
parsedData = await (0, prismaParser_1.parsePrismaDMMF)(schemaPath);
|
|
155
|
+
if (parsedData) {
|
|
156
|
+
console.log('Using Prisma DMMF (via @prisma/internals)');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (_error) {
|
|
160
|
+
// Fall back to schema parsing
|
|
161
|
+
}
|
|
162
|
+
// If DMMF parsing failed, parse schema file directly
|
|
163
|
+
if (!parsedData) {
|
|
164
|
+
console.log('Parsing Prisma schema file...');
|
|
165
|
+
parsedData = (0, prismaParser_1.parsePrismaSchema)(schemaPath);
|
|
166
|
+
}
|
|
167
|
+
const { models, enums } = parsedData;
|
|
168
|
+
// Filter models if --model option is provided
|
|
169
|
+
let filteredModels = models;
|
|
170
|
+
if (options.model) {
|
|
171
|
+
const modelName = options.model.toLowerCase();
|
|
172
|
+
const matchedModel = Object.keys(models).find(m => m.toLowerCase() === modelName);
|
|
173
|
+
if (!matchedModel) {
|
|
174
|
+
throw new Error(`Model "${options.model}" not found in schema. Available models: ${Object.keys(models).join(', ')}`);
|
|
175
|
+
}
|
|
176
|
+
filteredModels = { [matchedModel]: models[matchedModel] };
|
|
177
|
+
console.log(`Filtering to model: ${matchedModel}`);
|
|
178
|
+
}
|
|
179
|
+
console.log(`Found ${Object.keys(models).length} models${options.model ? ` (generating ${Object.keys(filteredModels).length})` : ''}`);
|
|
180
|
+
// Determine which components to generate
|
|
181
|
+
const shouldGenerate = {
|
|
182
|
+
model: !options.only || options.only === 'model',
|
|
183
|
+
route: !options.only || options.only === 'route',
|
|
184
|
+
acl: !options.only || options.only === 'acl'
|
|
185
|
+
};
|
|
186
|
+
// Validate --only option
|
|
187
|
+
if (options.only && !['model', 'route', 'acl'].includes(options.only)) {
|
|
188
|
+
throw new Error(`Invalid --only value "${options.only}". Must be one of: model, route, acl`);
|
|
189
|
+
}
|
|
190
|
+
// Generate model files
|
|
191
|
+
if (shouldGenerate.model) {
|
|
192
|
+
(0, modelGenerator_1.generateAllModels)(filteredModels, modelDir);
|
|
193
|
+
}
|
|
194
|
+
// Parse datasource to determine database type
|
|
195
|
+
let datasource = { isPostgreSQL: true, url: null, provider: null, isMySQL: false };
|
|
196
|
+
try {
|
|
197
|
+
datasource = (0, datasourceParser_1.parseDatasource)(schemaPath);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
// Only warn if it's not the expected "No url found" error in Prisma 7
|
|
201
|
+
if (!error.message.includes('No url found')) {
|
|
202
|
+
console.warn('Could not parse datasource, assuming PostgreSQL:', error.message);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Generate ACL configuration
|
|
206
|
+
if (shouldGenerate.acl) {
|
|
207
|
+
console.log(`\nGenerating ACL configuration...`);
|
|
208
|
+
try {
|
|
209
|
+
// For non-PostgreSQL databases (MySQL, SQLite, etc.), generate permissive ACL
|
|
210
|
+
if (!datasource.isPostgreSQL) {
|
|
211
|
+
console.log(`${datasource.provider || 'Non-PostgreSQL'} database detected - generating permissive ACL...`);
|
|
212
|
+
await (0, aclGenerator_1.generateACL)(models, aclPath, null, false, options.userTable, {}, options.debug);
|
|
213
|
+
}
|
|
214
|
+
else if (options.model) {
|
|
215
|
+
// Update only specific model in acl.ts
|
|
216
|
+
await updateACLForModel(filteredModels, models, aclPath, datasource, options.userTable, options.debug);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
// Generate ACL for all models
|
|
220
|
+
await (0, aclGenerator_1.generateACL)(models, aclPath, datasource.url, datasource.isPostgreSQL, options.userTable, {}, options.debug);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
console.error('Failed to generate ACL:', error.message);
|
|
225
|
+
console.log('Generating permissive ACL fallback...');
|
|
226
|
+
// Pass null for URL and false for isPostgreSQL to skip database connection
|
|
227
|
+
await (0, aclGenerator_1.generateACL)(models, aclPath, null, false, options.userTable, {}, options.debug);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// Generate routes
|
|
231
|
+
if (shouldGenerate.route) {
|
|
232
|
+
(0, routeGenerator_1.generateAllRoutes)(filteredModels, routesDir);
|
|
233
|
+
}
|
|
234
|
+
return { models, enums };
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/commands/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ModelInfo, RelationshipInfo } from '../parsers/prismaFilterBuilder';
|
|
2
|
+
/**
|
|
3
|
+
* Generate complete acl.ts file (TypeScript)
|
|
4
|
+
*/
|
|
5
|
+
export declare function generateACL(models: Record<string, ModelInfo>, outputPath: string, databaseUrl: string | null, isPostgreSQL: boolean, userTableOption?: string, relationships?: Record<string, Record<string, RelationshipInfo>>, debug?: boolean, allModels?: Record<string, ModelInfo>): Promise<void>;
|
|
6
|
+
//# sourceMappingURL=aclGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aclGenerator.d.ts","sourceRoot":"","sources":["../../../src/generators/aclGenerator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AA+UlF;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EACjC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,YAAY,EAAE,OAAO,EACrB,eAAe,CAAC,EAAE,MAAM,EACxB,aAAa,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAM,EACpE,KAAK,GAAE,OAAe,EACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC,CAuFf"}
|
|
@@ -0,0 +1,384 @@
|
|
|
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.generateACL = generateACL;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const pg_1 = require("pg");
|
|
40
|
+
const enhancedRLSConverter_1 = require("../parsers/enhancedRLSConverter");
|
|
41
|
+
const functionAnalyzer_1 = require("../parsers/functionAnalyzer");
|
|
42
|
+
/**
|
|
43
|
+
* Auto-detect user table name (case-insensitive search for user/users)
|
|
44
|
+
*/
|
|
45
|
+
function detectUserTable(models, userTableOption) {
|
|
46
|
+
if (userTableOption) {
|
|
47
|
+
return userTableOption;
|
|
48
|
+
}
|
|
49
|
+
const modelNames = Object.keys(models);
|
|
50
|
+
const userTables = modelNames.filter(name => name.toLowerCase() === 'user' || name.toLowerCase() === 'users');
|
|
51
|
+
if (userTables.length === 0) {
|
|
52
|
+
throw new Error('No user table found (user/users). Please specify --user-table option.');
|
|
53
|
+
}
|
|
54
|
+
if (userTables.length > 1) {
|
|
55
|
+
throw new Error(`Multiple user tables found: ${userTables.join(', ')}. Please specify --user-table option.`);
|
|
56
|
+
}
|
|
57
|
+
return userTables[0];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Extract ACL policies from PostgreSQL RLS
|
|
61
|
+
*/
|
|
62
|
+
async function extractPostgreSQLPolicies(databaseUrl, models) {
|
|
63
|
+
const client = new pg_1.Client({ connectionString: databaseUrl });
|
|
64
|
+
try {
|
|
65
|
+
await client.connect();
|
|
66
|
+
const policies = {};
|
|
67
|
+
// Create mapping from database table name to model name
|
|
68
|
+
const tableToModelMap = {};
|
|
69
|
+
for (const [modelName, modelData] of Object.entries(models)) {
|
|
70
|
+
const dbName = modelData.dbName || modelName.toLowerCase();
|
|
71
|
+
tableToModelMap[dbName] = modelName;
|
|
72
|
+
policies[modelName] = [];
|
|
73
|
+
}
|
|
74
|
+
// Query all policies from PostgreSQL RLS (pg_policies)
|
|
75
|
+
const result = await client.query(`
|
|
76
|
+
SELECT
|
|
77
|
+
tablename,
|
|
78
|
+
policyname,
|
|
79
|
+
permissive,
|
|
80
|
+
roles,
|
|
81
|
+
cmd,
|
|
82
|
+
qual,
|
|
83
|
+
with_check
|
|
84
|
+
FROM pg_policies
|
|
85
|
+
WHERE schemaname = 'public'
|
|
86
|
+
ORDER BY tablename, policyname
|
|
87
|
+
`);
|
|
88
|
+
// Group policies by model (using table to model mapping)
|
|
89
|
+
for (const row of result.rows) {
|
|
90
|
+
const tableName = row.tablename;
|
|
91
|
+
const modelName = tableToModelMap[tableName];
|
|
92
|
+
if (modelName && policies[modelName] !== undefined) {
|
|
93
|
+
policies[modelName].push({
|
|
94
|
+
name: row.policyname,
|
|
95
|
+
permissive: row.permissive === 'PERMISSIVE',
|
|
96
|
+
roles: row.roles,
|
|
97
|
+
command: row.cmd,
|
|
98
|
+
using: row.qual,
|
|
99
|
+
withCheck: row.with_check
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
await client.end();
|
|
104
|
+
return policies;
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
try {
|
|
108
|
+
await client.end();
|
|
109
|
+
}
|
|
110
|
+
catch (_e) {
|
|
111
|
+
// ignore
|
|
112
|
+
}
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Generate ACL functions for a single model from PostgreSQL policies
|
|
118
|
+
*/
|
|
119
|
+
function generateModelACL(modelName, policies, converter) {
|
|
120
|
+
const hasPolicies = policies && policies.length > 0;
|
|
121
|
+
if (!hasPolicies) {
|
|
122
|
+
// No policies - generate permissive access
|
|
123
|
+
return ` ${modelName}: {
|
|
124
|
+
canCreate(_user: RapiddUser): boolean {
|
|
125
|
+
return true;
|
|
126
|
+
},
|
|
127
|
+
getAccessFilter(_user: RapiddUser): Record<string, unknown> | boolean {
|
|
128
|
+
return {};
|
|
129
|
+
},
|
|
130
|
+
getUpdateFilter(_user: RapiddUser): Record<string, unknown> | boolean | false {
|
|
131
|
+
return {};
|
|
132
|
+
},
|
|
133
|
+
getDeleteFilter(_user: RapiddUser): Record<string, unknown> | boolean | false {
|
|
134
|
+
return {};
|
|
135
|
+
},
|
|
136
|
+
getOmitFields(_user: RapiddUser): string[] {
|
|
137
|
+
return [];
|
|
138
|
+
},
|
|
139
|
+
}`;
|
|
140
|
+
}
|
|
141
|
+
// Find policies by command type
|
|
142
|
+
const selectPolicies = policies.filter(p => p.command === 'SELECT' || p.command === 'ALL');
|
|
143
|
+
const insertPolicies = policies.filter(p => p.command === 'INSERT' || p.command === 'ALL');
|
|
144
|
+
const updatePolicies = policies.filter(p => p.command === 'UPDATE' || p.command === 'ALL');
|
|
145
|
+
const deletePolicies = policies.filter(p => p.command === 'DELETE' || p.command === 'ALL');
|
|
146
|
+
// Generate each function
|
|
147
|
+
const canCreateCode = generateFunction(insertPolicies, 'withCheck', converter, modelName);
|
|
148
|
+
const accessFilterCode = generateFilter(selectPolicies, 'using', converter, modelName);
|
|
149
|
+
let updateFilterCode = generateFilter(updatePolicies, 'using', converter, modelName);
|
|
150
|
+
let deleteFilterCode = generateFilter(deletePolicies, 'using', converter, modelName);
|
|
151
|
+
// If update/delete filters are empty/false but access filter is not, copy access filter
|
|
152
|
+
if ((updateFilterCode === 'return false;' || updateFilterCode === 'return {};') &&
|
|
153
|
+
accessFilterCode !== 'return false;' && accessFilterCode !== 'return {};') {
|
|
154
|
+
updateFilterCode = accessFilterCode;
|
|
155
|
+
}
|
|
156
|
+
if ((deleteFilterCode === 'return false;' || deleteFilterCode === 'return {};') &&
|
|
157
|
+
accessFilterCode !== 'return false;' && accessFilterCode !== 'return {};') {
|
|
158
|
+
deleteFilterCode = accessFilterCode;
|
|
159
|
+
}
|
|
160
|
+
return ` ${modelName}: {
|
|
161
|
+
canCreate(user: RapiddUser): boolean {
|
|
162
|
+
${canCreateCode}
|
|
163
|
+
},
|
|
164
|
+
getAccessFilter(user: RapiddUser): Record<string, unknown> | boolean {
|
|
165
|
+
${accessFilterCode}
|
|
166
|
+
},
|
|
167
|
+
getUpdateFilter(user: RapiddUser): Record<string, unknown> | boolean | false {
|
|
168
|
+
${updateFilterCode}
|
|
169
|
+
},
|
|
170
|
+
getDeleteFilter(user: RapiddUser): Record<string, unknown> | boolean | false {
|
|
171
|
+
${deleteFilterCode}
|
|
172
|
+
},
|
|
173
|
+
getOmitFields(_user: RapiddUser): string[] {
|
|
174
|
+
return [];
|
|
175
|
+
},
|
|
176
|
+
}`;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Generate JavaScript function from policies
|
|
180
|
+
*/
|
|
181
|
+
function generateFunction(policies, expressionField, converter, modelName) {
|
|
182
|
+
if (policies.length === 0) {
|
|
183
|
+
return 'return true;';
|
|
184
|
+
}
|
|
185
|
+
const conditions = [];
|
|
186
|
+
for (const policy of policies) {
|
|
187
|
+
const expr = expressionField === 'withCheck'
|
|
188
|
+
? (policy.withCheck || policy.using)
|
|
189
|
+
: policy[expressionField];
|
|
190
|
+
if (expr) {
|
|
191
|
+
try {
|
|
192
|
+
const jsExpr = converter.convertToJavaScript(expr, 'data', 'user', modelName);
|
|
193
|
+
console.log(` Policy '${policy.name}': ${expr.substring(0, 50)}... -> ${jsExpr.substring(0, 80)}`);
|
|
194
|
+
conditions.push(jsExpr);
|
|
195
|
+
}
|
|
196
|
+
catch (e) {
|
|
197
|
+
console.warn(` Failed to convert policy '${policy.name}' for ${modelName}: ${e.message}`);
|
|
198
|
+
console.warn(` SQL: ${expr}`);
|
|
199
|
+
conditions.push(`true /* TODO: Manual conversion needed for policy '${policy.name}' */`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (conditions.length === 0) {
|
|
204
|
+
return 'return true;';
|
|
205
|
+
}
|
|
206
|
+
// If any condition is 'true', the entire expression is true
|
|
207
|
+
if (conditions.some(c => c === 'true' || c.startsWith('true /*'))) {
|
|
208
|
+
return 'return true;';
|
|
209
|
+
}
|
|
210
|
+
// Policies are OR'd together (any policy allows)
|
|
211
|
+
return `return ${conditions.join(' || ')};`;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Generate Prisma filter function
|
|
215
|
+
*/
|
|
216
|
+
function generateFilter(policies, expressionField, converter, modelName) {
|
|
217
|
+
if (policies.length === 0) {
|
|
218
|
+
return 'return false;';
|
|
219
|
+
}
|
|
220
|
+
const filtersWithRoles = [];
|
|
221
|
+
for (const policy of policies) {
|
|
222
|
+
const expr = policy[expressionField];
|
|
223
|
+
if (expr) {
|
|
224
|
+
try {
|
|
225
|
+
const prismaFilter = converter.convertToPrismaFilter(expr, 'user', modelName);
|
|
226
|
+
const analysis = converter.analyzer ? converter.analyzer.analyzeSQLForFilters(expr) : null;
|
|
227
|
+
// Track role conditions and data filters separately
|
|
228
|
+
const roleConditions = analysis?.conditions?.filter(c => c.type === 'role_any' || c.type === 'role_equal') || [];
|
|
229
|
+
filtersWithRoles.push({
|
|
230
|
+
filter: prismaFilter,
|
|
231
|
+
roleConditions,
|
|
232
|
+
hasDataFilter: prismaFilter !== '{}'
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
catch (e) {
|
|
236
|
+
console.warn(` Failed to convert filter policy '${policy.name}' for ${modelName}: ${e.message}`);
|
|
237
|
+
console.warn(` SQL: ${expr}`);
|
|
238
|
+
// On error, skip filter (fail-safe - no access)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (filtersWithRoles.length === 0) {
|
|
243
|
+
return 'return false;';
|
|
244
|
+
}
|
|
245
|
+
// Build conditional filter logic
|
|
246
|
+
return buildConditionalFilter(filtersWithRoles);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Build conditional filter with role checks
|
|
250
|
+
*/
|
|
251
|
+
function buildConditionalFilter(filtersWithRoles) {
|
|
252
|
+
const roleOnlyFilters = [];
|
|
253
|
+
const dataFilters = [];
|
|
254
|
+
for (const item of filtersWithRoles) {
|
|
255
|
+
if (item.roleConditions.length > 0 && !item.hasDataFilter) {
|
|
256
|
+
// Pure role check - return {} if role matches
|
|
257
|
+
roleOnlyFilters.push(...item.roleConditions);
|
|
258
|
+
}
|
|
259
|
+
else if (item.roleConditions.length > 0 && item.hasDataFilter) {
|
|
260
|
+
// Has both role and data filter - already handled with if statement
|
|
261
|
+
if (item.filter.includes('if (')) {
|
|
262
|
+
return item.filter;
|
|
263
|
+
}
|
|
264
|
+
dataFilters.push(item.filter);
|
|
265
|
+
}
|
|
266
|
+
else if (item.hasDataFilter) {
|
|
267
|
+
// Data filter only
|
|
268
|
+
dataFilters.push(item.filter);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Generate conditional code
|
|
272
|
+
const conditions = [];
|
|
273
|
+
// Collect all roles that grant full access
|
|
274
|
+
const rolesWithFullAccess = new Set();
|
|
275
|
+
for (const roleCond of roleOnlyFilters) {
|
|
276
|
+
if (roleCond.type === 'role_any' && roleCond.roles) {
|
|
277
|
+
roleCond.roles.forEach(r => rolesWithFullAccess.add(r));
|
|
278
|
+
}
|
|
279
|
+
else if (roleCond.type === 'role_equal' && roleCond.role) {
|
|
280
|
+
rolesWithFullAccess.add(roleCond.role);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// Add single consolidated role check if needed
|
|
284
|
+
if (rolesWithFullAccess.size > 0) {
|
|
285
|
+
const roleArray = Array.from(rolesWithFullAccess);
|
|
286
|
+
if (roleArray.length === 1) {
|
|
287
|
+
conditions.push(`if (user?.role === '${roleArray[0]}') return {};`);
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
conditions.push(`if ([${roleArray.map(r => `'${r}'`).join(', ')}].includes(user?.role)) return {};`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// Deduplicate data filters
|
|
294
|
+
const uniqueDataFilters = [...new Set(dataFilters)];
|
|
295
|
+
// Add final return with data filters
|
|
296
|
+
if (uniqueDataFilters.length === 0) {
|
|
297
|
+
conditions.push('return false;');
|
|
298
|
+
}
|
|
299
|
+
else if (uniqueDataFilters.length === 1) {
|
|
300
|
+
conditions.push(`return ${uniqueDataFilters[0]};`);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
conditions.push(`return { OR: [${uniqueDataFilters.join(', ')}] };`);
|
|
304
|
+
}
|
|
305
|
+
return conditions.join(' ');
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Generate complete acl.ts file (TypeScript)
|
|
309
|
+
*/
|
|
310
|
+
async function generateACL(models, outputPath, databaseUrl, isPostgreSQL, userTableOption, relationships = {}, debug = false, allModels) {
|
|
311
|
+
// Use allModels for user table detection if provided (when filtering by model)
|
|
312
|
+
const modelsForUserDetection = allModels || models;
|
|
313
|
+
const _userTable = detectUserTable(modelsForUserDetection, userTableOption);
|
|
314
|
+
const modelNames = Object.keys(models);
|
|
315
|
+
let policies = {};
|
|
316
|
+
// Create enhanced converter with analyzed functions, models, and relationships
|
|
317
|
+
let converter = (0, enhancedRLSConverter_1.createEnhancedConverter)({}, {}, models, relationships);
|
|
318
|
+
if (isPostgreSQL && databaseUrl) {
|
|
319
|
+
console.log('PostgreSQL detected - analyzing database...');
|
|
320
|
+
// Step 1: Analyze functions
|
|
321
|
+
try {
|
|
322
|
+
const functionAnalysis = await (0, functionAnalyzer_1.analyzeFunctions)(databaseUrl);
|
|
323
|
+
console.log(`Analyzed ${Object.keys(functionAnalysis.functionMappings).length} PostgreSQL functions`);
|
|
324
|
+
// Create enhanced converter with analyzed mappings, models, and relationships
|
|
325
|
+
converter = (0, enhancedRLSConverter_1.createEnhancedConverter)(functionAnalysis.functionMappings, functionAnalysis.sessionVariables, models, relationships);
|
|
326
|
+
// Save function analysis for debugging (only if --debug flag is set)
|
|
327
|
+
if (debug) {
|
|
328
|
+
const configPath = path.join(path.dirname(outputPath), 'acl-mappings.json');
|
|
329
|
+
const mappingConfig = (0, functionAnalyzer_1.generateMappingConfig)(functionAnalysis);
|
|
330
|
+
fs.writeFileSync(configPath, JSON.stringify(mappingConfig, null, 2));
|
|
331
|
+
console.log(`Function mappings saved to ${configPath}`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
catch (error) {
|
|
335
|
+
console.warn(`Could not analyze functions: ${error.message}`);
|
|
336
|
+
}
|
|
337
|
+
// Step 2: Extract policies
|
|
338
|
+
try {
|
|
339
|
+
policies = await extractPostgreSQLPolicies(databaseUrl, models);
|
|
340
|
+
const totalPolicies = Object.values(policies).reduce((sum, p) => sum + p.length, 0);
|
|
341
|
+
console.log(`Extracted ${totalPolicies} policies from PostgreSQL RLS`);
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
console.warn(`Failed to extract PostgreSQL policies: ${error.message}`);
|
|
345
|
+
console.log('Generating permissive ACL for all models...');
|
|
346
|
+
for (const modelName of modelNames) {
|
|
347
|
+
policies[modelName] = [];
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
if (!isPostgreSQL) {
|
|
353
|
+
console.log('Non-PostgreSQL database detected - generating permissive ACL');
|
|
354
|
+
}
|
|
355
|
+
console.log('Generating permissive ACL for all models...');
|
|
356
|
+
for (const modelName of modelNames) {
|
|
357
|
+
policies[modelName] = [];
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
// Generate ACL TypeScript code
|
|
361
|
+
let aclCode = `import type { AclConfig, RapiddUser } from '../types';
|
|
362
|
+
|
|
363
|
+
const acl: AclConfig = {
|
|
364
|
+
model: {
|
|
365
|
+
`;
|
|
366
|
+
const modelACLCode = modelNames.map(modelName => {
|
|
367
|
+
return generateModelACL(modelName, policies[modelName], converter);
|
|
368
|
+
});
|
|
369
|
+
aclCode += modelACLCode.join(',\n');
|
|
370
|
+
aclCode += `
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
export default acl;
|
|
375
|
+
`;
|
|
376
|
+
// Ensure output directory exists
|
|
377
|
+
const outputDir = path.dirname(outputPath);
|
|
378
|
+
if (!fs.existsSync(outputDir)) {
|
|
379
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
380
|
+
}
|
|
381
|
+
fs.writeFileSync(outputPath, aclCode);
|
|
382
|
+
console.log('Generated acl.ts with dynamic function mappings');
|
|
383
|
+
}
|
|
384
|
+
//# sourceMappingURL=aclGenerator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aclGenerator.js","sourceRoot":"","sources":["../../../src/generators/aclGenerator.ts"],"names":[],"mappings":"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"}
|