@postxl/generator 0.45.0 → 0.47.0
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 +20 -1
- package/dist/generator.js +66 -101
- package/dist/generators/indices/emptydatabasemigration.generator.js +3 -3
- package/dist/generators/models/react.generator/lookup.generator.js +91 -10
- package/dist/generators/models/repository.generator.js +1 -5
- package/dist/lib/meta.d.ts +2 -2
- package/dist/lib/meta.js +1 -1
- package/dist/lib/schema/schema.d.ts +1 -38
- package/dist/lib/utils/error.d.ts +4 -0
- package/dist/lib/utils/error.js +11 -1
- package/dist/prisma/parse.js +79 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
1
|
# PXL Generator
|
|
2
2
|
|
|
3
|
-
A utility package that lets you move quickly and generate basic components of your app easily.
|
|
3
|
+
A utility package that lets you move quickly and generate basic components of your app easily.
|
|
4
|
+
|
|
5
|
+
#### Linking Generator to Template
|
|
6
|
+
|
|
7
|
+
To use the latest version of the generator link the local dependency using [`pnpm link`](https://pnpm.io/cli/link) command.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
# /
|
|
11
|
+
pnpm build
|
|
12
|
+
|
|
13
|
+
# /packages/manager/template/
|
|
14
|
+
pnpm link ../../generator/
|
|
15
|
+
|
|
16
|
+
# /
|
|
17
|
+
pnpm prisma generate
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
> If you've correctly linked the generator, you should see a message when running `pnpm i`.
|
|
21
|
+
|
|
22
|
+

|
package/dist/generator.js
CHANGED
|
@@ -93,7 +93,7 @@ const CONFIG_SCHEMA = zod_1.z
|
|
|
93
93
|
pathToTypes: zod_1.z.string().optional(),
|
|
94
94
|
trpcRoutesFolder: zod_1.z.string().optional(),
|
|
95
95
|
reactFolderOutput: zod_1.z.string().optional(),
|
|
96
|
-
|
|
96
|
+
prismaMigrationsFolder: zod_1.z.string().optional(),
|
|
97
97
|
randomSeed: zod_1.z
|
|
98
98
|
.string()
|
|
99
99
|
.optional()
|
|
@@ -106,31 +106,21 @@ const CONFIG_SCHEMA = zod_1.z
|
|
|
106
106
|
.transform((s) => {
|
|
107
107
|
return {
|
|
108
108
|
paths: {
|
|
109
|
-
dataLibPath: (0, types_1.toPath)(s.pathToDataLib || '
|
|
109
|
+
dataLibPath: (0, types_1.toPath)(s.pathToDataLib || './backend/libs/data/src/'),
|
|
110
110
|
cypressPath: (0, types_1.toPath)(s.pathToCypress || './e2e/cypress/'),
|
|
111
|
-
e2eLibPath: (0, types_1.toPath)(s.pathToE2ELib || './e2e/src/'),
|
|
112
|
-
importExportPath: (0, types_1.toPath)(s.pathToImportExport || 'import-export'),
|
|
113
|
-
actionsPath: (0, types_1.toPath)(s.pathToActions || 'actions'),
|
|
114
|
-
businessLogicPath: (0, types_1.toPath)(s.pathToBusinessLogic || 'business-logic'),
|
|
115
|
-
|
|
116
|
-
modelTypeDefinitionsPath: (0, types_1.toPath)(s.pathToTypes || 'types'),
|
|
117
|
-
reactFolderPath: (0, types_1.toPath)(s.reactFolderOutput || '
|
|
118
|
-
seedDataPath: (0, types_1.toPath)(s.pathToSeedData || 'seed-data'),
|
|
119
|
-
seedLibPath: (0, types_1.toPath)(s.pathToSeedLib || 'seed'),
|
|
120
|
-
trpcRoutesFolderPath: (0, types_1.toPath)(s.trpcRoutesFolder || 'trpc'),
|
|
111
|
+
e2eLibPath: (0, types_1.toPath)(s.pathToE2ELib || './backend/libs/e2e/src/'),
|
|
112
|
+
importExportPath: (0, types_1.toPath)(s.pathToImportExport || './backend/libs/import-export/src/'),
|
|
113
|
+
actionsPath: (0, types_1.toPath)(s.pathToActions || './backend/libs/actions/src/'),
|
|
114
|
+
businessLogicPath: (0, types_1.toPath)(s.pathToBusinessLogic || './backend/libs/business-logic/src/'),
|
|
115
|
+
prismaMigrationsFolderPath: (0, types_1.toPath)(s.prismaMigrationsFolder || './migrations'),
|
|
116
|
+
modelTypeDefinitionsPath: (0, types_1.toPath)(s.pathToTypes || './backend/libs/types/src/'),
|
|
117
|
+
reactFolderPath: (0, types_1.toPath)(s.reactFolderOutput || './web/src/components/'),
|
|
118
|
+
seedDataPath: (0, types_1.toPath)(s.pathToSeedData || './backend/seed-data/src/'),
|
|
119
|
+
seedLibPath: (0, types_1.toPath)(s.pathToSeedLib || './backend/libs/seed/src/'),
|
|
120
|
+
trpcRoutesFolderPath: (0, types_1.toPath)(s.trpcRoutesFolder || './backend/libs/trpc/src/routes/'),
|
|
121
121
|
},
|
|
122
122
|
randomSeed: s.randomSeed,
|
|
123
123
|
force: s.force,
|
|
124
|
-
disableGenerators: {
|
|
125
|
-
actions: s.pathToActions === undefined,
|
|
126
|
-
businessLogic: s.pathToBusinessLogic === undefined,
|
|
127
|
-
data: s.pathToDataLib === undefined,
|
|
128
|
-
importExport: s.pathToImportExport === undefined,
|
|
129
|
-
react: s.reactFolderOutput === undefined,
|
|
130
|
-
seed: s.pathToSeedLib === undefined,
|
|
131
|
-
trpc: s.trpcRoutesFolder === undefined,
|
|
132
|
-
types: s.pathToTypes === undefined,
|
|
133
|
-
},
|
|
134
124
|
userType: (0, types_1.toTypeName)(`User`),
|
|
135
125
|
};
|
|
136
126
|
});
|
|
@@ -173,100 +163,75 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
|
|
|
173
163
|
for (const model of models) {
|
|
174
164
|
const meta = (0, meta_1.getModelMetadata)({ model });
|
|
175
165
|
// Types
|
|
176
|
-
|
|
177
|
-
generated.write(`/${meta.types.filePath}.ts`, (0, types_generator_3.generateModelTypes)({ model, meta }));
|
|
178
|
-
}
|
|
166
|
+
generated.write(`/${meta.types.filePath}.ts`, (0, types_generator_3.generateModelTypes)({ model, meta }));
|
|
179
167
|
// Seed
|
|
180
|
-
|
|
181
|
-
generated.write(`/${meta.seed.filePath}.ts`, (0, seed_generator_1.generateSeedModel)({ model, itemCount: 5, meta }));
|
|
182
|
-
}
|
|
168
|
+
generated.write(`/${meta.seed.filePath}.ts`, (0, seed_generator_1.generateSeedModel)({ model, itemCount: 5, meta }));
|
|
183
169
|
// Data
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
generated.write(`/${meta.e2e.dataMockerStubFilePath}.ts`, (0, stub_generator_1.generateStub)({ model, meta }));
|
|
189
|
-
}
|
|
170
|
+
generated.write(`/${meta.data.stubFilePath}.ts`, (0, stub_generator_1.generateStub)({ model, meta }));
|
|
171
|
+
generated.write(`/${meta.data.repository.filePath}.ts`, (0, repository_generator_1.generateRepository)({ model, meta }));
|
|
172
|
+
generated.write(`/${meta.data.mockRepository.filePath}.ts`, (0, repository_generator_1.generateMockRepository)({ model, meta }));
|
|
173
|
+
generated.write(`/${meta.e2e.dataMockerStubFilePath}.ts`, (0, stub_generator_1.generateStub)({ model, meta }));
|
|
190
174
|
// Import-Export
|
|
191
|
-
|
|
192
|
-
generated.write(`/${meta.importExport.decoder.filePath}.ts`, (0, importexport_decoder_generator_1.generateModelImportExportDecoder)({ model, meta, schemaMeta: (0, meta_1.getSchemaMetadata)({ config }) }));
|
|
193
|
-
}
|
|
175
|
+
generated.write(`/${meta.importExport.decoder.filePath}.ts`, (0, importexport_decoder_generator_1.generateModelImportExportDecoder)({ model, meta, schemaMeta: (0, meta_1.getSchemaMetadata)({ config }) }));
|
|
194
176
|
// Business Logic
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
generated.write(`/${meta.businessLogic.update.serviceFilePath}.ts`, (0, businesslogic_update_generator_1.generateModelBusinessLogicUpdate)({ model, meta }));
|
|
198
|
-
}
|
|
177
|
+
generated.write(`/${meta.businessLogic.view.serviceFilePath}.ts`, (0, businesslogic_view_generator_1.generateModelBusinessLogicView)({ model, meta }));
|
|
178
|
+
generated.write(`/${meta.businessLogic.update.serviceFilePath}.ts`, (0, businesslogic_update_generator_1.generateModelBusinessLogicUpdate)({ model, meta }));
|
|
199
179
|
// Routes
|
|
200
|
-
|
|
201
|
-
generated.write(`/${meta.trpc.routerFilePath}.ts`, (0, route_generator_1.generateRoute)({ model, meta }));
|
|
202
|
-
}
|
|
180
|
+
generated.write(`/${meta.trpc.routerFilePath}.ts`, (0, route_generator_1.generateRoute)({ model, meta }));
|
|
203
181
|
// React
|
|
204
|
-
|
|
205
|
-
yield generated.copy((0, react_generator_2.generateReactComponentsForModel)({ model, meta }), meta.react.folderPath);
|
|
206
|
-
}
|
|
182
|
+
yield generated.copy((0, react_generator_2.generateReactComponentsForModel)({ model, meta }), meta.react.folderPath);
|
|
207
183
|
logger.log(`- ${model.name} processed`);
|
|
208
184
|
}
|
|
209
185
|
// Generate Enums
|
|
210
186
|
for (const enumerator of enums.values()) {
|
|
211
187
|
const meta = (0, meta_1.getEnumMetadata)({ enumerator });
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
if (!config.disableGenerators.react) {
|
|
216
|
-
yield generated.copy((0, react_generator_1.generateEnumReactComponents)({ enumerator, meta }), meta.react.folderPath);
|
|
217
|
-
}
|
|
188
|
+
generated.write(`/${meta.types.filePath}.ts`, (0, types_generator_1.generateEnumType)({ enumerator, prismaClientPath, meta }));
|
|
189
|
+
yield generated.copy((0, react_generator_1.generateEnumReactComponents)({ enumerator, meta }), meta.react.folderPath);
|
|
218
190
|
}
|
|
219
191
|
// Generate Index Files and Services
|
|
220
192
|
const meta = (0, meta_1.getSchemaMetadata)({ config });
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
if (!config.disableGenerators.importExport) {
|
|
241
|
-
generated.write(`/${meta.importExport.types.filePath}.ts`, (0, importexport_types_generator_1.generateImportExportTypes)({ models, meta }));
|
|
242
|
-
generated.write(`/${meta.importExport.exporterClass.filePath}.ts`, (0, importexport_exporter_class_generator_1.generateImportExportExporterClass)({ models, meta }));
|
|
243
|
-
generated.write(`/${meta.importExport.importService.filePath}.ts`, (0, importexport_import_service_generator_1.generateImportExportImportService)({ models, meta }));
|
|
244
|
-
generated.write(`/${meta.importExport.decoder.indexFilePath}.ts`, (0, importexport_decoder_generator_1.generateImportExportDecoderIndex)({ models, meta }));
|
|
245
|
-
generated.write(`/${meta.importExport.decoder.fullDecoderFilePath}.ts`, (0, importexport_decoder_generator_1.generateImportExportDecoder)({ models, meta }));
|
|
246
|
-
generated.write(`/${meta.importExport.converterFunctions.filePath}.ts`, (0, importexport_convert_import_functions_generator_1.generateImportExportConvertImportFunctions)({ models, meta }));
|
|
247
|
-
}
|
|
248
|
-
if (!config.disableGenerators.actions) {
|
|
249
|
-
generated.write(`/${meta.actions.dispatcherService.filePath}.ts`, (0, dispatcher_service_generator_1.generateActionsDispatcherService)({ models, meta }));
|
|
250
|
-
}
|
|
251
|
-
if (!config.disableGenerators.businessLogic) {
|
|
252
|
-
generated.write(`/${meta.businessLogic.view.indexFilePath}.ts`, (0, businesslogic_view_index_generator_1.generateBusinessLogicViewIndex)({ models, meta }));
|
|
253
|
-
generated.write(`/${meta.businessLogic.view.moduleFilePath}.ts`, (0, businesslogic_view_module_generator_1.generateBusinessLogicViewModule)({ models, meta }));
|
|
254
|
-
generated.write(`/${meta.businessLogic.view.serviceFilePath}.ts`, (0, businesslogic_view_service_generator_1.generateBusinessLogicViewService)({ models, meta }));
|
|
255
|
-
generated.write(`/${meta.businessLogic.update.indexFilePath}.ts`, (0, businesslogic_update_index_generator_1.generateBusinessLogicUpdateIndex)({ models, meta }));
|
|
256
|
-
generated.write(`/${meta.businessLogic.update.moduleFilePath}.ts`, (0, businesslogic_update_module_generator_1.generateBusinessLogicUpdateModule)({ models, meta }));
|
|
257
|
-
generated.write(`/${meta.businessLogic.update.serviceFilePath}.ts`, (0, businesslogic_update_service_generator_1.generateBusinessLogicUpdateService)({ models, meta }));
|
|
258
|
-
generated.write(`/${meta.businessLogic.update.actionTypesFilePath}.ts`, (0, businesslogic_actiontypes_generator_1.generateBusinessLogicActionTypes)({ models, meta }));
|
|
259
|
-
}
|
|
260
|
-
if (!config.disableGenerators.seed) {
|
|
261
|
-
generated.write(`/${meta.seedData.initialMigrationFilePath}.ts`, (0, seed_migration_generator_1.generateSeedMigration)({ models, meta }));
|
|
262
|
-
generated.write(`/${meta.seedData.templateExcelFilePath}`, yield (0, seed_template_generator_1.generateSeedExcelTemplate)({ models }));
|
|
263
|
-
}
|
|
264
|
-
if (!config.disableGenerators.trpc) {
|
|
265
|
-
generated.write(`/${meta.trpc.routesFilePath}.ts`, (0, route_generator_1.generateRoutesIndex)({ models, meta }));
|
|
266
|
-
}
|
|
267
|
-
if (!config.disableGenerators.types) {
|
|
268
|
-
generated.write(`/${meta.types.indexFilePath}.ts`, (0, types_generator_2.generateTypesIndex)({ models, enums, meta }));
|
|
193
|
+
// Data
|
|
194
|
+
generated.write(`/${meta.data.dataMockModuleFilePath}.ts`, (0, datamock_module_generator_1.generateDataMockModule)({ models, meta }));
|
|
195
|
+
generated.write(`/${meta.data.dataModuleFilePath}.ts`, (0, datamodule_generator_1.generateDataModule)({ models, meta }));
|
|
196
|
+
generated.write(`/${meta.data.dataService.filePath}.ts`, (0, dataservice_generator_1.generateDataService)({ models, meta }));
|
|
197
|
+
generated.write(`/${meta.data.testDataServiceFilePath}.ts`, (0, testdata_service_generator_1.generateTestDataService)({ models, meta }));
|
|
198
|
+
generated.write(`/${meta.e2e.dataMocker.filePath}.ts`, (0, datamocker_generator_1.generateDataMocker)({ models, meta }));
|
|
199
|
+
generated.write(`/${meta.e2e.selectorsFilePath}.ts`, (0, selectors_generator_1.generateSelectors)());
|
|
200
|
+
generated.write(`/${meta.e2e.dataMocker.stubIndexFilePath}.ts`, (0, stubs_generator_1.generateDataMockerStubsIndex)({ models, meta }));
|
|
201
|
+
generated.write(`/${meta.data.repository.constFilePath}.ts`, (0, repositories_generator_1.generateRepositoriesArray)({ models, meta }));
|
|
202
|
+
generated.write(`/${meta.data.repository.indexFilePath}.ts`, (0, repositories_generator_1.generateRepositoriesIndex)({ models, meta }));
|
|
203
|
+
generated.write(`/${meta.data.stubIndexFilePath}.ts`, (0, stubs_generator_1.generateStubsIndex)({ models, meta }));
|
|
204
|
+
generated.write(`/${meta.data.types.filePath}.ts`, (0, data_types_generator_1.generateDataTypes)({ models, meta }));
|
|
205
|
+
// We only generate the empty database migration if the migration folder already has an existing migration
|
|
206
|
+
// Else we would generate a migration that deletes from tables that have not yet been created in the database
|
|
207
|
+
// We include this check here as the template does not come with any migration - hence this migration should also not be generated
|
|
208
|
+
if ((0, emptydatabasemigration_generator_1.prismaMigrationExists)(meta)) {
|
|
209
|
+
generated.write((0, emptydatabasemigration_generator_1.deriveEmptyDatabaseMigrationFilePath)(meta), (0, emptydatabasemigration_generator_1.generateEmptyDatabaseStoredProcedure)({ models, meta }));
|
|
269
210
|
}
|
|
211
|
+
// Import-Export
|
|
212
|
+
generated.write(`/${meta.importExport.types.filePath}.ts`, (0, importexport_types_generator_1.generateImportExportTypes)({ models, meta }));
|
|
213
|
+
generated.write(`/${meta.importExport.exporterClass.filePath}.ts`, (0, importexport_exporter_class_generator_1.generateImportExportExporterClass)({ models, meta }));
|
|
214
|
+
generated.write(`/${meta.importExport.importService.filePath}.ts`, (0, importexport_import_service_generator_1.generateImportExportImportService)({ models, meta }));
|
|
215
|
+
generated.write(`/${meta.importExport.decoder.indexFilePath}.ts`, (0, importexport_decoder_generator_1.generateImportExportDecoderIndex)({ models, meta }));
|
|
216
|
+
generated.write(`/${meta.importExport.decoder.fullDecoderFilePath}.ts`, (0, importexport_decoder_generator_1.generateImportExportDecoder)({ models, meta }));
|
|
217
|
+
generated.write(`/${meta.importExport.converterFunctions.filePath}.ts`, (0, importexport_convert_import_functions_generator_1.generateImportExportConvertImportFunctions)({ models, meta }));
|
|
218
|
+
// Actions
|
|
219
|
+
generated.write(`/${meta.actions.dispatcherService.filePath}.ts`, (0, dispatcher_service_generator_1.generateActionsDispatcherService)({ models, meta }));
|
|
220
|
+
// Business Logic
|
|
221
|
+
generated.write(`/${meta.businessLogic.view.indexFilePath}.ts`, (0, businesslogic_view_index_generator_1.generateBusinessLogicViewIndex)({ models, meta }));
|
|
222
|
+
generated.write(`/${meta.businessLogic.view.moduleFilePath}.ts`, (0, businesslogic_view_module_generator_1.generateBusinessLogicViewModule)({ models, meta }));
|
|
223
|
+
generated.write(`/${meta.businessLogic.view.serviceFilePath}.ts`, (0, businesslogic_view_service_generator_1.generateBusinessLogicViewService)({ models, meta }));
|
|
224
|
+
generated.write(`/${meta.businessLogic.update.indexFilePath}.ts`, (0, businesslogic_update_index_generator_1.generateBusinessLogicUpdateIndex)({ models, meta }));
|
|
225
|
+
generated.write(`/${meta.businessLogic.update.moduleFilePath}.ts`, (0, businesslogic_update_module_generator_1.generateBusinessLogicUpdateModule)({ models, meta }));
|
|
226
|
+
generated.write(`/${meta.businessLogic.update.serviceFilePath}.ts`, (0, businesslogic_update_service_generator_1.generateBusinessLogicUpdateService)({ models, meta }));
|
|
227
|
+
generated.write(`/${meta.businessLogic.update.actionTypesFilePath}.ts`, (0, businesslogic_actiontypes_generator_1.generateBusinessLogicActionTypes)({ models, meta }));
|
|
228
|
+
// Seed
|
|
229
|
+
generated.write(`/${meta.seedData.initialMigrationFilePath}.ts`, (0, seed_migration_generator_1.generateSeedMigration)({ models, meta }));
|
|
230
|
+
generated.write(`/${meta.seedData.templateExcelFilePath}`, yield (0, seed_template_generator_1.generateSeedExcelTemplate)({ models }));
|
|
231
|
+
// Routes
|
|
232
|
+
generated.write(`/${meta.trpc.routesFilePath}.ts`, (0, route_generator_1.generateRoutesIndex)({ models, meta }));
|
|
233
|
+
// Types
|
|
234
|
+
generated.write(`/${meta.types.indexFilePath}.ts`, (0, types_generator_2.generateTypesIndex)({ models, enums, meta }));
|
|
270
235
|
// -------------------------------------------------------------------------
|
|
271
236
|
// Add disclaimer and format.
|
|
272
237
|
yield generated.transformUTF8Files((path, content) => `${DISCLAIMER}\n${content}`);
|
|
@@ -45,11 +45,11 @@ exports.generateEmptyDatabaseStoredProcedure = generateEmptyDatabaseStoredProced
|
|
|
45
45
|
function deriveEmptyDatabaseMigrationFilePath(meta) {
|
|
46
46
|
const firstMigration = getFirstPrismaMigration(meta);
|
|
47
47
|
if (firstMigration === undefined) {
|
|
48
|
-
throw new Error(`No Prisma migration found in ${meta.
|
|
48
|
+
throw new Error(`No Prisma migration found in ${meta.prismaMigrationsPath}! Please run "prisma migrate dev" first.`);
|
|
49
49
|
}
|
|
50
50
|
const existingTimestamp = firstMigration.split('_')[0];
|
|
51
51
|
const nextTimestamp = (Number.parseInt(existingTimestamp) + 1).toString();
|
|
52
|
-
return `/${meta.
|
|
52
|
+
return `/${meta.prismaMigrationsPath}/${nextTimestamp}_emptyDatabase/migration.sql`;
|
|
53
53
|
}
|
|
54
54
|
exports.deriveEmptyDatabaseMigrationFilePath = deriveEmptyDatabaseMigrationFilePath;
|
|
55
55
|
/**
|
|
@@ -64,7 +64,7 @@ exports.prismaMigrationExists = prismaMigrationExists;
|
|
|
64
64
|
* Returns the first migration in the migrations folder if it exists.
|
|
65
65
|
*/
|
|
66
66
|
function getFirstPrismaMigration(meta) {
|
|
67
|
-
const folder = meta.
|
|
67
|
+
const folder = meta.prismaMigrationsPath;
|
|
68
68
|
try {
|
|
69
69
|
return fs_1.default.readdirSync(folder).find((f) => fs_1.default.statSync(`${folder}/${f}`).isDirectory());
|
|
70
70
|
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateModelLookupComponents = void 0;
|
|
4
|
+
const id_collector_1 = require("../../../lib/id-collector");
|
|
4
5
|
const imports_1 = require("../../../lib/imports");
|
|
5
6
|
/**
|
|
6
7
|
* Utility generator that generates lookup components for a given model.
|
|
7
8
|
*/
|
|
8
9
|
function generateModelLookupComponents({ model, meta }) {
|
|
9
10
|
const { react: { context, components }, } = meta;
|
|
11
|
+
const selectorCollector = id_collector_1.SelectorCollector.from(meta.seed.constantName + '-formComponents');
|
|
10
12
|
const imports = imports_1.ImportsGenerator.from(meta.react.folderPath)
|
|
11
13
|
.addImport({
|
|
12
14
|
items: [context.hookFnName],
|
|
@@ -26,7 +28,7 @@ function generateModelLookupComponents({ model, meta }) {
|
|
|
26
28
|
* ${model.description}
|
|
27
29
|
*/`;
|
|
28
30
|
}
|
|
29
|
-
return `
|
|
31
|
+
return /* ts */ `
|
|
30
32
|
import React from 'react'
|
|
31
33
|
|
|
32
34
|
import { MenuSelectInput, MenuSelectField } from '@components/atoms/MenuSelect'
|
|
@@ -46,7 +48,16 @@ export const ${components.forms.selectInputName} = ({
|
|
|
46
48
|
...delegated
|
|
47
49
|
}: UnionOmit<React.ComponentPropsWithoutRef<typeof SelectInput<${typeName}>>, ${tsOmittedFields}>) => {
|
|
48
50
|
const { list, ready } = ${context.hookFnName}()
|
|
49
|
-
return <SelectInput<${typeName}>
|
|
51
|
+
return <SelectInput<${typeName}>
|
|
52
|
+
options={list}
|
|
53
|
+
${reactLabelField}
|
|
54
|
+
loading={!ready}
|
|
55
|
+
__cypress_field_selector__={
|
|
56
|
+
delegated.__cypress_field_selector__
|
|
57
|
+
?? "${selectorCollector.idFor('', { typePrefix: 'selectInput' })}"
|
|
58
|
+
}
|
|
59
|
+
{...delegated}
|
|
60
|
+
/>
|
|
50
61
|
}
|
|
51
62
|
|
|
52
63
|
${description}
|
|
@@ -54,7 +65,16 @@ export const ${components.forms.selectFieldName} = ({
|
|
|
54
65
|
...delegated
|
|
55
66
|
}: Omit<React.ComponentPropsWithoutRef<typeof SelectField<${typeName}>>, ${tsOmittedFields}>) => {
|
|
56
67
|
const { list, ready } = ${context.hookFnName}()
|
|
57
|
-
return <SelectField<${typeName}>
|
|
68
|
+
return <SelectField<${typeName}>
|
|
69
|
+
options={list}
|
|
70
|
+
${reactLabelField}
|
|
71
|
+
loading={!ready}
|
|
72
|
+
__cypress_field_selector__={
|
|
73
|
+
delegated.__cypress_field_selector__
|
|
74
|
+
?? "${selectorCollector.idFor('', { typePrefix: 'selectField' })}"
|
|
75
|
+
}
|
|
76
|
+
{...delegated}
|
|
77
|
+
/>
|
|
58
78
|
}
|
|
59
79
|
|
|
60
80
|
// Menu Select
|
|
@@ -64,7 +84,16 @@ export const ${components.forms.menuSelectInputName} = ({
|
|
|
64
84
|
...delegated
|
|
65
85
|
}: UnionOmit<React.ComponentPropsWithoutRef<typeof MenuSelectInput<${typeName}>>, ${tsOmittedFields}>) => {
|
|
66
86
|
const { list, ready } = ${context.hookFnName}()
|
|
67
|
-
return <MenuSelectInput<${typeName}>
|
|
87
|
+
return <MenuSelectInput<${typeName}>
|
|
88
|
+
options={list}
|
|
89
|
+
${reactLabelField}
|
|
90
|
+
loading={!ready}
|
|
91
|
+
__cypress_options_selector__={
|
|
92
|
+
delegated.__cypress_options_selector__
|
|
93
|
+
?? "${selectorCollector.idFor('', { typePrefix: 'menuSelectInput' })}"
|
|
94
|
+
}
|
|
95
|
+
{...delegated}
|
|
96
|
+
/>
|
|
68
97
|
}
|
|
69
98
|
|
|
70
99
|
${description}
|
|
@@ -72,7 +101,16 @@ export const ${components.forms.menuSelectFieldName} = ({
|
|
|
72
101
|
...delegated
|
|
73
102
|
}: UnionOmit<React.ComponentPropsWithoutRef<typeof MenuSelectField<${typeName}>>, ${tsOmittedFields}>) => {
|
|
74
103
|
const { list, ready } = ${context.hookFnName}()
|
|
75
|
-
return <MenuSelectField<${typeName}>
|
|
104
|
+
return <MenuSelectField<${typeName}>
|
|
105
|
+
options={list}
|
|
106
|
+
${reactLabelField}
|
|
107
|
+
loading={!ready}
|
|
108
|
+
__cypress_options_selector__={
|
|
109
|
+
delegated.__cypress_options_selector__
|
|
110
|
+
?? "${selectorCollector.idFor('', { typePrefix: 'menuSelectField' })}"
|
|
111
|
+
}
|
|
112
|
+
{...delegated}
|
|
113
|
+
/>
|
|
76
114
|
}
|
|
77
115
|
|
|
78
116
|
// Search
|
|
@@ -82,7 +120,20 @@ export const ${components.forms.searchInputName} = ({
|
|
|
82
120
|
...delegated
|
|
83
121
|
}: UnionOmit<React.ComponentPropsWithoutRef<typeof SearchInput<${typeName}>>, ${tsOmittedFields}>) => {
|
|
84
122
|
const { list, ready } = ${context.hookFnName}()
|
|
85
|
-
return <SearchInput<${typeName}>
|
|
123
|
+
return <SearchInput<${typeName}>
|
|
124
|
+
options={list}
|
|
125
|
+
${reactLabelField}
|
|
126
|
+
loading={!ready}
|
|
127
|
+
__cypress_combobox_selector__={
|
|
128
|
+
delegated.__cypress_combobox_selector__
|
|
129
|
+
?? "${selectorCollector.idFor('field', { typePrefix: 'searchInput' })}"
|
|
130
|
+
}
|
|
131
|
+
__cypress_options_selector__={
|
|
132
|
+
delegated.__cypress_options_selector__
|
|
133
|
+
?? "${selectorCollector.idFor('options', { typePrefix: 'searchInput' })}"
|
|
134
|
+
}
|
|
135
|
+
{...delegated}
|
|
136
|
+
/>
|
|
86
137
|
}
|
|
87
138
|
|
|
88
139
|
${description}
|
|
@@ -90,17 +141,38 @@ export const ${components.forms.searchFieldName} = ({
|
|
|
90
141
|
...delegated
|
|
91
142
|
}: Omit<React.ComponentPropsWithoutRef<typeof SearchField<${typeName}>>, ${tsOmittedFields}>) => {
|
|
92
143
|
const { list, ready } = ${context.hookFnName}()
|
|
93
|
-
return <SearchField<${typeName}>
|
|
144
|
+
return <SearchField<${typeName}>
|
|
145
|
+
options={list}
|
|
146
|
+
${reactLabelField}
|
|
147
|
+
loading={!ready}
|
|
148
|
+
__cypress_combobox_selector__={
|
|
149
|
+
delegated.__cypress_combobox_selector__
|
|
150
|
+
?? "${selectorCollector.idFor('field', { typePrefix: 'searchField' })}"
|
|
151
|
+
}
|
|
152
|
+
__cypress_options_selector__={
|
|
153
|
+
delegated.__cypress_options_selector__
|
|
154
|
+
?? "${selectorCollector.idFor('options', { typePrefix: 'searchField' })}"
|
|
155
|
+
}
|
|
156
|
+
{...delegated}
|
|
157
|
+
/>
|
|
94
158
|
}
|
|
95
159
|
|
|
96
160
|
// Table
|
|
97
|
-
|
|
98
161
|
${description}
|
|
99
162
|
export const ${components.forms.tableSelectInputName} = ({
|
|
100
163
|
...delegated
|
|
101
164
|
}: UnionOmit<React.ComponentPropsWithoutRef<typeof TableSelectInput<${typeName}>>, ${tsOmittedFields}>) => {
|
|
102
165
|
const { list, ready } = ${context.hookFnName}()
|
|
103
|
-
return <TableSelectInput<${typeName}>
|
|
166
|
+
return <TableSelectInput<${typeName}>
|
|
167
|
+
options={list}
|
|
168
|
+
${reactLabelField}
|
|
169
|
+
loading={!ready}
|
|
170
|
+
__cypress_input_field_selector__={
|
|
171
|
+
delegated.__cypress_input_field_selector__
|
|
172
|
+
?? "${selectorCollector.idFor('', { typePrefix: 'tableSelectInput' })}"
|
|
173
|
+
}
|
|
174
|
+
{...delegated}
|
|
175
|
+
/>
|
|
104
176
|
}
|
|
105
177
|
|
|
106
178
|
${description}
|
|
@@ -108,7 +180,16 @@ export const ${components.forms.tableSelectFieldName} = ({
|
|
|
108
180
|
...delegated
|
|
109
181
|
}: UnionOmit<React.ComponentPropsWithoutRef<typeof TableSelectField<${typeName}>>, ${tsOmittedFields}>) => {
|
|
110
182
|
const { list, ready } = ${context.hookFnName}()
|
|
111
|
-
return <TableSelectField<${typeName}>
|
|
183
|
+
return <TableSelectField<${typeName}>
|
|
184
|
+
options={list}
|
|
185
|
+
${reactLabelField}
|
|
186
|
+
loading={!ready}
|
|
187
|
+
__cypress_input_field_selector__={
|
|
188
|
+
delegated.__cypress_input_field_selector__
|
|
189
|
+
?? "${selectorCollector.idFor('', { typePrefix: 'tableSelectField' })}"
|
|
190
|
+
}
|
|
191
|
+
{...delegated}
|
|
192
|
+
/>
|
|
112
193
|
}
|
|
113
194
|
`;
|
|
114
195
|
}
|
|
@@ -785,10 +785,6 @@ function generateUserRepositorySpecificBlocks_InDatabase({ model, meta, imports,
|
|
|
785
785
|
rootUserInitializeBlock: '',
|
|
786
786
|
};
|
|
787
787
|
}
|
|
788
|
-
imports.addImport({
|
|
789
|
-
from: meta.types.importPath,
|
|
790
|
-
items: [(0, types_1.toVariableName)('UserRole')],
|
|
791
|
-
});
|
|
792
788
|
const { rootUserId, rootUserValue } = generateSharedRootUserBlocks({ model, meta, imports });
|
|
793
789
|
return {
|
|
794
790
|
rootUserNameConst: `public static ROOT_USER_ID = ${meta.types.toBrandedIdTypeFnName}(${rootUserId})`,
|
|
@@ -868,7 +864,7 @@ function generateSharedRootUserBlocks({ model, meta, imports, }) {
|
|
|
868
864
|
}
|
|
869
865
|
else if (field.kind === 'id') {
|
|
870
866
|
if (field.unbrandedTypeName === 'string') {
|
|
871
|
-
value =
|
|
867
|
+
value = 'rootId';
|
|
872
868
|
}
|
|
873
869
|
else if (field.unbrandedTypeName === 'number') {
|
|
874
870
|
value = -1;
|
package/dist/lib/meta.d.ts
CHANGED
|
@@ -635,9 +635,9 @@ export type SchemaMetaData = {
|
|
|
635
635
|
selectorsFilePath: Types.FilePath;
|
|
636
636
|
};
|
|
637
637
|
/**
|
|
638
|
-
* Path to the directory containing migrations.
|
|
638
|
+
* Path to the directory containing Prisma migrations.
|
|
639
639
|
*/
|
|
640
|
-
|
|
640
|
+
prismaMigrationsPath: Types.FilePath;
|
|
641
641
|
/**
|
|
642
642
|
* The schema configuration for reference.
|
|
643
643
|
*/
|
package/dist/lib/meta.js
CHANGED
|
@@ -251,7 +251,7 @@ function getSchemaMetadata({ config }) {
|
|
|
251
251
|
upsert: Types.toTypeName(`UpsertDTO`),
|
|
252
252
|
},
|
|
253
253
|
},
|
|
254
|
-
|
|
254
|
+
prismaMigrationsPath: Types.toPath(`${config.paths.prismaMigrationsFolderPath}`),
|
|
255
255
|
config,
|
|
256
256
|
};
|
|
257
257
|
}
|
|
@@ -7,43 +7,6 @@ import * as Types from './types';
|
|
|
7
7
|
* NOTE: This may be accessed in every model, field and enumerator.
|
|
8
8
|
*/
|
|
9
9
|
export type SchemaConfig = {
|
|
10
|
-
/**
|
|
11
|
-
* Indicates whether the generator should be ignored
|
|
12
|
-
*/
|
|
13
|
-
disableGenerators: {
|
|
14
|
-
/**
|
|
15
|
-
* If true, actions module will not be generated.
|
|
16
|
-
*/
|
|
17
|
-
actions: boolean;
|
|
18
|
-
/**
|
|
19
|
-
* If true, business logic module will not be generated.
|
|
20
|
-
*/
|
|
21
|
-
businessLogic: boolean;
|
|
22
|
-
/**
|
|
23
|
-
* If true, data module will not be generated.
|
|
24
|
-
*/
|
|
25
|
-
data: boolean;
|
|
26
|
-
/**
|
|
27
|
-
* If true, import-export module will not be generated.
|
|
28
|
-
*/
|
|
29
|
-
importExport: boolean;
|
|
30
|
-
/**
|
|
31
|
-
* If true, seed data will not be generated.
|
|
32
|
-
*/
|
|
33
|
-
seed: boolean;
|
|
34
|
-
/**
|
|
35
|
-
* If true, React components will not be generated.
|
|
36
|
-
*/
|
|
37
|
-
react: boolean;
|
|
38
|
-
/**
|
|
39
|
-
* If true, trpc routes will not be generated.
|
|
40
|
-
*/
|
|
41
|
-
trpc: boolean;
|
|
42
|
-
/**
|
|
43
|
-
* If true, type definitions for models will not be generated.
|
|
44
|
-
*/
|
|
45
|
-
types: boolean;
|
|
46
|
-
};
|
|
47
10
|
paths: {
|
|
48
11
|
/**
|
|
49
12
|
* Path to the directory containing actions.
|
|
@@ -84,7 +47,7 @@ export type SchemaConfig = {
|
|
|
84
47
|
/**
|
|
85
48
|
* Path to the directory containing Prisma migrations.
|
|
86
49
|
*/
|
|
87
|
-
|
|
50
|
+
prismaMigrationsFolderPath: Types.FilePath;
|
|
88
51
|
/**
|
|
89
52
|
* Path to the directory containing model type definitions.
|
|
90
53
|
*
|
|
@@ -3,3 +3,7 @@
|
|
|
3
3
|
* By showing the error via console.log and throwing it again, we ensure that the error message is shown.
|
|
4
4
|
*/
|
|
5
5
|
export declare function throwError(message: string): never;
|
|
6
|
+
/**
|
|
7
|
+
* Extracts the error message from an error object or any other object.
|
|
8
|
+
*/
|
|
9
|
+
export declare function extractError(error: unknown): string;
|
package/dist/lib/utils/error.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.throwError = void 0;
|
|
3
|
+
exports.extractError = exports.throwError = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Prisma generator often overwrites any error message because of some concurrency issues.
|
|
6
6
|
* By showing the error via console.log and throwing it again, we ensure that the error message is shown.
|
|
@@ -11,3 +11,13 @@ function throwError(message) {
|
|
|
11
11
|
throw new Error(m);
|
|
12
12
|
}
|
|
13
13
|
exports.throwError = throwError;
|
|
14
|
+
/**
|
|
15
|
+
* Extracts the error message from an error object or any other object.
|
|
16
|
+
*/
|
|
17
|
+
function extractError(error) {
|
|
18
|
+
if (error instanceof Error) {
|
|
19
|
+
return error.message;
|
|
20
|
+
}
|
|
21
|
+
return JSON.stringify(error);
|
|
22
|
+
}
|
|
23
|
+
exports.extractError = extractError;
|
package/dist/prisma/parse.js
CHANGED
|
@@ -37,6 +37,7 @@ const REQUIRED_MODELS = ['User', 'Config', 'File', 'Action', 'Mutation'];
|
|
|
37
37
|
*/
|
|
38
38
|
function parsePrismaSchema({ datamodel: { enums: enumsRaw, models: modelsRaw }, config, }) {
|
|
39
39
|
ensureRequiredModelsExists(modelsRaw);
|
|
40
|
+
ensureConsistency({ models: modelsRaw, enums: enumsRaw });
|
|
40
41
|
// NOTE: We preprocess models and enums so that we can populate relationships.
|
|
41
42
|
const models = modelsRaw.map((dmmfModel) => parseModelCore({ dmmfModel, config }));
|
|
42
43
|
const enums = enumsRaw.map((dmmfEnum) => parseEnum({ dmmfEnum, config }));
|
|
@@ -49,10 +50,60 @@ exports.parsePrismaSchema = parsePrismaSchema;
|
|
|
49
50
|
function ensureRequiredModelsExists(models) {
|
|
50
51
|
for (const requiredModel of REQUIRED_MODELS) {
|
|
51
52
|
if (!models.find((m) => m.name === requiredModel)) {
|
|
52
|
-
(0, error_1.throwError)(`Required model ${requiredModel} not found in schema!`);
|
|
53
|
+
(0, error_1.throwError)(`Required model ${highlight(requiredModel)} not found in schema!`);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Validates:
|
|
59
|
+
* - That there are no duplicate model names
|
|
60
|
+
* - That model names are singular
|
|
61
|
+
* - That model attributes are valid
|
|
62
|
+
* - That field attributes are valid
|
|
63
|
+
* - That enum attributes are valid
|
|
64
|
+
*/
|
|
65
|
+
function ensureConsistency({ models, enums }) {
|
|
66
|
+
const errors = [];
|
|
67
|
+
const modelNames = models.map((m) => m.name);
|
|
68
|
+
const duplicateModelName = modelNames.find((name, i) => modelNames.indexOf(name) !== i);
|
|
69
|
+
if (duplicateModelName) {
|
|
70
|
+
errors.push(`Model ${duplicateModelName} is defined more than once.`);
|
|
71
|
+
}
|
|
72
|
+
for (const model of models) {
|
|
73
|
+
if ((0, string_1.isPlural)(model.name)) {
|
|
74
|
+
errors.push(`Model ${highlight(model.name)} is plural. Please use singular names for models.`);
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
(0, attributes_1.getModelAttributes)(model);
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
errors.push(`Model ${highlight(model.name)} has invalid model attributes: ${(0, error_1.extractError)(e)}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
for (const model of models) {
|
|
84
|
+
for (const field of model.fields) {
|
|
85
|
+
try {
|
|
86
|
+
(0, attributes_1.getFieldAttributes)(field);
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
errors.push(`Model ${highlight(model.name)} has invalid attributes for field ${highlight(field.name)}:
|
|
90
|
+
${(0, error_1.extractError)(e)}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
for (const enumDef of enums) {
|
|
95
|
+
try {
|
|
96
|
+
(0, attributes_1.getEnumAttributes)(enumDef);
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
errors.push(`Enum ${highlight(enumDef.name)} has invalid attributes:
|
|
100
|
+
${(0, error_1.extractError)(e)}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (errors.length > 0) {
|
|
104
|
+
(0, error_1.throwError)(`${errors.length} ${(0, string_1.pluralize)('issue', errors.length)} detected in schema:\n * ${errors.join('\n * ')}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
56
107
|
function isModelNotIgnored(model) {
|
|
57
108
|
return model !== undefined && !model.attributes.ignore;
|
|
58
109
|
}
|
|
@@ -98,14 +149,14 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
98
149
|
continue;
|
|
99
150
|
}
|
|
100
151
|
if (dmmfField.relationFromFields.length > 1) {
|
|
101
|
-
|
|
152
|
+
(0, error_1.throwError)(`Field ${highlight(`${dmmfModel.name}.${dmmfField.relationName}`)} has more than one "from" field`);
|
|
102
153
|
}
|
|
103
154
|
const referencedModel = models.find((m) => m.sourceName === dmmfField.type);
|
|
104
155
|
if (!referencedModel) {
|
|
105
|
-
(0, error_1.throwError)(`
|
|
156
|
+
(0, error_1.throwError)(`Field ${highlight(`${dmmfModel.name}.${dmmfField.name}`)} references unknown model ${highlight(dmmfField.type)}.`);
|
|
106
157
|
}
|
|
107
158
|
if (dmmfField.relationOnDelete && dmmfField.relationOnDelete !== 'NoAction') {
|
|
108
|
-
(0, error_1.throwError)(`Investigate: "onDelete" attribute for relationship ${dmmfField.relationName} must be "NoAction": any deletes must be handled in the application layer, e.g. to update repository and search caches!`);
|
|
159
|
+
(0, error_1.throwError)(`Investigate model ${highlight(dmmfModel.name)}: "onDelete" attribute for relationship ${highlight(dmmfField.relationName)} must be "NoAction": any deletes must be handled in the application layer, e.g. to update repository and search caches!`);
|
|
109
160
|
}
|
|
110
161
|
relations[dmmfField.relationFromFields[0]] = referencedModel;
|
|
111
162
|
}
|
|
@@ -123,6 +174,7 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
123
174
|
dmmfField.kind !== 'object')
|
|
124
175
|
.map((dmmfField) => {
|
|
125
176
|
const attributes = (0, attributes_1.getFieldAttributes)(dmmfField);
|
|
177
|
+
const fieldName = highlight(`${dmmfModel.name}.${dmmfField.name}`);
|
|
126
178
|
const shared = {
|
|
127
179
|
name: Types.toFieldName((0, string_1.toCamelCase)(dmmfField.name)),
|
|
128
180
|
description: attributes.description,
|
|
@@ -137,7 +189,7 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
137
189
|
const refModel = relations[dmmfField.name];
|
|
138
190
|
const refField = relationFields[dmmfField.name];
|
|
139
191
|
if (!refField) {
|
|
140
|
-
(0, error_1.throwError)(
|
|
192
|
+
(0, error_1.throwError)(`${fieldName}: Relation field ${highlight(dmmfField.name)} not found.`);
|
|
141
193
|
}
|
|
142
194
|
return Object.assign(Object.assign({ kind: 'relation' }, shared), { relatedModelBacklinkFieldName: Types.toFieldName(refField.name), typeName: Types.toTypeName(dmmfField.type), unbrandedTypeName: getTsTypeForId(dmmfField), relationToModel: refModel });
|
|
143
195
|
}
|
|
@@ -148,7 +200,7 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
148
200
|
if (dmmfField.kind === 'scalar') {
|
|
149
201
|
let validation = undefined;
|
|
150
202
|
if (dmmfField.isList) {
|
|
151
|
-
(0, error_1.throwError)(
|
|
203
|
+
(0, error_1.throwError)(`${fieldName}: Array fields with scalars (e.g. String[]) aren't supported! Use a relation instead. `);
|
|
152
204
|
}
|
|
153
205
|
if (dmmfField.type === 'Int') {
|
|
154
206
|
validation = { type: 'int' };
|
|
@@ -161,11 +213,11 @@ function parseModel({ dmmfModel, enums, models, config, }) {
|
|
|
161
213
|
if (dmmfField.kind === 'enum') {
|
|
162
214
|
const fieldEnumDef = enums.find((e) => e.sourceName === dmmfField.type);
|
|
163
215
|
if (!fieldEnumDef) {
|
|
164
|
-
(0, error_1.throwError)(
|
|
216
|
+
(0, error_1.throwError)(`${fieldName}: Field references unknown enum ${highlight(dmmfField.type)}.`);
|
|
165
217
|
}
|
|
166
218
|
return Object.assign(Object.assign({ kind: 'enum' }, shared), { typeName: getTsTypeForEnum(dmmfField), enumerator: fieldEnumDef });
|
|
167
219
|
}
|
|
168
|
-
(0, error_1.throwError)(
|
|
220
|
+
(0, error_1.throwError)(`${fieldName} is not scalar, enum nor relation.`);
|
|
169
221
|
})
|
|
170
222
|
.filter((field) => !isFieldIgnored({ field }));
|
|
171
223
|
const { idField, defaultField, nameField, createdAtField, updatedAtField } = validateFields({ fields, model: core });
|
|
@@ -188,6 +240,7 @@ function validateFields({ fields, model: { name } }) {
|
|
|
188
240
|
let nameField = undefined;
|
|
189
241
|
let defaultField = undefined;
|
|
190
242
|
for (const field of fields) {
|
|
243
|
+
const fieldName = highlight(`${name}.${field.name}`);
|
|
191
244
|
switch (field.kind) {
|
|
192
245
|
case 'scalar':
|
|
193
246
|
if (field.name === 'name') {
|
|
@@ -195,20 +248,20 @@ function validateFields({ fields, model: { name } }) {
|
|
|
195
248
|
}
|
|
196
249
|
if (field.attributes.isCreatedAt) {
|
|
197
250
|
if (createdAtField) {
|
|
198
|
-
|
|
251
|
+
(0, error_1.throwError)(`${fieldName} has multiple createdAt fields`);
|
|
199
252
|
}
|
|
200
253
|
createdAtField = field;
|
|
201
254
|
}
|
|
202
255
|
if (field.attributes.isUpdatedAt) {
|
|
203
256
|
if (updatedAtField) {
|
|
204
|
-
|
|
257
|
+
(0, error_1.throwError)(`${fieldName} has multiple updatedAt fields`);
|
|
205
258
|
}
|
|
206
259
|
updatedAtField = field;
|
|
207
260
|
}
|
|
208
261
|
break;
|
|
209
262
|
case 'id':
|
|
210
263
|
if (idField) {
|
|
211
|
-
|
|
264
|
+
(0, error_1.throwError)(`${fieldName} has multiple id fields`);
|
|
212
265
|
}
|
|
213
266
|
idField = field;
|
|
214
267
|
break;
|
|
@@ -220,20 +273,20 @@ function validateFields({ fields, model: { name } }) {
|
|
|
220
273
|
//handle default case
|
|
221
274
|
if (field.attributes.isDefaultField && field.kind === 'scalar') {
|
|
222
275
|
if (defaultField !== undefined) {
|
|
223
|
-
|
|
276
|
+
(0, error_1.throwError)(`${fieldName} has multiple default fields`);
|
|
224
277
|
}
|
|
225
278
|
defaultField = field;
|
|
226
279
|
}
|
|
227
280
|
//handle name field
|
|
228
281
|
if (field.attributes.isLabel) {
|
|
229
282
|
if (labelField !== undefined) {
|
|
230
|
-
|
|
283
|
+
(0, error_1.throwError)(`${fieldName} has multiple name fields`);
|
|
231
284
|
}
|
|
232
285
|
labelField = field;
|
|
233
286
|
}
|
|
234
287
|
}
|
|
235
288
|
if (!idField) {
|
|
236
|
-
|
|
289
|
+
(0, error_1.throwError)(`Model ${highlight(name)} does not have an id field`);
|
|
237
290
|
}
|
|
238
291
|
return { idField, defaultField, nameField: (_a = labelField !== null && labelField !== void 0 ? labelField : nameField) !== null && _a !== void 0 ? _a : idField, createdAtField, updatedAtField };
|
|
239
292
|
}
|
|
@@ -309,12 +362,12 @@ function getTsTypeForScalar(field) {
|
|
|
309
362
|
return Types.toTypeName('number');
|
|
310
363
|
case 'Json':
|
|
311
364
|
case 'Bytes':
|
|
312
|
-
(0, error_1.throwError)(
|
|
365
|
+
(0, error_1.throwError)(`Field ${highlight(field.name)}: Type ${field.type} Not implemented yet`);
|
|
313
366
|
// While TypeScript understands that throwError never returns, eslint doesn't and complains.
|
|
314
367
|
// Hence we ignore the fallthrough error.
|
|
315
368
|
// eslint-disable-next-line no-fallthrough
|
|
316
369
|
default:
|
|
317
|
-
(0, error_1.throwError)(`Investigate: 'default' case in getTsTypeForScalar for field ${field.name} of type ${field.type}`);
|
|
370
|
+
(0, error_1.throwError)(`Investigate: 'default' case in getTsTypeForScalar for field ${highlight(field.name)} of type ${field.type}`);
|
|
318
371
|
}
|
|
319
372
|
}
|
|
320
373
|
/**
|
|
@@ -332,7 +385,7 @@ function getTsTypeForId(field) {
|
|
|
332
385
|
case 'Int':
|
|
333
386
|
return Types.toTypeName('number');
|
|
334
387
|
default:
|
|
335
|
-
(0, error_1.throwError)(`The id field ${field.name}
|
|
388
|
+
(0, error_1.throwError)(`The id field ${highlight(field.name)} is of type ${field.type} - but only BigInt, Boolean, Decimal, Float, Int and String are supported for Ids.`);
|
|
336
389
|
}
|
|
337
390
|
}
|
|
338
391
|
/**
|
|
@@ -347,9 +400,17 @@ function getTsTypeForEnum(field) {
|
|
|
347
400
|
case 'Decimal':
|
|
348
401
|
case 'Float':
|
|
349
402
|
case 'Int':
|
|
350
|
-
(0, error_1.throwError)(`The enum field ${field.name}
|
|
403
|
+
(0, error_1.throwError)(`The enum field ${highlight(field.name)} is of type ${field.type} - but only String fields are supported for enums so far.`);
|
|
351
404
|
break;
|
|
352
405
|
default:
|
|
353
406
|
return Types.toTypeName(field.type);
|
|
354
407
|
}
|
|
355
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* Highlights a string cyan
|
|
411
|
+
*
|
|
412
|
+
* NOTE: We would normally use `chalk.cyan` here, but this causes an error in the generator, so we use this workaround.
|
|
413
|
+
*/
|
|
414
|
+
function highlight(str) {
|
|
415
|
+
return `\u001B[36m${str}\u001B[39m`;
|
|
416
|
+
}
|