@autobe/compiler 0.30.0-dev.20260315 → 0.30.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/LICENSE +661 -661
- package/lib/database/validateDatabaseApplication.js +318 -318
- package/lib/raw/AutoBeCompilerCommonTemplate.js +5 -5
- package/lib/raw/AutoBeCompilerCommonTemplate.js.map +1 -1
- package/lib/raw/AutoBeCompilerInterfaceTemplate.js +4 -4
- package/lib/raw/AutoBeCompilerInterfaceTemplate.js.map +1 -1
- package/lib/raw/AutoBeCompilerRealizeTemplate.js +27 -27
- package/lib/raw/AutoBeCompilerRealizeTemplate.js.map +1 -1
- package/lib/raw/AutoBeCompilerRealizeTemplateOfPostgres.js +4 -4
- package/lib/raw/AutoBeCompilerRealizeTemplateOfPostgres.js.map +1 -1
- package/lib/raw/AutoBeCompilerRealizeTemplateOfSQLite.js +4 -4
- package/lib/raw/AutoBeCompilerRealizeTemplateOfSQLite.js.map +1 -1
- package/lib/raw/AutoBeCompilerTestTemplate.js +8 -8
- package/lib/raw/AutoBeCompilerTestTemplate.js.map +1 -1
- package/lib/raw/nestjs.json +1640 -1640
- package/lib/raw/test.json +130 -130
- package/package.json +4 -4
- package/src/AutoBeCompiler.ts +93 -93
- package/src/AutoBeTypeScriptCompiler.ts +136 -136
- package/src/database/AutoBeDatabaseCompiler.ts +48 -48
- package/src/database/validateDatabaseApplication.ts +873 -873
- package/src/index.ts +5 -5
- package/src/interface/AutoBeInterfaceCompiler.ts +79 -79
- package/src/raw/AutoBeCompilerCommonTemplate.ts +5 -5
- package/src/raw/AutoBeCompilerInterfaceTemplate.ts +4 -4
- package/src/raw/AutoBeCompilerRealizeTemplate.ts +27 -27
- package/src/raw/AutoBeCompilerRealizeTemplateOfPostgres.ts +4 -4
- package/src/raw/AutoBeCompilerRealizeTemplateOfSQLite.ts +4 -4
- package/src/raw/AutoBeCompilerTestTemplate.ts +8 -8
- package/src/raw/nestjs.json +1640 -1640
- package/src/raw/test.json +130 -130
- package/src/realize/AutoBeRealizeCompiler.ts +42 -42
- package/src/realize/testRealizeProject.ts +78 -78
- package/src/realize/writeRealizeControllers.ts +217 -217
- package/src/test/AutoBeTestCompiler.ts +112 -112
- package/src/test/programmers/AutoBeTestAccessorProgrammer.ts +42 -42
- package/src/test/programmers/AutoBeTestFunctionalProgrammer.ts +87 -87
- package/src/test/programmers/AutoBeTestLiteralProgrammer.ts +65 -65
- package/src/test/programmers/AutoBeTestOperatorProgrammer.ts +84 -84
- package/src/test/programmers/AutoBeTestPredicateProgrammer.ts +131 -131
- package/src/test/programmers/AutoBeTestRandomProgrammer.ts +304 -304
- package/src/test/programmers/AutoBeTestStatementProgrammer.ts +154 -154
- package/src/test/programmers/IAutoBeTestApiFunction.ts +6 -6
- package/src/test/programmers/IAutoBeTestProgrammerContext.ts +11 -11
- package/src/test/programmers/writeTestExpression.ts +29 -29
- package/src/test/programmers/writeTestFunction.ts +103 -103
- package/src/test/programmers/writeTestStatement.ts +19 -19
- package/src/utils/ArrayUtil.ts +21 -21
- package/src/utils/FilePrinter.ts +67 -67
- package/src/utils/ProcessUtil.ts +14 -14
- package/src/utils/shrinkCompileResult.ts +16 -16
- package/README.md +0 -261
|
@@ -60,15 +60,15 @@ function validateDuplicatedFiles(app) {
|
|
|
60
60
|
path: `application.files[${container.index}]`,
|
|
61
61
|
table: null,
|
|
62
62
|
field: null,
|
|
63
|
-
message: utils_1.StringUtil.trim `
|
|
64
|
-
File ${container.file.filename} is duplicated.
|
|
65
|
-
|
|
66
|
-
Accessors of the other duplicated files are:
|
|
67
|
-
|
|
63
|
+
message: utils_1.StringUtil.trim `
|
|
64
|
+
File ${container.file.filename} is duplicated.
|
|
65
|
+
|
|
66
|
+
Accessors of the other duplicated files are:
|
|
67
|
+
|
|
68
68
|
${array
|
|
69
69
|
.filter((_oppo, j) => i !== j)
|
|
70
70
|
.map((oppo) => `- application.files[${oppo.index}]`)
|
|
71
|
-
.join("\n")},
|
|
71
|
+
.join("\n")},
|
|
72
72
|
`,
|
|
73
73
|
});
|
|
74
74
|
});
|
|
@@ -95,15 +95,15 @@ function validateDuplicatedModels(app) {
|
|
|
95
95
|
path: `application.files[${container.fileIndex}].models[${container.modelIndex}]`,
|
|
96
96
|
table: container.model.name,
|
|
97
97
|
field: null,
|
|
98
|
-
message: utils_1.StringUtil.trim `
|
|
99
|
-
Model ${container.model.name} is duplicated.
|
|
100
|
-
|
|
101
|
-
Accessors of the other duplicated models are:
|
|
102
|
-
|
|
98
|
+
message: utils_1.StringUtil.trim `
|
|
99
|
+
Model ${container.model.name} is duplicated.
|
|
100
|
+
|
|
101
|
+
Accessors of the other duplicated models are:
|
|
102
|
+
|
|
103
103
|
${array
|
|
104
104
|
.filter((_oppo, j) => i !== j)
|
|
105
105
|
.map((oppo) => `- application.files[${oppo.fileIndex}].models[${oppo.modelIndex}]`)
|
|
106
|
-
.join("\n")},
|
|
106
|
+
.join("\n")},
|
|
107
107
|
`,
|
|
108
108
|
});
|
|
109
109
|
});
|
|
@@ -126,15 +126,15 @@ function validateDuplicatedFields(dict, model, accessor) {
|
|
|
126
126
|
path,
|
|
127
127
|
table: model.name,
|
|
128
128
|
field,
|
|
129
|
-
message: utils_1.StringUtil.trim `
|
|
130
|
-
Field ${field} is duplicated.
|
|
131
|
-
|
|
132
|
-
Accessors of the other duplicated fields are:
|
|
133
|
-
|
|
129
|
+
message: utils_1.StringUtil.trim `
|
|
130
|
+
Field ${field} is duplicated.
|
|
131
|
+
|
|
132
|
+
Accessors of the other duplicated fields are:
|
|
133
|
+
|
|
134
134
|
${array
|
|
135
135
|
.filter((_oppo, j) => i !== j)
|
|
136
136
|
.map((a) => `- ${a}`)
|
|
137
|
-
.join("\n")},
|
|
137
|
+
.join("\n")},
|
|
138
138
|
`,
|
|
139
139
|
});
|
|
140
140
|
});
|
|
@@ -145,38 +145,38 @@ function validateDuplicatedFields(dict, model, accessor) {
|
|
|
145
145
|
path: `${accessor}.plainFields[${i}].name`,
|
|
146
146
|
table: model.name,
|
|
147
147
|
field: field.name,
|
|
148
|
-
message: utils_1.StringUtil.trim `
|
|
149
|
-
Field name conflicts with an existing table name.
|
|
150
|
-
|
|
151
|
-
**What happened?**
|
|
152
|
-
The field "${field.name}" in model "${model.name}" has the same name as another table "${field.name}".
|
|
153
|
-
This can cause confusion and potential issues in the generated code.
|
|
154
|
-
|
|
155
|
-
**Why is this a problem?**
|
|
156
|
-
- Naming conflicts can lead to ambiguous references in your code
|
|
157
|
-
- It may cause issues with Prisma's relation inference
|
|
158
|
-
- It makes the schema harder to understand and maintain
|
|
159
|
-
|
|
160
|
-
**How to fix this:**
|
|
161
|
-
|
|
162
|
-
1. **If this is a denormalization field (pre-calculated value):**
|
|
163
|
-
- Consider if this field is really necessary
|
|
164
|
-
- If it's storing aggregated data from the related table, it might be better to calculate it dynamically
|
|
165
|
-
- Remove the field if it's redundant
|
|
166
|
-
|
|
167
|
-
2. **If this is a legitimate field:**
|
|
168
|
-
- Rename the field to be more descriptive
|
|
169
|
-
- Good naming examples:
|
|
170
|
-
- Instead of "user", use "user_name" or "user_id"
|
|
171
|
-
- Instead of "order", use "order_status" or "order_count"
|
|
172
|
-
- Instead of "product", use "product_name" or "product_code"
|
|
173
|
-
|
|
174
|
-
3. **Naming best practices:**
|
|
175
|
-
- Use specific, descriptive names that indicate the field's purpose
|
|
176
|
-
- Avoid using table names as field names
|
|
177
|
-
- Consider adding a suffix or prefix to clarify the field's role
|
|
178
|
-
|
|
179
|
-
Please rename the field or remove it if unnecessary.
|
|
148
|
+
message: utils_1.StringUtil.trim `
|
|
149
|
+
Field name conflicts with an existing table name.
|
|
150
|
+
|
|
151
|
+
**What happened?**
|
|
152
|
+
The field "${field.name}" in model "${model.name}" has the same name as another table "${field.name}".
|
|
153
|
+
This can cause confusion and potential issues in the generated code.
|
|
154
|
+
|
|
155
|
+
**Why is this a problem?**
|
|
156
|
+
- Naming conflicts can lead to ambiguous references in your code
|
|
157
|
+
- It may cause issues with Prisma's relation inference
|
|
158
|
+
- It makes the schema harder to understand and maintain
|
|
159
|
+
|
|
160
|
+
**How to fix this:**
|
|
161
|
+
|
|
162
|
+
1. **If this is a denormalization field (pre-calculated value):**
|
|
163
|
+
- Consider if this field is really necessary
|
|
164
|
+
- If it's storing aggregated data from the related table, it might be better to calculate it dynamically
|
|
165
|
+
- Remove the field if it's redundant
|
|
166
|
+
|
|
167
|
+
2. **If this is a legitimate field:**
|
|
168
|
+
- Rename the field to be more descriptive
|
|
169
|
+
- Good naming examples:
|
|
170
|
+
- Instead of "user", use "user_name" or "user_id"
|
|
171
|
+
- Instead of "order", use "order_status" or "order_count"
|
|
172
|
+
- Instead of "product", use "product_name" or "product_code"
|
|
173
|
+
|
|
174
|
+
3. **Naming best practices:**
|
|
175
|
+
- Use specific, descriptive names that indicate the field's purpose
|
|
176
|
+
- Avoid using table names as field names
|
|
177
|
+
- Consider adding a suffix or prefix to clarify the field's role
|
|
178
|
+
|
|
179
|
+
Please rename the field or remove it if unnecessary.
|
|
180
180
|
`,
|
|
181
181
|
});
|
|
182
182
|
});
|
|
@@ -202,15 +202,15 @@ function validateDuplicatedIndexes(model, accessor) {
|
|
|
202
202
|
path,
|
|
203
203
|
table: model.name,
|
|
204
204
|
field: null,
|
|
205
|
-
message: utils_1.StringUtil.trim `
|
|
206
|
-
Duplicated index found (${fieldNames.join(", ")}).
|
|
207
|
-
|
|
208
|
-
Accessors of the other duplicated indexes are:
|
|
209
|
-
|
|
205
|
+
message: utils_1.StringUtil.trim `
|
|
206
|
+
Duplicated index found (${fieldNames.join(", ")}).
|
|
207
|
+
|
|
208
|
+
Accessors of the other duplicated indexes are:
|
|
209
|
+
|
|
210
210
|
${array
|
|
211
211
|
.filter((_oppo, j) => i !== j)
|
|
212
212
|
.map((a) => `- ${a}`)
|
|
213
|
-
.join("\n")},
|
|
213
|
+
.join("\n")},
|
|
214
214
|
`,
|
|
215
215
|
});
|
|
216
216
|
});
|
|
@@ -228,13 +228,13 @@ function validateDuplicatedIndexes(model, accessor) {
|
|
|
228
228
|
path: `${accessor}.uniqueIndexes[${i}].fieldNames[0]`,
|
|
229
229
|
table: model.name,
|
|
230
230
|
field: null,
|
|
231
|
-
message: utils_1.StringUtil.trim `
|
|
232
|
-
Duplicated unique index found (${subset[0]}).
|
|
233
|
-
|
|
234
|
-
You have defined an unique index that is already included,
|
|
235
|
-
in the foreign field with unique constraint.
|
|
236
|
-
|
|
237
|
-
Remove this unique index to avoid the duplication.
|
|
231
|
+
message: utils_1.StringUtil.trim `
|
|
232
|
+
Duplicated unique index found (${subset[0]}).
|
|
233
|
+
|
|
234
|
+
You have defined an unique index that is already included,
|
|
235
|
+
in the foreign field with unique constraint.
|
|
236
|
+
|
|
237
|
+
Remove this unique index to avoid the duplication.
|
|
238
238
|
`,
|
|
239
239
|
});
|
|
240
240
|
const cIndex = model.uniqueIndexes.findIndex((u) => u.fieldNames.length === subset.length &&
|
|
@@ -244,45 +244,45 @@ function validateDuplicatedIndexes(model, accessor) {
|
|
|
244
244
|
path: `${accessor}.uniqueIndexes[${i}].fieldNames`,
|
|
245
245
|
table: model.name,
|
|
246
246
|
field: null,
|
|
247
|
-
message: utils_1.StringUtil.trim `
|
|
248
|
-
Redundant subset unique index detected.
|
|
249
|
-
|
|
250
|
-
**What is a subset unique index problem?**
|
|
251
|
-
When you have a unique index on multiple fields, any subset of those fields is automatically unique too.
|
|
252
|
-
This is a fundamental property of unique constraints in databases.
|
|
253
|
-
|
|
254
|
-
**Current situation:**
|
|
255
|
-
- You have a unique index on: (${unique.fieldNames.join(", ")})
|
|
256
|
-
- But there's already a unique index on its subset: (${subset.join(", ")})
|
|
257
|
-
- This makes the larger unique index redundant for uniqueness purposes
|
|
258
|
-
|
|
259
|
-
**Why is this a problem?**
|
|
260
|
-
1. **Logical redundancy**: If (A) is unique, then (A, B) is automatically unique
|
|
261
|
-
2. **Performance overhead**: Maintaining unnecessary indexes slows down write operations
|
|
262
|
-
3. **Storage waste**: Each index consumes disk space
|
|
263
|
-
4. **Confusion**: It's unclear which uniqueness constraint is the intended one
|
|
264
|
-
|
|
265
|
-
**Example to illustrate:**
|
|
266
|
-
If email is unique, then (email, name) is automatically unique because:
|
|
267
|
-
- No two records can have the same email
|
|
268
|
-
- Therefore, no two records can have the same (email, name) combination
|
|
269
|
-
|
|
270
|
-
**How to fix:**
|
|
271
|
-
Choose one of these solutions based on your needs:
|
|
272
|
-
|
|
273
|
-
1. **If you need uniqueness only:**
|
|
274
|
-
- Keep just the subset unique index: (${subset.join(", ")})
|
|
275
|
-
- Remove the larger unique index
|
|
276
|
-
|
|
277
|
-
2. **If you need the multi-field index for query performance:**
|
|
278
|
-
- Keep the subset as unique index: (${subset.join(", ")})
|
|
279
|
-
- Change the larger index to a plain (non-unique) index for performance
|
|
280
|
-
|
|
281
|
-
3. **If the subset unique was added by mistake:**
|
|
282
|
-
- Remove the subset unique index
|
|
283
|
-
- Keep the multi-field unique index
|
|
284
|
-
|
|
285
|
-
Please review your uniqueness requirements and adjust accordingly.
|
|
247
|
+
message: utils_1.StringUtil.trim `
|
|
248
|
+
Redundant subset unique index detected.
|
|
249
|
+
|
|
250
|
+
**What is a subset unique index problem?**
|
|
251
|
+
When you have a unique index on multiple fields, any subset of those fields is automatically unique too.
|
|
252
|
+
This is a fundamental property of unique constraints in databases.
|
|
253
|
+
|
|
254
|
+
**Current situation:**
|
|
255
|
+
- You have a unique index on: (${unique.fieldNames.join(", ")})
|
|
256
|
+
- But there's already a unique index on its subset: (${subset.join(", ")})
|
|
257
|
+
- This makes the larger unique index redundant for uniqueness purposes
|
|
258
|
+
|
|
259
|
+
**Why is this a problem?**
|
|
260
|
+
1. **Logical redundancy**: If (A) is unique, then (A, B) is automatically unique
|
|
261
|
+
2. **Performance overhead**: Maintaining unnecessary indexes slows down write operations
|
|
262
|
+
3. **Storage waste**: Each index consumes disk space
|
|
263
|
+
4. **Confusion**: It's unclear which uniqueness constraint is the intended one
|
|
264
|
+
|
|
265
|
+
**Example to illustrate:**
|
|
266
|
+
If email is unique, then (email, name) is automatically unique because:
|
|
267
|
+
- No two records can have the same email
|
|
268
|
+
- Therefore, no two records can have the same (email, name) combination
|
|
269
|
+
|
|
270
|
+
**How to fix:**
|
|
271
|
+
Choose one of these solutions based on your needs:
|
|
272
|
+
|
|
273
|
+
1. **If you need uniqueness only:**
|
|
274
|
+
- Keep just the subset unique index: (${subset.join(", ")})
|
|
275
|
+
- Remove the larger unique index
|
|
276
|
+
|
|
277
|
+
2. **If you need the multi-field index for query performance:**
|
|
278
|
+
- Keep the subset as unique index: (${subset.join(", ")})
|
|
279
|
+
- Change the larger index to a plain (non-unique) index for performance
|
|
280
|
+
|
|
281
|
+
3. **If the subset unique was added by mistake:**
|
|
282
|
+
- Remove the subset unique index
|
|
283
|
+
- Keep the multi-field unique index
|
|
284
|
+
|
|
285
|
+
Please review your uniqueness requirements and adjust accordingly.
|
|
286
286
|
`,
|
|
287
287
|
});
|
|
288
288
|
});
|
|
@@ -298,43 +298,43 @@ function validateDuplicatedIndexes(model, accessor) {
|
|
|
298
298
|
path: `${accessor}.plainIndexes[${i}].fieldNames`,
|
|
299
299
|
table: model.name,
|
|
300
300
|
field: null,
|
|
301
|
-
message: utils_1.StringUtil.trim `
|
|
302
|
-
Inefficient subset index detected - superset index exists.
|
|
303
|
-
|
|
304
|
-
**What is a subset/superset index problem?**
|
|
305
|
-
In database indexing, when you have an index on (A, B, C), it can efficiently serve queries
|
|
306
|
-
that filter by A, or by (A, B), or by (A, B, C). This is called index prefix matching.
|
|
307
|
-
|
|
308
|
-
**Current situation:**
|
|
309
|
-
- You have a plain index on: (${x.fieldNames.join(", ")})
|
|
310
|
-
- But there's already a plain index on its superset: (${y.fieldNames.join(", ")})
|
|
311
|
-
- The subset index is redundant because the superset can handle the same queries
|
|
312
|
-
|
|
313
|
-
**Why is this a problem?**
|
|
314
|
-
1. **Query efficiency**: The superset index can handle all queries the subset can
|
|
315
|
-
2. **Storage waste**: You're maintaining two indexes where one would suffice
|
|
316
|
-
3. **Write performance**: Each index slows down INSERT, UPDATE, and DELETE operations
|
|
317
|
-
4. **Maintenance overhead**: More indexes mean more work for the database
|
|
318
|
-
|
|
319
|
-
**How indexes work (example):**
|
|
320
|
-
If you have an index on (country, city, street):
|
|
321
|
-
- ✅ Can efficiently find by country
|
|
322
|
-
- ✅ Can efficiently find by country + city
|
|
323
|
-
- ✅ Can efficiently find by country + city + street
|
|
324
|
-
- ❌ Cannot efficiently find by city alone
|
|
325
|
-
- ❌ Cannot efficiently find by street alone
|
|
326
|
-
|
|
327
|
-
**How to fix:**
|
|
328
|
-
Remove the subset index (${x.fieldNames.join(", ")}) because:
|
|
329
|
-
- The superset index (${y.fieldNames.join(", ")}) already covers these queries
|
|
330
|
-
- You'll save storage space and improve write performance
|
|
331
|
-
- Query performance will remain the same
|
|
332
|
-
|
|
333
|
-
**When to keep both indexes:**
|
|
334
|
-
Only if the subset index is UNIQUE (which it isn't in this case), as unique
|
|
335
|
-
constraints serve a different purpose than performance optimization.
|
|
336
|
-
|
|
337
|
-
Please remove the redundant subset index.
|
|
301
|
+
message: utils_1.StringUtil.trim `
|
|
302
|
+
Inefficient subset index detected - superset index exists.
|
|
303
|
+
|
|
304
|
+
**What is a subset/superset index problem?**
|
|
305
|
+
In database indexing, when you have an index on (A, B, C), it can efficiently serve queries
|
|
306
|
+
that filter by A, or by (A, B), or by (A, B, C). This is called index prefix matching.
|
|
307
|
+
|
|
308
|
+
**Current situation:**
|
|
309
|
+
- You have a plain index on: (${x.fieldNames.join(", ")})
|
|
310
|
+
- But there's already a plain index on its superset: (${y.fieldNames.join(", ")})
|
|
311
|
+
- The subset index is redundant because the superset can handle the same queries
|
|
312
|
+
|
|
313
|
+
**Why is this a problem?**
|
|
314
|
+
1. **Query efficiency**: The superset index can handle all queries the subset can
|
|
315
|
+
2. **Storage waste**: You're maintaining two indexes where one would suffice
|
|
316
|
+
3. **Write performance**: Each index slows down INSERT, UPDATE, and DELETE operations
|
|
317
|
+
4. **Maintenance overhead**: More indexes mean more work for the database
|
|
318
|
+
|
|
319
|
+
**How indexes work (example):**
|
|
320
|
+
If you have an index on (country, city, street):
|
|
321
|
+
- ✅ Can efficiently find by country
|
|
322
|
+
- ✅ Can efficiently find by country + city
|
|
323
|
+
- ✅ Can efficiently find by country + city + street
|
|
324
|
+
- ❌ Cannot efficiently find by city alone
|
|
325
|
+
- ❌ Cannot efficiently find by street alone
|
|
326
|
+
|
|
327
|
+
**How to fix:**
|
|
328
|
+
Remove the subset index (${x.fieldNames.join(", ")}) because:
|
|
329
|
+
- The superset index (${y.fieldNames.join(", ")}) already covers these queries
|
|
330
|
+
- You'll save storage space and improve write performance
|
|
331
|
+
- Query performance will remain the same
|
|
332
|
+
|
|
333
|
+
**When to keep both indexes:**
|
|
334
|
+
Only if the subset index is UNIQUE (which it isn't in this case), as unique
|
|
335
|
+
constraints serve a different purpose than performance optimization.
|
|
336
|
+
|
|
337
|
+
Please remove the redundant subset index.
|
|
338
338
|
`,
|
|
339
339
|
});
|
|
340
340
|
});
|
|
@@ -346,12 +346,12 @@ function validateDuplicatedIndexes(model, accessor) {
|
|
|
346
346
|
path: `${accessor}.ginIndexes`,
|
|
347
347
|
table: model.name,
|
|
348
348
|
field: null,
|
|
349
|
-
message: utils_1.StringUtil.trim `
|
|
350
|
-
Duplicated GIN index found.
|
|
351
|
-
|
|
352
|
-
GIN index can only be used once per field.
|
|
353
|
-
|
|
354
|
-
Please remove the duplicated GIN indexes.
|
|
349
|
+
message: utils_1.StringUtil.trim `
|
|
350
|
+
Duplicated GIN index found.
|
|
351
|
+
|
|
352
|
+
GIN index can only be used once per field.
|
|
353
|
+
|
|
354
|
+
Please remove the duplicated GIN indexes.
|
|
355
355
|
`,
|
|
356
356
|
});
|
|
357
357
|
return errors;
|
|
@@ -387,24 +387,24 @@ function validateDuplicatedRelationOppositeNames(dict, model) {
|
|
|
387
387
|
path: `application.files[${c.fileIndex}].models[${c.modelIndex}].foreignFields[${item.foreignFieldIndex}].relation.oppositeName`,
|
|
388
388
|
table: c.model.name,
|
|
389
389
|
field: ff.name,
|
|
390
|
-
message: utils_1.StringUtil.trim `
|
|
391
|
-
oppositeName "${oppositeName}" conflicts with existing field in target model "${model.name}".
|
|
392
|
-
|
|
393
|
-
**What happened?**
|
|
394
|
-
The oppositeName "${oppositeName}" would create a reverse relation property in "${model.name}",
|
|
395
|
-
but "${model.name}" already has a field or relation with that name.
|
|
396
|
-
|
|
397
|
-
**Why is this a problem?**
|
|
398
|
-
- Prisma cannot have two properties with the same name in a model
|
|
399
|
-
- This will cause Prisma schema compilation errors
|
|
400
|
-
- The reverse relation would overwrite or conflict with the existing field
|
|
401
|
-
|
|
402
|
-
**How to fix:**
|
|
403
|
-
Choose a different oppositeName that doesn't conflict with existing fields in "${model.name}".
|
|
404
|
-
|
|
405
|
-
**Naming suggestions:**
|
|
406
|
-
- Add a descriptive prefix/suffix: "${oppositeName}List", "${oppositeName}Items", "related${oppositeName.charAt(0).toUpperCase() + oppositeName.slice(1)}"
|
|
407
|
-
- Use the source model name: "${c.model.name.replace(/_/g, "").toLowerCase()}s"
|
|
390
|
+
message: utils_1.StringUtil.trim `
|
|
391
|
+
oppositeName "${oppositeName}" conflicts with existing field in target model "${model.name}".
|
|
392
|
+
|
|
393
|
+
**What happened?**
|
|
394
|
+
The oppositeName "${oppositeName}" would create a reverse relation property in "${model.name}",
|
|
395
|
+
but "${model.name}" already has a field or relation with that name.
|
|
396
|
+
|
|
397
|
+
**Why is this a problem?**
|
|
398
|
+
- Prisma cannot have two properties with the same name in a model
|
|
399
|
+
- This will cause Prisma schema compilation errors
|
|
400
|
+
- The reverse relation would overwrite or conflict with the existing field
|
|
401
|
+
|
|
402
|
+
**How to fix:**
|
|
403
|
+
Choose a different oppositeName that doesn't conflict with existing fields in "${model.name}".
|
|
404
|
+
|
|
405
|
+
**Naming suggestions:**
|
|
406
|
+
- Add a descriptive prefix/suffix: "${oppositeName}List", "${oppositeName}Items", "related${oppositeName.charAt(0).toUpperCase() + oppositeName.slice(1)}"
|
|
407
|
+
- Use the source model name: "${c.model.name.replace(/_/g, "").toLowerCase()}s"
|
|
408
408
|
`,
|
|
409
409
|
});
|
|
410
410
|
});
|
|
@@ -421,41 +421,41 @@ function validateDuplicatedRelationOppositeNames(dict, model) {
|
|
|
421
421
|
path: `application.files[${c.fileIndex}].models[${c.modelIndex}].foreignFields[${item.foreignFieldIndex}].relation.oppositeName`,
|
|
422
422
|
table: c.model.name,
|
|
423
423
|
field: ff.name,
|
|
424
|
-
message: utils_1.StringUtil.trim `
|
|
425
|
-
Duplicated relation oppositeName "${oppositeName}" detected on target model "${model.name}".
|
|
426
|
-
|
|
427
|
-
**What is oppositeName?**
|
|
428
|
-
In Prisma relations, oppositeName defines the name of the reverse relation field
|
|
429
|
-
on the target model. It allows the target model to access related records through
|
|
430
|
-
this named property.
|
|
431
|
-
|
|
432
|
-
**Current situation:**
|
|
433
|
-
Multiple foreign key fields from different models are trying to create reverse
|
|
434
|
-
relations on "${model.name}" with the same oppositeName "${oppositeName}".
|
|
435
|
-
|
|
436
|
-
**Conflicting relations:**
|
|
424
|
+
message: utils_1.StringUtil.trim `
|
|
425
|
+
Duplicated relation oppositeName "${oppositeName}" detected on target model "${model.name}".
|
|
426
|
+
|
|
427
|
+
**What is oppositeName?**
|
|
428
|
+
In Prisma relations, oppositeName defines the name of the reverse relation field
|
|
429
|
+
on the target model. It allows the target model to access related records through
|
|
430
|
+
this named property.
|
|
431
|
+
|
|
432
|
+
**Current situation:**
|
|
433
|
+
Multiple foreign key fields from different models are trying to create reverse
|
|
434
|
+
relations on "${model.name}" with the same oppositeName "${oppositeName}".
|
|
435
|
+
|
|
436
|
+
**Conflicting relations:**
|
|
437
437
|
${array
|
|
438
438
|
.filter((_, j) => i !== j)
|
|
439
439
|
.map((oppo) => `- Model "${oppo.container.model.name}", field "${oppo.foreignField.name}" (accessor: application.files[${oppo.container.fileIndex}].models[${oppo.container.modelIndex}].foreignFields[${oppo.foreignFieldIndex}].relation.oppositeName)`)
|
|
440
|
-
.join("\n")}
|
|
441
|
-
|
|
442
|
-
**Why is this a problem?**
|
|
443
|
-
- Prisma requires unique relation names within a model
|
|
444
|
-
- When "${model.name}" tries to access related records, it won't know which relation to use
|
|
445
|
-
- This will cause Prisma schema compilation errors
|
|
446
|
-
|
|
447
|
-
**How to fix:**
|
|
448
|
-
Each relation pointing to "${model.name}" must have a unique oppositeName.
|
|
449
|
-
|
|
450
|
-
**Naming suggestions:**
|
|
451
|
-
- Use descriptive names that indicate the relationship's purpose
|
|
452
|
-
- Include the source model name for clarity
|
|
453
|
-
- Examples:
|
|
454
|
-
- Instead of both using "orders", use "customerOrders" and "sellerOrders"
|
|
455
|
-
- Instead of both using "users", use "createdByUser" and "assignedToUser"
|
|
456
|
-
- For "${c.model.name}" → "${model.name}": consider "${c.model.name.charAt(0).toLowerCase() + c.model.name.slice(1)}s" or a more descriptive name
|
|
457
|
-
|
|
458
|
-
Please rename the oppositeName to be unique across all relations targeting "${model.name}".
|
|
440
|
+
.join("\n")}
|
|
441
|
+
|
|
442
|
+
**Why is this a problem?**
|
|
443
|
+
- Prisma requires unique relation names within a model
|
|
444
|
+
- When "${model.name}" tries to access related records, it won't know which relation to use
|
|
445
|
+
- This will cause Prisma schema compilation errors
|
|
446
|
+
|
|
447
|
+
**How to fix:**
|
|
448
|
+
Each relation pointing to "${model.name}" must have a unique oppositeName.
|
|
449
|
+
|
|
450
|
+
**Naming suggestions:**
|
|
451
|
+
- Use descriptive names that indicate the relationship's purpose
|
|
452
|
+
- Include the source model name for clarity
|
|
453
|
+
- Examples:
|
|
454
|
+
- Instead of both using "orders", use "customerOrders" and "sellerOrders"
|
|
455
|
+
- Instead of both using "users", use "createdByUser" and "assignedToUser"
|
|
456
|
+
- For "${c.model.name}" → "${model.name}": consider "${c.model.name.charAt(0).toLowerCase() + c.model.name.slice(1)}s" or a more descriptive name
|
|
457
|
+
|
|
458
|
+
Please rename the oppositeName to be unique across all relations targeting "${model.name}".
|
|
459
459
|
`,
|
|
460
460
|
});
|
|
461
461
|
});
|
|
@@ -473,8 +473,8 @@ function validateValidNames(model, accessor) {
|
|
|
473
473
|
path: props.accessor,
|
|
474
474
|
table: model.name,
|
|
475
475
|
field: props.field,
|
|
476
|
-
message: utils_1.StringUtil.trim `
|
|
477
|
-
The name "${props.value}" is a system reserved keyword and cannot be used.
|
|
476
|
+
message: utils_1.StringUtil.trim `
|
|
477
|
+
The name "${props.value}" is a system reserved keyword and cannot be used.
|
|
478
478
|
`,
|
|
479
479
|
});
|
|
480
480
|
else if (utils_1.AutoBeEscaper.variable(props.value) === false)
|
|
@@ -482,10 +482,10 @@ function validateValidNames(model, accessor) {
|
|
|
482
482
|
path: props.accessor,
|
|
483
483
|
table: model.name,
|
|
484
484
|
field: props.field,
|
|
485
|
-
message: utils_1.StringUtil.trim `
|
|
486
|
-
The name "${props.value}" is not a valid identifier.
|
|
487
|
-
|
|
488
|
-
Change to a valid identifier which can be a variable name in programming languages.
|
|
485
|
+
message: utils_1.StringUtil.trim `
|
|
486
|
+
The name "${props.value}" is not a valid identifier.
|
|
487
|
+
|
|
488
|
+
Change to a valid identifier which can be a variable name in programming languages.
|
|
489
489
|
`,
|
|
490
490
|
});
|
|
491
491
|
};
|
|
@@ -584,38 +584,38 @@ function validateIndexes(model, accessor) {
|
|
|
584
584
|
path: `${accessor}.ginIndexes[${i}].fieldName`,
|
|
585
585
|
table: model.name,
|
|
586
586
|
field: null,
|
|
587
|
-
message: utils_1.StringUtil.trim `
|
|
588
|
-
GIN index cannot be applied to this field.
|
|
589
|
-
|
|
590
|
-
**What is a GIN index?**
|
|
591
|
-
GIN (Generalized Inverted Index) is a special index type in PostgreSQL designed for
|
|
592
|
-
full-text search and operations on complex data types. In AutoBE, GIN indexes are
|
|
593
|
-
used exclusively for string fields to enable efficient text searching.
|
|
594
|
-
|
|
595
|
-
**Current problem:**
|
|
596
|
-
The field "${gin.fieldName}" specified for GIN index does not exist in the plain fields
|
|
597
|
-
of model "${model.name}".
|
|
598
|
-
|
|
599
|
-
**Possible causes:**
|
|
600
|
-
1. The field name is misspelled
|
|
601
|
-
2. The field is a foreign key field (not a plain field)
|
|
602
|
-
3. The field was removed but the index definition remained
|
|
603
|
-
|
|
604
|
-
**How to fix:**
|
|
605
|
-
1. Check if the field name is correct
|
|
606
|
-
2. Ensure the field exists in the plainFields array
|
|
607
|
-
3. Make sure the field is of type "string" (GIN indexes only work with strings)
|
|
608
|
-
4. If the field doesn't exist, either:
|
|
609
|
-
- Add the missing string field to plainFields
|
|
610
|
-
- Remove this GIN index definition
|
|
611
|
-
|
|
612
|
-
**Example of correct GIN index usage:**
|
|
613
|
-
plainFields: [
|
|
614
|
-
{ name: "content", type: "string" } // ✓ Can use GIN index
|
|
615
|
-
]
|
|
616
|
-
ginIndexes: [
|
|
617
|
-
{ fieldName: "content" } // ✓ Correct
|
|
618
|
-
]
|
|
587
|
+
message: utils_1.StringUtil.trim `
|
|
588
|
+
GIN index cannot be applied to this field.
|
|
589
|
+
|
|
590
|
+
**What is a GIN index?**
|
|
591
|
+
GIN (Generalized Inverted Index) is a special index type in PostgreSQL designed for
|
|
592
|
+
full-text search and operations on complex data types. In AutoBE, GIN indexes are
|
|
593
|
+
used exclusively for string fields to enable efficient text searching.
|
|
594
|
+
|
|
595
|
+
**Current problem:**
|
|
596
|
+
The field "${gin.fieldName}" specified for GIN index does not exist in the plain fields
|
|
597
|
+
of model "${model.name}".
|
|
598
|
+
|
|
599
|
+
**Possible causes:**
|
|
600
|
+
1. The field name is misspelled
|
|
601
|
+
2. The field is a foreign key field (not a plain field)
|
|
602
|
+
3. The field was removed but the index definition remained
|
|
603
|
+
|
|
604
|
+
**How to fix:**
|
|
605
|
+
1. Check if the field name is correct
|
|
606
|
+
2. Ensure the field exists in the plainFields array
|
|
607
|
+
3. Make sure the field is of type "string" (GIN indexes only work with strings)
|
|
608
|
+
4. If the field doesn't exist, either:
|
|
609
|
+
- Add the missing string field to plainFields
|
|
610
|
+
- Remove this GIN index definition
|
|
611
|
+
|
|
612
|
+
**Example of correct GIN index usage:**
|
|
613
|
+
plainFields: [
|
|
614
|
+
{ name: "content", type: "string" } // ✓ Can use GIN index
|
|
615
|
+
]
|
|
616
|
+
ginIndexes: [
|
|
617
|
+
{ fieldName: "content" } // ✓ Correct
|
|
618
|
+
]
|
|
619
619
|
`,
|
|
620
620
|
});
|
|
621
621
|
else if (model.plainFields[pIndex].type !== "string")
|
|
@@ -623,44 +623,44 @@ function validateIndexes(model, accessor) {
|
|
|
623
623
|
path: `${accessor}.ginIndexes[${i}].fieldName`,
|
|
624
624
|
table: model.name,
|
|
625
625
|
field: model.plainFields[pIndex].name,
|
|
626
|
-
message: utils_1.StringUtil.trim `
|
|
627
|
-
GIN index type mismatch - requires string field.
|
|
628
|
-
|
|
629
|
-
**What is a GIN index?**
|
|
630
|
-
GIN (Generalized Inverted Index) is PostgreSQL's specialized index for full-text search.
|
|
631
|
-
It's designed to efficiently search within text content, making it perfect for features like:
|
|
632
|
-
- Search functionality in articles or posts
|
|
633
|
-
- Finding keywords in product descriptions
|
|
634
|
-
- Filtering by text content
|
|
635
|
-
|
|
636
|
-
**Current problem:**
|
|
637
|
-
You're trying to apply a GIN index to field "${gin.fieldName}" which is of type "${model.plainFields[pIndex].type}".
|
|
638
|
-
GIN indexes can ONLY be applied to "string" type fields.
|
|
639
|
-
|
|
640
|
-
**Why string fields only?**
|
|
641
|
-
GIN indexes work by breaking down text into searchable tokens (words, phrases).
|
|
642
|
-
Other data types like numbers, booleans, or dates don't have this text structure.
|
|
643
|
-
|
|
644
|
-
**How to fix:**
|
|
645
|
-
|
|
646
|
-
1. **If you need text search on this field:**
|
|
647
|
-
- Change the field type to "string"
|
|
648
|
-
- Example: If storing a product code as number, consider storing as string instead
|
|
649
|
-
|
|
650
|
-
2. **If the field should remain as ${model.plainFields[pIndex].type}:**
|
|
651
|
-
- Remove the GIN index for this field
|
|
652
|
-
- Use a regular index instead (plainIndexes)
|
|
653
|
-
- Consider if you really need an index on this field
|
|
654
|
-
|
|
655
|
-
3. **Alternative indexing strategies:**
|
|
656
|
-
- For ${model.plainFields[pIndex].type} fields, use plainIndexes for general performance
|
|
657
|
-
- For unique ${model.plainFields[pIndex].type} values, use uniqueIndexes
|
|
658
|
-
- GIN indexes should be reserved for text search scenarios only
|
|
659
|
-
|
|
660
|
-
**Location of the field:**
|
|
661
|
-
- Field definition: ${`${accessor}.plainFields[${pIndex}]`}
|
|
662
|
-
|
|
663
|
-
Please either change the field type to "string" or remove the GIN index.
|
|
626
|
+
message: utils_1.StringUtil.trim `
|
|
627
|
+
GIN index type mismatch - requires string field.
|
|
628
|
+
|
|
629
|
+
**What is a GIN index?**
|
|
630
|
+
GIN (Generalized Inverted Index) is PostgreSQL's specialized index for full-text search.
|
|
631
|
+
It's designed to efficiently search within text content, making it perfect for features like:
|
|
632
|
+
- Search functionality in articles or posts
|
|
633
|
+
- Finding keywords in product descriptions
|
|
634
|
+
- Filtering by text content
|
|
635
|
+
|
|
636
|
+
**Current problem:**
|
|
637
|
+
You're trying to apply a GIN index to field "${gin.fieldName}" which is of type "${model.plainFields[pIndex].type}".
|
|
638
|
+
GIN indexes can ONLY be applied to "string" type fields.
|
|
639
|
+
|
|
640
|
+
**Why string fields only?**
|
|
641
|
+
GIN indexes work by breaking down text into searchable tokens (words, phrases).
|
|
642
|
+
Other data types like numbers, booleans, or dates don't have this text structure.
|
|
643
|
+
|
|
644
|
+
**How to fix:**
|
|
645
|
+
|
|
646
|
+
1. **If you need text search on this field:**
|
|
647
|
+
- Change the field type to "string"
|
|
648
|
+
- Example: If storing a product code as number, consider storing as string instead
|
|
649
|
+
|
|
650
|
+
2. **If the field should remain as ${model.plainFields[pIndex].type}:**
|
|
651
|
+
- Remove the GIN index for this field
|
|
652
|
+
- Use a regular index instead (plainIndexes)
|
|
653
|
+
- Consider if you really need an index on this field
|
|
654
|
+
|
|
655
|
+
3. **Alternative indexing strategies:**
|
|
656
|
+
- For ${model.plainFields[pIndex].type} fields, use plainIndexes for general performance
|
|
657
|
+
- For unique ${model.plainFields[pIndex].type} values, use uniqueIndexes
|
|
658
|
+
- GIN indexes should be reserved for text search scenarios only
|
|
659
|
+
|
|
660
|
+
**Location of the field:**
|
|
661
|
+
- Field definition: ${`${accessor}.plainFields[${pIndex}]`}
|
|
662
|
+
|
|
663
|
+
Please either change the field type to "string" or remove the GIN index.
|
|
664
664
|
`,
|
|
665
665
|
});
|
|
666
666
|
},
|
|
@@ -689,53 +689,53 @@ function validateReferences(model, accessor, dict) {
|
|
|
689
689
|
path: `${accessor}.foreignFields[${i}].relation.targetModel`,
|
|
690
690
|
table: model.name,
|
|
691
691
|
field: field.name,
|
|
692
|
-
message: utils_1.StringUtil.trim `
|
|
693
|
-
Cross-reference dependency detected between models.
|
|
694
|
-
|
|
695
|
-
**What is Cross-reference dependency?**
|
|
696
|
-
A cross-reference dependency (also known as circular dependency) occurs when two models
|
|
697
|
-
reference each other through foreign key fields. This creates a circular relationship
|
|
698
|
-
where Model A references Model B, and Model B also references Model A.
|
|
699
|
-
|
|
700
|
-
**Current situation:**
|
|
701
|
-
- ${model.name} model has a foreign key field "${field.name}" that references ${field.relation.targetModel}
|
|
702
|
-
- ${field.relation.targetModel} model also has a foreign key field that references ${model.name}
|
|
703
|
-
- Location of opposite reference: application.files[${target.fileIndex}].models[${target.modelIndex}].foreignFields[${j}].relation.targetModel
|
|
704
|
-
|
|
705
|
-
**Why is this a problem?**
|
|
706
|
-
Circular dependencies can cause issues with:
|
|
707
|
-
- Database initialization (which table to create first?)
|
|
708
|
-
- Data insertion (which record to insert first?)
|
|
709
|
-
- Cascading updates and deletes
|
|
710
|
-
- Query performance and complexity
|
|
711
|
-
|
|
712
|
-
**How to fix this:**
|
|
713
|
-
You need to remove one of the foreign key relationships. Here's how to decide:
|
|
714
|
-
|
|
715
|
-
1. **Identify the primary relationship direction**
|
|
716
|
-
- Which model is the "parent" and which is the "child"?
|
|
717
|
-
- Which relationship is essential for your business logic?
|
|
718
|
-
- Example: In User ↔ Profile, User is typically the parent
|
|
719
|
-
|
|
720
|
-
2. **Remove the redundant foreign key**
|
|
721
|
-
- Keep the foreign key in the child model pointing to the parent
|
|
722
|
-
- Remove the foreign key in the parent model pointing to the child
|
|
723
|
-
- You can still access the reverse relationship through Prisma's implicit relations
|
|
724
|
-
|
|
725
|
-
3. **Update any affected indexes**
|
|
726
|
-
- Remove indexes that include the deleted foreign key field
|
|
727
|
-
- Update composite indexes if necessary
|
|
728
|
-
|
|
729
|
-
**Example solution:**
|
|
730
|
-
If you have:
|
|
731
|
-
- User model with profileId foreign key
|
|
732
|
-
- Profile model with userId foreign key
|
|
733
|
-
|
|
734
|
-
You should:
|
|
735
|
-
- Keep userId in Profile (child references parent)
|
|
736
|
-
- Remove profileId from User
|
|
737
|
-
- Access user's profile through: user.profile (Prisma will handle this)
|
|
738
|
-
|
|
692
|
+
message: utils_1.StringUtil.trim `
|
|
693
|
+
Cross-reference dependency detected between models.
|
|
694
|
+
|
|
695
|
+
**What is Cross-reference dependency?**
|
|
696
|
+
A cross-reference dependency (also known as circular dependency) occurs when two models
|
|
697
|
+
reference each other through foreign key fields. This creates a circular relationship
|
|
698
|
+
where Model A references Model B, and Model B also references Model A.
|
|
699
|
+
|
|
700
|
+
**Current situation:**
|
|
701
|
+
- ${model.name} model has a foreign key field "${field.name}" that references ${field.relation.targetModel}
|
|
702
|
+
- ${field.relation.targetModel} model also has a foreign key field that references ${model.name}
|
|
703
|
+
- Location of opposite reference: application.files[${target.fileIndex}].models[${target.modelIndex}].foreignFields[${j}].relation.targetModel
|
|
704
|
+
|
|
705
|
+
**Why is this a problem?**
|
|
706
|
+
Circular dependencies can cause issues with:
|
|
707
|
+
- Database initialization (which table to create first?)
|
|
708
|
+
- Data insertion (which record to insert first?)
|
|
709
|
+
- Cascading updates and deletes
|
|
710
|
+
- Query performance and complexity
|
|
711
|
+
|
|
712
|
+
**How to fix this:**
|
|
713
|
+
You need to remove one of the foreign key relationships. Here's how to decide:
|
|
714
|
+
|
|
715
|
+
1. **Identify the primary relationship direction**
|
|
716
|
+
- Which model is the "parent" and which is the "child"?
|
|
717
|
+
- Which relationship is essential for your business logic?
|
|
718
|
+
- Example: In User ↔ Profile, User is typically the parent
|
|
719
|
+
|
|
720
|
+
2. **Remove the redundant foreign key**
|
|
721
|
+
- Keep the foreign key in the child model pointing to the parent
|
|
722
|
+
- Remove the foreign key in the parent model pointing to the child
|
|
723
|
+
- You can still access the reverse relationship through Prisma's implicit relations
|
|
724
|
+
|
|
725
|
+
3. **Update any affected indexes**
|
|
726
|
+
- Remove indexes that include the deleted foreign key field
|
|
727
|
+
- Update composite indexes if necessary
|
|
728
|
+
|
|
729
|
+
**Example solution:**
|
|
730
|
+
If you have:
|
|
731
|
+
- User model with profileId foreign key
|
|
732
|
+
- Profile model with userId foreign key
|
|
733
|
+
|
|
734
|
+
You should:
|
|
735
|
+
- Keep userId in Profile (child references parent)
|
|
736
|
+
- Remove profileId from User
|
|
737
|
+
- Access user's profile through: user.profile (Prisma will handle this)
|
|
738
|
+
|
|
739
739
|
Please eliminate the circular dependency and regenerate the schema.`,
|
|
740
740
|
});
|
|
741
741
|
}
|