zenstack 1.0.0 → 1.0.16

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 (264) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +126 -1
  3. package/bin/cli +3 -0
  4. package/bin/post-install.js +24 -0
  5. package/cli/cli-error.d.ts +5 -0
  6. package/cli/cli-error.js +10 -0
  7. package/cli/cli-error.js.map +1 -0
  8. package/cli/cli-util.d.ts +18 -0
  9. package/cli/cli-util.js +143 -0
  10. package/cli/cli-util.js.map +1 -0
  11. package/cli/index.d.ts +15 -0
  12. package/cli/index.js +121 -0
  13. package/cli/index.js.map +1 -0
  14. package/cli/plugin-runner.d.ts +14 -0
  15. package/cli/plugin-runner.js +145 -0
  16. package/cli/plugin-runner.js.map +1 -0
  17. package/constants.d.ts +1 -0
  18. package/constants.js +6 -0
  19. package/constants.js.map +1 -0
  20. package/language-server/constants.d.ts +15 -0
  21. package/language-server/constants.js +20 -0
  22. package/language-server/constants.js.map +1 -0
  23. package/language-server/main.d.ts +1 -0
  24. package/language-server/main.js +13 -0
  25. package/language-server/main.js.map +1 -0
  26. package/language-server/types.d.ts +10 -0
  27. package/language-server/types.js +3 -0
  28. package/language-server/types.js.map +1 -0
  29. package/language-server/utils.d.ts +18 -0
  30. package/language-server/utils.js +58 -0
  31. package/language-server/utils.js.map +1 -0
  32. package/language-server/validator/attribute-validator.d.ts +9 -0
  33. package/language-server/validator/attribute-validator.js +11 -0
  34. package/language-server/validator/attribute-validator.js.map +1 -0
  35. package/language-server/validator/datamodel-validator.d.ts +15 -0
  36. package/language-server/validator/datamodel-validator.js +278 -0
  37. package/language-server/validator/datamodel-validator.js.map +1 -0
  38. package/language-server/validator/datasource-validator.d.ts +12 -0
  39. package/language-server/validator/datasource-validator.js +66 -0
  40. package/language-server/validator/datasource-validator.js.map +1 -0
  41. package/language-server/validator/enum-validator.d.ts +11 -0
  42. package/language-server/validator/enum-validator.js +28 -0
  43. package/language-server/validator/enum-validator.js.map +1 -0
  44. package/language-server/validator/expression-validator.d.ts +10 -0
  45. package/language-server/validator/expression-validator.js +30 -0
  46. package/language-server/validator/expression-validator.js.map +1 -0
  47. package/language-server/validator/schema-validator.d.ts +10 -0
  48. package/language-server/validator/schema-validator.js +28 -0
  49. package/language-server/validator/schema-validator.js.map +1 -0
  50. package/language-server/validator/utils.d.ts +25 -0
  51. package/language-server/validator/utils.js +257 -0
  52. package/language-server/validator/utils.js.map +1 -0
  53. package/language-server/validator/zmodel-validator.d.ts +21 -0
  54. package/language-server/validator/zmodel-validator.js +69 -0
  55. package/language-server/validator/zmodel-validator.js.map +1 -0
  56. package/language-server/zmodel-code-action.d.ts +14 -0
  57. package/language-server/zmodel-code-action.js +93 -0
  58. package/language-server/zmodel-code-action.js.map +1 -0
  59. package/language-server/zmodel-formatter.d.ts +9 -0
  60. package/language-server/zmodel-formatter.js +76 -0
  61. package/language-server/zmodel-formatter.js.map +1 -0
  62. package/language-server/zmodel-linker.d.ts +29 -0
  63. package/language-server/zmodel-linker.js +366 -0
  64. package/language-server/zmodel-linker.js.map +1 -0
  65. package/language-server/zmodel-module.d.ts +41 -0
  66. package/language-server/zmodel-module.js +80 -0
  67. package/language-server/zmodel-module.js.map +1 -0
  68. package/language-server/zmodel-scope.d.ts +10 -0
  69. package/language-server/zmodel-scope.js +44 -0
  70. package/language-server/zmodel-scope.js.map +1 -0
  71. package/language-server/zmodel-workspace-manager.d.ts +8 -0
  72. package/language-server/zmodel-workspace-manager.js +37 -0
  73. package/language-server/zmodel-workspace-manager.js.map +1 -0
  74. package/package.json +133 -8
  75. package/plugins/access-policy/expression-writer.d.ts +39 -0
  76. package/plugins/access-policy/expression-writer.js +361 -0
  77. package/plugins/access-policy/expression-writer.js.map +1 -0
  78. package/plugins/access-policy/index.d.ts +4 -0
  79. package/plugins/access-policy/index.js +24 -0
  80. package/plugins/access-policy/index.js.map +1 -0
  81. package/plugins/access-policy/policy-guard-generator.d.ts +15 -0
  82. package/plugins/access-policy/policy-guard-generator.js +349 -0
  83. package/plugins/access-policy/policy-guard-generator.js.map +1 -0
  84. package/plugins/access-policy/typescript-expression-transformer.d.ts +26 -0
  85. package/plugins/access-policy/typescript-expression-transformer.js +111 -0
  86. package/plugins/access-policy/typescript-expression-transformer.js.map +1 -0
  87. package/plugins/access-policy/utils.d.ts +5 -0
  88. package/plugins/access-policy/utils.js +14 -0
  89. package/plugins/access-policy/utils.js.map +1 -0
  90. package/plugins/access-policy/zod-schema-generator.d.ts +12 -0
  91. package/plugins/access-policy/zod-schema-generator.js +158 -0
  92. package/plugins/access-policy/zod-schema-generator.js.map +1 -0
  93. package/plugins/model-meta/index.d.ts +4 -0
  94. package/plugins/model-meta/index.js +168 -0
  95. package/plugins/model-meta/index.js.map +1 -0
  96. package/plugins/plugin-utils.d.ts +16 -0
  97. package/plugins/plugin-utils.js +54 -0
  98. package/plugins/plugin-utils.js.map +1 -0
  99. package/plugins/prisma/indent-string.d.ts +4 -0
  100. package/plugins/prisma/indent-string.js +12 -0
  101. package/plugins/prisma/indent-string.js.map +1 -0
  102. package/plugins/prisma/index.d.ts +4 -0
  103. package/plugins/prisma/index.js +24 -0
  104. package/plugins/prisma/index.js.map +1 -0
  105. package/plugins/prisma/prisma-builder.d.ts +152 -0
  106. package/plugins/prisma/prisma-builder.js +363 -0
  107. package/plugins/prisma/prisma-builder.js.map +1 -0
  108. package/plugins/prisma/schema-generator.d.ts +25 -0
  109. package/plugins/prisma/schema-generator.js +292 -0
  110. package/plugins/prisma/schema-generator.js.map +1 -0
  111. package/plugins/prisma/zmodel-code-generator.d.ts +28 -0
  112. package/plugins/prisma/zmodel-code-generator.js +114 -0
  113. package/plugins/prisma/zmodel-code-generator.js.map +1 -0
  114. package/res/prism-zmodel.js +20 -0
  115. package/res/starter.zmodel +51 -0
  116. package/res/stdlib.zmodel +346 -0
  117. package/telemetry.d.ts +20 -0
  118. package/telemetry.js +119 -0
  119. package/telemetry.js.map +1 -0
  120. package/types.d.ts +12 -0
  121. package/types.js +3 -0
  122. package/types.js.map +1 -0
  123. package/utils/ast-utils.d.ts +16 -0
  124. package/utils/ast-utils.js +85 -0
  125. package/utils/ast-utils.js.map +1 -0
  126. package/utils/exec-utils.d.ts +6 -0
  127. package/utils/exec-utils.js +13 -0
  128. package/utils/exec-utils.js.map +1 -0
  129. package/utils/pkg-utils.d.ts +3 -0
  130. package/utils/pkg-utils.js +46 -0
  131. package/utils/pkg-utils.js.map +1 -0
  132. package/utils/version-utils.d.ts +1 -0
  133. package/utils/version-utils.js +14 -0
  134. package/utils/version-utils.js.map +1 -0
  135. package/.vscode/extensions.json +0 -7
  136. package/.vscode/launch.json +0 -49
  137. package/.vscode/settings.json +0 -4
  138. package/packages/internal/jest.config.ts +0 -32
  139. package/packages/internal/package.json +0 -42
  140. package/packages/internal/src/constants.ts +0 -1
  141. package/packages/internal/src/handler/data/guard-utils.ts +0 -7
  142. package/packages/internal/src/handler/data/handler.ts +0 -415
  143. package/packages/internal/src/handler/data/query-processor.ts +0 -504
  144. package/packages/internal/src/handler/index.ts +0 -1
  145. package/packages/internal/src/handler/types.ts +0 -20
  146. package/packages/internal/src/index.ts +0 -3
  147. package/packages/internal/src/request-handler.ts +0 -27
  148. package/packages/internal/src/request.ts +0 -101
  149. package/packages/internal/src/types.ts +0 -40
  150. package/packages/internal/tests/query-processor.test.ts +0 -172
  151. package/packages/internal/tsconfig.json +0 -21
  152. package/packages/runtime/auth.d.ts +0 -1
  153. package/packages/runtime/auth.js +0 -3
  154. package/packages/runtime/hooks.d.ts +0 -10
  155. package/packages/runtime/hooks.js +0 -3
  156. package/packages/runtime/index.d.ts +0 -3
  157. package/packages/runtime/index.js +0 -1
  158. package/packages/runtime/package-lock.json +0 -512
  159. package/packages/runtime/package.json +0 -16
  160. package/packages/runtime/server.d.ts +0 -1
  161. package/packages/runtime/server.js +0 -3
  162. package/packages/runtime/types.d.ts +0 -1
  163. package/packages/runtime/types.js +0 -3
  164. package/packages/schema/.eslintrc.json +0 -13
  165. package/packages/schema/.vscodeignore +0 -4
  166. package/packages/schema/asset/logo-dark.png +0 -0
  167. package/packages/schema/asset/logo-light.png +0 -0
  168. package/packages/schema/bin/cli +0 -3
  169. package/packages/schema/jest.config.ts +0 -32
  170. package/packages/schema/langium-config.json +0 -14
  171. package/packages/schema/langium-quickstart.md +0 -41
  172. package/packages/schema/language-configuration.json +0 -30
  173. package/packages/schema/package.json +0 -96
  174. package/packages/schema/src/cli/cli-util.ts +0 -80
  175. package/packages/schema/src/cli/index.ts +0 -64
  176. package/packages/schema/src/extension.ts +0 -76
  177. package/packages/schema/src/generator/constants.ts +0 -5
  178. package/packages/schema/src/generator/index.ts +0 -92
  179. package/packages/schema/src/generator/next-auth/index.ts +0 -197
  180. package/packages/schema/src/generator/package.template.json +0 -9
  181. package/packages/schema/src/generator/prisma/expression-writer.ts +0 -352
  182. package/packages/schema/src/generator/prisma/index.ts +0 -32
  183. package/packages/schema/src/generator/prisma/plain-expression-builder.ts +0 -91
  184. package/packages/schema/src/generator/prisma/prisma-builder.ts +0 -366
  185. package/packages/schema/src/generator/prisma/query-gard-generator.ts +0 -208
  186. package/packages/schema/src/generator/prisma/schema-generator.ts +0 -300
  187. package/packages/schema/src/generator/react-hooks/index.ts +0 -181
  188. package/packages/schema/src/generator/service/index.ts +0 -107
  189. package/packages/schema/src/generator/tsconfig.template.json +0 -17
  190. package/packages/schema/src/generator/types.ts +0 -17
  191. package/packages/schema/src/generator/utils.ts +0 -9
  192. package/packages/schema/src/language-server/generated/ast.ts +0 -603
  193. package/packages/schema/src/language-server/generated/grammar.ts +0 -2190
  194. package/packages/schema/src/language-server/generated/module.ts +0 -24
  195. package/packages/schema/src/language-server/main.ts +0 -12
  196. package/packages/schema/src/language-server/stdlib.zmodel +0 -22
  197. package/packages/schema/src/language-server/types.ts +0 -9
  198. package/packages/schema/src/language-server/zmodel-index.ts +0 -33
  199. package/packages/schema/src/language-server/zmodel-linker.ts +0 -409
  200. package/packages/schema/src/language-server/zmodel-module.ts +0 -90
  201. package/packages/schema/src/language-server/zmodel-scope.ts +0 -21
  202. package/packages/schema/src/language-server/zmodel-validator.ts +0 -35
  203. package/packages/schema/src/language-server/zmodel.langium +0 -186
  204. package/packages/schema/src/utils/exec-utils.ts +0 -5
  205. package/packages/schema/src/utils/indent-string.ts +0 -6
  206. package/packages/schema/syntaxes/zmodel.json +0 -57
  207. package/packages/schema/syntaxes/zmodel.tmLanguage.json +0 -57
  208. package/packages/schema/tests/generator/expression-writer.test.ts +0 -676
  209. package/packages/schema/tests/generator/prisma-builder.test.ts +0 -138
  210. package/packages/schema/tests/schema/parser.test.ts +0 -423
  211. package/packages/schema/tests/schema/sample-todo.test.ts +0 -14
  212. package/packages/schema/tests/utils.ts +0 -38
  213. package/packages/schema/tsconfig.json +0 -23
  214. package/pnpm-workspace.yaml +0 -3
  215. package/samples/todo/.env +0 -2
  216. package/samples/todo/.eslintrc.json +0 -3
  217. package/samples/todo/.vscode/launch.json +0 -11
  218. package/samples/todo/README.md +0 -34
  219. package/samples/todo/components/AuthGuard.tsx +0 -17
  220. package/samples/todo/components/Avatar.tsx +0 -22
  221. package/samples/todo/components/BreadCrumb.tsx +0 -44
  222. package/samples/todo/components/ManageMembers.tsx +0 -134
  223. package/samples/todo/components/NavBar.tsx +0 -57
  224. package/samples/todo/components/SpaceMembers.tsx +0 -76
  225. package/samples/todo/components/Spaces.tsx +0 -28
  226. package/samples/todo/components/TimeInfo.tsx +0 -17
  227. package/samples/todo/components/Todo.tsx +0 -72
  228. package/samples/todo/components/TodoList.tsx +0 -77
  229. package/samples/todo/lib/context.ts +0 -31
  230. package/samples/todo/next.config.js +0 -10
  231. package/samples/todo/package-lock.json +0 -7527
  232. package/samples/todo/package.json +0 -45
  233. package/samples/todo/pages/_app.tsx +0 -50
  234. package/samples/todo/pages/api/auth/[...nextauth].ts +0 -83
  235. package/samples/todo/pages/api/zenstack/[...path].ts +0 -16
  236. package/samples/todo/pages/create-space.tsx +0 -114
  237. package/samples/todo/pages/index.tsx +0 -32
  238. package/samples/todo/pages/space/[slug]/[listId]/index.tsx +0 -88
  239. package/samples/todo/pages/space/[slug]/index.tsx +0 -169
  240. package/samples/todo/postcss.config.js +0 -6
  241. package/samples/todo/public/avatar.jpg +0 -0
  242. package/samples/todo/public/favicon.ico +0 -0
  243. package/samples/todo/public/logo.png +0 -0
  244. package/samples/todo/public/vercel.svg +0 -4
  245. package/samples/todo/styles/globals.css +0 -7
  246. package/samples/todo/tailwind.config.js +0 -11
  247. package/samples/todo/tsconfig.json +0 -28
  248. package/samples/todo/types/next-auth.d.ts +0 -14
  249. package/samples/todo/types/next.d.ts +0 -16
  250. package/samples/todo/zenstack/migrations/20221014084317_init/migration.sql +0 -153
  251. package/samples/todo/zenstack/migrations/20221020094651_upate_cli/migration.sql +0 -23
  252. package/samples/todo/zenstack/migrations/migration_lock.toml +0 -3
  253. package/samples/todo/zenstack/schema.prisma +0 -126
  254. package/samples/todo/zenstack/schema.zmodel +0 -161
  255. package/tests/integration/jest.config.ts +0 -16
  256. package/tests/integration/package-lock.json +0 -1081
  257. package/tests/integration/package.json +0 -27
  258. package/tests/integration/tests/operation-coverate.test.ts +0 -563
  259. package/tests/integration/tests/operations.zmodel +0 -69
  260. package/tests/integration/tests/todo-e2e.test.ts +0 -577
  261. package/tests/integration/tests/todo.zmodel +0 -123
  262. package/tests/integration/tests/tsconfig.template.json +0 -10
  263. package/tests/integration/tests/utils.ts +0 -133
  264. package/tests/integration/tsconfig.json +0 -10
@@ -1,300 +0,0 @@
1
- import {
2
- AttributeArg,
3
- DataModel,
4
- DataModelAttribute,
5
- DataModelField,
6
- DataModelFieldAttribute,
7
- DataSource,
8
- Enum,
9
- Expression,
10
- InvocationExpr,
11
- isArrayExpr,
12
- isInvocationExpr,
13
- isLiteralExpr,
14
- isReferenceExpr,
15
- LiteralExpr,
16
- } from '@lang/generated/ast';
17
- import { writeFile } from 'fs/promises';
18
- import { AstNode } from 'langium';
19
- import path from 'path';
20
- import { GUARD_FIELD_NAME, TRANSACTION_FIELD_NAME } from '../constants';
21
- import { Context, GeneratorError } from '../types';
22
- import {
23
- AttributeArg as PrismaAttributeArg,
24
- AttributeArgValue as PrismaAttributeArgValue,
25
- DataSourceUrl as PrismaDataSourceUrl,
26
- FieldAttribute as PrismaFieldAttribute,
27
- ModelAttribute as PrismaModelAttribute,
28
- Model as PrismaDataModel,
29
- FieldReference as PrismaFieldReference,
30
- FieldReferenceArg as PrismaFieldReferenceArg,
31
- FunctionCall as PrismaFunctionCall,
32
- FunctionCallArg as PrismaFunctionCallArg,
33
- PrismaModel,
34
- ModelFieldType,
35
- } from './prisma-builder';
36
-
37
- const supportedProviders = ['postgresql', 'mysql', 'sqlite', 'sqlserver'];
38
- const supportedAttrbutes = [
39
- 'id',
40
- 'index',
41
- 'relation',
42
- 'default',
43
- 'createdAt',
44
- 'updatedAt',
45
- 'unique',
46
- ];
47
-
48
- export default class PrismaSchemaGenerator {
49
- constructor(private readonly context: Context) {}
50
-
51
- async generate() {
52
- const { schema } = this.context;
53
- const prisma = new PrismaModel();
54
-
55
- for (const decl of schema.declarations) {
56
- switch (decl.$type) {
57
- case DataSource:
58
- this.generateDataSource(prisma, decl as DataSource);
59
- break;
60
-
61
- case Enum:
62
- this.generateEnum(prisma, decl as Enum);
63
- break;
64
-
65
- case DataModel:
66
- this.generateModel(prisma, decl as DataModel);
67
- break;
68
- }
69
- }
70
-
71
- this.generateGenerator(prisma);
72
-
73
- const outFile = path.join(this.context.outDir, 'schema.prisma');
74
- await writeFile(outFile, prisma.toString());
75
- return outFile;
76
- }
77
-
78
- private generateDataSource(prisma: PrismaModel, dataSource: DataSource) {
79
- let provider: string | undefined = undefined;
80
- let url: PrismaDataSourceUrl | undefined = undefined;
81
- let shadowDatabaseUrl: PrismaDataSourceUrl | undefined = undefined;
82
-
83
- for (const f of dataSource.fields) {
84
- switch (f.name) {
85
- case 'provider': {
86
- if (this.isStringLiteral(f.value)) {
87
- provider = f.value.value as string;
88
- } else {
89
- throw new GeneratorError(
90
- 'Datasource provider must be set to a string'
91
- );
92
- }
93
- if (!supportedProviders.includes(provider)) {
94
- throw new GeneratorError(
95
- `Provider ${provider} is not supported. Supported providers: ${supportedProviders.join(
96
- ', '
97
- )}`
98
- );
99
- }
100
- break;
101
- }
102
-
103
- case 'url': {
104
- const r = this.extractDataSourceUrl(f.value);
105
- if (!r) {
106
- throw new GeneratorError(
107
- 'Invalid value for datasource url'
108
- );
109
- }
110
- url = r;
111
- break;
112
- }
113
-
114
- case 'shadowDatabaseUrl': {
115
- const r = this.extractDataSourceUrl(f.value);
116
- if (!r) {
117
- throw new GeneratorError(
118
- 'Invalid value for datasource url'
119
- );
120
- }
121
- shadowDatabaseUrl = r;
122
- break;
123
- }
124
- }
125
- }
126
-
127
- if (!provider) {
128
- throw new GeneratorError('Datasource is missing "provider" field');
129
- }
130
- if (!url) {
131
- throw new GeneratorError('Datasource is missing "url" field');
132
- }
133
-
134
- prisma.addDataSource(dataSource.name, provider, url, shadowDatabaseUrl);
135
- }
136
-
137
- private extractDataSourceUrl(fieldValue: LiteralExpr | InvocationExpr) {
138
- if (this.isStringLiteral(fieldValue)) {
139
- return new PrismaDataSourceUrl(fieldValue.value as string, false);
140
- } else if (
141
- isInvocationExpr(fieldValue) &&
142
- fieldValue.function.ref?.name === 'env' &&
143
- fieldValue.args.length === 1 &&
144
- this.isStringLiteral(fieldValue.args[0].value)
145
- ) {
146
- return new PrismaDataSourceUrl(
147
- fieldValue.args[0].value.value as string,
148
- true
149
- );
150
- } else {
151
- return null;
152
- }
153
- }
154
-
155
- private generateGenerator(prisma: PrismaModel) {
156
- prisma.addGenerator(
157
- 'client',
158
- 'prisma-client-js',
159
- path.join('../', this.context.generatedCodeDir, '.prisma'),
160
- ['fieldReference', 'interactiveTransactions']
161
- );
162
- }
163
-
164
- private generateModel(prisma: PrismaModel, decl: DataModel) {
165
- const model = prisma.addModel(decl.name);
166
- for (const field of decl.fields) {
167
- this.generateModelField(model, field);
168
- }
169
-
170
- // add an "zenstack_guard" field for dealing with pure auth() related conditions
171
- model.addField(GUARD_FIELD_NAME, 'Boolean', [
172
- new PrismaFieldAttribute('default', [
173
- new PrismaAttributeArg(
174
- undefined,
175
- new PrismaAttributeArgValue('Boolean', true)
176
- ),
177
- ]),
178
- ]);
179
-
180
- // add an "zenstack_transaction" field for tracking records created/updated with nested writes
181
- model.addField(TRANSACTION_FIELD_NAME, 'String?');
182
-
183
- for (const attr of decl.attributes.filter((attr) =>
184
- supportedAttrbutes.includes(attr.decl.ref?.name!)
185
- )) {
186
- this.generateModelAttribute(model, attr);
187
- }
188
- }
189
-
190
- private generateModelField(model: PrismaDataModel, field: DataModelField) {
191
- const type = new ModelFieldType(
192
- (field.type.type || field.type.reference?.ref?.name)!,
193
- field.type.array,
194
- field.type.optional
195
- );
196
-
197
- const attributes = field.attributes
198
- .filter((attr) => supportedAttrbutes.includes(attr.decl.ref?.name!))
199
- .map((attr) => this.makeFieldAttribute(attr));
200
- model.addField(field.name, type, attributes);
201
- }
202
-
203
- private makeFieldAttribute(attr: DataModelFieldAttribute) {
204
- return new PrismaFieldAttribute(
205
- attr.decl.ref?.name!,
206
- attr.args.map((arg) => this.makeAttributeArg(arg))
207
- );
208
- }
209
-
210
- makeAttributeArg(arg: AttributeArg): PrismaAttributeArg {
211
- return new PrismaAttributeArg(
212
- arg.name,
213
- this.makeAttributeArgValue(arg.value)
214
- );
215
- }
216
-
217
- makeAttributeArgValue(node: Expression): PrismaAttributeArgValue {
218
- if (isLiteralExpr(node)) {
219
- switch (typeof node.value) {
220
- case 'string':
221
- return new PrismaAttributeArgValue('String', node.value);
222
- case 'number':
223
- return new PrismaAttributeArgValue('Number', node.value);
224
- case 'boolean':
225
- return new PrismaAttributeArgValue('Boolean', node.value);
226
- default:
227
- throw new GeneratorError(
228
- `Unexpected literal type: ${typeof node.value}`
229
- );
230
- }
231
- } else if (isArrayExpr(node)) {
232
- return new PrismaAttributeArgValue(
233
- 'Array',
234
- new Array(
235
- ...node.items.map((item) =>
236
- this.makeAttributeArgValue(item)
237
- )
238
- )
239
- );
240
- } else if (isReferenceExpr(node)) {
241
- return new PrismaAttributeArgValue(
242
- 'FieldReference',
243
- new PrismaFieldReference(
244
- node.target.ref?.name!,
245
- node.args.map(
246
- (arg) =>
247
- new PrismaFieldReferenceArg(arg.name, arg.value)
248
- )
249
- )
250
- );
251
- } else if (isInvocationExpr(node)) {
252
- // invocation
253
- return new PrismaAttributeArgValue(
254
- 'FunctionCall',
255
- this.makeFunctionCall(node)
256
- );
257
- } else {
258
- throw new GeneratorError(
259
- `Unsupported attribute argument expression type: ${node.$type}`
260
- );
261
- }
262
- }
263
-
264
- makeFunctionCall(node: InvocationExpr): PrismaFunctionCall {
265
- return new PrismaFunctionCall(
266
- node.function.ref?.name!,
267
- node.args.map((arg) => {
268
- if (!isLiteralExpr(arg.value)) {
269
- throw new GeneratorError(
270
- 'Function call argument must be literal'
271
- );
272
- }
273
- return new PrismaFunctionCallArg(arg.name, arg.value.value);
274
- })
275
- );
276
- }
277
-
278
- private generateModelAttribute(
279
- model: PrismaDataModel,
280
- attr: DataModelAttribute
281
- ) {
282
- model.attributes.push(
283
- new PrismaModelAttribute(
284
- attr.decl.ref?.name!,
285
- attr.args.map((arg) => this.makeAttributeArg(arg))
286
- )
287
- );
288
- }
289
-
290
- private generateEnum(prisma: PrismaModel, decl: Enum) {
291
- prisma.addEnum(
292
- decl.name,
293
- decl.fields.map((f) => f.name)
294
- );
295
- }
296
-
297
- private isStringLiteral(node: AstNode): node is LiteralExpr {
298
- return isLiteralExpr(node) && typeof node.value === 'string';
299
- }
300
- }
@@ -1,181 +0,0 @@
1
- import { Context, Generator } from '../types';
2
- import { Project } from 'ts-morph';
3
- import * as path from 'path';
4
- import { paramCase } from 'change-case';
5
- import { DataModel } from '@lang/generated/ast';
6
- import colors from 'colors';
7
- import { extractDataModelsWithAllowRules } from '../utils';
8
- import { API_ROUTE_NAME, INTERNAL_PACKAGE } from '../constants';
9
-
10
- export default class ReactHooksGenerator implements Generator {
11
- async generate(context: Context) {
12
- const project = new Project();
13
-
14
- const models = extractDataModelsWithAllowRules(context.schema);
15
-
16
- this.generateIndex(project, context, models);
17
-
18
- models.forEach((d) => this.generateModelHooks(project, context, d));
19
-
20
- await project.save();
21
-
22
- console.log(colors.blue(' ✔️ React hooks generated'));
23
- }
24
-
25
- private generateModelHooks(
26
- project: Project,
27
- context: Context,
28
- model: DataModel
29
- ) {
30
- const fileName = paramCase(model.name);
31
- const sf = project.createSourceFile(
32
- path.join(context.generatedCodeDir, `src/hooks/${fileName}.ts`),
33
- undefined,
34
- { overwrite: true }
35
- );
36
-
37
- sf.addImportDeclaration({
38
- namedImports: [{ name: 'Prisma', alias: 'P' }, model.name],
39
- isTypeOnly: true,
40
- moduleSpecifier: '../../.prisma',
41
- });
42
- sf.addStatements(`import { request } from '${INTERNAL_PACKAGE}';`);
43
- sf.addStatements(`import { type SWRResponse } from 'swr'`);
44
-
45
- sf.addStatements(
46
- `const endpoint = '/api/${API_ROUTE_NAME}/data/${model.name}';`
47
- );
48
-
49
- const useFuncBody = sf
50
- .addFunction({
51
- name: `use${model.name}`,
52
- isExported: true,
53
- })
54
- .addBody();
55
-
56
- useFuncBody.addStatements(['const mutate = request.getMutate();']);
57
-
58
- // create
59
- useFuncBody
60
- .addFunction({
61
- name: 'create',
62
- isAsync: true,
63
- typeParameters: [`T extends P.${model.name}CreateArgs`],
64
- parameters: [
65
- { name: 'args', type: `P.${model.name}CreateArgs` },
66
- ],
67
- })
68
- .addBody()
69
- .addStatements([
70
- `return request.post<P.${model.name}CreateArgs, P.CheckSelect<T, ${model.name}, P.${model.name}GetPayload<T>>>(endpoint, args, mutate);`,
71
- ]);
72
-
73
- // find
74
- useFuncBody
75
- .addFunction({
76
- name: 'find',
77
- typeParameters: [`T extends P.${model.name}FindManyArgs`],
78
- returnType: `SWRResponse<P.CheckSelect<T, ${model.name}[], P.${model.name}GetPayload<T, keyof T>[]>, any>`,
79
- parameters: [
80
- {
81
- name: 'args?',
82
- type: `P.SelectSubset<T, P.${model.name}FindManyArgs>`,
83
- },
84
- ],
85
- })
86
- .addBody()
87
- .addStatements([
88
- `return request.get<P.CheckSelect<T, Array<${model.name}>, Array<P.${model.name}GetPayload<T>>>>(endpoint, args);`,
89
- ]);
90
-
91
- // get
92
- useFuncBody
93
- .addFunction({
94
- name: 'get',
95
- typeParameters: [
96
- `T extends P.Subset<P.${model.name}FindFirstArgs, 'select' | 'include'>`,
97
- ],
98
- returnType: `SWRResponse<P.CheckSelect<T, ${model.name}, P.${model.name}GetPayload<T, keyof T>>, any>`,
99
- parameters: [
100
- {
101
- name: 'id',
102
- type: 'String',
103
- },
104
- {
105
- name: 'args?',
106
- type: `P.SelectSubset<T, P.Subset<P.${model.name}FindFirstArgs, 'select' | 'include'>>`,
107
- },
108
- ],
109
- })
110
- .addBody()
111
- .addStatements([
112
- `return request.get<P.CheckSelect<T, ${model.name}, P.${model.name}GetPayload<T>>>(id ? \`\${endpoint}/\${id}\`: null, args);`,
113
- ]);
114
-
115
- // update
116
- useFuncBody
117
- .addFunction({
118
- name: 'update',
119
- isAsync: true,
120
- typeParameters: [
121
- `T extends Omit<P.${model.name}UpdateArgs, 'where'>`,
122
- ],
123
- parameters: [
124
- { name: 'id', type: 'String' },
125
- {
126
- name: 'args',
127
- type: `Omit<P.${model.name}UpdateArgs, 'where'>`,
128
- },
129
- ],
130
- })
131
- .addBody()
132
- .addStatements([
133
- `return request.put<Omit<P.${model.name}UpdateArgs, 'where'>, P.CheckSelect<T, ${model.name}, P.${model.name}GetPayload<T>>>(\`\${endpoint}/\${id}\`, args, mutate);`,
134
- ]);
135
-
136
- // del
137
- useFuncBody
138
- .addFunction({
139
- name: 'del',
140
- isAsync: true,
141
- typeParameters: [
142
- `T extends Omit<P.${model.name}DeleteArgs, 'where'>`,
143
- ],
144
- parameters: [
145
- { name: 'id', type: 'String' },
146
- {
147
- name: 'args?',
148
- type: `Omit<P.${model.name}DeleteArgs, 'where'>`,
149
- },
150
- ],
151
- })
152
- .addBody()
153
- .addStatements([
154
- `return request.del<P.CheckSelect<T, ${model.name}, P.${model.name}GetPayload<T>>>(\`\${endpoint}/\${id}\`, args, mutate);`,
155
- ]);
156
-
157
- useFuncBody.addStatements([
158
- 'return { create, find, get, update, del };',
159
- ]);
160
-
161
- sf.formatText();
162
- }
163
-
164
- private generateIndex(
165
- project: Project,
166
- context: Context,
167
- models: DataModel[]
168
- ) {
169
- const sf = project.createSourceFile(
170
- path.join(context.generatedCodeDir, 'src/hooks/index.ts'),
171
- undefined,
172
- { overwrite: true }
173
- );
174
-
175
- sf.addStatements(
176
- models.map((d) => `export * from './${paramCase(d.name)}';`)
177
- );
178
-
179
- sf.formatText();
180
- }
181
- }
@@ -1,107 +0,0 @@
1
- import { Context, Generator } from '../types';
2
- import { Project, StructureKind, VariableDeclarationKind } from 'ts-morph';
3
- import * as path from 'path';
4
- import colors from 'colors';
5
- import { INTERNAL_PACKAGE } from '../constants';
6
-
7
- export default class ServiceGenerator implements Generator {
8
- async generate(context: Context) {
9
- const project = new Project();
10
- const sf = project.createSourceFile(
11
- path.join(context.generatedCodeDir, 'src/index.ts'),
12
- undefined,
13
- { overwrite: true }
14
- );
15
-
16
- sf.addImportDeclaration({
17
- namedImports: ['PrismaClient'],
18
- moduleSpecifier: '../.prisma',
19
- });
20
-
21
- sf.addImportDeclaration({
22
- namedImports: ['Service', 'PolicyOperationKind', 'QueryContext'],
23
- moduleSpecifier: INTERNAL_PACKAGE,
24
- isTypeOnly: true,
25
- });
26
-
27
- const cls = sf.addClass({
28
- name: 'ZenStackService',
29
- isExported: true,
30
- implements: ['Service<PrismaClient>'],
31
- });
32
- cls.addMember({
33
- kind: StructureKind.Property,
34
- name: 'private readonly _prisma',
35
- initializer: 'new PrismaClient()',
36
- });
37
-
38
- cls.addGetAccessor({
39
- name: 'db',
40
- })
41
- .addBody()
42
- .setBodyText('return this._prisma;');
43
-
44
- sf.addVariableStatement({
45
- declarationKind: VariableDeclarationKind.Let,
46
- declarations: [
47
- {
48
- name: 'guardModule',
49
- type: 'any',
50
- },
51
- ],
52
- });
53
- cls
54
- .addMethod({
55
- name: 'resolveField',
56
- isAsync: true,
57
- parameters: [
58
- {
59
- name: 'model',
60
- type: 'string',
61
- },
62
- {
63
- name: 'field',
64
- type: 'string',
65
- },
66
- ],
67
- })
68
- .addBody().setBodyText(`
69
- if (!guardModule) {
70
- guardModule = await import('./query/guard');
71
- }
72
- return guardModule._fieldMapping?.[model]?.[field];
73
- `);
74
-
75
- cls
76
- .addMethod({
77
- name: 'buildQueryGuard',
78
- isAsync: true,
79
- parameters: [
80
- {
81
- name: 'model',
82
- type: 'string',
83
- },
84
- {
85
- name: 'operation',
86
- type: 'PolicyOperationKind',
87
- },
88
- {
89
- name: 'context',
90
- type: 'QueryContext',
91
- },
92
- ],
93
- })
94
- .addBody().setBodyText(`
95
- const module: any = await import('./query/guard');
96
- const provider: (context: QueryContext) => any = module[model+ '_' + operation];
97
- return provider(context);
98
- `);
99
-
100
- sf.addStatements(['export default new ZenStackService();']);
101
-
102
- sf.formatText();
103
- await project.save();
104
-
105
- console.log(colors.blue(` ✔️ ZenStack service generated`));
106
- }
107
- }
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES6",
4
- "module": "CommonJS",
5
- "lib": ["ESNext", "DOM"],
6
- "sourceMap": true,
7
- "outDir": "lib",
8
- "strict": true,
9
- "moduleResolution": "node",
10
- "esModuleInterop": true,
11
- "skipLibCheck": true,
12
- "declaration": true,
13
- "resolveJsonModule": true
14
- },
15
- "include": ["**/*.ts"],
16
- "exclude": ["node_modules", ".prisma", "**/*.d.ts"]
17
- }
@@ -1,17 +0,0 @@
1
- import { Model } from '@lang/generated/ast';
2
-
3
- export interface Context {
4
- schema: Model;
5
- outDir: string;
6
- generatedCodeDir: string;
7
- }
8
-
9
- export interface Generator {
10
- generate(context: Context): Promise<void>;
11
- }
12
-
13
- export class GeneratorError extends Error {
14
- constructor(message: string) {
15
- super(message);
16
- }
17
- }
@@ -1,9 +0,0 @@
1
- import { DataModel, isDataModel, Model } from '@lang/generated/ast';
2
-
3
- export function extractDataModelsWithAllowRules(model: Model) {
4
- return model.declarations.filter(
5
- (d) =>
6
- isDataModel(d) &&
7
- !!d.attributes.find((attr) => attr.decl.ref?.name === 'allow')
8
- ) as DataModel[];
9
- }