@postxl/generator 0.9.1 → 0.10.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.
- package/dist/generator.js +1 -0
- package/dist/generators/indices/datamockmodule.generator.js +13 -10
- package/dist/generators/models/repository.generator.d.ts +7 -0
- package/dist/generators/models/repository.generator.js +89 -14
- package/dist/lib/attributes.d.ts +5 -0
- package/dist/lib/meta.d.ts +12 -0
- package/dist/lib/meta.js +3 -0
- package/dist/prisma/attributes.js +41 -9
- package/package.json +1 -1
package/dist/generator.js
CHANGED
|
@@ -151,6 +151,7 @@ const generate = ({ models, enums, config, prismaClientPath, logger, }) => __awa
|
|
|
151
151
|
if (!config.disableGenerators.data) {
|
|
152
152
|
generated.write(`/${meta.data.stubFilePath}.ts`, (0, stub_generator_1.generateStub)({ model, meta }));
|
|
153
153
|
generated.write(`/${meta.data.repoFilePath}.ts`, (0, repository_generator_1.generateRepository)({ model, meta }));
|
|
154
|
+
generated.write(`/${meta.data.mockRepoFilePath}.ts`, (0, repository_generator_1.generateMockRepository)({ model, meta }));
|
|
154
155
|
}
|
|
155
156
|
// Routes
|
|
156
157
|
if (!config.disableGenerators.trpc) {
|
|
@@ -47,22 +47,25 @@ function generateDataMockModule({ models, meta }) {
|
|
|
47
47
|
});
|
|
48
48
|
for (const { model, meta } of mm) {
|
|
49
49
|
imports.addImport({ items: [model.typeName], from: meta.types.importPath });
|
|
50
|
-
imports.addImport({ items: [meta.data.repositoryClassName], from: meta.data.
|
|
51
|
-
imports.addImport({ items: [meta.
|
|
50
|
+
imports.addImport({ items: [meta.data.repositoryClassName], from: meta.data.repoFilePath });
|
|
51
|
+
imports.addImport({ items: [meta.data.mockRepositoryClassName], from: meta.data.mockRepoFilePath });
|
|
52
52
|
}
|
|
53
53
|
const providers = mm
|
|
54
|
-
.map(({ meta, model }) => `
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
.map(({ meta, model }) => `{
|
|
55
|
+
provide: ${meta.data.repositoryClassName},
|
|
56
|
+
useFactory: async () => {
|
|
57
|
+
const repository = new ${meta.data.mockRepositoryClassName}()
|
|
58
|
+
if (!!seed && !!seed.${meta.seed.constantName}) {
|
|
59
|
+
await repository.reInit(seed.${meta.seed.constantName})
|
|
60
|
+
}
|
|
61
|
+
return repository
|
|
62
|
+
}
|
|
63
|
+
}`)
|
|
59
64
|
.join(', ');
|
|
60
65
|
return `
|
|
61
66
|
import { DynamicModule } from '@nestjs/common'
|
|
62
67
|
import { DbModule } from '@${meta.config.project}/db'
|
|
63
68
|
|
|
64
|
-
import { provideMockRepository } from './mock.repository'
|
|
65
|
-
|
|
66
69
|
${imports.generate()}
|
|
67
70
|
|
|
68
71
|
export class DataMockModule {
|
|
@@ -77,7 +80,7 @@ export class DataMockModule {
|
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
// eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars
|
|
80
|
-
static async mock(): Promise<DynamicModule> {
|
|
83
|
+
static async mock(seed?: MockData): Promise<DynamicModule> {
|
|
81
84
|
const providers = [
|
|
82
85
|
DataService,
|
|
83
86
|
TestDataService,
|
|
@@ -7,3 +7,10 @@ export declare function generateRepository({ model, meta }: {
|
|
|
7
7
|
model: Model;
|
|
8
8
|
meta: ModelMetaData;
|
|
9
9
|
}): string;
|
|
10
|
+
/**
|
|
11
|
+
* Generates a mock repository data structure for a given model: same a repository, but in memory only
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateMockRepository({ model: modelSource, meta: metaSource, }: {
|
|
14
|
+
model: Model;
|
|
15
|
+
meta: ModelMetaData;
|
|
16
|
+
}): string;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateRepository = void 0;
|
|
3
|
+
exports.generateMockRepository = exports.generateRepository = void 0;
|
|
4
4
|
const fields_1 = require("../../lib/schema/fields");
|
|
5
5
|
const string_1 = require("../../lib/utils/string");
|
|
6
6
|
const schema_1 = require("../../lib/schema/schema");
|
|
7
7
|
const meta_1 = require("../../lib/meta");
|
|
8
8
|
const imports_1 = require("../../lib/imports");
|
|
9
|
+
const types_1 = require("../../lib/schema/types");
|
|
9
10
|
/**
|
|
10
11
|
* Generates repository data structure for a given model.
|
|
11
12
|
*/
|
|
@@ -18,6 +19,28 @@ function generateRepository({ model, meta }) {
|
|
|
18
19
|
const relations = fields
|
|
19
20
|
.filter(schema_1.isFieldRelation)
|
|
20
21
|
.map((field) => (Object.assign(Object.assign({}, field), { meta: (0, meta_1.getModelMetadata)({ model: field.relationToModel }), fieldMeta: (0, meta_1.getFieldMetadata)({ field }) })));
|
|
22
|
+
const getIndexDefinition = (fieldNames) => {
|
|
23
|
+
const fields = fieldNames.map((f) => {
|
|
24
|
+
const result = model.fields.find((field) => field.name === f);
|
|
25
|
+
if (!result) {
|
|
26
|
+
throw new Error(`Index field ${f} not found in model ${model.name}`);
|
|
27
|
+
}
|
|
28
|
+
if (result.kind !== 'relation') {
|
|
29
|
+
throw new Error(`Index field ${f} is not a relation in model ${model.name}`);
|
|
30
|
+
}
|
|
31
|
+
const meta = (0, meta_1.getModelMetadata)({ model: result.relationToModel });
|
|
32
|
+
return Object.assign(Object.assign({}, result), { meta });
|
|
33
|
+
});
|
|
34
|
+
const [firstField, ...restFields] = fields;
|
|
35
|
+
if (!restFields || restFields.length === 0) {
|
|
36
|
+
throw new Error(`Index for model ${model.name} must have at least 2 fields!`);
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
fields,
|
|
40
|
+
name: (0, string_1.toCamelCase)(`${firstField.name}${restFields.map((f) => (0, string_1.toPascalCase)(f.name)).join('')}Index`),
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
const indexes = model.attributes.index ? [getIndexDefinition(model.attributes.index)] : [];
|
|
21
44
|
const defaultValueInitFn = `
|
|
22
45
|
if (item.${(_a = model.defaultField) === null || _a === void 0 ? void 0 : _a.name}) {
|
|
23
46
|
if (this.defaultValue) {
|
|
@@ -38,7 +61,11 @@ function generateRepository({ model, meta }) {
|
|
|
38
61
|
items: [model.typeName, model.brandedIdType, meta.types.toBrandedIdTypeFnName],
|
|
39
62
|
from: meta.types.importPath,
|
|
40
63
|
})
|
|
41
|
-
.addImport({ items: [meta.types.zodDecoderFnName], from: meta.types.importPath })
|
|
64
|
+
.addImport({ items: [meta.types.zodDecoderFnName], from: meta.types.importPath })
|
|
65
|
+
.addImport({
|
|
66
|
+
items: [(0, types_1.toClassName)('Repository')],
|
|
67
|
+
from: (0, types_1.toFileName)(model.schemaConfig.paths.dataLibPath + 'repository.type'),
|
|
68
|
+
});
|
|
42
69
|
relations.forEach((r) => {
|
|
43
70
|
imports.addImport({
|
|
44
71
|
items: [r.meta.types.brandedIdType],
|
|
@@ -48,9 +75,7 @@ function generateRepository({ model, meta }) {
|
|
|
48
75
|
return `
|
|
49
76
|
import { Injectable, Logger } from '@nestjs/common'
|
|
50
77
|
import { DbService, ${model.sourceName} as DbType } from '@${model.schemaConfig.project}/db'
|
|
51
|
-
import { format, pluralize } from '@pxl/common'
|
|
52
|
-
|
|
53
|
-
import { Repository } from '../repository.type'
|
|
78
|
+
import { format, pluralize, NestedMap } from '@pxl/common'
|
|
54
79
|
|
|
55
80
|
${imports.generate()}
|
|
56
81
|
|
|
@@ -84,13 +109,26 @@ export class ${meta.data.repositoryClassName} implements Repository<
|
|
|
84
109
|
${uniqueStringFields.map((f) => `'${f.name}': new Map<string, ${model.typeName}>()`).join(',\n')}
|
|
85
110
|
}
|
|
86
111
|
|
|
112
|
+
${indexes
|
|
113
|
+
.map((i) => `
|
|
114
|
+
protected ${i.name} = new NestedMap<${i.fields.map((f) => f.meta.types.brandedIdType).join(',')}, ${model.typeName}>(
|
|
115
|
+
${i.fields.map((f) => `(x) => x.${f.name}`).join(',')}
|
|
116
|
+
)
|
|
117
|
+
`)
|
|
118
|
+
.join('\n')}
|
|
119
|
+
${model.attributes.inMemoryOnly
|
|
120
|
+
? ''
|
|
121
|
+
: `
|
|
87
122
|
constructor(${model.attributes.inMemoryOnly ? '' : 'protected '}db: DbService) {}
|
|
88
|
-
|
|
123
|
+
`}
|
|
124
|
+
|
|
89
125
|
public async init() {
|
|
90
126
|
this.data.clear()
|
|
91
127
|
|
|
92
|
-
${uniqueStringFields.map((f) => `this.uniqueIds.${f.name}.clear()\n
|
|
128
|
+
${uniqueStringFields.map((f) => `this.uniqueIds.${f.name}.clear()`).join('\n')}
|
|
93
129
|
|
|
130
|
+
${indexes.map((i) => `this.${i.name}.clear()`).join('\n')}
|
|
131
|
+
|
|
94
132
|
${model.attributes.inMemoryOnly
|
|
95
133
|
? 'return Promise.resolve()'
|
|
96
134
|
: `
|
|
@@ -99,10 +137,11 @@ export class ${meta.data.repositoryClassName} implements Repository<
|
|
|
99
137
|
|
|
100
138
|
for (const rawItem of data) {
|
|
101
139
|
const item = this.${decoder}(rawItem)
|
|
102
|
-
this.
|
|
140
|
+
this.set(item)
|
|
103
141
|
|
|
104
142
|
${model.defaultField ? defaultValueInitFn : ''}
|
|
105
143
|
${uniqueStringFields.map((f) => `this.uniqueIds.${f.name}.set(item.${f.name}, item)`).join('\n')}
|
|
144
|
+
${indexes.map((i) => `this.${i.name}.set(item)`).join('\n')}
|
|
106
145
|
}
|
|
107
146
|
|
|
108
147
|
${isGenerated ? idIntInitFn : ''}
|
|
@@ -110,12 +149,18 @@ export class ${meta.data.repositoryClassName} implements Repository<
|
|
|
110
149
|
${model.defaultField ? defaultValueInitCheckFn : ''}
|
|
111
150
|
|
|
112
151
|
this.logger.log(\`\${format(this.data.size)} \${pluralize('${model.typeName}', this.data.size)} loaded\`)
|
|
152
|
+
${indexes
|
|
153
|
+
.map((i) => `this.logger.log(\`\${this.${i.name}.size} ${model.typeName} loaded into index ${i.name}\`)`)
|
|
154
|
+
.join('\n')}
|
|
113
155
|
`}
|
|
114
156
|
}
|
|
115
157
|
|
|
116
158
|
public async reInit(data: ${model.typeName}[]): Promise<void> {
|
|
117
159
|
${model.attributes.inMemoryOnly
|
|
118
|
-
?
|
|
160
|
+
? `
|
|
161
|
+
await this.init()
|
|
162
|
+
await this.createMany(data)
|
|
163
|
+
`
|
|
119
164
|
: `
|
|
120
165
|
if (!this.db.useE2ETestDB) {
|
|
121
166
|
const errorMsg =
|
|
@@ -123,8 +168,9 @@ export class ${meta.data.repositoryClassName} implements Repository<
|
|
|
123
168
|
this.logger.error(errorMsg)
|
|
124
169
|
throw new Error(errorMsg)
|
|
125
170
|
}
|
|
126
|
-
await this.db.runOnlyOnTestDb(() => this.db.${meta.data.repository.getMethodFnName}.createMany({ data: data.map((i) => this.toCreateItem(i)) }))
|
|
171
|
+
await this.db.runOnlyOnTestDb(() => this.db.${meta.data.repository.getMethodFnName}.createMany({ data: data.map((i) => this.toCreateItem(i)) }))
|
|
127
172
|
return this.init()
|
|
173
|
+
`}
|
|
128
174
|
}
|
|
129
175
|
|
|
130
176
|
public get(id: ${model.brandedIdType} | null): ${model.typeName} | null {
|
|
@@ -142,6 +188,17 @@ export class ${meta.data.repositoryClassName} implements Repository<
|
|
|
142
188
|
return Array.from(this.data.values())
|
|
143
189
|
}
|
|
144
190
|
|
|
191
|
+
${indexes
|
|
192
|
+
.map((i) => `
|
|
193
|
+
public getFrom${indexes.length === 1 ? 'Index' : (0, string_1.toPascalCase)(i.name)}
|
|
194
|
+
({ ${i.fields.map((f) => f.name).join(',')} }: { ${i.fields
|
|
195
|
+
.map((f) => `${f.name} : ${f.meta.types.brandedIdType}`)
|
|
196
|
+
.join(';')} }): ${model.typeName} | null {
|
|
197
|
+
return this.${i.name}.get(${i.fields.map((f) => f.name).join(',')}) ?? null
|
|
198
|
+
}
|
|
199
|
+
`)
|
|
200
|
+
.join('\n')}
|
|
201
|
+
|
|
145
202
|
public filter(predicate: (item: ${model.typeName}) => boolean): ${model.typeName}[] {
|
|
146
203
|
return this.getAllAsArray().filter(predicate)
|
|
147
204
|
}
|
|
@@ -205,7 +262,7 @@ export class ${meta.data.repositoryClassName} implements Repository<
|
|
|
205
262
|
|
|
206
263
|
${model.attributes.inMemoryOnly
|
|
207
264
|
? `
|
|
208
|
-
const newItem = await Promise.resolve({ item, id })
|
|
265
|
+
const newItem = await Promise.resolve({ ...item, id: ${meta.types.toBrandedIdTypeFnName}(id) })
|
|
209
266
|
`
|
|
210
267
|
: `
|
|
211
268
|
const newItem = this.${decoder}(
|
|
@@ -398,6 +455,8 @@ export class ${meta.data.repositoryClassName} implements Repository<
|
|
|
398
455
|
${!r.isRequired ? `}` : ''}
|
|
399
456
|
`)
|
|
400
457
|
.join('\n')}
|
|
458
|
+
|
|
459
|
+
${indexes.map((i) => `this.${i.name}.set(item)`).join('\n')}
|
|
401
460
|
}
|
|
402
461
|
|
|
403
462
|
/**
|
|
@@ -420,22 +479,38 @@ export class ${meta.data.repositoryClassName} implements Repository<
|
|
|
420
479
|
${!r.isRequired ? '}' : ''}
|
|
421
480
|
`)
|
|
422
481
|
.join('\n')}
|
|
482
|
+
|
|
483
|
+
${indexes.map((i) => `this.${i.name}.delete(item)`).join('\n')}
|
|
423
484
|
}
|
|
424
485
|
|
|
486
|
+
|
|
487
|
+
${model.attributes.inMemoryOnly
|
|
488
|
+
? ''
|
|
489
|
+
: `
|
|
425
490
|
/**
|
|
426
491
|
* Utility function that converts a given Database object to a TypeScript model instance
|
|
427
492
|
*/
|
|
428
493
|
private ${decoder}(item: Pick<DbType, ${[...model.fields.values()]
|
|
429
|
-
|
|
430
|
-
|
|
494
|
+
.map((f) => `'${f.sourceName}'`)
|
|
495
|
+
.join(' | ')}>): ${model.typeName} {
|
|
431
496
|
return ${meta.types.zodDecoderFnName}.parse({
|
|
432
497
|
${[...model.fields.values()].map((f) => `${f.name}: item.${f.sourceName}`).join(',\n')}
|
|
433
498
|
})
|
|
434
|
-
}
|
|
499
|
+
}`}
|
|
435
500
|
}
|
|
436
501
|
`;
|
|
437
502
|
}
|
|
438
503
|
exports.generateRepository = generateRepository;
|
|
504
|
+
/**
|
|
505
|
+
* Generates a mock repository data structure for a given model: same a repository, but in memory only
|
|
506
|
+
*/
|
|
507
|
+
function generateMockRepository({ model: modelSource, meta: metaSource, }) {
|
|
508
|
+
// We re-use the repository generator, but we change the meta data to use the mock repository name and the model to be in memory only
|
|
509
|
+
const meta = Object.assign(Object.assign({}, metaSource), { data: Object.assign(Object.assign({}, metaSource.data), { repositoryClassName: metaSource.data.mockRepositoryClassName, repoFilePath: metaSource.data.mockRepoFilePath }) });
|
|
510
|
+
const model = Object.assign(Object.assign({}, modelSource), { attributes: Object.assign(Object.assign({}, modelSource.attributes), { inMemoryOnly: true }) });
|
|
511
|
+
return generateRepository({ model, meta });
|
|
512
|
+
}
|
|
513
|
+
exports.generateMockRepository = generateMockRepository;
|
|
439
514
|
function getEnsureUniqueFnName(field) {
|
|
440
515
|
return `ensureUnique${(0, string_1.toPascalCase)(field.name)}`;
|
|
441
516
|
}
|
package/dist/lib/attributes.d.ts
CHANGED
|
@@ -33,6 +33,11 @@ export type ModelAttributes = {
|
|
|
33
33
|
* Whether the model should be stored in the database or only in memory.
|
|
34
34
|
*/
|
|
35
35
|
inMemoryOnly: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Schema tag: ´@@Index()`
|
|
38
|
+
* Creates an index on the given fields.
|
|
39
|
+
*/
|
|
40
|
+
index?: string[];
|
|
36
41
|
};
|
|
37
42
|
export type FieldAttributes = {
|
|
38
43
|
/**
|
package/dist/lib/meta.d.ts
CHANGED
|
@@ -125,10 +125,22 @@ export type ModelMetaData = {
|
|
|
125
125
|
* Path to the file containing the repository definition.
|
|
126
126
|
*/
|
|
127
127
|
repoFilePath: Types.Path;
|
|
128
|
+
/**
|
|
129
|
+
* Name of the file containing the mock repository definition for this model.
|
|
130
|
+
*/
|
|
131
|
+
mockRepoFileName: Types.FileName;
|
|
132
|
+
/**
|
|
133
|
+
* Path to the file containing the mock repository definition.
|
|
134
|
+
*/
|
|
135
|
+
mockRepoFilePath: Types.Path;
|
|
128
136
|
/**
|
|
129
137
|
* The name of the class for the repository definition of this model (e.g. AggregationRepository).
|
|
130
138
|
*/
|
|
131
139
|
repositoryClassName: Types.ClassName;
|
|
140
|
+
/**
|
|
141
|
+
* The name of the class for the in-memory mock repository definition of this model (e.g. MockAggregationRepository).
|
|
142
|
+
*/
|
|
143
|
+
mockRepositoryClassName: Types.ClassName;
|
|
132
144
|
/**
|
|
133
145
|
* The name by which the repository is exposed in the dataService/context. (e.g. aggregations)
|
|
134
146
|
*/
|
package/dist/lib/meta.js
CHANGED
|
@@ -71,10 +71,13 @@ function getModelMetadata({ model }) {
|
|
|
71
71
|
defaultStubConstantName: Types.toVariableName(`${camelCase}DefaultStub`),
|
|
72
72
|
repoFileName: Types.toFileName(`${camelCase}.repository`),
|
|
73
73
|
repoFilePath: Types.toPath(`${config.paths.dataLibPath}repositories/${camelCase}.repository`),
|
|
74
|
+
mockRepoFileName: Types.toFileName(`${camelCase}.mock.repository`),
|
|
75
|
+
mockRepoFilePath: Types.toPath(`${config.paths.dataLibPath}repositories/mock/${camelCase}.mock.repository`),
|
|
74
76
|
stubFilePath: Types.toPath(`${config.paths.dataLibPath}stubs/${camelCase}.stub`),
|
|
75
77
|
importPath: Types.toPath(`@${config.project}/data`),
|
|
76
78
|
stubGenerationFnName: Types.toFunction(`stub${PascalCase}`),
|
|
77
79
|
repositoryClassName: Types.toClassName(`${PascalCase}Repository`),
|
|
80
|
+
mockRepositoryClassName: Types.toClassName(`Mock${PascalCase}Repository`),
|
|
78
81
|
dataServiceName: Types.toVariableName(`${uncapitalizedPlural}`),
|
|
79
82
|
excelExportTableName: `${pluralized}`,
|
|
80
83
|
repository: {
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.getFieldAttributes = exports.getModelAttributes = exports.parseArgumentToStringOrStringArray = exports.parseAttributesFromDocumentation = void 0;
|
|
4
7
|
const remeda_1 = require("remeda");
|
|
5
8
|
const string_1 = require("../lib/utils/string");
|
|
9
|
+
const zod_1 = __importDefault(require("zod"));
|
|
6
10
|
/**
|
|
7
11
|
* Parses attributes from a given string using provided prefix.
|
|
8
12
|
*/
|
|
@@ -43,20 +47,48 @@ function parseArgumentToStringOrStringArray(str) {
|
|
|
43
47
|
throw new Error(`Could not parse attribute argument: ${str}`);
|
|
44
48
|
}
|
|
45
49
|
exports.parseArgumentToStringOrStringArray = parseArgumentToStringOrStringArray;
|
|
50
|
+
const blankStringBooleanDecoder = zod_1.default
|
|
51
|
+
.string()
|
|
52
|
+
.transform((str) => true)
|
|
53
|
+
.or(zod_1.default.boolean())
|
|
54
|
+
.optional()
|
|
55
|
+
.default(false);
|
|
46
56
|
/**
|
|
47
57
|
* Returns attribute information for a given model.
|
|
48
58
|
*/
|
|
49
59
|
function getModelAttributes(model) {
|
|
50
60
|
const attributes = parseAttributesFromDocumentation(model);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
const decoder = zod_1.default
|
|
62
|
+
.object({
|
|
63
|
+
ignore: blankStringBooleanDecoder,
|
|
64
|
+
skipUpdate: blankStringBooleanDecoder,
|
|
65
|
+
customUpdate: blankStringBooleanDecoder,
|
|
66
|
+
skipCreate: blankStringBooleanDecoder,
|
|
67
|
+
customCreate: blankStringBooleanDecoder,
|
|
68
|
+
skipDelete: blankStringBooleanDecoder,
|
|
69
|
+
customDelete: blankStringBooleanDecoder,
|
|
70
|
+
inMemoryOnly: blankStringBooleanDecoder,
|
|
71
|
+
description: zod_1.default.string().optional(),
|
|
72
|
+
schema: zod_1.default.string().optional(),
|
|
73
|
+
index: zod_1.default.array(zod_1.default.string()).optional(),
|
|
74
|
+
})
|
|
75
|
+
.transform((obj) => ({
|
|
76
|
+
ignore: obj.ignore,
|
|
77
|
+
skipUpdate: obj.skipUpdate || obj.customUpdate,
|
|
78
|
+
skipCreate: obj.skipCreate || obj.customCreate,
|
|
79
|
+
skipDelete: obj.skipDelete || obj.customDelete,
|
|
80
|
+
inMemoryOnly: obj.inMemoryOnly,
|
|
81
|
+
description: obj.description,
|
|
82
|
+
schema: obj.schema,
|
|
83
|
+
index: obj.index,
|
|
84
|
+
}));
|
|
85
|
+
const result = decoder.safeParse(attributes);
|
|
86
|
+
if (!result.success) {
|
|
87
|
+
throw new Error(`Model ${model.name} has invalid model attributes: ${result.error}`);
|
|
88
|
+
}
|
|
89
|
+
if (result.data.description === 'The calculated metric value for a dataset.') {
|
|
90
|
+
}
|
|
91
|
+
return result.data;
|
|
60
92
|
}
|
|
61
93
|
exports.getModelAttributes = getModelAttributes;
|
|
62
94
|
/**
|