zenstack 0.1.47 → 0.1.50

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.
Files changed (169) hide show
  1. package/LICENSE.md +9 -0
  2. package/bin/cli +1 -1
  3. package/bundle/asset/logo-dark-256.png +0 -0
  4. package/bundle/asset/logo-dark.png +0 -0
  5. package/bundle/asset/logo-light-256.png +0 -0
  6. package/bundle/asset/logo-light.png +0 -0
  7. package/bundle/cli/index.js +6849 -0
  8. package/bundle/cli/index.js.map +7 -0
  9. package/bundle/extension.js +39 -0
  10. package/bundle/extension.js.map +7 -0
  11. package/bundle/language-server/main.js +6105 -0
  12. package/bundle/language-server/main.js.map +7 -0
  13. package/{out/generator → bundle/res}/package.template.json +0 -0
  14. package/bundle/res/stdlib.zmodel +101 -0
  15. package/{out/generator → bundle/res}/tsconfig.template.json +0 -0
  16. package/package.json +38 -14
  17. package/src/cli/cli-util.ts +71 -0
  18. package/src/cli/index.ts +182 -0
  19. package/src/extension.ts +76 -0
  20. package/src/generator/constants.ts +5 -0
  21. package/src/generator/index.ts +102 -0
  22. package/{out/generator/next-auth/index.js → src/generator/next-auth/index.ts} +49 -58
  23. package/src/generator/prisma/expression-writer.ts +360 -0
  24. package/src/generator/prisma/index.ts +35 -0
  25. package/src/generator/prisma/prisma-builder.ts +370 -0
  26. package/src/generator/prisma/query-gard-generator.ts +213 -0
  27. package/src/generator/prisma/schema-generator.ts +305 -0
  28. package/src/generator/prisma/typescript-expression-transformer.ts +108 -0
  29. package/src/generator/react-hooks/index.ts +184 -0
  30. package/src/generator/service/index.ts +110 -0
  31. package/src/generator/types.ts +17 -0
  32. package/src/generator/utils.ts +18 -0
  33. package/src/language-server/constants.ts +28 -0
  34. package/src/language-server/generated/ast.ts +616 -0
  35. package/{out/language-server/generated/grammar.js → src/language-server/generated/grammar.ts} +5 -8
  36. package/src/language-server/generated/module.ts +24 -0
  37. package/src/language-server/langium-ext.d.ts +10 -0
  38. package/src/language-server/lsp/zmodel-definition-provider.ts +87 -0
  39. package/src/language-server/main.ts +13 -0
  40. package/src/language-server/types.ts +25 -0
  41. package/src/language-server/validator/attribute-validator.ts +11 -0
  42. package/src/language-server/validator/datamodel-validator.ts +311 -0
  43. package/src/language-server/validator/datasource-validator.ts +102 -0
  44. package/src/language-server/validator/enum-validator.ts +14 -0
  45. package/src/language-server/validator/schema-validator.ts +31 -0
  46. package/src/language-server/validator/utils.ts +158 -0
  47. package/src/language-server/validator/zmodel-validator.ts +84 -0
  48. package/src/language-server/zmodel-linker.ts +446 -0
  49. package/src/language-server/zmodel-module.ts +136 -0
  50. package/src/language-server/zmodel-scope.ts +45 -0
  51. package/src/language-server/zmodel-workspace-manager.ts +23 -0
  52. package/src/language-server/zmodel.langium +197 -0
  53. package/{out/cli → src/res}/package.template.json +2 -3
  54. package/src/res/stdlib.zmodel +101 -0
  55. package/{out/cli → src/res}/tsconfig.template.json +1 -1
  56. package/src/utils/exec-utils.ts +8 -0
  57. package/src/utils/indent-string.ts +9 -0
  58. package/LICENSE +0 -21
  59. package/out/cli/cli-util.js +0 -64
  60. package/out/cli/cli-util.js.map +0 -1
  61. package/out/cli/generator.js +0 -1
  62. package/out/cli/generator.js.map +0 -1
  63. package/out/cli/index.js +0 -124
  64. package/out/cli/index.js.map +0 -1
  65. package/out/extension.js +0 -81
  66. package/out/extension.js.map +0 -1
  67. package/out/generator/constants.js +0 -9
  68. package/out/generator/constants.js.map +0 -1
  69. package/out/generator/data-server/index.js +0 -1
  70. package/out/generator/data-server/index.js.map +0 -1
  71. package/out/generator/index.js +0 -98
  72. package/out/generator/index.js.map +0 -1
  73. package/out/generator/next-auth/index.js.map +0 -1
  74. package/out/generator/prisma/expression-writer.js +0 -287
  75. package/out/generator/prisma/expression-writer.js.map +0 -1
  76. package/out/generator/prisma/index.js +0 -44
  77. package/out/generator/prisma/index.js.map +0 -1
  78. package/out/generator/prisma/plain-expression-builder.js +0 -69
  79. package/out/generator/prisma/plain-expression-builder.js.map +0 -1
  80. package/out/generator/prisma/prisma-builder.js +0 -307
  81. package/out/generator/prisma/prisma-builder.js.map +0 -1
  82. package/out/generator/prisma/query-gard-generator.js +0 -159
  83. package/out/generator/prisma/query-gard-generator.js.map +0 -1
  84. package/out/generator/prisma/schema-generator.js +0 -193
  85. package/out/generator/prisma/schema-generator.js.map +0 -1
  86. package/out/generator/query-guard/index.js +0 -2
  87. package/out/generator/query-guard/index.js.map +0 -1
  88. package/out/generator/react-hooks/index.js +0 -179
  89. package/out/generator/react-hooks/index.js.map +0 -1
  90. package/out/generator/server/data/data-generator.js +0 -376
  91. package/out/generator/server/data/data-generator.js.map +0 -1
  92. package/out/generator/server/data/expression-writer.js +0 -287
  93. package/out/generator/server/data/expression-writer.js.map +0 -1
  94. package/out/generator/server/data/plain-expression-builder.js +0 -69
  95. package/out/generator/server/data/plain-expression-builder.js.map +0 -1
  96. package/out/generator/server/data-generator.js +0 -82
  97. package/out/generator/server/data-generator.js.map +0 -1
  98. package/out/generator/server/expression-writer.js +0 -1
  99. package/out/generator/server/expression-writer.js.map +0 -1
  100. package/out/generator/server/function/function-generator.js +0 -50
  101. package/out/generator/server/function/function-generator.js.map +0 -1
  102. package/out/generator/server/function-generator.js +0 -13
  103. package/out/generator/server/function-generator.js.map +0 -1
  104. package/out/generator/server/index.js +0 -88
  105. package/out/generator/server/index.js.map +0 -1
  106. package/out/generator/server/js-expression-builder.js +0 -1
  107. package/out/generator/server/js-expression-builder.js.map +0 -1
  108. package/out/generator/server/plain-expression-builder.js +0 -1
  109. package/out/generator/server/plain-expression-builder.js.map +0 -1
  110. package/out/generator/server/server-code-generator.js +0 -3
  111. package/out/generator/server/server-code-generator.js.map +0 -1
  112. package/out/generator/server/server-code-writer.js +0 -1
  113. package/out/generator/server/server-code-writer.js.map +0 -1
  114. package/out/generator/service/index.js +0 -133
  115. package/out/generator/service/index.js.map +0 -1
  116. package/out/generator/types.js +0 -10
  117. package/out/generator/types.js.map +0 -1
  118. package/out/generator/utils.js +0 -10
  119. package/out/generator/utils.js.map +0 -1
  120. package/out/langium-ext.js +0 -3
  121. package/out/langium-ext.js.map +0 -1
  122. package/out/language-server/constants.js +0 -20
  123. package/out/language-server/constants.js.map +0 -1
  124. package/out/language-server/generated/ast.js +0 -390
  125. package/out/language-server/generated/ast.js.map +0 -1
  126. package/out/language-server/generated/grammar.js.map +0 -1
  127. package/out/language-server/generated/module.js +0 -23
  128. package/out/language-server/generated/module.js.map +0 -1
  129. package/out/language-server/langium-ext.js +0 -3
  130. package/out/language-server/langium-ext.js.map +0 -1
  131. package/out/language-server/main.js +0 -13
  132. package/out/language-server/main.js.map +0 -1
  133. package/out/language-server/stdlib.zmodel +0 -23
  134. package/out/language-server/types.js +0 -3
  135. package/out/language-server/types.js.map +0 -1
  136. package/out/language-server/validator/attribute-validator copy.js +0 -12
  137. package/out/language-server/validator/attribute-validator copy.js.map +0 -1
  138. package/out/language-server/validator/attribute-validator.js +0 -7
  139. package/out/language-server/validator/attribute-validator.js.map +0 -1
  140. package/out/language-server/validator/datamodel-validator.js +0 -199
  141. package/out/language-server/validator/datamodel-validator.js.map +0 -1
  142. package/out/language-server/validator/datasource-validator copy.js +0 -77
  143. package/out/language-server/validator/datasource-validator copy.js.map +0 -1
  144. package/out/language-server/validator/datasource-validator.js +0 -77
  145. package/out/language-server/validator/datasource-validator.js.map +0 -1
  146. package/out/language-server/validator/enum-validator.js +0 -10
  147. package/out/language-server/validator/enum-validator.js.map +0 -1
  148. package/out/language-server/validator/model-validator.js +0 -21
  149. package/out/language-server/validator/model-validator.js.map +0 -1
  150. package/out/language-server/validator/schema-validator.js +0 -21
  151. package/out/language-server/validator/schema-validator.js.map +0 -1
  152. package/out/language-server/validator/utils.js +0 -106
  153. package/out/language-server/validator/utils.js.map +0 -1
  154. package/out/language-server/validator/zmodel-validator.js +0 -52
  155. package/out/language-server/validator/zmodel-validator.js.map +0 -1
  156. package/out/language-server/zmodel-index.js +0 -11
  157. package/out/language-server/zmodel-index.js.map +0 -1
  158. package/out/language-server/zmodel-linker.js +0 -249
  159. package/out/language-server/zmodel-linker.js.map +0 -1
  160. package/out/language-server/zmodel-module.js +0 -46
  161. package/out/language-server/zmodel-module.js.map +0 -1
  162. package/out/language-server/zmodel-scope.js +0 -41
  163. package/out/language-server/zmodel-scope.js.map +0 -1
  164. package/out/language-server/zmodel-validator.js +0 -35
  165. package/out/language-server/zmodel-validator.js.map +0 -1
  166. package/out/utils/exec-utils.js +0 -9
  167. package/out/utils/exec-utils.js.map +0 -1
  168. package/out/utils/indent-string.js +0 -9
  169. package/out/utils/indent-string.js.map +0 -1
@@ -1,63 +1,40 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
- var __importDefault = (this && this.__importDefault) || function (mod) {
35
- return (mod && mod.__esModule) ? mod : { "default": mod };
36
- };
37
- Object.defineProperty(exports, "__esModule", { value: true });
38
- const ts_morph_1 = require("ts-morph");
39
- const path = __importStar(require("path"));
40
- const colors_1 = __importDefault(require("colors"));
41
- class NextAuthGenerator {
42
- generate(context) {
43
- return __awaiter(this, void 0, void 0, function* () {
44
- const project = new ts_morph_1.Project();
45
- this.generateIndex(project, context);
46
- this.generateAdapter(project, context);
47
- this.generateAuthorize(project, context);
48
- yield project.save();
49
- console.log(colors_1.default.blue(` ✔️ Next-auth adapter generated`));
50
- });
1
+ import { Context, Generator } from '../types';
2
+ import { Project } from 'ts-morph';
3
+ import * as path from 'path';
4
+ import colors from 'colors';
5
+
6
+ /**
7
+ * Generates NextAuth adaptor code
8
+ */
9
+ export default class NextAuthGenerator implements Generator {
10
+ async generate(context: Context): Promise<void> {
11
+ const project = new Project();
12
+
13
+ this.generateIndex(project, context);
14
+ this.generateAdapter(project, context);
15
+ this.generateAuthorize(project, context);
16
+
17
+ await project.save();
18
+
19
+ console.log(colors.blue(` ✔️ Next-auth adapter generated`));
51
20
  }
52
- generateIndex(project, context) {
53
- const sf = project.createSourceFile(path.join(context.generatedCodeDir, 'src/auth/index.ts'), undefined, { overwrite: true });
21
+
22
+ private generateIndex(project: Project, context: Context) {
23
+ const sf = project.createSourceFile(
24
+ path.join(context.generatedCodeDir, 'src/auth/index.ts'),
25
+ undefined,
26
+ { overwrite: true }
27
+ );
28
+
54
29
  sf.addStatements([
55
30
  `export * from './next-auth-adapter';`,
56
31
  `export * from './authorize';`,
57
32
  ]);
33
+
58
34
  sf.formatText();
59
35
  }
60
- generateAdapter(project, context) {
36
+
37
+ private generateAdapter(project: Project, context: Context) {
61
38
  const content = `
62
39
  import { ZenStackService } from '..';
63
40
  import { Adapter } from 'next-auth/adapters';
@@ -118,10 +95,20 @@ class NextAuthGenerator {
118
95
  };
119
96
  }
120
97
  `;
121
- const sf = project.createSourceFile(path.join(context.generatedCodeDir, 'src/auth/next-auth-adapter.ts'), content, { overwrite: true });
98
+
99
+ const sf = project.createSourceFile(
100
+ path.join(
101
+ context.generatedCodeDir,
102
+ 'src/auth/next-auth-adapter.ts'
103
+ ),
104
+ content,
105
+ { overwrite: true }
106
+ );
107
+
122
108
  sf.formatText();
123
109
  }
124
- generateAuthorize(project, context) {
110
+
111
+ private generateAuthorize(project: Project, context: Context) {
125
112
  const content = `
126
113
  import { ZenStackService } from '..';
127
114
  import { hash, compare } from 'bcryptjs';
@@ -201,9 +188,13 @@ class NextAuthGenerator {
201
188
  };
202
189
  }
203
190
  `;
204
- const sf = project.createSourceFile(path.join(context.generatedCodeDir, 'src/auth/authorize.ts'), content, { overwrite: true });
191
+
192
+ const sf = project.createSourceFile(
193
+ path.join(context.generatedCodeDir, 'src/auth/authorize.ts'),
194
+ content,
195
+ { overwrite: true }
196
+ );
197
+
205
198
  sf.formatText();
206
199
  }
207
200
  }
208
- exports.default = NextAuthGenerator;
209
- //# sourceMappingURL=index.js.map
@@ -0,0 +1,360 @@
1
+ import {
2
+ BinaryExpr,
3
+ Expression,
4
+ isDataModel,
5
+ isDataModelField,
6
+ isEnumField,
7
+ isMemberAccessExpr,
8
+ isReferenceExpr,
9
+ isThisExpr,
10
+ LiteralExpr,
11
+ MemberAccessExpr,
12
+ ReferenceExpr,
13
+ UnaryExpr,
14
+ } from '@lang/generated/ast';
15
+ import { CodeBlockWriter } from 'ts-morph';
16
+ import { GUARD_FIELD_NAME } from '../constants';
17
+ import { GeneratorError } from '../types';
18
+ import TypeScriptExpressionTransformer from './typescript-expression-transformer';
19
+
20
+ type ComparisonOperator = '==' | '!=' | '>' | '>=' | '<' | '<=';
21
+
22
+ /**
23
+ * Utility for writing ZModel expression as Prisma query argument objects into a ts-morph writer
24
+ */
25
+ export default class ExpressionWriter {
26
+ private readonly plainExprBuilder = new TypeScriptExpressionTransformer();
27
+
28
+ constructor(private readonly writer: CodeBlockWriter) {}
29
+
30
+ /**
31
+ * Writes the given ZModel expression.
32
+ */
33
+ write(expr: Expression): void {
34
+ const _write = () => {
35
+ switch (expr.$type) {
36
+ case LiteralExpr:
37
+ this.writeLiteral(expr as LiteralExpr);
38
+ break;
39
+
40
+ case UnaryExpr:
41
+ this.writeUnary(expr as UnaryExpr);
42
+ break;
43
+
44
+ case BinaryExpr:
45
+ this.writeBinary(expr as BinaryExpr);
46
+ break;
47
+
48
+ case ReferenceExpr:
49
+ this.writeReference(expr as ReferenceExpr);
50
+ break;
51
+
52
+ case MemberAccessExpr:
53
+ this.writeMemberAccess(expr as MemberAccessExpr);
54
+ break;
55
+
56
+ default:
57
+ throw new Error(`Not implemented: ${expr.$type}`);
58
+ }
59
+ };
60
+
61
+ this.block(_write);
62
+ }
63
+
64
+ private writeReference(expr: ReferenceExpr) {
65
+ if (isEnumField(expr.target.ref)) {
66
+ throw new Error('We should never get here');
67
+ } else {
68
+ this.writer.write(`${expr.target.ref?.name}: true`);
69
+ }
70
+ }
71
+
72
+ private writeMemberAccess(expr: MemberAccessExpr) {
73
+ this.writeFieldCondition(
74
+ expr.operand,
75
+ () => {
76
+ this.block(() => {
77
+ this.writer.write(`${expr.member.ref?.name}: true`);
78
+ });
79
+ },
80
+ 'is'
81
+ );
82
+ }
83
+
84
+ private writeExprList(exprs: Expression[]) {
85
+ this.writer.writeLine('[');
86
+ for (let i = 0; i < exprs.length; i++) {
87
+ this.write(exprs[i]);
88
+ if (i !== exprs.length - 1) {
89
+ this.writer.writeLine(',');
90
+ }
91
+ }
92
+ this.writer.writeLine(']');
93
+ }
94
+
95
+ private writeBinary(expr: BinaryExpr) {
96
+ switch (expr.operator) {
97
+ case '&&':
98
+ case '||':
99
+ this.writeLogical(expr, expr.operator);
100
+ break;
101
+
102
+ case '==':
103
+ case '!=':
104
+ case '>':
105
+ case '>=':
106
+ case '<':
107
+ case '<=':
108
+ this.writeComparison(expr, expr.operator);
109
+ break;
110
+
111
+ case '?':
112
+ case '!':
113
+ case '^':
114
+ this.writeCollectionPredicate(expr, expr.operator);
115
+ break;
116
+ }
117
+ }
118
+
119
+ private writeCollectionPredicate(expr: BinaryExpr, operator: string) {
120
+ this.writeFieldCondition(
121
+ expr.left,
122
+ () => {
123
+ this.write(expr.right);
124
+ },
125
+ operator === '?' ? 'some' : operator === '!' ? 'every' : 'none'
126
+ );
127
+ }
128
+
129
+ private isFieldAccess(expr: Expression): boolean {
130
+ if (isThisExpr(expr)) {
131
+ return true;
132
+ }
133
+ if (isMemberAccessExpr(expr)) {
134
+ return this.isFieldAccess(expr.operand);
135
+ }
136
+ if (isReferenceExpr(expr) && isDataModelField(expr.target.ref)) {
137
+ return true;
138
+ }
139
+ return false;
140
+ }
141
+
142
+ private guard(write: () => void) {
143
+ this.writer.write(`${GUARD_FIELD_NAME}: `);
144
+ write();
145
+ }
146
+
147
+ private plain(expr: Expression) {
148
+ this.writer.write(this.plainExprBuilder.transform(expr));
149
+ }
150
+
151
+ private writeComparison(expr: BinaryExpr, operator: ComparisonOperator) {
152
+ const leftIsFieldAccess = this.isFieldAccess(expr.left);
153
+ const rightIsFieldAccess = this.isFieldAccess(expr.right);
154
+
155
+ if (leftIsFieldAccess && rightIsFieldAccess) {
156
+ throw new GeneratorError(
157
+ `Comparison between fields are not supported yet`
158
+ );
159
+ }
160
+
161
+ if (!leftIsFieldAccess && !rightIsFieldAccess) {
162
+ // compile down to a plain expression
163
+ this.guard(() => {
164
+ this.plain(expr.left);
165
+ this.writer.write(' ' + operator + ' ');
166
+ this.plain(expr.right);
167
+ });
168
+
169
+ return;
170
+ }
171
+
172
+ let fieldAccess: Expression;
173
+ let operand: Expression;
174
+ if (leftIsFieldAccess) {
175
+ fieldAccess = expr.left;
176
+ operand = expr.right;
177
+ } else {
178
+ fieldAccess = expr.right;
179
+ operand = expr.left;
180
+ operator = this.negateOperator(operator);
181
+ }
182
+
183
+ this.writeFieldCondition(
184
+ fieldAccess,
185
+ () => {
186
+ this.block(
187
+ () => {
188
+ if (this.isModelTyped(fieldAccess)) {
189
+ // comparing with an object, conver to "id" comparison instead
190
+ this.writer.write('id: ');
191
+ this.block(() => {
192
+ this.writeOperator(operator, () => {
193
+ this.plain(operand);
194
+ this.writer.write('?.id');
195
+ });
196
+ });
197
+ } else {
198
+ this.writeOperator(operator, () => {
199
+ this.plain(operand);
200
+ });
201
+ }
202
+ },
203
+ // "this" expression is compiled away (to .id access), so we should
204
+ // avoid generating a new layer
205
+ !isThisExpr(fieldAccess)
206
+ );
207
+ },
208
+ 'is'
209
+ );
210
+ }
211
+
212
+ private writeOperator(
213
+ operator: ComparisonOperator,
214
+ writeOperand: () => void
215
+ ) {
216
+ if (operator === '!=') {
217
+ // wrap a 'not'
218
+ this.writer.write('not: ');
219
+ this.block(() => {
220
+ this.writeOperator('==', writeOperand);
221
+ });
222
+ } else {
223
+ this.writer.write(`${this.mapOperator(operator)}: `);
224
+ writeOperand();
225
+ }
226
+ }
227
+
228
+ private writeFieldCondition(
229
+ fieldAccess: Expression,
230
+ writeCondition: () => void,
231
+ relationOp: 'is' | 'some' | 'every' | 'none'
232
+ ) {
233
+ let selector: string | undefined;
234
+ let operand: Expression | undefined;
235
+
236
+ if (isThisExpr(fieldAccess)) {
237
+ // pass on
238
+ writeCondition();
239
+ return;
240
+ } else if (isReferenceExpr(fieldAccess)) {
241
+ selector = fieldAccess.target.ref?.name;
242
+ } else if (isMemberAccessExpr(fieldAccess)) {
243
+ selector = fieldAccess.member.ref?.name;
244
+ operand = fieldAccess.operand;
245
+ } else {
246
+ throw new GeneratorError(
247
+ `Unsupported expression type: ${fieldAccess.$type}`
248
+ );
249
+ }
250
+
251
+ if (!selector) {
252
+ throw new GeneratorError(`Failed to write FieldAccess expression`);
253
+ }
254
+
255
+ if (operand) {
256
+ // member access expression
257
+ this.writeFieldCondition(
258
+ operand,
259
+ () => {
260
+ this.block(
261
+ () => {
262
+ this.writer.write(selector + ': ');
263
+ if (this.isModelTyped(fieldAccess)) {
264
+ // expression is resolved to a model, generate relation query
265
+ this.block(() => {
266
+ this.writer.write(`${relationOp}: `);
267
+ writeCondition();
268
+ });
269
+ } else {
270
+ // generate plain query
271
+ writeCondition();
272
+ }
273
+ },
274
+ // if operand is "this", it doesn't really generate a new layer of query,
275
+ // so we should avoid generating a new block
276
+ !isThisExpr(operand)
277
+ );
278
+ },
279
+ 'is'
280
+ );
281
+ } else if (this.isModelTyped(fieldAccess)) {
282
+ // reference resolved to a model, generate relation query
283
+ this.writer.write(selector + ': ');
284
+ this.block(() => {
285
+ this.writer.write(`${relationOp}: `);
286
+ writeCondition();
287
+ });
288
+ } else {
289
+ // generate a plain query
290
+ this.writer.write(selector + ': ');
291
+ writeCondition();
292
+ }
293
+ }
294
+
295
+ private block(write: () => void, condition = true) {
296
+ if (condition) {
297
+ this.writer.block(write);
298
+ } else {
299
+ write();
300
+ }
301
+ }
302
+
303
+ private isModelTyped(expr: Expression) {
304
+ return isDataModel(expr.$resolvedType?.decl);
305
+ }
306
+
307
+ private mapOperator(operator: '==' | '!=' | '>' | '>=' | '<' | '<=') {
308
+ switch (operator) {
309
+ case '==':
310
+ return 'equals';
311
+ case '!=':
312
+ throw new Error('Operation != should have been compiled away');
313
+ case '>':
314
+ return 'gt';
315
+ case '>=':
316
+ return 'ge';
317
+ case '<':
318
+ return 'lt';
319
+ case '<=':
320
+ return 'le';
321
+ }
322
+ }
323
+
324
+ private negateOperator(operator: '==' | '!=' | '>' | '>=' | '<' | '<=') {
325
+ switch (operator) {
326
+ case '>':
327
+ return '<=';
328
+ case '<':
329
+ return '>=';
330
+ case '>=':
331
+ return '<';
332
+ case '<=':
333
+ return '>';
334
+ default:
335
+ return operator;
336
+ }
337
+ }
338
+
339
+ private writeLogical(expr: BinaryExpr, operator: '&&' | '||') {
340
+ this.writer.writeLine(`${operator === '&&' ? 'AND' : 'OR'}: `);
341
+ this.writeExprList([expr.left, expr.right]);
342
+ }
343
+
344
+ private writeUnary(expr: UnaryExpr) {
345
+ if (expr.operator !== '!') {
346
+ throw new GeneratorError(
347
+ `Unary operator "${expr.operator}" is not supported`
348
+ );
349
+ }
350
+
351
+ this.writer.writeLine('NOT: ');
352
+ this.write(expr.operand);
353
+ }
354
+
355
+ private writeLiteral(expr: LiteralExpr) {
356
+ this.guard(() => {
357
+ this.plain(expr);
358
+ });
359
+ }
360
+ }
@@ -0,0 +1,35 @@
1
+ import colors from 'colors';
2
+ import { Context, Generator, GeneratorError } from '../types';
3
+ import { execSync } from '../../utils/exec-utils';
4
+ import PrismaSchemaGenerator from './schema-generator';
5
+ import QueryGuardGenerator from './query-gard-generator';
6
+
7
+ /**
8
+ * Generates Prisma schema and db client
9
+ */
10
+ export default class PrismaGenerator implements Generator {
11
+ async generate(context: Context): Promise<void> {
12
+ // generate prisma schema
13
+ const schemaFile = await new PrismaSchemaGenerator(context).generate();
14
+
15
+ // run prisma generate and install @prisma/client
16
+ await this.generatePrismaClient(schemaFile);
17
+
18
+ // generate prisma query guard
19
+ await new QueryGuardGenerator(context).generate();
20
+
21
+ console.log(
22
+ colors.blue(` ✔️ Prisma schema and query guard generated`)
23
+ );
24
+ }
25
+
26
+ private async generatePrismaClient(schemaFile: string) {
27
+ try {
28
+ execSync(`npx prisma generate --schema "${schemaFile}"`);
29
+ } catch {
30
+ throw new GeneratorError(
31
+ `Failed to generate client code with Prisma. Check errors above for clues.\nThis normally shouldn't happen. Please file an issue at: http://go.zenstack.dev/bug.`
32
+ );
33
+ }
34
+ }
35
+ }