@visulima/crud 1.0.14 → 2.0.0
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 +18 -0
- package/dist/{chunk-DOLZ4YNP.js → chunk-GMVQBGMY.js} +1 -1
- package/dist/{chunk-54HHLITU.mjs.map → chunk-GMVQBGMY.js.map} +1 -1
- package/dist/{chunk-54HHLITU.mjs → chunk-I5N5SJZ7.mjs} +1 -1
- package/dist/{chunk-DOLZ4YNP.js.map → chunk-I5N5SJZ7.mjs.map} +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/index.mjs +2 -2
- package/dist/next/index.d.mts +1 -1
- package/dist/next/index.d.ts +1 -1
- package/dist/next/index.js +4 -4
- package/dist/next/index.js.map +1 -1
- package/dist/next/index.mjs +4 -4
- package/dist/next/index.mjs.map +1 -1
- package/dist/{types.d-21565c86.d.ts → types.d-6e8ef982.d.ts} +1 -1
- package/package.json +19 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## @visulima/crud [2.0.0](https://github.com/visulima/visulima/compare/@visulima/crud@1.0.14...@visulima/crud@2.0.0) (2023-08-28)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### ⚠ BREAKING CHANGES
|
|
5
|
+
|
|
6
|
+
* update minimum Node.js version requirement to 18
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* refactor query parsing and update dependencies ([#203](https://github.com/visulima/visulima/issues/203)) ([cf77427](https://github.com/visulima/visulima/commit/cf7742795f970ebeeb5da22a82fd17750028ee87))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Dependencies
|
|
15
|
+
|
|
16
|
+
* **@visulima/pagination:** upgraded to 3.0.0
|
|
17
|
+
* **@visulima/prisma-dmmf-transformer:** upgraded to 2.0.0
|
|
18
|
+
|
|
1
19
|
## @visulima/crud [1.0.14](https://github.com/visulima/visulima/compare/@visulima/crud@1.0.13...@visulima/crud@1.0.14) (2023-07-28)
|
|
2
20
|
|
|
3
21
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.d.ts","../src/utils/get-accessible-routes.ts"],"names":["RouteType","getAccessibleRoutes","only","exclude","defaultExposeStrategy","accessibleRoutes","element","get_accessible_routes_default"],"mappings":"AAOO,IAAKA,OACRA,EAAA,OAAS,SACTA,EAAA,OAAS,SACTA,EAAA,SAAW,WACXA,EAAA,SAAW,WACXA,EAAA,OAAS,SALDA,OAAA,ICLZ,IAAMC,EAAsB,CAACC,EAAoBC,EAAuBC,EAAwC,QAAuB,CACnI,IAAIC,EACAD,IAA0B,OAAS,CAAC,EAAI,iDAA6F,EAEzI,OAAI,MAAM,QAAQF,CAAI,IAClBG,EAAmBH,GAGnBC,GAAS,SACTE,EAAmBA,EAAiB,OAAQC,GAAY,CAACH,EAAQ,SAASG,CAAO,CAAC,GAG/ED,CACX,EAEOE,EAAQN","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\n// eslint-disable-next-line no-shadow\nexport enum RouteType {\n CREATE = \"CREATE\",\n DELETE = \"DELETE\",\n READ_ALL = \"READ_ALL\",\n READ_ONE = \"READ_ONE\",\n UPDATE = \"UPDATE\",\n}\n\nexport interface ModelOption {\n exclude?: RouteType[];\n formatResourceId?: (resourceId: string) => number | string;\n name?: string;\n only?: RouteType[];\n}\n\nexport type ModelsOptions<M extends string = string> = {\n [key in M]?: ModelOption;\n};\n\nexport interface HandlerOptions<M extends string = string> {\n exposeStrategy?: \"all\" | \"none\";\n formatResourceId?: (resourceId: string) => number | string;\n handlers?: {\n create?: CreateHandler;\n delete?: DeleteHandler;\n get?: GetHandler;\n list?: ListHandler;\n update?: UpdateHandler;\n };\n models?: ModelsOptions<M>;\n pagination?: PaginationConfig;\n}\n\nexport interface 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 resourceId: number | string;\n resourceName: string;\n}\n\nexport interface Adapter<T, Q, M extends string = string> {\n connect?: () => Promise<void>;\n create: (resourceName: M, data: any, query: Q) => Promise<T>;\n delete: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;\n disconnect?: () => Promise<void>;\n getAll: (resourceName: M, query: Q) => Promise<T[]>;\n getModels: () => M[];\n getOne: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;\n getPaginationData: (resourceName: M, query: Q) => Promise<PaginationData>;\n handleError?: (error: Error) => void;\n init?: () => Promise<void>;\n mapModelsToRouteNames?: () => Promise<{ [key in M]?: string }>;\n models?: M[];\n parseQuery: (resourceName: M, query: ParsedQueryParameters) => Q;\n update: (resourceName: M, resourceId: number | string, data: any, query: Q) => Promise<T>;\n}\n\nexport interface PaginationData {\n page: number;\n pageCount: number;\n total: number;\n}\n\nexport type RecursiveField = Record<string, Record<string, boolean> | boolean>;\n\nexport type WhereOperator = \"$cont\" | \"$ends\" | \"$eq\" | \"$gt\" | \"$gte\" | \"$in\" | \"$isnull\" | \"$lt\" | \"$lte\" | \"$neq\" | \"$notin\" | \"$starts\";\n\nexport type SearchCondition = Date | boolean | number | string | null;\n\nexport type WhereCondition = {\n [key in WhereOperator]?: SearchCondition;\n};\n\n// TODO: find the correct way to type this\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type Condition = Record<string, Condition | SearchCondition | WhereCondition>;\n\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type WhereField = Condition & {\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $and?: Condition | Condition[];\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $not?: Condition | Condition[];\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $or?: Condition | Condition[];\n};\n\nexport type OrderByOperator = \"$asc\" | \"$desc\";\n\nexport type OrderByField = Record<string,
|
|
1
|
+
{"version":3,"sources":["../src/types.d.ts","../src/utils/get-accessible-routes.ts"],"names":["RouteType","getAccessibleRoutes","only","exclude","defaultExposeStrategy","accessibleRoutes","element","get_accessible_routes_default"],"mappings":"AAOO,IAAKA,OACRA,EAAA,OAAS,SACTA,EAAA,OAAS,SACTA,EAAA,SAAW,WACXA,EAAA,SAAW,WACXA,EAAA,OAAS,SALDA,OAAA,ICLZ,IAAMC,EAAsB,CAACC,EAAoBC,EAAuBC,EAAwC,QAAuB,CACnI,IAAIC,EACAD,IAA0B,OAAS,CAAC,EAAI,iDAA6F,EAEzI,OAAI,MAAM,QAAQF,CAAI,IAClBG,EAAmBH,GAGnBC,GAAS,SACTE,EAAmBA,EAAiB,OAAQC,GAAY,CAACH,EAAQ,SAASG,CAAO,CAAC,GAG/ED,CACX,EAEOE,EAAQN","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\n// eslint-disable-next-line no-shadow\nexport enum RouteType {\n CREATE = \"CREATE\",\n DELETE = \"DELETE\",\n READ_ALL = \"READ_ALL\",\n READ_ONE = \"READ_ONE\",\n UPDATE = \"UPDATE\",\n}\n\nexport interface ModelOption {\n exclude?: RouteType[];\n formatResourceId?: (resourceId: string) => number | string;\n name?: string;\n only?: RouteType[];\n}\n\nexport type ModelsOptions<M extends string = string> = {\n [key in M]?: ModelOption;\n};\n\nexport interface HandlerOptions<M extends string = string> {\n exposeStrategy?: \"all\" | \"none\";\n formatResourceId?: (resourceId: string) => number | string;\n handlers?: {\n create?: CreateHandler;\n delete?: DeleteHandler;\n get?: GetHandler;\n list?: ListHandler;\n update?: UpdateHandler;\n };\n models?: ModelsOptions<M>;\n pagination?: PaginationConfig;\n}\n\nexport interface 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 resourceId: number | string;\n resourceName: string;\n}\n\nexport interface Adapter<T, Q, M extends string = string> {\n connect?: () => Promise<void>;\n create: (resourceName: M, data: any, query: Q) => Promise<T>;\n delete: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;\n disconnect?: () => Promise<void>;\n getAll: (resourceName: M, query: Q) => Promise<T[]>;\n getModels: () => M[];\n getOne: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;\n getPaginationData: (resourceName: M, query: Q) => Promise<PaginationData>;\n handleError?: (error: Error) => void;\n init?: () => Promise<void>;\n mapModelsToRouteNames?: () => Promise<{ [key in M]?: string }>;\n models?: M[];\n parseQuery: (resourceName: M, query: ParsedQueryParameters) => Q;\n update: (resourceName: M, resourceId: number | string, data: any, query: Q) => Promise<T>;\n}\n\nexport interface PaginationData {\n page: number;\n pageCount: number;\n total: number;\n}\n\nexport type RecursiveField = Record<string, Record<string, boolean> | boolean>;\n\nexport type WhereOperator = \"$cont\" | \"$ends\" | \"$eq\" | \"$gt\" | \"$gte\" | \"$in\" | \"$isnull\" | \"$lt\" | \"$lte\" | \"$neq\" | \"$notin\" | \"$starts\";\n\nexport type SearchCondition = Date | boolean | number | string | null;\n\nexport type WhereCondition = {\n [key in WhereOperator]?: SearchCondition;\n};\n\n// TODO: find the correct way to type this\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type Condition = Record<string, Condition | SearchCondition | WhereCondition>;\n\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type WhereField = Condition & {\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $and?: Condition | Condition[];\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $not?: Condition | Condition[];\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $or?: Condition | Condition[];\n};\n\nexport type OrderByOperator = \"$asc\" | \"$desc\";\n\nexport type OrderByField = Record<string, OrderByOperator>;\n\nexport interface ParsedQueryParameters {\n distinct?: string;\n include?: RecursiveField;\n limit?: number;\n orderBy?: OrderByField;\n originalQuery?: Record<string, any>;\n page?: number;\n select?: RecursiveField;\n skip?: number;\n where?: WhereField;\n}\n\nexport type ExecuteHandler<Request, Response> = (request: Request, response: Response) => Promise<void>;\n\nexport interface FakePrismaClient {\n $connect: () => void;\n $disconnect: () => Promise<void>;\n [key: string]: any;\n _dmmf?: any;\n\n _getDmmf?: () => any;\n}\n","import { RouteType } from \"../types.d\";\n\nconst getAccessibleRoutes = (only?: RouteType[], exclude?: RouteType[], defaultExposeStrategy: \"all\" | \"none\" = \"all\"): RouteType[] => {\n let accessibleRoutes: RouteType[] =\n 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 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.d.ts","../src/utils/get-accessible-routes.ts"],"names":["RouteType","getAccessibleRoutes","only","exclude","defaultExposeStrategy","accessibleRoutes","element","get_accessible_routes_default"],"mappings":"AAOO,IAAKA,OACRA,EAAA,OAAS,SACTA,EAAA,OAAS,SACTA,EAAA,SAAW,WACXA,EAAA,SAAW,WACXA,EAAA,OAAS,SALDA,OAAA,ICLZ,IAAMC,EAAsB,CAACC,EAAoBC,EAAuBC,EAAwC,QAAuB,CACnI,IAAIC,EACAD,IAA0B,OAAS,CAAC,EAAI,iDAA6F,EAEzI,OAAI,MAAM,QAAQF,CAAI,IAClBG,EAAmBH,GAGnBC,GAAS,SACTE,EAAmBA,EAAiB,OAAQC,GAAY,CAACH,EAAQ,SAASG,CAAO,CAAC,GAG/ED,CACX,EAEOE,EAAQN","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\n// eslint-disable-next-line no-shadow\nexport enum RouteType {\n CREATE = \"CREATE\",\n DELETE = \"DELETE\",\n READ_ALL = \"READ_ALL\",\n READ_ONE = \"READ_ONE\",\n UPDATE = \"UPDATE\",\n}\n\nexport interface ModelOption {\n exclude?: RouteType[];\n formatResourceId?: (resourceId: string) => number | string;\n name?: string;\n only?: RouteType[];\n}\n\nexport type ModelsOptions<M extends string = string> = {\n [key in M]?: ModelOption;\n};\n\nexport interface HandlerOptions<M extends string = string> {\n exposeStrategy?: \"all\" | \"none\";\n formatResourceId?: (resourceId: string) => number | string;\n handlers?: {\n create?: CreateHandler;\n delete?: DeleteHandler;\n get?: GetHandler;\n list?: ListHandler;\n update?: UpdateHandler;\n };\n models?: ModelsOptions<M>;\n pagination?: PaginationConfig;\n}\n\nexport interface 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 resourceId: number | string;\n resourceName: string;\n}\n\nexport interface Adapter<T, Q, M extends string = string> {\n connect?: () => Promise<void>;\n create: (resourceName: M, data: any, query: Q) => Promise<T>;\n delete: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;\n disconnect?: () => Promise<void>;\n getAll: (resourceName: M, query: Q) => Promise<T[]>;\n getModels: () => M[];\n getOne: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;\n getPaginationData: (resourceName: M, query: Q) => Promise<PaginationData>;\n handleError?: (error: Error) => void;\n init?: () => Promise<void>;\n mapModelsToRouteNames?: () => Promise<{ [key in M]?: string }>;\n models?: M[];\n parseQuery: (resourceName: M, query: ParsedQueryParameters) => Q;\n update: (resourceName: M, resourceId: number | string, data: any, query: Q) => Promise<T>;\n}\n\nexport interface PaginationData {\n page: number;\n pageCount: number;\n total: number;\n}\n\nexport type RecursiveField = Record<string, Record<string, boolean> | boolean>;\n\nexport type WhereOperator = \"$cont\" | \"$ends\" | \"$eq\" | \"$gt\" | \"$gte\" | \"$in\" | \"$isnull\" | \"$lt\" | \"$lte\" | \"$neq\" | \"$notin\" | \"$starts\";\n\nexport type SearchCondition = Date | boolean | number | string | null;\n\nexport type WhereCondition = {\n [key in WhereOperator]?: SearchCondition;\n};\n\n// TODO: find the correct way to type this\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type Condition = Record<string, Condition | SearchCondition | WhereCondition>;\n\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type WhereField = Condition & {\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $and?: Condition | Condition[];\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $not?: Condition | Condition[];\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $or?: Condition | Condition[];\n};\n\nexport type OrderByOperator = \"$asc\" | \"$desc\";\n\nexport type OrderByField = Record<string,
|
|
1
|
+
{"version":3,"sources":["../src/types.d.ts","../src/utils/get-accessible-routes.ts"],"names":["RouteType","getAccessibleRoutes","only","exclude","defaultExposeStrategy","accessibleRoutes","element","get_accessible_routes_default"],"mappings":"AAOO,IAAKA,OACRA,EAAA,OAAS,SACTA,EAAA,OAAS,SACTA,EAAA,SAAW,WACXA,EAAA,SAAW,WACXA,EAAA,OAAS,SALDA,OAAA,ICLZ,IAAMC,EAAsB,CAACC,EAAoBC,EAAuBC,EAAwC,QAAuB,CACnI,IAAIC,EACAD,IAA0B,OAAS,CAAC,EAAI,iDAA6F,EAEzI,OAAI,MAAM,QAAQF,CAAI,IAClBG,EAAmBH,GAGnBC,GAAS,SACTE,EAAmBA,EAAiB,OAAQC,GAAY,CAACH,EAAQ,SAASG,CAAO,CAAC,GAG/ED,CACX,EAEOE,EAAQN","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\n// eslint-disable-next-line no-shadow\nexport enum RouteType {\n CREATE = \"CREATE\",\n DELETE = \"DELETE\",\n READ_ALL = \"READ_ALL\",\n READ_ONE = \"READ_ONE\",\n UPDATE = \"UPDATE\",\n}\n\nexport interface ModelOption {\n exclude?: RouteType[];\n formatResourceId?: (resourceId: string) => number | string;\n name?: string;\n only?: RouteType[];\n}\n\nexport type ModelsOptions<M extends string = string> = {\n [key in M]?: ModelOption;\n};\n\nexport interface HandlerOptions<M extends string = string> {\n exposeStrategy?: \"all\" | \"none\";\n formatResourceId?: (resourceId: string) => number | string;\n handlers?: {\n create?: CreateHandler;\n delete?: DeleteHandler;\n get?: GetHandler;\n list?: ListHandler;\n update?: UpdateHandler;\n };\n models?: ModelsOptions<M>;\n pagination?: PaginationConfig;\n}\n\nexport interface 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 resourceId: number | string;\n resourceName: string;\n}\n\nexport interface Adapter<T, Q, M extends string = string> {\n connect?: () => Promise<void>;\n create: (resourceName: M, data: any, query: Q) => Promise<T>;\n delete: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;\n disconnect?: () => Promise<void>;\n getAll: (resourceName: M, query: Q) => Promise<T[]>;\n getModels: () => M[];\n getOne: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;\n getPaginationData: (resourceName: M, query: Q) => Promise<PaginationData>;\n handleError?: (error: Error) => void;\n init?: () => Promise<void>;\n mapModelsToRouteNames?: () => Promise<{ [key in M]?: string }>;\n models?: M[];\n parseQuery: (resourceName: M, query: ParsedQueryParameters) => Q;\n update: (resourceName: M, resourceId: number | string, data: any, query: Q) => Promise<T>;\n}\n\nexport interface PaginationData {\n page: number;\n pageCount: number;\n total: number;\n}\n\nexport type RecursiveField = Record<string, Record<string, boolean> | boolean>;\n\nexport type WhereOperator = \"$cont\" | \"$ends\" | \"$eq\" | \"$gt\" | \"$gte\" | \"$in\" | \"$isnull\" | \"$lt\" | \"$lte\" | \"$neq\" | \"$notin\" | \"$starts\";\n\nexport type SearchCondition = Date | boolean | number | string | null;\n\nexport type WhereCondition = {\n [key in WhereOperator]?: SearchCondition;\n};\n\n// TODO: find the correct way to type this\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type Condition = Record<string, Condition | SearchCondition | WhereCondition>;\n\n// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\nexport type WhereField = Condition & {\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $and?: Condition | Condition[];\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $not?: Condition | Condition[];\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n $or?: Condition | Condition[];\n};\n\nexport type OrderByOperator = \"$asc\" | \"$desc\";\n\nexport type OrderByField = Record<string, OrderByOperator>;\n\nexport interface ParsedQueryParameters {\n distinct?: string;\n include?: RecursiveField;\n limit?: number;\n orderBy?: OrderByField;\n originalQuery?: Record<string, any>;\n page?: number;\n select?: RecursiveField;\n skip?: number;\n where?: WhereField;\n}\n\nexport type ExecuteHandler<Request, Response> = (request: Request, response: Response) => Promise<void>;\n\nexport interface FakePrismaClient {\n $connect: () => void;\n $disconnect: () => Promise<void>;\n [key: string]: any;\n _dmmf?: any;\n\n _getDmmf?: () => any;\n}\n","import { RouteType } from \"../types.d\";\n\nconst getAccessibleRoutes = (only?: RouteType[], exclude?: RouteType[], defaultExposeStrategy: \"all\" | \"none\" = \"all\"): RouteType[] => {\n let accessibleRoutes: RouteType[] =\n 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.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HttpError } from 'http-errors';
|
|
2
|
-
import { C as Condition, S as SearchCondition, A as Adapter, F as FakePrismaClient, P as PaginationData, a as ParsedQueryParameters, R as RouteType, M as ModelsOptions } from './types.d-
|
|
3
|
-
export { H as CrudHandlerOptions, b as HandlerParameters, c as ModelOption, O as OrderByField, d as OrderByOperator, e as PaginationConfig, f as RecursiveField, U as UniqueResourceHandlerParameters, W as WhereCondition, g as WhereField, h as WhereOperator } from './types.d-
|
|
2
|
+
import { C as Condition, S as SearchCondition, A as Adapter, F as FakePrismaClient, P as PaginationData, a as ParsedQueryParameters, R as RouteType, M as ModelsOptions } from './types.d-6e8ef982.js';
|
|
3
|
+
export { H as CrudHandlerOptions, b as HandlerParameters, c as ModelOption, O as OrderByField, d as OrderByOperator, e as PaginationConfig, f as RecursiveField, U as UniqueResourceHandlerParameters, W as WhereCondition, g as WhereField, h as WhereOperator } from './types.d-6e8ef982.js';
|
|
4
4
|
import { OpenAPIV3 } from 'openapi-types';
|
|
5
5
|
|
|
6
6
|
type PrismaRecursiveField = "include" | "select";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HttpError } from 'http-errors';
|
|
2
|
-
import { C as Condition, S as SearchCondition, A as Adapter, F as FakePrismaClient, P as PaginationData, a as ParsedQueryParameters, R as RouteType, M as ModelsOptions } from './types.d-
|
|
3
|
-
export { H as CrudHandlerOptions, b as HandlerParameters, c as ModelOption, O as OrderByField, d as OrderByOperator, e as PaginationConfig, f as RecursiveField, U as UniqueResourceHandlerParameters, W as WhereCondition, g as WhereField, h as WhereOperator } from './types.d-
|
|
2
|
+
import { C as Condition, S as SearchCondition, A as Adapter, F as FakePrismaClient, P as PaginationData, a as ParsedQueryParameters, R as RouteType, M as ModelsOptions } from './types.d-6e8ef982.js';
|
|
3
|
+
export { H as CrudHandlerOptions, b as HandlerParameters, c as ModelOption, O as OrderByField, d as OrderByOperator, e as PaginationConfig, f as RecursiveField, U as UniqueResourceHandlerParameters, W as WhereCondition, g as WhereField, h as WhereOperator } from './types.d-6e8ef982.js';
|
|
4
4
|
import { OpenAPIV3 } from 'openapi-types';
|
|
5
5
|
|
|
6
6
|
type PrismaRecursiveField = "include" | "select";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkGMVQBGMY_js = require('./chunk-GMVQBGMY.js');
|
|
4
4
|
var W = require('http-errors');
|
|
5
5
|
var pagination = require('@visulima/pagination');
|
|
6
6
|
var prismaDmmfTransformer = require('@visulima/prisma-dmmf-transformer');
|
|
@@ -9,11 +9,11 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
9
9
|
|
|
10
10
|
var W__default = /*#__PURE__*/_interopDefault(W);
|
|
11
11
|
|
|
12
|
-
var X=(s,e)=>{let t={};return e.forEach(r=>{t[r]=s[r].plural;}),t},M=X;var Y=new Set(["string","boolean","number"]),N=s=>Y.has(typeof s),O=N;var q=s=>{let e={};if(Object.keys(s).forEach(t=>{let r=s[t];O(r)&&(e[t]=r);}),Object.keys(e).length!==1)throw new Error("cursor needs to be an object with exactly 1 property with a primitive value");return e},$=q;var ee={$asc:"asc",$desc:"desc"},te=s=>{let e={};return Object.keys(s).forEach(t=>{let r=s[t];e[t]=ee[r];}),e},I=te;var D=(s,e)=>{let t={};return Object.keys(s).forEach(r=>{t[r]=s[r]===!0?!0:{[e]:D(s[r],e)};}),t},E=D;var R=s=>s instanceof Object,re={$cont:"contains",$ends:"endsWith",$eq:"equals",$gt:"gt",$gte:"gte",$in:"in",$lt:"lt",$lte:"lte",$neq:"not",$notin:"notIn",$starts:"startsWith"},se=s=>/^\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(s),ne=s=>se(s)?new Date(s):typeof s=="string"&&s==="$isnull"?null:s,F=(s,e)=>{let t=s.split(".");return t.splice(-1,1),e.includes(t.join("."))},k=s=>{let e=Object.keys(s)[0],t=re[e];if(t)return {[t]:s[e]}},V=(s,e,t,r)=>{let n=e.split(".").reverse(),a={};n.forEach((p,c)=>{c===0?v(s,p,a,r):a={[p]:{some:a}};});let i=n.reverse()[0],o=t[i];t[i]={some:{...o?.some,...a[i]?.some}};},A=(s,e)=>{let t={};return Object.keys(s).forEach(r=>{let n=s[r];if(F(r,e))V(n,r,t,e);else if(O(n))t[r]=n;else if(R(n)){let a=k(n);a&&(t[r]=a);}}),t},v=(s,e,t,r)=>{if(O(s))t[e]=ne(s);else switch(e){case"$or":{R(s)&&(t.OR=A(s,r));break}case"$and":{R(s)&&(t.AND=A(s,r));break}case"$not":{R(s)&&(t.NOT=A(s,r));break}default:{t[e]=k(s);break}}},ie=(s,e)=>{let t={};return Object.keys(s).forEach(r=>{let n=s[r];F(r,e)?V(n,r,t,e):v(n,r,t,e);}),t},B=ie;var j=class{constructor({manyRelations:e={},models:t,primaryKey:r="id",prismaClient:n}){this.getPrismaClientModels=async()=>{if(this.prismaClient._dmmf!==void 0)return this.dmmf=this.prismaClient._dmmf,this.dmmf?.mappingsMap;if(this.prismaClient._getDmmf!==void 0)return this.dmmf=await this.prismaClient._getDmmf(),this.dmmf.mappingsMap;throw new Error("Couldn't get prisma client models")};this.prismaClient=n,this.primaryKey=r,this.manyRelations=e,this.ctorModels=t;}getPrismaDelegate(e){return this.prismaClient[`${e.charAt(0).toLowerCase()}${e.slice(1)}`]}get client(){return this.prismaClient}async connect(){this.prismaClient.$connect();}async create(e,t,r){return await this.getPrismaDelegate(e).create({data:t,include:r.include,select:r.select})}async delete(e,t,r){return await this.getPrismaDelegate(e).delete({include:r.include,select:r.select,where:{[this.primaryKey]:t}})}async disconnect(){await this.prismaClient.$disconnect();}async getAll(e,t){return await this.getPrismaDelegate(e).findMany({cursor:t.cursor,distinct:t.distinct,include:t.include,orderBy:t.orderBy,select:t.select,skip:t.skip,take:t.take,where:t.where})}getModels(){return this.models??[]}async getOne(e,t,r){let n=this.getPrismaDelegate(e);return await(n.findUnique??n.findOne)({include:r.include,select:r.select,where:{[this.primaryKey]:t}})}async getPaginationData(e,t){let r=await this.getPrismaDelegate(e).count({distinct:t.distinct,where:t.where});return {page:Math.ceil((t.skip??0)/(t.take??0))+1,pageCount:Math.ceil(r/(t.take??0)),total:r}}handleError(e){throw console.error(e),e instanceof Error&&e.stack&&console.error(e.stack),e.constructor.name==="PrismaClientKnownRequestError"||e.constructor.name==="PrismaClientValidationError"?W__default.default(400,"invalid request, check your server logs for more info"):W__default.default(500,"an unknown error occured, check your server logs for more info")}async init(){let e=this.ctorModels,t=await this.getPrismaClientModels();e!==void 0&&e.forEach(r=>{if(!Object.keys(t).includes(r))throw new Error(`Model name ${r} is invalid.`)}),this.models=e??Object.keys(t);}async mapModelsToRouteNames(){return M(await this.getPrismaClientModels(),this.getModels())}parseQuery(e,t){let r={};return t.select&&(r.select=E(t.select,"select")),t.include&&(r.include=E(t.include,"include")),t.originalQuery?.where&&(r.where=B(JSON.parse(t.originalQuery.where),this.manyRelations[e]??[])),t.orderBy&&(r.orderBy=I(t.orderBy)),t.limit!==void 0&&(r.take=t.limit),t.skip!==void 0&&(r.skip=t.skip),t.originalQuery?.cursor&&(r.cursor=$(JSON.parse(t.originalQuery.cursor))),t.distinct&&(r.distinct=t.distinct),r}async update(e,t,r,n){return await this.getPrismaDelegate(e).update({data:r,include:n.include,select:n.select,where:{[this.primaryKey]:t}})}};var ae=s=>`#/components/schemas/${s}`,f=ae;var Q=s=>{switch(s){case"Int":case"BigInt":return "integer";case"DateTime":case"Bytes":case"String":return "string";case"Float":case"Decimal":return "number";case"Json":return "object";case"Boolean":return "boolean";case"Null":return "null";default:return ""}},C="PaginationData",me=[{methodStart:"createOne",schemaNameStart:"Create"},{methodStart:"updateOne",schemaNameStart:"Update"}],S=class{constructor(e){this.dmmf=e;this.schemaInputTypes=new Map;}formatInputTypeData(e){if(e.kind==="object"){let r=f(e.type.name);return e.isList?{items:{$ref:r},type:"array",xml:{name:e.type.name,wrapped:!0}}:{$ref:r}}let t=Q(e.type);return e.isList?{items:{type:t},type:"array",xml:{name:e.type.name,wrapped:!0}}:{type:t}}getExampleModelsSchemas(e,t){let r=i=>{let o=i.replace("#/components/schemas/",""),p=t[o],c={};return Object.entries(p.properties??{}).forEach(([l,d])=>{let m=d.type;c[l]=m==="array"?[a(d.items)]:m;}),c},n=i=>{let o={};return Object.entries(i).forEach(([p,c])=>{o[p]=c.$ref===void 0?c.type:r(c.$ref);}),o},a=i=>{let o={};return Object.entries(i).forEach(([p,c])=>{c.items.$ref!==void 0?o[p]=[r(c.items.$ref)]:c.type==="array"?o[p]=[a(c.items)]:c.type==="object"?o[p]=n(c.properties):o[p]=c.type;}),o};return e.reduce((i,o)=>{let p={},c=t[o];Object.entries(c.properties).forEach(([m,g])=>{let u=g.type;u==="array"?p[m]=[r(g.items.$ref)]:u==="object"?p[m]=n(g.properties):p[m]=u;});let l=this.getPaginationDataSchema()[C],d={};return Object.entries(l.properties).forEach(([m,g])=>{d[m]=g.type;}),{...i,[`${o}`]:{value:p},[`${o}Page`]:{value:{data:[p],meta:d}},[`${o}s`]:{value:[p]}}},{})}getPaginatedModelsSchemas(e){return e.reduce((t,r)=>({...t,[`${r}Page`]:{properties:{data:{items:{$ref:f(r)},type:"array",xml:{name:"data",wrapped:!0}},meta:{$ref:f(C)}},type:"object",xml:{name:`${r}Page`}}}),{})}getPaginationDataSchema(){return pagination.createPaginationMetaSchemaObject(C)}parseInputTypes(e){let t=e.reduce((r,n)=>(me.map(i=>({name:`${i.methodStart}${n}`,schemaName:`${i.schemaNameStart}${n}`})).forEach(({name:i,schemaName:o})=>{let p=this.dmmf.mutationType.fieldMap[i].args[0].inputTypes[0].type.fields,c=[],l=p.reduce((d,m)=>{if(m.inputTypes[0].kind==="scalar"){let g=prismaDmmfTransformer.getJSONSchemaProperty(this.dmmf.datamodel,{})({name:m.name,...m.inputTypes[0]}),{type:u}=g[1];u&&Array.isArray(u)?u.includes("null")&&(d[m.name]={...u,nullable:!0,type:u.filter(b=>b!=="null")},d[m.name].type.length===1&&(d[m.name]={...d[m.name],type:d[m.name].type[0]})):d[m.name]=g[1];}else {let g=this.parseObjectInputType(m.inputTypes[0]);d[m.name]={...g,nullable:m.isNullable};}return m.isRequired&&c.push(m.name),d},{});r[o]={properties:l,type:"object",xml:{name:o}},c.length>0&&(r[o].required=c);}),r),{});return this.schemaInputTypes.forEach((r,n)=>{t[n]={properties:r,type:"object",xml:{name:n}};}),t}parseModels(){let e=prismaDmmfTransformer.transformDMMF(this.dmmf).definitions;return Object.keys(e).forEach(t=>{let{properties:r}=e[t];Object.keys(r).forEach(n=>{Array.isArray(r[n].type)&&r[n].type.includes("null")&&(r[n].type=r[n].type.filter(a=>a!=="null"),r[n].type.length===1&&(r[n].type=r[n].type[0]),r[n].nullable=!0);});}),e}parseObjectInputType(e){return e.kind==="object"?(this.schemaInputTypes.has(e.type.name)||(this.schemaInputTypes.set(e.type.name,{}),e.type.fields.forEach(t=>{let r={};if(t.inputTypes.length>1){let n=!1,a=t.inputTypes.map(i=>{let o=this.formatInputTypeData(i);if(o.type==="null"){n=!0;return}return o}).filter(Boolean);a.length===1?r=a[0]:r.anyOf=a,n&&(r.nullable=!0);}else {let n=t.inputTypes[0];r=this.formatInputTypeData(n);}this.schemaInputTypes.set(e.type.name,{...this.schemaInputTypes.get(e.type.name),[t.name]:r}),t.inputTypes.forEach(n=>{n.kind==="object"&&this.parseObjectInputType(n);});})),{$ref:f(e.type.name)}):{type:Q(e.type)}}},_=S;var de=(s,e,t="all")=>s.reduce((r,n)=>e?.[n]?{...r,[n]:chunkDOLZ4YNP_js.b(e[n].only,e[n].exclude,t)}:{...r,[n]:chunkDOLZ4YNP_js.b(void 0,void 0,t)},{}),L=de;var h={distinct:{description:"Fields to distinctively retrieve",name:"distinct",schema:{type:"string"}},include:{description:"Include relations, same as select",name:"include",schema:{type:"string"}},limit:{description:"Maximum number of elements to retrieve",name:"limit",schema:{minimum:0,type:"integer"}},orderBy:{description:'Field on which to order by a direction. See <a href="https://next-crud.js.org/query-params#orderBy">the docs</a>',name:"orderBy",schema:{type:"string"}},page:{description:"Page number. Use only for pagination.",name:"page",schema:{minimum:1,type:"integer"}},select:{description:"Fields to select. For nested fields, chain them separated with a dot, eg: user.posts",name:"select",schema:{type:"string"}},skip:{description:"Number of rows to skip",name:"skip",schema:{minimum:0,type:"integer"}},where:{description:'Fields to filter. See <a href="https://next-crud.js.org/query-params#where">the docs</a>',name:"where",schema:{type:"string"}}},U=[h.select,h.include],le=[...U,h.limit,h.skip,h.where,h.orderBy,h.page,h.distinct],H=(s,e=[])=>s==="READ_ALL"?[...le,...e].filter(Boolean):[...U,...e].filter(Boolean);var ge=s=>`#/components/examples/${s}`,y=ge;var P=(s,e)=>e?{items:{$ref:f(s)},type:"array"}:{$ref:f(s)},ue=(s,e)=>{if(s==="CREATE")return {content:{content:{"application/json":{example:y(e),schema:P(e)}},description:`${e} created`},statusCode:201};if(s==="DELETE")return {content:{content:{"application/json":{example:y(e),schema:P(e)}},description:`${e} item deleted`},statusCode:200};if(s==="READ_ALL")return {content:{content:{"application/json":{examples:{Default:{$ref:y(`${e}s`)},Pagination:{$ref:y(`${e}Page`)}},schema:{oneOf:[P(e,!0),P(`${e}Page`,!1)]}}},description:`${e} list retrieved`},statusCode:200};if(s==="READ_ONE")return {content:{content:{"application/json":{example:y(e),schema:P(e)}},description:`${e} item retrieved`},statusCode:200};if(s==="UPDATE")return {content:{content:{"application/json":{example:y(e),schema:P(e)}},description:`${e} item updated`},statusCode:200}},J=(s,e)=>({content:{"application/json":{schema:{$ref:f(`${s}${e}`)}}}}),fe=s=>{switch(s){case"CREATE":return "post";case"READ_ALL":case"READ_ONE":return "get";case"UPDATE":return "put";case"DELETE":return "delete";default:throw new TypeError(`Method for route type ${s} was not found.`)}},K=({hasId:s,modelName:e,modelsConfig:t,routeTypes:r,tag:n})=>{let a={};return r.forEach(i=>{if(r.includes(i)){let o=t?.[e]?.routeTypes?.[i]?.response.name??t?.[e]?.type?.name??e,p=fe(i),c=ue(i,o);if(c===void 0)throw new TypeError(`Route type ${i}; response config was not found.`);a[p]={parameters:H(i).map(l=>({...l,in:"query"})),responses:{[c.statusCode]:c.content,...t?.[e]?.routeTypes?.[i]?.responses},summary:t?.[e]?.routeTypes?.[i]?.summary,tags:[n]},s&&a[p].parameters.push({description:`ID of the ${e}`,in:"path",name:"id",required:!0,schema:{type:"string"}}),i==="UPDATE"?a[p].requestBody=J("Update",o):i==="CREATE"&&(a[p].requestBody=J("Create",o));}}),a},he=({models:s,modelsConfig:e,routes:t,routesMap:r})=>Object.keys(t).reduce((n,a)=>{let i=t[a],o=s?.[a]?.name?s[a].name:r?.[a]??a,p=e?.[a]?.tag.name??a;if(i.includes("CREATE")||i.includes("READ_ALL")){let c=`/${o}`,l=["READ_ALL","CREATE"].filter(d=>i.includes(d));n[c]=K({modelName:a,modelsConfig:e,routeTypes:l,tag:p});}if(i.includes("READ_ONE")||i.includes("UPDATE")||i.includes("DELETE")){let c=`/${o}/{id}`,l=["READ_ONE","UPDATE","DELETE"].filter(d=>i.includes(d));n[c]=K({hasId:!0,modelName:a,modelsConfig:e,routeTypes:l,tag:p});}return n},{}),G=he;var ye=(s,e)=>s.map(t=>e?.[t]?.tag?e[t].tag:{name:t}),Z=ye;var Pe=(s,e)=>(Object.values(s).forEach(t=>{Object.values(t).forEach(r=>{typeof r.responses=="object"&&Object.values(r.responses).forEach(n=>{typeof n.content=="object"&&Object.values(n.content).forEach(a=>{if(typeof a.example=="string"){let i=a.example.replace("#/components/examples/","");e[i]?.value!==void 0&&(a.example=e[i].value);}});});});}),s),Oe=async({crud:s={models:{}},defaultExposeStrategy:e="all",models:t,prismaClient:r,swagger:n={allowedMediaTypes:{"application/json":!0},models:{}}})=>{let a,i;if(r._dmmf!==void 0?(a=r._dmmf,i=a?.mappingsMap):r._getDmmf!==void 0&&(a=await r._getDmmf(),i=a.mappingsMap),a===void 0)throw new TypeError("Couldn't get prisma client models");let o=new _(a),p=o.parseModels(),c=Object.keys(p),l=JSON.stringify({...p,...o.parseInputTypes(c),...o.getPaginationDataSchema(),...o.getPaginatedModelsSchemas(c)});t!==void 0&&t.forEach(x=>{if(!Object.keys(i).includes(x))throw new Error(`Model name ${x} is invalid.`)});let d=t??Object.keys(i),m=L(d,s.models,e),g=Z(d,n.models),u=G({models:s.models,modelsConfig:n.models,routes:m,routesMap:M(i,d)}),b=JSON.parse(l.replaceAll("#/definitions","#/components/schemas")),T=o.getExampleModelsSchemas(c,b);return {examples:T,paths:Pe(u,T),schemas:b,tags:g}},be=Oe;
|
|
12
|
+
var X=(s,e)=>{let t={};return e.forEach(r=>{t[r]=s[r].plural;}),t},M=X;var Y=new Set(["string","boolean","number"]),N=s=>Y.has(typeof s),O=N;var q=s=>{let e={};if(Object.keys(s).forEach(t=>{let r=s[t];O(r)&&(e[t]=r);}),Object.keys(e).length!==1)throw new Error("cursor needs to be an object with exactly 1 property with a primitive value");return e},$=q;var ee={$asc:"asc",$desc:"desc"},te=s=>{let e={};return Object.keys(s).forEach(t=>{let r=s[t];e[t]=ee[r];}),e},I=te;var D=(s,e)=>{let t={};return Object.keys(s).forEach(r=>{t[r]=s[r]===!0?!0:{[e]:D(s[r],e)};}),t},E=D;var R=s=>s instanceof Object,re={$cont:"contains",$ends:"endsWith",$eq:"equals",$gt:"gt",$gte:"gte",$in:"in",$lt:"lt",$lte:"lte",$neq:"not",$notin:"notIn",$starts:"startsWith"},se=s=>/^\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(s),ne=s=>se(s)?new Date(s):typeof s=="string"&&s==="$isnull"?null:s,F=(s,e)=>{let t=s.split(".");return t.splice(-1,1),e.includes(t.join("."))},k=s=>{let e=Object.keys(s)[0],t=re[e];if(t)return {[t]:s[e]}},V=(s,e,t,r)=>{let n=e.split(".").reverse(),a={};n.forEach((p,c)=>{c===0?v(s,p,a,r):a={[p]:{some:a}};});let i=n.reverse()[0],o=t[i];t[i]={some:{...o?.some,...a[i]?.some}};},A=(s,e)=>{let t={};return Object.keys(s).forEach(r=>{let n=s[r];if(F(r,e))V(n,r,t,e);else if(O(n))t[r]=n;else if(R(n)){let a=k(n);a&&(t[r]=a);}}),t},v=(s,e,t,r)=>{if(O(s))t[e]=ne(s);else switch(e){case"$or":{R(s)&&(t.OR=A(s,r));break}case"$and":{R(s)&&(t.AND=A(s,r));break}case"$not":{R(s)&&(t.NOT=A(s,r));break}default:{t[e]=k(s);break}}},ie=(s,e)=>{let t={};return Object.keys(s).forEach(r=>{let n=s[r];F(r,e)?V(n,r,t,e):v(n,r,t,e);}),t},B=ie;var j=class{constructor({manyRelations:e={},models:t,primaryKey:r="id",prismaClient:n}){this.getPrismaClientModels=async()=>{if(this.prismaClient._dmmf!==void 0)return this.dmmf=this.prismaClient._dmmf,this.dmmf?.mappingsMap;if(this.prismaClient._getDmmf!==void 0)return this.dmmf=await this.prismaClient._getDmmf(),this.dmmf.mappingsMap;throw new Error("Couldn't get prisma client models")};this.prismaClient=n,this.primaryKey=r,this.manyRelations=e,this.ctorModels=t;}getPrismaDelegate(e){return this.prismaClient[`${e.charAt(0).toLowerCase()}${e.slice(1)}`]}get client(){return this.prismaClient}async connect(){this.prismaClient.$connect();}async create(e,t,r){return await this.getPrismaDelegate(e).create({data:t,include:r.include,select:r.select})}async delete(e,t,r){return await this.getPrismaDelegate(e).delete({include:r.include,select:r.select,where:{[this.primaryKey]:t}})}async disconnect(){await this.prismaClient.$disconnect();}async getAll(e,t){return await this.getPrismaDelegate(e).findMany({cursor:t.cursor,distinct:t.distinct,include:t.include,orderBy:t.orderBy,select:t.select,skip:t.skip,take:t.take,where:t.where})}getModels(){return this.models??[]}async getOne(e,t,r){let n=this.getPrismaDelegate(e);return await(n.findUnique??n.findOne)({include:r.include,select:r.select,where:{[this.primaryKey]:t}})}async getPaginationData(e,t){let r=await this.getPrismaDelegate(e).count({distinct:t.distinct,where:t.where});return {page:Math.ceil((t.skip??0)/(t.take??0))+1,pageCount:Math.ceil(r/(t.take??0)),total:r}}handleError(e){throw console.error(e),e instanceof Error&&e.stack&&console.error(e.stack),e.constructor.name==="PrismaClientKnownRequestError"||e.constructor.name==="PrismaClientValidationError"?W__default.default(400,"invalid request, check your server logs for more info"):W__default.default(500,"an unknown error occured, check your server logs for more info")}async init(){let e=this.ctorModels,t=await this.getPrismaClientModels();e!==void 0&&e.forEach(r=>{if(!Object.keys(t).includes(r))throw new Error(`Model name ${r} is invalid.`)}),this.models=e??Object.keys(t);}async mapModelsToRouteNames(){return M(await this.getPrismaClientModels(),this.getModels())}parseQuery(e,t){let r={};return t.select&&(r.select=E(t.select,"select")),t.include&&(r.include=E(t.include,"include")),t.originalQuery?.where&&(r.where=B(JSON.parse(t.originalQuery.where),this.manyRelations[e]??[])),t.orderBy&&(r.orderBy=I(t.orderBy)),t.limit!==void 0&&(r.take=t.limit),t.skip!==void 0&&(r.skip=t.skip),t.originalQuery?.cursor&&(r.cursor=$(JSON.parse(t.originalQuery.cursor))),t.distinct&&(r.distinct=t.distinct),r}async update(e,t,r,n){return await this.getPrismaDelegate(e).update({data:r,include:n.include,select:n.select,where:{[this.primaryKey]:t}})}};var ae=s=>`#/components/schemas/${s}`,f=ae;var Q=s=>{switch(s){case"Int":case"BigInt":return "integer";case"DateTime":case"Bytes":case"String":return "string";case"Float":case"Decimal":return "number";case"Json":return "object";case"Boolean":return "boolean";case"Null":return "null";default:return ""}},C="PaginationData",me=[{methodStart:"createOne",schemaNameStart:"Create"},{methodStart:"updateOne",schemaNameStart:"Update"}],S=class{constructor(e){this.dmmf=e;this.schemaInputTypes=new Map;}formatInputTypeData(e){if(e.kind==="object"){let r=f(e.type.name);return e.isList?{items:{$ref:r},type:"array",xml:{name:e.type.name,wrapped:!0}}:{$ref:r}}let t=Q(e.type);return e.isList?{items:{type:t},type:"array",xml:{name:e.type.name,wrapped:!0}}:{type:t}}getExampleModelsSchemas(e,t){let r=i=>{let o=i.replace("#/components/schemas/",""),p=t[o],c={};return Object.entries(p.properties??{}).forEach(([l,d])=>{let m=d.type;c[l]=m==="array"?[a(d.items)]:m;}),c},n=i=>{let o={};return Object.entries(i).forEach(([p,c])=>{o[p]=c.$ref===void 0?c.type:r(c.$ref);}),o},a=i=>{let o={};return Object.entries(i).forEach(([p,c])=>{c.items.$ref!==void 0?o[p]=[r(c.items.$ref)]:c.type==="array"?o[p]=[a(c.items)]:c.type==="object"?o[p]=n(c.properties):o[p]=c.type;}),o};return e.reduce((i,o)=>{let p={},c=t[o];Object.entries(c.properties).forEach(([m,g])=>{let u=g.type;u==="array"?p[m]=[r(g.items.$ref)]:u==="object"?p[m]=n(g.properties):p[m]=u;});let l=this.getPaginationDataSchema()[C],d={};return Object.entries(l.properties).forEach(([m,g])=>{d[m]=g.type;}),{...i,[`${o}`]:{value:p},[`${o}Page`]:{value:{data:[p],meta:d}},[`${o}s`]:{value:[p]}}},{})}getPaginatedModelsSchemas(e){return e.reduce((t,r)=>({...t,[`${r}Page`]:{properties:{data:{items:{$ref:f(r)},type:"array",xml:{name:"data",wrapped:!0}},meta:{$ref:f(C)}},type:"object",xml:{name:`${r}Page`}}}),{})}getPaginationDataSchema(){return pagination.createPaginationMetaSchemaObject(C)}parseInputTypes(e){let t=e.reduce((r,n)=>(me.map(i=>({name:`${i.methodStart}${n}`,schemaName:`${i.schemaNameStart}${n}`})).forEach(({name:i,schemaName:o})=>{let p=this.dmmf.mutationType.fieldMap[i].args[0].inputTypes[0].type.fields,c=[],l=p.reduce((d,m)=>{if(m.inputTypes[0].kind==="scalar"){let g=prismaDmmfTransformer.getJSONSchemaProperty(this.dmmf.datamodel,{})({name:m.name,...m.inputTypes[0]}),{type:u}=g[1];u&&Array.isArray(u)?u.includes("null")&&(d[m.name]={...u,nullable:!0,type:u.filter(b=>b!=="null")},d[m.name].type.length===1&&(d[m.name]={...d[m.name],type:d[m.name].type[0]})):d[m.name]=g[1];}else {let g=this.parseObjectInputType(m.inputTypes[0]);d[m.name]={...g,nullable:m.isNullable};}return m.isRequired&&c.push(m.name),d},{});r[o]={properties:l,type:"object",xml:{name:o}},c.length>0&&(r[o].required=c);}),r),{});return this.schemaInputTypes.forEach((r,n)=>{t[n]={properties:r,type:"object",xml:{name:n}};}),t}parseModels(){let e=prismaDmmfTransformer.transformDMMF(this.dmmf).definitions;return Object.keys(e).forEach(t=>{let{properties:r}=e[t];Object.keys(r).forEach(n=>{Array.isArray(r[n].type)&&r[n].type.includes("null")&&(r[n].type=r[n].type.filter(a=>a!=="null"),r[n].type.length===1&&(r[n].type=r[n].type[0]),r[n].nullable=!0);});}),e}parseObjectInputType(e){return e.kind==="object"?(this.schemaInputTypes.has(e.type.name)||(this.schemaInputTypes.set(e.type.name,{}),e.type.fields.forEach(t=>{let r={};if(t.inputTypes.length>1){let n=!1,a=t.inputTypes.map(i=>{let o=this.formatInputTypeData(i);if(o.type==="null"){n=!0;return}return o}).filter(Boolean);a.length===1?r=a[0]:r.anyOf=a,n&&(r.nullable=!0);}else {let n=t.inputTypes[0];r=this.formatInputTypeData(n);}this.schemaInputTypes.set(e.type.name,{...this.schemaInputTypes.get(e.type.name),[t.name]:r}),t.inputTypes.forEach(n=>{n.kind==="object"&&this.parseObjectInputType(n);});})),{$ref:f(e.type.name)}):{type:Q(e.type)}}},_=S;var de=(s,e,t="all")=>s.reduce((r,n)=>e?.[n]?{...r,[n]:chunkGMVQBGMY_js.b(e[n].only,e[n].exclude,t)}:{...r,[n]:chunkGMVQBGMY_js.b(void 0,void 0,t)},{}),L=de;var h={distinct:{description:"Fields to distinctively retrieve",name:"distinct",schema:{type:"string"}},include:{description:"Include relations, same as select",name:"include",schema:{type:"string"}},limit:{description:"Maximum number of elements to retrieve",name:"limit",schema:{minimum:0,type:"integer"}},orderBy:{description:'Field on which to order by a direction. See <a href="https://next-crud.js.org/query-params#orderBy">the docs</a>',name:"orderBy",schema:{type:"string"}},page:{description:"Page number. Use only for pagination.",name:"page",schema:{minimum:1,type:"integer"}},select:{description:"Fields to select. For nested fields, chain them separated with a dot, eg: user.posts",name:"select",schema:{type:"string"}},skip:{description:"Number of rows to skip",name:"skip",schema:{minimum:0,type:"integer"}},where:{description:'Fields to filter. See <a href="https://next-crud.js.org/query-params#where">the docs</a>',name:"where",schema:{type:"string"}}},U=[h.select,h.include],le=[...U,h.limit,h.skip,h.where,h.orderBy,h.page,h.distinct],H=(s,e=[])=>s==="READ_ALL"?[...le,...e].filter(Boolean):[...U,...e].filter(Boolean);var ge=s=>`#/components/examples/${s}`,y=ge;var P=(s,e)=>e?{items:{$ref:f(s)},type:"array"}:{$ref:f(s)},ue=(s,e)=>{if(s==="CREATE")return {content:{content:{"application/json":{example:y(e),schema:P(e)}},description:`${e} created`},statusCode:201};if(s==="DELETE")return {content:{content:{"application/json":{example:y(e),schema:P(e)}},description:`${e} item deleted`},statusCode:200};if(s==="READ_ALL")return {content:{content:{"application/json":{examples:{Default:{$ref:y(`${e}s`)},Pagination:{$ref:y(`${e}Page`)}},schema:{oneOf:[P(e,!0),P(`${e}Page`,!1)]}}},description:`${e} list retrieved`},statusCode:200};if(s==="READ_ONE")return {content:{content:{"application/json":{example:y(e),schema:P(e)}},description:`${e} item retrieved`},statusCode:200};if(s==="UPDATE")return {content:{content:{"application/json":{example:y(e),schema:P(e)}},description:`${e} item updated`},statusCode:200}},J=(s,e)=>({content:{"application/json":{schema:{$ref:f(`${s}${e}`)}}}}),fe=s=>{switch(s){case"CREATE":return "post";case"READ_ALL":case"READ_ONE":return "get";case"UPDATE":return "put";case"DELETE":return "delete";default:throw new TypeError(`Method for route type ${s} was not found.`)}},K=({hasId:s,modelName:e,modelsConfig:t,routeTypes:r,tag:n})=>{let a={};return r.forEach(i=>{if(r.includes(i)){let o=t?.[e]?.routeTypes?.[i]?.response.name??t?.[e]?.type?.name??e,p=fe(i),c=ue(i,o);if(c===void 0)throw new TypeError(`Route type ${i}; response config was not found.`);a[p]={parameters:H(i).map(l=>({...l,in:"query"})),responses:{[c.statusCode]:c.content,...t?.[e]?.routeTypes?.[i]?.responses},summary:t?.[e]?.routeTypes?.[i]?.summary,tags:[n]},s&&a[p].parameters.push({description:`ID of the ${e}`,in:"path",name:"id",required:!0,schema:{type:"string"}}),i==="UPDATE"?a[p].requestBody=J("Update",o):i==="CREATE"&&(a[p].requestBody=J("Create",o));}}),a},he=({models:s,modelsConfig:e,routes:t,routesMap:r})=>Object.keys(t).reduce((n,a)=>{let i=t[a],o=s?.[a]?.name?s[a].name:r?.[a]??a,p=e?.[a]?.tag.name??a;if(i.includes("CREATE")||i.includes("READ_ALL")){let c=`/${o}`,l=["READ_ALL","CREATE"].filter(d=>i.includes(d));n[c]=K({modelName:a,modelsConfig:e,routeTypes:l,tag:p});}if(i.includes("READ_ONE")||i.includes("UPDATE")||i.includes("DELETE")){let c=`/${o}/{id}`,l=["READ_ONE","UPDATE","DELETE"].filter(d=>i.includes(d));n[c]=K({hasId:!0,modelName:a,modelsConfig:e,routeTypes:l,tag:p});}return n},{}),G=he;var ye=(s,e)=>s.map(t=>e?.[t]?.tag?e[t].tag:{name:t}),Z=ye;var Pe=(s,e)=>(Object.values(s).forEach(t=>{Object.values(t).forEach(r=>{typeof r.responses=="object"&&Object.values(r.responses).forEach(n=>{typeof n.content=="object"&&Object.values(n.content).forEach(a=>{if(typeof a.example=="string"){let i=a.example.replace("#/components/examples/","");e[i]?.value!==void 0&&(a.example=e[i].value);}});});});}),s),Oe=async({crud:s={models:{}},defaultExposeStrategy:e="all",models:t,prismaClient:r,swagger:n={allowedMediaTypes:{"application/json":!0},models:{}}})=>{let a,i;if(r._dmmf!==void 0?(a=r._dmmf,i=a?.mappingsMap):r._getDmmf!==void 0&&(a=await r._getDmmf(),i=a.mappingsMap),a===void 0)throw new TypeError("Couldn't get prisma client models");let o=new _(a),p=o.parseModels(),c=Object.keys(p),l=JSON.stringify({...p,...o.parseInputTypes(c),...o.getPaginationDataSchema(),...o.getPaginatedModelsSchemas(c)});t!==void 0&&t.forEach(x=>{if(!Object.keys(i).includes(x))throw new Error(`Model name ${x} is invalid.`)});let d=t??Object.keys(i),m=L(d,s.models,e),g=Z(d,n.models),u=G({models:s.models,modelsConfig:n.models,routes:m,routesMap:M(i,d)}),b=JSON.parse(l.replaceAll("#/definitions","#/components/schemas")),T=o.getExampleModelsSchemas(c,b);return {examples:T,paths:Pe(u,T),schemas:b,tags:g}},be=Oe;
|
|
13
13
|
|
|
14
14
|
Object.defineProperty(exports, 'RouteType', {
|
|
15
15
|
enumerable: true,
|
|
16
|
-
get: function () { return
|
|
16
|
+
get: function () { return chunkGMVQBGMY_js.a; }
|
|
17
17
|
});
|
|
18
18
|
exports.PrismaAdapter = j;
|
|
19
19
|
exports.modelsToOpenApi = be;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { b } from './chunk-
|
|
2
|
-
export { a as RouteType } from './chunk-
|
|
1
|
+
import { b } from './chunk-I5N5SJZ7.mjs';
|
|
2
|
+
export { a as RouteType } from './chunk-I5N5SJZ7.mjs';
|
|
3
3
|
import W from 'http-errors';
|
|
4
4
|
import { createPaginationMetaSchemaObject } from '@visulima/pagination';
|
|
5
5
|
import { getJSONSchemaProperty, transformDMMF } from '@visulima/prisma-dmmf-transformer';
|
package/dist/next/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ParsedQueryParameters, A as Adapter, H as HandlerOptions, E as ExecuteHandler } from '../types.d-
|
|
1
|
+
import { a as ParsedQueryParameters, A as Adapter, H as HandlerOptions, E as ExecuteHandler } from '../types.d-6e8ef982.js';
|
|
2
2
|
import { NextApiRequest, NextApiResponse } from 'next';
|
|
3
3
|
|
|
4
4
|
declare const handler$1: <T, R extends Request, Context, Q extends ParsedQueryParameters = any, M extends string = string>(adapter: Adapter<T, Q, string>, options?: HandlerOptions<M> | undefined) => Promise<ExecuteHandler<R, Context>>;
|
package/dist/next/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ParsedQueryParameters, A as Adapter, H as HandlerOptions, E as ExecuteHandler } from '../types.d-
|
|
1
|
+
import { a as ParsedQueryParameters, A as Adapter, H as HandlerOptions, E as ExecuteHandler } from '../types.d-6e8ef982.js';
|
|
2
2
|
import { NextApiRequest, NextApiResponse } from 'next';
|
|
3
3
|
|
|
4
4
|
declare const handler$1: <T, R extends Request, Context, Q extends ParsedQueryParameters = any, M extends string = string>(adapter: Adapter<T, Q, string>, options?: HandlerOptions<M> | undefined) => Promise<ExecuteHandler<R, Context>>;
|
package/dist/next/index.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkGMVQBGMY_js = require('../chunk-GMVQBGMY.js');
|
|
4
4
|
var R = require('http-errors');
|
|
5
5
|
var apiUtils = require('next/dist/server/api-utils');
|
|
6
6
|
var pagination = require('@visulima/pagination');
|
|
7
|
-
var M = require('lodash.set');
|
|
8
7
|
var url = require('url');
|
|
8
|
+
var O = require('lodash.set');
|
|
9
9
|
var pathToRegexp = require('path-to-regexp');
|
|
10
10
|
|
|
11
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
12
|
|
|
13
13
|
var R__default = /*#__PURE__*/_interopDefault(R);
|
|
14
|
-
var
|
|
14
|
+
var O__default = /*#__PURE__*/_interopDefault(O);
|
|
15
15
|
|
|
16
|
-
var v=async({adapter:s,query:t,request:e,resourceName:r})=>({data:await s.create(r,e.body,t),status:201}),T=v;var U=async({adapter:s,query:t,resourceId:e,resourceName:r})=>{if(typeof await s.getOne(r,e,t)=="object")return {data:await s.delete(r,e,t),status:200};throw R__default.default(404,`${r} ${e} not found`)},H=U;var D=async({adapter:s,pagination:t,query:e,resourceName:r})=>{let a=!1,i;if(e.page!==void 0){if(e.page<=0)throw new Error("page query must be a strictly positive number");i={page:e.page,perPage:e.limit??t.perPage};}i&&(a=!0,e.skip=(i.page-1)*i.perPage,e.limit=i.perPage);let n=await s.getAll(r,e);if(a){let{page:o,total:p}=await s.getPaginationData(r,e);return {data:pagination.paginate(o,i.perPage,p,n).toJSON(),status:200}}return {data:n,status:200}},E=D;var L=async({adapter:s,query:t,resourceId:e,resourceName:r})=>{let a=await s.getOne(r,e,t);if(typeof a!="object")throw R__default.default(404,`${r} ${e} not found`);return {data:a,status:200}},b=L;var
|
|
16
|
+
var v=async({adapter:s,query:t,request:e,resourceName:r})=>({data:await s.create(r,e.body,t),status:201}),T=v;var U=async({adapter:s,query:t,resourceId:e,resourceName:r})=>{if(typeof await s.getOne(r,e,t)=="object")return {data:await s.delete(r,e,t),status:200};throw R__default.default(404,`${r} ${e} not found`)},H=U;var D=async({adapter:s,pagination:t,query:e,resourceName:r})=>{let a=!1,i;if(e.page!==void 0){if(e.page<=0)throw new Error("page query must be a strictly positive number");i={page:e.page,perPage:e.limit??t.perPage};}i&&(a=!0,e.skip=(i.page-1)*i.perPage,e.limit=i.perPage);let n=await s.getAll(r,e);if(a){let{page:o,total:p}=await s.getPaginationData(r,e);return {data:pagination.paginate(o,i.perPage,p,n).toJSON(),status:200}}return {data:n,status:200}},E=D;var L=async({adapter:s,query:t,resourceId:e,resourceName:r})=>{let a=await s.getOne(r,e,t);if(typeof a!="object")throw R__default.default(404,`${r} ${e} not found`);return {data:a,status:200}},b=L;var _=async({adapter:s,query:t,request:e,resourceId:r,resourceName:a})=>{if(typeof await s.getOne(a,r,t)=="object")return {data:await s.update(a,r,e.body,t),status:201};throw R__default.default(404,`${a} ${r} not found`)},w=_;var Q=s=>{let t={};return s.split(",").forEach(r=>{O__default.default(t,r,!0);}),t},J=s=>{let t=JSON.parse(s),e={};return Object.keys(t).forEach(r=>{O__default.default(e,r,t[r]);}),e},W=s=>{let t={},e=JSON.parse(s);if(Object.keys(e).length>0){let r=Object.keys(e)[0];(e[r]==="$asc"||e[r]==="$desc")&&(t[r]=e[r]);}if(Object.keys(t).length!==1)throw new Error("orderBy needs to be an object with exactly 1 property with either $asc or $desc value");return t},G=s=>{if(s){let{searchParams:t}=new url.URL(s),e={};return t.get("select")&&(e.select=Q(t.get("select"))),t.get("include")&&(e.include=Q(t.get("include"))),t.get("where")&&(e.where=J(t.get("where"))),t.get("orderBy")&&(e.orderBy=W(t.get("orderBy"))),t.has("limit")&&(e.limit=Number.isFinite(+t.get("limit"))?+t.get("limit"):void 0),t.has("skip")&&(e.skip=Number.isFinite(+t.get("skip"))?+t.get("skip"):void 0),t.get("distinct")&&(e.distinct=t.get("distinct")),t.get("page")&&(e.page=Number.isFinite(+t.get("page"))?+t.get("page"):void 0),{originalQuery:Object.fromEntries(t.entries()),...e}}return {}},M=G;var V=s=>Number.isSafeInteger(+s)?+s:s,A=V;var z=s=>`${s.charAt(0).toLowerCase()}${s.slice(1)}`,C=(s,t)=>{let e=s.split("?")[0];if(e===void 0)throw new TypeError("Path is undefined");let r=Object.keys(t).find(a=>{let i=t[a],n=z(i);return new RegExp(`(${i}|${n}$)|(${i}|${n}/)`,"g").test(e)});if(r===void 0)throw new Error(`Couldn't find model ${r} name for url ${s}`);return {modelName:r,resourceName:t[r]}};var K=(s,t,e)=>{let r=t.split("?")[0];if(r===void 0)throw new TypeError("Path is undefined");if(!r.includes(`/${e}`))throw new Error(`invalid resource name '${e}' for route '${r}'`);let a=pathToRegexp.match([`/(.*)/${e}`,`/(.*)/${e}/:id`],{decode:decodeURIComponent}),i=pathToRegexp.match(`/(.*)/${e}`,{decode:decodeURIComponent});switch(s){case"GET":{let n=a(r);return typeof n=="object"&&n.params.id?{resourceId:n.params.id,routeType:"READ_ONE"}:{routeType:"READ_ALL"}}case"POST":return i(r)?{routeType:"CREATE"}:{routeType:null};case"PUT":case"PATCH":{let n=a(r);return typeof n=="object"&&n.params.id?{resourceId:n.params.id,routeType:"UPDATE"}:{routeType:null}}case"DELETE":{let n=a(r);return typeof n=="object"&&n.params.id?{resourceId:n.params.id,routeType:"DELETE"}:{routeType:null}}default:return {routeType:null}}},j=K;var Y=["create","delete","getAll","getOne","parseQuery","update","getPaginationData","getModels"],Z=s=>{Y.forEach(t=>{if(!s[t])throw R__default.default(500,`Adapter must implement the "${t}" method.`)});},k=Z;async function ee(s,t,e,r){try{k(e);}catch(o){let p=o;throw new apiUtils.ApiError(p.statusCode,p.message)}await e.init?.();let a={formatResourceId:A,pagination:{perPage:20},...r},i=await e.mapModelsToRouteNames?.(),n={};return e.getModels().forEach(o=>{n[o]=a.models?.[o]?.name??i?.[o]??o;}),async(o,p)=>{let{modelName:l,resourceName:h}=C(o.url,n);if(!h)throw R__default.default(404,`Resource not found: ${o.url}`);let{resourceId:P,routeType:g}=j(o.method,o.url,h);if(g===null)throw R__default.default(404,`Route not found: ${o.url}`);let y=r?.models?.[l];if(!chunkGMVQBGMY_js.b(y?.only,y?.exclude,r?.exposeStrategy??"all").includes(g))throw R__default.default(404,`Route not found: ${o.url}`);try{let m=y?.formatResourceId?.(P)??a.formatResourceId(P);await e.connect?.();let u=M(`https://${o.headers.host?.replace(/\/$/,"")}/${o.url}`),c={adapter:e,query:e.parseQuery(l,u),resourceName:l};try{let d;switch(g){case"READ_ONE":{d=await(a.handlers?.get??b)({...c,resourceId:m});break}case"READ_ALL":{d=await(a.handlers?.list??E)({...c,pagination:a.pagination,query:{...c.query,limit:u.limit?Number(u.limit):void 0,page:u.page?Number(u.page):void 0}});break}case"CREATE":{d=await(a.handlers?.create??T)({...c,request:o});break}case"UPDATE":{d=await(a.handlers?.update??w)({...c,request:o,resourceId:m});break}case"DELETE":{d=await(a.handlers?.delete??H)({...c,resourceId:m});break}default:d={data:"Method not found",status:404};}await s(p,d);}catch(d){if(e.handleError&&!(d instanceof apiUtils.ApiError))e.handleError(d);else throw d}}finally{await e.disconnect?.(),await t(p);}}}var f=ee;var te=async(s,t)=>await f(async(e,r)=>new Response(JSON.stringify(r.data),{headers:{"content-type":"application/json; charset=utf-8"},status:r.status}),async()=>{},s,t),re=te;var se=async(s,t)=>await f(async(e,r)=>{e.status(r.status).send(r.data);},async e=>{e.end();},s,t),ae=se;
|
|
17
17
|
|
|
18
18
|
exports.edgeHandler = re;
|
|
19
19
|
exports.nodeHandler = ae;
|
package/dist/next/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/base-crud-handler.ts","../../src/handler/create.ts","../../src/handler/delete.ts","../../src/handler/list.ts","../../src/handler/read.ts","../../src/handler/update.ts","../../src/query-parser.ts","../../src/utils/format-resource-id.ts","../../src/utils/get-resource-name-from-url.ts","../../src/utils/get-route-type.ts","../../src/utils/validate-adapter-methods.ts","../../src/next/api/edge/index.ts","../../src/next/api/node/index.ts"],"names":["createHttpError","ApiError","createHandler","adapter","query","request","resourceName","create_default","deleteHandler","resourceId","delete_default","paginate","listHandler","pagination","isPaginated","paginationOptions","resources","page","total","list_default","readHandler","resource","read_default","updateHandler","update_default","set","parse","parseRecursive","select","selectFields","field","parseWhere","where","whereObject","parsed","key","parseOrderBy","orderBy","orderByObject","parseQuery","queryString","parsedQuery","query_parser_default","formatResourceId","format_resource_id_default","ensureCamelCase","string_","getResourceNameFromUrl","url","models","realPath","modelName","name","routeName","camelCaseModel","match","getRouteType","method","entityMatcher","simpleMatcher","pathMatch","get_route_type_default","adapterMethods","validateAdapterMethods","validate_adapter_methods_default","baseHandler","responseExecutor","finalExecutor","options","error_","error","config","routeNames","modelRoutes","responseOrContext","routeType","modelConfig","get_accessible_routes_default","resourceIdFormatted","parameters","responseConfig","base_crud_handler_default","handler","_","edge_default","response","node_default"],"mappings":"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","sourcesContent":["import type { HttpError } from \"http-errors\";\nimport createHttpError from \"http-errors\";\n// eslint-disable-next-line import/no-extraneous-dependencies\nimport { ApiError } from \"next/dist/server/api-utils\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport createHandler from \"./handler/create\";\nimport deleteHandler from \"./handler/delete\";\nimport listHandler from \"./handler/list\";\nimport readHandler from \"./handler/read\";\nimport updateHandler from \"./handler/update\";\nimport parseQuery from \"./query-parser\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, HandlerParameters, ParsedQueryParameters } from \"./types.d\";\nimport { RouteType } from \"./types.d\";\nimport formatResourceId from \"./utils/format-resource-id\";\nimport getAccessibleRoutes from \"./utils/get-accessible-routes\";\nimport { getResourceNameFromUrl } from \"./utils/get-resource-name-from-url\";\nimport getRouteType from \"./utils/get-route-type\";\nimport validateAdapterMethods from \"./utils/validate-adapter-methods\";\n\ninterface ResponseConfig {\n data: any;\n status: number;\n}\n\nasync function baseHandler<R extends Request, Context, T, Q extends ParsedQueryParameters = any, M extends string = string>(\n responseExecutor: (responseOrContext: Context, responseConfig: ResponseConfig) => Promise<Response>,\n finalExecutor: (responseOrContext: Context) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Context>>;\n\nasync function baseHandler<R extends IncomingMessage, RResponse extends ServerResponse, T, Q extends ParsedQueryParameters = any, M extends string = string>(\n responseExecutor: (responseOrContext: RResponse, responseConfig: ResponseConfig) => Promise<void>,\n finalExecutor: (responseOrContext: RResponse) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, RResponse>>;\n\n// eslint-disable-next-line sonarjs/cognitive-complexity,func-style\nasync function baseHandler<R extends { method: string; url: string }, RResponse, T, Q extends ParsedQueryParameters = any, M extends string = string>(\n responseExecutor: (responseOrContext: RResponse, responseConfig: ResponseConfig) => Promise<RResponse>,\n finalExecutor: (responseOrContext: RResponse) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, RResponse>> {\n try {\n validateAdapterMethods(adapter);\n } catch (error_: any) {\n const error = error_ as HttpError;\n\n throw new ApiError(error.statusCode, error.message);\n }\n\n await adapter.init?.();\n\n const config = {\n formatResourceId,\n pagination: {\n perPage: 20,\n },\n ...options,\n };\n\n const routeNames = await adapter.mapModelsToRouteNames?.();\n const modelRoutes: { [key in M]?: string } = {};\n\n adapter.getModels().forEach((modelName) => {\n modelRoutes[modelName as M] = config.models?.[modelName as M]?.name ?? routeNames?.[modelName] ?? modelName;\n });\n\n return async (request, responseOrContext) => {\n const { modelName, resourceName } = getResourceNameFromUrl(request.url, modelRoutes as { [key in M]: string });\n\n if (!resourceName) {\n if (process.env.NODE_ENV === \"development\") {\n const mappedModels = await adapter.mapModelsToRouteNames?.();\n\n if (typeof mappedModels === \"object\") {\n throw createHttpError(404, `Resource not found, possible models: ${Object.values(mappedModels).join(\", \")}`);\n }\n }\n\n throw createHttpError(404, `Resource not found: ${request.url}`);\n }\n\n const { resourceId, routeType } = getRouteType(request.method, request.url, resourceName);\n\n if (routeType === null) {\n throw createHttpError(404, `Route not found: ${request.url}`);\n }\n\n const modelConfig = options?.models?.[modelName as M];\n\n const accessibleRoutes = getAccessibleRoutes(modelConfig?.only, modelConfig?.exclude, options?.exposeStrategy ?? \"all\");\n\n if (!accessibleRoutes.includes(routeType)) {\n throw createHttpError(404, `Route not found: ${request.url}`);\n }\n\n try {\n const resourceIdFormatted = modelConfig?.formatResourceId?.(resourceId as string) ?? config.formatResourceId(resourceId as string);\n\n await adapter.connect?.();\n\n const parsedQuery = parseQuery(request.url);\n const parameters: HandlerParameters<T, Q> = {\n adapter,\n query: adapter.parseQuery(modelName as M, parsedQuery),\n resourceName: modelName,\n };\n\n try {\n let responseConfig: ResponseConfig;\n\n switch (routeType) {\n case RouteType.READ_ONE: {\n responseConfig = await (config.handlers?.get ?? readHandler)<T, Q>({\n ...parameters,\n resourceId: resourceIdFormatted,\n });\n break;\n }\n case RouteType.READ_ALL: {\n responseConfig = await (config.handlers?.list ?? listHandler)<T, Q>({\n ...parameters,\n pagination: config.pagination,\n query: {\n ...parameters.query,\n limit: parsedQuery.limit ? Number(parsedQuery.limit) : undefined,\n page: parsedQuery.page ? Number(parsedQuery.page) : undefined,\n },\n });\n break;\n }\n case RouteType.CREATE: {\n responseConfig = await (config.handlers?.create ?? createHandler)<T, Q, R>({\n ...parameters,\n request: request as R & { body: Record<string, any> },\n });\n break;\n }\n case RouteType.UPDATE: {\n responseConfig = await (config.handlers?.update ?? updateHandler)<T, Q, R>({\n ...parameters,\n request: request as R & { body: Partial<T> },\n resourceId: resourceIdFormatted,\n });\n break;\n }\n case RouteType.DELETE: {\n responseConfig = await (config.handlers?.delete ?? deleteHandler)<T, Q>({\n ...parameters,\n resourceId: resourceIdFormatted,\n });\n break;\n }\n default: {\n responseConfig = {\n data: \"Method not found\",\n status: 404,\n };\n }\n }\n\n await responseExecutor(responseOrContext, responseConfig);\n } catch (error: any) {\n if (adapter.handleError && !(error instanceof ApiError)) {\n adapter.handleError(error);\n } else {\n throw error;\n }\n }\n } finally {\n await adapter.disconnect?.();\n\n await finalExecutor(responseOrContext);\n }\n };\n}\n\nexport default baseHandler;\n","import type { HandlerParameters } from \"../types.d\";\n\nconst createHandler: Handler = async ({ adapter, query, request, resourceName }) => {\n const resources = await adapter.create(resourceName, request.body, query);\n\n return {\n data: resources,\n status: 201,\n };\n};\n\nexport type Handler = <T, Q, Request>(\n parameters: HandlerParameters<T, Q> & { request: Request & { body: Record<string, any> } },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default createHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst deleteHandler: Handler = async ({ adapter, query, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource === \"object\") {\n const deletedResource = await adapter.delete(resourceName, resourceId, query);\n\n return {\n data: deletedResource,\n status: 200,\n };\n }\n\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n};\n\nexport type Handler = <T, Q>(\n parameters: UniqueResourceHandlerParameters<T, Q>,\n) => Promise<{\n data: any;\n status: number;\n}>;\nexport default deleteHandler;\n","import { paginate } from \"@visulima/pagination\";\n\nimport type { HandlerParameters, PaginationConfig, ParsedQueryParameters } from \"../types.d\";\n\ninterface PaginationOptions {\n page: number;\n perPage: number;\n}\n\nconst listHandler: Handler = async ({ adapter, pagination, query, resourceName }) => {\n let isPaginated = false;\n let paginationOptions: PaginationOptions | undefined;\n\n if (query.page !== undefined) {\n if (query.page <= 0) {\n throw new Error(\"page query must be a strictly positive number\");\n }\n\n paginationOptions = {\n page: query.page,\n perPage: query.limit ?? pagination.perPage,\n };\n }\n\n if (paginationOptions) {\n isPaginated = true;\n\n // eslint-disable-next-line no-param-reassign\n query.skip = (paginationOptions.page - 1) * paginationOptions.perPage;\n // eslint-disable-next-line no-param-reassign\n query.limit = paginationOptions.perPage;\n }\n\n const resources = await adapter.getAll(resourceName, query);\n\n if (isPaginated) {\n const { page, total } = await adapter.getPaginationData(resourceName, query);\n\n const paginator = paginate(page, (paginationOptions as PaginationOptions).perPage, total, resources);\n\n return {\n data: paginator.toJSON(),\n status: 200,\n };\n }\n\n return {\n data: resources,\n status: 200,\n };\n};\n\nexport type Handler = <T, Q extends ParsedQueryParameters>(\n parameters: HandlerParameters<T, Q> & { pagination: PaginationConfig },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default listHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst readHandler: Handler = async ({ adapter, query, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource !== \"object\") {\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n }\n\n return {\n data: resource,\n status: 200,\n };\n};\n\nexport type Handler = <T, Q>(\n parameters: UniqueResourceHandlerParameters<T, Q>,\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default readHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst updateHandler: Handler = async ({ adapter, query, request, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource === \"object\") {\n const updatedResource = await adapter.update(resourceName, resourceId, request.body, query);\n\n return {\n data: updatedResource,\n status: 201,\n };\n }\n\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n};\n\nexport type Handler = <T, Q, Request>(\n parameters: UniqueResourceHandlerParameters<T, Q> & { request: Request & { body: Partial<T> } },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default updateHandler;\n","// eslint-disable-next-line no-restricted-imports\nimport set from \"lodash.set\";\nimport { parse } from \"node:url\";\n\nimport type { OrderByField, ParsedQueryParameters, RecursiveField, WhereField } from \"./types.d\";\n\nconst parseRecursive = (select: string): RecursiveField => {\n const selectFields: RecursiveField = {};\n\n const fields = select.split(\",\");\n\n fields.forEach((field) => {\n set(selectFields, field, true);\n });\n\n return selectFields;\n};\n\nconst parseWhere = (where: string): WhereField => {\n const whereObject = JSON.parse(where);\n const parsed: WhereField = {};\n\n Object.keys(whereObject).forEach((key) => {\n set(parsed, key, whereObject[key]);\n });\n\n return parsed;\n};\n\nconst parseOrderBy = (orderBy: string): OrderByField => {\n const parsed: OrderByField = {};\n const orderByObject = JSON.parse(orderBy);\n\n if (Object.keys(orderByObject).length > 0) {\n const key = Object.keys(orderByObject)[0] as string;\n\n if (orderByObject[key as keyof typeof orderByObject] === \"$asc\" || orderByObject[key as keyof typeof orderByObject] === \"$desc\") {\n parsed[key] = orderByObject[key as keyof typeof orderByObject];\n }\n }\n\n if (Object.keys(parsed).length !== 1) {\n throw new Error(\"orderBy needs to be an object with exactly 1 property with either $asc or $desc value\");\n }\n\n return parsed;\n};\n\n// eslint-disable-next-line sonarjs/cognitive-complexity\nconst parseQuery = (queryString?: string): ParsedQueryParameters => {\n if (queryString) {\n const { query } = parse(queryString, true);\n const parsedQuery: ParsedQueryParameters = {};\n\n if (query[\"select\"]) {\n parsedQuery.select = parseRecursive(query[\"select\"] as string);\n }\n\n if (query[\"include\"]) {\n parsedQuery.include = parseRecursive(query[\"include\"] as string);\n }\n\n if (query[\"where\"]) {\n parsedQuery.where = parseWhere(query[\"where\"] as string);\n }\n\n if (query[\"orderBy\"]) {\n parsedQuery.orderBy = parseOrderBy(query[\"orderBy\"] as string);\n }\n\n if (query[\"limit\"] !== undefined) {\n parsedQuery.limit = Number.isFinite(+query[\"limit\"]) ? +query[\"limit\"] : undefined;\n }\n if (query[\"skip\"] !== undefined) {\n parsedQuery.skip = Number.isFinite(+query[\"skip\"]) ? +query[\"skip\"] : undefined;\n }\n\n if (query[\"distinct\"]) {\n parsedQuery.distinct = query[\"distinct\"] as string;\n }\n\n if (query[\"page\"]) {\n parsedQuery.page = Number.isFinite(+query[\"page\"]) ? +query[\"page\"] : undefined;\n }\n\n return {\n originalQuery: query,\n ...parsedQuery,\n };\n }\n\n return {};\n};\n\nexport default parseQuery;\n","const formatResourceId = (resourceId: string): number | string => (Number.isSafeInteger(+resourceId) ? +resourceId : resourceId);\n\nexport default formatResourceId;\n","export const ensureCamelCase = (string_: string): string => `${string_.charAt(0).toLowerCase()}${string_.slice(1)}`;\n\nexport const getResourceNameFromUrl = <M extends string = string>(\n url: string,\n models: { [key in M]: string },\n): {\n modelName: string;\n resourceName: string;\n} => {\n // Exclude the query params from the path\n const realPath = url.split(\"?\")[0];\n\n if (realPath === undefined) {\n throw new TypeError(\"Path is undefined\");\n }\n\n const modelName = (Object.keys(models) as M[]).find((name) => {\n const routeName = models[name];\n const camelCaseModel = ensureCamelCase(routeName);\n\n // eslint-disable-next-line @rushstack/security/no-unsafe-regexp,security/detect-non-literal-regexp\n return new RegExp(`(${routeName}|${camelCaseModel}$)|(${routeName}|${camelCaseModel}/)`, \"g\").test(realPath);\n });\n\n if (modelName === undefined) {\n throw new Error(`Couldn't find model name for url ${url}`);\n }\n\n return {\n modelName,\n resourceName: models[modelName],\n };\n};\n","import { match } from \"path-to-regexp\";\n\nimport { RouteType } from \"../types.d\";\n\ninterface PathMatch {\n id: string;\n}\n\nconst getRouteType: (method: string, url: string, resourceName: string) => GetRouteType = (method, url, resourceName) => {\n // Exclude the query params from the path\n const realPath = url.split(\"?\")[0];\n\n if (realPath === undefined) {\n throw new TypeError(\"Path is undefined\");\n }\n\n if (!realPath.includes(`/${resourceName}`)) {\n throw new Error(`invalid resource name '${resourceName}' for route '${realPath}'`);\n }\n\n const entityMatcher = match<PathMatch>([`/(.*)/${resourceName}`, `/(.*)/${resourceName}/:id`], { decode: decodeURIComponent });\n const simpleMatcher = match(`/(.*)/${resourceName}`, {\n decode: decodeURIComponent,\n });\n\n switch (method) {\n case \"GET\": {\n const pathMatch = entityMatcher(realPath);\n\n // If we got a /something after the resource name, we are reading 1 entity\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.READ_ONE,\n };\n }\n\n return {\n routeType: RouteType.READ_ALL,\n };\n }\n case \"POST\": {\n const pathMatch = simpleMatcher(realPath);\n\n if (pathMatch) {\n return {\n routeType: RouteType.CREATE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n case \"PUT\":\n case \"PATCH\": {\n const pathMatch = entityMatcher(realPath);\n\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.UPDATE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n case \"DELETE\": {\n const pathMatch = entityMatcher(realPath);\n\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.DELETE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n default: {\n return {\n routeType: null,\n };\n }\n }\n};\n\nexport interface GetRouteType {\n resourceId?: string;\n routeType: RouteType | null;\n}\n\nexport default getRouteType;\n","import createHttpError from \"http-errors\";\n\nimport type { Adapter } from \"../types.d\";\n\nconst adapterMethods = [\"create\", \"delete\", \"getAll\", \"getOne\", \"parseQuery\", \"update\", \"getPaginationData\", \"getModels\"];\n\nconst validateAdapterMethods = <T, Q>(adapter: Adapter<T, Q>): void => {\n adapterMethods.forEach((method) => {\n if (!adapter[method as keyof Adapter<T, Q>]) {\n throw createHttpError(500, `Adapter must implement the \"${method}\" method.`);\n }\n });\n};\n\nexport default validateAdapterMethods;\n","import baseHandler from \"../../../base-crud-handler\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, ParsedQueryParameters } from \"../../../types.d\";\n\nconst handler = async <T, R extends Request, Context, Q extends ParsedQueryParameters = any, M extends string = string>(\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Context>> =>\n await baseHandler<R, Context, T, Q, M>(\n async (_, responseConfig) =>\n new Response(JSON.stringify(responseConfig.data), {\n headers: {\n \"content-type\": \"application/json; charset=utf-8\",\n },\n status: responseConfig.status,\n }),\n async () => {},\n adapter,\n options,\n );\n\nexport default handler;\n","import type { NextApiRequest, NextApiResponse } from \"next\";\n\nimport baseHandler from \"../../../base-crud-handler\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, ParsedQueryParameters } from \"../../../types.d\";\n\nconst handler = async <\n T,\n Q extends ParsedQueryParameters = any,\n R extends NextApiRequest = NextApiRequest,\n Response extends NextApiResponse = NextApiResponse,\n M extends string = string,\n>(\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Response>> =>\n await baseHandler<R, Response, T, Q, M>(\n async (response, responseConfig) => {\n response.status(responseConfig.status).send(responseConfig.data);\n },\n async (response) => {\n response.end();\n },\n adapter,\n options,\n );\n\nexport default handler;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/base-crud-handler.ts","../../src/handler/create.ts","../../src/handler/delete.ts","../../src/handler/list.ts","../../src/handler/read.ts","../../src/handler/update.ts","../../src/query-parser.ts","../../src/utils/format-resource-id.ts","../../src/utils/get-resource-name-from-url.ts","../../src/utils/get-route-type.ts","../../src/utils/validate-adapter-methods.ts","../../src/next/api/edge/index.ts","../../src/next/api/node/index.ts"],"names":["createHttpError","ApiError","createHandler","adapter","query","request","resourceName","create_default","deleteHandler","resourceId","delete_default","paginate","listHandler","pagination","isPaginated","paginationOptions","resources","page","total","list_default","readHandler","resource","read_default","updateHandler","update_default","URL","set","parseRecursive","select","selectFields","field","parseWhere","where","whereObject","parsed","key","parseOrderBy","orderBy","orderByObject","parseQuery","url","searchParams","parsedQuery","query_parser_default","formatResourceId","format_resource_id_default","ensureCamelCase","string_","getResourceNameFromUrl","models","realPath","modelName","name","routeName","camelCaseModel","match","getRouteType","method","entityMatcher","simpleMatcher","pathMatch","get_route_type_default","adapterMethods","validateAdapterMethods","validate_adapter_methods_default","baseHandler","responseExecutor","finalExecutor","options","error_","error","config","routeNames","modelRoutes","responseOrContext","routeType","modelConfig","get_accessible_routes_default","resourceIdFormatted","parameters","responseConfig","base_crud_handler_default","handler","_","edge_default","response","node_default"],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { HttpError } from \"http-errors\";\nimport createHttpError from \"http-errors\";\n// eslint-disable-next-line import/no-extraneous-dependencies\nimport { ApiError } from \"next/dist/server/api-utils\";\n\nimport createHandler from \"./handler/create\";\nimport deleteHandler from \"./handler/delete\";\nimport listHandler from \"./handler/list\";\nimport readHandler from \"./handler/read\";\nimport updateHandler from \"./handler/update\";\nimport parseQuery from \"./query-parser\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, HandlerParameters, ParsedQueryParameters } from \"./types.d\";\nimport { RouteType } from \"./types.d\";\nimport formatResourceId from \"./utils/format-resource-id\";\nimport getAccessibleRoutes from \"./utils/get-accessible-routes\";\nimport { getResourceNameFromUrl } from \"./utils/get-resource-name-from-url\";\nimport getRouteType from \"./utils/get-route-type\";\nimport validateAdapterMethods from \"./utils/validate-adapter-methods\";\n\ninterface ResponseConfig {\n data: any;\n status: number;\n}\n\nasync function baseHandler<R extends Request, Context, T, Q extends ParsedQueryParameters = any, M extends string = string>(\n responseExecutor: (responseOrContext: Context, responseConfig: ResponseConfig) => Promise<Response>,\n finalExecutor: (responseOrContext: Context) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Context>>;\n\nasync function baseHandler<R extends IncomingMessage, RResponse extends ServerResponse, T, Q extends ParsedQueryParameters = any, M extends string = string>(\n responseExecutor: (responseOrContext: RResponse, responseConfig: ResponseConfig) => Promise<void>,\n finalExecutor: (responseOrContext: RResponse) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, RResponse>>;\n\n// eslint-disable-next-line sonarjs/cognitive-complexity,func-style\nasync function baseHandler<\n R extends { headers: { host?: string }; method: string; url: string },\n RResponse,\n T,\n Q extends ParsedQueryParameters = any,\n M extends string = string,\n>(\n responseExecutor: (responseOrContext: RResponse, responseConfig: ResponseConfig) => Promise<RResponse>,\n finalExecutor: (responseOrContext: RResponse) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, RResponse>> {\n try {\n validateAdapterMethods(adapter);\n } catch (error_: any) {\n const error = error_ as HttpError;\n\n throw new ApiError(error.statusCode, error.message);\n }\n\n await adapter.init?.();\n\n const config = {\n formatResourceId,\n pagination: {\n perPage: 20,\n },\n ...options,\n };\n\n const routeNames = await adapter.mapModelsToRouteNames?.();\n const modelRoutes: { [key in M]?: string } = {};\n\n adapter.getModels().forEach((modelName) => {\n modelRoutes[modelName as M] = config.models?.[modelName as M]?.name ?? routeNames?.[modelName] ?? modelName;\n });\n\n return async (request, responseOrContext) => {\n const { modelName, resourceName } = getResourceNameFromUrl(request.url, modelRoutes as { [key in M]: string });\n\n if (!resourceName) {\n if (process.env.NODE_ENV === \"development\") {\n const mappedModels = await adapter.mapModelsToRouteNames?.();\n\n if (typeof mappedModels === \"object\") {\n throw createHttpError(404, `Resource not found, possible models: ${Object.values(mappedModels).join(\", \")}`);\n }\n }\n\n throw createHttpError(404, `Resource not found: ${request.url}`);\n }\n\n const { resourceId, routeType } = getRouteType(request.method, request.url, resourceName);\n\n if (routeType === null) {\n throw createHttpError(404, `Route not found: ${request.url}`);\n }\n\n const modelConfig = options?.models?.[modelName as M];\n\n const accessibleRoutes = getAccessibleRoutes(modelConfig?.only, modelConfig?.exclude, options?.exposeStrategy ?? \"all\");\n\n if (!accessibleRoutes.includes(routeType)) {\n throw createHttpError(404, `Route not found: ${request.url}`);\n }\n\n try {\n const resourceIdFormatted = modelConfig?.formatResourceId?.(resourceId as string) ?? config.formatResourceId(resourceId as string);\n\n await adapter.connect?.();\n\n const parsedQuery = parseQuery(`https://${request.headers.host?.replace(/\\/$/, \"\")}/${request.url}`);\n const parameters: HandlerParameters<T, Q> = {\n adapter,\n query: adapter.parseQuery(modelName as M, parsedQuery),\n resourceName: modelName,\n };\n\n try {\n let responseConfig: ResponseConfig;\n\n switch (routeType) {\n case RouteType.READ_ONE: {\n responseConfig = await (config.handlers?.get ?? readHandler)<T, Q>({\n ...parameters,\n resourceId: resourceIdFormatted,\n });\n break;\n }\n case RouteType.READ_ALL: {\n responseConfig = await (config.handlers?.list ?? listHandler)<T, Q>({\n ...parameters,\n pagination: config.pagination,\n query: {\n ...parameters.query,\n limit: parsedQuery.limit ? Number(parsedQuery.limit) : undefined,\n page: parsedQuery.page ? Number(parsedQuery.page) : undefined,\n },\n });\n break;\n }\n case RouteType.CREATE: {\n responseConfig = await (config.handlers?.create ?? createHandler)<T, Q, R>({\n ...parameters,\n request: request as R & { body: Record<string, any> },\n });\n break;\n }\n case RouteType.UPDATE: {\n responseConfig = await (config.handlers?.update ?? updateHandler)<T, Q, R>({\n ...parameters,\n request: request as R & { body: Partial<T> },\n resourceId: resourceIdFormatted,\n });\n break;\n }\n case RouteType.DELETE: {\n responseConfig = await (config.handlers?.delete ?? deleteHandler)<T, Q>({\n ...parameters,\n resourceId: resourceIdFormatted,\n });\n break;\n }\n default: {\n responseConfig = {\n data: \"Method not found\",\n status: 404,\n };\n }\n }\n\n await responseExecutor(responseOrContext, responseConfig);\n } catch (error: any) {\n if (adapter.handleError && !(error instanceof ApiError)) {\n adapter.handleError(error);\n } else {\n throw error;\n }\n }\n } finally {\n await adapter.disconnect?.();\n\n await finalExecutor(responseOrContext);\n }\n };\n}\n\nexport default baseHandler;\n","import type { HandlerParameters } from \"../types.d\";\n\nconst createHandler: Handler = async ({ adapter, query, request, resourceName }) => {\n const resources = await adapter.create(resourceName, request.body, query);\n\n return {\n data: resources,\n status: 201,\n };\n};\n\nexport type Handler = <T, Q, Request>(\n parameters: HandlerParameters<T, Q> & { request: Request & { body: Record<string, any> } },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default createHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst deleteHandler: Handler = async ({ adapter, query, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource === \"object\") {\n const deletedResource = await adapter.delete(resourceName, resourceId, query);\n\n return {\n data: deletedResource,\n status: 200,\n };\n }\n\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n};\n\nexport type Handler = <T, Q>(\n parameters: UniqueResourceHandlerParameters<T, Q>,\n) => Promise<{\n data: any;\n status: number;\n}>;\nexport default deleteHandler;\n","import { paginate } from \"@visulima/pagination\";\n\nimport type { HandlerParameters, PaginationConfig, ParsedQueryParameters } from \"../types.d\";\n\ninterface PaginationOptions {\n page: number;\n perPage: number;\n}\n\nconst listHandler: Handler = async ({ adapter, pagination, query, resourceName }) => {\n let isPaginated = false;\n let paginationOptions: PaginationOptions | undefined;\n\n if (query.page !== undefined) {\n if (query.page <= 0) {\n throw new Error(\"page query must be a strictly positive number\");\n }\n\n paginationOptions = {\n page: query.page,\n perPage: query.limit ?? pagination.perPage,\n };\n }\n\n if (paginationOptions) {\n isPaginated = true;\n\n // eslint-disable-next-line no-param-reassign\n query.skip = (paginationOptions.page - 1) * paginationOptions.perPage;\n // eslint-disable-next-line no-param-reassign\n query.limit = paginationOptions.perPage;\n }\n\n const resources = await adapter.getAll(resourceName, query);\n\n if (isPaginated) {\n const { page, total } = await adapter.getPaginationData(resourceName, query);\n\n const paginator = paginate(page, (paginationOptions as PaginationOptions).perPage, total, resources);\n\n return {\n data: paginator.toJSON(),\n status: 200,\n };\n }\n\n return {\n data: resources,\n status: 200,\n };\n};\n\nexport type Handler = <T, Q extends ParsedQueryParameters>(\n parameters: HandlerParameters<T, Q> & { pagination: PaginationConfig },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default listHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst readHandler: Handler = async ({ adapter, query, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource !== \"object\") {\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n }\n\n return {\n data: resource,\n status: 200,\n };\n};\n\nexport type Handler = <T, Q>(\n parameters: UniqueResourceHandlerParameters<T, Q>,\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default readHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst updateHandler: Handler = async ({ adapter, query, request, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource === \"object\") {\n const updatedResource = await adapter.update(resourceName, resourceId, request.body, query);\n\n return {\n data: updatedResource,\n status: 201,\n };\n }\n\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n};\n\nexport type Handler = <T, Q, Request>(\n parameters: UniqueResourceHandlerParameters<T, Q> & { request: Request & { body: Partial<T> } },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default updateHandler;\n","import { URL } from \"node:url\";\n// eslint-disable-next-line no-restricted-imports\nimport set from \"lodash.set\";\n\nimport type { OrderByField, ParsedQueryParameters, RecursiveField, WhereField } from \"./types.d\";\n\nconst parseRecursive = (select: string): RecursiveField => {\n const selectFields: RecursiveField = {};\n\n const fields = select.split(\",\");\n\n fields.forEach((field) => {\n set(selectFields, field, true);\n });\n\n return selectFields;\n};\n\nconst parseWhere = (where: string): WhereField => {\n const whereObject = JSON.parse(where);\n const parsed: WhereField = {};\n\n Object.keys(whereObject).forEach((key) => {\n set(parsed, key, whereObject[key]);\n });\n\n return parsed;\n};\n\nconst parseOrderBy = (orderBy: string): OrderByField => {\n const parsed: OrderByField = {};\n const orderByObject = JSON.parse(orderBy);\n\n if (Object.keys(orderByObject).length > 0) {\n const key = Object.keys(orderByObject)[0] as string;\n\n if (orderByObject[key as keyof typeof orderByObject] === \"$asc\" || orderByObject[key as keyof typeof orderByObject] === \"$desc\") {\n parsed[key] = orderByObject[key as keyof typeof orderByObject];\n }\n }\n\n if (Object.keys(parsed).length !== 1) {\n throw new Error(\"orderBy needs to be an object with exactly 1 property with either $asc or $desc value\");\n }\n\n return parsed;\n};\n\n// eslint-disable-next-line sonarjs/cognitive-complexity\nconst parseQuery = (url?: string): ParsedQueryParameters => {\n if (url) {\n const { searchParams } = new URL(url);\n const parsedQuery: ParsedQueryParameters = {};\n\n if (searchParams.get(\"select\")) {\n parsedQuery.select = parseRecursive(searchParams.get(\"select\") as string);\n }\n\n if (searchParams.get(\"include\")) {\n parsedQuery.include = parseRecursive(searchParams.get(\"include\") as string);\n }\n\n if (searchParams.get(\"where\")) {\n parsedQuery.where = parseWhere(searchParams.get(\"where\") as string);\n }\n\n if (searchParams.get(\"orderBy\")) {\n parsedQuery.orderBy = parseOrderBy(searchParams.get(\"orderBy\") as string);\n }\n\n if (searchParams.has(\"limit\")) {\n parsedQuery.limit = Number.isFinite(+(searchParams.get(\"limit\") as string)) ? +(searchParams.get(\"limit\") as string) : undefined;\n }\n\n if (searchParams.has(\"skip\")) {\n parsedQuery.skip = Number.isFinite(+(searchParams.get(\"skip\") as string)) ? +(searchParams.get(\"skip\") as string) : undefined;\n }\n\n if (searchParams.get(\"distinct\")) {\n parsedQuery.distinct = searchParams.get(\"distinct\") as string;\n }\n\n if (searchParams.get(\"page\")) {\n parsedQuery.page = Number.isFinite(+(searchParams.get(\"page\") as string)) ? +(searchParams.get(\"page\") as string) : undefined;\n }\n\n return {\n originalQuery: Object.fromEntries(searchParams.entries()),\n ...parsedQuery,\n };\n }\n\n return {};\n};\n\nexport default parseQuery;\n","const formatResourceId = (resourceId: string): number | string => (Number.isSafeInteger(+resourceId) ? +resourceId : resourceId);\n\nexport default formatResourceId;\n","export const ensureCamelCase = (string_: string): string => `${string_.charAt(0).toLowerCase()}${string_.slice(1)}`;\n\nexport const getResourceNameFromUrl = <M extends string = string>(\n url: string,\n models: { [key in M]: string },\n): {\n modelName: string;\n resourceName: string;\n} => {\n // Exclude the query params from the path\n const realPath = url.split(\"?\")[0];\n\n if (realPath === undefined) {\n throw new TypeError(\"Path is undefined\");\n }\n\n const modelName = (Object.keys(models) as M[]).find((name) => {\n const routeName = models[name];\n const camelCaseModel = ensureCamelCase(routeName);\n\n // eslint-disable-next-line @rushstack/security/no-unsafe-regexp,security/detect-non-literal-regexp\n return new RegExp(`(${routeName}|${camelCaseModel}$)|(${routeName}|${camelCaseModel}/)`, \"g\").test(realPath);\n });\n\n if (modelName === undefined) {\n throw new Error(`Couldn't find model ${modelName} name for url ${url}`);\n }\n\n return {\n modelName,\n resourceName: models[modelName],\n };\n};\n","import { match } from \"path-to-regexp\";\n\nimport { RouteType } from \"../types.d\";\n\ninterface PathMatch {\n id: string;\n}\n\nconst getRouteType: (method: string, url: string, resourceName: string) => GetRouteType = (method, url, resourceName) => {\n // Exclude the query params from the path\n const realPath = url.split(\"?\")[0];\n\n if (realPath === undefined) {\n throw new TypeError(\"Path is undefined\");\n }\n\n if (!realPath.includes(`/${resourceName}`)) {\n throw new Error(`invalid resource name '${resourceName}' for route '${realPath}'`);\n }\n\n const entityMatcher = match<PathMatch>([`/(.*)/${resourceName}`, `/(.*)/${resourceName}/:id`], { decode: decodeURIComponent });\n const simpleMatcher = match(`/(.*)/${resourceName}`, {\n decode: decodeURIComponent,\n });\n\n switch (method) {\n case \"GET\": {\n const pathMatch = entityMatcher(realPath);\n\n // If we got a /something after the resource name, we are reading 1 entity\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.READ_ONE,\n };\n }\n\n return {\n routeType: RouteType.READ_ALL,\n };\n }\n case \"POST\": {\n const pathMatch = simpleMatcher(realPath);\n\n if (pathMatch) {\n return {\n routeType: RouteType.CREATE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n case \"PUT\":\n case \"PATCH\": {\n const pathMatch = entityMatcher(realPath);\n\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.UPDATE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n case \"DELETE\": {\n const pathMatch = entityMatcher(realPath);\n\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.DELETE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n default: {\n return {\n routeType: null,\n };\n }\n }\n};\n\nexport interface GetRouteType {\n resourceId?: string;\n routeType: RouteType | null;\n}\n\nexport default getRouteType;\n","import createHttpError from \"http-errors\";\n\nimport type { Adapter } from \"../types.d\";\n\nconst adapterMethods = [\"create\", \"delete\", \"getAll\", \"getOne\", \"parseQuery\", \"update\", \"getPaginationData\", \"getModels\"];\n\nconst validateAdapterMethods = <T, Q>(adapter: Adapter<T, Q>): void => {\n adapterMethods.forEach((method) => {\n if (!adapter[method as keyof Adapter<T, Q>]) {\n throw createHttpError(500, `Adapter must implement the \"${method}\" method.`);\n }\n });\n};\n\nexport default validateAdapterMethods;\n","import baseHandler from \"../../../base-crud-handler\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, ParsedQueryParameters } from \"../../../types.d\";\n\nconst handler = async <T, R extends Request, Context, Q extends ParsedQueryParameters = any, M extends string = string>(\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Context>> =>\n await baseHandler<R, Context, T, Q, M>(\n async (_, responseConfig) =>\n new Response(JSON.stringify(responseConfig.data), {\n headers: {\n \"content-type\": \"application/json; charset=utf-8\",\n },\n status: responseConfig.status,\n }),\n async () => {},\n adapter,\n options,\n );\n\nexport default handler;\n","import type { NextApiRequest, NextApiResponse } from \"next\";\n\nimport baseHandler from \"../../../base-crud-handler\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, ParsedQueryParameters } from \"../../../types.d\";\n\nconst handler = async <\n T,\n Q extends ParsedQueryParameters = any,\n R extends NextApiRequest = NextApiRequest,\n Response extends NextApiResponse = NextApiResponse,\n M extends string = string,\n>(\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Response>> =>\n await baseHandler<R, Response, T, Q, M>(\n async (response, responseConfig) => {\n response.status(responseConfig.status).send(responseConfig.data);\n },\n async (response) => {\n response.end();\n },\n adapter,\n options,\n );\n\nexport default handler;\n"]}
|
package/dist/next/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { b as b$1 } from '../chunk-
|
|
1
|
+
import { b as b$1 } from '../chunk-I5N5SJZ7.mjs';
|
|
2
2
|
import R from 'http-errors';
|
|
3
3
|
import { ApiError } from 'next/dist/server/api-utils';
|
|
4
4
|
import { paginate } from '@visulima/pagination';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import { URL } from 'url';
|
|
6
|
+
import O from 'lodash.set';
|
|
7
7
|
import { match } from 'path-to-regexp';
|
|
8
8
|
|
|
9
|
-
var v=async({adapter:s,query:t,request:e,resourceName:r})=>({data:await s.create(r,e.body,t),status:201}),T=v;var U=async({adapter:s,query:t,resourceId:e,resourceName:r})=>{if(typeof await s.getOne(r,e,t)=="object")return {data:await s.delete(r,e,t),status:200};throw R(404,`${r} ${e} not found`)},H=U;var D=async({adapter:s,pagination:t,query:e,resourceName:r})=>{let a=!1,i;if(e.page!==void 0){if(e.page<=0)throw new Error("page query must be a strictly positive number");i={page:e.page,perPage:e.limit??t.perPage};}i&&(a=!0,e.skip=(i.page-1)*i.perPage,e.limit=i.perPage);let n=await s.getAll(r,e);if(a){let{page:o,total:p}=await s.getPaginationData(r,e);return {data:paginate(o,i.perPage,p,n).toJSON(),status:200}}return {data:n,status:200}},E=D;var L=async({adapter:s,query:t,resourceId:e,resourceName:r})=>{let a=await s.getOne(r,e,t);if(typeof a!="object")throw R(404,`${r} ${e} not found`);return {data:a,status:200}},b=L;var
|
|
9
|
+
var v=async({adapter:s,query:t,request:e,resourceName:r})=>({data:await s.create(r,e.body,t),status:201}),T=v;var U=async({adapter:s,query:t,resourceId:e,resourceName:r})=>{if(typeof await s.getOne(r,e,t)=="object")return {data:await s.delete(r,e,t),status:200};throw R(404,`${r} ${e} not found`)},H=U;var D=async({adapter:s,pagination:t,query:e,resourceName:r})=>{let a=!1,i;if(e.page!==void 0){if(e.page<=0)throw new Error("page query must be a strictly positive number");i={page:e.page,perPage:e.limit??t.perPage};}i&&(a=!0,e.skip=(i.page-1)*i.perPage,e.limit=i.perPage);let n=await s.getAll(r,e);if(a){let{page:o,total:p}=await s.getPaginationData(r,e);return {data:paginate(o,i.perPage,p,n).toJSON(),status:200}}return {data:n,status:200}},E=D;var L=async({adapter:s,query:t,resourceId:e,resourceName:r})=>{let a=await s.getOne(r,e,t);if(typeof a!="object")throw R(404,`${r} ${e} not found`);return {data:a,status:200}},b=L;var _=async({adapter:s,query:t,request:e,resourceId:r,resourceName:a})=>{if(typeof await s.getOne(a,r,t)=="object")return {data:await s.update(a,r,e.body,t),status:201};throw R(404,`${a} ${r} not found`)},w=_;var Q=s=>{let t={};return s.split(",").forEach(r=>{O(t,r,!0);}),t},J=s=>{let t=JSON.parse(s),e={};return Object.keys(t).forEach(r=>{O(e,r,t[r]);}),e},W=s=>{let t={},e=JSON.parse(s);if(Object.keys(e).length>0){let r=Object.keys(e)[0];(e[r]==="$asc"||e[r]==="$desc")&&(t[r]=e[r]);}if(Object.keys(t).length!==1)throw new Error("orderBy needs to be an object with exactly 1 property with either $asc or $desc value");return t},G=s=>{if(s){let{searchParams:t}=new URL(s),e={};return t.get("select")&&(e.select=Q(t.get("select"))),t.get("include")&&(e.include=Q(t.get("include"))),t.get("where")&&(e.where=J(t.get("where"))),t.get("orderBy")&&(e.orderBy=W(t.get("orderBy"))),t.has("limit")&&(e.limit=Number.isFinite(+t.get("limit"))?+t.get("limit"):void 0),t.has("skip")&&(e.skip=Number.isFinite(+t.get("skip"))?+t.get("skip"):void 0),t.get("distinct")&&(e.distinct=t.get("distinct")),t.get("page")&&(e.page=Number.isFinite(+t.get("page"))?+t.get("page"):void 0),{originalQuery:Object.fromEntries(t.entries()),...e}}return {}},M=G;var V=s=>Number.isSafeInteger(+s)?+s:s,A=V;var z=s=>`${s.charAt(0).toLowerCase()}${s.slice(1)}`,C=(s,t)=>{let e=s.split("?")[0];if(e===void 0)throw new TypeError("Path is undefined");let r=Object.keys(t).find(a=>{let i=t[a],n=z(i);return new RegExp(`(${i}|${n}$)|(${i}|${n}/)`,"g").test(e)});if(r===void 0)throw new Error(`Couldn't find model ${r} name for url ${s}`);return {modelName:r,resourceName:t[r]}};var K=(s,t,e)=>{let r=t.split("?")[0];if(r===void 0)throw new TypeError("Path is undefined");if(!r.includes(`/${e}`))throw new Error(`invalid resource name '${e}' for route '${r}'`);let a=match([`/(.*)/${e}`,`/(.*)/${e}/:id`],{decode:decodeURIComponent}),i=match(`/(.*)/${e}`,{decode:decodeURIComponent});switch(s){case"GET":{let n=a(r);return typeof n=="object"&&n.params.id?{resourceId:n.params.id,routeType:"READ_ONE"}:{routeType:"READ_ALL"}}case"POST":return i(r)?{routeType:"CREATE"}:{routeType:null};case"PUT":case"PATCH":{let n=a(r);return typeof n=="object"&&n.params.id?{resourceId:n.params.id,routeType:"UPDATE"}:{routeType:null}}case"DELETE":{let n=a(r);return typeof n=="object"&&n.params.id?{resourceId:n.params.id,routeType:"DELETE"}:{routeType:null}}default:return {routeType:null}}},j=K;var Y=["create","delete","getAll","getOne","parseQuery","update","getPaginationData","getModels"],Z=s=>{Y.forEach(t=>{if(!s[t])throw R(500,`Adapter must implement the "${t}" method.`)});},k=Z;async function ee(s,t,e,r){try{k(e);}catch(o){let p=o;throw new ApiError(p.statusCode,p.message)}await e.init?.();let a={formatResourceId:A,pagination:{perPage:20},...r},i=await e.mapModelsToRouteNames?.(),n={};return e.getModels().forEach(o=>{n[o]=a.models?.[o]?.name??i?.[o]??o;}),async(o,p)=>{let{modelName:l,resourceName:h}=C(o.url,n);if(!h)throw R(404,`Resource not found: ${o.url}`);let{resourceId:P,routeType:g}=j(o.method,o.url,h);if(g===null)throw R(404,`Route not found: ${o.url}`);let y=r?.models?.[l];if(!b$1(y?.only,y?.exclude,r?.exposeStrategy??"all").includes(g))throw R(404,`Route not found: ${o.url}`);try{let m=y?.formatResourceId?.(P)??a.formatResourceId(P);await e.connect?.();let u=M(`https://${o.headers.host?.replace(/\/$/,"")}/${o.url}`),c={adapter:e,query:e.parseQuery(l,u),resourceName:l};try{let d;switch(g){case"READ_ONE":{d=await(a.handlers?.get??b)({...c,resourceId:m});break}case"READ_ALL":{d=await(a.handlers?.list??E)({...c,pagination:a.pagination,query:{...c.query,limit:u.limit?Number(u.limit):void 0,page:u.page?Number(u.page):void 0}});break}case"CREATE":{d=await(a.handlers?.create??T)({...c,request:o});break}case"UPDATE":{d=await(a.handlers?.update??w)({...c,request:o,resourceId:m});break}case"DELETE":{d=await(a.handlers?.delete??H)({...c,resourceId:m});break}default:d={data:"Method not found",status:404};}await s(p,d);}catch(d){if(e.handleError&&!(d instanceof ApiError))e.handleError(d);else throw d}}finally{await e.disconnect?.(),await t(p);}}}var f=ee;var te=async(s,t)=>await f(async(e,r)=>new Response(JSON.stringify(r.data),{headers:{"content-type":"application/json; charset=utf-8"},status:r.status}),async()=>{},s,t),re=te;var se=async(s,t)=>await f(async(e,r)=>{e.status(r.status).send(r.data);},async e=>{e.end();},s,t),ae=se;
|
|
10
10
|
|
|
11
11
|
export { re as edgeHandler, ae as nodeHandler };
|
|
12
12
|
//# sourceMappingURL=out.js.map
|
package/dist/next/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/base-crud-handler.ts","../../src/handler/create.ts","../../src/handler/delete.ts","../../src/handler/list.ts","../../src/handler/read.ts","../../src/handler/update.ts","../../src/query-parser.ts","../../src/utils/format-resource-id.ts","../../src/utils/get-resource-name-from-url.ts","../../src/utils/get-route-type.ts","../../src/utils/validate-adapter-methods.ts","../../src/next/api/edge/index.ts","../../src/next/api/node/index.ts"],"names":["createHttpError","ApiError","createHandler","adapter","query","request","resourceName","create_default","deleteHandler","resourceId","delete_default","paginate","listHandler","pagination","isPaginated","paginationOptions","resources","page","total","list_default","readHandler","resource","read_default","updateHandler","update_default","set","parse","parseRecursive","select","selectFields","field","parseWhere","where","whereObject","parsed","key","parseOrderBy","orderBy","orderByObject","parseQuery","queryString","parsedQuery","query_parser_default","formatResourceId","format_resource_id_default","ensureCamelCase","string_","getResourceNameFromUrl","url","models","realPath","modelName","name","routeName","camelCaseModel","match","getRouteType","method","entityMatcher","simpleMatcher","pathMatch","get_route_type_default","adapterMethods","validateAdapterMethods","validate_adapter_methods_default","baseHandler","responseExecutor","finalExecutor","options","error_","error","config","routeNames","modelRoutes","responseOrContext","routeType","modelConfig","get_accessible_routes_default","resourceIdFormatted","parameters","responseConfig","base_crud_handler_default","handler","_","edge_default","response","node_default"],"mappings":"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","sourcesContent":["import type { HttpError } from \"http-errors\";\nimport createHttpError from \"http-errors\";\n// eslint-disable-next-line import/no-extraneous-dependencies\nimport { ApiError } from \"next/dist/server/api-utils\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport createHandler from \"./handler/create\";\nimport deleteHandler from \"./handler/delete\";\nimport listHandler from \"./handler/list\";\nimport readHandler from \"./handler/read\";\nimport updateHandler from \"./handler/update\";\nimport parseQuery from \"./query-parser\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, HandlerParameters, ParsedQueryParameters } from \"./types.d\";\nimport { RouteType } from \"./types.d\";\nimport formatResourceId from \"./utils/format-resource-id\";\nimport getAccessibleRoutes from \"./utils/get-accessible-routes\";\nimport { getResourceNameFromUrl } from \"./utils/get-resource-name-from-url\";\nimport getRouteType from \"./utils/get-route-type\";\nimport validateAdapterMethods from \"./utils/validate-adapter-methods\";\n\ninterface ResponseConfig {\n data: any;\n status: number;\n}\n\nasync function baseHandler<R extends Request, Context, T, Q extends ParsedQueryParameters = any, M extends string = string>(\n responseExecutor: (responseOrContext: Context, responseConfig: ResponseConfig) => Promise<Response>,\n finalExecutor: (responseOrContext: Context) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Context>>;\n\nasync function baseHandler<R extends IncomingMessage, RResponse extends ServerResponse, T, Q extends ParsedQueryParameters = any, M extends string = string>(\n responseExecutor: (responseOrContext: RResponse, responseConfig: ResponseConfig) => Promise<void>,\n finalExecutor: (responseOrContext: RResponse) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, RResponse>>;\n\n// eslint-disable-next-line sonarjs/cognitive-complexity,func-style\nasync function baseHandler<R extends { method: string; url: string }, RResponse, T, Q extends ParsedQueryParameters = any, M extends string = string>(\n responseExecutor: (responseOrContext: RResponse, responseConfig: ResponseConfig) => Promise<RResponse>,\n finalExecutor: (responseOrContext: RResponse) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, RResponse>> {\n try {\n validateAdapterMethods(adapter);\n } catch (error_: any) {\n const error = error_ as HttpError;\n\n throw new ApiError(error.statusCode, error.message);\n }\n\n await adapter.init?.();\n\n const config = {\n formatResourceId,\n pagination: {\n perPage: 20,\n },\n ...options,\n };\n\n const routeNames = await adapter.mapModelsToRouteNames?.();\n const modelRoutes: { [key in M]?: string } = {};\n\n adapter.getModels().forEach((modelName) => {\n modelRoutes[modelName as M] = config.models?.[modelName as M]?.name ?? routeNames?.[modelName] ?? modelName;\n });\n\n return async (request, responseOrContext) => {\n const { modelName, resourceName } = getResourceNameFromUrl(request.url, modelRoutes as { [key in M]: string });\n\n if (!resourceName) {\n if (process.env.NODE_ENV === \"development\") {\n const mappedModels = await adapter.mapModelsToRouteNames?.();\n\n if (typeof mappedModels === \"object\") {\n throw createHttpError(404, `Resource not found, possible models: ${Object.values(mappedModels).join(\", \")}`);\n }\n }\n\n throw createHttpError(404, `Resource not found: ${request.url}`);\n }\n\n const { resourceId, routeType } = getRouteType(request.method, request.url, resourceName);\n\n if (routeType === null) {\n throw createHttpError(404, `Route not found: ${request.url}`);\n }\n\n const modelConfig = options?.models?.[modelName as M];\n\n const accessibleRoutes = getAccessibleRoutes(modelConfig?.only, modelConfig?.exclude, options?.exposeStrategy ?? \"all\");\n\n if (!accessibleRoutes.includes(routeType)) {\n throw createHttpError(404, `Route not found: ${request.url}`);\n }\n\n try {\n const resourceIdFormatted = modelConfig?.formatResourceId?.(resourceId as string) ?? config.formatResourceId(resourceId as string);\n\n await adapter.connect?.();\n\n const parsedQuery = parseQuery(request.url);\n const parameters: HandlerParameters<T, Q> = {\n adapter,\n query: adapter.parseQuery(modelName as M, parsedQuery),\n resourceName: modelName,\n };\n\n try {\n let responseConfig: ResponseConfig;\n\n switch (routeType) {\n case RouteType.READ_ONE: {\n responseConfig = await (config.handlers?.get ?? readHandler)<T, Q>({\n ...parameters,\n resourceId: resourceIdFormatted,\n });\n break;\n }\n case RouteType.READ_ALL: {\n responseConfig = await (config.handlers?.list ?? listHandler)<T, Q>({\n ...parameters,\n pagination: config.pagination,\n query: {\n ...parameters.query,\n limit: parsedQuery.limit ? Number(parsedQuery.limit) : undefined,\n page: parsedQuery.page ? Number(parsedQuery.page) : undefined,\n },\n });\n break;\n }\n case RouteType.CREATE: {\n responseConfig = await (config.handlers?.create ?? createHandler)<T, Q, R>({\n ...parameters,\n request: request as R & { body: Record<string, any> },\n });\n break;\n }\n case RouteType.UPDATE: {\n responseConfig = await (config.handlers?.update ?? updateHandler)<T, Q, R>({\n ...parameters,\n request: request as R & { body: Partial<T> },\n resourceId: resourceIdFormatted,\n });\n break;\n }\n case RouteType.DELETE: {\n responseConfig = await (config.handlers?.delete ?? deleteHandler)<T, Q>({\n ...parameters,\n resourceId: resourceIdFormatted,\n });\n break;\n }\n default: {\n responseConfig = {\n data: \"Method not found\",\n status: 404,\n };\n }\n }\n\n await responseExecutor(responseOrContext, responseConfig);\n } catch (error: any) {\n if (adapter.handleError && !(error instanceof ApiError)) {\n adapter.handleError(error);\n } else {\n throw error;\n }\n }\n } finally {\n await adapter.disconnect?.();\n\n await finalExecutor(responseOrContext);\n }\n };\n}\n\nexport default baseHandler;\n","import type { HandlerParameters } from \"../types.d\";\n\nconst createHandler: Handler = async ({ adapter, query, request, resourceName }) => {\n const resources = await adapter.create(resourceName, request.body, query);\n\n return {\n data: resources,\n status: 201,\n };\n};\n\nexport type Handler = <T, Q, Request>(\n parameters: HandlerParameters<T, Q> & { request: Request & { body: Record<string, any> } },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default createHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst deleteHandler: Handler = async ({ adapter, query, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource === \"object\") {\n const deletedResource = await adapter.delete(resourceName, resourceId, query);\n\n return {\n data: deletedResource,\n status: 200,\n };\n }\n\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n};\n\nexport type Handler = <T, Q>(\n parameters: UniqueResourceHandlerParameters<T, Q>,\n) => Promise<{\n data: any;\n status: number;\n}>;\nexport default deleteHandler;\n","import { paginate } from \"@visulima/pagination\";\n\nimport type { HandlerParameters, PaginationConfig, ParsedQueryParameters } from \"../types.d\";\n\ninterface PaginationOptions {\n page: number;\n perPage: number;\n}\n\nconst listHandler: Handler = async ({ adapter, pagination, query, resourceName }) => {\n let isPaginated = false;\n let paginationOptions: PaginationOptions | undefined;\n\n if (query.page !== undefined) {\n if (query.page <= 0) {\n throw new Error(\"page query must be a strictly positive number\");\n }\n\n paginationOptions = {\n page: query.page,\n perPage: query.limit ?? pagination.perPage,\n };\n }\n\n if (paginationOptions) {\n isPaginated = true;\n\n // eslint-disable-next-line no-param-reassign\n query.skip = (paginationOptions.page - 1) * paginationOptions.perPage;\n // eslint-disable-next-line no-param-reassign\n query.limit = paginationOptions.perPage;\n }\n\n const resources = await adapter.getAll(resourceName, query);\n\n if (isPaginated) {\n const { page, total } = await adapter.getPaginationData(resourceName, query);\n\n const paginator = paginate(page, (paginationOptions as PaginationOptions).perPage, total, resources);\n\n return {\n data: paginator.toJSON(),\n status: 200,\n };\n }\n\n return {\n data: resources,\n status: 200,\n };\n};\n\nexport type Handler = <T, Q extends ParsedQueryParameters>(\n parameters: HandlerParameters<T, Q> & { pagination: PaginationConfig },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default listHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst readHandler: Handler = async ({ adapter, query, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource !== \"object\") {\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n }\n\n return {\n data: resource,\n status: 200,\n };\n};\n\nexport type Handler = <T, Q>(\n parameters: UniqueResourceHandlerParameters<T, Q>,\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default readHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst updateHandler: Handler = async ({ adapter, query, request, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource === \"object\") {\n const updatedResource = await adapter.update(resourceName, resourceId, request.body, query);\n\n return {\n data: updatedResource,\n status: 201,\n };\n }\n\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n};\n\nexport type Handler = <T, Q, Request>(\n parameters: UniqueResourceHandlerParameters<T, Q> & { request: Request & { body: Partial<T> } },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default updateHandler;\n","// eslint-disable-next-line no-restricted-imports\nimport set from \"lodash.set\";\nimport { parse } from \"node:url\";\n\nimport type { OrderByField, ParsedQueryParameters, RecursiveField, WhereField } from \"./types.d\";\n\nconst parseRecursive = (select: string): RecursiveField => {\n const selectFields: RecursiveField = {};\n\n const fields = select.split(\",\");\n\n fields.forEach((field) => {\n set(selectFields, field, true);\n });\n\n return selectFields;\n};\n\nconst parseWhere = (where: string): WhereField => {\n const whereObject = JSON.parse(where);\n const parsed: WhereField = {};\n\n Object.keys(whereObject).forEach((key) => {\n set(parsed, key, whereObject[key]);\n });\n\n return parsed;\n};\n\nconst parseOrderBy = (orderBy: string): OrderByField => {\n const parsed: OrderByField = {};\n const orderByObject = JSON.parse(orderBy);\n\n if (Object.keys(orderByObject).length > 0) {\n const key = Object.keys(orderByObject)[0] as string;\n\n if (orderByObject[key as keyof typeof orderByObject] === \"$asc\" || orderByObject[key as keyof typeof orderByObject] === \"$desc\") {\n parsed[key] = orderByObject[key as keyof typeof orderByObject];\n }\n }\n\n if (Object.keys(parsed).length !== 1) {\n throw new Error(\"orderBy needs to be an object with exactly 1 property with either $asc or $desc value\");\n }\n\n return parsed;\n};\n\n// eslint-disable-next-line sonarjs/cognitive-complexity\nconst parseQuery = (queryString?: string): ParsedQueryParameters => {\n if (queryString) {\n const { query } = parse(queryString, true);\n const parsedQuery: ParsedQueryParameters = {};\n\n if (query[\"select\"]) {\n parsedQuery.select = parseRecursive(query[\"select\"] as string);\n }\n\n if (query[\"include\"]) {\n parsedQuery.include = parseRecursive(query[\"include\"] as string);\n }\n\n if (query[\"where\"]) {\n parsedQuery.where = parseWhere(query[\"where\"] as string);\n }\n\n if (query[\"orderBy\"]) {\n parsedQuery.orderBy = parseOrderBy(query[\"orderBy\"] as string);\n }\n\n if (query[\"limit\"] !== undefined) {\n parsedQuery.limit = Number.isFinite(+query[\"limit\"]) ? +query[\"limit\"] : undefined;\n }\n if (query[\"skip\"] !== undefined) {\n parsedQuery.skip = Number.isFinite(+query[\"skip\"]) ? +query[\"skip\"] : undefined;\n }\n\n if (query[\"distinct\"]) {\n parsedQuery.distinct = query[\"distinct\"] as string;\n }\n\n if (query[\"page\"]) {\n parsedQuery.page = Number.isFinite(+query[\"page\"]) ? +query[\"page\"] : undefined;\n }\n\n return {\n originalQuery: query,\n ...parsedQuery,\n };\n }\n\n return {};\n};\n\nexport default parseQuery;\n","const formatResourceId = (resourceId: string): number | string => (Number.isSafeInteger(+resourceId) ? +resourceId : resourceId);\n\nexport default formatResourceId;\n","export const ensureCamelCase = (string_: string): string => `${string_.charAt(0).toLowerCase()}${string_.slice(1)}`;\n\nexport const getResourceNameFromUrl = <M extends string = string>(\n url: string,\n models: { [key in M]: string },\n): {\n modelName: string;\n resourceName: string;\n} => {\n // Exclude the query params from the path\n const realPath = url.split(\"?\")[0];\n\n if (realPath === undefined) {\n throw new TypeError(\"Path is undefined\");\n }\n\n const modelName = (Object.keys(models) as M[]).find((name) => {\n const routeName = models[name];\n const camelCaseModel = ensureCamelCase(routeName);\n\n // eslint-disable-next-line @rushstack/security/no-unsafe-regexp,security/detect-non-literal-regexp\n return new RegExp(`(${routeName}|${camelCaseModel}$)|(${routeName}|${camelCaseModel}/)`, \"g\").test(realPath);\n });\n\n if (modelName === undefined) {\n throw new Error(`Couldn't find model name for url ${url}`);\n }\n\n return {\n modelName,\n resourceName: models[modelName],\n };\n};\n","import { match } from \"path-to-regexp\";\n\nimport { RouteType } from \"../types.d\";\n\ninterface PathMatch {\n id: string;\n}\n\nconst getRouteType: (method: string, url: string, resourceName: string) => GetRouteType = (method, url, resourceName) => {\n // Exclude the query params from the path\n const realPath = url.split(\"?\")[0];\n\n if (realPath === undefined) {\n throw new TypeError(\"Path is undefined\");\n }\n\n if (!realPath.includes(`/${resourceName}`)) {\n throw new Error(`invalid resource name '${resourceName}' for route '${realPath}'`);\n }\n\n const entityMatcher = match<PathMatch>([`/(.*)/${resourceName}`, `/(.*)/${resourceName}/:id`], { decode: decodeURIComponent });\n const simpleMatcher = match(`/(.*)/${resourceName}`, {\n decode: decodeURIComponent,\n });\n\n switch (method) {\n case \"GET\": {\n const pathMatch = entityMatcher(realPath);\n\n // If we got a /something after the resource name, we are reading 1 entity\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.READ_ONE,\n };\n }\n\n return {\n routeType: RouteType.READ_ALL,\n };\n }\n case \"POST\": {\n const pathMatch = simpleMatcher(realPath);\n\n if (pathMatch) {\n return {\n routeType: RouteType.CREATE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n case \"PUT\":\n case \"PATCH\": {\n const pathMatch = entityMatcher(realPath);\n\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.UPDATE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n case \"DELETE\": {\n const pathMatch = entityMatcher(realPath);\n\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.DELETE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n default: {\n return {\n routeType: null,\n };\n }\n }\n};\n\nexport interface GetRouteType {\n resourceId?: string;\n routeType: RouteType | null;\n}\n\nexport default getRouteType;\n","import createHttpError from \"http-errors\";\n\nimport type { Adapter } from \"../types.d\";\n\nconst adapterMethods = [\"create\", \"delete\", \"getAll\", \"getOne\", \"parseQuery\", \"update\", \"getPaginationData\", \"getModels\"];\n\nconst validateAdapterMethods = <T, Q>(adapter: Adapter<T, Q>): void => {\n adapterMethods.forEach((method) => {\n if (!adapter[method as keyof Adapter<T, Q>]) {\n throw createHttpError(500, `Adapter must implement the \"${method}\" method.`);\n }\n });\n};\n\nexport default validateAdapterMethods;\n","import baseHandler from \"../../../base-crud-handler\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, ParsedQueryParameters } from \"../../../types.d\";\n\nconst handler = async <T, R extends Request, Context, Q extends ParsedQueryParameters = any, M extends string = string>(\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Context>> =>\n await baseHandler<R, Context, T, Q, M>(\n async (_, responseConfig) =>\n new Response(JSON.stringify(responseConfig.data), {\n headers: {\n \"content-type\": \"application/json; charset=utf-8\",\n },\n status: responseConfig.status,\n }),\n async () => {},\n adapter,\n options,\n );\n\nexport default handler;\n","import type { NextApiRequest, NextApiResponse } from \"next\";\n\nimport baseHandler from \"../../../base-crud-handler\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, ParsedQueryParameters } from \"../../../types.d\";\n\nconst handler = async <\n T,\n Q extends ParsedQueryParameters = any,\n R extends NextApiRequest = NextApiRequest,\n Response extends NextApiResponse = NextApiResponse,\n M extends string = string,\n>(\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Response>> =>\n await baseHandler<R, Response, T, Q, M>(\n async (response, responseConfig) => {\n response.status(responseConfig.status).send(responseConfig.data);\n },\n async (response) => {\n response.end();\n },\n adapter,\n options,\n );\n\nexport default handler;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/base-crud-handler.ts","../../src/handler/create.ts","../../src/handler/delete.ts","../../src/handler/list.ts","../../src/handler/read.ts","../../src/handler/update.ts","../../src/query-parser.ts","../../src/utils/format-resource-id.ts","../../src/utils/get-resource-name-from-url.ts","../../src/utils/get-route-type.ts","../../src/utils/validate-adapter-methods.ts","../../src/next/api/edge/index.ts","../../src/next/api/node/index.ts"],"names":["createHttpError","ApiError","createHandler","adapter","query","request","resourceName","create_default","deleteHandler","resourceId","delete_default","paginate","listHandler","pagination","isPaginated","paginationOptions","resources","page","total","list_default","readHandler","resource","read_default","updateHandler","update_default","URL","set","parseRecursive","select","selectFields","field","parseWhere","where","whereObject","parsed","key","parseOrderBy","orderBy","orderByObject","parseQuery","url","searchParams","parsedQuery","query_parser_default","formatResourceId","format_resource_id_default","ensureCamelCase","string_","getResourceNameFromUrl","models","realPath","modelName","name","routeName","camelCaseModel","match","getRouteType","method","entityMatcher","simpleMatcher","pathMatch","get_route_type_default","adapterMethods","validateAdapterMethods","validate_adapter_methods_default","baseHandler","responseExecutor","finalExecutor","options","error_","error","config","routeNames","modelRoutes","responseOrContext","routeType","modelConfig","get_accessible_routes_default","resourceIdFormatted","parameters","responseConfig","base_crud_handler_default","handler","_","edge_default","response","node_default"],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { HttpError } from \"http-errors\";\nimport createHttpError from \"http-errors\";\n// eslint-disable-next-line import/no-extraneous-dependencies\nimport { ApiError } from \"next/dist/server/api-utils\";\n\nimport createHandler from \"./handler/create\";\nimport deleteHandler from \"./handler/delete\";\nimport listHandler from \"./handler/list\";\nimport readHandler from \"./handler/read\";\nimport updateHandler from \"./handler/update\";\nimport parseQuery from \"./query-parser\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, HandlerParameters, ParsedQueryParameters } from \"./types.d\";\nimport { RouteType } from \"./types.d\";\nimport formatResourceId from \"./utils/format-resource-id\";\nimport getAccessibleRoutes from \"./utils/get-accessible-routes\";\nimport { getResourceNameFromUrl } from \"./utils/get-resource-name-from-url\";\nimport getRouteType from \"./utils/get-route-type\";\nimport validateAdapterMethods from \"./utils/validate-adapter-methods\";\n\ninterface ResponseConfig {\n data: any;\n status: number;\n}\n\nasync function baseHandler<R extends Request, Context, T, Q extends ParsedQueryParameters = any, M extends string = string>(\n responseExecutor: (responseOrContext: Context, responseConfig: ResponseConfig) => Promise<Response>,\n finalExecutor: (responseOrContext: Context) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Context>>;\n\nasync function baseHandler<R extends IncomingMessage, RResponse extends ServerResponse, T, Q extends ParsedQueryParameters = any, M extends string = string>(\n responseExecutor: (responseOrContext: RResponse, responseConfig: ResponseConfig) => Promise<void>,\n finalExecutor: (responseOrContext: RResponse) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, RResponse>>;\n\n// eslint-disable-next-line sonarjs/cognitive-complexity,func-style\nasync function baseHandler<\n R extends { headers: { host?: string }; method: string; url: string },\n RResponse,\n T,\n Q extends ParsedQueryParameters = any,\n M extends string = string,\n>(\n responseExecutor: (responseOrContext: RResponse, responseConfig: ResponseConfig) => Promise<RResponse>,\n finalExecutor: (responseOrContext: RResponse) => Promise<void>,\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, RResponse>> {\n try {\n validateAdapterMethods(adapter);\n } catch (error_: any) {\n const error = error_ as HttpError;\n\n throw new ApiError(error.statusCode, error.message);\n }\n\n await adapter.init?.();\n\n const config = {\n formatResourceId,\n pagination: {\n perPage: 20,\n },\n ...options,\n };\n\n const routeNames = await adapter.mapModelsToRouteNames?.();\n const modelRoutes: { [key in M]?: string } = {};\n\n adapter.getModels().forEach((modelName) => {\n modelRoutes[modelName as M] = config.models?.[modelName as M]?.name ?? routeNames?.[modelName] ?? modelName;\n });\n\n return async (request, responseOrContext) => {\n const { modelName, resourceName } = getResourceNameFromUrl(request.url, modelRoutes as { [key in M]: string });\n\n if (!resourceName) {\n if (process.env.NODE_ENV === \"development\") {\n const mappedModels = await adapter.mapModelsToRouteNames?.();\n\n if (typeof mappedModels === \"object\") {\n throw createHttpError(404, `Resource not found, possible models: ${Object.values(mappedModels).join(\", \")}`);\n }\n }\n\n throw createHttpError(404, `Resource not found: ${request.url}`);\n }\n\n const { resourceId, routeType } = getRouteType(request.method, request.url, resourceName);\n\n if (routeType === null) {\n throw createHttpError(404, `Route not found: ${request.url}`);\n }\n\n const modelConfig = options?.models?.[modelName as M];\n\n const accessibleRoutes = getAccessibleRoutes(modelConfig?.only, modelConfig?.exclude, options?.exposeStrategy ?? \"all\");\n\n if (!accessibleRoutes.includes(routeType)) {\n throw createHttpError(404, `Route not found: ${request.url}`);\n }\n\n try {\n const resourceIdFormatted = modelConfig?.formatResourceId?.(resourceId as string) ?? config.formatResourceId(resourceId as string);\n\n await adapter.connect?.();\n\n const parsedQuery = parseQuery(`https://${request.headers.host?.replace(/\\/$/, \"\")}/${request.url}`);\n const parameters: HandlerParameters<T, Q> = {\n adapter,\n query: adapter.parseQuery(modelName as M, parsedQuery),\n resourceName: modelName,\n };\n\n try {\n let responseConfig: ResponseConfig;\n\n switch (routeType) {\n case RouteType.READ_ONE: {\n responseConfig = await (config.handlers?.get ?? readHandler)<T, Q>({\n ...parameters,\n resourceId: resourceIdFormatted,\n });\n break;\n }\n case RouteType.READ_ALL: {\n responseConfig = await (config.handlers?.list ?? listHandler)<T, Q>({\n ...parameters,\n pagination: config.pagination,\n query: {\n ...parameters.query,\n limit: parsedQuery.limit ? Number(parsedQuery.limit) : undefined,\n page: parsedQuery.page ? Number(parsedQuery.page) : undefined,\n },\n });\n break;\n }\n case RouteType.CREATE: {\n responseConfig = await (config.handlers?.create ?? createHandler)<T, Q, R>({\n ...parameters,\n request: request as R & { body: Record<string, any> },\n });\n break;\n }\n case RouteType.UPDATE: {\n responseConfig = await (config.handlers?.update ?? updateHandler)<T, Q, R>({\n ...parameters,\n request: request as R & { body: Partial<T> },\n resourceId: resourceIdFormatted,\n });\n break;\n }\n case RouteType.DELETE: {\n responseConfig = await (config.handlers?.delete ?? deleteHandler)<T, Q>({\n ...parameters,\n resourceId: resourceIdFormatted,\n });\n break;\n }\n default: {\n responseConfig = {\n data: \"Method not found\",\n status: 404,\n };\n }\n }\n\n await responseExecutor(responseOrContext, responseConfig);\n } catch (error: any) {\n if (adapter.handleError && !(error instanceof ApiError)) {\n adapter.handleError(error);\n } else {\n throw error;\n }\n }\n } finally {\n await adapter.disconnect?.();\n\n await finalExecutor(responseOrContext);\n }\n };\n}\n\nexport default baseHandler;\n","import type { HandlerParameters } from \"../types.d\";\n\nconst createHandler: Handler = async ({ adapter, query, request, resourceName }) => {\n const resources = await adapter.create(resourceName, request.body, query);\n\n return {\n data: resources,\n status: 201,\n };\n};\n\nexport type Handler = <T, Q, Request>(\n parameters: HandlerParameters<T, Q> & { request: Request & { body: Record<string, any> } },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default createHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst deleteHandler: Handler = async ({ adapter, query, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource === \"object\") {\n const deletedResource = await adapter.delete(resourceName, resourceId, query);\n\n return {\n data: deletedResource,\n status: 200,\n };\n }\n\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n};\n\nexport type Handler = <T, Q>(\n parameters: UniqueResourceHandlerParameters<T, Q>,\n) => Promise<{\n data: any;\n status: number;\n}>;\nexport default deleteHandler;\n","import { paginate } from \"@visulima/pagination\";\n\nimport type { HandlerParameters, PaginationConfig, ParsedQueryParameters } from \"../types.d\";\n\ninterface PaginationOptions {\n page: number;\n perPage: number;\n}\n\nconst listHandler: Handler = async ({ adapter, pagination, query, resourceName }) => {\n let isPaginated = false;\n let paginationOptions: PaginationOptions | undefined;\n\n if (query.page !== undefined) {\n if (query.page <= 0) {\n throw new Error(\"page query must be a strictly positive number\");\n }\n\n paginationOptions = {\n page: query.page,\n perPage: query.limit ?? pagination.perPage,\n };\n }\n\n if (paginationOptions) {\n isPaginated = true;\n\n // eslint-disable-next-line no-param-reassign\n query.skip = (paginationOptions.page - 1) * paginationOptions.perPage;\n // eslint-disable-next-line no-param-reassign\n query.limit = paginationOptions.perPage;\n }\n\n const resources = await adapter.getAll(resourceName, query);\n\n if (isPaginated) {\n const { page, total } = await adapter.getPaginationData(resourceName, query);\n\n const paginator = paginate(page, (paginationOptions as PaginationOptions).perPage, total, resources);\n\n return {\n data: paginator.toJSON(),\n status: 200,\n };\n }\n\n return {\n data: resources,\n status: 200,\n };\n};\n\nexport type Handler = <T, Q extends ParsedQueryParameters>(\n parameters: HandlerParameters<T, Q> & { pagination: PaginationConfig },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default listHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst readHandler: Handler = async ({ adapter, query, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource !== \"object\") {\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n }\n\n return {\n data: resource,\n status: 200,\n };\n};\n\nexport type Handler = <T, Q>(\n parameters: UniqueResourceHandlerParameters<T, Q>,\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default readHandler;\n","import createHttpError from \"http-errors\";\n\nimport type { UniqueResourceHandlerParameters } from \"../types.d\";\n\nconst updateHandler: Handler = async ({ adapter, query, request, resourceId, resourceName }) => {\n const resource = await adapter.getOne(resourceName, resourceId, query);\n\n if (typeof resource === \"object\") {\n const updatedResource = await adapter.update(resourceName, resourceId, request.body, query);\n\n return {\n data: updatedResource,\n status: 201,\n };\n }\n\n throw createHttpError(404, `${resourceName} ${resourceId} not found`);\n};\n\nexport type Handler = <T, Q, Request>(\n parameters: UniqueResourceHandlerParameters<T, Q> & { request: Request & { body: Partial<T> } },\n) => Promise<{\n data: any;\n status: number;\n}>;\n\nexport default updateHandler;\n","import { URL } from \"node:url\";\n// eslint-disable-next-line no-restricted-imports\nimport set from \"lodash.set\";\n\nimport type { OrderByField, ParsedQueryParameters, RecursiveField, WhereField } from \"./types.d\";\n\nconst parseRecursive = (select: string): RecursiveField => {\n const selectFields: RecursiveField = {};\n\n const fields = select.split(\",\");\n\n fields.forEach((field) => {\n set(selectFields, field, true);\n });\n\n return selectFields;\n};\n\nconst parseWhere = (where: string): WhereField => {\n const whereObject = JSON.parse(where);\n const parsed: WhereField = {};\n\n Object.keys(whereObject).forEach((key) => {\n set(parsed, key, whereObject[key]);\n });\n\n return parsed;\n};\n\nconst parseOrderBy = (orderBy: string): OrderByField => {\n const parsed: OrderByField = {};\n const orderByObject = JSON.parse(orderBy);\n\n if (Object.keys(orderByObject).length > 0) {\n const key = Object.keys(orderByObject)[0] as string;\n\n if (orderByObject[key as keyof typeof orderByObject] === \"$asc\" || orderByObject[key as keyof typeof orderByObject] === \"$desc\") {\n parsed[key] = orderByObject[key as keyof typeof orderByObject];\n }\n }\n\n if (Object.keys(parsed).length !== 1) {\n throw new Error(\"orderBy needs to be an object with exactly 1 property with either $asc or $desc value\");\n }\n\n return parsed;\n};\n\n// eslint-disable-next-line sonarjs/cognitive-complexity\nconst parseQuery = (url?: string): ParsedQueryParameters => {\n if (url) {\n const { searchParams } = new URL(url);\n const parsedQuery: ParsedQueryParameters = {};\n\n if (searchParams.get(\"select\")) {\n parsedQuery.select = parseRecursive(searchParams.get(\"select\") as string);\n }\n\n if (searchParams.get(\"include\")) {\n parsedQuery.include = parseRecursive(searchParams.get(\"include\") as string);\n }\n\n if (searchParams.get(\"where\")) {\n parsedQuery.where = parseWhere(searchParams.get(\"where\") as string);\n }\n\n if (searchParams.get(\"orderBy\")) {\n parsedQuery.orderBy = parseOrderBy(searchParams.get(\"orderBy\") as string);\n }\n\n if (searchParams.has(\"limit\")) {\n parsedQuery.limit = Number.isFinite(+(searchParams.get(\"limit\") as string)) ? +(searchParams.get(\"limit\") as string) : undefined;\n }\n\n if (searchParams.has(\"skip\")) {\n parsedQuery.skip = Number.isFinite(+(searchParams.get(\"skip\") as string)) ? +(searchParams.get(\"skip\") as string) : undefined;\n }\n\n if (searchParams.get(\"distinct\")) {\n parsedQuery.distinct = searchParams.get(\"distinct\") as string;\n }\n\n if (searchParams.get(\"page\")) {\n parsedQuery.page = Number.isFinite(+(searchParams.get(\"page\") as string)) ? +(searchParams.get(\"page\") as string) : undefined;\n }\n\n return {\n originalQuery: Object.fromEntries(searchParams.entries()),\n ...parsedQuery,\n };\n }\n\n return {};\n};\n\nexport default parseQuery;\n","const formatResourceId = (resourceId: string): number | string => (Number.isSafeInteger(+resourceId) ? +resourceId : resourceId);\n\nexport default formatResourceId;\n","export const ensureCamelCase = (string_: string): string => `${string_.charAt(0).toLowerCase()}${string_.slice(1)}`;\n\nexport const getResourceNameFromUrl = <M extends string = string>(\n url: string,\n models: { [key in M]: string },\n): {\n modelName: string;\n resourceName: string;\n} => {\n // Exclude the query params from the path\n const realPath = url.split(\"?\")[0];\n\n if (realPath === undefined) {\n throw new TypeError(\"Path is undefined\");\n }\n\n const modelName = (Object.keys(models) as M[]).find((name) => {\n const routeName = models[name];\n const camelCaseModel = ensureCamelCase(routeName);\n\n // eslint-disable-next-line @rushstack/security/no-unsafe-regexp,security/detect-non-literal-regexp\n return new RegExp(`(${routeName}|${camelCaseModel}$)|(${routeName}|${camelCaseModel}/)`, \"g\").test(realPath);\n });\n\n if (modelName === undefined) {\n throw new Error(`Couldn't find model ${modelName} name for url ${url}`);\n }\n\n return {\n modelName,\n resourceName: models[modelName],\n };\n};\n","import { match } from \"path-to-regexp\";\n\nimport { RouteType } from \"../types.d\";\n\ninterface PathMatch {\n id: string;\n}\n\nconst getRouteType: (method: string, url: string, resourceName: string) => GetRouteType = (method, url, resourceName) => {\n // Exclude the query params from the path\n const realPath = url.split(\"?\")[0];\n\n if (realPath === undefined) {\n throw new TypeError(\"Path is undefined\");\n }\n\n if (!realPath.includes(`/${resourceName}`)) {\n throw new Error(`invalid resource name '${resourceName}' for route '${realPath}'`);\n }\n\n const entityMatcher = match<PathMatch>([`/(.*)/${resourceName}`, `/(.*)/${resourceName}/:id`], { decode: decodeURIComponent });\n const simpleMatcher = match(`/(.*)/${resourceName}`, {\n decode: decodeURIComponent,\n });\n\n switch (method) {\n case \"GET\": {\n const pathMatch = entityMatcher(realPath);\n\n // If we got a /something after the resource name, we are reading 1 entity\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.READ_ONE,\n };\n }\n\n return {\n routeType: RouteType.READ_ALL,\n };\n }\n case \"POST\": {\n const pathMatch = simpleMatcher(realPath);\n\n if (pathMatch) {\n return {\n routeType: RouteType.CREATE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n case \"PUT\":\n case \"PATCH\": {\n const pathMatch = entityMatcher(realPath);\n\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.UPDATE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n case \"DELETE\": {\n const pathMatch = entityMatcher(realPath);\n\n if (typeof pathMatch === \"object\" && pathMatch.params.id) {\n return {\n resourceId: pathMatch.params.id,\n routeType: RouteType.DELETE,\n };\n }\n\n return {\n routeType: null,\n };\n }\n default: {\n return {\n routeType: null,\n };\n }\n }\n};\n\nexport interface GetRouteType {\n resourceId?: string;\n routeType: RouteType | null;\n}\n\nexport default getRouteType;\n","import createHttpError from \"http-errors\";\n\nimport type { Adapter } from \"../types.d\";\n\nconst adapterMethods = [\"create\", \"delete\", \"getAll\", \"getOne\", \"parseQuery\", \"update\", \"getPaginationData\", \"getModels\"];\n\nconst validateAdapterMethods = <T, Q>(adapter: Adapter<T, Q>): void => {\n adapterMethods.forEach((method) => {\n if (!adapter[method as keyof Adapter<T, Q>]) {\n throw createHttpError(500, `Adapter must implement the \"${method}\" method.`);\n }\n });\n};\n\nexport default validateAdapterMethods;\n","import baseHandler from \"../../../base-crud-handler\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, ParsedQueryParameters } from \"../../../types.d\";\n\nconst handler = async <T, R extends Request, Context, Q extends ParsedQueryParameters = any, M extends string = string>(\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Context>> =>\n await baseHandler<R, Context, T, Q, M>(\n async (_, responseConfig) =>\n new Response(JSON.stringify(responseConfig.data), {\n headers: {\n \"content-type\": \"application/json; charset=utf-8\",\n },\n status: responseConfig.status,\n }),\n async () => {},\n adapter,\n options,\n );\n\nexport default handler;\n","import type { NextApiRequest, NextApiResponse } from \"next\";\n\nimport baseHandler from \"../../../base-crud-handler\";\nimport type { Adapter, ExecuteHandler, HandlerOptions, ParsedQueryParameters } from \"../../../types.d\";\n\nconst handler = async <\n T,\n Q extends ParsedQueryParameters = any,\n R extends NextApiRequest = NextApiRequest,\n Response extends NextApiResponse = NextApiResponse,\n M extends string = string,\n>(\n adapter: Adapter<T, Q>,\n options?: HandlerOptions<M>,\n): Promise<ExecuteHandler<R, Response>> =>\n await baseHandler<R, Response, T, Q, M>(\n async (response, responseConfig) => {\n response.status(responseConfig.status).send(responseConfig.data);\n },\n async (response) => {\n response.end();\n },\n adapter,\n options,\n );\n\nexport default handler;\n"]}
|
|
@@ -133,7 +133,7 @@ type WhereField = Condition & {
|
|
|
133
133
|
|
|
134
134
|
type OrderByOperator = "$asc" | "$desc";
|
|
135
135
|
|
|
136
|
-
type OrderByField = Record<string,
|
|
136
|
+
type OrderByField = Record<string, OrderByOperator>;
|
|
137
137
|
|
|
138
138
|
interface ParsedQueryParameters {
|
|
139
139
|
distinct?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@visulima/crud",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "visulima crud",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"anolilab",
|
|
@@ -70,16 +70,16 @@
|
|
|
70
70
|
"test:watch": "vitest"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@visulima/pagination": "
|
|
74
|
-
"@visulima/prisma-dmmf-transformer": "
|
|
73
|
+
"@visulima/pagination": "3.0.0",
|
|
74
|
+
"@visulima/prisma-dmmf-transformer": "2.0.0",
|
|
75
75
|
"http-errors": "^2.0.0",
|
|
76
76
|
"lodash.set": "^4.3.2",
|
|
77
77
|
"path-to-regexp": "^6.2.1"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
|
-
"@anolilab/eslint-config": "^11.
|
|
81
|
-
"@anolilab/prettier-config": "^5.0.
|
|
82
|
-
"@anolilab/semantic-release-preset": "^6.0.
|
|
80
|
+
"@anolilab/eslint-config": "^11.3.3",
|
|
81
|
+
"@anolilab/prettier-config": "^5.0.3",
|
|
82
|
+
"@anolilab/semantic-release-preset": "^6.0.4",
|
|
83
83
|
"@prisma/client": "4.16.2",
|
|
84
84
|
"@rushstack/eslint-plugin-security": "^0.6.0",
|
|
85
85
|
"@testing-library/react": "^14.0.0",
|
|
@@ -87,31 +87,32 @@
|
|
|
87
87
|
"@types/http-errors": "^2.0.1",
|
|
88
88
|
"@types/json-schema": "7.0.12",
|
|
89
89
|
"@types/lodash.set": "^4.3.7",
|
|
90
|
-
"@types/node": "18.
|
|
91
|
-
"@vitest/coverage-v8": "^0.
|
|
90
|
+
"@types/node": "18.17.1",
|
|
91
|
+
"@vitest/coverage-v8": "^0.34.3",
|
|
92
92
|
"cross-env": "^7.0.3",
|
|
93
|
-
"eslint": "^8.
|
|
93
|
+
"eslint": "^8.48.0",
|
|
94
94
|
"eslint-plugin-etc": "^2.0.3",
|
|
95
95
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
96
|
-
"eslint-plugin-mdx": "^2.
|
|
97
|
-
"eslint-plugin-testing-library": "^
|
|
96
|
+
"eslint-plugin-mdx": "^2.2.0",
|
|
97
|
+
"eslint-plugin-testing-library": "^6.0.1",
|
|
98
98
|
"eslint-plugin-vitest": "^0.2.8",
|
|
99
|
+
"eslint-plugin-vitest-globals": "^1.4.0",
|
|
99
100
|
"next": "^12.0.0 || ^13.0.0",
|
|
100
101
|
"next-test-api-route-handler": "^4.0.0-canary.1",
|
|
101
|
-
"node-mocks-http": "^1.
|
|
102
|
+
"node-mocks-http": "^1.13.0",
|
|
102
103
|
"openapi-types": "^12.1.3",
|
|
103
|
-
"prettier": "^3.0.
|
|
104
|
+
"prettier": "^3.0.2",
|
|
104
105
|
"react": "^18.2.0",
|
|
105
106
|
"react-dom": "^18.2.0",
|
|
106
107
|
"rimraf": "^5.0.1",
|
|
107
|
-
"semantic-release": "^21.
|
|
108
|
+
"semantic-release": "^21.1.1",
|
|
108
109
|
"sort-package-json": "^2.5.1",
|
|
109
|
-
"tsup": "^7.
|
|
110
|
-
"typescript": "^5.
|
|
111
|
-
"vitest": "^0.
|
|
110
|
+
"tsup": "^7.2.0",
|
|
111
|
+
"typescript": "^5.2.2",
|
|
112
|
+
"vitest": "^0.34.3"
|
|
112
113
|
},
|
|
113
114
|
"engines": {
|
|
114
|
-
"node": ">=
|
|
115
|
+
"node": ">=18.* <=20.*"
|
|
115
116
|
},
|
|
116
117
|
"publishConfig": {
|
|
117
118
|
"access": "public",
|