@postxl/generator 0.68.0 → 0.69.1
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 +34 -43
- package/dist/generators/indices/{datamodule.generator.d.ts → data/module.generator.d.ts} +2 -2
- package/dist/generators/indices/{datamodule.generator.js → data/module.generator.js} +4 -5
- package/dist/generators/indices/{dataservice.generator.d.ts → data/service.generator.d.ts} +2 -2
- package/dist/generators/indices/{dataservice.generator.js → data/service.generator.js} +5 -5
- package/dist/generators/indices/{data-types.generator.d.ts → data/types.generator.d.ts} +2 -2
- package/dist/generators/indices/{data-types.generator.js → data/types.generator.js} +2 -2
- package/dist/generators/indices/{importexport-convert-import-functions.generator.d.ts → import-export/importexport-convert-import-functions.generator.d.ts} +2 -2
- package/dist/generators/indices/{importexport-convert-import-functions.generator.js → import-export/importexport-convert-import-functions.generator.js} +4 -26
- package/dist/generators/indices/{importexport-exporter-class.generator.d.ts → import-export/importexport-exporter-class.generator.d.ts} +2 -2
- package/dist/generators/indices/{importexport-exporter-class.generator.js → import-export/importexport-exporter-class.generator.js} +4 -5
- package/dist/generators/indices/{importexport-import-service.generator.d.ts → import-export/importexport-import-service.generator.d.ts} +2 -2
- package/dist/generators/indices/{importexport-import-service.generator.js → import-export/importexport-import-service.generator.js} +4 -4
- package/dist/generators/indices/{importexport-types.generator.d.ts → import-export/importexport-types.generator.d.ts} +2 -2
- package/dist/generators/indices/{importexport-types.generator.js → import-export/importexport-types.generator.js} +2 -2
- package/dist/generators/indices/types.generator.js +13 -1
- package/dist/generators/indices/{businesslogic-actiontypes.generator.d.ts → update/actiontypes.generator.d.ts} +2 -2
- package/dist/generators/indices/{businesslogic-actiontypes.generator.js → update/actiontypes.generator.js} +3 -3
- package/dist/generators/indices/{businesslogic-update-module.generator.d.ts → update/module.generator.d.ts} +2 -2
- package/dist/generators/indices/{businesslogic-update-module.generator.js → update/module.generator.js} +2 -2
- package/dist/generators/indices/{businesslogic-update-service.generator.d.ts → update/service.generator.d.ts} +2 -2
- package/dist/generators/indices/{businesslogic-update-service.generator.js → update/service.generator.js} +2 -2
- package/dist/generators/indices/{businesslogic-view-module.generator.d.ts → view/module.generator.d.ts} +2 -2
- package/dist/generators/indices/{businesslogic-view-module.generator.js → view/module.generator.js} +2 -2
- package/dist/generators/indices/{businesslogic-view-service.generator.d.ts → view/service.generator.d.ts} +2 -2
- package/dist/generators/indices/{businesslogic-view-service.generator.js → view/service.generator.js} +2 -2
- package/dist/generators/models/repository.generator.d.ts +0 -46
- package/dist/generators/models/repository.generator.js +348 -796
- package/dist/generators/models/route.generator.js +2 -2
- package/dist/generators/models/types.generator.js +27 -2
- package/dist/generators/models/{businesslogic-update.generator.d.ts → update/service.generator.d.ts} +2 -2
- package/dist/generators/models/update/service.generator.js +252 -0
- package/dist/generators/models/{businesslogic-view.generator.d.ts → view/service.generator.d.ts} +2 -2
- package/dist/generators/models/{businesslogic-view.generator.js → view/service.generator.js} +12 -18
- package/dist/lib/attributes.d.ts +0 -5
- package/dist/lib/meta.d.ts +16 -54
- package/dist/lib/meta.js +2 -18
- package/dist/prisma/attributes.js +0 -2
- package/package.json +1 -1
- package/dist/generators/indices/datamock-module.generator.d.ts +0 -9
- package/dist/generators/indices/datamock-module.generator.js +0 -64
- package/dist/generators/indices/datamocker.generator.d.ts +0 -9
- package/dist/generators/indices/datamocker.generator.js +0 -88
- package/dist/generators/indices/emptydatabasemigration.generator.d.ts +0 -11
- package/dist/generators/indices/emptydatabasemigration.generator.js +0 -34
- package/dist/generators/indices/testdata-service.generator.d.ts +0 -9
- package/dist/generators/indices/testdata-service.generator.js +0 -84
- package/dist/generators/models/businesslogic-update.generator.js +0 -324
- /package/dist/generators/models/{react.generator → react}/context.generator.d.ts +0 -0
- /package/dist/generators/models/{react.generator → react}/context.generator.js +0 -0
- /package/dist/generators/models/{react.generator → react}/index.d.ts +0 -0
- /package/dist/generators/models/{react.generator → react}/index.js +0 -0
- /package/dist/generators/models/{react.generator → react}/library.generator.d.ts +0 -0
- /package/dist/generators/models/{react.generator → react}/library.generator.js +0 -0
- /package/dist/generators/models/{react.generator → react}/lookup.generator.d.ts +0 -0
- /package/dist/generators/models/{react.generator → react}/lookup.generator.js +0 -0
- /package/dist/generators/models/{react.generator → react}/modals.generator.d.ts +0 -0
- /package/dist/generators/models/{react.generator → react}/modals.generator.js +0 -0
|
@@ -8,9 +8,9 @@ const types_1 = require("../../lib/schema/types");
|
|
|
8
8
|
*/
|
|
9
9
|
function generateRoute({ model, meta }) {
|
|
10
10
|
const { idField, defaultField } = model;
|
|
11
|
-
const { scopeName
|
|
11
|
+
const { scopeName } = meta.update;
|
|
12
12
|
const defaultValueMethod = `
|
|
13
|
-
getDefault: procedure.query(({ ctx }) => ctx.view.${meta.data.dataServiceName}
|
|
13
|
+
getDefault: procedure.query(({ ctx }) => ctx.view.${meta.data.dataServiceName}.data.defaultValue),
|
|
14
14
|
`;
|
|
15
15
|
const imports = imports_1.ImportsGenerator.from(meta.trpc.routerFilePath).addImports({
|
|
16
16
|
[meta.types.importPath]: [
|
|
@@ -53,8 +53,6 @@ export type ${meta.types.typeName} = {
|
|
|
53
53
|
.join('\n')}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
56
|
/**
|
|
59
57
|
* Branded Id type that should be used to identify an instance of a ${meta.userFriendlyName}.
|
|
60
58
|
*/
|
|
@@ -95,6 +93,33 @@ export type ${meta.types.dto.update} = ${schemaMeta.types.dto.update}<${meta.typ
|
|
|
95
93
|
* Data transfer object for upserting a new or existing ${meta.userFriendlyName} instance.
|
|
96
94
|
*/
|
|
97
95
|
export type ${meta.types.dto.upsert} = ${schemaMeta.types.dto.upsert}<${meta.types.typeName}, ${model.brandedIdType}>
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Data transfer object for cloning a new ${meta.userFriendlyName} instance.
|
|
99
|
+
*/
|
|
100
|
+
export type ${meta.types.dto.clone} = {
|
|
101
|
+
${model.fields
|
|
102
|
+
.map((f) => {
|
|
103
|
+
const type = (0, typescript_1.getFieldType)(f);
|
|
104
|
+
// NOTE: ID field is always required to resolve the source.
|
|
105
|
+
if (f.kind === 'id') {
|
|
106
|
+
return `${f.name}: ${type}`;
|
|
107
|
+
}
|
|
108
|
+
if (f.isUnique) {
|
|
109
|
+
// NOTE: `unique` fields require a new value.
|
|
110
|
+
if (f.isRequired) {
|
|
111
|
+
return `${f.name}: ${type}`;
|
|
112
|
+
}
|
|
113
|
+
return `${f.name}: ${type} | null`;
|
|
114
|
+
}
|
|
115
|
+
// NOTE: Non-unique fields can be copied from the source.
|
|
116
|
+
if (f.isRequired) {
|
|
117
|
+
return `${f.name}?: ${type}`;
|
|
118
|
+
}
|
|
119
|
+
return `${f.name}?: ${type} | null`;
|
|
120
|
+
})
|
|
121
|
+
.join(', ')}
|
|
122
|
+
}
|
|
98
123
|
`;
|
|
99
124
|
}
|
|
100
125
|
exports.generateModelTypes = generateModelTypes;
|
package/dist/generators/models/{businesslogic-update.generator.d.ts → update/service.generator.d.ts}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ModelMetaData } from '
|
|
2
|
-
import { Model } from '
|
|
1
|
+
import { ModelMetaData } from '../../../lib/meta';
|
|
2
|
+
import { Model } from '../../../lib/schema/schema';
|
|
3
3
|
/**
|
|
4
4
|
* Generates update business logic for a given model.
|
|
5
5
|
* The update logic handles all Create/Update/Delete/Upsert operations. See template's readme for more info.
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateModelBusinessLogicUpdate = void 0;
|
|
7
|
+
const assert_1 = __importDefault(require("assert"));
|
|
8
|
+
const imports_1 = require("../../../lib/imports");
|
|
9
|
+
const meta_1 = require("../../../lib/meta");
|
|
10
|
+
const fields_1 = require("../../../lib/schema/fields");
|
|
11
|
+
const types_1 = require("../../../lib/schema/types");
|
|
12
|
+
const types_2 = require("../../../lib/types");
|
|
13
|
+
const typescript_1 = require("../../../lib/typescript");
|
|
14
|
+
const jsdoc_1 = require("../../../lib/utils/jsdoc");
|
|
15
|
+
const zod_1 = require("../../../lib/zod");
|
|
16
|
+
/**
|
|
17
|
+
* Generates update business logic for a given model.
|
|
18
|
+
* The update logic handles all Create/Update/Delete/Upsert operations. See template's readme for more info.
|
|
19
|
+
*/
|
|
20
|
+
function generateModelBusinessLogicUpdate({ model, meta }) {
|
|
21
|
+
const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
|
|
22
|
+
const { view, update, types, data } = meta;
|
|
23
|
+
const imports = imports_1.ImportsGenerator.from(meta.update.serviceClassLocation.path).addImports({
|
|
24
|
+
[data.repository.location.import]: data.repository.className,
|
|
25
|
+
[types.importPath]: [model.brandedIdType, types.typeName, types.toBrandedIdTypeFnName],
|
|
26
|
+
[view.serviceLocation.import]: [view.serviceClassName],
|
|
27
|
+
[schemaMeta.actions.execution.interfaceLocation.import]: [schemaMeta.actions.execution.interface],
|
|
28
|
+
[schemaMeta.actions.dispatcher.definitionLocation.import]: [schemaMeta.actions.dispatcher.definition],
|
|
29
|
+
[schemaMeta.update.serviceLocation.path]: schemaMeta.update.serviceClassName,
|
|
30
|
+
[schemaMeta.view.serviceLocation.import]: schemaMeta.view.serviceClassName,
|
|
31
|
+
});
|
|
32
|
+
for (const field of (0, fields_1.getRelationFields)(model)) {
|
|
33
|
+
// NOTE: We add `toBrandedType` functions for foreign models for decoders.
|
|
34
|
+
if (field.relationToModel.typeName === model.typeName) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const refModelMeta = (0, meta_1.getModelMetadata)({ model: field.relationToModel });
|
|
38
|
+
imports.addImport({
|
|
39
|
+
from: refModelMeta.types.importPath,
|
|
40
|
+
items: [refModelMeta.types.toBrandedIdTypeFnName],
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const cloneFn = generateCloneFn({ model, meta, imports });
|
|
44
|
+
return /* ts */ `
|
|
45
|
+
import { Inject, Injectable, forwardRef } from '@nestjs/common'
|
|
46
|
+
import { z } from 'zod'
|
|
47
|
+
|
|
48
|
+
${imports.generate()}
|
|
49
|
+
|
|
50
|
+
export type Scope = "${meta.actions.actionScopeConstType}"
|
|
51
|
+
|
|
52
|
+
export type Actions = {
|
|
53
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} and returns it.`])}
|
|
54
|
+
create: {
|
|
55
|
+
payload: CreatePayload
|
|
56
|
+
result: ${types.typeName}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
${(0, jsdoc_1.toJsDocComment)([`Updates a ${meta.userFriendlyName} and returns it.`])}
|
|
60
|
+
update: {
|
|
61
|
+
payload: UpdatePayload
|
|
62
|
+
result: ${types.typeName}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates or updates a ${meta.userFriendlyName} and returns it.`])}
|
|
66
|
+
upsert: {
|
|
67
|
+
payload: UpsertPayload
|
|
68
|
+
result: ${types.typeName}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
${(0, jsdoc_1.toJsDocComment)([`Deletes a ${meta.userFriendlyName} and returns its id.`])}
|
|
72
|
+
delete: {
|
|
73
|
+
payload: ${model.brandedIdType}
|
|
74
|
+
result: ${model.brandedIdType}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Zod decoder for validating the create input of a ${meta.userFriendlyName}.
|
|
80
|
+
*/
|
|
81
|
+
export const ${meta.update.createInputDecoder} = z.object({
|
|
82
|
+
${model.fields
|
|
83
|
+
.filter((f) => !f.attributes.isReadonly)
|
|
84
|
+
.map((f) => `${f.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field: f })}`)
|
|
85
|
+
.join(',')}
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
type CreatePayload = z.infer<typeof ${meta.update.createInputDecoder}>
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Zod decoder for validating the update input of a ${meta.userFriendlyName} .
|
|
92
|
+
*/
|
|
93
|
+
export const ${meta.update.updateInputDecoder} = z.object({
|
|
94
|
+
${model.fields
|
|
95
|
+
.filter((f) => !f.attributes.isReadonly || f.kind === 'id')
|
|
96
|
+
.map((f) => `${f.name}: z.${(0, zod_1.getZodDecoderDefinition)({ field: f, allowAnyOptionalField: f.kind !== 'id' })}`)
|
|
97
|
+
.join(',')}
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
type UpdatePayload = z.infer<typeof ${meta.update.updateInputDecoder}>
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Zod decoder for validating the upsert input of a ${meta.userFriendlyName} .
|
|
104
|
+
*/
|
|
105
|
+
export const ${meta.update.upsertInputDecoder} = z.union([
|
|
106
|
+
${meta.update.updateInputDecoder},
|
|
107
|
+
${meta.update.createInputDecoder}
|
|
108
|
+
])
|
|
109
|
+
|
|
110
|
+
type UpsertPayload = z.infer<typeof ${meta.update.upsertInputDecoder}>
|
|
111
|
+
|
|
112
|
+
export type ${update.serviceInterfaceName} = ${schemaMeta.actions.dispatcher.definition}<Actions>
|
|
113
|
+
|
|
114
|
+
@Injectable()
|
|
115
|
+
export class ${update.serviceClassName} implements ${update.serviceInterfaceName} {
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Instance of the ${meta.userFriendlyName} view service for convenience.
|
|
119
|
+
*/
|
|
120
|
+
private view: ${view.serviceClassName}
|
|
121
|
+
|
|
122
|
+
constructor(
|
|
123
|
+
private readonly data: ${data.repository.className},
|
|
124
|
+
|
|
125
|
+
@Inject(forwardRef(() => ${schemaMeta.update.serviceClassName}))
|
|
126
|
+
private readonly updateService: ${schemaMeta.update.serviceClassName},
|
|
127
|
+
|
|
128
|
+
@Inject(forwardRef(() => ${schemaMeta.view.serviceClassName}))
|
|
129
|
+
private readonly viewService: ${schemaMeta.view.serviceClassName}
|
|
130
|
+
) {
|
|
131
|
+
this.view = this.viewService.${view.serviceVariableName}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates a new ${meta.userFriendlyName} and returns it.`])}
|
|
135
|
+
public async create({ data, execution }: {
|
|
136
|
+
data: CreatePayload;
|
|
137
|
+
execution: ${schemaMeta.actions.execution.interface}
|
|
138
|
+
}): Promise<${types.typeName}> {
|
|
139
|
+
return this.data.create({ item: data, execution })
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
${(0, jsdoc_1.toJsDocComment)([`Updates a ${meta.userFriendlyName} and returns it.`])}
|
|
143
|
+
public async update({ data, execution }: {
|
|
144
|
+
data: UpdatePayload;
|
|
145
|
+
execution: ${schemaMeta.actions.execution.interface}
|
|
146
|
+
}): Promise<${types.typeName}> {
|
|
147
|
+
return this.data.update({ item: data, execution })
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
${(0, jsdoc_1.toJsDocComment)([`Creates or updates a ${meta.userFriendlyName} and returns it.`])}
|
|
151
|
+
public async upsert({ data, execution }: {
|
|
152
|
+
data: UpsertPayload;
|
|
153
|
+
execution: ${schemaMeta.actions.execution.interface}
|
|
154
|
+
}): Promise<${types.typeName}> {
|
|
155
|
+
return this.data.upsert({ item: data, execution })
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
${(0, jsdoc_1.toJsDocComment)([`Deletes a ${meta.userFriendlyName} instance and returns its id.`])}
|
|
159
|
+
public async delete({ data, execution }: {
|
|
160
|
+
data: ${model.brandedIdType};
|
|
161
|
+
execution: ${schemaMeta.actions.execution.interface}
|
|
162
|
+
}): Promise<${model.brandedIdType}> {
|
|
163
|
+
return this.data.delete({ id: data, execution })
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
${cloneFn}
|
|
167
|
+
}
|
|
168
|
+
`;
|
|
169
|
+
}
|
|
170
|
+
exports.generateModelBusinessLogicUpdate = generateModelBusinessLogicUpdate;
|
|
171
|
+
function generateCloneFn({ model, meta, imports }) {
|
|
172
|
+
const schemaMeta = (0, meta_1.getSchemaMetadata)({ config: model.schemaConfig });
|
|
173
|
+
for (const enumField of (0, fields_1.getEnumFields)(model)) {
|
|
174
|
+
const enumMeta = (0, meta_1.getEnumMetadata)(enumField);
|
|
175
|
+
imports.addTypeImport({
|
|
176
|
+
from: enumMeta.types.importPath,
|
|
177
|
+
items: [enumField.typeName],
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
const fnInputFields = model.fields
|
|
181
|
+
.filter((f) => {
|
|
182
|
+
switch (f.kind) {
|
|
183
|
+
case 'id':
|
|
184
|
+
case 'scalar':
|
|
185
|
+
case 'enum':
|
|
186
|
+
return true;
|
|
187
|
+
case 'relation':
|
|
188
|
+
return false;
|
|
189
|
+
default:
|
|
190
|
+
throw new types_2.ExhaustiveSwitchCheck(f);
|
|
191
|
+
}
|
|
192
|
+
})
|
|
193
|
+
.map((f) => {
|
|
194
|
+
const type = (0, typescript_1.getFieldType)(f);
|
|
195
|
+
switch (f.kind) {
|
|
196
|
+
case 'id':
|
|
197
|
+
return `${f.name}: ${type}`;
|
|
198
|
+
case 'scalar':
|
|
199
|
+
case 'enum':
|
|
200
|
+
if (f.isUnique) {
|
|
201
|
+
// NOTE: `unique` fields require a new value.
|
|
202
|
+
if (f.isRequired) {
|
|
203
|
+
return `${f.name}: ${type}`;
|
|
204
|
+
}
|
|
205
|
+
return `${f.name}: ${type} | null`;
|
|
206
|
+
}
|
|
207
|
+
// NOTE: Non-unique fields can be copied from the source.
|
|
208
|
+
if (f.isRequired) {
|
|
209
|
+
return `${f.name}?: ${type}`;
|
|
210
|
+
}
|
|
211
|
+
return `${f.name}?: ${type} | null`;
|
|
212
|
+
case 'relation':
|
|
213
|
+
(0, assert_1.default)(false);
|
|
214
|
+
break;
|
|
215
|
+
default:
|
|
216
|
+
throw new types_2.ExhaustiveSwitchCheck(f);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
const foreignKeyMappings = (0, fields_1.getRelationFields)(model).map((f) => {
|
|
220
|
+
if (f.isRequired) {
|
|
221
|
+
return `${f.name}: mappings.get({ model: '${f.relationToModel.typeName}', id: item.${f.name} })`;
|
|
222
|
+
}
|
|
223
|
+
return `${f.name}: item.${f.name} ? mappings.get({ model: '${f.relationToModel.typeName}', id: item.${f.name} }) : null`;
|
|
224
|
+
});
|
|
225
|
+
if (foreignKeyMappings.length > 0) {
|
|
226
|
+
imports.addImports({
|
|
227
|
+
[schemaMeta.types.importPath]: [schemaMeta.types.idTypesIndex],
|
|
228
|
+
[(0, types_1.toPackageName)('@postxl/runtime')]: [(0, types_1.toClassName)('TypedMapping')],
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return `
|
|
232
|
+
${(0, jsdoc_1.toJsDocComment)([`Clones a ${meta.userFriendlyName} with mapped foreign ids.`])}
|
|
233
|
+
public async clone(
|
|
234
|
+
{ data, execution }: {
|
|
235
|
+
data: { ${fnInputFields.join('; ')} },
|
|
236
|
+
execution: ${schemaMeta.actions.execution.interface}
|
|
237
|
+
},
|
|
238
|
+
${foreignKeyMappings.length > 0 ? `mappings = new TypedMapping<${schemaMeta.types.idTypesIndex}>()` : ''}
|
|
239
|
+
): Promise<${meta.types.typeName}> {
|
|
240
|
+
const clone = await this.data.clone({
|
|
241
|
+
id: data.id,
|
|
242
|
+
item: (${foreignKeyMappings.length > 0 ? 'item' : ''}) => ({
|
|
243
|
+
...data,
|
|
244
|
+
${foreignKeyMappings.join(',\n')}
|
|
245
|
+
}),
|
|
246
|
+
execution
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
return clone
|
|
250
|
+
}
|
|
251
|
+
`;
|
|
252
|
+
}
|
package/dist/generators/models/{businesslogic-view.generator.d.ts → view/service.generator.d.ts}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ModelMetaData } from '
|
|
2
|
-
import { Model } from '
|
|
1
|
+
import { ModelMetaData } from '../../../lib/meta';
|
|
2
|
+
import { Model } from '../../../lib/schema/schema';
|
|
3
3
|
/**
|
|
4
4
|
* Generates view business logic for a given model.
|
|
5
5
|
* The view logic exposes all information and links of a model. See template's readme for more info.
|
package/dist/generators/models/{businesslogic-view.generator.js → view/service.generator.js}
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateModelBusinessLogicView = void 0;
|
|
4
|
-
const imports_1 = require("
|
|
5
|
-
const meta_1 = require("
|
|
6
|
-
const fields_1 = require("
|
|
7
|
-
const types_1 = require("
|
|
8
|
-
const types_2 = require("
|
|
9
|
-
const ast_1 = require("
|
|
10
|
-
const jsdoc_1 = require("
|
|
4
|
+
const imports_1 = require("../../../lib/imports");
|
|
5
|
+
const meta_1 = require("../../../lib/meta");
|
|
6
|
+
const fields_1 = require("../../../lib/schema/fields");
|
|
7
|
+
const types_1 = require("../../../lib/schema/types");
|
|
8
|
+
const types_2 = require("../../../lib/types");
|
|
9
|
+
const ast_1 = require("../../../lib/utils/ast");
|
|
10
|
+
const jsdoc_1 = require("../../../lib/utils/jsdoc");
|
|
11
11
|
/**
|
|
12
12
|
* Generates view business logic for a given model.
|
|
13
13
|
* The view logic exposes all information and links of a model. See template's readme for more info.
|
|
@@ -20,12 +20,6 @@ function generateModelBusinessLogicView({ model, meta }) {
|
|
|
20
20
|
[meta.types.importPath]: [(0, types_1.toAnnotatedTypeName)(model.brandedIdType), (0, types_1.toAnnotatedTypeName)(meta.types.typeName)],
|
|
21
21
|
[schemaMeta.view.serviceLocation.path]: schemaMeta.view.serviceClassName,
|
|
22
22
|
});
|
|
23
|
-
/**
|
|
24
|
-
* The name of the variable that holds the repository instance for the current model
|
|
25
|
-
* (e.g. when we generate business logic service for Aggregation, the AggregationRepository
|
|
26
|
-
* would be referenced using `this.data` variable).
|
|
27
|
-
*/
|
|
28
|
-
const modelRepositoryVariableName = meta.view.dataRepositoryVariableName;
|
|
29
23
|
/**
|
|
30
24
|
* The name of the variable that holds the central business logic service instance.
|
|
31
25
|
* Instead of injecting a repository instance for each model, we inject this single instance
|
|
@@ -33,7 +27,7 @@ function generateModelBusinessLogicView({ model, meta }) {
|
|
|
33
27
|
*/
|
|
34
28
|
const viewServiceClassName = 'viewService';
|
|
35
29
|
const constructorParameters = [
|
|
36
|
-
`public readonly
|
|
30
|
+
`public readonly data: ${meta.data.repository.className}`,
|
|
37
31
|
`@Inject(forwardRef(() => ${schemaMeta.view.serviceClassName})) private readonly ${viewServiceClassName}: ${schemaMeta.view.serviceClassName}`,
|
|
38
32
|
];
|
|
39
33
|
/**
|
|
@@ -76,7 +70,7 @@ function generateModelBusinessLogicView({ model, meta }) {
|
|
|
76
70
|
* Linked: The ${meta.userFriendlyName} contains the linked (raw) items themselves, not only the ids.
|
|
77
71
|
*/
|
|
78
72
|
public async getLinkedItem(id: ${model.brandedIdType}): Promise<${meta.types.linkedTypeName} | null> {
|
|
79
|
-
const itemRaw = await this
|
|
73
|
+
const itemRaw = await this.data.get(id)
|
|
80
74
|
if (!itemRaw) {
|
|
81
75
|
return null
|
|
82
76
|
}
|
|
@@ -157,7 +151,7 @@ export class ${meta.view.serviceClassName} {
|
|
|
157
151
|
* Raw: The ${meta.userFriendlyName} only contains linked Ids, not the linked items themselves.
|
|
158
152
|
*/
|
|
159
153
|
public async get(id: ${model.brandedIdType}): Promise<${meta.types.typeName} | null> {
|
|
160
|
-
return this
|
|
154
|
+
return this.data.get(id)
|
|
161
155
|
}
|
|
162
156
|
|
|
163
157
|
${hasLinkedItems ? linkedItemsGetterFn : ''}
|
|
@@ -166,7 +160,7 @@ export class ${meta.view.serviceClassName} {
|
|
|
166
160
|
* Returns a map of all ${meta.userFriendlyNamePlural}.
|
|
167
161
|
*/
|
|
168
162
|
public async getAll(): Promise<Map<${meta.types.brandedIdType}, ${model.typeName}>> {
|
|
169
|
-
return this
|
|
163
|
+
return this.data.getAll()
|
|
170
164
|
}
|
|
171
165
|
|
|
172
166
|
/**
|
|
@@ -181,7 +175,7 @@ export class ${meta.view.serviceClassName} {
|
|
|
181
175
|
sort?: { field: keyof ${model.typeName}; ascending: boolean }
|
|
182
176
|
cursor?: Cursor
|
|
183
177
|
}) {
|
|
184
|
-
const items = await this
|
|
178
|
+
const items = await this.data.getAllAsArray()
|
|
185
179
|
const filtered = !filter
|
|
186
180
|
? items
|
|
187
181
|
: items.filter((item) => filterFn(item, filter.field, filter.operator, filter.value))
|
package/dist/lib/attributes.d.ts
CHANGED
|
@@ -16,11 +16,6 @@ export type ModelAttributes = {
|
|
|
16
16
|
* Note: Prisma has it's own schema attribute - but does not expose it in the DMMF.
|
|
17
17
|
*/
|
|
18
18
|
databaseSchema: string;
|
|
19
|
-
/**
|
|
20
|
-
* Schema tag: ´@@InMemoryOnly()`
|
|
21
|
-
* Whether the model should be stored in the database or only in memory.
|
|
22
|
-
*/
|
|
23
|
-
inMemoryOnly: boolean;
|
|
24
19
|
/**
|
|
25
20
|
* Schema tag: ´@@Index()`
|
|
26
21
|
* Creates an index on the given fields.
|
package/dist/lib/meta.d.ts
CHANGED
|
@@ -182,10 +182,6 @@ export type SchemaMetaData = {
|
|
|
182
182
|
* Location of the module class
|
|
183
183
|
*/
|
|
184
184
|
moduleLocation: Types.ModuleLocation;
|
|
185
|
-
/**
|
|
186
|
-
* Path to the file containing the data module class definition.
|
|
187
|
-
*/
|
|
188
|
-
emptyDbCommandFilePath: Types.FilePath;
|
|
189
185
|
repository: {
|
|
190
186
|
/**
|
|
191
187
|
* Path to the file containing the repository type definition.
|
|
@@ -218,20 +214,6 @@ export type SchemaMetaData = {
|
|
|
218
214
|
*/
|
|
219
215
|
bulkMutationForModel: Types.TypeName;
|
|
220
216
|
};
|
|
221
|
-
mockModule: {
|
|
222
|
-
/**
|
|
223
|
-
* Path to the file containing the mock data for the database.
|
|
224
|
-
*/
|
|
225
|
-
location: Types.ModuleLocation;
|
|
226
|
-
/**
|
|
227
|
-
* Name of the mock data module class.
|
|
228
|
-
*/
|
|
229
|
-
name: Types.ClassName;
|
|
230
|
-
};
|
|
231
|
-
/**
|
|
232
|
-
* Name of the data mock type/interface.
|
|
233
|
-
*/
|
|
234
|
-
dataMockDataType: Types.TypeName;
|
|
235
217
|
dataService: {
|
|
236
218
|
/**
|
|
237
219
|
* Path to the file containing data service class definitions.
|
|
@@ -350,10 +332,6 @@ export type SchemaMetaData = {
|
|
|
350
332
|
* Name of the function that converts a delta to BulkMutations.
|
|
351
333
|
*/
|
|
352
334
|
deltaToBulkMutations: Types.FunctionName;
|
|
353
|
-
/**
|
|
354
|
-
* Name of the function that converts mock data to BulkMutations.
|
|
355
|
-
*/
|
|
356
|
-
mockDataToBulkMutations: Types.FunctionName;
|
|
357
335
|
};
|
|
358
336
|
/**
|
|
359
337
|
* Meta data for the import export types file.
|
|
@@ -596,6 +574,18 @@ export type SchemaMetaData = {
|
|
|
596
574
|
* Path that may be used to import the type definitions package.
|
|
597
575
|
*/
|
|
598
576
|
importPath: Types.BackendModulePath;
|
|
577
|
+
/**
|
|
578
|
+
* Index of all branded ID types associated with the models.
|
|
579
|
+
*
|
|
580
|
+
* @example
|
|
581
|
+
* ```
|
|
582
|
+
* type SchemaIdTypes = {
|
|
583
|
+
* Post: PostId
|
|
584
|
+
* Comment: CommentId
|
|
585
|
+
* }
|
|
586
|
+
* ```
|
|
587
|
+
*/
|
|
588
|
+
idTypesIndex: Types.TypeName;
|
|
599
589
|
/**
|
|
600
590
|
* Path and type names for the Data Transfer Objects (DTOs).
|
|
601
591
|
*/
|
|
@@ -630,10 +620,6 @@ export type SchemaMetaData = {
|
|
|
630
620
|
* Meta data for the e2e generators.
|
|
631
621
|
*/
|
|
632
622
|
e2e: {
|
|
633
|
-
/**
|
|
634
|
-
* Path to the file containing data mocker class definitions.
|
|
635
|
-
*/
|
|
636
|
-
dataMockerLocation: Types.ModuleLocation;
|
|
637
623
|
/**
|
|
638
624
|
* Path to the file containing component test ids for e2e tests.
|
|
639
625
|
*/
|
|
@@ -765,26 +751,6 @@ export type ModelMetaData = {
|
|
|
765
751
|
*/
|
|
766
752
|
getMethodFnName: Types.FunctionName;
|
|
767
753
|
};
|
|
768
|
-
mockRepository: {
|
|
769
|
-
/**
|
|
770
|
-
* Path to the file containing the mock repository definition.
|
|
771
|
-
*/
|
|
772
|
-
location: Types.ModuleLocation;
|
|
773
|
-
/**
|
|
774
|
-
* The name of the class for the in-memory mock repository definition of this model (e.g. MockAggregationRepository).
|
|
775
|
-
*/
|
|
776
|
-
className: Types.ClassName;
|
|
777
|
-
};
|
|
778
|
-
};
|
|
779
|
-
e2e: {
|
|
780
|
-
/**
|
|
781
|
-
* The path to the file containing stub definitions of this model.
|
|
782
|
-
*/
|
|
783
|
-
stubLocation: Types.ModuleLocation;
|
|
784
|
-
/**
|
|
785
|
-
* The name of the function that adds missing values to the partially populated model value.
|
|
786
|
-
*/
|
|
787
|
-
stubGenerationFnName: Types.FunctionName;
|
|
788
754
|
};
|
|
789
755
|
/**
|
|
790
756
|
* Properties provided by the `importExport` generators
|
|
@@ -870,10 +836,6 @@ export type ModelMetaData = {
|
|
|
870
836
|
* Path to the view service for this model.
|
|
871
837
|
*/
|
|
872
838
|
serviceLocation: Types.ModuleLocation;
|
|
873
|
-
/**
|
|
874
|
-
* The name of the variable that holds the repository instance for the current model
|
|
875
|
-
*/
|
|
876
|
-
dataRepositoryVariableName: Types.VariableName;
|
|
877
839
|
/**
|
|
878
840
|
* The name of the variable that defines the filter operator decoder for the current model.
|
|
879
841
|
*/
|
|
@@ -929,10 +891,6 @@ export type ModelMetaData = {
|
|
|
929
891
|
* The name of the function that decodes an Upsert object to a fully typed object (e.g. `aggregationUpsertDecoder`.)
|
|
930
892
|
*/
|
|
931
893
|
upsertInputDecoder: Types.VariableName;
|
|
932
|
-
/**
|
|
933
|
-
* Name by which the business logic service exposes the data service.
|
|
934
|
-
*/
|
|
935
|
-
dataRepositoryVariableName: Types.VariableName;
|
|
936
894
|
};
|
|
937
895
|
/**
|
|
938
896
|
* Properties provided by the `seed` generators.
|
|
@@ -1113,6 +1071,10 @@ export type ModelMetaData = {
|
|
|
1113
1071
|
* The name of the type that represents a DTO for upserting an existing object (e.g. `AggregationUpsertDTO`.)
|
|
1114
1072
|
*/
|
|
1115
1073
|
upsert: Types.TypeName;
|
|
1074
|
+
/**
|
|
1075
|
+
* The name of the type that represents a DTO for cloning an existing object (e.g. `AggregationCloneDTO`.)
|
|
1076
|
+
*/
|
|
1077
|
+
clone: Types.TypeName;
|
|
1116
1078
|
};
|
|
1117
1079
|
/**
|
|
1118
1080
|
* The name of the file containing type definitions (e.g. `aggregation.type`).
|
package/dist/lib/meta.js
CHANGED
|
@@ -118,7 +118,6 @@ function getSchemaMetadata({ config }) {
|
|
|
118
118
|
data: {
|
|
119
119
|
moduleName: Types.toClassName(`DataModule`),
|
|
120
120
|
moduleLocation: Types.toModuleLocation(`data`, `${config.paths.dataLibPath}data.module`),
|
|
121
|
-
emptyDbCommandFilePath: Types.toPath(`${config.paths.dbLibPath}wipe-database.sql`),
|
|
122
121
|
repository: {
|
|
123
122
|
typeFilePath: Types.toPath(`${config.paths.dataLibPath}repository.type`),
|
|
124
123
|
typeName: Types.toTypeName(`Repository`),
|
|
@@ -138,14 +137,8 @@ function getSchemaMetadata({ config }) {
|
|
|
138
137
|
},
|
|
139
138
|
stubIndexFilePath: Types.toPath(`${config.paths.dataLibPath}stubs/index`),
|
|
140
139
|
testDataServiceFilePath: Types.toPath(`${config.paths.e2eLibPath}test-data.service`),
|
|
141
|
-
mockModule: {
|
|
142
|
-
location: Types.toModuleLocation(`data`, `${config.paths.dataLibPath}data.mock.module`),
|
|
143
|
-
name: Types.toClassName(`DataMockModule`),
|
|
144
|
-
},
|
|
145
|
-
dataMockDataType: Types.toTypeName(`MockData`),
|
|
146
140
|
},
|
|
147
141
|
e2e: {
|
|
148
|
-
dataMockerLocation: Types.toModuleLocation(`e2e`, `${config.paths.playwrightPath}support/data-mocker.class`),
|
|
149
142
|
testIdsFilePath: Types.toPath(`${config.paths.playwrightPath}support/model-test-ids`),
|
|
150
143
|
},
|
|
151
144
|
importExport: {
|
|
@@ -174,7 +167,6 @@ function getSchemaMetadata({ config }) {
|
|
|
174
167
|
location: Types.toModuleLocation(`import-export`, `${config.paths.importExportPath}convert-import.functions`),
|
|
175
168
|
importedDataToBulkMutations: Types.toFunctionName(`importToBulkMutations`),
|
|
176
169
|
deltaToBulkMutations: Types.toFunctionName(`deltaToBulkMutations`),
|
|
177
|
-
mockDataToBulkMutations: Types.toFunctionName(`mockDataToBulkMutations`),
|
|
178
170
|
},
|
|
179
171
|
types: {
|
|
180
172
|
location: Types.toModuleLocation(`import-export`, `${config.paths.importExportPath}types`),
|
|
@@ -245,6 +237,7 @@ function getSchemaMetadata({ config }) {
|
|
|
245
237
|
types: {
|
|
246
238
|
indexFilePath: Types.toPath(`${config.paths.modelTypeDefinitionsPath}index`),
|
|
247
239
|
importPath: Types.toBackendModulePath(`@backend/types`),
|
|
240
|
+
idTypesIndex: Types.toTypeName(`SchemaIds`),
|
|
248
241
|
dto: {
|
|
249
242
|
path: Types.toPath(`${config.paths.modelTypeDefinitionsPath}dto.types`),
|
|
250
243
|
genericModel: Types.toTypeName(`GenericModel`),
|
|
@@ -284,20 +277,12 @@ function getModelMetadata({ model }) {
|
|
|
284
277
|
decoderFnName: Types.toFunctionName(`to${PascalCase}`),
|
|
285
278
|
getMethodFnName: Types.toFunctionName(`${camelCase}`),
|
|
286
279
|
},
|
|
287
|
-
mockRepository: {
|
|
288
|
-
location: Types.toModuleLocation(`data`, `${config.paths.dataLibPath}repositories/mock/${camelCase}.mock.repository`),
|
|
289
|
-
className: Types.toClassName(`Mock${PascalCase}Repository`),
|
|
290
|
-
},
|
|
291
280
|
stubLocation: Types.toModuleLocation(`data`, `${config.paths.dataLibPath}stubs/${camelCase}.stub`),
|
|
292
281
|
stubGenerationFnName: Types.toFunctionName(`stub${PascalCase}`),
|
|
293
282
|
defaultStubConstantName: Types.toVariableName(`${camelCase}DefaultStub`),
|
|
294
283
|
dataServiceName: Types.toVariableName(`${uncapitalizedPlural}`),
|
|
295
284
|
dataServiceIdName: Types.toVariableName(`${uncapitalized}`),
|
|
296
285
|
},
|
|
297
|
-
e2e: {
|
|
298
|
-
stubGenerationFnName: Types.toFunctionName(`stub${PascalCase}`),
|
|
299
|
-
stubLocation: Types.toModuleLocation(`e2e`, `${config.paths.playwrightPath}support/stubs/${camelCase}.stub`),
|
|
300
|
-
},
|
|
301
286
|
importExport: {
|
|
302
287
|
exportDataPropertyName: Types.toVariableName(`${capitalizedPlural}`),
|
|
303
288
|
exportDataFullPropertyName: Types.toVariableName(`${uncapitalizedPlural}`),
|
|
@@ -320,7 +305,6 @@ function getModelMetadata({ model }) {
|
|
|
320
305
|
serviceClassName: Types.toClassName(`${PascalCase}ViewService`),
|
|
321
306
|
serviceVariableName: Types.toVariableName(`${uncapitalizedPlural}`),
|
|
322
307
|
serviceLocation: Types.toModuleLocation(`view`, `${config.paths.businessViewLogicPath}${camelCase}.view.service`),
|
|
323
|
-
dataRepositoryVariableName: Types.toVariableName(`data`),
|
|
324
308
|
cursorDecoder: Types.toVariableName(`CURSOR_DECODER`),
|
|
325
309
|
filterOperatorDecoder: Types.toVariableName(`FILTER_OPERATOR_DECODER`),
|
|
326
310
|
},
|
|
@@ -335,7 +319,6 @@ function getModelMetadata({ model }) {
|
|
|
335
319
|
createInputDecoder: Types.toVariableName(`${camelCase}CreateInputDecoder`),
|
|
336
320
|
updateInputDecoder: Types.toVariableName(`${camelCase}UpdateInputDecoder`),
|
|
337
321
|
upsertInputDecoder: Types.toVariableName(`${camelCase}UpsertInputDecoder`),
|
|
338
|
-
dataRepositoryVariableName: Types.toVariableName(`data`),
|
|
339
322
|
},
|
|
340
323
|
seed: {
|
|
341
324
|
location: Types.toModuleLocation('seed-data', `${config.paths.seedDataPath}001-base-data/${uncapitalizedPlural}.seed`),
|
|
@@ -405,6 +388,7 @@ function getModelMetadata({ model }) {
|
|
|
405
388
|
create: Types.toTypeName(`${PascalCase}CreateDTO`),
|
|
406
389
|
update: Types.toTypeName(`${PascalCase}UpdateDTO`),
|
|
407
390
|
upsert: Types.toTypeName(`${PascalCase}UpsertDTO`),
|
|
391
|
+
clone: Types.toTypeName(`${PascalCase}CloneDTO`),
|
|
408
392
|
},
|
|
409
393
|
typeName: Types.toTypeName(`${PascalCase}`),
|
|
410
394
|
linkedTypeName: Types.toTypeName(`${PascalCase}Linked`),
|
|
@@ -71,7 +71,6 @@ function getModelAttributes(model) {
|
|
|
71
71
|
const decoder = zod_1.default
|
|
72
72
|
.object({
|
|
73
73
|
ignore: blankStringBooleanDecoder,
|
|
74
|
-
inMemoryOnly: blankStringBooleanDecoder,
|
|
75
74
|
description: zod_1.default.string().optional(),
|
|
76
75
|
schema: zod_1.default.string({
|
|
77
76
|
required_error: `The PostXL attribute ${(0, logger_1.highlight)('`///@@Schema`')} attribute must be provided (in addition to Prisma's @@schema attribute)!`,
|
|
@@ -85,7 +84,6 @@ function getModelAttributes(model) {
|
|
|
85
84
|
})
|
|
86
85
|
.transform((obj) => ({
|
|
87
86
|
ignore: obj.ignore,
|
|
88
|
-
inMemoryOnly: obj.inMemoryOnly,
|
|
89
87
|
description: obj.description,
|
|
90
88
|
databaseSchema: obj.schema,
|
|
91
89
|
index: obj.index,
|
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { SchemaMetaData } from '../../lib/meta';
|
|
2
|
-
import { Model } from '../../lib/schema/schema';
|
|
3
|
-
/**
|
|
4
|
-
* Generates a mocking class
|
|
5
|
-
*/
|
|
6
|
-
export declare function generateDataMockModule({ models, meta }: {
|
|
7
|
-
models: Model[];
|
|
8
|
-
meta: SchemaMetaData;
|
|
9
|
-
}): string;
|