@postxl/generator 0.13.0 → 0.14.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/dist/generator.js +4 -0
- package/dist/generators/indices/datamockmodule.generator.js +1 -1
- package/dist/generators/indices/seed-template-decoder.generator.d.ts +9 -0
- package/dist/generators/indices/seed-template-decoder.generator.js +116 -0
- package/dist/generators/indices/seed-template.generator.d.ts +9 -0
- package/dist/generators/indices/seed-template.generator.js +80 -0
- package/dist/generators/models/react.generator/library.generator.js +5 -2
- package/dist/generators/models/react.generator/modals.generator.js +10 -5
- package/dist/generators/models/repository.generator.js +20 -13
- package/dist/generators/models/seed.generator.js +48 -27
- package/dist/generators/models/stub.generator.js +10 -5
- package/dist/generators/models/types.generator.js +2 -1
- package/dist/lib/attributes.d.ts +1 -1
- package/dist/lib/imports.d.ts +1 -1
- package/dist/lib/meta.d.ts +49 -13
- package/dist/lib/meta.js +13 -1
- package/dist/lib/schema/types.d.ts +2 -2
- package/dist/lib/utils/file.js +2 -0
- package/dist/lib/utils/logger.d.ts +5 -5
- package/dist/lib/utils/string.d.ts +5 -0
- package/dist/lib/utils/string.js +10 -2
- package/dist/prisma/attributes.js +20 -9
- package/dist/prisma/parse.js +2 -0
- package/package.json +3 -2
package/dist/generator.js
CHANGED
|
@@ -61,6 +61,8 @@ const meta_1 = require("./lib/meta");
|
|
|
61
61
|
const types_1 = require("./lib/schema/types");
|
|
62
62
|
const client_path_1 = require("./prisma/client-path");
|
|
63
63
|
const parse_1 = require("./prisma/parse");
|
|
64
|
+
const seed_template_decoder_generator_1 = require("./generators/indices/seed-template-decoder.generator");
|
|
65
|
+
const seed_template_generator_1 = require("./generators/indices/seed-template.generator");
|
|
64
66
|
const CONFIG_SCHEMA = zod_1.z
|
|
65
67
|
.object({
|
|
66
68
|
project: zod_1.z.string(),
|
|
@@ -188,6 +190,8 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
|
|
|
188
190
|
}
|
|
189
191
|
if (!config.disableGenerators.seed) {
|
|
190
192
|
generated.write(`/${meta.seed.indexFilePath}.ts`, (0, seed_generator_1.generateSeedIndex)({ models, meta }));
|
|
193
|
+
generated.write(`/${meta.seed.templateExcelFilePath}`, yield (0, seed_template_generator_1.generateSeedExcelTemplate)({ models }));
|
|
194
|
+
generated.write(`/${meta.seed.templateDecoderFilePath}.ts`, (0, seed_template_decoder_generator_1.generateSeedTemplateDecoder)({ models, meta }));
|
|
191
195
|
}
|
|
192
196
|
if (!config.disableGenerators.trpc) {
|
|
193
197
|
generated.write(`/${meta.trpc.routesFilePath}.ts`, (0, route_generator_1.generateRoutesIndex)({ models, meta }));
|
|
@@ -51,7 +51,7 @@ function generateDataMockModule({ models, meta }) {
|
|
|
51
51
|
imports.addImport({ items: [meta.data.mockRepositoryClassName], from: meta.data.mockRepoFilePath });
|
|
52
52
|
}
|
|
53
53
|
const providers = mm
|
|
54
|
-
.map(({ meta
|
|
54
|
+
.map(({ meta }) => `{
|
|
55
55
|
provide: ${meta.data.repositoryClassName},
|
|
56
56
|
useFactory: async () => {
|
|
57
57
|
const repository = new ${meta.data.mockRepositoryClassName}()
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SchemaMetaData } from '../../lib/meta';
|
|
2
|
+
import { Model } from '../../lib/schema/schema';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a decoder for the Seed Excel template
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateSeedTemplateDecoder({ models, meta }: {
|
|
7
|
+
models: Model[];
|
|
8
|
+
meta: SchemaMetaData;
|
|
9
|
+
}): string;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateSeedTemplateDecoder = void 0;
|
|
4
|
+
const imports_1 = require("../../lib/imports");
|
|
5
|
+
const meta_1 = require("../../lib/meta");
|
|
6
|
+
const types_1 = require("../../lib/types");
|
|
7
|
+
/**
|
|
8
|
+
* Creates a decoder for the Seed Excel template
|
|
9
|
+
*/
|
|
10
|
+
function generateSeedTemplateDecoder({ models, meta }) {
|
|
11
|
+
const imports = imports_1.ImportsGenerator.from(meta.seed.templateDecoderFilePath);
|
|
12
|
+
const decoders = [];
|
|
13
|
+
const tableDecoders = [];
|
|
14
|
+
const renameTransforms = [];
|
|
15
|
+
for (const model of [...models].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
16
|
+
const modelMeta = (0, meta_1.getModelMetadata)({ model });
|
|
17
|
+
decoders.push(generateTableDecoder({ model, meta: modelMeta, imports }));
|
|
18
|
+
tableDecoders.push(`${modelMeta.seed.excel.tableName}: z.array(${modelMeta.seed.decoder.schemaName})`);
|
|
19
|
+
renameTransforms.push(`${modelMeta.seed.decoder.dataName}: item['${modelMeta.seed.excel.tableName}']`);
|
|
20
|
+
}
|
|
21
|
+
return `
|
|
22
|
+
import * as z from 'zod'
|
|
23
|
+
import { excelStringDecoder, excelStringNullableDecoder, excelBooleanDecoder, excelDateNullableDecoder, excelDateDecoder } from '@pxl/common'
|
|
24
|
+
|
|
25
|
+
${imports.generate()}
|
|
26
|
+
|
|
27
|
+
${decoders.join('\n')}
|
|
28
|
+
|
|
29
|
+
export const seedTemplateDecoder = z
|
|
30
|
+
.object({${tableDecoders.join(',\n')}})
|
|
31
|
+
.transform((item) => ({${renameTransforms.join(',\n')}}))
|
|
32
|
+
`;
|
|
33
|
+
}
|
|
34
|
+
exports.generateSeedTemplateDecoder = generateSeedTemplateDecoder;
|
|
35
|
+
function generateTableDecoder({ model, meta, imports, }) {
|
|
36
|
+
const fieldDecoders = [];
|
|
37
|
+
const renameTransforms = [];
|
|
38
|
+
for (const field of model.fields) {
|
|
39
|
+
const fieldMeta = (0, meta_1.getFieldMetadata)({ field });
|
|
40
|
+
renameTransforms.push(`${field.name}: item['${fieldMeta.excelColumnName}']`);
|
|
41
|
+
switch (field.kind) {
|
|
42
|
+
case 'id': {
|
|
43
|
+
imports.addImport({
|
|
44
|
+
items: [meta.types.toBrandedIdTypeFnName],
|
|
45
|
+
from: meta.types.filePath,
|
|
46
|
+
});
|
|
47
|
+
fieldDecoders.push(`${fieldMeta.excelColumnName}: ${toExcelDecoder({
|
|
48
|
+
typeName: field.unbrandedTypeName,
|
|
49
|
+
nullable: false,
|
|
50
|
+
})}.transform((id: ${field.unbrandedTypeName}) => ${meta.types.toBrandedIdTypeFnName}(id))`);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case 'scalar': {
|
|
54
|
+
fieldDecoders.push(`${fieldMeta.excelColumnName}: ${toExcelDecoder({
|
|
55
|
+
typeName: field.typeName,
|
|
56
|
+
nullable: !field.isRequired,
|
|
57
|
+
})}`);
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
case 'relation': {
|
|
61
|
+
const refModel = field.relationToModel;
|
|
62
|
+
const refMeta = (0, meta_1.getModelMetadata)({ model: refModel });
|
|
63
|
+
imports.addImport({
|
|
64
|
+
items: [refMeta.types.toBrandedIdTypeFnName],
|
|
65
|
+
from: refMeta.types.filePath,
|
|
66
|
+
});
|
|
67
|
+
fieldDecoders.push(`${fieldMeta.excelColumnName}: ${toExcelDecoder({
|
|
68
|
+
typeName: field.unbrandedTypeName,
|
|
69
|
+
nullable: !field.isRequired,
|
|
70
|
+
})}.transform((id: ${field.unbrandedTypeName}${field.isRequired ? '' : '| null'}) => ${field.isRequired ? '' : ' id === null ? null : '}${refMeta.types.toBrandedIdTypeFnName}(id))`);
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case 'enum': {
|
|
74
|
+
const refEnumMeta = (0, meta_1.getEnumMetadata)({ enumerator: field.enumerator });
|
|
75
|
+
imports.addImport({
|
|
76
|
+
items: [field.enumerator.typeName],
|
|
77
|
+
from: refEnumMeta.types.filePath,
|
|
78
|
+
});
|
|
79
|
+
fieldDecoders.push(`${fieldMeta.excelColumnName}: z.enum([${field.enumerator.values.map((v) => `'${v}'`).join(', ')}])${field.isRequired ? '' : '.nullable()'}`);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
default: {
|
|
83
|
+
throw new types_1.ExhaustiveSwitchCheck(field);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return `
|
|
88
|
+
/**
|
|
89
|
+
* The schema for the ${model.name} table
|
|
90
|
+
*/
|
|
91
|
+
const ${meta.seed.decoder.schemaName} = z
|
|
92
|
+
.object({${fieldDecoders.join(',\n')}})
|
|
93
|
+
.transform((item) => ({${renameTransforms.join(',\n')}}))
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The type of the ${model.name} table
|
|
97
|
+
*/
|
|
98
|
+
export type ${meta.seed.decoder.decoderTypeName} = z.infer<typeof ${meta.seed.decoder.schemaName}>
|
|
99
|
+
|
|
100
|
+
export const ${meta.seed.decoder.decoderName} = z.array(${meta.seed.decoder.schemaName})
|
|
101
|
+
`;
|
|
102
|
+
}
|
|
103
|
+
function toExcelDecoder({ typeName, nullable }) {
|
|
104
|
+
switch (typeName) {
|
|
105
|
+
case 'string':
|
|
106
|
+
return nullable ? 'excelStringNullableDecoder' : 'excelStringDecoder';
|
|
107
|
+
case 'boolean':
|
|
108
|
+
return 'excelBooleanDecoder';
|
|
109
|
+
case 'number':
|
|
110
|
+
return `z.number()${nullable ? '.nullable()' : ''}`;
|
|
111
|
+
case 'Date':
|
|
112
|
+
return nullable ? 'excelDateNullableDecoder' : 'excelDateDecoder';
|
|
113
|
+
default:
|
|
114
|
+
throw new Error('Unknown type');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Model } from '../../lib/schema/schema';
|
|
3
|
+
/**
|
|
4
|
+
* Creates an Excel template file that can be used to manage Seed data.
|
|
5
|
+
* The template file contains a sheet for each model, with the column for each field.
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateSeedExcelTemplate({ models }: {
|
|
8
|
+
models: Model[];
|
|
9
|
+
}): Promise<Buffer>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.generateSeedExcelTemplate = void 0;
|
|
36
|
+
const Excel = __importStar(require("exceljs"));
|
|
37
|
+
const meta_1 = require("../../lib/meta");
|
|
38
|
+
/**
|
|
39
|
+
* Creates an Excel template file that can be used to manage Seed data.
|
|
40
|
+
* The template file contains a sheet for each model, with the column for each field.
|
|
41
|
+
*/
|
|
42
|
+
function generateSeedExcelTemplate({ models }) {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
const wb = initializeWorkbook();
|
|
45
|
+
for (const model of [...models].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
46
|
+
const meta = (0, meta_1.getModelMetadata)({ model });
|
|
47
|
+
addModel({ model, meta, wb });
|
|
48
|
+
}
|
|
49
|
+
const buffer = Buffer.from(yield wb.xlsx.writeBuffer());
|
|
50
|
+
return buffer;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
exports.generateSeedExcelTemplate = generateSeedExcelTemplate;
|
|
54
|
+
function initializeWorkbook() {
|
|
55
|
+
const wb = new Excel.Workbook();
|
|
56
|
+
wb.creator = 'XLPort';
|
|
57
|
+
wb.lastModifiedBy = 'XLPort';
|
|
58
|
+
wb.created = new Date();
|
|
59
|
+
wb.modified = new Date();
|
|
60
|
+
return wb;
|
|
61
|
+
}
|
|
62
|
+
function addModel({ model, meta, wb }) {
|
|
63
|
+
const ws = wb.addWorksheet(model.name);
|
|
64
|
+
const table = ws.addTable({
|
|
65
|
+
name: meta.seed.excel.tableName,
|
|
66
|
+
ref: 'A1',
|
|
67
|
+
headerRow: true,
|
|
68
|
+
totalsRow: false,
|
|
69
|
+
style: {
|
|
70
|
+
theme: 'TableStyleMedium2',
|
|
71
|
+
showRowStripes: true,
|
|
72
|
+
},
|
|
73
|
+
columns: model.fields.map((field) => ({
|
|
74
|
+
name: (0, meta_1.getFieldMetadata)({ field }).excelColumnName,
|
|
75
|
+
})),
|
|
76
|
+
rows: [],
|
|
77
|
+
});
|
|
78
|
+
table.addRow(model.fields.map(() => null));
|
|
79
|
+
table.commit();
|
|
80
|
+
}
|
|
@@ -56,13 +56,14 @@ function generateModelLibraryComponents({ model, meta }) {
|
|
|
56
56
|
/**
|
|
57
57
|
* Show a single ${model.name} entry.
|
|
58
58
|
*/
|
|
59
|
-
export const ${components.cardComponentName} =
|
|
59
|
+
export const ${components.cardComponentName} = React.forwardRef<HTMLLIElement, { item: ${model.typeName} }>(({ item }, forwardedRef) => {
|
|
60
60
|
const [isEditModalOpen, setIsEditModalOpen] = useState(false)
|
|
61
61
|
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false)
|
|
62
62
|
|
|
63
63
|
return (
|
|
64
64
|
<>
|
|
65
65
|
<Card
|
|
66
|
+
ref={forwardedRef}
|
|
66
67
|
title={item.name}
|
|
67
68
|
actions={[
|
|
68
69
|
{
|
|
@@ -96,7 +97,9 @@ function generateModelLibraryComponents({ model, meta }) {
|
|
|
96
97
|
/>
|
|
97
98
|
</>
|
|
98
99
|
)
|
|
99
|
-
}
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
${components.cardComponentName}.displayName = '${components.cardComponentName}'
|
|
100
103
|
`;
|
|
101
104
|
}
|
|
102
105
|
exports.generateModelLibraryComponents = generateModelLibraryComponents;
|
|
@@ -391,7 +391,7 @@ function getFormFieldComponents({ model }) {
|
|
|
391
391
|
case 'scalar': {
|
|
392
392
|
// Each scalar field has a different generic component based on the provided type.
|
|
393
393
|
scalar: switch (field.typeName) {
|
|
394
|
-
case 'string':
|
|
394
|
+
case 'string': {
|
|
395
395
|
form.append(`
|
|
396
396
|
<div>
|
|
397
397
|
<Label>${label}</Label>
|
|
@@ -399,7 +399,8 @@ function getFormFieldComponents({ model }) {
|
|
|
399
399
|
</div>
|
|
400
400
|
`);
|
|
401
401
|
break scalar;
|
|
402
|
-
|
|
402
|
+
}
|
|
403
|
+
case 'number': {
|
|
403
404
|
let decimals = 0;
|
|
404
405
|
if (((_a = field.validation) === null || _a === void 0 ? void 0 : _a.type) === 'float') {
|
|
405
406
|
decimals = 2;
|
|
@@ -411,7 +412,8 @@ function getFormFieldComponents({ model }) {
|
|
|
411
412
|
</div>
|
|
412
413
|
`);
|
|
413
414
|
break scalar;
|
|
414
|
-
|
|
415
|
+
}
|
|
416
|
+
case 'boolean': {
|
|
415
417
|
form.append(`
|
|
416
418
|
<div>
|
|
417
419
|
<Label>Is ${label}</Label>
|
|
@@ -419,12 +421,15 @@ function getFormFieldComponents({ model }) {
|
|
|
419
421
|
</div>
|
|
420
422
|
`);
|
|
421
423
|
break scalar;
|
|
422
|
-
|
|
424
|
+
}
|
|
425
|
+
case 'Date': {
|
|
423
426
|
form.append(`{/* Skipped date field ${field.name}. */}`);
|
|
424
427
|
break scalar;
|
|
425
|
-
|
|
428
|
+
}
|
|
429
|
+
default: {
|
|
426
430
|
console.warn(`Unknown scalar type ${field.typeName} for field ${model.name}.${field.name}.`);
|
|
427
431
|
break scalar;
|
|
432
|
+
}
|
|
428
433
|
}
|
|
429
434
|
break;
|
|
430
435
|
}
|
|
@@ -41,14 +41,16 @@ function generateRepository({ model, meta }) {
|
|
|
41
41
|
};
|
|
42
42
|
};
|
|
43
43
|
const indexes = model.attributes.index ? [getIndexDefinition(model.attributes.index)] : [];
|
|
44
|
-
const defaultValueInitFn =
|
|
44
|
+
const defaultValueInitFn = model.defaultField
|
|
45
|
+
? `
|
|
45
46
|
if (item.${(_a = model.defaultField) === null || _a === void 0 ? void 0 : _a.name}) {
|
|
46
47
|
if (this.defaultValue) {
|
|
47
48
|
console.warn(\`More than one default ${meta.userFriendlyName} found! \${this.defaultValue.id} and \${item.id}\`)
|
|
48
49
|
}
|
|
49
50
|
this.defaultValue = item
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
+
`
|
|
53
|
+
: '';
|
|
52
54
|
const defaultValueInitCheckFn = `
|
|
53
55
|
if (!this.db.isCLI && !this.defaultValue) {
|
|
54
56
|
throw new Error('No default ${meta.userFriendlyName} found!')
|
|
@@ -405,17 +407,22 @@ export class ${meta.data.repositoryClassName} implements Repository<
|
|
|
405
407
|
}
|
|
406
408
|
`)
|
|
407
409
|
.join('\n')}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
410
|
+
|
|
411
|
+
${maxLengthStringFields
|
|
412
|
+
.map((f) => `
|
|
413
|
+
/**
|
|
414
|
+
* Utility function that ensures that the ${f.name} field has a max length of ${f.attributes.maxLength}
|
|
415
|
+
*/
|
|
416
|
+
private ${getEnsureMaxLengthFnName(f)}(item: { ${f.name}?: string }) {
|
|
417
|
+
if (!item.${f.name}) {
|
|
418
|
+
return
|
|
419
|
+
}
|
|
420
|
+
if (item.${f.name}.length <= ${f.attributes.maxLength}) {
|
|
421
|
+
return
|
|
422
|
+
}
|
|
423
|
+
item.${f.name} = item.${f.name}.substring(0, ${f.attributes.maxLength - 4}) + \`...\`
|
|
424
|
+
}`)
|
|
425
|
+
.join('\n')}
|
|
419
426
|
|
|
420
427
|
${uniqueStringFields
|
|
421
428
|
.map((f) => {
|
|
@@ -95,39 +95,57 @@ function generateFieldData({ field, model, index, exampleMode, }) {
|
|
|
95
95
|
throw new types_1.ExhaustiveSwitchCheck(field);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
-
function generateFieldDataId({ field,
|
|
98
|
+
function generateFieldDataId({ field, index }) {
|
|
99
99
|
const idModelMeta = (0, meta_1.getModelMetadata)({ model: field.model });
|
|
100
100
|
return `${idModelMeta.types.toBrandedIdTypeFnName}(${field.unbrandedTypeName === 'string' ? `'${index}'` : index})`;
|
|
101
101
|
}
|
|
102
|
-
function quoteSingleQuote(str) {
|
|
103
|
-
return str !== null ? str.replace(/'/g, "\\'") : null;
|
|
104
|
-
}
|
|
105
102
|
function generateFieldDataScalar({ field, model, index, exampleMode, }) {
|
|
106
103
|
const { hasExample, example } = getFieldExample({ field, model, index, exampleMode });
|
|
107
104
|
switch (field.typeName) {
|
|
108
|
-
case 'string':
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
case 'string': {
|
|
106
|
+
if (hasExample) {
|
|
107
|
+
return `${example}`;
|
|
108
|
+
}
|
|
109
|
+
const result = generateFieldDataString({ field, model, index });
|
|
110
|
+
if (result === null) {
|
|
111
111
|
return 'null';
|
|
112
|
-
|
|
112
|
+
}
|
|
113
|
+
if (result === undefined) {
|
|
113
114
|
return 'undefined';
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
case '
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
115
|
+
}
|
|
116
|
+
return `'${result.replace(/'/g, "\\'")}'`;
|
|
117
|
+
}
|
|
118
|
+
case 'number': {
|
|
119
|
+
if (hasExample) {
|
|
120
|
+
return `${example}`;
|
|
121
|
+
}
|
|
122
|
+
return generateFieldDataNumber();
|
|
123
|
+
}
|
|
124
|
+
case 'boolean': {
|
|
125
|
+
if (hasExample) {
|
|
126
|
+
return `${example}`;
|
|
127
|
+
}
|
|
128
|
+
return generateFieldDataBoolean();
|
|
129
|
+
}
|
|
130
|
+
case 'Date': {
|
|
131
|
+
if (hasExample) {
|
|
132
|
+
// TODO: Maybe we should parse the date example to correct format?
|
|
133
|
+
return `${example}`;
|
|
134
|
+
}
|
|
135
|
+
return generateFieldDataDate();
|
|
136
|
+
}
|
|
137
|
+
default: {
|
|
122
138
|
console.warn(`Unknown scalar type: ${field.typeName}`);
|
|
123
139
|
return '';
|
|
140
|
+
}
|
|
124
141
|
}
|
|
125
142
|
}
|
|
126
|
-
function getFieldExample({ field,
|
|
127
|
-
if (exampleMode.mode === 'NoExamples')
|
|
128
|
-
return { hasExample: false
|
|
143
|
+
function getFieldExample({ field, index, exampleMode, }) {
|
|
144
|
+
if (exampleMode.mode === 'NoExamples') {
|
|
145
|
+
return { hasExample: false };
|
|
146
|
+
}
|
|
129
147
|
if (!field.attributes.examples || field.attributes.examples.length === 0) {
|
|
130
|
-
return { hasExample: false
|
|
148
|
+
return { hasExample: false };
|
|
131
149
|
}
|
|
132
150
|
switch (exampleMode.mode) {
|
|
133
151
|
case 'Permutations': {
|
|
@@ -138,30 +156,33 @@ function getFieldExample({ field, model, index, exampleMode, }) {
|
|
|
138
156
|
const example = field.attributes.examples[(index - 1) % field.attributes.examples.length];
|
|
139
157
|
return { hasExample: true, example };
|
|
140
158
|
}
|
|
141
|
-
default:
|
|
159
|
+
default: {
|
|
142
160
|
throw new types_1.ExhaustiveSwitchCheck(exampleMode);
|
|
161
|
+
}
|
|
143
162
|
}
|
|
144
163
|
}
|
|
145
164
|
function generateFieldDataString({ field, model, index }) {
|
|
146
|
-
if (field.name === 'name')
|
|
165
|
+
if (field.name === 'name') {
|
|
147
166
|
return `${(0, string_1.toPascalCase)(model.name)} ${index}`;
|
|
148
|
-
|
|
167
|
+
}
|
|
168
|
+
if (field.name === 'email') {
|
|
149
169
|
return faker_1.faker.internet.email();
|
|
170
|
+
}
|
|
150
171
|
return faker_1.faker.lorem.words(3);
|
|
151
172
|
}
|
|
152
|
-
function generateFieldDataNumber(
|
|
173
|
+
function generateFieldDataNumber() {
|
|
153
174
|
return faker_1.faker.datatype.float({ precision: 0.1, min: 0, max: 1 }).toString();
|
|
154
175
|
}
|
|
155
|
-
function generateFieldDataBoolean(
|
|
176
|
+
function generateFieldDataBoolean() {
|
|
156
177
|
return faker_1.faker.datatype.boolean().toString();
|
|
157
178
|
}
|
|
158
|
-
function generateFieldDataDate(
|
|
179
|
+
function generateFieldDataDate() {
|
|
159
180
|
const d = faker_1.faker.date.past(3, '2023-04-01T00:00:00.000Z');
|
|
160
181
|
//set time to midnight UTC
|
|
161
182
|
d.setUTCHours(0, 0, 0, 0);
|
|
162
183
|
return `new Date('${d.toISOString()}')`;
|
|
163
184
|
}
|
|
164
|
-
function generateFieldDataRelation({ field,
|
|
185
|
+
function generateFieldDataRelation({ field, itemCount, }) {
|
|
165
186
|
const referenceId = faker_1.faker.datatype.number({ min: 1, max: itemCount });
|
|
166
187
|
const refModelMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
|
|
167
188
|
const brandingFn = refModelMeta.types.toBrandedIdTypeFnName;
|
|
@@ -53,18 +53,23 @@ function getAssigmentStatementModel({ fields }) {
|
|
|
53
53
|
return `${f.name}: null`;
|
|
54
54
|
}
|
|
55
55
|
switch (f.kind) {
|
|
56
|
-
case 'scalar':
|
|
56
|
+
case 'scalar': {
|
|
57
57
|
return `${f.name}: ${(0, fields_1.getDefaultValueForType)(f.typeName)}`;
|
|
58
|
-
|
|
58
|
+
}
|
|
59
|
+
case 'id': {
|
|
59
60
|
const idRefMeta = (0, meta_1.getModelMetadata)({ model: f.model });
|
|
60
61
|
return `${f.name}: ${idRefMeta.types.toBrandedIdTypeFnName}(${(0, fields_1.getDefaultValueForType)(f.unbrandedTypeName)})`;
|
|
61
|
-
|
|
62
|
+
}
|
|
63
|
+
case 'relation': {
|
|
62
64
|
const refModelMeta = (0, meta_1.getModelMetadata)({ model: f.relationToModel });
|
|
63
65
|
return `${f.name}: ${refModelMeta.types.toBrandedIdTypeFnName}(${(0, fields_1.getDefaultValueForType)(f.unbrandedTypeName)})`;
|
|
64
|
-
|
|
66
|
+
}
|
|
67
|
+
case 'enum': {
|
|
65
68
|
return `${f.name}: "${f.enumerator.values[0]}"`;
|
|
66
|
-
|
|
69
|
+
}
|
|
70
|
+
default: {
|
|
67
71
|
throw new types_1.ExhaustiveSwitchCheck(f);
|
|
72
|
+
}
|
|
68
73
|
}
|
|
69
74
|
})
|
|
70
75
|
.join(',\n');
|
|
@@ -90,8 +90,9 @@ function getFieldComment(f) {
|
|
|
90
90
|
${comment}*/`;
|
|
91
91
|
}
|
|
92
92
|
function getFieldExamples(f) {
|
|
93
|
-
if (!f.attributes.examples)
|
|
93
|
+
if (!f.attributes.examples) {
|
|
94
94
|
return undefined;
|
|
95
|
+
}
|
|
95
96
|
return `Examples: ${f.attributes.examples.map((e) => `"${e}"`).join(', ')}`;
|
|
96
97
|
}
|
|
97
98
|
/**
|
package/dist/lib/attributes.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export type FieldAttributes = {
|
|
|
51
51
|
/**
|
|
52
52
|
* Schema tag: ´@@Examples("Example1", "Example2")`
|
|
53
53
|
*/
|
|
54
|
-
examples?:
|
|
54
|
+
examples?: (string | number | boolean)[];
|
|
55
55
|
/**
|
|
56
56
|
* Schema tag: ´@@DefaultField()`
|
|
57
57
|
* The property of the model that identifies the default row.
|
package/dist/lib/imports.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export declare class ImportsGenerator {
|
|
|
25
25
|
* NOTE: You should never add no items from a given path.
|
|
26
26
|
*/
|
|
27
27
|
addImport({ items, from, }: {
|
|
28
|
-
items: (Types.
|
|
28
|
+
items: (Types.Fnction | Types.ClassName | Types.TypeName | Types.VariableName)[];
|
|
29
29
|
from: Types.Path;
|
|
30
30
|
}): ImportsGenerator;
|
|
31
31
|
/**
|
package/dist/lib/meta.d.ts
CHANGED
|
@@ -39,6 +39,14 @@ export type SchemaMetaData = {
|
|
|
39
39
|
* Path to the index file for the seed package.
|
|
40
40
|
*/
|
|
41
41
|
indexFilePath: Types.Path;
|
|
42
|
+
/**
|
|
43
|
+
* Path to seed Excel template file.
|
|
44
|
+
*/
|
|
45
|
+
templateExcelFilePath: Types.Path;
|
|
46
|
+
/**
|
|
47
|
+
* Path to template decoder file.
|
|
48
|
+
*/
|
|
49
|
+
templateDecoderFilePath: Types.Path;
|
|
42
50
|
/**
|
|
43
51
|
* Path that may be used in the import statement.
|
|
44
52
|
*/
|
|
@@ -116,7 +124,7 @@ export type ModelMetaData = {
|
|
|
116
124
|
/**
|
|
117
125
|
* The name of the function that adds missing values to the partially populated model value.
|
|
118
126
|
*/
|
|
119
|
-
stubGenerationFnName: Types.
|
|
127
|
+
stubGenerationFnName: Types.Fnction;
|
|
120
128
|
/**
|
|
121
129
|
* Name of the file containing the repository definition for this model.
|
|
122
130
|
*/
|
|
@@ -153,11 +161,11 @@ export type ModelMetaData = {
|
|
|
153
161
|
/**
|
|
154
162
|
* The name of the function that decodes a source (database) object to a fully typed object, e.g. `toAggregation`.
|
|
155
163
|
*/
|
|
156
|
-
decoderFnName: Types.
|
|
164
|
+
decoderFnName: Types.Fnction;
|
|
157
165
|
/**
|
|
158
166
|
* The name of the method that should be used to get objects from the database, e.g. `aggregations`.
|
|
159
167
|
*/
|
|
160
|
-
getMethodFnName: Types.
|
|
168
|
+
getMethodFnName: Types.Fnction;
|
|
161
169
|
};
|
|
162
170
|
};
|
|
163
171
|
seed: {
|
|
@@ -173,6 +181,30 @@ export type ModelMetaData = {
|
|
|
173
181
|
* The file or package name that contains the seed data for this model (e.g. `@d2i/aggregations`).
|
|
174
182
|
*/
|
|
175
183
|
importPath: Types.Path;
|
|
184
|
+
excel: {
|
|
185
|
+
/**
|
|
186
|
+
* The name of the Excel table, e.g. `Aggregations`.
|
|
187
|
+
*/
|
|
188
|
+
tableName: string;
|
|
189
|
+
};
|
|
190
|
+
decoder: {
|
|
191
|
+
/**
|
|
192
|
+
* The name of the Zod schema, e.g. `aggregationSchema`.
|
|
193
|
+
*/
|
|
194
|
+
schemaName: Types.VariableName;
|
|
195
|
+
/**
|
|
196
|
+
* The name of the decoder, e.g. `aggregationDecoder`.
|
|
197
|
+
*/
|
|
198
|
+
decoderName: Types.VariableName;
|
|
199
|
+
/**
|
|
200
|
+
* The name of the inferred decoder type, e.g. `AggregationType`.
|
|
201
|
+
*/
|
|
202
|
+
decoderTypeName: Types.TypeName;
|
|
203
|
+
/**
|
|
204
|
+
* The name of the resulting field in the seed data
|
|
205
|
+
*/
|
|
206
|
+
dataName: Types.VariableName;
|
|
207
|
+
};
|
|
176
208
|
};
|
|
177
209
|
react: {
|
|
178
210
|
/**
|
|
@@ -187,11 +219,11 @@ export type ModelMetaData = {
|
|
|
187
219
|
/**
|
|
188
220
|
* Name of the function that should be used as React hook (e.g. `useAggregationContext`).
|
|
189
221
|
*/
|
|
190
|
-
hookFnName: Types.
|
|
222
|
+
hookFnName: Types.Fnction;
|
|
191
223
|
/**
|
|
192
224
|
* Name of the function that may be used to get a single instance of this model (e.g. `useAggregation`).
|
|
193
225
|
*/
|
|
194
|
-
instanceGetterHookFnName: Types.
|
|
226
|
+
instanceGetterHookFnName: Types.Fnction;
|
|
195
227
|
/**
|
|
196
228
|
* Name of the context wrapper.
|
|
197
229
|
*/
|
|
@@ -253,7 +285,7 @@ export type ModelMetaData = {
|
|
|
253
285
|
/**
|
|
254
286
|
* The full method name of the React Query method (e.g. `aggregations.getMap`).
|
|
255
287
|
*/
|
|
256
|
-
reactQueryMethod: Types.
|
|
288
|
+
reactQueryMethod: Types.Fnction;
|
|
257
289
|
};
|
|
258
290
|
create: {
|
|
259
291
|
/**
|
|
@@ -263,7 +295,7 @@ export type ModelMetaData = {
|
|
|
263
295
|
/**
|
|
264
296
|
* The full method name of the React Query method (e.g. `aggregations.create`).
|
|
265
297
|
*/
|
|
266
|
-
reactQueryMethod: Types.
|
|
298
|
+
reactQueryMethod: Types.Fnction;
|
|
267
299
|
};
|
|
268
300
|
update: {
|
|
269
301
|
/**
|
|
@@ -273,7 +305,7 @@ export type ModelMetaData = {
|
|
|
273
305
|
/**
|
|
274
306
|
* The full method name of the React Query method (e.g. `aggregations.update`).
|
|
275
307
|
*/
|
|
276
|
-
reactQueryMethod: Types.
|
|
308
|
+
reactQueryMethod: Types.Fnction;
|
|
277
309
|
};
|
|
278
310
|
delete: {
|
|
279
311
|
/**
|
|
@@ -283,7 +315,7 @@ export type ModelMetaData = {
|
|
|
283
315
|
/**
|
|
284
316
|
* The full method name of the React Query method (e.g. `aggregations.delete`).
|
|
285
317
|
*/
|
|
286
|
-
reactQueryMethod: Types.
|
|
318
|
+
reactQueryMethod: Types.Fnction;
|
|
287
319
|
};
|
|
288
320
|
};
|
|
289
321
|
types: {
|
|
@@ -303,11 +335,11 @@ export type ModelMetaData = {
|
|
|
303
335
|
* Function that may be used to convert a scalar value to a branded ID type,
|
|
304
336
|
* e.g. `toAggregationId`.
|
|
305
337
|
*/
|
|
306
|
-
toBrandedIdTypeFnName: Types.
|
|
338
|
+
toBrandedIdTypeFnName: Types.Fnction;
|
|
307
339
|
/**
|
|
308
340
|
* The name of the function that decodes a source (database) object to a fully typed object, e.g. `aggregationDecoder`.
|
|
309
341
|
*/
|
|
310
|
-
zodDecoderFnName: Types.
|
|
342
|
+
zodDecoderFnName: Types.Fnction;
|
|
311
343
|
/**
|
|
312
344
|
* The name of the file containing type definitions (e.g. `aggregation.type`).
|
|
313
345
|
*/
|
|
@@ -332,11 +364,15 @@ export type FieldMetaData = {
|
|
|
332
364
|
/**
|
|
333
365
|
* The name of the method that should be used to get all child objects for a given item, e.g. `getItemsForAggregation`.
|
|
334
366
|
*/
|
|
335
|
-
getByForeignKeyMethodFnName: Types.
|
|
367
|
+
getByForeignKeyMethodFnName: Types.Fnction;
|
|
336
368
|
/**
|
|
337
369
|
* The name of the method that should be used to get all child Ids for a given item, e.g. `getIdsForAggregation`.
|
|
338
370
|
*/
|
|
339
|
-
getByForeignKeyIdsMethodFnName: Types.
|
|
371
|
+
getByForeignKeyIdsMethodFnName: Types.Fnction;
|
|
372
|
+
/**
|
|
373
|
+
* The name of the column in the seed Excel table, e.g. `Aggregation`.
|
|
374
|
+
*/
|
|
375
|
+
excelColumnName: string;
|
|
340
376
|
};
|
|
341
377
|
/**
|
|
342
378
|
* A collection of hardcoded values shared across multiple generators related to the given field in the model.
|
package/dist/lib/meta.js
CHANGED
|
@@ -46,6 +46,8 @@ function getSchemaMetadata({ config }) {
|
|
|
46
46
|
},
|
|
47
47
|
seed: {
|
|
48
48
|
indexFilePath: Types.toPath(`${config.paths.seedPath}index`),
|
|
49
|
+
templateExcelFilePath: Types.toPath(`${config.paths.seedPath}template.xlsx`),
|
|
50
|
+
templateDecoderFilePath: Types.toPath(`${config.paths.seedPath}seed-decoder`),
|
|
49
51
|
importPath: Types.toPath(`@${config.project}/seed`),
|
|
50
52
|
randomSeed: config.randomSeed,
|
|
51
53
|
},
|
|
@@ -63,7 +65,7 @@ exports.getSchemaMetadata = getSchemaMetadata;
|
|
|
63
65
|
*/
|
|
64
66
|
function getModelMetadata({ model }) {
|
|
65
67
|
const { name, schemaConfig: config } = model;
|
|
66
|
-
const { PascalCase, camelCase, pluralized, uncapitalizedPlural } = (0, string_1.conjugateNames)(name);
|
|
68
|
+
const { PascalCase, camelCase, pluralized, uncapitalizedPlural, capitalizedPlural } = (0, string_1.conjugateNames)(name);
|
|
67
69
|
return {
|
|
68
70
|
userFriendlyName: PascalCase,
|
|
69
71
|
data: {
|
|
@@ -89,6 +91,15 @@ function getModelMetadata({ model }) {
|
|
|
89
91
|
filePath: Types.toPath(`${config.paths.seedPath}${uncapitalizedPlural}`),
|
|
90
92
|
constantName: Types.toVariableName(`${uncapitalizedPlural}`),
|
|
91
93
|
importPath: Types.toPath(`@${config.project}/seed`),
|
|
94
|
+
excel: {
|
|
95
|
+
tableName: `${capitalizedPlural}`,
|
|
96
|
+
},
|
|
97
|
+
decoder: {
|
|
98
|
+
schemaName: Types.toVariableName(`${camelCase}Schema`),
|
|
99
|
+
decoderTypeName: Types.toTypeName(`${PascalCase}DecoderType`),
|
|
100
|
+
decoderName: Types.toVariableName(`${camelCase}Decoder`),
|
|
101
|
+
dataName: Types.toVariableName(`${uncapitalizedPlural}`),
|
|
102
|
+
},
|
|
92
103
|
},
|
|
93
104
|
react: {
|
|
94
105
|
folderName: Types.toFolderName(`${PascalCase}`),
|
|
@@ -161,6 +172,7 @@ function getFieldMetadata({ field }) {
|
|
|
161
172
|
tsFieldName: Types.toVariableName((0, string_1.toCamelCase)(field.name)),
|
|
162
173
|
getByForeignKeyMethodFnName: Types.toFunction(`getItemsFor${PascalCase}`),
|
|
163
174
|
getByForeignKeyIdsMethodFnName: Types.toFunction(`getIdsFor${PascalCase}`),
|
|
175
|
+
excelColumnName: (0, string_1.toPascalCase)(field.name),
|
|
164
176
|
};
|
|
165
177
|
// switch (field.kind) {
|
|
166
178
|
// case 'id':
|
|
@@ -11,13 +11,13 @@ export declare const toTypeName: (t: string) => TypeName;
|
|
|
11
11
|
/**
|
|
12
12
|
* The name of a function (e.g. "toAggregation").
|
|
13
13
|
*/
|
|
14
|
-
export type
|
|
14
|
+
export type Fnction = string & {
|
|
15
15
|
readonly ___type: 'FunctionName';
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
18
|
* Converts a string to a branded function name.
|
|
19
19
|
*/
|
|
20
|
-
export declare const toFunction: (t: string) =>
|
|
20
|
+
export declare const toFunction: (t: string) => Fnction;
|
|
21
21
|
/**
|
|
22
22
|
* The name of a class, e.g. "AggregationRepository".
|
|
23
23
|
*/
|
package/dist/lib/utils/file.js
CHANGED
|
@@ -40,6 +40,8 @@ function _resolvePath(path) {
|
|
|
40
40
|
const chunks = path.split('/');
|
|
41
41
|
const resolved = [];
|
|
42
42
|
while (chunks.length > 0) {
|
|
43
|
+
// NOTE: We can safely force unwrap here because we check the length of the array.
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
43
45
|
const chunk = chunks.shift();
|
|
44
46
|
if (chunk === '..') {
|
|
45
47
|
resolved.pop();
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Compatible with the `@prisma/internals` logger and console.
|
|
4
4
|
*/
|
|
5
5
|
export interface Logger {
|
|
6
|
-
log(...data:
|
|
7
|
-
warn(message:
|
|
8
|
-
info(message:
|
|
9
|
-
error(message:
|
|
10
|
-
query(message:
|
|
6
|
+
log(...data: unknown[]): void;
|
|
7
|
+
warn(message: unknown, ...optionalParams: unknown[]): void;
|
|
8
|
+
info(message: unknown, ...optionalParams: unknown[]): void;
|
|
9
|
+
error(message: unknown, ...optionalParams: unknown[]): void;
|
|
10
|
+
query(message: unknown, ...optionalParams: unknown[]): void;
|
|
11
11
|
}
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Returns the same string with a lowercase first letter.
|
|
3
3
|
*/
|
|
4
4
|
export declare const uncapitalize: (str: string) => string;
|
|
5
|
+
/**
|
|
6
|
+
* Returns the same string with an uppercase first letter.
|
|
7
|
+
*/
|
|
8
|
+
export declare const capitalize: (str: string) => string;
|
|
5
9
|
/**
|
|
6
10
|
* Returns the camelCase version of the given string.
|
|
7
11
|
*/
|
|
@@ -26,4 +30,5 @@ export declare const conjugateNames: (name: string) => {
|
|
|
26
30
|
camelCase: string;
|
|
27
31
|
pluralized: string;
|
|
28
32
|
uncapitalizedPlural: string;
|
|
33
|
+
capitalizedPlural: string;
|
|
29
34
|
};
|
package/dist/lib/utils/string.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.conjugateNames = exports.commentLines = exports.pluralize = exports.toPascalCase = exports.toCamelCase = exports.uncapitalize = void 0;
|
|
3
|
+
exports.conjugateNames = exports.commentLines = exports.pluralize = exports.toPascalCase = exports.toCamelCase = exports.capitalize = exports.uncapitalize = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Returns the same string with a lowercase first letter.
|
|
6
6
|
*/
|
|
@@ -8,6 +8,13 @@ const uncapitalize = (str) => {
|
|
|
8
8
|
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
9
9
|
};
|
|
10
10
|
exports.uncapitalize = uncapitalize;
|
|
11
|
+
/**
|
|
12
|
+
* Returns the same string with an uppercase first letter.
|
|
13
|
+
*/
|
|
14
|
+
const capitalize = (str) => {
|
|
15
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
16
|
+
};
|
|
17
|
+
exports.capitalize = capitalize;
|
|
11
18
|
/**
|
|
12
19
|
* Returns the camelCase version of the given string.
|
|
13
20
|
*/
|
|
@@ -102,7 +109,8 @@ exports.commentLines = commentLines;
|
|
|
102
109
|
const conjugateNames = (name) => ({
|
|
103
110
|
PascalCase: (0, exports.toPascalCase)(name),
|
|
104
111
|
camelCase: (0, exports.toCamelCase)(name),
|
|
105
|
-
pluralized: (0, exports.pluralize)(name),
|
|
112
|
+
pluralized: (0, exports.capitalize)((0, exports.pluralize)(name)),
|
|
106
113
|
uncapitalizedPlural: (0, exports.uncapitalize)((0, exports.pluralize)(name)),
|
|
114
|
+
capitalizedPlural: (0, exports.capitalize)((0, exports.pluralize)(name)),
|
|
107
115
|
});
|
|
108
116
|
exports.conjugateNames = conjugateNames;
|
|
@@ -30,26 +30,33 @@ function parseAttributesFromDocumentation({ documentation }) {
|
|
|
30
30
|
}
|
|
31
31
|
exports.parseAttributesFromDocumentation = parseAttributesFromDocumentation;
|
|
32
32
|
function parseArgumentToStringOrStringArray(str) {
|
|
33
|
-
if (str === '')
|
|
33
|
+
if (str === '') {
|
|
34
34
|
return '';
|
|
35
|
+
}
|
|
35
36
|
try {
|
|
36
37
|
return JSON.parse(str);
|
|
37
38
|
}
|
|
38
|
-
catch (_a) {
|
|
39
|
+
catch (_a) {
|
|
40
|
+
// ignore
|
|
41
|
+
}
|
|
39
42
|
try {
|
|
40
43
|
return JSON.parse(`[${str}]`);
|
|
41
44
|
}
|
|
42
|
-
catch (_b) {
|
|
45
|
+
catch (_b) {
|
|
46
|
+
// ignore
|
|
47
|
+
}
|
|
43
48
|
try {
|
|
44
49
|
return JSON.parse(`"${str}"`);
|
|
45
50
|
}
|
|
46
|
-
catch (_c) {
|
|
51
|
+
catch (_c) {
|
|
52
|
+
// ignore
|
|
53
|
+
}
|
|
47
54
|
throw new Error(`Could not parse attribute argument: ${str}`);
|
|
48
55
|
}
|
|
49
56
|
exports.parseArgumentToStringOrStringArray = parseArgumentToStringOrStringArray;
|
|
50
57
|
const blankStringBooleanDecoder = zod_1.default
|
|
51
58
|
.string()
|
|
52
|
-
.transform((
|
|
59
|
+
.transform(() => true)
|
|
53
60
|
.or(zod_1.default.boolean())
|
|
54
61
|
.optional()
|
|
55
62
|
.default(false);
|
|
@@ -84,9 +91,10 @@ function getModelAttributes(model) {
|
|
|
84
91
|
}));
|
|
85
92
|
const result = decoder.safeParse(attributes);
|
|
86
93
|
if (!result.success) {
|
|
87
|
-
throw new Error(`Model ${model.name} has invalid model attributes: ${result.error}`);
|
|
94
|
+
throw new Error(`Model ${model.name} has invalid model attributes: ${result.error.toString()}`);
|
|
88
95
|
}
|
|
89
96
|
if (result.data.description === 'The calculated metric value for a dataset.') {
|
|
97
|
+
// TODO: What is this supposed to do?
|
|
90
98
|
}
|
|
91
99
|
return result.data;
|
|
92
100
|
}
|
|
@@ -99,10 +107,13 @@ function getFieldAttributes(field) {
|
|
|
99
107
|
if (attributes.examples === undefined && attributes.example !== undefined) {
|
|
100
108
|
attributes.examples = attributes.example;
|
|
101
109
|
}
|
|
110
|
+
// Prisma also has an "@ignore" attribute - see https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#ignore
|
|
111
|
+
// we handle this the same way as our custom "ignore" attribute
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
113
|
+
const isPrismaIgnored = field.isIgnored === true;
|
|
114
|
+
const isPXLIgnored = Object.hasOwn(attributes, 'ignore');
|
|
102
115
|
return {
|
|
103
|
-
|
|
104
|
-
// we handle this the same way as our custom "ignore" attribute
|
|
105
|
-
ignore: field.isIgnored || Object.hasOwn(attributes, 'ignore'),
|
|
116
|
+
ignore: isPrismaIgnored || isPXLIgnored,
|
|
106
117
|
description: attributes.description && (0, remeda_1.isString)(attributes.description) ? attributes.description : undefined,
|
|
107
118
|
isDefaultField: Object.hasOwn(attributes, 'isDefault'),
|
|
108
119
|
isLabel: Object.hasOwn(attributes, 'isLabel'),
|
package/dist/prisma/parse.js
CHANGED
|
@@ -237,6 +237,7 @@ function getTsTypeForScalar(field) {
|
|
|
237
237
|
case 'JSON':
|
|
238
238
|
case 'Bytes':
|
|
239
239
|
(0, error_1.throwError)('Not implemented yet');
|
|
240
|
+
break;
|
|
240
241
|
default:
|
|
241
242
|
// return field.type
|
|
242
243
|
(0, error_1.throwError)(`Investigate: 'default' case in getTypescriptType for field ${field.name} of type ${field.type}`);
|
|
@@ -273,6 +274,7 @@ function getTsTypeForEnum(field) {
|
|
|
273
274
|
case 'Float':
|
|
274
275
|
case 'Int':
|
|
275
276
|
(0, error_1.throwError)(`The enum field ${field.name} is of type ${field.type} - but only String fields are supported for enums so far.`);
|
|
277
|
+
break;
|
|
276
278
|
default:
|
|
277
279
|
return Types.toTypeName(field.type);
|
|
278
280
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postxl/generator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"main": "./dist/generator.js",
|
|
5
5
|
"typings": "./dist/generator.d.ts",
|
|
6
6
|
"bin": {
|
|
@@ -17,11 +17,12 @@
|
|
|
17
17
|
"@faker-js/faker": "7.6.0",
|
|
18
18
|
"@prisma/generator-helper": "4.12.0",
|
|
19
19
|
"@prisma/internals": "^4.12.0",
|
|
20
|
+
"exceljs": "^4.3.0",
|
|
20
21
|
"fast-glob": "^3.2.12",
|
|
21
22
|
"prettier": "^2.8.7",
|
|
22
23
|
"remeda": "1.9.4",
|
|
23
24
|
"zod": "3.21.4",
|
|
24
|
-
"@postxl/lock": "0.3.
|
|
25
|
+
"@postxl/lock": "0.3.2"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@prisma/client": "4.12.0",
|