@postxl/generator 0.47.0 → 0.47.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.
package/dist/generator.js CHANGED
@@ -165,7 +165,7 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
165
165
  // Types
166
166
  generated.write(`/${meta.types.filePath}.ts`, (0, types_generator_3.generateModelTypes)({ model, meta }));
167
167
  // Seed
168
- generated.write(`/${meta.seed.filePath}.ts`, (0, seed_generator_1.generateSeedModel)({ model, itemCount: 5, meta }));
168
+ generated.write(`/${meta.seed.filePath}.ts`, (0, seed_generator_1.generateSeedModel)({ model, itemCount: 5, meta, models }));
169
169
  // Data
170
170
  generated.write(`/${meta.data.stubFilePath}.ts`, (0, stub_generator_1.generateStub)({ model, meta }));
171
171
  generated.write(`/${meta.data.repository.filePath}.ts`, (0, repository_generator_1.generateRepository)({ model, meta }));
@@ -11,11 +11,11 @@ function generateSeedMigration({ models, meta }) {
11
11
  const modelTypes = [];
12
12
  for (const model of models) {
13
13
  const modelMeta = (0, meta_1.getModelMetadata)({ model });
14
- imports.addImport({
15
- items: [modelMeta.seed.constantName],
16
- from: modelMeta.seed.filePath,
14
+ imports.addImports({
15
+ [modelMeta.seed.filePath]: [modelMeta.seed.constantName],
16
+ [meta.importExport.importPath]: [meta.importExport.converterFunctions.importedDataToBulkMutations],
17
17
  });
18
- modelTypes.push(`${modelMeta.seed.constantName}: { create: ${modelMeta.seed.constantName} }`);
18
+ modelTypes.push(`${modelMeta.seed.constantName}`);
19
19
  }
20
20
  return /* ts */ `
21
21
  import { createActionSeedData } from '${meta.seed.importPath}'
@@ -24,11 +24,10 @@ ${imports.generate()}
24
24
  export const MIGRATION_001_BASEDATA = createActionSeedData({
25
25
  name: 'Base data',
26
26
  order: 1,
27
- data: [
28
- {
27
+ data: ${meta.importExport.converterFunctions.importedDataToBulkMutations}({
29
28
  ${modelTypes.join(',\n')}
30
29
  },
31
- ],
30
+ ),
32
31
  })
33
32
  `;
34
33
  }
@@ -10,6 +10,9 @@ const imports_1 = require("../../../lib/imports");
10
10
  function generateModelLibraryComponents({ model, meta }) {
11
11
  const { react: { context, components }, } = meta;
12
12
  const selectorCollector = id_collector_1.SelectorCollector.from(meta.seed.constantName + '-card');
13
+ const titleProp = model.nameField.isRequired
14
+ ? `title={item.${model.nameField.name}}`
15
+ : `title={item.${model.nameField.name} ?? item.${model.idField.name}}`;
13
16
  const imports = imports_1.ImportsGenerator.from(meta.react.folderPath)
14
17
  .addTypeImport({
15
18
  items: [model.typeName],
@@ -52,7 +55,7 @@ function generateModelLibraryComponents({ model, meta }) {
52
55
  <>
53
56
  <Card
54
57
  ref={forwardedRef}
55
- title={item.${model.nameField.name}}
58
+ ${titleProp}
56
59
  actions={[
57
60
  {
58
61
  label: 'Edit',
@@ -20,7 +20,9 @@ function generateModelLookupComponents({ model, meta }) {
20
20
  });
21
21
  const typeName = model.typeName;
22
22
  const tsOmittedFields = `'label' | 'options' | 'loading'`;
23
- const reactLabelField = `label={(l) => l.${model.nameField.name}}`;
23
+ const labelProp = model.nameField.isRequired
24
+ ? `label={(l) => l.${model.nameField.name}}`
25
+ : `label={(l) => l.${model.nameField.name} ?? l.${model.idField.name}}`;
24
26
  let description = '';
25
27
  if (model.description) {
26
28
  description = `
@@ -50,7 +52,7 @@ export const ${components.forms.selectInputName} = ({
50
52
  const { list, ready } = ${context.hookFnName}()
51
53
  return <SelectInput<${typeName}>
52
54
  options={list}
53
- ${reactLabelField}
55
+ ${labelProp}
54
56
  loading={!ready}
55
57
  __cypress_field_selector__={
56
58
  delegated.__cypress_field_selector__
@@ -67,7 +69,7 @@ export const ${components.forms.selectFieldName} = ({
67
69
  const { list, ready } = ${context.hookFnName}()
68
70
  return <SelectField<${typeName}>
69
71
  options={list}
70
- ${reactLabelField}
72
+ ${labelProp}
71
73
  loading={!ready}
72
74
  __cypress_field_selector__={
73
75
  delegated.__cypress_field_selector__
@@ -86,7 +88,7 @@ export const ${components.forms.menuSelectInputName} = ({
86
88
  const { list, ready } = ${context.hookFnName}()
87
89
  return <MenuSelectInput<${typeName}>
88
90
  options={list}
89
- ${reactLabelField}
91
+ ${labelProp}
90
92
  loading={!ready}
91
93
  __cypress_options_selector__={
92
94
  delegated.__cypress_options_selector__
@@ -103,7 +105,7 @@ export const ${components.forms.menuSelectFieldName} = ({
103
105
  const { list, ready } = ${context.hookFnName}()
104
106
  return <MenuSelectField<${typeName}>
105
107
  options={list}
106
- ${reactLabelField}
108
+ ${labelProp}
107
109
  loading={!ready}
108
110
  __cypress_options_selector__={
109
111
  delegated.__cypress_options_selector__
@@ -122,7 +124,7 @@ export const ${components.forms.searchInputName} = ({
122
124
  const { list, ready } = ${context.hookFnName}()
123
125
  return <SearchInput<${typeName}>
124
126
  options={list}
125
- ${reactLabelField}
127
+ ${labelProp}
126
128
  loading={!ready}
127
129
  __cypress_combobox_selector__={
128
130
  delegated.__cypress_combobox_selector__
@@ -143,7 +145,7 @@ export const ${components.forms.searchFieldName} = ({
143
145
  const { list, ready } = ${context.hookFnName}()
144
146
  return <SearchField<${typeName}>
145
147
  options={list}
146
- ${reactLabelField}
148
+ ${labelProp}
147
149
  loading={!ready}
148
150
  __cypress_combobox_selector__={
149
151
  delegated.__cypress_combobox_selector__
@@ -165,7 +167,7 @@ export const ${components.forms.tableSelectInputName} = ({
165
167
  const { list, ready } = ${context.hookFnName}()
166
168
  return <TableSelectInput<${typeName}>
167
169
  options={list}
168
- ${reactLabelField}
170
+ ${labelProp}
169
171
  loading={!ready}
170
172
  __cypress_input_field_selector__={
171
173
  delegated.__cypress_input_field_selector__
@@ -182,7 +184,7 @@ export const ${components.forms.tableSelectFieldName} = ({
182
184
  const { list, ready } = ${context.hookFnName}()
183
185
  return <TableSelectField<${typeName}>
184
186
  options={list}
185
- ${reactLabelField}
187
+ ${labelProp}
186
188
  loading={!ready}
187
189
  __cypress_input_field_selector__={
188
190
  delegated.__cypress_input_field_selector__
@@ -3,10 +3,11 @@ import { Model, SchemaConfig } from '../../lib/schema/schema';
3
3
  /**
4
4
  * Creates a seed file for a given model.
5
5
  */
6
- export declare function generateSeedModel({ model, itemCount, meta, }: {
6
+ export declare function generateSeedModel({ model, itemCount, meta, models, }: {
7
7
  model: Model;
8
8
  itemCount: number;
9
9
  meta: ModelMetaData;
10
+ models: Model[];
10
11
  }): string;
11
12
  /**
12
13
  * Creates the seed file that exposes all seed data as single object.
@@ -12,11 +12,15 @@ const string_1 = require("../../lib/utils/string");
12
12
  /**
13
13
  * Creates a seed file for a given model.
14
14
  */
15
- function generateSeedModel({ model, itemCount, meta, }) {
15
+ function generateSeedModel({ model, itemCount, meta, models, }) {
16
16
  var _a;
17
17
  // NOTE: We seed `faker` independently for each model.
18
18
  // This way changes to another model or to the ordering of models in the schema doesn't impact the generated values.
19
19
  faker_1.faker.seed((_a = model.attributes.randomSeed) !== null && _a !== void 0 ? _a : 0);
20
+ const modelMap = new Map();
21
+ for (const model of models) {
22
+ modelMap.set(model.name, model);
23
+ }
20
24
  const imports = imports_1.ImportsGenerator.from(meta.seed.filePath).addImport({
21
25
  items: [(0, types_1.toAnnotatedTypeName)(model.typeName), meta.types.toBrandedIdTypeFnName],
22
26
  from: meta.types.importPath,
@@ -33,7 +37,7 @@ function generateSeedModel({ model, itemCount, meta, }) {
33
37
  const mode = getExampleMode({ model, maxItemCount: itemCount });
34
38
  const examples = [];
35
39
  for (let i = 1; i <= mode.itemCount; i++) {
36
- examples.push(generateExample({ model, index: i, mode }));
40
+ examples.push(generateExample({ model, index: i, mode, models: modelMap }));
37
41
  }
38
42
  return `
39
43
  ${imports.generate()}
@@ -57,7 +61,7 @@ function getExampleMode({ model, maxItemCount }) {
57
61
  field.attributes.examples.length > 0) {
58
62
  if (numberOfExamplesPerField === undefined) {
59
63
  numberOfExamplesPerField = field.attributes.examples.length;
60
- numberOfAllPossiblePermutations = 1;
64
+ numberOfAllPossiblePermutations = field.attributes.examples.length;
61
65
  }
62
66
  else if (numberOfExamplesPerField !== field.attributes.examples.length) {
63
67
  sameNumberOfExamplesPerField = false;
@@ -73,23 +77,23 @@ function getExampleMode({ model, maxItemCount }) {
73
77
  }
74
78
  return { kind: 'Permutations', itemCount: Math.min(numberOfAllPossiblePermutations, maxItemCount) };
75
79
  }
76
- function generateExample({ model, index, mode }) {
80
+ function generateExample({ model, index, mode, models, }) {
77
81
  const data = new serializer_1.Serializer();
78
82
  data.append('{');
79
83
  for (const field of model.fields.values()) {
80
- data.append(`${field.name}: ${generateFieldData({ field, model, index, mode })},`);
84
+ data.append(`${field.name}: ${generateFieldData({ field, model, index, mode, models })},`);
81
85
  }
82
86
  data.append('}');
83
87
  return data.print();
84
88
  }
85
- function generateFieldData({ field, model, index, mode, }) {
89
+ function generateFieldData({ field, model, index, mode, models, }) {
86
90
  switch (field.kind) {
87
91
  case 'id':
88
92
  return generateIdFieldExample({ field, model, index, mode });
89
93
  case 'scalar':
90
94
  return generateScalarFieldExample({ field, model, index, mode });
91
95
  case 'relation':
92
- return generateRelationFieldExample({ field, model, index, mode });
96
+ return generateRelationFieldExample({ field, model, index, mode, models });
93
97
  case 'enum':
94
98
  return generateEnumFieldExample({ field, mode, index });
95
99
  default:
@@ -215,14 +219,24 @@ function generateMockDate() {
215
219
  d.setUTCHours(0, 0, 0, 0);
216
220
  return `new Date('${d.toISOString()}')`;
217
221
  }
218
- function generateRelationFieldExample({ field, index, model, mode, }) {
222
+ function generateRelationFieldExample({ field, index, model, mode, models, }) {
219
223
  if (!field.isRequired) {
220
224
  return 'null';
221
225
  }
222
- const referenceId = faker_1.faker.datatype.number({ min: 1, max: mode.itemCount });
223
- const refModelMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
226
+ const refModel = models.get(field.relationToModel.name);
227
+ if (!refModel) {
228
+ throw new Error(`Could not find model ${field.relationToModel.name}`);
229
+ }
230
+ const refModelMeta = (0, meta_1.getModelMetadata)({ model: refModel });
231
+ const refModelExampleMode = getExampleMode({ model: refModel, maxItemCount: mode.itemCount });
232
+ const referenceId = faker_1.faker.datatype.number({ min: 1, max: refModelExampleMode.itemCount });
224
233
  const brandingFn = refModelMeta.types.toBrandedIdTypeFnName;
225
- const { hasExample, example } = generateFieldExample({ field, model, index, mode });
234
+ const { hasExample, example } = generateFieldExample({
235
+ field: refModel.idField,
236
+ model: refModel,
237
+ index,
238
+ mode: refModelExampleMode,
239
+ });
226
240
  if (field.unbrandedTypeName === 'string') {
227
241
  if (hasExample && typeof example === 'string') {
228
242
  return `${brandingFn}('${quoteSingleQuote(example)}')`;
@@ -158,6 +158,8 @@ function parseModel({ dmmfModel, enums, models, config, }) {
158
158
  if (dmmfField.relationOnDelete && dmmfField.relationOnDelete !== 'NoAction') {
159
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!`);
160
160
  }
161
+ // Note: At this point, we only have the `ModelCore`. After all models are parsed, we need to updated
162
+ // the relations with the full `Model`. This is done in the `linkModels` function.
161
163
  relations[dmmfField.relationFromFields[0]] = referencedModel;
162
164
  }
163
165
  const relationFields = dmmfModel.fields
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postxl/generator",
3
- "version": "0.47.0",
3
+ "version": "0.47.2",
4
4
  "main": "./dist/generator.js",
5
5
  "typings": "./dist/generator.d.ts",
6
6
  "bin": {