@rapidd/build 1.2.1 → 1.2.3
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/package.json
CHANGED
package/src/commands/build.js
CHANGED
|
@@ -7,394 +7,6 @@ const { generateACL } = require('../generators/aclGenerator');
|
|
|
7
7
|
const { parseDatasource } = require('../parsers/datasourceParser');
|
|
8
8
|
const { generateAllRoutes } = require('../generators/routeGenerator');
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
* Generate src/Model.js base class file
|
|
12
|
-
*/
|
|
13
|
-
function generateBaseModelFile(modelJsPath) {
|
|
14
|
-
const content = `const { QueryBuilder, prisma, prismaTransaction } = require("./QueryBuilder");
|
|
15
|
-
const {acl} = require('../rapidd/rapidd');
|
|
16
|
-
const {ErrorResponse} = require('./Api');
|
|
17
|
-
|
|
18
|
-
class Model {
|
|
19
|
-
/**
|
|
20
|
-
* @param {string} name
|
|
21
|
-
* @param {{'user': {}}} options
|
|
22
|
-
*/
|
|
23
|
-
constructor(name, options){
|
|
24
|
-
this.modelName = name;
|
|
25
|
-
this.queryBuilder = new QueryBuilder(name);
|
|
26
|
-
this.acl = acl.model[name] || {};
|
|
27
|
-
this.options = options || {}
|
|
28
|
-
this.user = this.options.user || {'id': 1, 'role': 'application'};
|
|
29
|
-
this.user_id = this.user ? this.user.id : null;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
get primaryKey(){
|
|
33
|
-
const pkey = this.queryBuilder.getPrimaryKey();
|
|
34
|
-
return Array.isArray(pkey) ? pkey.join('_') : pkey;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
get fields(){
|
|
38
|
-
return this.queryBuilder.fields;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
_select = (fields) => this.queryBuilder.select(fields);
|
|
42
|
-
_filter = (q) => this.queryBuilder.filter(q);
|
|
43
|
-
_include = (include) => this.queryBuilder.include(include, this.user);
|
|
44
|
-
_queryCreate = (data) => this.queryBuilder.create(data, this.user);
|
|
45
|
-
_queryUpdate = (id, data) => this.queryBuilder.update(id, data, this.user);
|
|
46
|
-
// ACL METHODS
|
|
47
|
-
_canCreate = () => this.acl.canCreate(this.user);
|
|
48
|
-
_getAccessFilter = () => this.acl.getAccessFilter?.(this.user);
|
|
49
|
-
_getUpdateFilter = () => this.acl.getUpdateFilter(this.user);
|
|
50
|
-
_getDeleteFilter = () => this.acl.getDeleteFilter(this.user);
|
|
51
|
-
_omit = () => this.queryBuilder.omit(this.user);
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
*
|
|
55
|
-
* @param {string} q
|
|
56
|
-
* @property {string|Object} include
|
|
57
|
-
* @param {number} limit
|
|
58
|
-
* @param {number} offset
|
|
59
|
-
* @param {string} sortBy
|
|
60
|
-
* @param {'asc'|'desc'} sortOrder
|
|
61
|
-
* @param {{}} [options={}]
|
|
62
|
-
* @returns {Promise<Object[]>}
|
|
63
|
-
*/
|
|
64
|
-
_getMany = async (q = {}, include = "", limit = 25, offset = 0, sortBy = this.primaryKey, sortOrder = "asc", options = {})=>{
|
|
65
|
-
const take = this.take(Number(limit));
|
|
66
|
-
const skip = this.skip(Number(offset));
|
|
67
|
-
|
|
68
|
-
sortBy = sortBy?.trim();
|
|
69
|
-
sortOrder = sortOrder?.trim();
|
|
70
|
-
if (!sortBy.includes('.') && this.fields[sortBy] == undefined) {
|
|
71
|
-
throw new ErrorResponse(400, "invalid_sort_field", {sortBy, modelName: this.constructor.name});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Query the database using Prisma with filters, pagination, and limits
|
|
75
|
-
const [data, total] = await prismaTransaction([
|
|
76
|
-
(tx) => tx[this.name].findMany({
|
|
77
|
-
'where': this.filter(q),
|
|
78
|
-
'include': this.include(include),
|
|
79
|
-
'take': take,
|
|
80
|
-
'skip': skip,
|
|
81
|
-
'orderBy': this.sort(sortBy, sortOrder),
|
|
82
|
-
'omit': this._omit(),
|
|
83
|
-
...options
|
|
84
|
-
}),
|
|
85
|
-
(tx) => tx[this.name].count({
|
|
86
|
-
'where': this.filter(q)
|
|
87
|
-
})
|
|
88
|
-
]);
|
|
89
|
-
return {data, meta: {take, skip, total}};
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* @param {number} id
|
|
93
|
-
* @param {string | Object} include
|
|
94
|
-
* @param {{}} [options={}]
|
|
95
|
-
* @returns {Promise<{} | null>}
|
|
96
|
-
*/
|
|
97
|
-
_get = async (id, include, options = {}) =>{
|
|
98
|
-
const {omit, ..._options} = options;
|
|
99
|
-
console.log(JSON.stringify(this.include(include)));
|
|
100
|
-
// To determine if the record is inaccessible, either due to non-existence or insufficient permissions, two simultaneous queries are performed.
|
|
101
|
-
const _response = this.prisma.findUnique({
|
|
102
|
-
'where': {
|
|
103
|
-
[this.primaryKey]: id,
|
|
104
|
-
},
|
|
105
|
-
'include': this.include(include),
|
|
106
|
-
'omit': {...this._omit(), ...omit},
|
|
107
|
-
..._options
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const _checkPermission = this.prisma.findUnique({
|
|
111
|
-
'where': {
|
|
112
|
-
[this.primaryKey]: id,
|
|
113
|
-
...this.getAccessFilter()
|
|
114
|
-
},
|
|
115
|
-
'select': {
|
|
116
|
-
'id': true
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const [response, checkPermission] = await Promise.all([_response, _checkPermission]);
|
|
121
|
-
if(response){
|
|
122
|
-
if(checkPermission){
|
|
123
|
-
if(response.id != checkPermission?.id){ // IN CASE access_filter CONTAINS id FIELD
|
|
124
|
-
throw new ErrorResponse(403, "no_permission");
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
else{
|
|
128
|
-
throw new ErrorResponse(403, "no_permission");
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
else{
|
|
132
|
-
throw new ErrorResponse(404, "record_not_found");
|
|
133
|
-
}
|
|
134
|
-
return response;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* @param {{}} data
|
|
138
|
-
* @param {{}} [options={}]
|
|
139
|
-
* @returns {Promise<Object>}
|
|
140
|
-
*/
|
|
141
|
-
_create = async (data, options = {}) => {
|
|
142
|
-
// CHECK CREATE PERMISSION
|
|
143
|
-
if (!this.canCreate()) {
|
|
144
|
-
throw new ErrorResponse(403, "no_permission_to_create");
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// VALIDATE PASSED FIELDS AND RELATIONSHIPS
|
|
148
|
-
this._queryCreate(data);
|
|
149
|
-
|
|
150
|
-
// CREATE
|
|
151
|
-
return await this.prisma.create({
|
|
152
|
-
'data': data,
|
|
153
|
-
'include': this.include('ALL'),
|
|
154
|
-
...options
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* @param {number} id
|
|
160
|
-
* @param {{}} data
|
|
161
|
-
* @param {{}} [options={}]
|
|
162
|
-
* @returns {Promise<Object>}
|
|
163
|
-
*/
|
|
164
|
-
_update = async (id, data, options = {}) => {
|
|
165
|
-
delete data.createdAt;
|
|
166
|
-
delete data.createdBy;
|
|
167
|
-
// CHECK UPDATE PERMISSION
|
|
168
|
-
const updateFilter = this.getUpdateFilter();
|
|
169
|
-
if (updateFilter === false) {
|
|
170
|
-
throw new ErrorResponse(403, "no_permission_to_update");
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// VALIDATE PASSED FIELDS AND RELATIONSHIPS
|
|
174
|
-
this._queryUpdate(id, data);
|
|
175
|
-
const response = await this.prisma.update({
|
|
176
|
-
'where': {
|
|
177
|
-
[this.primaryKey]: id,
|
|
178
|
-
...updateFilter
|
|
179
|
-
},
|
|
180
|
-
'data': data,
|
|
181
|
-
'include': this.include('ALL'),
|
|
182
|
-
...options
|
|
183
|
-
});
|
|
184
|
-
if(response){
|
|
185
|
-
return response;
|
|
186
|
-
}
|
|
187
|
-
throw new ErrorResponse(403, "no_permission");
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* @param {{}} data
|
|
192
|
-
* @param {string} [unique_key=this.primaryKey]
|
|
193
|
-
* @param {{}} [options={}]
|
|
194
|
-
* @returns {Promise<Object>}
|
|
195
|
-
*/
|
|
196
|
-
async _upsert(data, unique_key = this.primaryKey, options = {}){
|
|
197
|
-
const createData = data;
|
|
198
|
-
const updateData = JSON.parse(JSON.stringify(data));
|
|
199
|
-
this.queryBuilder.create(createData, this.user);
|
|
200
|
-
this.queryBuilder.update(updateData, this.user);
|
|
201
|
-
return await this.prisma.upsert({
|
|
202
|
-
'where': {
|
|
203
|
-
[unique_key]: data[unique_key]
|
|
204
|
-
},
|
|
205
|
-
'create': createData,
|
|
206
|
-
'update': updateData,
|
|
207
|
-
'include': this.include('ALL'),
|
|
208
|
-
...options
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
*
|
|
214
|
-
* @param {string} q
|
|
215
|
-
* @returns {Promise<number>}
|
|
216
|
-
*/
|
|
217
|
-
_count = async (q = {}) => {
|
|
218
|
-
return await this.prisma.count({
|
|
219
|
-
'where': this.filter(q)
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* @param {number} id
|
|
225
|
-
* @param {{}} [options={}]
|
|
226
|
-
* @returns {Promise<Object>}
|
|
227
|
-
*/
|
|
228
|
-
_delete = async (id, options = {}) => {
|
|
229
|
-
// CHECK DELETE PERMISSION
|
|
230
|
-
const deleteFilter = this.getDeleteFilter();
|
|
231
|
-
if (deleteFilter === false) {
|
|
232
|
-
throw new ErrorResponse(403, "no_permission_to_delete");
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const response = await this.prisma.delete({
|
|
236
|
-
'where': {
|
|
237
|
-
[this.primaryKey]: id,
|
|
238
|
-
...deleteFilter
|
|
239
|
-
},
|
|
240
|
-
'select': this.select(),
|
|
241
|
-
...options
|
|
242
|
-
});
|
|
243
|
-
if(response){
|
|
244
|
-
return response;
|
|
245
|
-
}
|
|
246
|
-
throw new ErrorResponse(403, "no_permission");
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
*
|
|
251
|
-
* @param {string} q
|
|
252
|
-
* @property {string|Object} include
|
|
253
|
-
* @param {number} limit
|
|
254
|
-
* @param {number} offset
|
|
255
|
-
* @param {string} sortBy
|
|
256
|
-
* @param {'asc'|'desc'} sortOrder
|
|
257
|
-
* @returns {Promise<Object[]>}
|
|
258
|
-
*/
|
|
259
|
-
async getMany(q = {}, include = "", limit = 25, offset = 0, sortBy = "id", sortOrder = "asc"){
|
|
260
|
-
return await this._getMany(q, include, Number(limit), Number(offset), sortBy, sortOrder);
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* @param {number} id
|
|
264
|
-
* @param {string | Object} include
|
|
265
|
-
* @param {{}} [options={}]
|
|
266
|
-
* @returns {Promise<{} | null>}
|
|
267
|
-
*/
|
|
268
|
-
async get(id, include, options = {}){
|
|
269
|
-
return await this._get(id, include, options);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* @param {number} id
|
|
274
|
-
* @param {{}} data
|
|
275
|
-
* @param {{}} [options={}]
|
|
276
|
-
* @returns {Promise<Object>}
|
|
277
|
-
*/
|
|
278
|
-
async update(id, data, options = {}){
|
|
279
|
-
return await this._update(id, data, options);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* @param {{}} data
|
|
284
|
-
* @param {string} [unique_key=this.primaryKey]
|
|
285
|
-
* @param {{}} [options={}]
|
|
286
|
-
* @returns {Promise<Object>}
|
|
287
|
-
*/
|
|
288
|
-
async upsert(data, unique_key = this.primaryKey, options = {}){
|
|
289
|
-
return await this._upsert(data, unique_key, options);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
*
|
|
294
|
-
* @param {string} q
|
|
295
|
-
* @returns {Promise<number>}
|
|
296
|
-
*/
|
|
297
|
-
async count(q = {}) {
|
|
298
|
-
return await this._count(q);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* @param {number} id
|
|
303
|
-
* @returns {Promise<Object>}
|
|
304
|
-
*/
|
|
305
|
-
async delete(id, data, options = {}){
|
|
306
|
-
return await this._delete(id, data, options);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
select(fields){
|
|
310
|
-
return this._select(fields);
|
|
311
|
-
}
|
|
312
|
-
filter(include){
|
|
313
|
-
return {...this._filter(include), ...this.getAccessFilter()};
|
|
314
|
-
}
|
|
315
|
-
include(include){
|
|
316
|
-
return this._include(include);
|
|
317
|
-
}
|
|
318
|
-
sort(sortBy, sortOrder) {
|
|
319
|
-
return this.queryBuilder.sort(sortBy, sortOrder);
|
|
320
|
-
}
|
|
321
|
-
take(limit){
|
|
322
|
-
return this.queryBuilder.take(Number(limit));
|
|
323
|
-
}
|
|
324
|
-
skip(offset){
|
|
325
|
-
const parsed = parseInt(offset);
|
|
326
|
-
if(isNaN(parsed) || parsed < 0){
|
|
327
|
-
return 0;
|
|
328
|
-
}
|
|
329
|
-
return parsed;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/**
|
|
333
|
-
*
|
|
334
|
-
* @returns {Object}
|
|
335
|
-
*/
|
|
336
|
-
getAccessFilter(){
|
|
337
|
-
const filter = this._getAccessFilter()
|
|
338
|
-
if(this.user.role == "application" || filter === true){
|
|
339
|
-
return {};
|
|
340
|
-
}
|
|
341
|
-
return this._getAccessFilter();
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Check if user can create records
|
|
346
|
-
* @returns {boolean}
|
|
347
|
-
*/
|
|
348
|
-
canCreate() {
|
|
349
|
-
if(this.user.role == "application") return true;
|
|
350
|
-
return this._canCreate();
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Get update filter for ACL
|
|
355
|
-
* @returns {Object|false}
|
|
356
|
-
*/
|
|
357
|
-
getUpdateFilter(){
|
|
358
|
-
const filter = this._getUpdateFilter();
|
|
359
|
-
if(this.user.role == "application" || filter === true){
|
|
360
|
-
return {};
|
|
361
|
-
}
|
|
362
|
-
return filter;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* Get delete filter for ACL
|
|
367
|
-
* @returns {Object|false}
|
|
368
|
-
*/
|
|
369
|
-
getDeleteFilter(){
|
|
370
|
-
const filter = this._getDeleteFilter();
|
|
371
|
-
if(this.user.role == "application" || filter === true){
|
|
372
|
-
return {};
|
|
373
|
-
}
|
|
374
|
-
return filter;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
set modelName (name){
|
|
378
|
-
this.name = name;
|
|
379
|
-
this.prisma = prisma[name];
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
static relatedObjects = [];
|
|
383
|
-
static Error = ErrorResponse;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
module.exports = {Model, QueryBuilder, prisma};`;
|
|
387
|
-
|
|
388
|
-
// Ensure src directory exists
|
|
389
|
-
const srcDir = path.dirname(modelJsPath);
|
|
390
|
-
if (!fs.existsSync(srcDir)) {
|
|
391
|
-
fs.mkdirSync(srcDir, { recursive: true });
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
fs.writeFileSync(modelJsPath, content);
|
|
395
|
-
console.log('✓ Generated src/Model.js');
|
|
396
|
-
}
|
|
397
|
-
|
|
398
10
|
/**
|
|
399
11
|
* Generate rapidd/rapidd.js file
|
|
400
12
|
* @param {string} rapiddJsPath - Path to rapidd.js
|
|
@@ -930,12 +542,6 @@ async function buildModels(options) {
|
|
|
930
542
|
generateAllModels(filteredModels, modelDir, modelJsPath);
|
|
931
543
|
}
|
|
932
544
|
|
|
933
|
-
// Generate src/Model.js (base Model class) if it doesn't exist
|
|
934
|
-
if (!fs.existsSync(modelJsPath)) {
|
|
935
|
-
console.log('\nGenerating src/Model.js...');
|
|
936
|
-
generateBaseModelFile(modelJsPath);
|
|
937
|
-
}
|
|
938
|
-
|
|
939
545
|
// Parse datasource to determine database type
|
|
940
546
|
let datasource = { isPostgreSQL: true, url: null }; // Default to PostgreSQL
|
|
941
547
|
try {
|
|
@@ -9,13 +9,16 @@ const path = require('path');
|
|
|
9
9
|
*/
|
|
10
10
|
function generateModelFile(modelName, modelInfo) {
|
|
11
11
|
// Capitalize first letter for class name
|
|
12
|
-
const className = modelName.
|
|
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('');
|
|
13
16
|
|
|
14
17
|
return `const {Model, QueryBuilder, prisma} = require('../Model');
|
|
15
18
|
|
|
16
19
|
class ${className} extends Model {
|
|
17
20
|
constructor(options){
|
|
18
|
-
super('${
|
|
21
|
+
super('${modelName}', options);
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
/**
|
|
@@ -25,7 +28,7 @@ class ${className} extends Model {
|
|
|
25
28
|
* @param {number} offset
|
|
26
29
|
* @param {string} sortBy
|
|
27
30
|
* @param {'asc'|'desc'} sortOrder
|
|
28
|
-
* @returns {Object[]}
|
|
31
|
+
* @returns {Promise<Object[]>}
|
|
29
32
|
*/
|
|
30
33
|
async getMany(q = {}, include = "", limit = 25, offset = 0, sortBy = "id", sortOrder = "asc"){
|
|
31
34
|
return await this._getMany(q, include, Number(limit), Number(offset), sortBy, sortOrder);
|
|
@@ -34,7 +37,7 @@ class ${className} extends Model {
|
|
|
34
37
|
/**
|
|
35
38
|
* @param {number} id
|
|
36
39
|
* @param {string | Object} include
|
|
37
|
-
* @returns {
|
|
40
|
+
* @returns {Promise<Object | null>}
|
|
38
41
|
*/
|
|
39
42
|
async get(id, include){
|
|
40
43
|
return await this._get(id, include);
|
|
@@ -42,7 +45,7 @@ class ${className} extends Model {
|
|
|
42
45
|
|
|
43
46
|
/**
|
|
44
47
|
* @param {Object} data
|
|
45
|
-
* @returns {Object}
|
|
48
|
+
* @returns {Promise<Object>}
|
|
46
49
|
*/
|
|
47
50
|
async create(data){
|
|
48
51
|
return await this._create(data);
|
|
@@ -51,7 +54,7 @@ class ${className} extends Model {
|
|
|
51
54
|
/**
|
|
52
55
|
* @param {number} id
|
|
53
56
|
* @param {{}} data
|
|
54
|
-
* @returns {Object}
|
|
57
|
+
* @returns {Promise<Object>}
|
|
55
58
|
*/
|
|
56
59
|
async update(id, data){
|
|
57
60
|
return await this._update(id, data);
|
|
@@ -89,6 +92,8 @@ class ${className} extends Model {
|
|
|
89
92
|
include(include){
|
|
90
93
|
return this._include(include);
|
|
91
94
|
}
|
|
95
|
+
|
|
96
|
+
static QueryBuilder = new QueryBuilder('${modelName}');
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
module.exports = {${className}, QueryBuilder, prisma};
|
|
@@ -131,7 +136,10 @@ function generateAllModels(models, modelDir, modelJsPath) {
|
|
|
131
136
|
for (const [modelName, modelInfo] of Object.entries(models)) {
|
|
132
137
|
const modelCode = generateModelFile(modelName, modelInfo);
|
|
133
138
|
// Capitalize first letter for filename
|
|
134
|
-
const className = modelName.
|
|
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('');
|
|
135
143
|
const modelPath = path.join(modelDir, `${className}.js`);
|
|
136
144
|
fs.writeFileSync(modelPath, modelCode);
|
|
137
145
|
console.log(`Generated model: ${className}.js`);
|
|
@@ -7,7 +7,10 @@ const path = require('path');
|
|
|
7
7
|
* @returns {string} - Generated route code
|
|
8
8
|
*/
|
|
9
9
|
function generateRouteFile(modelName) {
|
|
10
|
-
const className = modelName.
|
|
10
|
+
const className = modelName.split(/[^a-zA-Z0-9]+/) // split on any non-alphanumeric char
|
|
11
|
+
.filter(Boolean) // remove empty parts
|
|
12
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
13
|
+
.join('');
|
|
11
14
|
|
|
12
15
|
return `const router = require('express').Router();
|
|
13
16
|
const {${className}, QueryBuilder, prisma} = require('../../../src/Model/${className}');
|
|
@@ -104,9 +107,9 @@ function generateAllRoutes(models, routesDir) {
|
|
|
104
107
|
// Generate individual route files
|
|
105
108
|
for (const modelName of Object.keys(models)) {
|
|
106
109
|
const routeCode = generateRouteFile(modelName);
|
|
107
|
-
const routePath = path.join(routesDir, `${modelName
|
|
110
|
+
const routePath = path.join(routesDir, `${modelName}.js`);
|
|
108
111
|
fs.writeFileSync(routePath, routeCode);
|
|
109
|
-
console.log(`Generated route: ${modelName
|
|
112
|
+
console.log(`Generated route: ${modelName}.js`);
|
|
110
113
|
}
|
|
111
114
|
}
|
|
112
115
|
|