@postxl/generator 0.16.0 → 0.16.2

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.
@@ -21,7 +21,7 @@ exports.generateEnumReactComponents = generateEnumReactComponents;
21
21
  */
22
22
  function generateEnumSelect({ enumerator, meta }) {
23
23
  const imports = imports_1.ImportsGenerator.from(meta.react.folderPath).addImport({
24
- items: [enumerator.typeName],
24
+ items: [enumerator.tsTypeName],
25
25
  from: meta.types.importPath,
26
26
  });
27
27
  return `
@@ -35,7 +35,7 @@ import { UnionOmit } from '@lib/types'
35
35
  ${imports.generate()}
36
36
 
37
37
  type Option = {
38
- id: ${enumerator.typeName}
38
+ id: ${enumerator.tsTypeName}
39
39
  label: string
40
40
  }
41
41
 
@@ -46,7 +46,7 @@ const OPTIONS: Option[] = [
46
46
  // Switcher
47
47
 
48
48
  export const ${meta.react.switcherInputName} = ({ ...delegated }: UnionOmit<
49
- React.ComponentPropsWithoutRef<typeof ButtonSwitcher<${enumerator.typeName}>>,
49
+ React.ComponentPropsWithoutRef<typeof ButtonSwitcher<${enumerator.tsTypeName}>>,
50
50
  'options'
51
51
  >) => (
52
52
  <ButtonSwitcher options={OPTIONS} {...delegated} />
@@ -8,15 +8,15 @@ function generateEnumType({ enumerator, meta, prismaClientPath, }) {
8
8
  return `
9
9
  import * as Prisma from '${prismaClientPath}'
10
10
 
11
- export type ${enumerator.typeName} = Prisma.${enumerator.sourceName}
12
- export const ${enumerator.typeName} = Prisma.${enumerator.sourceName}
11
+ export type ${enumerator.tsTypeName} = Prisma.${enumerator.sourceName}
12
+ export const ${enumerator.tsTypeName} = Prisma.${enumerator.sourceName}
13
13
  ${enumerator.description
14
14
  ? `/**
15
15
  * ${enumerator.description.split('\n').join('\n * ')}
16
16
  */
17
17
  `
18
18
  : ''}
19
- export const ${meta.types.membersList}: ${enumerator.typeName}[] = [
19
+ export const ${meta.types.membersList}: ${enumerator.tsTypeName}[] = [
20
20
  ${enumerator.values
21
21
  .map((v) => {
22
22
  var _a;
@@ -42,12 +42,10 @@ function generateTableDecoder({ model, meta, imports, }) {
42
42
  renameTransforms.push(`${field.name}: item['${fieldMeta.excelColumnName}']`);
43
43
  switch (field.kind) {
44
44
  case 'id': {
45
- imports.addImport({
46
- items: [meta.types.toBrandedIdTypeFnName],
47
- from: meta.types.importPath,
48
- });
45
+ imports.addImport({ items: [meta.types.toBrandedIdTypeFnName], from: meta.types.importPath });
49
46
  fieldDecoders.push(`${fieldMeta.excelColumnName}: ${toExcelDecoder({
50
- typeName: field.unbrandedTypeName,
47
+ tsTypeName: field.unbrandedTypeName,
48
+ dbTypeName: field.type,
51
49
  nullable: false,
52
50
  imports,
53
51
  })}.transform((id: ${field.unbrandedTypeName}) => ${meta.types.toBrandedIdTypeFnName}(id))`);
@@ -55,7 +53,8 @@ function generateTableDecoder({ model, meta, imports, }) {
55
53
  }
56
54
  case 'scalar': {
57
55
  fieldDecoders.push(`${fieldMeta.excelColumnName}: ${toExcelDecoder({
58
- typeName: field.typeName,
56
+ tsTypeName: field.tsTypeName,
57
+ dbTypeName: field.type,
59
58
  nullable: !field.isRequired,
60
59
  imports,
61
60
  })}`);
@@ -64,12 +63,10 @@ function generateTableDecoder({ model, meta, imports, }) {
64
63
  case 'relation': {
65
64
  const refModel = field.relationToModel;
66
65
  const refMeta = (0, meta_1.getModelMetadata)({ model: refModel });
67
- imports.addImport({
68
- items: [refMeta.types.toBrandedIdTypeFnName],
69
- from: refMeta.types.importPath,
70
- });
66
+ imports.addImport({ items: [refMeta.types.toBrandedIdTypeFnName], from: refMeta.types.importPath });
71
67
  fieldDecoders.push(`${fieldMeta.excelColumnName}: ${toExcelDecoder({
72
- typeName: field.unbrandedTypeName,
68
+ tsTypeName: field.unbrandedTypeName,
69
+ dbTypeName: field.type,
73
70
  nullable: !field.isRequired,
74
71
  imports,
75
72
  })}.transform((id: ${field.unbrandedTypeName}${field.isRequired ? '' : '| null'}) => ${field.isRequired ? '' : ' id === null ? null : '}${refMeta.types.toBrandedIdTypeFnName}(id))`);
@@ -77,10 +74,7 @@ function generateTableDecoder({ model, meta, imports, }) {
77
74
  }
78
75
  case 'enum': {
79
76
  const refEnumMeta = (0, meta_1.getEnumMetadata)({ enumerator: field.enumerator });
80
- imports.addImport({
81
- items: [field.enumerator.typeName],
82
- from: refEnumMeta.types.importPath,
83
- });
77
+ imports.addImport({ items: [field.enumerator.tsTypeName], from: refEnumMeta.types.importPath });
84
78
  fieldDecoders.push(`${fieldMeta.excelColumnName}: z.enum([${field.enumerator.values.map((v) => `'${v}'`).join(', ')}])${field.isRequired ? '' : '.nullable()'}`);
85
79
  break;
86
80
  }
@@ -105,8 +99,8 @@ export type ${meta.seed.decoder.decoderTypeName} = z.infer<typeof ${meta.seed.de
105
99
  export const ${meta.seed.decoder.decoderName} = z.array(${meta.seed.decoder.schemaName})
106
100
  `;
107
101
  }
108
- function toExcelDecoder({ typeName, nullable, imports, }) {
109
- switch (typeName) {
102
+ function toExcelDecoder({ tsTypeName, dbTypeName: typeName, nullable, imports, }) {
103
+ switch (tsTypeName) {
110
104
  case 'string': {
111
105
  const decoder = (0, types_1.toFunction)(nullable ? 'excelStringNullableDecoder' : 'excelStringDecoder');
112
106
  imports.addImport({
@@ -122,7 +116,13 @@ function toExcelDecoder({ typeName, nullable, imports, }) {
122
116
  });
123
117
  return 'excelBooleanDecoder';
124
118
  case 'number':
125
- return `z.number()${nullable ? '.nullable()' : ''}`;
119
+ switch (typeName) {
120
+ case 'Int':
121
+ case 'BigInt':
122
+ return `z.number().int()${nullable ? '.nullable()' : ''}`;
123
+ default:
124
+ return `z.number()${nullable ? '.nullable()' : ''}`;
125
+ }
126
126
  case 'Date': {
127
127
  const decoder = (0, types_1.toFunction)(nullable ? 'excelDateNullableDecoder' : 'excelDateDecoder');
128
128
  imports.addImport({
@@ -41,7 +41,7 @@ function generateModelBusinessLogic({ model, meta }) {
41
41
  * (e.g. when we generate business logic service for Aggregation, the AggregationRepository
42
42
  * would be referenced using `this.data` variable).
43
43
  */
44
- const modelRepositoryVariableName = Types.toVariableName('data');
44
+ const modelRepositoryVariableName = meta.businessLogic.dataRepositoryVariableName;
45
45
  /**
46
46
  * The name of the variable that holds the central business logic service instance.
47
47
  * Instead of injecting a repository instance for each model, we inject this single instance
@@ -312,7 +312,7 @@ function getFormImports({ model, meta }) {
312
312
  for (const f of (0, fields_1.getEnumFields)(model)) {
313
313
  const enumMeta = (0, meta_1.getEnumMetadata)(f);
314
314
  imports.addImport({
315
- items: [f.enumerator.typeName],
315
+ items: [f.enumerator.tsTypeName],
316
316
  from: enumMeta.types.importPath,
317
317
  });
318
318
  imports.addImport({
@@ -351,7 +351,7 @@ function getCreateFormInputFields({ model }) {
351
351
  form.append(`${getFormikFieldName(field.name)}: { id: ${field.relationToModel.brandedIdType} } | null`);
352
352
  break;
353
353
  case 'scalar':
354
- form.append(`${getFormikFieldName(field.name)}: ${field.typeName} | null`);
354
+ form.append(`${getFormikFieldName(field.name)}: ${field.tsTypeName} | null`);
355
355
  break;
356
356
  case 'enum':
357
357
  form.append(`${getFormikFieldName(field.name)}: { id: ${field.typeName} } | null`);
@@ -424,10 +424,10 @@ function getEditFormInputFields({ model }) {
424
424
  break;
425
425
  case 'scalar':
426
426
  if (field.isRequired) {
427
- form.append(`${getFormikFieldName(field.name)}: ${field.typeName}`);
427
+ form.append(`${getFormikFieldName(field.name)}: ${field.tsTypeName}`);
428
428
  }
429
429
  else {
430
- form.append(`${getFormikFieldName(field.name)}: ${field.typeName} | null`);
430
+ form.append(`${getFormikFieldName(field.name)}: ${field.tsTypeName} | null`);
431
431
  }
432
432
  break;
433
433
  case 'enum':
@@ -486,7 +486,7 @@ function getFormFieldComponents({ model }) {
486
486
  }
487
487
  case 'scalar': {
488
488
  // Each scalar field has a different generic component based on the provided type.
489
- scalar: switch (field.typeName) {
489
+ scalar: switch (field.tsTypeName) {
490
490
  case 'string': {
491
491
  form.append(`
492
492
  <div>
@@ -523,7 +523,7 @@ function getFormFieldComponents({ model }) {
523
523
  break scalar;
524
524
  }
525
525
  default: {
526
- console.warn(`Unknown scalar type ${field.typeName} for field ${model.name}.${field.name}.`);
526
+ console.warn(`Unknown scalar type ${field.tsTypeName} for field ${model.name}.${field.name}.`);
527
527
  break scalar;
528
528
  }
529
529
  }
@@ -11,7 +11,7 @@ const imports_1 = require("../../lib/imports");
11
11
  function generateRoute({ model, meta }) {
12
12
  const { idField, defaultField } = model;
13
13
  const defaultValueMethod = `
14
- getDefault: procedure.query(({ ctx }) => ctx.data.${meta.data.dataServiceName}.defaultValue),
14
+ getDefault: procedure.query(({ ctx }) => ctx.data.${meta.data.dataServiceName}.${meta.businessLogic.dataRepositoryVariableName}.defaultValue),
15
15
  `;
16
16
  const createMethod = getCreateMethod({ model, meta });
17
17
  const updateMethod = getUpdateMethod({ model, meta });
@@ -113,7 +113,7 @@ function quoteSingleQuote(str) {
113
113
  }
114
114
  function generateScalarFieldExample({ field, model, index, mode, }) {
115
115
  const { hasExample, example } = generateFieldExample({ field, model, index, mode });
116
- switch (field.typeName) {
116
+ switch (field.tsTypeName) {
117
117
  case 'string': {
118
118
  if (hasExample && typeof example === 'string') {
119
119
  return `'${quoteSingleQuote(example)}'`;
@@ -131,7 +131,13 @@ function generateScalarFieldExample({ field, model, index, mode, }) {
131
131
  if (hasExample) {
132
132
  return `${example}`;
133
133
  }
134
- return generateMockNumber();
134
+ switch (field.type) {
135
+ case 'BigInt':
136
+ case 'Int':
137
+ return generateMockInteger();
138
+ default:
139
+ return generateMockNumber();
140
+ }
135
141
  }
136
142
  case 'boolean': {
137
143
  if (hasExample) {
@@ -147,7 +153,7 @@ function generateScalarFieldExample({ field, model, index, mode, }) {
147
153
  return generateMockDate();
148
154
  }
149
155
  default: {
150
- console.warn(`Unknown scalar type: ${field.typeName}`);
156
+ console.warn(`Unknown scalar type: ${field.tsTypeName}`);
151
157
  return '';
152
158
  }
153
159
  }
@@ -182,6 +188,9 @@ function generateMockString({ field, model, index }) {
182
188
  }
183
189
  return faker_1.faker.lorem.words(3);
184
190
  }
191
+ function generateMockInteger() {
192
+ return faker_1.faker.datatype.number({ precision: 1, min: 1, max: 1000 }).toString();
193
+ }
185
194
  function generateMockNumber() {
186
195
  return faker_1.faker.datatype.float({ precision: 0.1, min: 0, max: 1 }).toString();
187
196
  }
@@ -48,7 +48,7 @@ function getAssignmentStatementModel({ fields, imports }) {
48
48
  }
49
49
  switch (f.kind) {
50
50
  case 'scalar': {
51
- return `${f.name}: ${(0, fields_1.getDefaultValueForType)(f.typeName)}`;
51
+ return `${f.name}: ${(0, fields_1.getDefaultValueForType)(f.tsTypeName)}`;
52
52
  }
53
53
  case 'id': {
54
54
  const idRefMeta = (0, meta_1.getModelMetadata)({ model: f.model });
@@ -28,7 +28,7 @@ function generateModelTypes({ model, meta }) {
28
28
  for (const f of (0, fields_1.getEnumFields)(model)) {
29
29
  const refEnumMeta = (0, meta_1.getEnumMetadata)({ enumerator: f.enumerator });
30
30
  imports.addImport({
31
- items: [f.enumerator.typeName],
31
+ items: [f.enumerator.tsTypeName],
32
32
  from: refEnumMeta.types.filePath,
33
33
  });
34
34
  }
@@ -123,7 +123,7 @@ function getFieldType(f) {
123
123
  case 'id':
124
124
  return f.model.brandedIdType;
125
125
  case 'scalar':
126
- return f.typeName;
126
+ return f.tsTypeName;
127
127
  default:
128
128
  throw new types_1.ExhaustiveSwitchCheck(f);
129
129
  }
@@ -140,7 +140,7 @@ function getLinkedFieldType(f) {
140
140
  case 'id':
141
141
  return `${f.name}: ${f.model.brandedIdType}`;
142
142
  case 'scalar':
143
- return `${f.name}: ${f.typeName}`;
143
+ return `${f.name}: ${f.tsTypeName}`;
144
144
  default:
145
145
  throw new types_1.ExhaustiveSwitchCheck(f);
146
146
  }
@@ -245,6 +245,10 @@ export type ModelMetaData = {
245
245
  * Path to the file containing the service.
246
246
  */
247
247
  serviceFilePath: Types.Path;
248
+ /**
249
+ * Name by which the business logic service exposes the data service.
250
+ */
251
+ dataRepositoryVariableName: Types.VariableName;
248
252
  };
249
253
  /**
250
254
  * Properties provided by the `seed` generators.
package/dist/lib/meta.js CHANGED
@@ -105,6 +105,7 @@ function getModelMetadata({ model }) {
105
105
  serviceVariableName: Types.toVariableName(`${uncapitalizedPlural}`),
106
106
  serviceFileName: Types.toFileName(`${camelCase}.service`),
107
107
  serviceFilePath: Types.toPath(`${config.paths.businessLogicPath}${camelCase}.service`),
108
+ dataRepositoryVariableName: Types.toVariableName(`data`),
108
109
  },
109
110
  seed: {
110
111
  filePath: Types.toPath(`${config.paths.seedPath}${uncapitalizedPlural}`),
@@ -45,11 +45,11 @@ exports.getDefaultValueForType = getDefaultValueForType;
45
45
  * Returns true if the given field is unique and a string field.
46
46
  */
47
47
  const isUniqueStringField = (f) => (f.kind === 'id' && f.isUnique && f.unbrandedTypeName === 'string') ||
48
- (f.kind === 'scalar' && f.isUnique && f.typeName === 'string');
48
+ (f.kind === 'scalar' && f.isUnique && f.tsTypeName === 'string');
49
49
  exports.isUniqueStringField = isUniqueStringField;
50
50
  /**
51
51
  * Returns true if the given field has a maxLength attribute.
52
52
  */
53
53
  const isMaxLengthStringField = (f) => (f.kind === 'id' && !!f.attributes.maxLength && f.unbrandedTypeName === 'string') ||
54
- (f.kind === 'scalar' && !!f.attributes.maxLength && f.typeName === 'string');
54
+ (f.kind === 'scalar' && !!f.attributes.maxLength && f.tsTypeName === 'string');
55
55
  exports.isMaxLengthStringField = isMaxLengthStringField;
@@ -190,6 +190,10 @@ export type FieldCore = {
190
190
  * Name of the field in the source e.g. in the database (e.g. Id)
191
191
  */
192
192
  sourceName: string;
193
+ /**
194
+ * The type of the field as it appears in the schema (e.g. `Int`, `Float`, `String`).
195
+ */
196
+ type: string;
193
197
  /**
194
198
  * Validation rule for the field.
195
199
  */
@@ -216,7 +220,7 @@ export type FieldScalar = Prettify<Omit<FieldCore, 'name'> & {
216
220
  /**
217
221
  * Name of the scalar TypeScript type, e.g. string
218
222
  */
219
- typeName: Types.TypeName;
223
+ tsTypeName: Types.TypeName;
220
224
  /**
221
225
  * If true, each element is unique.
222
226
  * Note: This is ensured by the repository/database
@@ -253,7 +257,7 @@ export type FieldId = Prettify<Omit<FieldCore, 'name'> & {
253
257
  * Name of the unbranded TypeScript type of the id field, e.g. string
254
258
  *
255
259
  * Note: This should only be used in the type generator - all other generators
256
- * should use the branded type "typeName"!
260
+ * should use the branded type "tsTypeName"!
257
261
  */
258
262
  unbrandedTypeName: Types.TypeName;
259
263
  }>;
@@ -283,7 +287,7 @@ export declare const isFieldId: (field: Field) => field is Prettify<Omit<FieldCo
283
287
  * Name of the unbranded TypeScript type of the id field, e.g. string
284
288
  *
285
289
  * Note: This should only be used in the type generator - all other generators
286
- * should use the branded type "typeName"!
290
+ * should use the branded type "tsTypeName"!
287
291
  */
288
292
  unbrandedTypeName: Types.TypeName;
289
293
  }>;
@@ -395,7 +399,7 @@ export type Enum = {
395
399
  /**
396
400
  * TypeScript type that should be used to reference an enumerator.
397
401
  */
398
- typeName: Types.TypeName;
402
+ tsTypeName: Types.TypeName;
399
403
  /**
400
404
  * Object containing all optional attributes of the enum.
401
405
  */
@@ -28,7 +28,23 @@ exports.getZodDecoderDefinition = getZodDecoderDefinition;
28
28
  function getZodTypeDefinition(field) {
29
29
  switch (field.kind) {
30
30
  case 'scalar':
31
- return `${field.typeName === 'Date' ? 'date' : field.typeName}()`;
31
+ switch (field.tsTypeName) {
32
+ case 'Date': {
33
+ return `date()`;
34
+ }
35
+ case 'number': {
36
+ switch (field.type) {
37
+ case 'Int':
38
+ case 'BigInt':
39
+ return `number().int()`;
40
+ default:
41
+ return `number()`;
42
+ }
43
+ }
44
+ default: {
45
+ return `${field.tsTypeName}()`;
46
+ }
47
+ }
32
48
  case 'enum':
33
49
  return `enum([${field.enumerator.values.map((v) => `'${v}'`).join(', ')}])`;
34
50
  case 'id':
@@ -105,6 +105,7 @@ function parseModel({ dmmfModel, enums, models, config, }) {
105
105
  isRequired: dmmfField.isRequired,
106
106
  attributes,
107
107
  schemaConfig: config,
108
+ type: dmmfField.type,
108
109
  };
109
110
  // NOTE: We mark scalar fields which are used in relations as relation fields by Purple Schema standards.
110
111
  if (dmmfField.name in relations) {
@@ -129,7 +130,7 @@ function parseModel({ dmmfModel, enums, models, config, }) {
129
130
  if (dmmfField.type === 'Float') {
130
131
  validation = { type: 'float' };
131
132
  }
132
- return Object.assign(Object.assign({ kind: 'scalar', validation }, shared), { isUnique: isUniqueField(dmmfField), isGenerated: isAutoIncrementField(dmmfField), typeName: getTsTypeForScalar(dmmfField) });
133
+ return Object.assign(Object.assign({ kind: 'scalar', validation }, shared), { isUnique: isUniqueField(dmmfField), isGenerated: isAutoIncrementField(dmmfField), tsTypeName: getTsTypeForScalar(dmmfField) });
133
134
  }
134
135
  if (dmmfField.kind === 'enum') {
135
136
  const fieldEnumDef = enums.find((e) => e.sourceName === dmmfField.type);
@@ -227,7 +228,7 @@ function parseEnum({ dmmfEnum, config }) {
227
228
  name: dmmfEnum.name,
228
229
  description: attributes.description,
229
230
  attributes,
230
- typeName: Types.toTypeName((0, string_1.toPascalCase)(dmmfEnum.name)),
231
+ tsTypeName: Types.toTypeName((0, string_1.toPascalCase)(dmmfEnum.name)),
231
232
  sourceName: dmmfEnum.name,
232
233
  values: dmmfEnum.values.map((v) => v.name),
233
234
  schemaConfig: config,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postxl/generator",
3
- "version": "0.16.0",
3
+ "version": "0.16.2",
4
4
  "main": "./dist/generator.js",
5
5
  "typings": "./dist/generator.d.ts",
6
6
  "bin": {
@@ -22,7 +22,7 @@
22
22
  "prettier": "^2.8.7",
23
23
  "remeda": "1.9.4",
24
24
  "zod": "3.21.4",
25
- "@postxl/lock": "0.4.2"
25
+ "@postxl/lock": "0.4.4"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@prisma/client": "4.12.0",
@@ -43,8 +43,8 @@
43
43
  "autoDetect": true
44
44
  },
45
45
  "scripts": {
46
- "build": "tsc -b",
47
- "prepublish": "tsc -b",
46
+ "build": "tsc -p tsconfig.build.json",
47
+ "prepublish": "tsc -p tsconfig.build.json",
48
48
  "dev": "tsc -b -w",
49
49
  "test": "jest",
50
50
  "test:watch": "jest --watch",