@visulima/crud 1.0.0 → 1.0.2

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 +21 -0
  2. package/README.md +48 -18
  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
package/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ ## @visulima/crud [1.0.2](https://github.com/visulima/visulima/compare/@visulima/crud@1.0.1...@visulima/crud@1.0.2) (2022-12-01)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * extended swagger generation for example and fixed typings ([#41](https://github.com/visulima/visulima/issues/41)) ([a16f49b](https://github.com/visulima/visulima/commit/a16f49b70f78763a63525e0d328bd2a597b183f7))
7
+
8
+
9
+
10
+ ### Dependencies
11
+
12
+ * **@visulima/pagination:** upgraded to 1.0.1
13
+ * **@visulima/prisma-dmmf-transformer:** upgraded to 1.0.1
14
+
15
+ ## @visulima/crud [1.0.1](https://github.com/visulima/visulima/compare/@visulima/crud@1.0.0...@visulima/crud@1.0.1) (2022-11-16)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * fixed wrong image and url for the npm version ([297c187](https://github.com/visulima/visulima/commit/297c187d07ca7fb82d25fd46defe4f320c514de9))
21
+
1
22
  ## @visulima/crud 1.0.0 (2022-11-15)
2
23
 
3
24
 
package/README.md CHANGED
@@ -37,38 +37,68 @@ With a more intuitive API for creating HTTP API endpoints.
37
37
  ## Installation
38
38
 
39
39
  ```sh
40
- npm install @visulima/crud
40
+ npm install @visulima/crud prisma @prisma/client
41
41
  ```
42
42
 
43
43
  ```sh
44
- yarn add @visulima/crud
44
+ yarn add @visulima/crud prisma @prisma/client
45
45
  ```
46
46
 
47
47
  ```sh
48
- pnpm add @visulima/crud
48
+ pnpm add @visulima/crud prisma @prisma/client
49
49
  ```
50
50
 
51
51
  ## Usage
52
52
 
53
- This package has an extended version of the `@visulima/connect` package.
54
- That means you can use all the features of the `@visulima/connect` package, in addition to the features of this package.
53
+ To use the `@visulima/crud` package, you need to have a [Prisma](https://www.prisma.io/) schema.
55
54
 
56
55
  ```ts
57
- // pages/api/hello.js
56
+ // pages/api/[...crud].ts
57
+
58
+ // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
58
59
  import type { NextApiRequest, NextApiResponse } from "next";
59
- import { createNodeRouter } from "@visulima/crud";
60
- import cors from "cors";
60
+ import { PrismaAdapter } from "@visulima/crud";
61
+ import { nodeHandler } from "@visulima/crud/next";
62
+ import type { User, Post, Prisma } from "@prisma/client";
63
+
64
+ import { prisma } from "../../lib/prisma-client";
65
+
66
+ const prismaAdapter = new PrismaAdapter<User | Post, Prisma.ModelName>({
67
+ prismaClient: prisma,
68
+ });
69
+
70
+ export default async (request, response) => {
71
+ const handler = await nodeHandler<User | Post, any, NextApiRequest, NextApiResponse, Prisma.ModelName>(prismaAdapter);
72
+
73
+ await handler(request, response);
74
+ };
75
+ ```
76
+
77
+ To use it with `api-platform connect` you need to install the `@visulima/api-platform` package.
78
+
79
+ ```ts
80
+ // pages/api/[...crud].ts
81
+
82
+ // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
83
+ import type { NextApiRequest, NextApiResponse } from "next";
84
+ import { createNodeRouter } from "@visulima/api-platform";
85
+ import { PrismaAdapter } from "@visulima/crud";
86
+ import { nodeHandler } from "@visulima/crud/next";
87
+ import type { User, Post, Prisma } from "@prisma/client";
88
+
89
+ import { prisma } from "../../lib/prisma-client";
90
+
91
+ const prismaAdapter = new PrismaAdapter<User | Post, Prisma.ModelName>({
92
+ prismaClient: prisma,
93
+ });
61
94
 
62
- // Default Req and Res are IncomingMessage and ServerResponse
63
- // You may want to pass in NextApiRequest and NextApiResponse
64
- const router = createNodeRouter<NextApiRequest, NextApiResponse>();
95
+ const router = createNodeRouter<NextApiRequest, NextApiResponse>().all(async (request, response) => {
96
+ const handler = await nodeHandler<User | Post, any, NextApiRequest, NextApiResponse, Prisma.ModelName>(prismaAdapter);
65
97
 
66
- router
67
- .get((req, res) => {
68
- res.send("Hello world");
69
- });
98
+ await handler(request, response);
99
+ });
70
100
 
71
- export default router.nodeHandler();
101
+ export default router.handler();
72
102
  ```
73
103
 
74
104
  ## Supported Node.js Versions
@@ -96,6 +126,6 @@ The visulima crud is open-sourced software licensed under the [MIT][license-url]
96
126
  [typescript-url]: "typescript"
97
127
  [license-image]: https://img.shields.io/npm/l/@visulima/crud?color=blueviolet&style=for-the-badge
98
128
  [license-url]: LICENSE.md "license"
99
- [npm-image]: https://img.shields.io/npm/v/@visulima/crud/alpha.svg?style=for-the-badge&logo=npm
100
- [npm-url]: https://www.npmjs.com/package/@visulima/crud/v/alpha "npm"
129
+ [npm-image]: https://img.shields.io/npm/v/@visulima/crud/latest.svg?style=for-the-badge&logo=npm
130
+ [npm-url]: https://www.npmjs.com/package/@visulima/crud/v/latest "npm"
101
131
 
@@ -0,0 +1,28 @@
1
+ // src/types.d.ts
2
+ var RouteType = /* @__PURE__ */ ((RouteType2) => {
3
+ RouteType2["CREATE"] = "CREATE";
4
+ RouteType2["READ_ALL"] = "READ_ALL";
5
+ RouteType2["READ_ONE"] = "READ_ONE";
6
+ RouteType2["UPDATE"] = "UPDATE";
7
+ RouteType2["DELETE"] = "DELETE";
8
+ return RouteType2;
9
+ })(RouteType || {});
10
+
11
+ // src/utils/get-accessible-routes.ts
12
+ var getAccessibleRoutes = (only, exclude, defaultExposeStrategy = "all") => {
13
+ let accessibleRoutes = defaultExposeStrategy === "none" ? [] : ["READ_ALL" /* READ_ALL */, "READ_ONE" /* READ_ONE */, "UPDATE" /* UPDATE */, "DELETE" /* DELETE */, "CREATE" /* CREATE */];
14
+ if (Array.isArray(only)) {
15
+ accessibleRoutes = only;
16
+ }
17
+ if (exclude == null ? void 0 : exclude.length) {
18
+ accessibleRoutes = accessibleRoutes.filter((element) => !exclude.includes(element));
19
+ }
20
+ return accessibleRoutes;
21
+ };
22
+ var get_accessible_routes_default = getAccessibleRoutes;
23
+
24
+ export {
25
+ RouteType,
26
+ get_accessible_routes_default
27
+ };
28
+ //# sourceMappingURL=chunk-SH6A4KBC.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.d.ts","../src/utils/get-accessible-routes.ts"],"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"],"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;","names":["RouteType"]}
1
+ {"version":3,"sources":["../src/types.d.ts","../src/utils/get-accessible-routes.ts"],"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"],"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;","names":["RouteType"]}
@@ -0,0 +1,28 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/types.d.ts
2
+ var RouteType = /* @__PURE__ */ ((RouteType2) => {
3
+ RouteType2["CREATE"] = "CREATE";
4
+ RouteType2["READ_ALL"] = "READ_ALL";
5
+ RouteType2["READ_ONE"] = "READ_ONE";
6
+ RouteType2["UPDATE"] = "UPDATE";
7
+ RouteType2["DELETE"] = "DELETE";
8
+ return RouteType2;
9
+ })(RouteType || {});
10
+
11
+ // src/utils/get-accessible-routes.ts
12
+ var getAccessibleRoutes = (only, exclude, defaultExposeStrategy = "all") => {
13
+ let accessibleRoutes = defaultExposeStrategy === "none" ? [] : ["READ_ALL" /* READ_ALL */, "READ_ONE" /* READ_ONE */, "UPDATE" /* UPDATE */, "DELETE" /* DELETE */, "CREATE" /* CREATE */];
14
+ if (Array.isArray(only)) {
15
+ accessibleRoutes = only;
16
+ }
17
+ if (exclude == null ? void 0 : exclude.length) {
18
+ accessibleRoutes = accessibleRoutes.filter((element) => !exclude.includes(element));
19
+ }
20
+ return accessibleRoutes;
21
+ };
22
+ var get_accessible_routes_default = getAccessibleRoutes;
23
+
24
+
25
+
26
+
27
+ exports.RouteType = RouteType; exports.get_accessible_routes_default = get_accessible_routes_default;
28
+ //# sourceMappingURL=chunk-ZY3WOLEP.js.map
@@ -0,0 +1 @@
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"]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { PrismaClient } from '@prisma/client';
2
2
  import { S as SearchCondition, C as Condition, A as Adapter, P as PaginationData, a as ParsedQueryParameters, R as RouteType, M as ModelsOptions } from './types.d-6817d247.js';
3
3
  export { A as Adapter, C as Condition, c as CrudHandlerOptions, H as HandlerParameters, d as ModelOption, M as ModelsOptions, O as OrderByField, e as OrderByOperator, b as PaginationConfig, P as PaginationData, a as ParsedQueryParameters, f as RecursiveField, R as RouteType, S as SearchCondition, U as UniqueResourceHandlerParameters, h as WhereCondition, W as WhereField, g as WhereOperator } from './types.d-6817d247.js';
4
+ import { OpenAPIV3 } from 'openapi-types';
4
5
 
5
6
  type PrismaRecursiveField = "select" | "include";
6
7
 
@@ -95,15 +96,6 @@ type SwaggerOperation = {
95
96
  response: SwaggerType;
96
97
  };
97
98
 
98
- type SwaggerTag = {
99
- name?: string;
100
- description?: string;
101
- externalDocs?: {
102
- description: string;
103
- url: string;
104
- };
105
- };
106
-
107
99
  type SwaggerParameter = {
108
100
  name: string;
109
101
  description?: string;
@@ -113,7 +105,7 @@ type SwaggerParameter = {
113
105
  };
114
106
 
115
107
  type ModelsConfig = {
116
- tag: SwaggerTag;
108
+ tag: OpenAPIV3.TagObject;
117
109
  type?: SwaggerType;
118
110
  routeTypes?: {
119
111
  [RouteType.READ_ALL]?: SwaggerOperation;
@@ -130,12 +122,14 @@ type SwaggerModelsConfig<M extends string> = {
130
122
  };
131
123
 
132
124
  declare const modelsToOpenApi: <M extends string = string>({ prismaClient, models: ctorModels, swagger, crud, defaultExposeStrategy, }: ModelsToOpenApiParameters<M>) => Promise<{
133
- schemas: any;
134
- examples: {};
135
- tags: SwaggerTag[];
136
- paths: {
137
- [key: string]: any;
125
+ schemas: {
126
+ [key: string]: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject;
127
+ };
128
+ examples: {
129
+ [key: string]: OpenAPIV3.ReferenceObject | OpenAPIV3.ExampleObject;
138
130
  };
131
+ tags: OpenAPIV3.TagObject[];
132
+ paths: OpenAPIV3.PathsObject;
139
133
  }>;
140
134
  interface ModelsToOpenApiParameters<M extends string = string> {
141
135
  prismaClient: PrismaClient;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
2
2
 
3
3
 
4
- var _chunkFJWRITBOjs = require('./chunk-FJWRITBO.js');
4
+ var _chunkZY3WOLEPjs = require('./chunk-ZY3WOLEP.js');
5
5
 
6
6
  // src/adapter/prisma/index.ts
7
7
  var _httperrors = require('http-errors'); var _httperrors2 = _interopRequireDefault(_httperrors);
@@ -58,16 +58,12 @@ var parse_order_by_default = parsePrismaOrderBy;
58
58
  var parsePrismaRecursiveField = (select, fieldName) => {
59
59
  const parsed = {};
60
60
  Object.keys(select).forEach((field) => {
61
- if (select[field] !== true) {
62
- parsed[field] = {
63
- [fieldName]: parsePrismaRecursiveField(
64
- select[field],
65
- fieldName
66
- )
67
- };
68
- } else {
69
- parsed[field] = true;
70
- }
61
+ parsed[field] = select[field] === true ? true : {
62
+ [fieldName]: parsePrismaRecursiveField(
63
+ select[field],
64
+ fieldName
65
+ )
66
+ };
71
67
  });
72
68
  return parsed;
73
69
  };
@@ -226,7 +222,7 @@ var PrismaAdapter = class {
226
222
  async init() {
227
223
  const models = this.ctorModels;
228
224
  const prismaDmmfModels = await this.getPrismaClientModels();
229
- if (typeof models !== "undefined") {
225
+ if (models !== void 0) {
230
226
  models.forEach((model) => {
231
227
  if (!Object.keys(prismaDmmfModels).includes(model)) {
232
228
  throw new Error(`Model name ${model} is invalid.`);
@@ -268,10 +264,10 @@ var PrismaAdapter = class {
268
264
  if (query.orderBy) {
269
265
  parsed.orderBy = parse_order_by_default(query.orderBy);
270
266
  }
271
- if (typeof query.limit !== "undefined") {
267
+ if (query.limit !== void 0) {
272
268
  parsed.take = query.limit;
273
269
  }
274
- if (typeof query.skip !== "undefined") {
270
+ if (query.skip !== void 0) {
275
271
  parsed.skip = query.skip;
276
272
  }
277
273
  if ((_b = query.originalQuery) == null ? void 0 : _b.cursor) {
@@ -624,29 +620,21 @@ var PrismaJsonSchemaParser = class {
624
620
  const values = {};
625
621
  Object.entries((model == null ? void 0 : model.properties) || {}).forEach(([key, v]) => {
626
622
  const type = v.type;
627
- if (type === "array") {
628
- values[key] = [arrayItemsToSchema(v.items)];
629
- } else {
630
- values[key] = type;
631
- }
623
+ values[key] = type === "array" ? [arrayItemsToSchema(v.items)] : type;
632
624
  });
633
625
  return values;
634
626
  };
635
627
  const objectPropertiesToSchema = (objectProperties) => {
636
628
  const values = {};
637
629
  Object.entries(objectProperties).forEach(([key, value]) => {
638
- if (typeof value.$ref !== "undefined") {
639
- values[key] = referenceToSchema(value.$ref);
640
- } else {
641
- values[key] = value.type;
642
- }
630
+ values[key] = value.$ref === void 0 ? value.type : referenceToSchema(value.$ref);
643
631
  });
644
632
  return values;
645
633
  };
646
634
  const arrayItemsToSchema = (items) => {
647
635
  const values = {};
648
636
  Object.entries(items).forEach(([key, value]) => {
649
- if (typeof value.items.$ref !== "undefined") {
637
+ if (value.items.$ref !== void 0) {
650
638
  values[key] = [referenceToSchema(value.items.$ref)];
651
639
  } else if (value.type === "array") {
652
640
  values[key] = [arrayItemsToSchema(value.items)];
@@ -681,6 +669,9 @@ var PrismaJsonSchemaParser = class {
681
669
  [`${modelName}`]: {
682
670
  value
683
671
  },
672
+ [`${modelName}s`]: {
673
+ value: [value]
674
+ },
684
675
  [`${modelName}Page`]: {
685
676
  value: {
686
677
  data: [value],
@@ -726,12 +717,12 @@ var getModelsAccessibleRoutes = (modelNames, models, defaultExposeStrategy = "al
726
717
  if (models == null ? void 0 : models[modelName]) {
727
718
  return {
728
719
  ...accumulator,
729
- [modelName]: _chunkFJWRITBOjs.get_accessible_routes_default.call(void 0, models[modelName].only, models[modelName].exclude, defaultExposeStrategy)
720
+ [modelName]: _chunkZY3WOLEPjs.get_accessible_routes_default.call(void 0, models[modelName].only, models[modelName].exclude, defaultExposeStrategy)
730
721
  };
731
722
  }
732
723
  return {
733
724
  ...accumulator,
734
- [modelName]: _chunkFJWRITBOjs.get_accessible_routes_default.call(void 0, void 0, void 0, defaultExposeStrategy)
725
+ [modelName]: _chunkZY3WOLEPjs.get_accessible_routes_default.call(void 0, void 0, void 0, defaultExposeStrategy)
735
726
  };
736
727
  }, {});
737
728
  var get_models_accessible_routes_default = getModelsAccessibleRoutes;
@@ -841,7 +832,8 @@ var generateSwaggerResponse = (routeType, modelName) => {
841
832
  description: `${modelName} created`,
842
833
  content: {
843
834
  "application/json": {
844
- schema: generateContentForSchema(modelName)
835
+ schema: generateContentForSchema(modelName),
836
+ example: format_example_ref_default(modelName)
845
837
  }
846
838
  }
847
839
  }
@@ -854,7 +846,8 @@ var generateSwaggerResponse = (routeType, modelName) => {
854
846
  description: `${modelName} item deleted`,
855
847
  content: {
856
848
  "application/json": {
857
- schema: generateContentForSchema(modelName)
849
+ schema: generateContentForSchema(modelName),
850
+ example: format_example_ref_default(modelName)
858
851
  }
859
852
  }
860
853
  }
@@ -872,7 +865,7 @@ var generateSwaggerResponse = (routeType, modelName) => {
872
865
  },
873
866
  examples: {
874
867
  Default: {
875
- $ref: format_example_ref_default(`${modelName}`)
868
+ $ref: format_example_ref_default(`${modelName}s`)
876
869
  },
877
870
  Pagination: {
878
871
  $ref: format_example_ref_default(`${modelName}Page`)
@@ -890,7 +883,8 @@ var generateSwaggerResponse = (routeType, modelName) => {
890
883
  description: `${modelName} item retrieved`,
891
884
  content: {
892
885
  "application/json": {
893
- schema: generateContentForSchema(modelName)
886
+ schema: generateContentForSchema(modelName),
887
+ example: format_example_ref_default(modelName)
894
888
  }
895
889
  }
896
890
  }
@@ -903,7 +897,8 @@ var generateSwaggerResponse = (routeType, modelName) => {
903
897
  description: `${modelName} item updated`,
904
898
  content: {
905
899
  "application/json": {
906
- schema: generateContentForSchema(modelName)
900
+ schema: generateContentForSchema(modelName),
901
+ example: format_example_ref_default(modelName)
907
902
  }
908
903
  }
909
904
  }
@@ -956,7 +951,7 @@ var generateSwaggerPathObject = ({
956
951
  const returnType = _nullishCoalesce(_nullishCoalesce(((_d = (_c = (_b = (_a = modelsConfig == null ? void 0 : modelsConfig[modelName]) == null ? void 0 : _a.routeTypes) == null ? void 0 : _b[routeType]) == null ? void 0 : _c.response) == null ? void 0 : _d.name), () => ( ((_f = (_e = modelsConfig == null ? void 0 : modelsConfig[modelName]) == null ? void 0 : _e.type) == null ? void 0 : _f.name))), () => ( modelName));
957
952
  const method = getRouteTypeMethod(routeType);
958
953
  const response = generateSwaggerResponse(routeType, returnType);
959
- if (typeof response === "undefined") {
954
+ if (response === void 0) {
960
955
  throw new TypeError(`Route type ${routeType}; response config was not found.`);
961
956
  }
962
957
  methods[method] = {
@@ -1040,6 +1035,30 @@ var getSwaggerTags = (modelNames, modelsConfig) => modelNames.map((modelName) =>
1040
1035
  var get_swagger_tags_default = getSwaggerTags;
1041
1036
 
1042
1037
  // src/swagger/adapter/prisma/index.ts
1038
+ var overwritePathsExampleWithModel = (swaggerPaths, examples) => {
1039
+ Object.values(swaggerPaths).forEach((pathSpec) => {
1040
+ Object.values(pathSpec).forEach((methodSpec) => {
1041
+ if (typeof methodSpec.responses === "object") {
1042
+ Object.values(methodSpec.responses).forEach((responseSpec) => {
1043
+ if (typeof responseSpec.content === "object") {
1044
+ Object.values(
1045
+ responseSpec.content
1046
+ ).forEach((contentSpec) => {
1047
+ var _a;
1048
+ if (typeof contentSpec.example === "string") {
1049
+ const example = contentSpec.example.replace("#/components/examples/", "");
1050
+ if (typeof examples[example] !== void 0 && typeof ((_a = examples[example]) == null ? void 0 : _a.value) !== void 0) {
1051
+ contentSpec.example = examples[example].value;
1052
+ }
1053
+ }
1054
+ });
1055
+ }
1056
+ });
1057
+ }
1058
+ });
1059
+ });
1060
+ return swaggerPaths;
1061
+ };
1043
1062
  var modelsToOpenApi = async ({
1044
1063
  prismaClient,
1045
1064
  models: ctorModels,
@@ -1068,7 +1087,7 @@ var modelsToOpenApi = async ({
1068
1087
  ...parser.getPaginationDataSchema(),
1069
1088
  ...parser.getPaginatedModelsSchemas(dModels)
1070
1089
  });
1071
- if (typeof ctorModels !== "undefined") {
1090
+ if (ctorModels !== void 0) {
1072
1091
  ctorModels.forEach((model) => {
1073
1092
  if (!Object.keys(prismaDmmfModels).includes(model)) {
1074
1093
  throw new Error(`Model name ${model} is invalid.`);
@@ -1085,11 +1104,12 @@ var modelsToOpenApi = async ({
1085
1104
  routesMap: models_to_route_names_default(prismaDmmfModels, models)
1086
1105
  });
1087
1106
  const schemas = JSON.parse(schema.replace(/#\/definitions/g, "#/components/schemas"));
1107
+ const examples = parser.getExampleModelsSchemas(dModels, schemas);
1088
1108
  return {
1089
1109
  schemas,
1090
- examples: parser.getExampleModelsSchemas(dModels, schemas),
1110
+ examples,
1091
1111
  tags: swaggerTags,
1092
- paths: swaggerPaths
1112
+ paths: overwritePathsExampleWithModel(swaggerPaths, examples)
1093
1113
  };
1094
1114
  };
1095
1115
  var prisma_default = modelsToOpenApi;
@@ -1097,5 +1117,5 @@ var prisma_default = modelsToOpenApi;
1097
1117
 
1098
1118
 
1099
1119
 
1100
- exports.PrismaAdapter = PrismaAdapter; exports.RouteType = _chunkFJWRITBOjs.RouteType; exports.modelsToOpenApi = prisma_default;
1120
+ exports.PrismaAdapter = PrismaAdapter; exports.RouteType = _chunkZY3WOLEPjs.RouteType; exports.modelsToOpenApi = prisma_default;
1101
1121
  //# sourceMappingURL=index.js.map