zenstack 2.0.0-alpha.7 → 2.0.0-beta.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.
@@ -12,326 +12,438 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.generate = void 0;
15
+ exports.EnhancerGenerator = void 0;
16
16
  const runtime_1 = require("@zenstackhq/runtime");
17
17
  const sdk_1 = require("@zenstackhq/sdk");
18
18
  const ast_1 = require("@zenstackhq/sdk/ast");
19
19
  const fs_1 = __importDefault(require("fs"));
20
20
  const path_1 = __importDefault(require("path"));
21
21
  const ts_morph_1 = require("ts-morph");
22
+ const upper_case_first_1 = require("upper-case-first");
22
23
  const __1 = require("..");
23
24
  const exec_utils_1 = require("../../../utils/exec-utils");
24
25
  const prisma_1 = require("../../prisma");
25
26
  const schema_generator_1 = require("../../prisma/schema-generator");
26
27
  const enhancer_utils_1 = require("../enhancer-utils");
27
- function generate(model, options, project, outDir) {
28
- return __awaiter(this, void 0, void 0, function* () {
29
- let logicalPrismaClientDir;
30
- let dmmf;
31
- const withLogicalClient = needsLogicalClient(model);
32
- if (withLogicalClient) {
33
- // schema contains delegate models, need to generate a logical prisma schema
34
- const result = yield generateLogicalPrisma(model, options, outDir);
35
- logicalPrismaClientDir = './.logical-prisma-client';
36
- dmmf = result.dmmf;
37
- // create a reexport of the logical prisma client
38
- const prismaDts = project.createSourceFile(path_1.default.join(outDir, 'prisma.d.ts'), `export type * from '${logicalPrismaClientDir}/index-fixed';`, { overwrite: true });
39
- yield prismaDts.save();
40
- }
41
- else {
42
- // just reexport the prisma client
43
- const prismaDts = project.createSourceFile(path_1.default.join(outDir, 'prisma.d.ts'), `export type * from '${(0, sdk_1.getPrismaClientImportSpec)(outDir, options)}';`, { overwrite: true });
44
- yield prismaDts.save();
45
- }
46
- const enhanceTs = project.createSourceFile(path_1.default.join(outDir, 'enhance.ts'), `import { createEnhancement, type EnhancementContext, type EnhancementOptions, type ZodSchemas } from '@zenstackhq/runtime';
28
+ const auth_type_generator_1 = require("./auth-type-generator");
29
+ class EnhancerGenerator {
30
+ constructor(model, options, project, outDir) {
31
+ this.model = model;
32
+ this.options = options;
33
+ this.project = project;
34
+ this.outDir = outDir;
35
+ }
36
+ generate() {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ let logicalPrismaClientDir;
39
+ let dmmf;
40
+ const prismaImport = (0, sdk_1.getPrismaClientImportSpec)(this.outDir, this.options);
41
+ if (this.needsLogicalClient()) {
42
+ // schema contains delegate models, need to generate a logical prisma schema
43
+ const result = yield this.generateLogicalPrisma();
44
+ logicalPrismaClientDir = './.logical-prisma-client';
45
+ dmmf = result.dmmf;
46
+ // create a reexport of the logical prisma client
47
+ const prismaDts = this.project.createSourceFile(path_1.default.join(this.outDir, 'prisma.d.ts'), `export type * from '${logicalPrismaClientDir}/index-fixed';`, { overwrite: true });
48
+ yield prismaDts.save();
49
+ }
50
+ else {
51
+ // just reexport the prisma client
52
+ const prismaDts = this.project.createSourceFile(path_1.default.join(this.outDir, 'prisma.d.ts'), `export type * from '${prismaImport}';`, { overwrite: true });
53
+ yield prismaDts.save();
54
+ }
55
+ const authModel = (0, sdk_1.getAuthModel)((0, sdk_1.getDataModels)(this.model));
56
+ const authTypes = authModel ? (0, auth_type_generator_1.generateAuthType)(this.model, authModel) : '';
57
+ const authTypeParam = authModel ? `auth.${authModel.name}` : 'AuthUser';
58
+ const enhanceTs = this.project.createSourceFile(path_1.default.join(this.outDir, 'enhance.ts'), `import { createEnhancement, type EnhancementContext, type EnhancementOptions, type ZodSchemas, type AuthUser } from '@zenstackhq/runtime';
47
59
  import modelMeta from './model-meta';
48
60
  import policy from './policy';
49
- ${options.withZodSchemas ? "import * as zodSchemas from './zod';" : 'const zodSchemas = undefined;'}
50
- import { Prisma } from '${(0, sdk_1.getPrismaClientImportSpec)(outDir, options)}';
51
- ${withLogicalClient ? `import { type PrismaClient } from '${logicalPrismaClientDir}/index-fixed';` : ``}
61
+ ${this.options.withZodSchemas ? "import * as zodSchemas from './zod';" : 'const zodSchemas = undefined;'}
62
+
63
+ ${logicalPrismaClientDir
64
+ ? this.createLogicalPrismaImports(prismaImport, logicalPrismaClientDir)
65
+ : this.createSimplePrismaImports(prismaImport)}
52
66
 
53
- export function enhance<DbClient extends object>(prisma: DbClient, context?: EnhancementContext, options?: EnhancementOptions)${withLogicalClient ? ': PrismaClient' : ''} {
67
+ ${authTypes}
68
+
69
+ ${logicalPrismaClientDir
70
+ ? this.createLogicalPrismaEnhanceFunction(authTypeParam)
71
+ : this.createSimplePrismaEnhanceFunction(authTypeParam)}
72
+ `, { overwrite: true });
73
+ yield this.saveSourceFile(enhanceTs);
74
+ return { dmmf };
75
+ });
76
+ }
77
+ createSimplePrismaImports(prismaImport) {
78
+ return `import { Prisma } from '${prismaImport}';
79
+ import type * as _P from '${prismaImport}';
80
+ `;
81
+ }
82
+ createSimplePrismaEnhanceFunction(authTypeParam) {
83
+ return `
84
+ export function enhance<DbClient extends object>(prisma: DbClient, context?: EnhancementContext<${authTypeParam}>, options?: EnhancementOptions) {
54
85
  return createEnhancement(prisma, {
55
86
  modelMeta,
56
87
  policy,
57
88
  zodSchemas: zodSchemas as unknown as (ZodSchemas | undefined),
58
89
  prismaModule: Prisma,
59
90
  ...options
60
- }, context)${withLogicalClient ? ' as PrismaClient' : ''};
61
- }
62
- `, { overwrite: true });
63
- yield saveSourceFile(enhanceTs, options);
64
- return { dmmf };
65
- });
66
- }
67
- exports.generate = generate;
68
- function needsLogicalClient(model) {
69
- return hasDelegateModel(model) || hasAuthInDefault(model);
70
- }
71
- function hasDelegateModel(model) {
72
- const dataModels = (0, sdk_1.getDataModels)(model);
73
- return dataModels.some((dm) => (0, sdk_1.isDelegateModel)(dm) && dataModels.some((sub) => sub.superTypes.some((base) => base.ref === dm)));
74
- }
75
- function hasAuthInDefault(model) {
76
- return (0, sdk_1.getDataModels)(model).some((dm) => dm.fields.some((f) => f.attributes.some((attr) => (0, enhancer_utils_1.isDefaultWithAuth)(attr))));
91
+ }, context);
92
+ }
93
+ `;
94
+ }
95
+ createLogicalPrismaImports(prismaImport, logicalPrismaClientDir) {
96
+ return `import { Prisma as _Prisma, PrismaClient as _PrismaClient } from '${prismaImport}';
97
+ import type {
98
+ InternalArgs,
99
+ TypeMapDef,
100
+ TypeMapCbDef,
101
+ DynamicClientExtensionThis,
102
+ } from '${prismaImport}/runtime/library';
103
+ import type * as _P from '${logicalPrismaClientDir}/index-fixed';
104
+ import type { Prisma, PrismaClient } from '${logicalPrismaClientDir}/index-fixed';
105
+ `;
106
+ }
107
+ createLogicalPrismaEnhanceFunction(authTypeParam) {
108
+ return `
109
+ // overload for plain PrismaClient
110
+ export function enhance<ExtArgs extends Record<string, any> & InternalArgs>(
111
+ prisma: _PrismaClient<any, any, ExtArgs>,
112
+ context?: EnhancementContext<${authTypeParam}>, options?: EnhancementOptions): PrismaClient;
113
+
114
+ // overload for extended PrismaClient
115
+ export function enhance<TypeMap extends TypeMapDef, TypeMapCb extends TypeMapCbDef, ExtArgs extends Record<string, any> & InternalArgs>(
116
+ prisma: DynamicClientExtensionThis<TypeMap, TypeMapCb, ExtArgs>,
117
+ context?: EnhancementContext<${authTypeParam}>, options?: EnhancementOptions): DynamicClientExtensionThis<Prisma.TypeMap, Prisma.TypeMapCb, ExtArgs>;
118
+
119
+ export function enhance(prisma: any, context?: EnhancementContext<${authTypeParam}>, options?: EnhancementOptions): any {
120
+ return createEnhancement(prisma, {
121
+ modelMeta,
122
+ policy,
123
+ zodSchemas: zodSchemas as unknown as (ZodSchemas | undefined),
124
+ prismaModule: _Prisma,
125
+ ...options
126
+ }, context);
77
127
  }
78
- function generateLogicalPrisma(model, options, outDir) {
79
- return __awaiter(this, void 0, void 0, function* () {
80
- const prismaGenerator = new schema_generator_1.PrismaSchemaGenerator(model);
81
- const prismaClientOutDir = './.logical-prisma-client';
82
- const logicalPrismaFile = path_1.default.join(outDir, 'logical.prisma');
83
- yield prismaGenerator.generate({
84
- provider: '@internal', // doesn't matter
85
- schemaPath: options.schemaPath,
86
- output: logicalPrismaFile,
87
- overrideClientGenerationPath: prismaClientOutDir,
88
- mode: 'logical',
89
- });
90
- // generate the prisma client
91
- const generateCmd = `prisma generate --schema "${logicalPrismaFile}" --no-engine`;
92
- try {
93
- // run 'prisma generate'
94
- yield (0, exec_utils_1.execPackage)(generateCmd, { stdio: 'ignore' });
95
- }
96
- catch (_a) {
97
- yield (0, prisma_1.trackPrismaSchemaError)(logicalPrismaFile);
128
+ `;
129
+ }
130
+ needsLogicalClient() {
131
+ return this.hasDelegateModel(this.model) || this.hasAuthInDefault(this.model);
132
+ }
133
+ hasDelegateModel(model) {
134
+ const dataModels = (0, sdk_1.getDataModels)(model);
135
+ return dataModels.some((dm) => (0, sdk_1.isDelegateModel)(dm) && dataModels.some((sub) => sub.superTypes.some((base) => base.ref === dm)));
136
+ }
137
+ hasAuthInDefault(model) {
138
+ return (0, sdk_1.getDataModels)(model).some((dm) => dm.fields.some((f) => f.attributes.some((attr) => (0, enhancer_utils_1.isDefaultWithAuth)(attr))));
139
+ }
140
+ generateLogicalPrisma() {
141
+ return __awaiter(this, void 0, void 0, function* () {
142
+ const prismaGenerator = new schema_generator_1.PrismaSchemaGenerator(this.model);
143
+ const prismaClientOutDir = './.logical-prisma-client';
144
+ const logicalPrismaFile = path_1.default.join(this.outDir, 'logical.prisma');
145
+ yield prismaGenerator.generate({
146
+ provider: '@internal', // doesn't matter
147
+ schemaPath: this.options.schemaPath,
148
+ output: logicalPrismaFile,
149
+ overrideClientGenerationPath: prismaClientOutDir,
150
+ mode: 'logical',
151
+ });
152
+ // generate the prisma client
153
+ const generateCmd = `prisma generate --schema "${logicalPrismaFile}" --no-engine`;
98
154
  try {
99
- // run 'prisma generate' again with output to the console
100
- yield (0, exec_utils_1.execPackage)(generateCmd);
155
+ // run 'prisma generate'
156
+ yield (0, exec_utils_1.execPackage)(generateCmd, { stdio: 'ignore' });
101
157
  }
102
- catch (_b) {
103
- // noop
158
+ catch (_a) {
159
+ yield (0, prisma_1.trackPrismaSchemaError)(logicalPrismaFile);
160
+ try {
161
+ // run 'prisma generate' again with output to the console
162
+ yield (0, exec_utils_1.execPackage)(generateCmd);
163
+ }
164
+ catch (_b) {
165
+ // noop
166
+ }
167
+ throw new sdk_1.PluginError(__1.name, `Failed to run "prisma generate" on logical schema: ${logicalPrismaFile}`);
104
168
  }
105
- throw new sdk_1.PluginError(__1.name, `Failed to run "prisma generate" on logical schema: ${logicalPrismaFile}`);
106
- }
107
- // make a bunch of typing fixes to the generated prisma client
108
- yield processClientTypes(model, path_1.default.join(outDir, prismaClientOutDir));
109
- return {
110
- prismaSchema: logicalPrismaFile,
111
- // load the dmmf of the logical prisma schema
112
- dmmf: yield (0, sdk_1.getDMMF)({ datamodel: fs_1.default.readFileSync(logicalPrismaFile, { encoding: 'utf-8' }) }),
113
- };
114
- });
115
- }
116
- function processClientTypes(model, prismaClientDir) {
117
- return __awaiter(this, void 0, void 0, function* () {
118
- // make necessary updates to the generated `index.d.ts` file and save it as `index-fixed.d.ts`
119
- const project = new ts_morph_1.Project();
120
- const sf = project.addSourceFileAtPath(path_1.default.join(prismaClientDir, 'index.d.ts'));
121
- // build a map of delegate models and their sub models
122
- const delegateInfo = [];
123
- model.declarations
124
- .filter((d) => (0, sdk_1.isDelegateModel)(d))
125
- .forEach((dm) => {
126
- delegateInfo.push([
127
- dm,
128
- model.declarations.filter((d) => (0, ast_1.isDataModel)(d) && d.superTypes.some((s) => s.ref === dm)),
129
- ]);
169
+ // make a bunch of typing fixes to the generated prisma client
170
+ yield this.processClientTypes(path_1.default.join(this.outDir, prismaClientOutDir));
171
+ return {
172
+ prismaSchema: logicalPrismaFile,
173
+ // load the dmmf of the logical prisma schema
174
+ dmmf: yield (0, sdk_1.getDMMF)({ datamodel: fs_1.default.readFileSync(logicalPrismaFile, { encoding: 'utf-8' }) }),
175
+ };
130
176
  });
131
- const sfNew = project.createSourceFile(path_1.default.join(prismaClientDir, 'index-fixed.d.ts'), undefined, {
132
- overwrite: true,
177
+ }
178
+ processClientTypes(prismaClientDir) {
179
+ return __awaiter(this, void 0, void 0, function* () {
180
+ // make necessary updates to the generated `index.d.ts` file and save it as `index-fixed.d.ts`
181
+ const project = new ts_morph_1.Project();
182
+ const sf = project.addSourceFileAtPath(path_1.default.join(prismaClientDir, 'index.d.ts'));
183
+ // build a map of delegate models and their sub models
184
+ const delegateInfo = [];
185
+ this.model.declarations
186
+ .filter((d) => (0, sdk_1.isDelegateModel)(d))
187
+ .forEach((dm) => {
188
+ delegateInfo.push([
189
+ dm,
190
+ this.model.declarations.filter((d) => (0, ast_1.isDataModel)(d) && d.superTypes.some((s) => s.ref === dm)),
191
+ ]);
192
+ });
193
+ const sfNew = project.createSourceFile(path_1.default.join(prismaClientDir, 'index-fixed.d.ts'), undefined, {
194
+ overwrite: true,
195
+ });
196
+ if (delegateInfo.length > 0) {
197
+ // transform types for delegated models
198
+ this.transformDelegate(sf, sfNew, delegateInfo);
199
+ sfNew.formatText();
200
+ }
201
+ else {
202
+ // just copy
203
+ sfNew.replaceWithText(sf.getFullText());
204
+ }
205
+ yield sfNew.save();
133
206
  });
134
- if (delegateInfo.length > 0) {
135
- // transform types for delegated models
136
- transformDelegate(sf, sfNew, delegateInfo);
137
- sfNew.formatText();
207
+ }
208
+ transformDelegate(sf, sfNew, delegateInfo) {
209
+ // copy toplevel imports
210
+ sfNew.addImportDeclarations(sf.getImportDeclarations().map((n) => n.getStructure()));
211
+ // copy toplevel import equals
212
+ sfNew.addStatements(sf.getChildrenOfKind(ts_morph_1.SyntaxKind.ImportEqualsDeclaration).map((n) => n.getFullText()));
213
+ // copy toplevel exports
214
+ sfNew.addExportAssignments(sf.getExportAssignments().map((n) => n.getStructure()));
215
+ // copy toplevel type aliases
216
+ sfNew.addTypeAliases(sf.getTypeAliases().map((n) => n.getStructure()));
217
+ // copy toplevel classes
218
+ sfNew.addClasses(sf.getClasses().map((n) => n.getStructure()));
219
+ // copy toplevel variables
220
+ sfNew.addVariableStatements(sf.getVariableStatements().map((n) => n.getStructure()));
221
+ // copy toplevel namespaces except for `Prisma`
222
+ sfNew.addModules(sf
223
+ .getModules()
224
+ .filter((n) => n.getName() !== 'Prisma')
225
+ .map((n) => n.getStructure()));
226
+ // transform the `Prisma` namespace
227
+ const prismaModule = sf.getModuleOrThrow('Prisma');
228
+ const newPrismaModule = sfNew.addModule({ name: 'Prisma', isExported: true });
229
+ this.transformPrismaModule(prismaModule, newPrismaModule, delegateInfo);
230
+ }
231
+ transformPrismaModule(prismaModule, newPrismaModule, delegateInfo) {
232
+ // module block is the direct container of declarations inside a namespace
233
+ const moduleBlock = prismaModule.getFirstChildByKindOrThrow(ts_morph_1.SyntaxKind.ModuleBlock);
234
+ // most of the toplevel constructs should be copied over
235
+ // here we use ts-morph batch operations for optimal performance
236
+ // copy imports
237
+ newPrismaModule.addStatements(moduleBlock.getChildrenOfKind(ts_morph_1.SyntaxKind.ImportEqualsDeclaration).map((n) => n.getFullText()));
238
+ // copy classes
239
+ newPrismaModule.addClasses(moduleBlock.getClasses().map((n) => n.getStructure()));
240
+ // copy functions
241
+ newPrismaModule.addFunctions(moduleBlock.getFunctions().map((n) => n.getStructure()));
242
+ // copy nested namespaces
243
+ newPrismaModule.addModules(moduleBlock.getModules().map((n) => n.getStructure()));
244
+ // transform variables
245
+ const newVariables = moduleBlock
246
+ .getVariableStatements()
247
+ .map((variable) => this.transformVariableStatement(variable));
248
+ newPrismaModule.addVariableStatements(newVariables);
249
+ // transform interfaces
250
+ const newInterfaces = moduleBlock.getInterfaces().map((iface) => this.transformInterface(iface, delegateInfo));
251
+ newPrismaModule.addInterfaces(newInterfaces);
252
+ // transform type aliases
253
+ const newTypeAliases = moduleBlock
254
+ .getTypeAliases()
255
+ .map((typeAlias) => this.transformTypeAlias(typeAlias, delegateInfo));
256
+ newPrismaModule.addTypeAliases(newTypeAliases);
257
+ }
258
+ transformVariableStatement(variable) {
259
+ const structure = variable.getStructure();
260
+ // remove `delegate_aux_*` fields from the variable's typing
261
+ const auxFields = this.findAuxDecls(variable);
262
+ if (auxFields.length > 0) {
263
+ structure.declarations.forEach((variable) => {
264
+ var _a;
265
+ let source = (_a = variable.type) === null || _a === void 0 ? void 0 : _a.toString();
266
+ auxFields.forEach((f) => {
267
+ source = source === null || source === void 0 ? void 0 : source.replace(f.getText(), '');
268
+ });
269
+ variable.type = source;
270
+ });
138
271
  }
139
- else {
140
- // just copy
141
- sfNew.replaceWithText(sf.getFullText());
272
+ return structure;
273
+ }
274
+ transformInterface(iface, delegateInfo) {
275
+ var _a, _b, _c;
276
+ const structure = iface.getStructure();
277
+ // filter out aux fields
278
+ structure.properties = (_a = structure.properties) === null || _a === void 0 ? void 0 : _a.filter((p) => !p.name.startsWith(runtime_1.DELEGATE_AUX_RELATION_PREFIX));
279
+ // filter out aux methods
280
+ structure.methods = (_b = structure.methods) === null || _b === void 0 ? void 0 : _b.filter((m) => !m.name.startsWith(runtime_1.DELEGATE_AUX_RELATION_PREFIX));
281
+ if (delegateInfo.some(([delegate]) => `${delegate.name}Delegate` === iface.getName())) {
282
+ // delegate models cannot be created directly, remove create/createMany/upsert
283
+ structure.methods = (_c = structure.methods) === null || _c === void 0 ? void 0 : _c.filter((m) => !['create', 'createMany', 'upsert'].includes(m.name));
142
284
  }
143
- yield sfNew.save();
144
- });
145
- }
146
- function transformDelegate(sf, sfNew, delegateModels) {
147
- // copy toplevel imports
148
- sfNew.addImportDeclarations(sf.getImportDeclarations().map((n) => n.getStructure()));
149
- // copy toplevel import equals
150
- sfNew.addStatements(sf.getChildrenOfKind(ts_morph_1.SyntaxKind.ImportEqualsDeclaration).map((n) => n.getFullText()));
151
- // copy toplevel exports
152
- sfNew.addExportAssignments(sf.getExportAssignments().map((n) => n.getStructure()));
153
- // copy toplevel type aliases
154
- sfNew.addTypeAliases(sf.getTypeAliases().map((n) => n.getStructure()));
155
- // copy toplevel classes
156
- sfNew.addClasses(sf.getClasses().map((n) => n.getStructure()));
157
- // copy toplevel variables
158
- sfNew.addVariableStatements(sf.getVariableStatements().map((n) => n.getStructure()));
159
- // copy toplevel namespaces except for `Prisma`
160
- sfNew.addModules(sf
161
- .getModules()
162
- .filter((n) => n.getName() !== 'Prisma')
163
- .map((n) => n.getStructure()));
164
- // transform the `Prisma` namespace
165
- const prismaModule = sf.getModuleOrThrow('Prisma');
166
- const newPrismaModule = sfNew.addModule({ name: 'Prisma', isExported: true });
167
- transformPrismaModule(prismaModule, newPrismaModule, delegateModels);
168
- }
169
- function transformPrismaModule(prismaModule, newPrismaModule, delegateInfo) {
170
- // module block is the direct container of declarations inside a namespace
171
- const moduleBlock = prismaModule.getFirstChildByKindOrThrow(ts_morph_1.SyntaxKind.ModuleBlock);
172
- // most of the toplevel constructs should be copied over
173
- // here we use ts-morph batch operations for optimal performance
174
- // copy imports
175
- newPrismaModule.addStatements(moduleBlock.getChildrenOfKind(ts_morph_1.SyntaxKind.ImportEqualsDeclaration).map((n) => n.getFullText()));
176
- // copy classes
177
- newPrismaModule.addClasses(moduleBlock.getClasses().map((n) => n.getStructure()));
178
- // copy functions
179
- newPrismaModule.addFunctions(moduleBlock.getFunctions().map((n) => n.getStructure()));
180
- // copy nested namespaces
181
- newPrismaModule.addModules(moduleBlock.getModules().map((n) => n.getStructure()));
182
- // transform variables
183
- const newVariables = moduleBlock.getVariableStatements().map((variable) => transformVariableStatement(variable));
184
- newPrismaModule.addVariableStatements(newVariables);
185
- // transform interfaces
186
- const newInterfaces = moduleBlock.getInterfaces().map((iface) => transformInterface(iface, delegateInfo));
187
- newPrismaModule.addInterfaces(newInterfaces);
188
- // transform type aliases
189
- const newTypeAliases = moduleBlock.getTypeAliases().map((typeAlias) => transformTypeAlias(typeAlias, delegateInfo));
190
- newPrismaModule.addTypeAliases(newTypeAliases);
191
- }
192
- function transformVariableStatement(variable) {
193
- const structure = variable.getStructure();
194
- // remove `delegate_aux_*` fields from the variable's typing
195
- const auxFields = findAuxDecls(variable);
196
- if (auxFields.length > 0) {
197
- structure.declarations.forEach((variable) => {
198
- var _a;
199
- let source = (_a = variable.type) === null || _a === void 0 ? void 0 : _a.toString();
200
- auxFields.forEach((f) => {
201
- source = source === null || source === void 0 ? void 0 : source.replace(f.getText(), '');
202
- });
203
- variable.type = source;
204
- });
285
+ return structure;
205
286
  }
206
- return structure;
207
- }
208
- function transformInterface(iface, delegateInfo) {
209
- var _a, _b, _c;
210
- const structure = iface.getStructure();
211
- // filter out aux fields
212
- structure.properties = (_a = structure.properties) === null || _a === void 0 ? void 0 : _a.filter((p) => !p.name.startsWith(runtime_1.DELEGATE_AUX_RELATION_PREFIX));
213
- // filter out aux methods
214
- structure.methods = (_b = structure.methods) === null || _b === void 0 ? void 0 : _b.filter((m) => !m.name.startsWith(runtime_1.DELEGATE_AUX_RELATION_PREFIX));
215
- if (delegateInfo.some(([delegate]) => `${delegate.name}Delegate` === iface.getName())) {
216
- // delegate models cannot be created directly, remove create/createMany/upsert
217
- structure.methods = (_c = structure.methods) === null || _c === void 0 ? void 0 : _c.filter((m) => !['create', 'createMany', 'upsert'].includes(m.name));
287
+ transformTypeAlias(typeAlias, delegateInfo) {
288
+ const structure = typeAlias.getStructure();
289
+ let source = structure.type;
290
+ // remove aux fields
291
+ source = this.removeAuxFieldsFromTypeAlias(typeAlias, source);
292
+ // remove discriminator field from concrete input types
293
+ source = this.removeDiscriminatorFromConcreteInput(typeAlias, delegateInfo, source);
294
+ // remove create/connectOrCreate/upsert fields from delegate's input types
295
+ source = this.removeCreateFromDelegateInput(typeAlias, delegateInfo, source);
296
+ // remove delegate fields from nested mutation input types
297
+ source = this.removeDelegateFieldsFromNestedMutationInput(typeAlias, delegateInfo, source);
298
+ // fix delegate payload union type
299
+ source = this.fixDelegatePayloadType(typeAlias, delegateInfo, source);
300
+ structure.type = source;
301
+ return structure;
218
302
  }
219
- return structure;
220
- }
221
- function transformTypeAlias(typeAlias, delegateInfo) {
222
- const structure = typeAlias.getStructure();
223
- let source = structure.type;
224
- // remove aux fields
225
- source = removeAuxFieldsFromTypeAlias(typeAlias, source);
226
- // remove discriminator field from concrete input types
227
- source = removeDiscriminatorFromConcreteInput(typeAlias, delegateInfo, source);
228
- // remove create/connectOrCreate/upsert fields from delegate's input types
229
- source = removeCreateFromDelegateInput(typeAlias, delegateInfo, source);
230
- // fix delegate payload union type
231
- source = fixDelegatePayloadType(typeAlias, delegateInfo, source);
232
- structure.type = source;
233
- return structure;
234
- }
235
- function fixDelegatePayloadType(typeAlias, delegateInfo, source) {
236
- // change the type of `$<DelegateModel>Payload` type of delegate model to a union of concrete types
237
- const typeName = typeAlias.getName();
238
- const payloadRecord = delegateInfo.find(([delegate]) => `$${delegate.name}Payload` === typeName);
239
- if (payloadRecord) {
240
- const discriminatorDecl = getDiscriminatorField(payloadRecord[0]);
241
- if (discriminatorDecl) {
242
- source = `${payloadRecord[1]
243
- .map((concrete) => `($${concrete.name}Payload<ExtArgs> & { scalars: { ${discriminatorDecl.name}: '${concrete.name}' } })`)
244
- .join(' | ')}`;
303
+ fixDelegatePayloadType(typeAlias, delegateInfo, source) {
304
+ // change the type of `$<DelegateModel>Payload` type of delegate model to a union of concrete types
305
+ const typeName = typeAlias.getName();
306
+ const payloadRecord = delegateInfo.find(([delegate]) => `$${delegate.name}Payload` === typeName);
307
+ if (payloadRecord) {
308
+ const discriminatorDecl = this.getDiscriminatorField(payloadRecord[0]);
309
+ if (discriminatorDecl) {
310
+ source = `${payloadRecord[1]
311
+ .map((concrete) => `($${concrete.name}Payload<ExtArgs> & { scalars: { ${discriminatorDecl.name}: '${concrete.name}' } })`)
312
+ .join(' | ')}`;
313
+ }
245
314
  }
315
+ return source;
246
316
  }
247
- return source;
248
- }
249
- function removeCreateFromDelegateInput(typeAlias, delegateModels, source) {
250
- // remove create/connectOrCreate/upsert fields from delegate's input types because
251
- // delegate models cannot be created directly
252
- const typeName = typeAlias.getName();
253
- const delegateModelNames = delegateModels.map(([delegate]) => delegate.name);
254
- const delegateCreateUpdateInputRegex = new RegExp(`\\${delegateModelNames.join('|')}(Unchecked)?(Create|Update).*Input`);
255
- if (delegateCreateUpdateInputRegex.test(typeName)) {
256
- const toRemove = typeAlias
257
- .getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertySignature)
258
- .filter((p) => ['create', 'connectOrCreate', 'upsert'].includes(p.getName()));
259
- toRemove.forEach((r) => {
260
- source = source.replace(r.getText(), '');
261
- });
317
+ removeCreateFromDelegateInput(typeAlias, delegateModels, source) {
318
+ // remove create/connectOrCreate/upsert fields from delegate's input types because
319
+ // delegate models cannot be created directly
320
+ const typeName = typeAlias.getName();
321
+ const delegateModelNames = delegateModels.map(([delegate]) => delegate.name);
322
+ const delegateCreateUpdateInputRegex = new RegExp(`\\${delegateModelNames.join('|')}(Unchecked)?(Create|Update).*Input`);
323
+ if (delegateCreateUpdateInputRegex.test(typeName)) {
324
+ const toRemove = typeAlias
325
+ .getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertySignature)
326
+ .filter((p) => ['create', 'connectOrCreate', 'upsert'].includes(p.getName()));
327
+ toRemove.forEach((r) => {
328
+ source = source.replace(r.getText(), '');
329
+ });
330
+ }
331
+ return source;
262
332
  }
263
- return source;
264
- }
265
- function removeDiscriminatorFromConcreteInput(typeAlias, delegateInfo, source) {
266
- // remove discriminator field from the create/update input of concrete models because
267
- // discriminator cannot be set directly
268
- const typeName = typeAlias.getName();
269
- const concreteModelNames = delegateInfo.map(([, concretes]) => concretes.map((c) => c.name)).flatMap((c) => c);
270
- const concreteCreateUpdateInputRegex = new RegExp(`(${concreteModelNames.join('|')})(Unchecked)?(Create|Update).*Input`);
271
- const match = typeName.match(concreteCreateUpdateInputRegex);
272
- if (match) {
273
- const modelName = match[1];
274
- const record = delegateInfo.find(([, concretes]) => concretes.some((c) => c.name === modelName));
275
- if (record) {
276
- // remove all discriminator fields recursively
277
- const delegateOfConcrete = record[0];
278
- const discriminators = getDiscriminatorFieldsRecursively(delegateOfConcrete);
279
- discriminators.forEach((discriminatorDecl) => {
280
- const discriminatorNode = findNamedProperty(typeAlias, discriminatorDecl.name);
281
- if (discriminatorNode) {
282
- source = source.replace(discriminatorNode.getText(), '');
283
- }
333
+ removeDiscriminatorFromConcreteInput(typeAlias, delegateInfo, source) {
334
+ // remove discriminator field from the create/update input of concrete models because
335
+ // discriminator cannot be set directly
336
+ const typeName = typeAlias.getName();
337
+ const concreteModelNames = delegateInfo.map(([, concretes]) => concretes.map((c) => c.name)).flatMap((c) => c);
338
+ const concreteCreateUpdateInputRegex = new RegExp(`(${concreteModelNames.join('|')})(Unchecked)?(Create|Update).*Input`);
339
+ const match = typeName.match(concreteCreateUpdateInputRegex);
340
+ if (match) {
341
+ const modelName = match[1];
342
+ const record = delegateInfo.find(([, concretes]) => concretes.some((c) => c.name === modelName));
343
+ if (record) {
344
+ // remove all discriminator fields recursively
345
+ const delegateOfConcrete = record[0];
346
+ const discriminators = this.getDiscriminatorFieldsRecursively(delegateOfConcrete);
347
+ discriminators.forEach((discriminatorDecl) => {
348
+ const discriminatorNode = this.findNamedProperty(typeAlias, discriminatorDecl.name);
349
+ if (discriminatorNode) {
350
+ source = source.replace(discriminatorNode.getText(), '');
351
+ }
352
+ });
353
+ }
354
+ }
355
+ return source;
356
+ }
357
+ removeAuxFieldsFromTypeAlias(typeAlias, source) {
358
+ // remove `delegate_aux_*` fields from the type alias
359
+ const auxDecls = this.findAuxDecls(typeAlias);
360
+ if (auxDecls.length > 0) {
361
+ auxDecls.forEach((d) => {
362
+ source = source.replace(d.getText(), '');
284
363
  });
285
364
  }
365
+ return source;
286
366
  }
287
- return source;
288
- }
289
- function removeAuxFieldsFromTypeAlias(typeAlias, source) {
290
- // remove `delegate_aux_*` fields from the type alias
291
- const auxDecls = findAuxDecls(typeAlias);
292
- if (auxDecls.length > 0) {
293
- auxDecls.forEach((d) => {
294
- source = source.replace(d.getText(), '');
367
+ removeDelegateFieldsFromNestedMutationInput(typeAlias, _delegateInfo, source) {
368
+ const name = typeAlias.getName();
369
+ // remove delegate model fields (and corresponding fk fields) from
370
+ // create/update input types nested inside concrete models
371
+ const regex = new RegExp(`(.+)(Create|Update)Without${(0, upper_case_first_1.upperCaseFirst)(runtime_1.DELEGATE_AUX_RELATION_PREFIX)}_(.+)Input`);
372
+ const match = name.match(regex);
373
+ if (!match) {
374
+ return source;
375
+ }
376
+ const nameTuple = match[3]; // [modelName]_[relationFieldName]_[concreteModelName]
377
+ const [modelName, relationFieldName, _] = nameTuple.split('_');
378
+ const fieldDef = this.findNamedProperty(typeAlias, relationFieldName);
379
+ if (fieldDef) {
380
+ // remove relation field of delegate type, e.g., `asset`
381
+ source = source.replace(fieldDef.getText(), '');
382
+ }
383
+ // remove fk fields related to the delegate type relation, e.g., `assetId`
384
+ const relationModel = this.model.declarations.find((d) => (0, ast_1.isDataModel)(d) && d.name === modelName);
385
+ if (!relationModel) {
386
+ return source;
387
+ }
388
+ const relationField = relationModel.fields.find((f) => f.name === relationFieldName);
389
+ if (!relationField) {
390
+ return source;
391
+ }
392
+ const relAttr = (0, sdk_1.getAttribute)(relationField, '@relation');
393
+ if (!relAttr) {
394
+ return source;
395
+ }
396
+ const fieldsArg = (0, sdk_1.getAttributeArg)(relAttr, 'fields');
397
+ let fkFields = [];
398
+ if ((0, ast_1.isArrayExpr)(fieldsArg)) {
399
+ fkFields = fieldsArg.items.map((e) => e.target.$refText);
400
+ }
401
+ fkFields.forEach((fkField) => {
402
+ const fieldDef = this.findNamedProperty(typeAlias, fkField);
403
+ if (fieldDef) {
404
+ source = source.replace(fieldDef.getText(), '');
405
+ }
295
406
  });
407
+ return source;
296
408
  }
297
- return source;
298
- }
299
- function findNamedProperty(typeAlias, name) {
300
- return typeAlias.getFirstDescendant((d) => d.isKind(ts_morph_1.SyntaxKind.PropertySignature) && d.getName() === name);
301
- }
302
- function findAuxDecls(node) {
303
- return node
304
- .getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertySignature)
305
- .filter((n) => n.getName().startsWith(runtime_1.DELEGATE_AUX_RELATION_PREFIX));
306
- }
307
- function getDiscriminatorField(delegate) {
308
- var _a;
309
- const delegateAttr = (0, sdk_1.getAttribute)(delegate, '@@delegate');
310
- if (!delegateAttr) {
311
- return undefined;
409
+ findNamedProperty(typeAlias, name) {
410
+ return typeAlias.getFirstDescendant((d) => d.isKind(ts_morph_1.SyntaxKind.PropertySignature) && d.getName() === name);
312
411
  }
313
- const arg = (_a = delegateAttr.args[0]) === null || _a === void 0 ? void 0 : _a.value;
314
- return (0, ast_1.isReferenceExpr)(arg) ? arg.target.ref : undefined;
315
- }
316
- function getDiscriminatorFieldsRecursively(delegate, result = []) {
317
- if ((0, sdk_1.isDelegateModel)(delegate)) {
318
- const discriminator = getDiscriminatorField(delegate);
319
- if (discriminator) {
320
- result.push(discriminator);
412
+ findAuxDecls(node) {
413
+ return node
414
+ .getDescendantsOfKind(ts_morph_1.SyntaxKind.PropertySignature)
415
+ .filter((n) => n.getName().startsWith(runtime_1.DELEGATE_AUX_RELATION_PREFIX));
416
+ }
417
+ getDiscriminatorField(delegate) {
418
+ var _a;
419
+ const delegateAttr = (0, sdk_1.getAttribute)(delegate, '@@delegate');
420
+ if (!delegateAttr) {
421
+ return undefined;
321
422
  }
322
- for (const superType of delegate.superTypes) {
323
- if (superType.ref) {
324
- result.push(...getDiscriminatorFieldsRecursively(superType.ref, result));
423
+ const arg = (_a = delegateAttr.args[0]) === null || _a === void 0 ? void 0 : _a.value;
424
+ return (0, ast_1.isReferenceExpr)(arg) ? arg.target.ref : undefined;
425
+ }
426
+ getDiscriminatorFieldsRecursively(delegate, result = []) {
427
+ if ((0, sdk_1.isDelegateModel)(delegate)) {
428
+ const discriminator = this.getDiscriminatorField(delegate);
429
+ if (discriminator) {
430
+ result.push(discriminator);
431
+ }
432
+ for (const superType of delegate.superTypes) {
433
+ if (superType.ref) {
434
+ result.push(...this.getDiscriminatorFieldsRecursively(superType.ref, result));
435
+ }
325
436
  }
326
437
  }
438
+ return result;
439
+ }
440
+ saveSourceFile(sf) {
441
+ return __awaiter(this, void 0, void 0, function* () {
442
+ if (this.options.preserveTsFiles) {
443
+ yield sf.save();
444
+ }
445
+ });
327
446
  }
328
- return result;
329
- }
330
- function saveSourceFile(sf, options) {
331
- return __awaiter(this, void 0, void 0, function* () {
332
- if (options.preserveTsFiles) {
333
- yield sf.save();
334
- }
335
- });
336
447
  }
448
+ exports.EnhancerGenerator = EnhancerGenerator;
337
449
  //# sourceMappingURL=index.js.map