@postxl/generator 0.15.5 → 0.15.7

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.
@@ -33,70 +33,90 @@ const Types = __importStar(require("../../lib/schema/types"));
33
33
  */
34
34
  function generateModelBusinessLogic({ model, meta }) {
35
35
  const imports = imports_1.ImportsGenerator.from(meta.businessLogic.serviceFilePath);
36
- const dependencies = new Map();
37
36
  imports.addImport({ from: meta.data.importPath, items: [meta.data.repositoryClassName] });
38
37
  imports.addImport({ from: meta.types.importPath, items: [model.brandedIdType, meta.types.typeName] });
39
- const dataRepositoryVariableName = Types.toVariableName('data');
40
- // Set of repositories (one for each referenced model) to be injected into the constructor.
41
- dependencies.set(meta.data.repositoryClassName, {
42
- repositoryClassName: meta.data.repositoryClassName,
43
- localRepositoryVariableName: dataRepositoryVariableName,
44
- });
45
- const linkedForeignBacklinkFields = new Map();
46
- // Converts each relationship to a variable that is pulled from the referenced model's repository - and validates
47
- // that it exists in case the relationship is required.
48
- // Variable definition and name of the variable is stored in a Map for each relationship - and is referenced in
49
- // the `getLinkedItem` function.
38
+ /**
39
+ * The name of the variable that holds the repository instance for the current model
40
+ * (e.g. when we generate business logic service for Aggregation, the AggregationRepository
41
+ * would be referenced using `this.data` variable).
42
+ */
43
+ const modelRepositoryVariableName = Types.toVariableName('data');
44
+ /**
45
+ * A map of referenced models indexed by the name of model's repository class.
46
+ */
47
+ const dependencies = new Map();
48
+ /**
49
+ * Variable names and their definitions indexed by the name of the relation they represent.
50
+ */
51
+ const variables = new Map();
50
52
  for (const relation of (0, fields_1.getRelationFields)(model)) {
51
53
  const refModel = relation.relationToModel;
52
54
  const refMeta = (0, meta_1.getModelMetadata)({ model: refModel });
53
55
  imports.addImport({ from: refMeta.data.importPath, items: [refMeta.data.repositoryClassName] });
54
- /**
55
- * Internal variable pointing to an instance of a referenced repository.
56
- */
57
- const repoReferenceName = relation.relationToModel.typeName !== model.typeName ? refMeta.internalPluralName : dataRepositoryVariableName;
58
- dependencies.set(refMeta.data.repositoryClassName, {
59
- localRepositoryVariableName: repoReferenceName,
60
- repositoryClassName: refMeta.data.repositoryClassName,
61
- });
62
- const variableDefinition = `
63
- const ${relation.relatedModelBacklinkFieldName} = this.${repoReferenceName}.get(itemRaw.${relation.name})
64
- ${!relation.isRequired
65
- ? ''
66
- : `if (!${relation.relatedModelBacklinkFieldName}) {
67
- throw new Error(\`Could not find ${refMeta.types.typeName} with id \${itemRaw.${relation.name}} for ${model.typeName}.${relation.name}!\`)
68
- }`}
69
- `;
70
- linkedForeignBacklinkFields.set(relation.name, {
71
- fieldName: relation.relatedModelBacklinkFieldName,
72
- variableDefinition,
73
- });
56
+ const variablePresenceCheck = `
57
+ if (!${relation.relatedModelBacklinkFieldName}) {
58
+ throw new Error(\`Could not find ${refMeta.types.typeName} with id \${itemRaw.${relation.name}} for ${model.typeName}.${relation.name}!\`)
59
+ }
60
+ `;
61
+ const relationVariableName = relation.relatedModelBacklinkFieldName;
62
+ if (relation.relationToModel.typeName === model.typeName) {
63
+ // NOTE: If the referenced model is a self-relation, we want to reuse the instance of the repository
64
+ // that is already injected into the constructor meaning that we don't need to set up a dependency and a local variable.
65
+ variables.set(relation.name, {
66
+ variableName: relationVariableName,
67
+ variableDefinition: `
68
+ const ${relationVariableName} = this.data.get(itemRaw.${relation.name})
69
+ ${relation.isRequired ? variablePresenceCheck : ``}
70
+ `,
71
+ });
72
+ }
73
+ else {
74
+ const refRepoVariableName = refMeta.internalPluralName;
75
+ dependencies.set(refMeta.data.repositoryClassName, {
76
+ localRepositoryVariableName: refRepoVariableName,
77
+ repositoryClassName: refMeta.data.repositoryClassName,
78
+ });
79
+ variables.set(relation.name, {
80
+ variableName: relationVariableName,
81
+ variableDefinition: `
82
+ const ${relationVariableName} = this.${refRepoVariableName}.get(itemRaw.${relation.name})
83
+ ${relation.isRequired ? variablePresenceCheck : ``}
84
+ `,
85
+ });
86
+ }
74
87
  }
75
- const hasLinkedItems = linkedForeignBacklinkFields.size > 0;
88
+ const hasLinkedItems = variables.size > 0;
76
89
  if (hasLinkedItems) {
77
90
  imports.addImport({ from: meta.types.importPath, items: [meta.types.linkedTypeName] });
78
91
  }
79
- const constructorParameters = [...dependencies.values()].map(({ localRepositoryVariableName, repositoryClassName }) => `private readonly ${localRepositoryVariableName}: ${repositoryClassName}`);
92
+ const constructorParameters = [`public readonly ${modelRepositoryVariableName}: ${meta.data.repositoryClassName}`];
93
+ for (const [, { localRepositoryVariableName, repositoryClassName }] of dependencies) {
94
+ constructorParameters.push(`private readonly ${localRepositoryVariableName}: ${repositoryClassName}`);
95
+ }
80
96
  const linkedItemsGetterFn = `
81
97
  /**
82
98
  * Returns the linked ${meta.userFriendlyName} with the given id or null if it does not exist.
83
99
  * Linked: The ${meta.userFriendlyName} contains the linked (raw) items themselves, not only the ids.
84
100
  */
85
101
  public getLinkedItem(id: ${model.brandedIdType}): ${meta.types.linkedTypeName} | null {
86
- const itemRaw = this.${dataRepositoryVariableName}.get(id)
87
- if (!itemRaw) return null
88
- ${[...linkedForeignBacklinkFields.values()].map(({ variableDefinition }) => variableDefinition).join('\n')}
102
+ const itemRaw = this.${modelRepositoryVariableName}.get(id)
103
+ if (!itemRaw) {
104
+ return null
105
+ }
106
+
107
+ ${[...variables.values()].map((r) => r.variableDefinition).join('\n')}
108
+
89
109
  const item: ${meta.types.linkedTypeName} = {
90
110
  ${model.fields
91
111
  .map((f) => {
92
112
  if (f.kind !== 'relation') {
93
113
  return `${f.name}: itemRaw.${f.name}`;
94
114
  }
95
- const linked = linkedForeignBacklinkFields.get(f.name);
96
- if (!linked) {
115
+ const linkedRel = variables.get(f.name);
116
+ if (!linkedRel) {
97
117
  throw new Error(`Could not find linked item for ${model.typeName}.${f.name}`);
98
118
  }
99
- return `${linked.fieldName}`;
119
+ return `${linkedRel.variableName}`;
100
120
  })
101
121
  .join(',\n')}
102
122
  }
@@ -117,7 +137,7 @@ export class ${meta.businessLogic.serviceClassName} {
117
137
  * Raw: The ${meta.userFriendlyName} only contains linked Ids, not the linked items themselves.
118
138
  */
119
139
  public get(id: ${model.brandedIdType}): ${meta.types.typeName} | null {
120
- return this.${dataRepositoryVariableName}.get(id)
140
+ return this.${modelRepositoryVariableName}.get(id)
121
141
  }
122
142
 
123
143
  ${hasLinkedItems ? linkedItemsGetterFn : ''}
@@ -126,14 +146,14 @@ export class ${meta.businessLogic.serviceClassName} {
126
146
  * Returns a map of all ${meta.userFriendlyName}s.
127
147
  */
128
148
  public getAll(): Map<${meta.types.brandedIdType}, ${model.typeName}> {
129
- return this.${dataRepositoryVariableName}.getAll()
149
+ return this.${modelRepositoryVariableName}.getAll()
130
150
  }
131
151
 
132
152
  /**
133
153
  * Creates a new ${meta.userFriendlyName}.
134
154
  */
135
155
  public async create(item: Omit<${model.typeName}, 'id'>): Promise<${model.typeName}> {
136
- return this.${dataRepositoryVariableName}.create(item)
156
+ return this.${modelRepositoryVariableName}.create(item)
137
157
  }
138
158
 
139
159
  /**
@@ -142,7 +162,7 @@ export class ${meta.businessLogic.serviceClassName} {
142
162
  public async update(item: Partial<${model.typeName}> & {
143
163
  id: ${model.brandedIdType}
144
164
  }): Promise<${model.typeName}> {
145
- return this.${dataRepositoryVariableName}.update(item)
165
+ return this.${modelRepositoryVariableName}.update(item)
146
166
  }
147
167
 
148
168
  /**
@@ -152,7 +172,7 @@ export class ${meta.businessLogic.serviceClassName} {
152
172
  * If the items is a dependency of another item, the deletion will fail!
153
173
  */
154
174
  public async delete(id: ${model.brandedIdType}): Promise<void> {
155
- return this.${dataRepositoryVariableName}.delete(id)
175
+ return this.${modelRepositoryVariableName}.delete(id)
156
176
  }
157
177
  }
158
178
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postxl/generator",
3
- "version": "0.15.5",
3
+ "version": "0.15.7",
4
4
  "main": "./dist/generator.js",
5
5
  "typings": "./dist/generator.d.ts",
6
6
  "bin": {