@postxl/generator 0.25.0 → 0.26.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.
@@ -114,6 +114,7 @@ function generateModelBusinessLogic({ model, meta }) {
114
114
  return item
115
115
  }
116
116
  `;
117
+ // prettier-ignore
117
118
  return `
118
119
  import { Inject, Injectable, forwardRef } from '@nestjs/common'
119
120
  import { FilterOperator } from '@pxl/common'
@@ -169,18 +170,14 @@ export class ${meta.businessLogic.serviceClassName} {
169
170
  /**
170
171
  * Creates a new ${meta.userFriendlyName}.
171
172
  */
172
- public async create(item: Omit<${model.typeName}, '${model.idField.name}'> & Partial<{
173
- ${model.idField.name}: ${model.idField.unbrandedTypeName}
174
- }>): Promise<${model.typeName}> {
173
+ public async create(item: Omit<${model.typeName}, '${model.idField.name}'> & Partial<{${model.idField.name}: ${model.idField.unbrandedTypeName}}>): Promise<${model.typeName}> {
175
174
  return this.${modelRepositoryVariableName}.create(item)
176
175
  }
177
176
 
178
177
  /**
179
178
  * Updates the given ${meta.userFriendlyName}.
180
179
  */
181
- public async update(item: Partial<${model.typeName}> & {
182
- id: ${model.brandedIdType}
183
- }): Promise<${model.typeName}> {
180
+ public async update(item: Partial<${model.typeName}> & {id: ${model.brandedIdType}}): Promise<${model.typeName}> {
184
181
  return this.${modelRepositoryVariableName}.update(item)
185
182
  }
186
183
 
@@ -48,12 +48,35 @@ type CreateInputData = {
48
48
  * A modal component that lets the user create a new ${meta.userFriendlyName} instance.
49
49
  */
50
50
  export const ${modals.createComponentName} = ({ show, onHide }: { show: boolean; onHide: () => void }) => {
51
+ const Typed = React.useMemo(
52
+ () => createTypedForm<CreateInputData>().with({ ${(() => {
53
+ const components = new Set();
54
+ for (const field of fields.values()) {
55
+ switch (field.kind) {
56
+ case 'enum': {
57
+ const enumMeta = (0, meta_1.getEnumMetadata)({ enumerator: field.enumerator });
58
+ components.add(enumMeta.react.selectFieldName);
59
+ break;
60
+ }
61
+ case 'relation': {
62
+ const refMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
63
+ components.add(refMeta.react.components.forms.searchFieldName);
64
+ break;
65
+ }
66
+ default:
67
+ continue;
68
+ }
69
+ }
70
+ return [...components].join(', ');
71
+ })()} }),
72
+ []
73
+ )
51
74
  const cache = trpc.useContext()
52
75
  const mutation = trpc.${trpc.create.reactQueryMethod}.useMutation()
53
76
 
54
77
  return (
55
78
  <ModalWithNavigationContainer label="Create new ${meta.userFriendlyName}" show={show} onHide={onHide} fixed wide>
56
- <Formik<CreateInputData>
79
+ <Typed.Formik
57
80
  initialValues={{
58
81
  ${fields
59
82
  .filter((f) => f.kind !== 'id')
@@ -109,7 +132,7 @@ export const ${modals.createComponentName} = ({ show, onHide }: { show: boolean;
109
132
  ${getFormFieldComponents({ model })}
110
133
  </ModalWithActions>
111
134
  )}
112
- </Formik>
135
+ </Typed.Formik>
113
136
  </ModalWithNavigationContainer>
114
137
  )
115
138
  }
@@ -141,12 +164,35 @@ export const ${components.modals.editComponentName} = ({
141
164
  show,
142
165
  onHide
143
166
  }: { data: ${model.typeName}; show: boolean; onHide: () => void }) => {
167
+ const Typed = React.useMemo(
168
+ () => createTypedForm<EditInputData>().with({ ${(() => {
169
+ const components = new Set();
170
+ for (const field of fields.values()) {
171
+ switch (field.kind) {
172
+ case 'enum': {
173
+ const enumMeta = (0, meta_1.getEnumMetadata)({ enumerator: field.enumerator });
174
+ components.add(enumMeta.react.selectFieldName);
175
+ break;
176
+ }
177
+ case 'relation': {
178
+ const refMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
179
+ components.add(refMeta.react.components.forms.searchFieldName);
180
+ break;
181
+ }
182
+ default:
183
+ continue;
184
+ }
185
+ }
186
+ return [...components].join(', ');
187
+ })()} }),
188
+ []
189
+ )
144
190
  const cache = trpc.useContext()
145
191
  const mutation = trpc.${trpc.update.reactQueryMethod}.useMutation()
146
192
 
147
193
  return (
148
194
  <ModalWithNavigationContainer label="Edit ${meta.userFriendlyName}" show={show} onHide={onHide} fixed wide>
149
- <Formik<EditInputData>
195
+ <Typed.Formik
150
196
  initialValues={{
151
197
  ${fields
152
198
  .map((field) => {
@@ -213,7 +259,7 @@ export const ${components.modals.editComponentName} = ({
213
259
  ${getFormFieldComponents({ model })}
214
260
  </ModalWithActions>
215
261
  )}
216
- </Formik>
262
+ </Typed.Formik>
217
263
  </ModalWithNavigationContainer>
218
264
  )
219
265
  }
@@ -323,13 +369,10 @@ function getFormImports({ model, meta }) {
323
369
  return `
324
370
  import React from 'react'
325
371
  import { toast } from 'react-hot-toast'
326
- import { Formik, FormikErrors } from 'formik'
372
+ import { FormikErrors } from 'formik'
327
373
 
328
- import { CheckBoxField } from '@components/atoms/CheckBoxInput'
374
+ import { createTypedForm } from '@components/atoms/Form'
329
375
  import { ConfirmButton, ModalWithNavigationContainer, Label, ModalWithActions } from '@components/atoms/Modal'
330
- import { TextAreaField } from '@components/atoms/TextAreaInput'
331
- import { TextField } from '@components/atoms/TextInput'
332
- import { NumberField } from '@components/atoms/NumberInput'
333
376
 
334
377
  import { trpc } from '@lib/trpc'
335
378
 
@@ -491,7 +534,7 @@ function getFormFieldComponents({ model }) {
491
534
  form.append(`
492
535
  <div>
493
536
  <Label>${label}</Label>
494
- <TextField placeholder="Type..." name="${formikFieldName}" />
537
+ <Typed.TextField placeholder="Type..." name="${formikFieldName}" />
495
538
  </div>
496
539
  `);
497
540
  break scalar;
@@ -504,7 +547,7 @@ function getFormFieldComponents({ model }) {
504
547
  form.append(`
505
548
  <div>
506
549
  <Label>${label}</Label>
507
- <NumberField placeholder="2511" name="${formikFieldName}" decimals={${decimals}}/>
550
+ <Typed.NumberField placeholder="2511" name="${formikFieldName}" decimals={${decimals}}/>
508
551
  </div>
509
552
  `);
510
553
  break scalar;
@@ -513,7 +556,7 @@ function getFormFieldComponents({ model }) {
513
556
  form.append(`
514
557
  <div>
515
558
  <Label>Is ${label}</Label>
516
- <CheckBoxField label="${label}" name="${formikFieldName}" />
559
+ <Typed.CheckBoxField label="${label}" name="${formikFieldName}" />
517
560
  </div>
518
561
  `);
519
562
  break scalar;
@@ -534,7 +577,7 @@ function getFormFieldComponents({ model }) {
534
577
  form.append(`
535
578
  <div>
536
579
  <Label>${refMeta.userFriendlyName}</Label>
537
- <${refMeta.react.components.forms.searchFieldName} name="${formikFieldName}" placeholder="Search..." />
580
+ <Typed.${refMeta.react.components.forms.searchFieldName} name="${formikFieldName}" placeholder="Search..." />
538
581
  </div>
539
582
  `);
540
583
  break;
@@ -544,7 +587,7 @@ function getFormFieldComponents({ model }) {
544
587
  form.append(`
545
588
  <div>
546
589
  <Label>${label}</Label>
547
- <${enumMeta.react.selectFieldName} name="${formikFieldName}" placeholder="Search..." />
590
+ <Typed.${enumMeta.react.selectFieldName} name="${formikFieldName}" placeholder="Search..." />
548
591
  </div>
549
592
  `);
550
593
  break;
@@ -210,12 +210,11 @@ function generateMainBuildingBlocks_InMemoryOnly({ model, meta, blocks, }) {
210
210
  public async deleteAll(): Promise<void> {
211
211
  return this.init()
212
212
  }`,
213
+ // prettier-ignore
213
214
  createCode: `
214
215
  // Non-mocked version is async - so we keep type-compatible signatures for create() and createWithId()
215
216
  // eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars
216
- public async create(item: Omit<${model.typeName}, '${idField.name}'> & Partial<{
217
- id: ${idField.unbrandedTypeName}
218
- }>): Promise<${model.typeName}> {
217
+ public async create(item: Omit<${model.typeName}, '${idField.name}'> & Partial<{id: ${idField.unbrandedTypeName}}>): Promise<${model.typeName}> {
219
218
  const newItem = await Promise.resolve(this.verifyItem(item))
220
219
 
221
220
  this.set(newItem)
@@ -327,10 +326,9 @@ function generateMainBuildingBlocks_InDatabase({ model, meta, imports, blocks, }
327
326
  return this.init()
328
327
  }
329
328
  `,
329
+ // prettier-ignore
330
330
  createCode: `
331
- public async create(item: Omit<${model.typeName}, '${idField.name}'> & Partial<{
332
- id: ${idField.unbrandedTypeName}
333
- }>): Promise<${model.typeName}> {
331
+ public async create(item: Omit<${model.typeName}, '${idField.name}'> & Partial<{ id: ${idField.unbrandedTypeName} }>): Promise<${model.typeName}> {
334
332
  const newItem = this.${decoderFunctionName}(
335
333
  await this.db.${meta.data.repository.getMethodFnName}.create({
336
334
  data: this.toCreateItem(this.verifyItem(item)),
@@ -352,16 +350,14 @@ function generateMainBuildingBlocks_InDatabase({ model, meta, imports, blocks, }
352
350
 
353
351
  return newItems
354
352
  }`,
353
+ // prettier-ignore
355
354
  updateCode: `
356
- public async update(item: Partial<${model.typeName}> & {
357
- id: ${model.brandedIdType}
358
- }): Promise<${model.typeName}> {
355
+ public async update(item: Partial<${model.typeName}> & { id: ${model.brandedIdType}}): Promise<${model.typeName}> {
359
356
  const existingItem = this.get(item.id)
360
357
 
361
358
  if (!existingItem) {
362
359
  throw new Error(\`Could not update ${meta.userFriendlyName} with id \${item.id}. Not found!\`)
363
360
  }
364
-
365
361
 
366
362
  ${blocks.maxLength.updateCode.join('\n')}
367
363
 
@@ -443,10 +439,10 @@ function generateIdBlocks_NoGeneration({ idField, model, meta, }) {
443
439
  verifyFunctionComment: `an error is thrown as field has no default setting in schema.`,
444
440
  verifyFunctionParameterType: model.typeName,
445
441
  verifyCode: `
446
- if (item.${idField.name} === undefined) {
447
- throw new Error('Id field ${idField.name} is required!')
448
- }
449
- const ${idField.name} = ${meta.types.toBrandedIdTypeFnName}(item.${idField.name})`,
442
+ if (item.${idField.name} === undefined) {
443
+ throw new Error('Id field ${idField.name} is required!')
444
+ }
445
+ const ${idField.name} = ${meta.types.toBrandedIdTypeFnName}(item.${idField.name})`,
450
446
  setCode: '',
451
447
  };
452
448
  }
@@ -458,10 +454,10 @@ function generateIdBlock_Int({ idField, model, meta, imports, }) {
458
454
  return {
459
455
  libraryImports: '',
460
456
  generateNextIdFunctionName: `
461
- protected currentMaxId = 0
462
- public generateNextId(): ${model.brandedIdType} {
463
- return ${meta.types.toBrandedIdTypeFnName}(++this.currentMaxId)
464
- }`,
457
+ protected currentMaxId = 0
458
+ public generateNextId(): ${model.brandedIdType} {
459
+ return ${meta.types.toBrandedIdTypeFnName}(++this.currentMaxId)
460
+ }`,
465
461
  initCode: `this.currentMaxId = (await this.db.${meta.data.repository.getMethodFnName}.aggregate({ _max: { ${idField.sourceName}: true } }))._max.${idField.sourceName} ?? 0`,
466
462
  verifyFunctionComment: 'the id is generated by increasing the highest former id and assigned to the item.',
467
463
  verifyFunctionParameterType: `(Omit<${model.typeName}, '${idField.name}'> & Partial<{${idField.name}: ${idField.unbrandedTypeName}}>)`,
@@ -477,9 +473,9 @@ function generateIdBlock_UUID({ idField, model, meta, imports, }) {
477
473
  return {
478
474
  libraryImports: `import { randomUUID } from 'crypto'`,
479
475
  generateNextIdFunctionName: `
480
- public generateNextId(): ${model.brandedIdType} {
481
- return ${meta.types.toBrandedIdTypeFnName}(randomUUID())
482
- }`,
476
+ public generateNextId(): ${model.brandedIdType} {
477
+ return ${meta.types.toBrandedIdTypeFnName}(randomUUID())
478
+ }`,
483
479
  initCode: '',
484
480
  verifyFunctionComment: 'a new UUID is generated and assigned to the item.',
485
481
  verifyFunctionParameterType: `(Omit<${model.typeName}, '${idField.name}'> & Partial<{${idField.name}: ${idField.unbrandedTypeName}}>)`,
@@ -689,24 +685,25 @@ function generateRelationsBlocks({ model, imports, }) {
689
685
  from: relationModelMeta.types.importPath,
690
686
  });
691
687
  result.mapDeclarations.push(`protected ${r.name}Map: Map<${relationModelMeta.types.brandedIdType}, Map<${model.brandedIdType}, ${model.typeName}>> = new Map()`);
688
+ // prettier-ignore
692
689
  result.getterFunctions.push(`
693
- /**
694
- * Function to retrieve all ${(0, string_1.pluralize)(model.name)} that are related to a ${r.name}
695
- */
696
- public ${fieldMeta.getByForeignKeyMethodFnName}(id: ${relationModelMeta.types.brandedIdType}): Map<${model.brandedIdType},${model.typeName}> {
697
- const result = this.${r.name}Map.get(id)
698
- if (!result) return new Map()
699
- return result
700
- }
690
+ /**
691
+ * Function to retrieve all ${(0, string_1.pluralize)(model.name)} that are related to a ${r.name}
692
+ */
693
+ public ${fieldMeta.getByForeignKeyMethodFnName}(id: ${relationModelMeta.types.brandedIdType}): Map<${model.brandedIdType}, ${model.typeName}> {
694
+ const result = this.${r.name}Map.get(id)
695
+ if (!result) return new Map()
696
+ return result
697
+ }
701
698
 
702
- /**
703
- * Function to retrieve all ${model.brandedIdType}s that are related to a ${r.name}
704
- */
705
- public ${fieldMeta.getByForeignKeyIdsMethodFnName}(id: ${relationModelMeta.types.brandedIdType}): ${model.brandedIdType}[] {
706
- const s = this.${r.name}Map.get(id)
707
- if (!s) return []
708
- return Array.from(s.keys())
709
- }`);
699
+ /**
700
+ * Function to retrieve all ${model.brandedIdType}s that are related to a ${r.name}
701
+ */
702
+ public ${fieldMeta.getByForeignKeyIdsMethodFnName}(id: ${relationModelMeta.types.brandedIdType}): ${model.brandedIdType}[] {
703
+ const s = this.${r.name}Map.get(id)
704
+ if (!s) return []
705
+ return Array.from(s.keys())
706
+ }`);
710
707
  result.setCode.push(`
711
708
  ${!r.isRequired ? `if (item.${r.name}) {` : ''}
712
709
  let ${r.name}Map = this.${r.name}Map.get(item.${r.name})
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postxl/generator",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "main": "./dist/generator.js",
5
5
  "typings": "./dist/generator.d.ts",
6
6
  "bin": {