@visulima/crud 1.0.1 → 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.
- package/CHANGELOG.md +14 -0
- package/README.md +46 -16
- package/dist/chunk-SH6A4KBC.mjs +28 -0
- package/dist/{chunk-UBXIGP5H.mjs.map → chunk-SH6A4KBC.mjs.map} +1 -1
- package/dist/chunk-ZY3WOLEP.js +28 -0
- package/dist/chunk-ZY3WOLEP.js.map +1 -0
- package/dist/index.d.ts +9 -15
- package/dist/index.js +57 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -34
- package/dist/index.mjs.map +1 -1
- package/dist/next/index.js +10 -281
- package/dist/next/index.js.map +1 -1
- package/dist/next/index.mjs +9 -280
- package/dist/next/index.mjs.map +1 -1
- package/next/package.json +18 -0
- package/package.json +16 -14
- package/dist/chunk-FJWRITBO.js +0 -52
- package/dist/chunk-FJWRITBO.js.map +0 -1
- package/dist/chunk-UBXIGP5H.mjs +0 -52
- package/src/adapter/prisma/index.ts +0 -241
- package/src/adapter/prisma/types.d.ts +0 -46
- package/src/adapter/prisma/utils/models-to-route-names.ts +0 -12
- package/src/adapter/prisma/utils/parse-cursor.ts +0 -26
- package/src/adapter/prisma/utils/parse-order-by.ts +0 -21
- package/src/adapter/prisma/utils/parse-recursive.ts +0 -26
- package/src/adapter/prisma/utils/parse-where.ts +0 -197
- package/src/base-crud-handler.ts +0 -181
- package/src/handler/create.ts +0 -21
- package/src/handler/delete.ts +0 -27
- package/src/handler/list.ts +0 -62
- package/src/handler/read.ts +0 -27
- package/src/handler/update.ts +0 -29
- package/src/index.ts +0 -27
- package/src/next/api/edge/index.ts +0 -23
- package/src/next/api/node/index.ts +0 -27
- package/src/next/index.ts +0 -2
- package/src/query-parser.ts +0 -94
- package/src/swagger/adapter/prisma/index.ts +0 -95
- package/src/swagger/json-schema-parser.ts +0 -456
- package/src/swagger/parameters.ts +0 -83
- package/src/swagger/types.d.ts +0 -53
- package/src/swagger/utils/format-example-ref.ts +0 -4
- package/src/swagger/utils/format-schema-ref.ts +0 -4
- package/src/swagger/utils/get-models-accessible-routes.ts +0 -23
- package/src/swagger/utils/get-swagger-paths.ts +0 -244
- package/src/swagger/utils/get-swagger-tags.ts +0 -13
- package/src/types.d.ts +0 -124
- package/src/utils/format-resource-id.ts +0 -3
- package/src/utils/get-accessible-routes.ts +0 -18
- package/src/utils/get-resource-name-from-url.ts +0 -23
- package/src/utils/get-route-type.ts +0 -99
- package/src/utils/is-primitive.ts +0 -5
- package/src/utils/validate-adapter-methods.ts +0 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
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
|
+
|
|
1
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)
|
|
2
16
|
|
|
3
17
|
|
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
|
-
|
|
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/
|
|
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 {
|
|
60
|
-
import
|
|
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
|
-
|
|
63
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
res.send("Hello world");
|
|
69
|
-
});
|
|
98
|
+
await handler(request, response);
|
|
99
|
+
});
|
|
70
100
|
|
|
71
|
-
export default router.
|
|
101
|
+
export default router.handler();
|
|
72
102
|
```
|
|
73
103
|
|
|
74
104
|
## Supported Node.js Versions
|
|
@@ -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":"
|
|
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:
|
|
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:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
[key: string]:
|
|
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
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
[
|
|
64
|
-
|
|
65
|
-
|
|
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 (
|
|
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 (
|
|
267
|
+
if (query.limit !== void 0) {
|
|
272
268
|
parsed.take = query.limit;
|
|
273
269
|
}
|
|
274
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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]:
|
|
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]:
|
|
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 (
|
|
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 (
|
|
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
|
|
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 =
|
|
1120
|
+
exports.PrismaAdapter = PrismaAdapter; exports.RouteType = _chunkZY3WOLEPjs.RouteType; exports.modelsToOpenApi = prisma_default;
|
|
1101
1121
|
//# sourceMappingURL=index.js.map
|