@visulima/crud 3.0.0-alpha.14 → 3.0.0-alpha.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 (144) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/LICENSE.md +32 -0
  3. package/dist/index.cjs +1 -13
  4. package/dist/index.d.cts +121 -6
  5. package/dist/index.d.mts +121 -6
  6. package/dist/index.d.ts +121 -6
  7. package/dist/index.mjs +1 -3
  8. package/dist/next/index.cjs +1 -11
  9. package/dist/next/index.d.cts +1747 -2
  10. package/dist/next/index.d.mts +1742 -2
  11. package/dist/next/index.d.ts +1742 -2
  12. package/dist/next/index.mjs +1 -2
  13. package/dist/packem_shared/PrismaAdapter-D0WRtRlB.cjs +1 -0
  14. package/dist/packem_shared/PrismaAdapter-EuQr18sT.mjs +1 -0
  15. package/dist/packem_shared/RouteType-BQ2RxFPE.mjs +1 -0
  16. package/dist/packem_shared/RouteType-DLV_OhhD.cjs +1 -0
  17. package/dist/packem_shared/base-crud-handler-B6xOUGDj.cjs +1 -0
  18. package/dist/packem_shared/base-crud-handler-DNKq7uog.mjs +1 -0
  19. package/dist/packem_shared/edgeHandler-CaIWVXt-.cjs +1 -0
  20. package/dist/packem_shared/edgeHandler-Deds33h_.mjs +1 -0
  21. package/dist/packem_shared/get-accessible-routes-DLLL11KB.cjs +1 -0
  22. package/dist/packem_shared/get-accessible-routes-xHYBQ_6q.mjs +1 -0
  23. package/dist/packem_shared/models-to-route-names-Dh2b_kIL.cjs +1 -0
  24. package/dist/packem_shared/models-to-route-names-UU1lZmbK.mjs +1 -0
  25. package/dist/packem_shared/modelsToOpenApi-CsQL5VTy.cjs +1 -0
  26. package/dist/packem_shared/modelsToOpenApi-ocNrUF5p.mjs +1 -0
  27. package/dist/packem_shared/nodeHandler-CeBCrxYT.mjs +1 -0
  28. package/dist/packem_shared/nodeHandler-D7AuOmUo.cjs +1 -0
  29. package/dist/packem_shared/types.d-C_XaTdLA.d.cts +126 -0
  30. package/dist/packem_shared/types.d-C_XaTdLA.d.mts +126 -0
  31. package/dist/packem_shared/types.d-C_XaTdLA.d.ts +126 -0
  32. package/package.json +6 -6
  33. package/dist/adapter/prisma/index.d.cts +0 -39
  34. package/dist/adapter/prisma/index.d.mts +0 -39
  35. package/dist/adapter/prisma/index.d.ts +0 -39
  36. package/dist/adapter/prisma/types.d.cts +0 -31
  37. package/dist/adapter/prisma/types.d.mts +0 -31
  38. package/dist/adapter/prisma/types.d.ts +0 -31
  39. package/dist/adapter/prisma/utils/models-to-route-names.d.cts +0 -5
  40. package/dist/adapter/prisma/utils/models-to-route-names.d.mts +0 -5
  41. package/dist/adapter/prisma/utils/models-to-route-names.d.ts +0 -5
  42. package/dist/adapter/prisma/utils/parse-cursor.d.cts +0 -3
  43. package/dist/adapter/prisma/utils/parse-cursor.d.mts +0 -3
  44. package/dist/adapter/prisma/utils/parse-cursor.d.ts +0 -3
  45. package/dist/adapter/prisma/utils/parse-order-by.d.cts +0 -4
  46. package/dist/adapter/prisma/utils/parse-order-by.d.mts +0 -4
  47. package/dist/adapter/prisma/utils/parse-order-by.d.ts +0 -4
  48. package/dist/adapter/prisma/utils/parse-recursive.d.cts +0 -4
  49. package/dist/adapter/prisma/utils/parse-recursive.d.mts +0 -4
  50. package/dist/adapter/prisma/utils/parse-recursive.d.ts +0 -4
  51. package/dist/adapter/prisma/utils/parse-where.d.cts +0 -4
  52. package/dist/adapter/prisma/utils/parse-where.d.mts +0 -4
  53. package/dist/adapter/prisma/utils/parse-where.d.ts +0 -4
  54. package/dist/base-crud-handler.d.cts +0 -9
  55. package/dist/base-crud-handler.d.mts +0 -9
  56. package/dist/base-crud-handler.d.ts +0 -9
  57. package/dist/handler/create.d.cts +0 -3
  58. package/dist/handler/create.d.mts +0 -3
  59. package/dist/handler/create.d.ts +0 -3
  60. package/dist/handler/delete.d.cts +0 -3
  61. package/dist/handler/delete.d.mts +0 -3
  62. package/dist/handler/delete.d.ts +0 -3
  63. package/dist/handler/list.d.cts +0 -3
  64. package/dist/handler/list.d.mts +0 -3
  65. package/dist/handler/list.d.ts +0 -3
  66. package/dist/handler/read.d.cts +0 -3
  67. package/dist/handler/read.d.mts +0 -3
  68. package/dist/handler/read.d.ts +0 -3
  69. package/dist/handler/update.d.cts +0 -3
  70. package/dist/handler/update.d.mts +0 -3
  71. package/dist/handler/update.d.ts +0 -3
  72. package/dist/next/api/edge/index.d.cts +0 -3
  73. package/dist/next/api/edge/index.d.mts +0 -3
  74. package/dist/next/api/edge/index.d.ts +0 -3
  75. package/dist/next/api/node/index.d.cts +0 -4
  76. package/dist/next/api/node/index.d.mts +0 -4
  77. package/dist/next/api/node/index.d.ts +0 -4
  78. package/dist/packem_shared/PrismaAdapter-Bd2bxZfN.mjs +0 -318
  79. package/dist/packem_shared/PrismaAdapter-BondygJ8.cjs +0 -324
  80. package/dist/packem_shared/RouteType-Bk3uAK0x.cjs +0 -14
  81. package/dist/packem_shared/RouteType-CB2xrWdf.mjs +0 -10
  82. package/dist/packem_shared/base-crud-handler-Cg8r7S9C.mjs +0 -587
  83. package/dist/packem_shared/base-crud-handler-DSlkMYL6.cjs +0 -572
  84. package/dist/packem_shared/edgeHandler-DFuv_tsd.cjs +0 -18
  85. package/dist/packem_shared/edgeHandler-l0sBgF0s.mjs +0 -16
  86. package/dist/packem_shared/get-accessible-routes-C6NF9Iry.cjs +0 -16
  87. package/dist/packem_shared/get-accessible-routes-sV5SDdFn.mjs +0 -14
  88. package/dist/packem_shared/models-to-route-names-CdwsK0V1.mjs +0 -9
  89. package/dist/packem_shared/models-to-route-names-Dv94PzhE.cjs +0 -11
  90. package/dist/packem_shared/modelsToOpenApi-DypKlIy4.cjs +0 -708
  91. package/dist/packem_shared/modelsToOpenApi-qs_cqTsd.mjs +0 -706
  92. package/dist/packem_shared/nodeHandler-BlXQahKv.cjs +0 -16
  93. package/dist/packem_shared/nodeHandler-R76tfOc6.mjs +0 -14
  94. package/dist/query-parser.d.cts +0 -3
  95. package/dist/query-parser.d.mts +0 -3
  96. package/dist/query-parser.d.ts +0 -3
  97. package/dist/swagger/adapter/prisma/index.d.cts +0 -22
  98. package/dist/swagger/adapter/prisma/index.d.mts +0 -22
  99. package/dist/swagger/adapter/prisma/index.d.ts +0 -22
  100. package/dist/swagger/json-schema-parser.d.cts +0 -18
  101. package/dist/swagger/json-schema-parser.d.mts +0 -18
  102. package/dist/swagger/json-schema-parser.d.ts +0 -18
  103. package/dist/swagger/parameters.d.cts +0 -5
  104. package/dist/swagger/parameters.d.mts +0 -5
  105. package/dist/swagger/parameters.d.ts +0 -5
  106. package/dist/swagger/types.d.cts +0 -39
  107. package/dist/swagger/types.d.mts +0 -39
  108. package/dist/swagger/types.d.ts +0 -39
  109. package/dist/swagger/utils/format-example-ref.d.cts +0 -2
  110. package/dist/swagger/utils/format-example-ref.d.mts +0 -2
  111. package/dist/swagger/utils/format-example-ref.d.ts +0 -2
  112. package/dist/swagger/utils/format-schema-ref.d.cts +0 -2
  113. package/dist/swagger/utils/format-schema-ref.d.mts +0 -2
  114. package/dist/swagger/utils/format-schema-ref.d.ts +0 -2
  115. package/dist/swagger/utils/get-models-accessible-routes.d.cts +0 -4
  116. package/dist/swagger/utils/get-models-accessible-routes.d.mts +0 -4
  117. package/dist/swagger/utils/get-models-accessible-routes.d.ts +0 -4
  118. package/dist/swagger/utils/get-swagger-paths.d.cts +0 -12
  119. package/dist/swagger/utils/get-swagger-paths.d.mts +0 -12
  120. package/dist/swagger/utils/get-swagger-paths.d.ts +0 -12
  121. package/dist/swagger/utils/get-swagger-tags.d.cts +0 -4
  122. package/dist/swagger/utils/get-swagger-tags.d.mts +0 -4
  123. package/dist/swagger/utils/get-swagger-tags.d.ts +0 -4
  124. package/dist/types.d.cts +0 -131
  125. package/dist/types.d.mts +0 -131
  126. package/dist/types.d.ts +0 -131
  127. package/dist/utils/format-resource-id.d.cts +0 -2
  128. package/dist/utils/format-resource-id.d.mts +0 -2
  129. package/dist/utils/format-resource-id.d.ts +0 -2
  130. package/dist/utils/get-accessible-routes.d.cts +0 -3
  131. package/dist/utils/get-accessible-routes.d.mts +0 -3
  132. package/dist/utils/get-accessible-routes.d.ts +0 -3
  133. package/dist/utils/get-resource-name-from-url.d.cts +0 -5
  134. package/dist/utils/get-resource-name-from-url.d.mts +0 -5
  135. package/dist/utils/get-resource-name-from-url.d.ts +0 -5
  136. package/dist/utils/get-route-type.d.cts +0 -7
  137. package/dist/utils/get-route-type.d.mts +0 -7
  138. package/dist/utils/get-route-type.d.ts +0 -7
  139. package/dist/utils/is-primitive.d.cts +0 -2
  140. package/dist/utils/is-primitive.d.mts +0 -2
  141. package/dist/utils/is-primitive.d.ts +0 -2
  142. package/dist/utils/validate-adapter-methods.d.cts +0 -3
  143. package/dist/utils/validate-adapter-methods.d.mts +0 -3
  144. package/dist/utils/validate-adapter-methods.d.ts +0 -3
@@ -1,708 +0,0 @@
1
- 'use strict';
2
-
3
- const modelsToRouteNames = require('./models-to-route-names-Dv94PzhE.cjs');
4
- const pagination = require('@visulima/pagination');
5
- const prismaDmmfTransformer = require('@visulima/prisma-dmmf-transformer');
6
- const getAccessibleRoutes = require('./get-accessible-routes-C6NF9Iry.cjs');
7
- const RouteType = require('./RouteType-Bk3uAK0x.cjs');
8
-
9
- const formatSchemaReference = (schemaName) => `#/components/schemas/${schemaName}`;
10
-
11
- const getJSONSchemaScalar = (fieldType) => {
12
- switch (fieldType) {
13
- case "BigInt":
14
- case "Int": {
15
- return "integer";
16
- }
17
- case "Boolean": {
18
- return "boolean";
19
- }
20
- case "Bytes":
21
- case "DateTime":
22
- case "String": {
23
- return "string";
24
- }
25
- case "Decimal":
26
- case "Float": {
27
- return "number";
28
- }
29
- case "Json": {
30
- return "object";
31
- }
32
- case "Null": {
33
- return "null";
34
- }
35
- default: {
36
- return "";
37
- }
38
- }
39
- };
40
- const PAGINATION_SCHEMA_NAME = "PaginationData";
41
- const methodsNames = [
42
- { methodStart: "createOne", schemaNameStart: "Create" },
43
- { methodStart: "updateOne", schemaNameStart: "Update" }
44
- ];
45
- class PrismaJsonSchemaParser {
46
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
47
- constructor(dmmf) {
48
- this.dmmf = dmmf;
49
- }
50
- dmmf;
51
- schemaInputTypes = /* @__PURE__ */ new Map();
52
- // eslint-disable-next-line class-methods-use-this,@typescript-eslint/explicit-module-boundary-types
53
- formatInputTypeData(inputType) {
54
- if (inputType.kind === "object") {
55
- const reference = formatSchemaReference(inputType.type.name);
56
- if (inputType.isList) {
57
- return {
58
- items: {
59
- $ref: reference
60
- },
61
- type: "array",
62
- xml: {
63
- name: inputType.type.name,
64
- wrapped: true
65
- }
66
- };
67
- }
68
- return { $ref: reference };
69
- }
70
- const type = getJSONSchemaScalar(inputType.type);
71
- if (inputType.isList) {
72
- return {
73
- items: {
74
- type
75
- },
76
- type: "array",
77
- xml: {
78
- name: inputType.type.name,
79
- wrapped: true
80
- }
81
- };
82
- }
83
- return { type };
84
- }
85
- getExampleModelsSchemas(modelNames, schemas) {
86
- const referenceToSchema = (reference) => {
87
- const name = reference.replace("#/components/schemas/", "");
88
- const model = schemas[name];
89
- const values = {};
90
- Object.entries(model.properties ?? {}).forEach(([key, v]) => {
91
- const type = v.type;
92
- values[key] = type === "array" ? [arrayItemsToSchema(v.items)] : type;
93
- });
94
- return values;
95
- };
96
- const objectPropertiesToSchema = (objectProperties) => {
97
- const values = {};
98
- Object.entries(objectProperties).forEach(([key, value]) => {
99
- values[key] = value.$ref === void 0 ? value.type : referenceToSchema(value.$ref);
100
- });
101
- return values;
102
- };
103
- const arrayItemsToSchema = (items) => {
104
- const values = {};
105
- Object.entries(items).forEach(([key, value]) => {
106
- if (value.items.$ref !== void 0) {
107
- values[key] = [referenceToSchema(value.items.$ref)];
108
- } else if (value.type === "array") {
109
- values[key] = [arrayItemsToSchema(value.items)];
110
- } else if (value.type === "object") {
111
- values[key] = objectPropertiesToSchema(value.properties);
112
- } else {
113
- values[key] = value.type;
114
- }
115
- });
116
- return values;
117
- };
118
- return modelNames.reduce((accumulator, modelName) => {
119
- const value = {};
120
- const model = schemas[modelName];
121
- Object.entries(model.properties).forEach(([key, v]) => {
122
- const type = v.type;
123
- if (type === "array") {
124
- value[key] = [referenceToSchema(v.items.$ref)];
125
- } else if (type === "object") {
126
- value[key] = objectPropertiesToSchema(v.properties);
127
- } else {
128
- value[key] = type;
129
- }
130
- });
131
- const pagination = this.getPaginationDataSchema()[PAGINATION_SCHEMA_NAME];
132
- const meta = {};
133
- Object.entries(pagination.properties).forEach(([key, v]) => {
134
- meta[key] = v.type;
135
- });
136
- return {
137
- ...accumulator,
138
- [`${modelName}Page`]: {
139
- value: {
140
- data: [value],
141
- meta
142
- }
143
- },
144
- [`${modelName}s`]: {
145
- value: [value]
146
- },
147
- [modelName]: {
148
- value
149
- }
150
- };
151
- }, {});
152
- }
153
- // eslint-disable-next-line class-methods-use-this
154
- getPaginatedModelsSchemas(modelNames) {
155
- return modelNames.reduce((accumulator, modelName) => {
156
- return {
157
- ...accumulator,
158
- [`${modelName}Page`]: {
159
- properties: {
160
- data: {
161
- items: {
162
- $ref: formatSchemaReference(modelName)
163
- },
164
- type: "array",
165
- xml: {
166
- name: "data",
167
- wrapped: true
168
- }
169
- },
170
- meta: {
171
- $ref: formatSchemaReference(PAGINATION_SCHEMA_NAME)
172
- }
173
- },
174
- type: "object",
175
- xml: {
176
- name: `${modelName}Page`
177
- }
178
- }
179
- };
180
- }, {});
181
- }
182
- // eslint-disable-next-line class-methods-use-this
183
- getPaginationDataSchema() {
184
- return pagination.createPaginationMetaSchemaObject(PAGINATION_SCHEMA_NAME);
185
- }
186
- parseInputTypes(models) {
187
- const definitions = models.reduce((accumulator, modelName) => {
188
- const methods = methodsNames.map((method) => {
189
- return {
190
- name: `${method.methodStart}${modelName}`,
191
- schemaName: `${method.schemaNameStart}${modelName}`
192
- };
193
- });
194
- methods.forEach(({ name: method, schemaName }) => {
195
- const dataFields = this.dmmf.mutationType.fieldMap[method].args[0].inputTypes[0].type.fields;
196
- const requiredProperties = [];
197
- const properties = dataFields.reduce((propertiesAccumulator, field) => {
198
- if (field.inputTypes[0].kind === "scalar") {
199
- const schema = prismaDmmfTransformer.getJSONSchemaProperty(
200
- this.dmmf.datamodel,
201
- {}
202
- )({
203
- name: field.name,
204
- ...field.inputTypes[0]
205
- });
206
- const { type: schemaType } = schema[1];
207
- if (schemaType && Array.isArray(schemaType)) {
208
- if (schemaType.includes("null")) {
209
- propertiesAccumulator[field.name] = {
210
- ...schemaType,
211
- nullable: true,
212
- type: schemaType.filter((type) => type !== "null")
213
- };
214
- if (propertiesAccumulator[field.name].type.length === 1) {
215
- propertiesAccumulator[field.name] = {
216
- ...propertiesAccumulator[field.name],
217
- type: propertiesAccumulator[field.name].type[0]
218
- };
219
- }
220
- }
221
- } else {
222
- propertiesAccumulator[field.name] = schema[1];
223
- }
224
- } else {
225
- const typeName = this.parseObjectInputType(field.inputTypes[0]);
226
- propertiesAccumulator[field.name] = {
227
- ...typeName,
228
- nullable: field.isNullable
229
- };
230
- }
231
- if (field.isRequired) {
232
- requiredProperties.push(field.name);
233
- }
234
- return propertiesAccumulator;
235
- }, {});
236
- accumulator[schemaName] = {
237
- properties,
238
- type: "object",
239
- xml: {
240
- name: schemaName
241
- }
242
- };
243
- if (requiredProperties.length > 0) {
244
- accumulator[schemaName].required = requiredProperties;
245
- }
246
- });
247
- return accumulator;
248
- }, {});
249
- this.schemaInputTypes.forEach((value, key) => {
250
- definitions[key] = {
251
- properties: value,
252
- type: "object",
253
- xml: {
254
- name: key
255
- }
256
- };
257
- });
258
- return definitions;
259
- }
260
- parseModels() {
261
- const modelsDefinitions = prismaDmmfTransformer.transformDMMF(this.dmmf).definitions;
262
- Object.keys(modelsDefinitions).forEach((definition) => {
263
- const { properties } = modelsDefinitions[definition];
264
- Object.keys(properties).forEach((property) => {
265
- if (Array.isArray(properties[property].type) && properties[property].type.includes("null")) {
266
- properties[property].type = properties[property].type.filter((type) => type !== "null");
267
- if (properties[property].type.length === 1) {
268
- properties[property].type = properties[property].type[0];
269
- }
270
- properties[property].nullable = true;
271
- }
272
- });
273
- });
274
- return modelsDefinitions;
275
- }
276
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
277
- parseObjectInputType(fieldType) {
278
- if (fieldType.kind === "object") {
279
- if (!this.schemaInputTypes.has(fieldType.type.name)) {
280
- this.schemaInputTypes.set(fieldType.type.name, {});
281
- fieldType.type.fields.forEach((field) => {
282
- let fieldData = {};
283
- if (field.inputTypes.length > 1) {
284
- let nullable = false;
285
- const anyOf = field.inputTypes.map((inputType) => {
286
- const inputTypeData = this.formatInputTypeData(inputType);
287
- if (inputTypeData.type === "null") {
288
- nullable = true;
289
- return;
290
- }
291
- return inputTypeData;
292
- }).filter(Boolean);
293
- if (anyOf.length === 1) {
294
- fieldData = anyOf[0];
295
- } else {
296
- fieldData.anyOf = anyOf;
297
- }
298
- if (nullable) {
299
- fieldData.nullable = true;
300
- }
301
- } else {
302
- const inputType = field.inputTypes[0];
303
- fieldData = this.formatInputTypeData(inputType);
304
- }
305
- this.schemaInputTypes.set(fieldType.type.name, {
306
- ...this.schemaInputTypes.get(fieldType.type.name),
307
- [field.name]: fieldData
308
- });
309
- field.inputTypes.forEach((inputType) => {
310
- if (inputType.kind === "object") {
311
- this.parseObjectInputType(inputType);
312
- }
313
- });
314
- });
315
- }
316
- return { $ref: formatSchemaReference(fieldType.type.name) };
317
- }
318
- return { type: getJSONSchemaScalar(fieldType.type) };
319
- }
320
- }
321
-
322
- const getModelsAccessibleRoutes = (modelNames, models, defaultExposeStrategy = "all") => (
323
- // eslint-disable-next-line unicorn/no-array-reduce
324
- modelNames.reduce((accumulator, modelName) => {
325
- if (models?.[modelName]) {
326
- return {
327
- ...accumulator,
328
- [modelName]: getAccessibleRoutes.getAccessibleRoutes(models[modelName].only, models[modelName].exclude, defaultExposeStrategy)
329
- };
330
- }
331
- return {
332
- ...accumulator,
333
- [modelName]: getAccessibleRoutes.getAccessibleRoutes(void 0, void 0, defaultExposeStrategy)
334
- };
335
- }, {})
336
- );
337
-
338
- const queryParameters = {
339
- distinct: {
340
- description: "Fields to distinctively retrieve",
341
- name: "distinct",
342
- schema: {
343
- type: "string"
344
- }
345
- },
346
- include: {
347
- description: "Include relations, same as select",
348
- name: "include",
349
- schema: {
350
- type: "string"
351
- }
352
- },
353
- limit: {
354
- description: "Maximum number of elements to retrieve",
355
- name: "limit",
356
- schema: {
357
- minimum: 0,
358
- type: "integer"
359
- }
360
- },
361
- orderBy: {
362
- description: 'Field on which to order by a direction. See <a href="https://next-crud.js.org/query-params#orderBy">the docs</a>',
363
- name: "orderBy",
364
- schema: {
365
- type: "string"
366
- }
367
- },
368
- page: {
369
- description: "Page number. Use only for pagination.",
370
- name: "page",
371
- schema: {
372
- minimum: 1,
373
- type: "integer"
374
- }
375
- },
376
- select: {
377
- description: "Fields to select. For nested fields, chain them separated with a dot, eg: user.posts",
378
- name: "select",
379
- schema: {
380
- type: "string"
381
- }
382
- },
383
- skip: {
384
- description: "Number of rows to skip",
385
- name: "skip",
386
- schema: {
387
- minimum: 0,
388
- type: "integer"
389
- }
390
- },
391
- where: {
392
- description: 'Fields to filter. See <a href="https://next-crud.js.org/query-params#where">the docs</a>',
393
- name: "where",
394
- schema: {
395
- type: "string"
396
- }
397
- }
398
- };
399
- const commonQueryParameters = [queryParameters.select, queryParameters.include].filter(Boolean);
400
- const listQueryParameters = [
401
- ...commonQueryParameters,
402
- queryParameters.limit,
403
- queryParameters.skip,
404
- queryParameters.where,
405
- queryParameters.orderBy,
406
- queryParameters.page,
407
- queryParameters.distinct
408
- ].filter(Boolean);
409
- const getQueryParameters = (routeType, additionalQueryParameters = []) => {
410
- if (routeType === RouteType.RouteType.READ_ALL) {
411
- return [...listQueryParameters, ...additionalQueryParameters].filter(Boolean);
412
- }
413
- return [...commonQueryParameters, ...additionalQueryParameters].filter(Boolean);
414
- };
415
-
416
- const formatExampleReference = (schemaName) => `#/components/examples/${schemaName}`;
417
-
418
- const generateContentForSchema = (schemaName, isArray) => {
419
- if (isArray) {
420
- return {
421
- items: {
422
- $ref: formatSchemaReference(schemaName)
423
- },
424
- type: "array"
425
- };
426
- }
427
- return {
428
- $ref: formatSchemaReference(schemaName)
429
- };
430
- };
431
- const generateSwaggerResponse = (routeType, modelName) => {
432
- if (routeType === RouteType.RouteType.CREATE) {
433
- return {
434
- content: {
435
- content: {
436
- "application/json": {
437
- example: formatExampleReference(modelName),
438
- schema: generateContentForSchema(modelName)
439
- }
440
- },
441
- description: `${modelName} created`
442
- },
443
- statusCode: 201
444
- };
445
- }
446
- if (routeType === RouteType.RouteType.DELETE) {
447
- return {
448
- content: {
449
- content: {
450
- "application/json": {
451
- example: formatExampleReference(modelName),
452
- schema: generateContentForSchema(modelName)
453
- }
454
- },
455
- description: `${modelName} item deleted`
456
- },
457
- statusCode: 200
458
- };
459
- }
460
- if (routeType === RouteType.RouteType.READ_ALL) {
461
- return {
462
- content: {
463
- content: {
464
- "application/json": {
465
- examples: {
466
- Default: {
467
- $ref: formatExampleReference(`${modelName}s`)
468
- },
469
- Pagination: {
470
- $ref: formatExampleReference(`${modelName}Page`)
471
- }
472
- },
473
- schema: {
474
- oneOf: [generateContentForSchema(modelName, true), generateContentForSchema(`${modelName}Page`, false)]
475
- }
476
- }
477
- },
478
- description: `${modelName} list retrieved`
479
- },
480
- statusCode: 200
481
- };
482
- }
483
- if (routeType === RouteType.RouteType.READ_ONE) {
484
- return {
485
- content: {
486
- content: {
487
- "application/json": {
488
- example: formatExampleReference(modelName),
489
- schema: generateContentForSchema(modelName)
490
- }
491
- },
492
- description: `${modelName} item retrieved`
493
- },
494
- statusCode: 200
495
- };
496
- }
497
- if (routeType === RouteType.RouteType.UPDATE) {
498
- return {
499
- content: {
500
- content: {
501
- "application/json": {
502
- example: formatExampleReference(modelName),
503
- schema: generateContentForSchema(modelName)
504
- }
505
- },
506
- description: `${modelName} item updated`
507
- },
508
- statusCode: 200
509
- };
510
- }
511
- return void 0;
512
- };
513
- const generateRequestBody = (schemaStartName, modelName) => {
514
- return {
515
- content: {
516
- "application/json": {
517
- schema: {
518
- $ref: formatSchemaReference(`${schemaStartName}${modelName}`)
519
- }
520
- }
521
- }
522
- };
523
- };
524
- const getRouteTypeMethod = (routeType) => {
525
- switch (routeType) {
526
- case RouteType.RouteType.CREATE: {
527
- return "post";
528
- }
529
- case RouteType.RouteType.DELETE: {
530
- return "delete";
531
- }
532
- case RouteType.RouteType.READ_ALL:
533
- case RouteType.RouteType.READ_ONE: {
534
- return "get";
535
- }
536
- case RouteType.RouteType.UPDATE: {
537
- return "put";
538
- }
539
- default: {
540
- throw new TypeError(`Method for route type ${routeType} was not found.`);
541
- }
542
- }
543
- };
544
- const generateSwaggerPathObject = ({
545
- hasId,
546
- modelName,
547
- modelsConfig,
548
- routeTypes,
549
- tag
550
- }) => {
551
- const methods = {};
552
- routeTypes.forEach((routeType) => {
553
- if (routeTypes.includes(routeType)) {
554
- const returnType = modelsConfig?.[modelName]?.routeTypes?.[routeType]?.response.name ?? modelsConfig?.[modelName]?.type?.name ?? modelName;
555
- const method = getRouteTypeMethod(routeType);
556
- const response = generateSwaggerResponse(routeType, returnType);
557
- if (response === void 0) {
558
- throw new TypeError(`Route type ${routeType}; response config was not found.`);
559
- }
560
- methods[method] = {
561
- parameters: getQueryParameters(routeType).map((queryParameter) => {
562
- return { ...queryParameter, in: "query" };
563
- }),
564
- responses: {
565
- [response.statusCode]: response.content,
566
- ...modelsConfig?.[modelName]?.routeTypes?.[routeType]?.responses
567
- },
568
- summary: modelsConfig?.[modelName]?.routeTypes?.[routeType]?.summary,
569
- tags: [tag]
570
- };
571
- if (hasId) {
572
- methods[method].parameters.push({
573
- description: `ID of the ${modelName}`,
574
- in: "path",
575
- name: "id",
576
- required: true,
577
- schema: {
578
- type: "string"
579
- }
580
- });
581
- }
582
- if (routeType === RouteType.RouteType.UPDATE) {
583
- methods[method].requestBody = generateRequestBody("Update", returnType);
584
- } else if (routeType === RouteType.RouteType.CREATE) {
585
- methods[method].requestBody = generateRequestBody("Create", returnType);
586
- }
587
- }
588
- });
589
- return methods;
590
- };
591
- const getSwaggerPaths = ({ models, modelsConfig, routes, routesMap }) => (
592
- // eslint-disable-next-line unicorn/no-array-reduce
593
- Object.keys(routes).reduce((accumulator, value) => {
594
- const routeTypes = routes[value];
595
- const resourceName = models?.[value]?.name ?? routesMap?.[value] ?? value;
596
- const tag = modelsConfig?.[value]?.tag.name ?? value;
597
- if (routeTypes.includes(RouteType.RouteType.CREATE) || routeTypes.includes(RouteType.RouteType.READ_ALL)) {
598
- const path = `/${resourceName}`;
599
- const routeTypesToUse = [RouteType.RouteType.READ_ALL, RouteType.RouteType.CREATE].filter((routeType) => routeTypes.includes(routeType));
600
- accumulator[path] = generateSwaggerPathObject({
601
- modelName: value,
602
- modelsConfig,
603
- routeTypes: routeTypesToUse,
604
- tag
605
- });
606
- }
607
- if (routeTypes.includes(RouteType.RouteType.READ_ONE) || routeTypes.includes(RouteType.RouteType.UPDATE) || routeTypes.includes(RouteType.RouteType.DELETE)) {
608
- const path = `/${resourceName}/{id}`;
609
- const routeTypesToUse = [RouteType.RouteType.READ_ONE, RouteType.RouteType.UPDATE, RouteType.RouteType.DELETE].filter((routeType) => routeTypes.includes(routeType));
610
- accumulator[path] = generateSwaggerPathObject({
611
- hasId: true,
612
- modelName: value,
613
- modelsConfig,
614
- routeTypes: routeTypesToUse,
615
- tag
616
- });
617
- }
618
- return accumulator;
619
- }, {})
620
- );
621
-
622
- const getSwaggerTags = (modelNames, modelsConfig) => modelNames.map((modelName) => {
623
- if (modelsConfig?.[modelName]?.tag) {
624
- return modelsConfig[modelName].tag;
625
- }
626
- return {
627
- name: modelName
628
- };
629
- });
630
-
631
- const overwritePathsExampleWithModel = (swaggerPaths, examples) => {
632
- Object.values(swaggerPaths).forEach((pathSpec) => {
633
- Object.values(pathSpec).forEach((methodSpec) => {
634
- if (typeof methodSpec.responses === "object") {
635
- Object.values(methodSpec.responses).forEach((responseSpec) => {
636
- if (typeof responseSpec.content === "object") {
637
- Object.values(responseSpec.content).forEach(
638
- (contentSpec) => {
639
- if (typeof contentSpec.example === "string") {
640
- const example = contentSpec.example.replace("#/components/examples/", "");
641
- if (examples[example]?.value !== void 0) {
642
- contentSpec.example = examples[example].value;
643
- }
644
- }
645
- }
646
- );
647
- }
648
- });
649
- }
650
- });
651
- });
652
- return swaggerPaths;
653
- };
654
- const modelsToOpenApi = async ({
655
- crud = { models: {} },
656
- defaultExposeStrategy = "all",
657
- models: ctorModels,
658
- prismaClient,
659
- swagger = { allowedMediaTypes: { "application/json": true }, models: {} }
660
- }) => {
661
- let dmmf;
662
- let prismaDmmfModels;
663
- if (prismaClient._dmmf !== void 0) {
664
- dmmf = prismaClient._dmmf;
665
- prismaDmmfModels = dmmf?.mappingsMap;
666
- } else if (prismaClient._getDmmf !== void 0) {
667
- dmmf = await prismaClient._getDmmf();
668
- prismaDmmfModels = dmmf.mappingsMap;
669
- }
670
- if (dmmf === void 0) {
671
- throw new TypeError("Couldn't get prisma client models");
672
- }
673
- const parser = new PrismaJsonSchemaParser(dmmf);
674
- const definitions = parser.parseModels();
675
- const dModels = Object.keys(definitions);
676
- const schema = JSON.stringify({
677
- ...definitions,
678
- ...parser.parseInputTypes(dModels),
679
- ...parser.getPaginationDataSchema(),
680
- ...parser.getPaginatedModelsSchemas(dModels)
681
- });
682
- if (ctorModels !== void 0) {
683
- ctorModels.forEach((model) => {
684
- if (!Object.keys(prismaDmmfModels).includes(model)) {
685
- throw new Error(`Model name ${model} is invalid.`);
686
- }
687
- });
688
- }
689
- const models = ctorModels ?? Object.keys(prismaDmmfModels);
690
- const swaggerRoutes = getModelsAccessibleRoutes(models, crud.models, defaultExposeStrategy);
691
- const swaggerTags = getSwaggerTags(models, swagger.models);
692
- const swaggerPaths = getSwaggerPaths({
693
- models: crud.models,
694
- modelsConfig: swagger.models,
695
- routes: swaggerRoutes,
696
- routesMap: modelsToRouteNames.modelsToRouteNames(prismaDmmfModels, models)
697
- });
698
- const schemas = JSON.parse(schema.replaceAll("#/definitions", "#/components/schemas"));
699
- const examples = parser.getExampleModelsSchemas(dModels, schemas);
700
- return {
701
- examples,
702
- paths: overwritePathsExampleWithModel(swaggerPaths, examples),
703
- schemas,
704
- tags: swaggerTags
705
- };
706
- };
707
-
708
- module.exports = modelsToOpenApi;