@visulima/crud 1.0.1 → 1.0.3

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 (54) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +46 -16
  3. package/dist/chunk-SH6A4KBC.mjs +28 -0
  4. package/dist/{chunk-UBXIGP5H.mjs.map → chunk-SH6A4KBC.mjs.map} +1 -1
  5. package/dist/chunk-ZY3WOLEP.js +28 -0
  6. package/dist/chunk-ZY3WOLEP.js.map +1 -0
  7. package/dist/index.d.ts +9 -15
  8. package/dist/index.js +57 -37
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +54 -34
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/next/index.js +10 -281
  13. package/dist/next/index.js.map +1 -1
  14. package/dist/next/index.mjs +9 -280
  15. package/dist/next/index.mjs.map +1 -1
  16. package/next/package.json +18 -0
  17. package/package.json +16 -14
  18. package/dist/chunk-FJWRITBO.js +0 -52
  19. package/dist/chunk-FJWRITBO.js.map +0 -1
  20. package/dist/chunk-UBXIGP5H.mjs +0 -52
  21. package/src/adapter/prisma/index.ts +0 -241
  22. package/src/adapter/prisma/types.d.ts +0 -46
  23. package/src/adapter/prisma/utils/models-to-route-names.ts +0 -12
  24. package/src/adapter/prisma/utils/parse-cursor.ts +0 -26
  25. package/src/adapter/prisma/utils/parse-order-by.ts +0 -21
  26. package/src/adapter/prisma/utils/parse-recursive.ts +0 -26
  27. package/src/adapter/prisma/utils/parse-where.ts +0 -197
  28. package/src/base-crud-handler.ts +0 -181
  29. package/src/handler/create.ts +0 -21
  30. package/src/handler/delete.ts +0 -27
  31. package/src/handler/list.ts +0 -62
  32. package/src/handler/read.ts +0 -27
  33. package/src/handler/update.ts +0 -29
  34. package/src/index.ts +0 -27
  35. package/src/next/api/edge/index.ts +0 -23
  36. package/src/next/api/node/index.ts +0 -27
  37. package/src/next/index.ts +0 -2
  38. package/src/query-parser.ts +0 -94
  39. package/src/swagger/adapter/prisma/index.ts +0 -95
  40. package/src/swagger/json-schema-parser.ts +0 -456
  41. package/src/swagger/parameters.ts +0 -83
  42. package/src/swagger/types.d.ts +0 -53
  43. package/src/swagger/utils/format-example-ref.ts +0 -4
  44. package/src/swagger/utils/format-schema-ref.ts +0 -4
  45. package/src/swagger/utils/get-models-accessible-routes.ts +0 -23
  46. package/src/swagger/utils/get-swagger-paths.ts +0 -244
  47. package/src/swagger/utils/get-swagger-tags.ts +0 -13
  48. package/src/types.d.ts +0 -124
  49. package/src/utils/format-resource-id.ts +0 -3
  50. package/src/utils/get-accessible-routes.ts +0 -18
  51. package/src/utils/get-resource-name-from-url.ts +0 -23
  52. package/src/utils/get-route-type.ts +0 -99
  53. package/src/utils/is-primitive.ts +0 -5
  54. package/src/utils/validate-adapter-methods.ts +0 -15
@@ -1,52 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __commonJS = (cb, mod) => function __require() {
8
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
20
- mod
21
- ));
22
-
23
- // src/types.d.ts
24
- var RouteType = /* @__PURE__ */ ((RouteType2) => {
25
- RouteType2["CREATE"] = "CREATE";
26
- RouteType2["READ_ALL"] = "READ_ALL";
27
- RouteType2["READ_ONE"] = "READ_ONE";
28
- RouteType2["UPDATE"] = "UPDATE";
29
- RouteType2["DELETE"] = "DELETE";
30
- return RouteType2;
31
- })(RouteType || {});
32
-
33
- // src/utils/get-accessible-routes.ts
34
- var getAccessibleRoutes = (only, exclude, defaultExposeStrategy = "all") => {
35
- let accessibleRoutes = defaultExposeStrategy === "none" ? [] : ["READ_ALL" /* READ_ALL */, "READ_ONE" /* READ_ONE */, "UPDATE" /* UPDATE */, "DELETE" /* DELETE */, "CREATE" /* CREATE */];
36
- if (Array.isArray(only)) {
37
- accessibleRoutes = only;
38
- }
39
- if (exclude == null ? void 0 : exclude.length) {
40
- accessibleRoutes = accessibleRoutes.filter((element) => !exclude.includes(element));
41
- }
42
- return accessibleRoutes;
43
- };
44
- var get_accessible_routes_default = getAccessibleRoutes;
45
-
46
-
47
-
48
-
49
-
50
-
51
- exports.__commonJS = __commonJS; exports.__toESM = __toESM; exports.RouteType = RouteType; exports.get_accessible_routes_default = get_accessible_routes_default;
52
- //# sourceMappingURL=chunk-FJWRITBO.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/types.d.ts","../src/utils/get-accessible-routes.ts"],"names":["RouteType"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAMO,IAAK,YAAL,kBAAKA,eAAL;AACH,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,cAAW;AACX,EAAAA,WAAA,cAAW;AACX,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,YAAS;AALD,SAAAA;AAAA,GAAA;;;ACJZ,IAAM,sBAAsB,CAAC,MAAoB,SAAuB,wBAAwC,UAAuB;AAEnI,MAAI,mBAAgC,0BAA0B,SAAS,CAAC,IAAI,0HAA6F;AAEzK,MAAI,MAAM,QAAQ,IAAI,GAAG;AACrB,uBAAmB;AAAA,EACvB;AAEA,MAAI,mCAAS,QAAQ;AACjB,uBAAmB,iBAAiB,OAAO,CAAC,YAAY,CAAC,QAAQ,SAAS,OAAO,CAAC;AAAA,EACtF;AAEA,SAAO;AACX;AAEA,IAAO,gCAAQ","sourcesContent":["import type { Handler as CreateHandler } from \"./handler/create\";\nimport type { Handler as DeleteHandler } from \"./handler/delete\";\nimport type { Handler as ListHandler } from \"./handler/list\";\nimport type { Handler as GetHandler } from \"./handler/read\";\nimport type { Handler as UpdateHandler } from \"./handler/update\";\n\nexport enum RouteType {\n CREATE = \"CREATE\",\n READ_ALL = \"READ_ALL\",\n READ_ONE = \"READ_ONE\",\n UPDATE = \"UPDATE\",\n DELETE = \"DELETE\",\n}\n\nexport type ModelOption = {\n name?: string\n only?: RouteType[]\n exclude?: RouteType[]\n formatResourceId?: (resourceId: string) => string | number\n};\n\nexport type ModelsOptions<M extends string = string> = {\n [key in M]?: ModelOption\n};\n\nexport type HandlerOptions<M extends string = string> = {\n formatResourceId?: (resourceId: string) => string | number;\n models?: ModelsOptions<M>;\n exposeStrategy?: \"all\" | \"none\";\n pagination?: PaginationConfig,\n handlers?: {\n create?: CreateHandler;\n delete?: DeleteHandler;\n get?: GetHandler;\n list?: ListHandler;\n update?: UpdateHandler;\n },\n};\n\nexport type PaginationConfig = {\n perPage: number\n};\n\nexport interface HandlerParameters<T, Q> {\n adapter: Adapter<T, Q>;\n query: Q;\n resourceName: string;\n}\n\nexport interface UniqueResourceHandlerParameters<T, Q> {\n adapter: Adapter<T, Q>;\n query: Q;\n resourceName: string;\n resourceId: string | number;\n}\n\nexport interface Adapter<T, Q, M extends string = string> {\n models?: M[];\n init?: () => Promise<void>;\n parseQuery(resourceName: M, query: ParsedQueryParameters): Q;\n getAll(resourceName: M, query: Q): Promise<T[]>;\n getOne(resourceName: M, resourceId: string | number, query: Q): Promise<T>;\n create(resourceName: M, data: any, query: Q): Promise<T>;\n update(resourceName: M, resourceId: string | number, data: any, query: Q): Promise<T>;\n delete(resourceName: M, resourceId: string | number, query: Q): Promise<T>;\n getPaginationData(resourceName: M, query: Q): Promise<PaginationData>;\n getModels(): M[];\n connect?: () => Promise<void>;\n disconnect?: () => Promise<void>;\n handleError?: (error: Error) => void;\n mapModelsToRouteNames?: () => Promise<{ [key in M]?: string }>;\n}\n\nexport type PaginationData = {\n total: number\n pageCount: number\n page: number\n};\n\nexport type RecursiveField = {\n [key: string]: boolean | TRecursiveField;\n};\n\nexport type WhereOperator = \"$eq\" | \"$neq\" | \"$in\" | \"$notin\" | \"$lt\" | \"$lte\" | \"$gt\" | \"$gte\" | \"$cont\" | \"$starts\" | \"$ends\" | \"$isnull\";\n\nexport type SearchCondition = string | boolean | number | Date | null;\n\nexport type WhereCondition = {\n [key in TWhereOperator]?: TSearchCondition;\n};\n\nexport type Condition = {\n [key: string]: TSearchCondition | TWhereCondition | TCondition;\n};\n\nexport type WhereField = Condition & {\n $and?: TCondition | TCondition[];\n $or?: TCondition | TCondition[];\n $not?: TCondition | TCondition[];\n};\n\nexport type OrderByOperator = \"$asc\" | \"$desc\";\n\nexport type OrderByField = {\n [key: string]: TOrderByOperator;\n};\n\nexport interface ParsedQueryParameters {\n select?: RecursiveField;\n include?: RecursiveField;\n where?: WhereField;\n orderBy?: OrderByField;\n limit?: number;\n skip?: number;\n distinct?: string;\n page?: number;\n originalQuery?: {\n [key: string]: any;\n };\n}\n\nexport interface ExecuteHandler<Request, Response> {\n (request: Request, response: Response): Promise<void>;\n}\n","import { RouteType } from \"../types.d\";\n\nconst getAccessibleRoutes = (only?: RouteType[], exclude?: RouteType[], defaultExposeStrategy: \"all\" | \"none\" = \"all\"): RouteType[] => {\n // eslint-disable-next-line max-len\n let accessibleRoutes: RouteType[] = defaultExposeStrategy === \"none\" ? [] : [RouteType.READ_ALL, RouteType.READ_ONE, RouteType.UPDATE, RouteType.DELETE, RouteType.CREATE];\n\n if (Array.isArray(only)) {\n accessibleRoutes = only;\n }\n\n if (exclude?.length) {\n accessibleRoutes = accessibleRoutes.filter((element) => !exclude.includes(element));\n }\n\n return accessibleRoutes;\n};\n\nexport default getAccessibleRoutes;\n"]}
@@ -1,52 +0,0 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __commonJS = (cb, mod) => function __require() {
8
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
20
- mod
21
- ));
22
-
23
- // src/types.d.ts
24
- var RouteType = /* @__PURE__ */ ((RouteType2) => {
25
- RouteType2["CREATE"] = "CREATE";
26
- RouteType2["READ_ALL"] = "READ_ALL";
27
- RouteType2["READ_ONE"] = "READ_ONE";
28
- RouteType2["UPDATE"] = "UPDATE";
29
- RouteType2["DELETE"] = "DELETE";
30
- return RouteType2;
31
- })(RouteType || {});
32
-
33
- // src/utils/get-accessible-routes.ts
34
- var getAccessibleRoutes = (only, exclude, defaultExposeStrategy = "all") => {
35
- let accessibleRoutes = defaultExposeStrategy === "none" ? [] : ["READ_ALL" /* READ_ALL */, "READ_ONE" /* READ_ONE */, "UPDATE" /* UPDATE */, "DELETE" /* DELETE */, "CREATE" /* CREATE */];
36
- if (Array.isArray(only)) {
37
- accessibleRoutes = only;
38
- }
39
- if (exclude == null ? void 0 : exclude.length) {
40
- accessibleRoutes = accessibleRoutes.filter((element) => !exclude.includes(element));
41
- }
42
- return accessibleRoutes;
43
- };
44
- var get_accessible_routes_default = getAccessibleRoutes;
45
-
46
- export {
47
- __commonJS,
48
- __toESM,
49
- RouteType,
50
- get_accessible_routes_default
51
- };
52
- //# sourceMappingURL=chunk-UBXIGP5H.mjs.map
@@ -1,241 +0,0 @@
1
- // eslint-disable-next-line import/no-extraneous-dependencies
2
- import {
3
- // @ts-ignore
4
- PrismaAction,
5
- // @ts-ignore
6
- PrismaClient,
7
- } from "@prisma/client";
8
- import createHttpError from "http-errors";
9
-
10
- import type { Adapter, PaginationData, ParsedQueryParameters } from "../../types.d";
11
- import type { PrismaParsedQueryParameters } from "./types.d";
12
- import modelsToRouteNames from "./utils/models-to-route-names";
13
- import parsePrismaCursor from "./utils/parse-cursor";
14
- import parsePrismaOrderBy from "./utils/parse-order-by";
15
- import parsePrismaRecursiveField from "./utils/parse-recursive";
16
- import parsePrismaWhere from "./utils/parse-where";
17
-
18
- interface AdapterCtorArguments<M extends string = string> {
19
- primaryKey?: string;
20
- manyRelations?: {
21
- [key in M]?: string[];
22
- };
23
- prismaClient: PrismaClient;
24
- models?: M[];
25
- }
26
-
27
- export default class PrismaAdapter<T, M extends string> implements Adapter<T, PrismaParsedQueryParameters, M> {
28
- private readonly primaryKey: string;
29
-
30
- private readonly manyRelations: {
31
- [key in M]?: string[];
32
- };
33
-
34
- private readonly prismaClient: PrismaClient;
35
-
36
- models?: M[];
37
-
38
- private readonly ctorModels?: M[];
39
-
40
- private dmmf: any;
41
-
42
- constructor({
43
- primaryKey = "id", prismaClient, manyRelations = {}, models,
44
- }: AdapterCtorArguments<M>) {
45
- this.prismaClient = prismaClient;
46
- this.primaryKey = primaryKey;
47
- this.manyRelations = manyRelations;
48
- this.ctorModels = models;
49
- }
50
-
51
- private getPrismaClientModels = async () => {
52
- // eslint-disable-next-line no-underscore-dangle
53
- if (this.prismaClient._dmmf) {
54
- // eslint-disable-next-line no-underscore-dangle
55
- this.dmmf = this.prismaClient._dmmf;
56
-
57
- return this.dmmf?.mappingsMap;
58
- }
59
-
60
- // eslint-disable-next-line no-underscore-dangle
61
- if (this.prismaClient._getDmmf) {
62
- // eslint-disable-next-line no-underscore-dangle
63
- this.dmmf = await this.prismaClient._getDmmf();
64
-
65
- return this.dmmf.mappingsMap;
66
- }
67
-
68
- throw new Error("Couldn't get prisma client models");
69
- };
70
-
71
- async init() {
72
- const models = this.ctorModels;
73
- const prismaDmmfModels = await this.getPrismaClientModels();
74
-
75
- if (typeof models !== "undefined") {
76
- models.forEach((model) => {
77
- if (!Object.keys(prismaDmmfModels).includes(model)) {
78
- throw new Error(`Model name ${model} is invalid.`);
79
- }
80
- });
81
- }
82
-
83
- // @ts-ignore
84
- this.models = models ?? (Object.keys(prismaDmmfModels) as M[]); // Retrieve model names from dmmf for prisma v2
85
- }
86
-
87
- async getPaginationData(resourceName: M, query: PrismaParsedQueryParameters): Promise<PaginationData> {
88
- // @ts-ignore
89
- const total: number = await this.getPrismaDelegate(resourceName).count({
90
- where: query.where,
91
- distinct: query.distinct,
92
- });
93
-
94
- return {
95
- total,
96
- pageCount: Math.ceil(total / (query.take as number)),
97
- page: Math.ceil((query.skip as number) / (query.take as number)) + 1,
98
- };
99
- }
100
-
101
- // eslint-disable-next-line class-methods-use-this
102
- handleError(error: any) {
103
- // eslint-disable-next-line no-console
104
- console.error(error);
105
-
106
- if (error instanceof Error && error.stack) {
107
- // eslint-disable-next-line no-console
108
- console.error(error.stack);
109
- }
110
-
111
- throw error.constructor.name === "PrismaClientKnownRequestError" || error.constructor.name === "PrismaClientValidationError"
112
- ? createHttpError(400, "invalid request, check your server logs for more info")
113
- : createHttpError(500, "an unknown error occured, check your server logs for more info");
114
- }
115
-
116
- parseQuery(resourceName: M, query: ParsedQueryParameters) {
117
- const parsed: PrismaParsedQueryParameters = {};
118
-
119
- if (query.select) {
120
- parsed.select = parsePrismaRecursiveField(query.select, "select");
121
- }
122
-
123
- if (query.include) {
124
- parsed.include = parsePrismaRecursiveField(query.include, "include");
125
- }
126
-
127
- if (query.originalQuery?.where) {
128
- parsed.where = parsePrismaWhere(JSON.parse(query.originalQuery.where), this.manyRelations[resourceName] ?? []);
129
- }
130
-
131
- if (query.orderBy) {
132
- parsed.orderBy = parsePrismaOrderBy(query.orderBy);
133
- }
134
-
135
- if (typeof query.limit !== "undefined") {
136
- parsed.take = query.limit;
137
- }
138
-
139
- if (typeof query.skip !== "undefined") {
140
- parsed.skip = query.skip;
141
- }
142
-
143
- if (query.originalQuery?.cursor) {
144
- parsed.cursor = parsePrismaCursor(JSON.parse(query.originalQuery.cursor));
145
- }
146
-
147
- if (query.distinct) {
148
- parsed.distinct = query.distinct;
149
- }
150
-
151
- return parsed;
152
- }
153
-
154
- async getAll(resourceName: M, query: PrismaParsedQueryParameters): Promise<T[]> {
155
- // @ts-ignore
156
- return (await this.getPrismaDelegate(resourceName).findMany({
157
- select: query.select,
158
- include: query.include,
159
- where: query.where,
160
- orderBy: query.orderBy,
161
- cursor: query.cursor,
162
- take: query.take,
163
- skip: query.skip,
164
- distinct: query.distinct,
165
- })) as T[];
166
- }
167
-
168
- async getOne(resourceName: M, resourceId: string | number, query: PrismaParsedQueryParameters): Promise<T> {
169
- const delegate = this.getPrismaDelegate(resourceName);
170
- /**
171
- * On prisma v2.12, findOne has been deprecated in favor of findUnique
172
- * We use findUnique in priority only if it's available
173
- */
174
- const findFunction = delegate.findUnique || delegate.findOne;
175
-
176
- // @ts-ignore
177
- return findFunction({
178
- where: {
179
- [this.primaryKey]: resourceId,
180
- },
181
- select: query.select,
182
- include: query.include,
183
- });
184
- }
185
-
186
- async create(resourceName: M, data: any, query: PrismaParsedQueryParameters): Promise<T> {
187
- // @ts-ignore
188
- return this.getPrismaDelegate(resourceName).create({
189
- data,
190
- select: query.select,
191
- include: query.include,
192
- });
193
- }
194
-
195
- async update(resourceName: M, resourceId: string | number, data: any, query: PrismaParsedQueryParameters): Promise<T> {
196
- // @ts-ignore
197
- return this.getPrismaDelegate(resourceName).update({
198
- where: {
199
- [this.primaryKey]: resourceId,
200
- },
201
- data,
202
- select: query.select,
203
- include: query.include,
204
- });
205
- }
206
-
207
- async delete(resourceName: M, resourceId: string | number, query: PrismaParsedQueryParameters): Promise<T> {
208
- // @ts-ignore
209
- return this.getPrismaDelegate(resourceName).delete({
210
- where: {
211
- [this.primaryKey]: resourceId,
212
- },
213
- select: query.select,
214
- include: query.include,
215
- });
216
- }
217
-
218
- connect() {
219
- return this.prismaClient.$connect();
220
- }
221
-
222
- disconnect() {
223
- return this.prismaClient.$disconnect();
224
- }
225
-
226
- get client() {
227
- return this.prismaClient;
228
- }
229
-
230
- getModels() {
231
- return this.models || [];
232
- }
233
-
234
- private getPrismaDelegate(resourceName: M): Record<PrismaAction, (...arguments_: any[]) => Promise<T>> {
235
- return this.prismaClient[`${resourceName.charAt(0).toLowerCase()}${resourceName.slice(1)}`];
236
- }
237
-
238
- public async mapModelsToRouteNames() {
239
- return modelsToRouteNames(await this.getPrismaClientModels(), this.getModels());
240
- }
241
- }
@@ -1,46 +0,0 @@
1
- import type { Condition, SearchCondition } from "../../types.d";
2
-
3
- export type PrismaRecursiveField = "select" | "include";
4
-
5
- export type PrismaRecursive<T extends PrismaRecursiveField> = Record<string, boolean | { [key in T]: PrismaRecursive<T> }>;
6
-
7
- export type PrismaWhereOperator = "equals" | "not" | "in" | "notIn" | "lt" | "lte" | "gt" | "gte" | "contains" | "startsWith" | "endsWith";
8
-
9
- export type PrismaOrderByOperator = "asc" | "desc";
10
-
11
- export type PrismaFieldFilterOperator = {
12
- [key in PrismaWhereOperator]?: SearchCondition;
13
- };
14
-
15
- export type PrismaFieldFilter = {
16
- [key: string]: SearchCondition | PrismaFieldFilterOperator | PrismaRelationFilter | Condition | undefined;
17
- };
18
-
19
- export type PrismaWhereField = PrismaFieldFilter & {
20
- AND?: PrismaFieldFilter;
21
- OR?: PrismaFieldFilter;
22
- NOT?: PrismaFieldFilter;
23
- };
24
-
25
- export type PrismaRelationFilter = {
26
- some: SearchCondition | PrismaFieldFilter;
27
- };
28
-
29
- export type PrismaOrderBy = {
30
- [key: string]: PrismaOrderByOperator;
31
- };
32
-
33
- export type PrismaCursor = {
34
- [key: string]: string | number | boolean;
35
- };
36
-
37
- export interface PrismaParsedQueryParameters {
38
- select?: PrismaRecursive<"select">;
39
- include?: PrismaRecursive<"include">;
40
- where?: PrismaWhereField;
41
- orderBy?: PrismaOrderBy;
42
- take?: number;
43
- skip?: number;
44
- cursor?: PrismaCursor;
45
- distinct?: string;
46
- }
@@ -1,12 +0,0 @@
1
- const modelsToRouteNames = <M extends string = string>(mappingsMap: { [key: string]: object }, models: M[]) => {
2
- const routesMap: { [key in M]?: string } = {};
3
-
4
- models?.forEach((model) => {
5
- // @ts-ignore
6
- routesMap[model] = mappingsMap[model].plural;
7
- });
8
-
9
- return routesMap;
10
- };
11
-
12
- export default modelsToRouteNames;
@@ -1,26 +0,0 @@
1
- import isPrimitive from "../../../utils/is-primitive";
2
- import type { PrismaCursor } from "../types.d";
3
-
4
- const parsePrismaCursor = (
5
- cursor: Record<string, string | number | boolean>,
6
- ): PrismaCursor => {
7
- const parsed: PrismaCursor = {};
8
-
9
- Object.keys(cursor).forEach((key) => {
10
- const value = cursor[key];
11
-
12
- if (isPrimitive(value)) {
13
- parsed[key as keyof typeof cursor] = value as string | number | boolean;
14
- }
15
- });
16
-
17
- if (Object.keys(parsed).length !== 1) {
18
- throw new Error(
19
- "cursor needs to be an object with exactly 1 property with a primitive value",
20
- );
21
- }
22
-
23
- return parsed;
24
- };
25
-
26
- export default parsePrismaCursor;
@@ -1,21 +0,0 @@
1
- import type { OrderByField, OrderByOperator } from "../../../types.d";
2
- import type { PrismaOrderBy, PrismaOrderByOperator } from "../types.d";
3
-
4
- const operatorsAssociation: Record<OrderByOperator, PrismaOrderByOperator> = {
5
- $asc: "asc",
6
- $desc: "desc",
7
- };
8
-
9
- const parsePrismaOrderBy = (orderBy: OrderByField): PrismaOrderBy => {
10
- const parsed: PrismaOrderBy = {};
11
-
12
- Object.keys(orderBy).forEach((key) => {
13
- const value = orderBy[key];
14
-
15
- parsed[key] = operatorsAssociation[value as OrderByOperator];
16
- });
17
-
18
- return parsed;
19
- };
20
-
21
- export default parsePrismaOrderBy;
@@ -1,26 +0,0 @@
1
- import type { RecursiveField } from "../../../types.d";
2
- import type { PrismaRecursive, PrismaRecursiveField } from "../types.d";
3
-
4
- const parsePrismaRecursiveField = <T extends PrismaRecursiveField>(
5
- select: RecursiveField,
6
- fieldName: T,
7
- ): PrismaRecursive<T> => {
8
- const parsed: PrismaRecursive<T> = {};
9
-
10
- Object.keys(select).forEach((field) => {
11
- if (select[field] !== true) {
12
- parsed[field] = {
13
- [fieldName]: parsePrismaRecursiveField(
14
- select[field] as RecursiveField,
15
- fieldName,
16
- ),
17
- } as Record<T, PrismaRecursive<T>>;
18
- } else {
19
- parsed[field] = true;
20
- }
21
- });
22
-
23
- return parsed;
24
- };
25
-
26
- export default parsePrismaRecursiveField;
@@ -1,197 +0,0 @@
1
- import type {
2
- Condition, SearchCondition, WhereCondition, WhereField, WhereOperator,
3
- } from "../../../types.d";
4
- import isPrimitive from "../../../utils/is-primitive";
5
- import type {
6
- PrismaFieldFilter, PrismaRelationFilter, PrismaWhereField, PrismaWhereOperator,
7
- } from "../types.d";
8
-
9
- const isObject = (a: any) => a instanceof Object;
10
-
11
- const operatorsAssociation: {
12
- [key in WhereOperator]?: PrismaWhereOperator;
13
- } = {
14
- $eq: "equals",
15
- $neq: "not",
16
- $cont: "contains",
17
- $ends: "endsWith",
18
- $gt: "gt",
19
- $gte: "gte",
20
- $in: "in",
21
- $lt: "lt",
22
- $lte: "lte",
23
- $notin: "notIn",
24
- $starts: "startsWith",
25
- };
26
-
27
- const isDateString = (value: string) => /^\d{4}-[01]\d-[0-3]\d(?:T[0-2](?:\d:[0-5]){2}\d(?:\.\d+)?(?:Z|[+-][0-2]\d(?::?[0-5]\d)?)?)?$/g.test(value);
28
-
29
- const getSearchValue = (originalValue: any): SearchCondition => {
30
- if (isDateString(originalValue)) {
31
- return new Date(originalValue);
32
- }
33
-
34
- if (typeof originalValue === "string" && originalValue === "$isnull") {
35
- return null;
36
- }
37
-
38
- return originalValue;
39
- };
40
-
41
- const isRelation = (key: string, manyRelations: string[]): boolean => {
42
- // Get the key containing . and remove the property name
43
- const splitKey = key.split(".");
44
- splitKey.splice(-1, 1);
45
-
46
- return manyRelations.includes(splitKey.join("."));
47
- };
48
-
49
- const parseSimpleField = (value: Condition): undefined | { [key: string]: Condition } => {
50
- const operator = Object.keys(value)[0];
51
- const prismaOperator: undefined | PrismaWhereOperator = operatorsAssociation[operator as keyof typeof operatorsAssociation];
52
-
53
- if (prismaOperator) {
54
- return {
55
- [prismaOperator]: value[operator as string],
56
- };
57
- }
58
-
59
- return undefined;
60
- };
61
-
62
- const parseRelation = (
63
- value: string | number | boolean | Date | Condition | WhereCondition,
64
- key: string,
65
- parsed: PrismaWhereField,
66
- manyRelations: string[],
67
- ) => {
68
- // Reverse the keys so that we can format our object by nesting
69
- const fields = key.split(".").reverse();
70
-
71
- let formatFields: { [key: string]: any } = {};
72
-
73
- fields.forEach((field, index) => {
74
- // If we iterate over the property name, which is index 0, we parse it like a normal field
75
- if (index === 0) {
76
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
77
- basicParse(value, field, formatFields, manyRelations);
78
- // Else we format the relation filter in the prisma way
79
- } else {
80
- formatFields = {
81
- [field]: {
82
- some: formatFields,
83
- },
84
- };
85
- }
86
- });
87
-
88
- // Retrieve the main relation field
89
- const initialFieldKey = fields.reverse()[0] as string;
90
- // Retrieve the old parsed version
91
- const oldParsed = parsed[initialFieldKey] as PrismaRelationFilter;
92
-
93
- // Format correctly in the prisma way
94
- // eslint-disable-next-line no-param-reassign
95
- parsed[initialFieldKey] = {
96
- some: {
97
- ...(oldParsed?.some as object),
98
- ...(formatFields[initialFieldKey as string]?.some as object),
99
- },
100
- };
101
- };
102
-
103
- const parseObjectCombination = (object: Condition, manyRelations: string[]): PrismaFieldFilter => {
104
- const parsed: PrismaFieldFilter = {};
105
-
106
- Object.keys(object).forEach((key) => {
107
- const value = object[key];
108
-
109
- if (isRelation(key, manyRelations)) {
110
- parseRelation(value, key, parsed, manyRelations);
111
- } else if (isPrimitive(value)) {
112
- parsed[key] = value as SearchCondition;
113
- } else if (isObject(value)) {
114
- const fieldResult = parseSimpleField(value as Condition);
115
-
116
- if (fieldResult) {
117
- parsed[key] = fieldResult;
118
- }
119
- }
120
- });
121
-
122
- return parsed;
123
- };
124
-
125
- const basicParse = (value: string | number | boolean | Condition | Date | WhereCondition, key: string, parsed: PrismaWhereField, manyRelations: string[]) => {
126
- if (isPrimitive(value)) {
127
- // eslint-disable-next-line no-param-reassign
128
- parsed[key] = getSearchValue(value);
129
- } else {
130
- switch (key) {
131
- case "$or": {
132
- if (isObject(value)) {
133
- // eslint-disable-next-line no-param-reassign
134
- parsed.OR = parseObjectCombination(value as Condition, manyRelations);
135
- }
136
- break;
137
- }
138
- case "$and": {
139
- if (isObject(value)) {
140
- // eslint-disable-next-line no-param-reassign
141
- parsed.AND = parseObjectCombination(value as Condition, manyRelations);
142
- }
143
- break;
144
- }
145
- case "$not": {
146
- if (isObject(value)) {
147
- // eslint-disable-next-line no-param-reassign
148
- parsed.NOT = parseObjectCombination(value as Condition, manyRelations);
149
- }
150
- break;
151
- }
152
- default: {
153
- // eslint-disable-next-line no-param-reassign
154
- parsed[key] = parseSimpleField(value as Condition);
155
- break;
156
- }
157
- }
158
- }
159
- };
160
-
161
- const parsePrismaWhere = (where: WhereField, manyRelations: string[]): PrismaWhereField => {
162
- const parsed: PrismaWhereField = {};
163
-
164
- Object.keys(where).forEach((key) => {
165
- const value = where[key];
166
- /**
167
- * If the key without property name is a relation
168
- *
169
- * We want the following example input:
170
- *
171
- * posts.author.id: 1
172
- *
173
- * to output
174
- *
175
- * {
176
- * posts: {
177
- * some: {
178
- * author: {
179
- * some: {
180
- * id: 1
181
- * }
182
- * }
183
- * }
184
- * }
185
- * }
186
- */
187
- if (isRelation(key, manyRelations)) {
188
- parseRelation(value, key, parsed, manyRelations);
189
- } else {
190
- basicParse(value, key, parsed, manyRelations);
191
- }
192
- });
193
-
194
- return parsed;
195
- };
196
-
197
- export default parsePrismaWhere;