@visulima/crud 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +46 -16
- package/dist/chunk-SH6A4KBC.mjs +28 -0
- package/dist/{chunk-UBXIGP5H.mjs.map → chunk-SH6A4KBC.mjs.map} +1 -1
- package/dist/chunk-ZY3WOLEP.js +28 -0
- package/dist/chunk-ZY3WOLEP.js.map +1 -0
- package/dist/index.d.ts +9 -15
- package/dist/index.js +57 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -34
- package/dist/index.mjs.map +1 -1
- package/dist/next/index.js +10 -281
- package/dist/next/index.js.map +1 -1
- package/dist/next/index.mjs +9 -280
- package/dist/next/index.mjs.map +1 -1
- package/next/package.json +18 -0
- package/package.json +16 -14
- package/dist/chunk-FJWRITBO.js +0 -52
- package/dist/chunk-FJWRITBO.js.map +0 -1
- package/dist/chunk-UBXIGP5H.mjs +0 -52
- package/src/adapter/prisma/index.ts +0 -241
- package/src/adapter/prisma/types.d.ts +0 -46
- package/src/adapter/prisma/utils/models-to-route-names.ts +0 -12
- package/src/adapter/prisma/utils/parse-cursor.ts +0 -26
- package/src/adapter/prisma/utils/parse-order-by.ts +0 -21
- package/src/adapter/prisma/utils/parse-recursive.ts +0 -26
- package/src/adapter/prisma/utils/parse-where.ts +0 -197
- package/src/base-crud-handler.ts +0 -181
- package/src/handler/create.ts +0 -21
- package/src/handler/delete.ts +0 -27
- package/src/handler/list.ts +0 -62
- package/src/handler/read.ts +0 -27
- package/src/handler/update.ts +0 -29
- package/src/index.ts +0 -27
- package/src/next/api/edge/index.ts +0 -23
- package/src/next/api/node/index.ts +0 -27
- package/src/next/index.ts +0 -2
- package/src/query-parser.ts +0 -94
- package/src/swagger/adapter/prisma/index.ts +0 -95
- package/src/swagger/json-schema-parser.ts +0 -456
- package/src/swagger/parameters.ts +0 -83
- package/src/swagger/types.d.ts +0 -53
- package/src/swagger/utils/format-example-ref.ts +0 -4
- package/src/swagger/utils/format-schema-ref.ts +0 -4
- package/src/swagger/utils/get-models-accessible-routes.ts +0 -23
- package/src/swagger/utils/get-swagger-paths.ts +0 -244
- package/src/swagger/utils/get-swagger-tags.ts +0 -13
- package/src/types.d.ts +0 -124
- package/src/utils/format-resource-id.ts +0 -3
- package/src/utils/get-accessible-routes.ts +0 -18
- package/src/utils/get-resource-name-from-url.ts +0 -23
- package/src/utils/get-route-type.ts +0 -99
- package/src/utils/is-primitive.ts +0 -5
- package/src/utils/validate-adapter-methods.ts +0 -15
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
import type { ModelOption, ModelsOptions } from "../../types.d";
|
|
2
|
-
import { RouteType } from "../../types.d";
|
|
3
|
-
import { getQueryParameters } from "../parameters";
|
|
4
|
-
import type { Routes, SwaggerModelsConfig } from "../types.d";
|
|
5
|
-
import formatExampleReference from "./format-example-ref";
|
|
6
|
-
import formatSchemaReference from "./format-schema-ref";
|
|
7
|
-
|
|
8
|
-
interface GenerateSwaggerPathObjectParameters<M extends string> {
|
|
9
|
-
tag: string;
|
|
10
|
-
routeTypes: RouteType[];
|
|
11
|
-
modelsConfig?: SwaggerModelsConfig<M>;
|
|
12
|
-
modelName: M;
|
|
13
|
-
hasId?: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
type HttpMethod = "get" | "post" | "put" | "delete";
|
|
17
|
-
|
|
18
|
-
const generateContentForSchema = (schemaName: string, isArray?: boolean) => {
|
|
19
|
-
if (isArray) {
|
|
20
|
-
return {
|
|
21
|
-
type: "array",
|
|
22
|
-
items: {
|
|
23
|
-
$ref: formatSchemaReference(schemaName),
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
$ref: formatSchemaReference(schemaName),
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const generateSwaggerResponse = (routeType: RouteType, modelName: string): { statusCode: number; content: any } | undefined => {
|
|
34
|
-
if (routeType === RouteType.CREATE) {
|
|
35
|
-
return {
|
|
36
|
-
statusCode: 201,
|
|
37
|
-
content: {
|
|
38
|
-
description: `${modelName} created`,
|
|
39
|
-
content: {
|
|
40
|
-
"application/json": {
|
|
41
|
-
schema: generateContentForSchema(modelName),
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (routeType === RouteType.DELETE) {
|
|
49
|
-
return {
|
|
50
|
-
statusCode: 200,
|
|
51
|
-
content: {
|
|
52
|
-
description: `${modelName} item deleted`,
|
|
53
|
-
content: {
|
|
54
|
-
"application/json": {
|
|
55
|
-
schema: generateContentForSchema(modelName),
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (routeType === RouteType.READ_ALL) {
|
|
63
|
-
return {
|
|
64
|
-
statusCode: 200,
|
|
65
|
-
content: {
|
|
66
|
-
description: `${modelName} list retrieved`,
|
|
67
|
-
content: {
|
|
68
|
-
"application/json": {
|
|
69
|
-
schema: {
|
|
70
|
-
oneOf: [generateContentForSchema(modelName, true), generateContentForSchema(`${modelName}Page`, false)],
|
|
71
|
-
},
|
|
72
|
-
examples: {
|
|
73
|
-
Default: {
|
|
74
|
-
$ref: formatExampleReference(`${modelName}`),
|
|
75
|
-
},
|
|
76
|
-
Pagination: {
|
|
77
|
-
$ref: formatExampleReference(`${modelName}Page`),
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (routeType === RouteType.READ_ONE) {
|
|
87
|
-
return {
|
|
88
|
-
statusCode: 200,
|
|
89
|
-
content: {
|
|
90
|
-
description: `${modelName} item retrieved`,
|
|
91
|
-
content: {
|
|
92
|
-
"application/json": {
|
|
93
|
-
schema: generateContentForSchema(modelName),
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (routeType === RouteType.UPDATE) {
|
|
101
|
-
return {
|
|
102
|
-
statusCode: 200,
|
|
103
|
-
content: {
|
|
104
|
-
description: `${modelName} item updated`,
|
|
105
|
-
content: {
|
|
106
|
-
"application/json": {
|
|
107
|
-
schema: generateContentForSchema(modelName),
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return undefined;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const generateRequestBody = (schemaStartName: string, modelName: string) => {
|
|
118
|
-
return {
|
|
119
|
-
content: {
|
|
120
|
-
"application/json": {
|
|
121
|
-
schema: {
|
|
122
|
-
$ref: formatSchemaReference(`${schemaStartName}${modelName}`),
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
};
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
const getRouteTypeMethod = (routeType: RouteType): HttpMethod => {
|
|
130
|
-
switch (routeType) {
|
|
131
|
-
case RouteType.CREATE: {
|
|
132
|
-
return "post";
|
|
133
|
-
}
|
|
134
|
-
case RouteType.READ_ALL:
|
|
135
|
-
case RouteType.READ_ONE: {
|
|
136
|
-
return "get";
|
|
137
|
-
}
|
|
138
|
-
case RouteType.UPDATE: {
|
|
139
|
-
return "put";
|
|
140
|
-
}
|
|
141
|
-
case RouteType.DELETE: {
|
|
142
|
-
return "delete";
|
|
143
|
-
}
|
|
144
|
-
default: {
|
|
145
|
-
throw new TypeError(`Method for route type ${routeType} was not found.`);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
const generateSwaggerPathObject = <M extends string>({
|
|
151
|
-
tag, routeTypes, modelName, modelsConfig, hasId,
|
|
152
|
-
}: GenerateSwaggerPathObjectParameters<M>) => {
|
|
153
|
-
const methods: { [key: string]: any } = {};
|
|
154
|
-
|
|
155
|
-
routeTypes.forEach((routeType) => {
|
|
156
|
-
if (routeTypes.includes(routeType)) {
|
|
157
|
-
const returnType = modelsConfig?.[modelName]?.routeTypes?.[routeType]?.response?.name ?? modelsConfig?.[modelName]?.type?.name ?? modelName;
|
|
158
|
-
const method: HttpMethod = getRouteTypeMethod(routeType);
|
|
159
|
-
const response = generateSwaggerResponse(routeType, returnType);
|
|
160
|
-
|
|
161
|
-
if (typeof response === "undefined") {
|
|
162
|
-
throw new TypeError(`Route type ${routeType}; response config was not found.`);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
methods[method as HttpMethod] = {
|
|
166
|
-
tags: [tag],
|
|
167
|
-
summary: modelsConfig?.[modelName]?.routeTypes?.[routeType]?.summary,
|
|
168
|
-
parameters: getQueryParameters(routeType).map((queryParameter) => {
|
|
169
|
-
return { ...queryParameter, in: "query" };
|
|
170
|
-
}),
|
|
171
|
-
responses: {
|
|
172
|
-
[response.statusCode]: response.content,
|
|
173
|
-
...modelsConfig?.[modelName]?.routeTypes?.[routeType]?.responses,
|
|
174
|
-
},
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
if (hasId) {
|
|
178
|
-
methods[method as HttpMethod].parameters.push({
|
|
179
|
-
in: "path",
|
|
180
|
-
name: "id",
|
|
181
|
-
description: `ID of the ${modelName}`,
|
|
182
|
-
required: true,
|
|
183
|
-
schema: {
|
|
184
|
-
type: "string",
|
|
185
|
-
},
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (routeType === RouteType.UPDATE || routeType === RouteType.CREATE) {
|
|
190
|
-
if (routeType === RouteType.UPDATE) {
|
|
191
|
-
methods[method as HttpMethod].requestBody = generateRequestBody("Update", returnType);
|
|
192
|
-
} else if (routeType === RouteType.CREATE) {
|
|
193
|
-
methods[method as HttpMethod].requestBody = generateRequestBody("Create", returnType);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
return methods;
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
interface GetSwaggerPathsParameters<M extends string> {
|
|
203
|
-
routes: Routes<M>;
|
|
204
|
-
modelsConfig?: SwaggerModelsConfig<M>;
|
|
205
|
-
models?: ModelsOptions<M>;
|
|
206
|
-
routesMap?: { [key in M]?: string };
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const getSwaggerPaths = <M extends string>({
|
|
210
|
-
routes, models, modelsConfig, routesMap,
|
|
211
|
-
}: GetSwaggerPathsParameters<M>) => Object.keys(routes).reduce((accumulator: { [key: string]: any }, value: string | M) => {
|
|
212
|
-
const routeTypes = routes[value] as RouteType[];
|
|
213
|
-
const resourceName = models?.[value]?.name ? (models[value] as ModelOption).name : routesMap?.[value as M] || value;
|
|
214
|
-
const tag = modelsConfig?.[value]?.tag?.name || value;
|
|
215
|
-
|
|
216
|
-
if (routeTypes.includes(RouteType.CREATE) || routeTypes.includes(RouteType.READ_ALL)) {
|
|
217
|
-
const path = `/${resourceName}`;
|
|
218
|
-
const routeTypesToUse = [RouteType.READ_ALL, RouteType.CREATE].filter((routeType) => routeTypes.includes(routeType));
|
|
219
|
-
|
|
220
|
-
accumulator[path] = generateSwaggerPathObject({
|
|
221
|
-
tag,
|
|
222
|
-
modelName: value as M,
|
|
223
|
-
modelsConfig,
|
|
224
|
-
routeTypes: routeTypesToUse,
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
if (routeTypes.includes(RouteType.READ_ONE) || routeTypes.includes(RouteType.UPDATE) || routeTypes.includes(RouteType.DELETE)) {
|
|
229
|
-
const path = `/${resourceName}/{id}`;
|
|
230
|
-
const routeTypesToUse = [RouteType.READ_ONE, RouteType.UPDATE, RouteType.DELETE].filter((routeType) => routeTypes.includes(routeType));
|
|
231
|
-
|
|
232
|
-
accumulator[path] = generateSwaggerPathObject({
|
|
233
|
-
tag,
|
|
234
|
-
modelName: value as M,
|
|
235
|
-
modelsConfig,
|
|
236
|
-
routeTypes: routeTypesToUse,
|
|
237
|
-
hasId: true,
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
return accumulator;
|
|
242
|
-
}, {});
|
|
243
|
-
|
|
244
|
-
export default getSwaggerPaths;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { ModelsConfig, SwaggerModelsConfig, SwaggerTag } from "../types.d";
|
|
2
|
-
|
|
3
|
-
const getSwaggerTags = <M extends string>(modelNames: M[], modelsConfig?: SwaggerModelsConfig<M>): SwaggerTag[] => modelNames.map((modelName) => {
|
|
4
|
-
if (modelsConfig?.[modelName]?.tag) {
|
|
5
|
-
return (modelsConfig[modelName as M] as ModelsConfig).tag;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return {
|
|
9
|
-
name: modelName,
|
|
10
|
-
};
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
export default getSwaggerTags;
|
package/src/types.d.ts
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import type { Handler as CreateHandler } from "./handler/create";
|
|
2
|
-
import type { Handler as DeleteHandler } from "./handler/delete";
|
|
3
|
-
import type { Handler as ListHandler } from "./handler/list";
|
|
4
|
-
import type { Handler as GetHandler } from "./handler/read";
|
|
5
|
-
import type { Handler as UpdateHandler } from "./handler/update";
|
|
6
|
-
|
|
7
|
-
export enum RouteType {
|
|
8
|
-
CREATE = "CREATE",
|
|
9
|
-
READ_ALL = "READ_ALL",
|
|
10
|
-
READ_ONE = "READ_ONE",
|
|
11
|
-
UPDATE = "UPDATE",
|
|
12
|
-
DELETE = "DELETE",
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export type ModelOption = {
|
|
16
|
-
name?: string
|
|
17
|
-
only?: RouteType[]
|
|
18
|
-
exclude?: RouteType[]
|
|
19
|
-
formatResourceId?: (resourceId: string) => string | number
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type ModelsOptions<M extends string = string> = {
|
|
23
|
-
[key in M]?: ModelOption
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export type HandlerOptions<M extends string = string> = {
|
|
27
|
-
formatResourceId?: (resourceId: string) => string | number;
|
|
28
|
-
models?: ModelsOptions<M>;
|
|
29
|
-
exposeStrategy?: "all" | "none";
|
|
30
|
-
pagination?: PaginationConfig,
|
|
31
|
-
handlers?: {
|
|
32
|
-
create?: CreateHandler;
|
|
33
|
-
delete?: DeleteHandler;
|
|
34
|
-
get?: GetHandler;
|
|
35
|
-
list?: ListHandler;
|
|
36
|
-
update?: UpdateHandler;
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export type PaginationConfig = {
|
|
41
|
-
perPage: number
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export interface HandlerParameters<T, Q> {
|
|
45
|
-
adapter: Adapter<T, Q>;
|
|
46
|
-
query: Q;
|
|
47
|
-
resourceName: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface UniqueResourceHandlerParameters<T, Q> {
|
|
51
|
-
adapter: Adapter<T, Q>;
|
|
52
|
-
query: Q;
|
|
53
|
-
resourceName: string;
|
|
54
|
-
resourceId: string | number;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface Adapter<T, Q, M extends string = string> {
|
|
58
|
-
models?: M[];
|
|
59
|
-
init?: () => Promise<void>;
|
|
60
|
-
parseQuery(resourceName: M, query: ParsedQueryParameters): Q;
|
|
61
|
-
getAll(resourceName: M, query: Q): Promise<T[]>;
|
|
62
|
-
getOne(resourceName: M, resourceId: string | number, query: Q): Promise<T>;
|
|
63
|
-
create(resourceName: M, data: any, query: Q): Promise<T>;
|
|
64
|
-
update(resourceName: M, resourceId: string | number, data: any, query: Q): Promise<T>;
|
|
65
|
-
delete(resourceName: M, resourceId: string | number, query: Q): Promise<T>;
|
|
66
|
-
getPaginationData(resourceName: M, query: Q): Promise<PaginationData>;
|
|
67
|
-
getModels(): M[];
|
|
68
|
-
connect?: () => Promise<void>;
|
|
69
|
-
disconnect?: () => Promise<void>;
|
|
70
|
-
handleError?: (error: Error) => void;
|
|
71
|
-
mapModelsToRouteNames?: () => Promise<{ [key in M]?: string }>;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export type PaginationData = {
|
|
75
|
-
total: number
|
|
76
|
-
pageCount: number
|
|
77
|
-
page: number
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export type RecursiveField = {
|
|
81
|
-
[key: string]: boolean | TRecursiveField;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
export type WhereOperator = "$eq" | "$neq" | "$in" | "$notin" | "$lt" | "$lte" | "$gt" | "$gte" | "$cont" | "$starts" | "$ends" | "$isnull";
|
|
85
|
-
|
|
86
|
-
export type SearchCondition = string | boolean | number | Date | null;
|
|
87
|
-
|
|
88
|
-
export type WhereCondition = {
|
|
89
|
-
[key in TWhereOperator]?: TSearchCondition;
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
export type Condition = {
|
|
93
|
-
[key: string]: TSearchCondition | TWhereCondition | TCondition;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
export type WhereField = Condition & {
|
|
97
|
-
$and?: TCondition | TCondition[];
|
|
98
|
-
$or?: TCondition | TCondition[];
|
|
99
|
-
$not?: TCondition | TCondition[];
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
export type OrderByOperator = "$asc" | "$desc";
|
|
103
|
-
|
|
104
|
-
export type OrderByField = {
|
|
105
|
-
[key: string]: TOrderByOperator;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
export interface ParsedQueryParameters {
|
|
109
|
-
select?: RecursiveField;
|
|
110
|
-
include?: RecursiveField;
|
|
111
|
-
where?: WhereField;
|
|
112
|
-
orderBy?: OrderByField;
|
|
113
|
-
limit?: number;
|
|
114
|
-
skip?: number;
|
|
115
|
-
distinct?: string;
|
|
116
|
-
page?: number;
|
|
117
|
-
originalQuery?: {
|
|
118
|
-
[key: string]: any;
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export interface ExecuteHandler<Request, Response> {
|
|
123
|
-
(request: Request, response: Response): Promise<void>;
|
|
124
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { RouteType } from "../types.d";
|
|
2
|
-
|
|
3
|
-
const getAccessibleRoutes = (only?: RouteType[], exclude?: RouteType[], defaultExposeStrategy: "all" | "none" = "all"): RouteType[] => {
|
|
4
|
-
// eslint-disable-next-line max-len
|
|
5
|
-
let accessibleRoutes: RouteType[] = defaultExposeStrategy === "none" ? [] : [RouteType.READ_ALL, RouteType.READ_ONE, RouteType.UPDATE, RouteType.DELETE, RouteType.CREATE];
|
|
6
|
-
|
|
7
|
-
if (Array.isArray(only)) {
|
|
8
|
-
accessibleRoutes = only;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
if (exclude?.length) {
|
|
12
|
-
accessibleRoutes = accessibleRoutes.filter((element) => !exclude.includes(element));
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return accessibleRoutes;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export default getAccessibleRoutes;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export const ensureCamelCase = (string_: string) => `${string_.charAt(0).toLowerCase()}${string_.slice(1)}`;
|
|
2
|
-
|
|
3
|
-
export const getResourceNameFromUrl = <M extends string = string>(url: string, models: { [key in M]?: string }) => {
|
|
4
|
-
// Exclude the query params from the path
|
|
5
|
-
const realPath = url.split("?")[0];
|
|
6
|
-
|
|
7
|
-
if (typeof realPath === "undefined") {
|
|
8
|
-
throw new TypeError("Path is undefined");
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const modelName = (Object.keys(models) as M[]).find((name) => {
|
|
12
|
-
const routeName = models[name] as string;
|
|
13
|
-
const camelCaseModel = ensureCamelCase(routeName);
|
|
14
|
-
|
|
15
|
-
// eslint-disable-next-line @rushstack/security/no-unsafe-regexp
|
|
16
|
-
return new RegExp(`(${routeName}|${camelCaseModel}$)|(${routeName}|${camelCaseModel}/)`, "g").test(realPath);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
modelName,
|
|
21
|
-
resourceName: models[modelName] as string,
|
|
22
|
-
};
|
|
23
|
-
};
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { match } from "path-to-regexp";
|
|
2
|
-
|
|
3
|
-
import { RouteType } from "../types.d";
|
|
4
|
-
|
|
5
|
-
type PathMatch = { id: string };
|
|
6
|
-
|
|
7
|
-
const getRouteType: (
|
|
8
|
-
method: string,
|
|
9
|
-
url: string,
|
|
10
|
-
resourceName: string,
|
|
11
|
-
) => GetRouteType = (method, url, resourceName) => {
|
|
12
|
-
// Exclude the query params from the path
|
|
13
|
-
const realPath = url.split("?")[0];
|
|
14
|
-
|
|
15
|
-
if (typeof realPath === "undefined") {
|
|
16
|
-
throw new TypeError("Path is undefined");
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (!realPath.includes(`/${resourceName}`)) {
|
|
20
|
-
throw new Error(`invalid resource name '${resourceName}' for route '${realPath}'`);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const entityMatcher = match<PathMatch>([`/(.*)/${resourceName}`, `/(.*)/${resourceName}/:id`], { decode: decodeURIComponent });
|
|
24
|
-
const simpleMatcher = match(`/(.*)/${resourceName}`, {
|
|
25
|
-
decode: decodeURIComponent,
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
switch (method) {
|
|
29
|
-
case "GET": {
|
|
30
|
-
const pathMatch = entityMatcher(realPath);
|
|
31
|
-
|
|
32
|
-
// If we got a /something after the resource name, we are reading 1 entity
|
|
33
|
-
if (pathMatch && pathMatch.params.id) {
|
|
34
|
-
return {
|
|
35
|
-
routeType: RouteType.READ_ONE,
|
|
36
|
-
resourceId: pathMatch.params.id,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
routeType: RouteType.READ_ALL,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
case "POST": {
|
|
45
|
-
const pathMatch = simpleMatcher(realPath);
|
|
46
|
-
|
|
47
|
-
if (pathMatch) {
|
|
48
|
-
return {
|
|
49
|
-
routeType: RouteType.CREATE,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
routeType: null,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
case "PUT":
|
|
58
|
-
case "PATCH": {
|
|
59
|
-
const pathMatch = entityMatcher(realPath);
|
|
60
|
-
|
|
61
|
-
if (pathMatch && pathMatch.params.id) {
|
|
62
|
-
return {
|
|
63
|
-
routeType: RouteType.UPDATE,
|
|
64
|
-
resourceId: pathMatch.params.id,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
routeType: null,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
case "DELETE": {
|
|
73
|
-
const pathMatch = entityMatcher(realPath);
|
|
74
|
-
|
|
75
|
-
if (pathMatch && pathMatch.params.id) {
|
|
76
|
-
return {
|
|
77
|
-
routeType: RouteType.DELETE,
|
|
78
|
-
resourceId: pathMatch.params.id,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
routeType: null,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
default: {
|
|
87
|
-
return {
|
|
88
|
-
routeType: null,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
export type GetRouteType = {
|
|
95
|
-
routeType: RouteType | null;
|
|
96
|
-
resourceId?: string;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
export default getRouteType;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import createHttpError from "http-errors";
|
|
2
|
-
|
|
3
|
-
import type { Adapter } from "../types.d";
|
|
4
|
-
|
|
5
|
-
const adapterMethods = ["create" || "delete" || "getAll" || "getOne" || "parseQuery" || "update" || "getPaginationData" || "getModels"];
|
|
6
|
-
|
|
7
|
-
const validateAdapterMethods = <T, Q>(adapter: Adapter<T, Q>) => {
|
|
8
|
-
adapterMethods.forEach((method) => {
|
|
9
|
-
if (!adapter[method as keyof Adapter<T, Q>]) {
|
|
10
|
-
throw createHttpError(500, `Adapter must implement the "${method}" method.`);
|
|
11
|
-
}
|
|
12
|
-
});
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export default validateAdapterMethods;
|