@postxl/generator 0.4.0 → 0.5.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.
@@ -11,9 +11,9 @@ function generateRepositoriesIndex({ models, meta }) {
11
11
  const exports = exports_1.ExportsGenerator.from(meta.data.repositoriesIndexFilePath);
12
12
  for (const model of models) {
13
13
  const meta = (0, meta_1.getModelMetadata)({ model });
14
- exports.exportEverythingFrom(meta.data.repoFilePath);
14
+ exports.exportEverythingFromPath(meta.data.repoFilePath);
15
15
  }
16
- exports.exportEverythingFrom(meta.data.repositoriesConstFilePath);
16
+ exports.exportEverythingFromPath(meta.data.repositoriesConstFilePath);
17
17
  return exports.generate();
18
18
  }
19
19
  exports.generateRepositoriesIndex = generateRepositoriesIndex;
@@ -10,7 +10,7 @@ function generateSeedIndex({ models, meta }) {
10
10
  const exports = exports_1.ExportsGenerator.from(meta.seed.indexFilePath);
11
11
  for (const model of models) {
12
12
  const meta = (0, meta_1.getModelMetadata)({ model });
13
- exports.exportEverythingFrom(meta.seed.filePath);
13
+ exports.exportEverythingFromPath(meta.seed.filePath);
14
14
  }
15
15
  return exports.generate();
16
16
  }
@@ -10,7 +10,7 @@ function generateStubsIndex({ models, meta }) {
10
10
  const exports = exports_1.ExportsGenerator.from(meta.data.stubIndexFilePath);
11
11
  for (const model of models) {
12
12
  const meta = (0, meta_1.getModelMetadata)({ model });
13
- exports.exportEverythingFrom(meta.data.stubFilePath);
13
+ exports.exportEverythingFromPath(meta.data.stubFilePath);
14
14
  }
15
15
  return exports.generate();
16
16
  }
@@ -10,11 +10,11 @@ function generateTypesIndex({ models, enums, meta, }) {
10
10
  const exports = exports_1.ExportsGenerator.from(meta.types.indexFilePath);
11
11
  for (const model of models) {
12
12
  const meta = (0, meta_1.getModelMetadata)({ model });
13
- exports.exportEverythingFrom(meta.types.filePath);
13
+ exports.exportEverythingFromPath(meta.types.filePath);
14
14
  }
15
15
  for (const enumerator of enums) {
16
16
  const meta = (0, meta_1.getEnumMetadata)({ enumerator });
17
- exports.exportEverythingFrom(meta.types.filePath);
17
+ exports.exportEverythingFromPath(meta.types.filePath);
18
18
  }
19
19
  return exports.generate();
20
20
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateReactComponentsForModel = void 0;
4
+ const exports_1 = require("../../../lib/exports");
4
5
  const vfs_1 = require("../../../lib/vfs");
5
6
  const context_generator_1 = require("./context.generator");
6
7
  const library_generator_1 = require("./library.generator");
@@ -10,23 +11,27 @@ const modals_generator_1 = require("./modals.generator");
10
11
  * Generates generic React components for a given model.
11
12
  */
12
13
  function generateReactComponentsForModel({ model, meta }) {
13
- const vfs = new vfs_1.VirtualFS({
14
- '/index.ts': `
15
- export * from './CreateModal'
16
- export * from './EditModal'
17
- export * from './DeleteModal'
18
-
19
- export * from './Form'
20
- export * from './context'
21
- export * from './Library'
22
- `,
23
- });
14
+ const vfs = new vfs_1.VirtualFS({});
15
+ const exports = exports_1.ExportsGenerator.fromRoot()
16
+ .exportEverythingFromFile('./CreateModal')
17
+ .exportEverythingFromFile('./EditModal')
18
+ .exportEverythingFromFile('./DeleteModal')
19
+ .exportEverythingFromFile('./Form')
20
+ .exportEverythingFromFile('./context');
24
21
  vfs.write(`/context.tsx`, (0, context_generator_1.generateModelContext)({ model, meta }));
25
22
  vfs.write(`/CreateModal.tsx`, (0, modals_generator_1.generateModelCreateModalComponent)({ model, meta }));
26
23
  vfs.write(`/EditModal.tsx`, (0, modals_generator_1.generateEditModalModelComponent)({ model, meta }));
27
24
  vfs.write(`/DeleteModal.tsx`, (0, modals_generator_1.generateDeleteModalModelComponent)({ model, meta }));
28
25
  vfs.write(`/Form.tsx`, (0, lookup_generator_1.generateModelLookupComponents)({ model, meta }));
29
- vfs.write(`/Library.tsx`, (0, library_generator_1.generateModelLibraryComponents)({ model, meta }));
26
+ // NOTE: library generator expects that the model has a `name` field.
27
+ // Make sure that you don't make a dependency on this
28
+ // component without checking that a model has a name field.
29
+ const hasNameField = model.nameField != null;
30
+ if (hasNameField) {
31
+ vfs.write(`/Library.tsx`, (0, library_generator_1.generateModelLibraryComponents)({ model, meta }));
32
+ exports.exportEverythingFromFile('./Library');
33
+ }
34
+ vfs.write(`/index.ts`, exports.generate());
30
35
  return vfs;
31
36
  }
32
37
  exports.generateReactComponentsForModel = generateReactComponentsForModel;
@@ -2,6 +2,9 @@ import { ModelMetaData } from '../../../lib/meta';
2
2
  import { Model } from '../../../lib/schema/schema';
3
3
  /**
4
4
  * Generates components that may be used to list all entries of a given data type.
5
+ *
6
+ * NOTE: Library expects that the model has a `name` field. Make sure that you don't make a dependency on
7
+ * this component without checking that a model has a name field.
5
8
  */
6
9
  export declare function generateModelLibraryComponents({ model, meta }: {
7
10
  model: Model;
@@ -6,6 +6,9 @@ const fields_1 = require("../../../lib/schema/fields");
6
6
  const imports_1 = require("../../../lib/imports");
7
7
  /**
8
8
  * Generates components that may be used to list all entries of a given data type.
9
+ *
10
+ * NOTE: Library expects that the model has a `name` field. Make sure that you don't make a dependency on
11
+ * this component without checking that a model has a name field.
9
12
  */
10
13
  function generateModelLibraryComponents({ model, meta }) {
11
14
  const { react: { context, components }, } = meta;
@@ -17,6 +17,11 @@ function generateModelLookupComponents({ model, meta }) {
17
17
  from: meta.types.importPath,
18
18
  });
19
19
  const typeName = model.typeName;
20
+ // NOTE: Depending on the model definition - whether it has a `name` field or not - we'll either
21
+ // auto-populate the `label` property or not.
22
+ const hasNameField = model.nameField != null;
23
+ const tsOmittedFields = hasNameField ? `'label' | 'options' | 'loading'` : `'options' | 'loading'`;
24
+ const reactLabelField = hasNameField ? `label={(l) => l.name}` : '';
20
25
  return `
21
26
  import React, { useMemo } from 'react'
22
27
 
@@ -34,63 +39,63 @@ ${imports.generate()}
34
39
 
35
40
  export const ${components.forms.selectInputName} = ({
36
41
  ...delegated
37
- }: UnionOmit<React.ComponentPropsWithoutRef<typeof SelectInput<${typeName}>>, 'label' | 'options' | 'loading'>) => {
42
+ }: UnionOmit<React.ComponentPropsWithoutRef<typeof SelectInput<${typeName}>>, ${tsOmittedFields}>) => {
38
43
  const { list, ready } = ${context.hookFnName}()
39
- return <SelectInput<${typeName}> options={list} label={(l) => l.name} loading={!ready} {...delegated} />
44
+ return <SelectInput<${typeName}> options={list} ${reactLabelField} loading={!ready} {...delegated} />
40
45
  }
41
46
 
42
47
  export const ${components.forms.selectFieldName} = ({
43
48
  ...delegated
44
- }: Omit<React.ComponentPropsWithoutRef<typeof SelectField<${typeName}>>, 'label' | 'options' | 'loading'>) => {
49
+ }: Omit<React.ComponentPropsWithoutRef<typeof SelectField<${typeName}>>, ${tsOmittedFields}>) => {
45
50
  const { list, ready } = ${context.hookFnName}()
46
- return <SelectField<${typeName}> options={list} label={(l) => l.name} loading={!ready} {...delegated} />
51
+ return <SelectField<${typeName}> options={list} ${reactLabelField} loading={!ready} {...delegated} />
47
52
  }
48
53
 
49
54
  // Menu Select
50
55
 
51
56
  export const ${components.forms.menuSelectInputName} = ({
52
57
  ...delegated
53
- }: UnionOmit<React.ComponentPropsWithoutRef<typeof MenuSelectInput<${typeName}>>, 'label' | 'options' | 'loading'>) => {
58
+ }: UnionOmit<React.ComponentPropsWithoutRef<typeof MenuSelectInput<${typeName}>>, ${tsOmittedFields}>) => {
54
59
  const { list, ready } = ${context.hookFnName}()
55
- return <MenuSelectInput<${typeName}> options={list} label={(l) => l.name} loading={!ready} {...delegated} />
60
+ return <MenuSelectInput<${typeName}> options={list} ${reactLabelField} loading={!ready} {...delegated} />
56
61
  }
57
62
 
58
63
  export const ${components.forms.menuSelectFieldName} = ({
59
64
  ...delegated
60
- }: UnionOmit<React.ComponentPropsWithoutRef<typeof MenuSelectField<${typeName}>>, 'label' | 'options' | 'loading'>) => {
65
+ }: UnionOmit<React.ComponentPropsWithoutRef<typeof MenuSelectField<${typeName}>>, ${tsOmittedFields}>) => {
61
66
  const { list, ready } = ${context.hookFnName}()
62
- return <MenuSelectField<${typeName}> options={list} label={(l) => l.name} loading={!ready} {...delegated} />
67
+ return <MenuSelectField<${typeName}> options={list} ${reactLabelField} loading={!ready} {...delegated} />
63
68
  }
64
69
 
65
70
  // Search
66
71
 
67
72
  export const ${components.forms.searchInputName} = ({
68
73
  ...delegated
69
- }: UnionOmit<React.ComponentPropsWithoutRef<typeof SearchInput<${typeName}>>, 'label' | 'options' | 'loading'>) => {
74
+ }: UnionOmit<React.ComponentPropsWithoutRef<typeof SearchInput<${typeName}>>, ${tsOmittedFields}>) => {
70
75
  const { list, ready } = ${context.hookFnName}()
71
- return <SearchInput<${typeName}> options={list} label={(l) => l.name} loading={!ready} {...delegated} />
76
+ return <SearchInput<${typeName}> options={list} ${reactLabelField} loading={!ready} {...delegated} />
72
77
  }
73
78
  export const ${components.forms.searchFieldName} = ({
74
79
  ...delegated
75
- }: Omit<React.ComponentPropsWithoutRef<typeof SearchField<${typeName}>>, 'label' | 'options' | 'loading'>) => {
80
+ }: Omit<React.ComponentPropsWithoutRef<typeof SearchField<${typeName}>>, ${tsOmittedFields}>) => {
76
81
  const { list, ready } = ${context.hookFnName}()
77
- return <SearchField<${typeName}> options={list} label={(l) => l.name} loading={!ready} {...delegated} />
82
+ return <SearchField<${typeName}> options={list} ${reactLabelField} loading={!ready} {...delegated} />
78
83
  }
79
84
 
80
85
  // Table
81
86
 
82
87
  export const ${components.forms.tableSelectInputName} = ({
83
88
  ...delegated
84
- }: UnionOmit<React.ComponentPropsWithoutRef<typeof TableSelectInput<${typeName}>>, 'label' | 'options' | 'loading'>) => {
89
+ }: UnionOmit<React.ComponentPropsWithoutRef<typeof TableSelectInput<${typeName}>>, ${tsOmittedFields}>) => {
85
90
  const { list, ready } = ${context.hookFnName}()
86
- return <TableSelectInput<${typeName}> options={list} label={(l) => l.name} loading={!ready} {...delegated} />
91
+ return <TableSelectInput<${typeName}> options={list} ${reactLabelField} loading={!ready} {...delegated} />
87
92
  }
88
93
 
89
94
  export const ${components.forms.tableSelectFieldName} = ({
90
95
  ...delegated
91
- }: UnionOmit<React.ComponentPropsWithoutRef<typeof TableSelectField<${typeName}>>, 'label' | 'options' | 'loading'>) => {
96
+ }: UnionOmit<React.ComponentPropsWithoutRef<typeof TableSelectField<${typeName}>>, ${tsOmittedFields}>) => {
92
97
  const { list, ready } = ${context.hookFnName}()
93
- return <TableSelectField<${typeName}> options={list} label={(l) => l.name} loading={!ready} {...delegated} />
98
+ return <TableSelectField<${typeName}> options={list} ${reactLabelField} loading={!ready} {...delegated} />
94
99
  }
95
100
  `;
96
101
  }
@@ -8,17 +8,32 @@ export declare class ExportsGenerator {
8
8
  * Path of the file we're generating exports for.
9
9
  */
10
10
  private _path;
11
- constructor({ path }: {
11
+ /**
12
+ * Tells whether this generator acts as a root.
13
+ */
14
+ private isRoot;
15
+ constructor({ path, isRoot }: {
12
16
  path: string;
17
+ isRoot?: boolean;
13
18
  });
14
19
  /**
15
20
  * Creates a new instance of the exports generator.
16
21
  */
17
22
  static from(path: Types.Path): ExportsGenerator;
23
+ /**
24
+ * Creates a new instance of the exports generator from this folder (i.e. every path is relative to this folder).
25
+ */
26
+ static fromRoot(): ExportsGenerator;
27
+ /**
28
+ * Adds a given file to the collection of files we're exporting everything from.
29
+ */
30
+ exportEverythingFromPath(from: Types.Path): ExportsGenerator;
18
31
  /**
19
32
  * Adds a given file to the collection of files we're exporting everything from.
33
+ *
34
+ * NOTE: This should only be used when the generator is a root generator.
20
35
  */
21
- exportEverythingFrom(from: Types.Path): ExportsGenerator;
36
+ exportEverythingFromFile(file: string): ExportsGenerator;
22
37
  /**
23
38
  * Returns the TypeScript export statements.
24
39
  */
@@ -6,9 +6,10 @@ const file_1 = require("./utils/file");
6
6
  * A utility component that lets you generate TypeScript export statements that export all items from a given file.
7
7
  */
8
8
  class ExportsGenerator {
9
- constructor({ path }) {
9
+ constructor({ path, isRoot }) {
10
10
  this._path = path;
11
11
  this._exports = new Set();
12
+ this.isRoot = isRoot !== null && isRoot !== void 0 ? isRoot : false;
12
13
  }
13
14
  /**
14
15
  * Creates a new instance of the exports generator.
@@ -16,14 +17,35 @@ class ExportsGenerator {
16
17
  static from(path) {
17
18
  return new ExportsGenerator({ path });
18
19
  }
20
+ /**
21
+ * Creates a new instance of the exports generator from this folder (i.e. every path is relative to this folder).
22
+ */
23
+ static fromRoot() {
24
+ return new ExportsGenerator({ path: './', isRoot: true });
25
+ }
19
26
  /**
20
27
  * Adds a given file to the collection of files we're exporting everything from.
21
28
  */
22
- exportEverythingFrom(from) {
29
+ exportEverythingFromPath(from) {
30
+ if (this.isRoot) {
31
+ throw new Error(`Cannot use "exportEverythingFromPath" on a root generator.`);
32
+ }
23
33
  const resolvedPath = (0, file_1.getRelativePath)({ from: this._path, to: from });
24
34
  this._exports.add(resolvedPath);
25
35
  return this;
26
36
  }
37
+ /**
38
+ * Adds a given file to the collection of files we're exporting everything from.
39
+ *
40
+ * NOTE: This should only be used when the generator is a root generator.
41
+ */
42
+ exportEverythingFromFile(file) {
43
+ if (!this.isRoot) {
44
+ throw new Error(`Cannot use "exportEverythingFromFile" on a non-root generator.`);
45
+ }
46
+ this._exports.add(file);
47
+ return this;
48
+ }
27
49
  /**
28
50
  * Returns the TypeScript export statements.
29
51
  */