@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.
Files changed (71) hide show
  1. package/README.md +219 -68
  2. package/dist/bin/cli.d.ts +3 -0
  3. package/dist/bin/cli.d.ts.map +1 -0
  4. package/dist/bin/cli.js +31 -0
  5. package/dist/bin/cli.js.map +1 -0
  6. package/dist/index.d.ts +18 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +32 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/src/commands/build.d.ts +17 -0
  11. package/dist/src/commands/build.d.ts.map +1 -0
  12. package/dist/src/commands/build.js +236 -0
  13. package/dist/src/commands/build.js.map +1 -0
  14. package/dist/src/generators/aclGenerator.d.ts +6 -0
  15. package/dist/src/generators/aclGenerator.d.ts.map +1 -0
  16. package/dist/src/generators/aclGenerator.js +384 -0
  17. package/dist/src/generators/aclGenerator.js.map +1 -0
  18. package/dist/src/generators/index.d.ts +4 -0
  19. package/dist/src/generators/index.d.ts.map +1 -0
  20. package/dist/src/generators/index.js +13 -0
  21. package/dist/src/generators/index.js.map +1 -0
  22. package/dist/src/generators/modelGenerator.d.ts +10 -0
  23. package/dist/src/generators/modelGenerator.d.ts.map +1 -0
  24. package/dist/src/generators/modelGenerator.js +143 -0
  25. package/dist/src/generators/modelGenerator.js.map +1 -0
  26. package/dist/src/generators/routeGenerator.d.ts +10 -0
  27. package/dist/src/generators/routeGenerator.d.ts.map +1 -0
  28. package/dist/src/generators/routeGenerator.js +148 -0
  29. package/dist/src/generators/routeGenerator.js.map +1 -0
  30. package/dist/src/parsers/datasourceParser.d.ts +11 -0
  31. package/dist/src/parsers/datasourceParser.d.ts.map +1 -0
  32. package/dist/src/parsers/datasourceParser.js +131 -0
  33. package/dist/src/parsers/datasourceParser.js.map +1 -0
  34. package/dist/src/parsers/deepSQLAnalyzer.d.ts +85 -0
  35. package/dist/src/parsers/deepSQLAnalyzer.d.ts.map +1 -0
  36. package/dist/src/parsers/deepSQLAnalyzer.js +482 -0
  37. package/dist/src/parsers/deepSQLAnalyzer.js.map +1 -0
  38. package/dist/src/parsers/enhancedRLSConverter.d.ts +14 -0
  39. package/dist/src/parsers/enhancedRLSConverter.d.ts.map +1 -0
  40. package/dist/src/parsers/enhancedRLSConverter.js +168 -0
  41. package/dist/src/parsers/enhancedRLSConverter.js.map +1 -0
  42. package/dist/src/parsers/functionAnalyzer.d.ts +55 -0
  43. package/dist/src/parsers/functionAnalyzer.d.ts.map +1 -0
  44. package/dist/src/parsers/functionAnalyzer.js +274 -0
  45. package/dist/src/parsers/functionAnalyzer.js.map +1 -0
  46. package/dist/src/parsers/index.d.ts +13 -0
  47. package/dist/src/parsers/index.d.ts.map +1 -0
  48. package/dist/src/parsers/index.js +20 -0
  49. package/dist/src/parsers/index.js.map +1 -0
  50. package/dist/src/parsers/prismaFilterBuilder.d.ts +79 -0
  51. package/dist/src/parsers/prismaFilterBuilder.d.ts.map +1 -0
  52. package/dist/src/parsers/prismaFilterBuilder.js +322 -0
  53. package/dist/src/parsers/prismaFilterBuilder.js.map +1 -0
  54. package/dist/src/parsers/prismaParser.d.ts +14 -0
  55. package/dist/src/parsers/prismaParser.d.ts.map +1 -0
  56. package/dist/src/parsers/prismaParser.js +263 -0
  57. package/dist/src/parsers/prismaParser.js.map +1 -0
  58. package/package.json +21 -13
  59. package/bin/cli.js +0 -33
  60. package/index.js +0 -11
  61. package/src/commands/build.js +0 -638
  62. package/src/generators/aclGenerator.js +0 -394
  63. package/src/generators/modelGenerator.js +0 -174
  64. package/src/generators/relationshipsGenerator.js +0 -200
  65. package/src/generators/routeGenerator.js +0 -119
  66. package/src/parsers/datasourceParser.js +0 -121
  67. package/src/parsers/deepSQLAnalyzer.js +0 -554
  68. package/src/parsers/enhancedRLSConverter.js +0 -181
  69. package/src/parsers/functionAnalyzer.js +0 -302
  70. package/src/parsers/prismaFilterBuilder.js +0 -422
  71. package/src/parsers/prismaParser.js +0 -287
@@ -1,394 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { Client } = require('pg');
4
- const { createEnhancedConverter } = require('../parsers/enhancedRLSConverter');
5
- const { analyzeFunctions, generateMappingConfig } = require('../parsers/functionAnalyzer');
6
-
7
- /**
8
- * Auto-detect user table name (case-insensitive search for user/users)
9
- */
10
- function detectUserTable(models, userTableOption) {
11
- if (userTableOption) {
12
- return userTableOption;
13
- }
14
-
15
- const modelNames = Object.keys(models);
16
- const userTables = modelNames.filter(name =>
17
- name.toLowerCase() === 'user' || name.toLowerCase() === 'users'
18
- );
19
-
20
- if (userTables.length === 0) {
21
- throw new Error('No user table found (user/users). Please specify --user-table option.');
22
- }
23
-
24
- if (userTables.length > 1) {
25
- throw new Error(`Multiple user tables found: ${userTables.join(', ')}. Please specify --user-table option.`);
26
- }
27
-
28
- return userTables[0];
29
- }
30
-
31
- /**
32
- * Extract ACL policies from PostgreSQL RLS
33
- */
34
- async function extractPostgreSQLPolicies(databaseUrl, models) {
35
- const client = new Client({ connectionString: databaseUrl });
36
-
37
- try {
38
- await client.connect();
39
-
40
- const policies = {};
41
-
42
- // Create mapping from database table name to model name
43
- const tableToModelMap = {};
44
- for (const [modelName, modelData] of Object.entries(models)) {
45
- const dbName = modelData.dbName || modelName.toLowerCase();
46
- tableToModelMap[dbName] = modelName;
47
- policies[modelName] = [];
48
- }
49
-
50
- // Query all policies from PostgreSQL RLS (pg_policies)
51
- const result = await client.query(`
52
- SELECT
53
- tablename,
54
- policyname,
55
- permissive,
56
- roles,
57
- cmd,
58
- qual,
59
- with_check
60
- FROM pg_policies
61
- WHERE schemaname = 'public'
62
- ORDER BY tablename, policyname
63
- `);
64
-
65
- // Group policies by model (using table to model mapping)
66
- for (const row of result.rows) {
67
- const tableName = row.tablename;
68
- const modelName = tableToModelMap[tableName];
69
-
70
- if (modelName && policies[modelName] !== undefined) {
71
- policies[modelName].push({
72
- name: row.policyname,
73
- permissive: row.permissive === 'PERMISSIVE',
74
- roles: row.roles,
75
- command: row.cmd,
76
- using: row.qual,
77
- withCheck: row.with_check
78
- });
79
- }
80
- }
81
-
82
- await client.end();
83
- return policies;
84
-
85
- } catch (error) {
86
- try {
87
- await client.end();
88
- } catch (e) {}
89
- throw error;
90
- }
91
- }
92
-
93
- /**
94
- * Generate ACL functions for a single model from PostgreSQL policies
95
- */
96
- function generateModelACL(modelName, policies, converter) {
97
- const hasPolicies = policies && policies.length > 0;
98
-
99
- if (!hasPolicies) {
100
- // No policies - generate permissive access
101
- return ` ${modelName}: {
102
- canCreate: (user) => true,
103
- getAccessFilter: (user) => ({}),
104
- getUpdateFilter: (user) => ({}),
105
- getDeleteFilter: (user) => ({}),
106
- getOmitFields: (user) => []
107
- }`;
108
- }
109
-
110
- // Find policies by command type
111
- const selectPolicies = policies.filter(p => p.command === 'SELECT' || p.command === 'ALL');
112
- const insertPolicies = policies.filter(p => p.command === 'INSERT' || p.command === 'ALL');
113
- const updatePolicies = policies.filter(p => p.command === 'UPDATE' || p.command === 'ALL');
114
- const deletePolicies = policies.filter(p => p.command === 'DELETE' || p.command === 'ALL');
115
-
116
- // Generate each function
117
- const canCreateCode = generateFunction(insertPolicies, 'withCheck', converter, modelName);
118
- const accessFilterCode = generateFilter(selectPolicies, 'using', converter, modelName);
119
- let updateFilterCode = generateFilter(updatePolicies, 'using', converter, modelName);
120
- let deleteFilterCode = generateFilter(deletePolicies, 'using', converter, modelName);
121
-
122
- // If update/delete filters are empty/false but access filter is not, copy access filter
123
- if ((updateFilterCode === 'return false;' || updateFilterCode === 'return {};') &&
124
- accessFilterCode !== 'return false;' && accessFilterCode !== 'return {};') {
125
- updateFilterCode = accessFilterCode;
126
- }
127
- if ((deleteFilterCode === 'return false;' || deleteFilterCode === 'return {};') &&
128
- accessFilterCode !== 'return false;' && accessFilterCode !== 'return {};') {
129
- deleteFilterCode = accessFilterCode;
130
- }
131
-
132
- return ` ${modelName}: {
133
- canCreate: (user) => {
134
- ${canCreateCode}
135
- },
136
- getAccessFilter: (user) => {
137
- ${accessFilterCode}
138
- },
139
- getUpdateFilter: (user) => {
140
- ${updateFilterCode}
141
- },
142
- getDeleteFilter: (user) => {
143
- ${deleteFilterCode}
144
- },
145
- getOmitFields: (user) => []
146
- }`;
147
- }
148
-
149
- /**
150
- * Generate JavaScript function from policies
151
- */
152
- function generateFunction(policies, expressionField, converter, modelName) {
153
- if (policies.length === 0) {
154
- return 'return true;';
155
- }
156
-
157
- const conditions = [];
158
-
159
- for (const policy of policies) {
160
- const expr = expressionField === 'withCheck'
161
- ? (policy.withCheck || policy.using)
162
- : policy[expressionField];
163
-
164
- if (expr) {
165
- try {
166
- const jsExpr = converter.convertToJavaScript(expr, 'data', 'user', modelName);
167
- console.log(`✓ Policy '${policy.name}': ${expr.substring(0, 50)}... -> ${jsExpr.substring(0, 80)}`);
168
- conditions.push(jsExpr);
169
- } catch (e) {
170
- console.warn(`⚠ Failed to convert policy '${policy.name}' for ${modelName}: ${e.message}`);
171
- console.warn(` SQL: ${expr}`);
172
- conditions.push(`true /* TODO: Manual conversion needed for policy '${policy.name}' */`);
173
- }
174
- }
175
- }
176
-
177
- if (conditions.length === 0) {
178
- return 'return true;';
179
- }
180
-
181
- // If any condition is 'true', the entire expression is true
182
- if (conditions.some(c => c === 'true' || c.startsWith('true /*'))) {
183
- return 'return true;';
184
- }
185
-
186
- // Policies are OR'd together (any policy allows)
187
- return `return ${conditions.join(' || ')};`;
188
- }
189
-
190
- /**
191
- * Generate Prisma filter function
192
- */
193
- function generateFilter(policies, expressionField, converter, modelName) {
194
- if (policies.length === 0) {
195
- return 'return false;';
196
- }
197
-
198
- const filtersWithRoles = [];
199
-
200
- for (const policy of policies) {
201
- const expr = policy[expressionField];
202
- if (expr) {
203
- try {
204
- const prismaFilter = converter.convertToPrismaFilter(expr, 'user', modelName);
205
- const analysis = converter.analyzer ? converter.analyzer.analyzeSQLForFilters(expr) : null;
206
-
207
- // Track role conditions and data filters separately
208
- const roleConditions = analysis?.conditions?.filter(c =>
209
- c.type === 'role_any' || c.type === 'role_equal'
210
- ) || [];
211
-
212
- filtersWithRoles.push({
213
- filter: prismaFilter,
214
- roleConditions,
215
- hasDataFilter: prismaFilter !== '{}'
216
- });
217
- } catch (e) {
218
- console.warn(`⚠ Failed to convert filter policy '${policy.name}' for ${modelName}: ${e.message}`);
219
- console.warn(` SQL: ${expr}`);
220
- // On error, skip filter (fail-safe - no access)
221
- }
222
- }
223
- }
224
-
225
- if (filtersWithRoles.length === 0) {
226
- return 'return false;';
227
- }
228
-
229
- // Build conditional filter logic
230
- return buildConditionalFilter(filtersWithRoles);
231
- }
232
-
233
- /**
234
- * Build conditional filter with role checks
235
- */
236
- function buildConditionalFilter(filtersWithRoles) {
237
- const roleOnlyFilters = [];
238
- const dataFilters = [];
239
-
240
- for (const item of filtersWithRoles) {
241
- if (item.roleConditions.length > 0 && !item.hasDataFilter) {
242
- // Pure role check - return {} if role matches
243
- roleOnlyFilters.push(...item.roleConditions);
244
- } else if (item.roleConditions.length > 0 && item.hasDataFilter) {
245
- // Has both role and data filter - already handled with if statement
246
- if (item.filter.includes('if (')) {
247
- return item.filter;
248
- }
249
- dataFilters.push(item.filter);
250
- } else if (item.hasDataFilter) {
251
- // Data filter only
252
- dataFilters.push(item.filter);
253
- }
254
- }
255
-
256
- // Generate conditional code
257
- const conditions = [];
258
-
259
- // Collect all roles that grant full access
260
- const rolesWithFullAccess = new Set();
261
- for (const roleCond of roleOnlyFilters) {
262
- if (roleCond.type === 'role_any') {
263
- roleCond.roles.forEach(r => rolesWithFullAccess.add(r));
264
- } else if (roleCond.type === 'role_equal') {
265
- rolesWithFullAccess.add(roleCond.role);
266
- }
267
- }
268
-
269
- // Add single consolidated role check if needed
270
- if (rolesWithFullAccess.size > 0) {
271
- const roleArray = Array.from(rolesWithFullAccess);
272
- if (roleArray.length === 1) {
273
- conditions.push(`if (user?.role === '${roleArray[0]}') { return {}; }`);
274
- } else {
275
- conditions.push(`if ([${roleArray.map(r => `'${r}'`).join(', ')}].includes(user?.role)) { return {}; }`);
276
- }
277
- }
278
-
279
- // Deduplicate data filters
280
- const uniqueDataFilters = [...new Set(dataFilters)];
281
-
282
- // Add final return with data filters
283
- if (uniqueDataFilters.length === 0) {
284
- conditions.push('return false;');
285
- } else if (uniqueDataFilters.length === 1) {
286
- conditions.push(`return ${uniqueDataFilters[0]};`);
287
- } else {
288
- conditions.push(`return { OR: [${uniqueDataFilters.join(', ')}] };`);
289
- }
290
-
291
- return conditions.join(' ');
292
- }
293
-
294
- /**
295
- * Generate complete acl.js file
296
- */
297
- async function generateACL(models, outputPath, databaseUrl, isPostgreSQL, userTableOption, relationships = {}, debug = false, allModels = null) {
298
- // Use allModels for user table detection if provided (when filtering by model)
299
- const modelsForUserDetection = allModels || models;
300
- const userTable = detectUserTable(modelsForUserDetection, userTableOption);
301
- const modelNames = Object.keys(models);
302
-
303
- let policies = {};
304
- const timestamp = new Date().toISOString();
305
-
306
- let aclCode = `const acl = {\n model: {},\n lastUpdateDate: '${timestamp}'\n};\n\n`;
307
-
308
- // Create enhanced converter with analyzed functions, models, and relationships
309
- let converter = createEnhancedConverter({}, {}, models, relationships);
310
-
311
- if (isPostgreSQL && databaseUrl) {
312
- console.log('PostgreSQL detected - analyzing database...');
313
-
314
- // Step 1: Analyze functions
315
- try {
316
- const functionAnalysis = await analyzeFunctions(databaseUrl);
317
- console.log(`✓ Analyzed ${Object.keys(functionAnalysis.functionMappings).length} PostgreSQL functions`);
318
-
319
- // Create enhanced converter with analyzed mappings, models, and relationships
320
- converter = createEnhancedConverter(
321
- functionAnalysis.functionMappings,
322
- functionAnalysis.sessionVariables,
323
- models,
324
- relationships
325
- );
326
-
327
- // Save function analysis for debugging (only if --debug flag is set)
328
- if (debug) {
329
- const configPath = path.join(path.dirname(outputPath), 'acl-mappings.json');
330
- const mappingConfig = generateMappingConfig(functionAnalysis);
331
- fs.writeFileSync(configPath, JSON.stringify(mappingConfig, null, 2));
332
- console.log(`✓ Function mappings saved to ${configPath}`);
333
- }
334
-
335
- // Also add user context requirements as a comment in acl.js
336
- if (Object.keys(functionAnalysis.userContextRequirements).length > 0) {
337
- aclCode = `/**
338
- * User Context Requirements:
339
- * The user object should contain:
340
- ${Object.entries(functionAnalysis.userContextRequirements)
341
- .map(([field, req]) => ` * - ${field}: ${typeof req === 'object' ? req.description : 'required'}`)
342
- .join('\n')}
343
- */
344
-
345
- ` + aclCode;
346
- }
347
- } catch (error) {
348
- console.warn(`⚠ Could not analyze functions: ${error.message}`);
349
- }
350
-
351
- // Step 2: Extract policies
352
- try {
353
- policies = await extractPostgreSQLPolicies(databaseUrl, models);
354
- const totalPolicies = Object.values(policies).reduce((sum, p) => sum + p.length, 0);
355
- console.log(`✓ Extracted ${totalPolicies} policies from PostgreSQL RLS`);
356
- } catch (error) {
357
- console.warn(`⚠ Failed to extract PostgreSQL policies: ${error.message}`);
358
- console.log('Generating permissive ACL for all models...');
359
- for (const modelName of modelNames) {
360
- policies[modelName] = [];
361
- }
362
- }
363
- } else {
364
- if (!isPostgreSQL) {
365
- console.log('Non-PostgreSQL database detected - generating permissive ACL');
366
- }
367
- console.log('Generating permissive ACL for all models...');
368
- for (const modelName of modelNames) {
369
- policies[modelName] = [];
370
- }
371
- }
372
-
373
- // Generate ACL for each model
374
- aclCode += 'acl.model = {\n';
375
- const modelACLCode = modelNames.map(modelName => {
376
- return generateModelACL(modelName, policies[modelName], converter);
377
- });
378
- aclCode += modelACLCode.join(',\n');
379
- aclCode += '\n};\n\n';
380
- aclCode += 'module.exports = acl;\n';
381
-
382
- // Ensure output directory exists
383
- const outputDir = path.dirname(outputPath);
384
- if (!fs.existsSync(outputDir)) {
385
- fs.mkdirSync(outputDir, { recursive: true });
386
- }
387
-
388
- fs.writeFileSync(outputPath, aclCode);
389
- console.log('✓ Generated acl.js with dynamic function mappings');
390
- }
391
-
392
- module.exports = {
393
- generateACL
394
- };
@@ -1,174 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- /**
5
- * Generate a single model file
6
- * @param {string} modelName - Name of the model
7
- * @param {Object} modelInfo - Model information from parser
8
- * @returns {string} - Generated model class code
9
- */
10
- function generateModelFile(modelName, modelInfo) {
11
- // Capitalize first letter for class name
12
- const className = modelName.split(/[^a-zA-Z0-9]+/) // split on any non-alphanumeric char
13
- .filter(Boolean) // remove empty parts
14
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
15
- .join('');
16
-
17
- return `const {Model, QueryBuilder, prisma} = require('../Model');
18
-
19
- class ${className} extends Model {
20
- constructor(options){
21
- super('${modelName}', options);
22
- }
23
-
24
- /**
25
- * @param {string} q
26
- * @property {string|Object} include
27
- * @param {number} limit
28
- * @param {number} offset
29
- * @param {string} sortBy
30
- * @param {'asc'|'desc'} sortOrder
31
- * @returns {Promise<Object[]>}
32
- */
33
- async getMany(q = {}, include = "", limit = 25, offset = 0, sortBy = "id", sortOrder = "asc"){
34
- return await this._getMany(q, include, Number(limit), Number(offset), sortBy, sortOrder);
35
- }
36
-
37
- /**
38
- * @param {number} id
39
- * @param {string | Object} include
40
- * @returns {Promise<Object | null>}
41
- */
42
- async get(id, include){
43
- return await this._get(id, include);
44
- }
45
-
46
- /**
47
- * @param {Object} data
48
- * @returns {Promise<Object>}
49
- */
50
- async create(data){
51
- return await this._create(data);
52
- }
53
-
54
- /**
55
- * @param {number} id
56
- * @param {{}} data
57
- * @returns {Promise<Object>}
58
- */
59
- async update(id, data){
60
- return await this._update(id, data);
61
- }
62
-
63
- /**
64
- * @param {{}} data
65
- * @param {string} [unique_key=this.primaryKey]
66
- * @returns {Promise<Object>}
67
- */
68
- async upsert(data, unique_key = this.primaryKey){
69
- return await this._upsert(data, unique_key);
70
- }
71
-
72
- /**
73
- * @param {number} id
74
- * @returns {Object}
75
- */
76
- async delete(id){
77
- return await this._delete(id);
78
- }
79
-
80
- /**
81
- * @param {string | Object} include
82
- * @returns {Object}
83
- */
84
- filter(include){
85
- return {...this._filter(include), ...this.getAccessFilter()};
86
- }
87
-
88
- /**
89
- * @param {string | Object} include
90
- * @returns {Object}
91
- */
92
- include(include){
93
- return this._include(include);
94
- }
95
-
96
- static QueryBuilder = new QueryBuilder('${modelName}');
97
- }
98
-
99
- module.exports = {${className}, QueryBuilder, prisma};
100
- `;
101
- }
102
-
103
- /**
104
- * Map Prisma types to JavaScript types
105
- * @param {string} prismaType - Prisma field type
106
- * @returns {string} - JavaScript type
107
- */
108
- function mapPrismaTypeToJS(prismaType) {
109
- const typeMap = {
110
- 'String': 'string',
111
- 'Int': 'number',
112
- 'Float': 'number',
113
- 'Decimal': 'number',
114
- 'Boolean': 'boolean',
115
- 'DateTime': 'Date',
116
- 'Json': 'object',
117
- 'Bytes': 'Buffer'
118
- };
119
-
120
- return typeMap[prismaType] || prismaType;
121
- }
122
-
123
- /**
124
- * Generate all model files
125
- * @param {Object} models - Models object from parser
126
- * @param {string} modelDir - Directory to output model files
127
- * @param {string} modelJsPath - Path to output Model.js
128
- */
129
- function generateAllModels(models, modelDir, modelJsPath) {
130
- // Create model directory if it doesn't exist
131
- if (!fs.existsSync(modelDir)) {
132
- fs.mkdirSync(modelDir, { recursive: true });
133
- }
134
-
135
- // Generate individual model files
136
- for (const [modelName, modelInfo] of Object.entries(models)) {
137
- const modelCode = generateModelFile(modelName, modelInfo);
138
- // Capitalize first letter for filename
139
- const className = modelName.split(/[^a-zA-Z0-9]+/) // split on any non-alphanumeric char
140
- .filter(Boolean) // remove empty parts
141
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
142
- .join('');
143
- const modelPath = path.join(modelDir, `${className}.js`);
144
- fs.writeFileSync(modelPath, modelCode);
145
- console.log(`Generated model: ${className}.js`);
146
- }
147
-
148
- // Copy Model.js to output if it exists in the project
149
- const sourceModelJs = path.join(process.cwd(), 'Model.js');
150
- if (fs.existsSync(sourceModelJs)) {
151
- fs.copyFileSync(sourceModelJs, modelJsPath);
152
- console.log('Copied Model.js to output');
153
- } else {
154
- console.warn('Warning: Model.js not found in project root');
155
- }
156
-
157
- // Copy rapidd.js to output if it exists
158
- const sourceRapiddJs = path.join(process.cwd(), 'rapidd', 'rapidd.js');
159
- const outputRapiddDir = modelDir.replace(/src[\/\\]Model$/, 'rapidd');
160
- const outputRapiddJs = path.join(outputRapiddDir, 'rapidd.js');
161
-
162
- if (fs.existsSync(sourceRapiddJs)) {
163
- if (!fs.existsSync(outputRapiddDir)) {
164
- fs.mkdirSync(outputRapiddDir, { recursive: true });
165
- }
166
- fs.copyFileSync(sourceRapiddJs, outputRapiddJs);
167
- console.log('Copied rapidd.js to output');
168
- }
169
- }
170
-
171
- module.exports = {
172
- generateAllModels,
173
- generateModelFile
174
- };