@visulima/crud 3.0.0-alpha.16 → 3.0.0-alpha.18
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 +38 -0
- package/README.md +127 -5
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +64 -3
- package/dist/index.d.mts +64 -3
- package/dist/index.d.ts +64 -3
- package/dist/index.mjs +1 -1
- package/dist/next/index.cjs +1 -1
- package/dist/next/index.d.cts +21 -13
- package/dist/next/index.d.mts +21 -13
- package/dist/next/index.d.ts +21 -13
- package/dist/next/index.mjs +1 -1
- package/dist/packem_shared/CrudApiError-BH1byAwV.mjs +1 -0
- package/dist/packem_shared/CrudApiError-DkRqkpib.cjs +1 -0
- package/dist/packem_shared/PrismaAdapter-Bhocjq94.mjs +1 -0
- package/dist/packem_shared/PrismaAdapter-DDoEjhQy.cjs +1 -0
- package/dist/packem_shared/baseHandler-BGTzX4YA.mjs +1 -0
- package/dist/packem_shared/baseHandler-DnuGeT2-.cjs +1 -0
- package/dist/packem_shared/edgeHandler-CjCFAdvT.mjs +1 -0
- package/dist/packem_shared/edgeHandler-DQ2KLGlC.cjs +1 -0
- package/dist/packem_shared/get-accessible-routes-BCUs20dV.cjs +1 -0
- package/dist/packem_shared/get-accessible-routes-CGvT_kuy.mjs +1 -0
- package/dist/packem_shared/models-to-route-names-BFpwjyxy.mjs +1 -0
- package/dist/packem_shared/models-to-route-names-CWnxPVCQ.cjs +1 -0
- package/dist/packem_shared/modelsToOpenApi-QqR_HHsz.cjs +1 -0
- package/dist/packem_shared/modelsToOpenApi-pOMrwJIY.mjs +1 -0
- package/dist/packem_shared/nodeHandler-atOpJB2d.mjs +1 -0
- package/dist/packem_shared/nodeHandler-tp623oY3.cjs +1 -0
- package/dist/packem_shared/types.d-CQwyFrf3.d.cts +207 -0
- package/dist/packem_shared/types.d-CQwyFrf3.d.mts +207 -0
- package/dist/packem_shared/types.d-CQwyFrf3.d.ts +207 -0
- package/package.json +4 -4
- package/dist/packem_shared/PrismaAdapter-D0WRtRlB.cjs +0 -1
- package/dist/packem_shared/PrismaAdapter-EuQr18sT.mjs +0 -1
- package/dist/packem_shared/base-crud-handler-B6xOUGDj.cjs +0 -1
- package/dist/packem_shared/base-crud-handler-DNKq7uog.mjs +0 -1
- package/dist/packem_shared/edgeHandler-CaIWVXt-.cjs +0 -1
- package/dist/packem_shared/edgeHandler-Deds33h_.mjs +0 -1
- package/dist/packem_shared/get-accessible-routes-DLLL11KB.cjs +0 -1
- package/dist/packem_shared/get-accessible-routes-xHYBQ_6q.mjs +0 -1
- package/dist/packem_shared/models-to-route-names-Dh2b_kIL.cjs +0 -1
- package/dist/packem_shared/models-to-route-names-UU1lZmbK.mjs +0 -1
- package/dist/packem_shared/modelsToOpenApi-CsQL5VTy.cjs +0 -1
- package/dist/packem_shared/modelsToOpenApi-ocNrUF5p.mjs +0 -1
- package/dist/packem_shared/nodeHandler-CeBCrxYT.mjs +0 -1
- package/dist/packem_shared/nodeHandler-D7AuOmUo.cjs +0 -1
- package/dist/packem_shared/types.d-C_XaTdLA.d.cts +0 -126
- package/dist/packem_shared/types.d-C_XaTdLA.d.mts +0 -126
- package/dist/packem_shared/types.d-C_XaTdLA.d.ts +0 -126
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
declare enum RouteType {
|
|
2
|
+
CREATE = "CREATE",
|
|
3
|
+
DELETE = "DELETE",
|
|
4
|
+
READ_ALL = "READ_ALL",
|
|
5
|
+
READ_ONE = "READ_ONE",
|
|
6
|
+
UPDATE = "UPDATE",
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A minimal validation schema. It is intentionally structural so that any
|
|
10
|
+
* validator exposing a synchronous/asynchronous `parse`/`safeParse` (e.g. zod)
|
|
11
|
+
* can be plugged in without pulling a hard dependency on the validator.
|
|
12
|
+
*
|
|
13
|
+
* The returned (possibly transformed) value replaces `request.body` before it
|
|
14
|
+
* reaches the adapter.
|
|
15
|
+
*/
|
|
16
|
+
interface BodySchema<T = unknown> {
|
|
17
|
+
parse: (data: unknown) => Promise<T> | T;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Per-model access policy. Every field is optional and additive on top of the
|
|
21
|
+
* route-level `only`/`exclude` knobs.
|
|
22
|
+
*/
|
|
23
|
+
interface ModelAccessPolicy {
|
|
24
|
+
/**
|
|
25
|
+
* Validation/transform schema applied to the body of `CREATE` requests
|
|
26
|
+
* before it is forwarded to the adapter. Throwing rejects the request
|
|
27
|
+
* with the thrown error (use an `http-errors` 4xx for a clean status).
|
|
28
|
+
*/
|
|
29
|
+
createSchema?: BodySchema;
|
|
30
|
+
/**
|
|
31
|
+
* Allowlist of field names a client may filter on (via `where`) or order by.
|
|
32
|
+
* When set, any other field referenced in `where`/`orderBy` is rejected with
|
|
33
|
+
* a 400. Prevents blind-exfiltration oracles on secret columns.
|
|
34
|
+
*/
|
|
35
|
+
filterableFields?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Allowlist of relation names a client may `include`. When set, requesting
|
|
38
|
+
* any other relation is rejected with a 400.
|
|
39
|
+
*/
|
|
40
|
+
includableRelations?: string[];
|
|
41
|
+
/**
|
|
42
|
+
* Field names that must never be returned to a client. They are stripped
|
|
43
|
+
* from `select` (if a client tried to select them) and forced into Prisma's
|
|
44
|
+
* `omit`-style exclusion is left to the adapter; here we simply drop them
|
|
45
|
+
* from an explicit `select`. Pair with `selectableFields` for a strict
|
|
46
|
+
* allowlist.
|
|
47
|
+
*/
|
|
48
|
+
readableFields?: string[];
|
|
49
|
+
/**
|
|
50
|
+
* Allowlist of field names a client may request via `select`. When set, any
|
|
51
|
+
* other selected field is dropped. Prevents `?select=passwordHash`.
|
|
52
|
+
*/
|
|
53
|
+
selectableFields?: string[];
|
|
54
|
+
/**
|
|
55
|
+
* Validation/transform schema applied to the body of `UPDATE` requests.
|
|
56
|
+
*/
|
|
57
|
+
updateSchema?: BodySchema;
|
|
58
|
+
/**
|
|
59
|
+
* Allowlist of field names a client may write (CREATE/UPDATE body). When set,
|
|
60
|
+
* any other key in the body is stripped before reaching the adapter,
|
|
61
|
+
* preventing mass-assignment of columns like `role`/`isAdmin`.
|
|
62
|
+
*/
|
|
63
|
+
writableFields?: string[];
|
|
64
|
+
}
|
|
65
|
+
interface ModelOption extends ModelAccessPolicy {
|
|
66
|
+
exclude?: RouteType[];
|
|
67
|
+
formatResourceId?: (resourceId: string) => number | string;
|
|
68
|
+
/**
|
|
69
|
+
* Hard cap on the number of rows a list request may return, regardless of
|
|
70
|
+
* the client-supplied `limit`. Overrides the handler-level `maxPerPage`.
|
|
71
|
+
*/
|
|
72
|
+
maxPerPage?: number;
|
|
73
|
+
name?: string;
|
|
74
|
+
only?: RouteType[];
|
|
75
|
+
}
|
|
76
|
+
type ModelsOptions<M extends string = string> = { [key in M]?: ModelOption };
|
|
77
|
+
type CreateHandler = <T, Q, Request>(parameters: HandlerParameters<T, Q> & {
|
|
78
|
+
request: Request & {
|
|
79
|
+
body: Record<string, unknown>;
|
|
80
|
+
};
|
|
81
|
+
}) => Promise<{
|
|
82
|
+
data: unknown;
|
|
83
|
+
status: number;
|
|
84
|
+
}>;
|
|
85
|
+
type DeleteHandler = <T, Q>(parameters: UniqueResourceHandlerParameters<T, Q>) => Promise<{
|
|
86
|
+
data: unknown;
|
|
87
|
+
status: number;
|
|
88
|
+
}>;
|
|
89
|
+
type GetHandler = <T, Q>(parameters: UniqueResourceHandlerParameters<T, Q>) => Promise<{
|
|
90
|
+
data: unknown;
|
|
91
|
+
status: number;
|
|
92
|
+
}>;
|
|
93
|
+
type ListHandler = <T, Q extends ParsedQueryParameters>(parameters: HandlerParameters<T, Q> & {
|
|
94
|
+
pagination: PaginationConfig;
|
|
95
|
+
}) => Promise<{
|
|
96
|
+
data: unknown;
|
|
97
|
+
status: number;
|
|
98
|
+
}>;
|
|
99
|
+
type UpdateHandler = <T, Q, Request>(parameters: UniqueResourceHandlerParameters<T, Q> & {
|
|
100
|
+
request: Request & {
|
|
101
|
+
body: Partial<T>;
|
|
102
|
+
};
|
|
103
|
+
}) => Promise<{
|
|
104
|
+
data: unknown;
|
|
105
|
+
status: number;
|
|
106
|
+
}>;
|
|
107
|
+
interface HandlerOptions<M extends string = string> {
|
|
108
|
+
exposeStrategy?: "all" | "none";
|
|
109
|
+
formatResourceId?: (resourceId: string) => number | string;
|
|
110
|
+
handlers?: {
|
|
111
|
+
create?: CreateHandler;
|
|
112
|
+
delete?: DeleteHandler;
|
|
113
|
+
get?: GetHandler;
|
|
114
|
+
list?: ListHandler;
|
|
115
|
+
update?: UpdateHandler;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Default hard cap on the number of rows a list request may return for any
|
|
119
|
+
* model, regardless of the client-supplied `limit`. Defaults to no cap.
|
|
120
|
+
* Per-model `maxPerPage` overrides this.
|
|
121
|
+
*/
|
|
122
|
+
maxPerPage?: number;
|
|
123
|
+
models?: ModelsOptions<M>;
|
|
124
|
+
/**
|
|
125
|
+
* Called once per request after the route type is resolved and before the
|
|
126
|
+
* adapter is invoked. Throw (ideally an `http-errors` error) to reject the
|
|
127
|
+
* request — a row/field access guard hook. Receives the resolved model name,
|
|
128
|
+
* route type and resource id (for single-resource routes).
|
|
129
|
+
*/
|
|
130
|
+
onRequest?: (context: {
|
|
131
|
+
method: string;
|
|
132
|
+
resourceId?: number | string;
|
|
133
|
+
resourceName: string;
|
|
134
|
+
routeType: RouteType;
|
|
135
|
+
url: string;
|
|
136
|
+
}) => Promise<void> | void;
|
|
137
|
+
pagination?: PaginationConfig;
|
|
138
|
+
}
|
|
139
|
+
interface PaginationConfig {
|
|
140
|
+
perPage: number;
|
|
141
|
+
}
|
|
142
|
+
interface HandlerParameters<T, Q> {
|
|
143
|
+
adapter: Adapter<T, Q>;
|
|
144
|
+
query: Q;
|
|
145
|
+
resourceName: string;
|
|
146
|
+
}
|
|
147
|
+
interface UniqueResourceHandlerParameters<T, Q> {
|
|
148
|
+
adapter: Adapter<T, Q>;
|
|
149
|
+
query: Q;
|
|
150
|
+
resourceId: number | string;
|
|
151
|
+
resourceName: string;
|
|
152
|
+
}
|
|
153
|
+
interface Adapter<T, Q, M extends string = string> {
|
|
154
|
+
connect?: () => Promise<void>;
|
|
155
|
+
create: (resourceName: M, data: unknown, query: Q) => Promise<T>;
|
|
156
|
+
delete: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;
|
|
157
|
+
disconnect?: () => Promise<void>;
|
|
158
|
+
getAll: (resourceName: M, query: Q) => Promise<T[]>;
|
|
159
|
+
getModels: () => M[];
|
|
160
|
+
getOne: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;
|
|
161
|
+
getPaginationData: (resourceName: M, query: Q) => Promise<PaginationData>;
|
|
162
|
+
handleError?: (error: Error) => void;
|
|
163
|
+
init?: () => Promise<void>;
|
|
164
|
+
mapModelsToRouteNames?: () => Promise<{ [key in M]?: string }>;
|
|
165
|
+
models?: M[];
|
|
166
|
+
parseQuery: (resourceName: M, query: ParsedQueryParameters) => Q;
|
|
167
|
+
update: (resourceName: M, resourceId: number | string, data: unknown, query: Q) => Promise<T>;
|
|
168
|
+
}
|
|
169
|
+
interface PaginationData {
|
|
170
|
+
page: number;
|
|
171
|
+
pageCount: number;
|
|
172
|
+
total: number;
|
|
173
|
+
}
|
|
174
|
+
type RecursiveField = Record<string, Record<string, boolean> | boolean>;
|
|
175
|
+
type WhereOperator = "$cont" | "$ends" | "$eq" | "$gt" | "$gte" | "$in" | "$isnull" | "$lt" | "$lte" | "$neq" | "$notin" | "$starts";
|
|
176
|
+
type SearchCondition = Date | boolean | number | string | null;
|
|
177
|
+
type WhereCondition = { [key in WhereOperator]?: SearchCondition };
|
|
178
|
+
type Condition = {
|
|
179
|
+
[key: string]: Condition | SearchCondition | WhereCondition;
|
|
180
|
+
};
|
|
181
|
+
type WhereField = Condition & {
|
|
182
|
+
$and?: Condition | Condition[];
|
|
183
|
+
$not?: Condition | Condition[];
|
|
184
|
+
$or?: Condition | Condition[];
|
|
185
|
+
};
|
|
186
|
+
type OrderByOperator = "$asc" | "$desc";
|
|
187
|
+
type OrderByField = Record<string, OrderByOperator>;
|
|
188
|
+
interface ParsedQueryParameters {
|
|
189
|
+
distinct?: string;
|
|
190
|
+
include?: RecursiveField;
|
|
191
|
+
limit?: number;
|
|
192
|
+
orderBy?: OrderByField;
|
|
193
|
+
originalQuery?: Record<string, string>;
|
|
194
|
+
page?: number;
|
|
195
|
+
select?: RecursiveField;
|
|
196
|
+
skip?: number;
|
|
197
|
+
where?: WhereField;
|
|
198
|
+
}
|
|
199
|
+
type ExecuteHandler<Request, Response, Result = void> = (request: Request, response: Response) => Promise<Result>;
|
|
200
|
+
interface FakePrismaClient {
|
|
201
|
+
$connect: () => Promise<void> | void;
|
|
202
|
+
$disconnect: () => Promise<void>;
|
|
203
|
+
[key: string]: unknown;
|
|
204
|
+
_dmmf?: unknown;
|
|
205
|
+
_getDmmf?: () => unknown;
|
|
206
|
+
}
|
|
207
|
+
export { Adapter as A, BodySchema as B, Condition as C, DeleteHandler as D, ExecuteHandler as E, FakePrismaClient as F, GetHandler as G, HandlerOptions as H, ListHandler as L, ModelsOptions as M, OrderByField as O, PaginationData as P, RouteType as R, SearchCondition as S, UniqueResourceHandlerParameters as U, WhereCondition as W, ParsedQueryParameters as a, CreateHandler as b, HandlerParameters as c, ModelAccessPolicy as d, ModelOption as e, OrderByOperator as f, PaginationConfig as g, RecursiveField as h, UpdateHandler as i, WhereField as j, WhereOperator as k };
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
declare enum RouteType {
|
|
2
|
+
CREATE = "CREATE",
|
|
3
|
+
DELETE = "DELETE",
|
|
4
|
+
READ_ALL = "READ_ALL",
|
|
5
|
+
READ_ONE = "READ_ONE",
|
|
6
|
+
UPDATE = "UPDATE",
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A minimal validation schema. It is intentionally structural so that any
|
|
10
|
+
* validator exposing a synchronous/asynchronous `parse`/`safeParse` (e.g. zod)
|
|
11
|
+
* can be plugged in without pulling a hard dependency on the validator.
|
|
12
|
+
*
|
|
13
|
+
* The returned (possibly transformed) value replaces `request.body` before it
|
|
14
|
+
* reaches the adapter.
|
|
15
|
+
*/
|
|
16
|
+
interface BodySchema<T = unknown> {
|
|
17
|
+
parse: (data: unknown) => Promise<T> | T;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Per-model access policy. Every field is optional and additive on top of the
|
|
21
|
+
* route-level `only`/`exclude` knobs.
|
|
22
|
+
*/
|
|
23
|
+
interface ModelAccessPolicy {
|
|
24
|
+
/**
|
|
25
|
+
* Validation/transform schema applied to the body of `CREATE` requests
|
|
26
|
+
* before it is forwarded to the adapter. Throwing rejects the request
|
|
27
|
+
* with the thrown error (use an `http-errors` 4xx for a clean status).
|
|
28
|
+
*/
|
|
29
|
+
createSchema?: BodySchema;
|
|
30
|
+
/**
|
|
31
|
+
* Allowlist of field names a client may filter on (via `where`) or order by.
|
|
32
|
+
* When set, any other field referenced in `where`/`orderBy` is rejected with
|
|
33
|
+
* a 400. Prevents blind-exfiltration oracles on secret columns.
|
|
34
|
+
*/
|
|
35
|
+
filterableFields?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Allowlist of relation names a client may `include`. When set, requesting
|
|
38
|
+
* any other relation is rejected with a 400.
|
|
39
|
+
*/
|
|
40
|
+
includableRelations?: string[];
|
|
41
|
+
/**
|
|
42
|
+
* Field names that must never be returned to a client. They are stripped
|
|
43
|
+
* from `select` (if a client tried to select them) and forced into Prisma's
|
|
44
|
+
* `omit`-style exclusion is left to the adapter; here we simply drop them
|
|
45
|
+
* from an explicit `select`. Pair with `selectableFields` for a strict
|
|
46
|
+
* allowlist.
|
|
47
|
+
*/
|
|
48
|
+
readableFields?: string[];
|
|
49
|
+
/**
|
|
50
|
+
* Allowlist of field names a client may request via `select`. When set, any
|
|
51
|
+
* other selected field is dropped. Prevents `?select=passwordHash`.
|
|
52
|
+
*/
|
|
53
|
+
selectableFields?: string[];
|
|
54
|
+
/**
|
|
55
|
+
* Validation/transform schema applied to the body of `UPDATE` requests.
|
|
56
|
+
*/
|
|
57
|
+
updateSchema?: BodySchema;
|
|
58
|
+
/**
|
|
59
|
+
* Allowlist of field names a client may write (CREATE/UPDATE body). When set,
|
|
60
|
+
* any other key in the body is stripped before reaching the adapter,
|
|
61
|
+
* preventing mass-assignment of columns like `role`/`isAdmin`.
|
|
62
|
+
*/
|
|
63
|
+
writableFields?: string[];
|
|
64
|
+
}
|
|
65
|
+
interface ModelOption extends ModelAccessPolicy {
|
|
66
|
+
exclude?: RouteType[];
|
|
67
|
+
formatResourceId?: (resourceId: string) => number | string;
|
|
68
|
+
/**
|
|
69
|
+
* Hard cap on the number of rows a list request may return, regardless of
|
|
70
|
+
* the client-supplied `limit`. Overrides the handler-level `maxPerPage`.
|
|
71
|
+
*/
|
|
72
|
+
maxPerPage?: number;
|
|
73
|
+
name?: string;
|
|
74
|
+
only?: RouteType[];
|
|
75
|
+
}
|
|
76
|
+
type ModelsOptions<M extends string = string> = { [key in M]?: ModelOption };
|
|
77
|
+
type CreateHandler = <T, Q, Request>(parameters: HandlerParameters<T, Q> & {
|
|
78
|
+
request: Request & {
|
|
79
|
+
body: Record<string, unknown>;
|
|
80
|
+
};
|
|
81
|
+
}) => Promise<{
|
|
82
|
+
data: unknown;
|
|
83
|
+
status: number;
|
|
84
|
+
}>;
|
|
85
|
+
type DeleteHandler = <T, Q>(parameters: UniqueResourceHandlerParameters<T, Q>) => Promise<{
|
|
86
|
+
data: unknown;
|
|
87
|
+
status: number;
|
|
88
|
+
}>;
|
|
89
|
+
type GetHandler = <T, Q>(parameters: UniqueResourceHandlerParameters<T, Q>) => Promise<{
|
|
90
|
+
data: unknown;
|
|
91
|
+
status: number;
|
|
92
|
+
}>;
|
|
93
|
+
type ListHandler = <T, Q extends ParsedQueryParameters>(parameters: HandlerParameters<T, Q> & {
|
|
94
|
+
pagination: PaginationConfig;
|
|
95
|
+
}) => Promise<{
|
|
96
|
+
data: unknown;
|
|
97
|
+
status: number;
|
|
98
|
+
}>;
|
|
99
|
+
type UpdateHandler = <T, Q, Request>(parameters: UniqueResourceHandlerParameters<T, Q> & {
|
|
100
|
+
request: Request & {
|
|
101
|
+
body: Partial<T>;
|
|
102
|
+
};
|
|
103
|
+
}) => Promise<{
|
|
104
|
+
data: unknown;
|
|
105
|
+
status: number;
|
|
106
|
+
}>;
|
|
107
|
+
interface HandlerOptions<M extends string = string> {
|
|
108
|
+
exposeStrategy?: "all" | "none";
|
|
109
|
+
formatResourceId?: (resourceId: string) => number | string;
|
|
110
|
+
handlers?: {
|
|
111
|
+
create?: CreateHandler;
|
|
112
|
+
delete?: DeleteHandler;
|
|
113
|
+
get?: GetHandler;
|
|
114
|
+
list?: ListHandler;
|
|
115
|
+
update?: UpdateHandler;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Default hard cap on the number of rows a list request may return for any
|
|
119
|
+
* model, regardless of the client-supplied `limit`. Defaults to no cap.
|
|
120
|
+
* Per-model `maxPerPage` overrides this.
|
|
121
|
+
*/
|
|
122
|
+
maxPerPage?: number;
|
|
123
|
+
models?: ModelsOptions<M>;
|
|
124
|
+
/**
|
|
125
|
+
* Called once per request after the route type is resolved and before the
|
|
126
|
+
* adapter is invoked. Throw (ideally an `http-errors` error) to reject the
|
|
127
|
+
* request — a row/field access guard hook. Receives the resolved model name,
|
|
128
|
+
* route type and resource id (for single-resource routes).
|
|
129
|
+
*/
|
|
130
|
+
onRequest?: (context: {
|
|
131
|
+
method: string;
|
|
132
|
+
resourceId?: number | string;
|
|
133
|
+
resourceName: string;
|
|
134
|
+
routeType: RouteType;
|
|
135
|
+
url: string;
|
|
136
|
+
}) => Promise<void> | void;
|
|
137
|
+
pagination?: PaginationConfig;
|
|
138
|
+
}
|
|
139
|
+
interface PaginationConfig {
|
|
140
|
+
perPage: number;
|
|
141
|
+
}
|
|
142
|
+
interface HandlerParameters<T, Q> {
|
|
143
|
+
adapter: Adapter<T, Q>;
|
|
144
|
+
query: Q;
|
|
145
|
+
resourceName: string;
|
|
146
|
+
}
|
|
147
|
+
interface UniqueResourceHandlerParameters<T, Q> {
|
|
148
|
+
adapter: Adapter<T, Q>;
|
|
149
|
+
query: Q;
|
|
150
|
+
resourceId: number | string;
|
|
151
|
+
resourceName: string;
|
|
152
|
+
}
|
|
153
|
+
interface Adapter<T, Q, M extends string = string> {
|
|
154
|
+
connect?: () => Promise<void>;
|
|
155
|
+
create: (resourceName: M, data: unknown, query: Q) => Promise<T>;
|
|
156
|
+
delete: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;
|
|
157
|
+
disconnect?: () => Promise<void>;
|
|
158
|
+
getAll: (resourceName: M, query: Q) => Promise<T[]>;
|
|
159
|
+
getModels: () => M[];
|
|
160
|
+
getOne: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;
|
|
161
|
+
getPaginationData: (resourceName: M, query: Q) => Promise<PaginationData>;
|
|
162
|
+
handleError?: (error: Error) => void;
|
|
163
|
+
init?: () => Promise<void>;
|
|
164
|
+
mapModelsToRouteNames?: () => Promise<{ [key in M]?: string }>;
|
|
165
|
+
models?: M[];
|
|
166
|
+
parseQuery: (resourceName: M, query: ParsedQueryParameters) => Q;
|
|
167
|
+
update: (resourceName: M, resourceId: number | string, data: unknown, query: Q) => Promise<T>;
|
|
168
|
+
}
|
|
169
|
+
interface PaginationData {
|
|
170
|
+
page: number;
|
|
171
|
+
pageCount: number;
|
|
172
|
+
total: number;
|
|
173
|
+
}
|
|
174
|
+
type RecursiveField = Record<string, Record<string, boolean> | boolean>;
|
|
175
|
+
type WhereOperator = "$cont" | "$ends" | "$eq" | "$gt" | "$gte" | "$in" | "$isnull" | "$lt" | "$lte" | "$neq" | "$notin" | "$starts";
|
|
176
|
+
type SearchCondition = Date | boolean | number | string | null;
|
|
177
|
+
type WhereCondition = { [key in WhereOperator]?: SearchCondition };
|
|
178
|
+
type Condition = {
|
|
179
|
+
[key: string]: Condition | SearchCondition | WhereCondition;
|
|
180
|
+
};
|
|
181
|
+
type WhereField = Condition & {
|
|
182
|
+
$and?: Condition | Condition[];
|
|
183
|
+
$not?: Condition | Condition[];
|
|
184
|
+
$or?: Condition | Condition[];
|
|
185
|
+
};
|
|
186
|
+
type OrderByOperator = "$asc" | "$desc";
|
|
187
|
+
type OrderByField = Record<string, OrderByOperator>;
|
|
188
|
+
interface ParsedQueryParameters {
|
|
189
|
+
distinct?: string;
|
|
190
|
+
include?: RecursiveField;
|
|
191
|
+
limit?: number;
|
|
192
|
+
orderBy?: OrderByField;
|
|
193
|
+
originalQuery?: Record<string, string>;
|
|
194
|
+
page?: number;
|
|
195
|
+
select?: RecursiveField;
|
|
196
|
+
skip?: number;
|
|
197
|
+
where?: WhereField;
|
|
198
|
+
}
|
|
199
|
+
type ExecuteHandler<Request, Response, Result = void> = (request: Request, response: Response) => Promise<Result>;
|
|
200
|
+
interface FakePrismaClient {
|
|
201
|
+
$connect: () => Promise<void> | void;
|
|
202
|
+
$disconnect: () => Promise<void>;
|
|
203
|
+
[key: string]: unknown;
|
|
204
|
+
_dmmf?: unknown;
|
|
205
|
+
_getDmmf?: () => unknown;
|
|
206
|
+
}
|
|
207
|
+
export { Adapter as A, BodySchema as B, Condition as C, DeleteHandler as D, ExecuteHandler as E, FakePrismaClient as F, GetHandler as G, HandlerOptions as H, ListHandler as L, ModelsOptions as M, OrderByField as O, PaginationData as P, RouteType as R, SearchCondition as S, UniqueResourceHandlerParameters as U, WhereCondition as W, ParsedQueryParameters as a, CreateHandler as b, HandlerParameters as c, ModelAccessPolicy as d, ModelOption as e, OrderByOperator as f, PaginationConfig as g, RecursiveField as h, UpdateHandler as i, WhereField as j, WhereOperator as k };
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
declare enum RouteType {
|
|
2
|
+
CREATE = "CREATE",
|
|
3
|
+
DELETE = "DELETE",
|
|
4
|
+
READ_ALL = "READ_ALL",
|
|
5
|
+
READ_ONE = "READ_ONE",
|
|
6
|
+
UPDATE = "UPDATE",
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A minimal validation schema. It is intentionally structural so that any
|
|
10
|
+
* validator exposing a synchronous/asynchronous `parse`/`safeParse` (e.g. zod)
|
|
11
|
+
* can be plugged in without pulling a hard dependency on the validator.
|
|
12
|
+
*
|
|
13
|
+
* The returned (possibly transformed) value replaces `request.body` before it
|
|
14
|
+
* reaches the adapter.
|
|
15
|
+
*/
|
|
16
|
+
interface BodySchema<T = unknown> {
|
|
17
|
+
parse: (data: unknown) => Promise<T> | T;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Per-model access policy. Every field is optional and additive on top of the
|
|
21
|
+
* route-level `only`/`exclude` knobs.
|
|
22
|
+
*/
|
|
23
|
+
interface ModelAccessPolicy {
|
|
24
|
+
/**
|
|
25
|
+
* Validation/transform schema applied to the body of `CREATE` requests
|
|
26
|
+
* before it is forwarded to the adapter. Throwing rejects the request
|
|
27
|
+
* with the thrown error (use an `http-errors` 4xx for a clean status).
|
|
28
|
+
*/
|
|
29
|
+
createSchema?: BodySchema;
|
|
30
|
+
/**
|
|
31
|
+
* Allowlist of field names a client may filter on (via `where`) or order by.
|
|
32
|
+
* When set, any other field referenced in `where`/`orderBy` is rejected with
|
|
33
|
+
* a 400. Prevents blind-exfiltration oracles on secret columns.
|
|
34
|
+
*/
|
|
35
|
+
filterableFields?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Allowlist of relation names a client may `include`. When set, requesting
|
|
38
|
+
* any other relation is rejected with a 400.
|
|
39
|
+
*/
|
|
40
|
+
includableRelations?: string[];
|
|
41
|
+
/**
|
|
42
|
+
* Field names that must never be returned to a client. They are stripped
|
|
43
|
+
* from `select` (if a client tried to select them) and forced into Prisma's
|
|
44
|
+
* `omit`-style exclusion is left to the adapter; here we simply drop them
|
|
45
|
+
* from an explicit `select`. Pair with `selectableFields` for a strict
|
|
46
|
+
* allowlist.
|
|
47
|
+
*/
|
|
48
|
+
readableFields?: string[];
|
|
49
|
+
/**
|
|
50
|
+
* Allowlist of field names a client may request via `select`. When set, any
|
|
51
|
+
* other selected field is dropped. Prevents `?select=passwordHash`.
|
|
52
|
+
*/
|
|
53
|
+
selectableFields?: string[];
|
|
54
|
+
/**
|
|
55
|
+
* Validation/transform schema applied to the body of `UPDATE` requests.
|
|
56
|
+
*/
|
|
57
|
+
updateSchema?: BodySchema;
|
|
58
|
+
/**
|
|
59
|
+
* Allowlist of field names a client may write (CREATE/UPDATE body). When set,
|
|
60
|
+
* any other key in the body is stripped before reaching the adapter,
|
|
61
|
+
* preventing mass-assignment of columns like `role`/`isAdmin`.
|
|
62
|
+
*/
|
|
63
|
+
writableFields?: string[];
|
|
64
|
+
}
|
|
65
|
+
interface ModelOption extends ModelAccessPolicy {
|
|
66
|
+
exclude?: RouteType[];
|
|
67
|
+
formatResourceId?: (resourceId: string) => number | string;
|
|
68
|
+
/**
|
|
69
|
+
* Hard cap on the number of rows a list request may return, regardless of
|
|
70
|
+
* the client-supplied `limit`. Overrides the handler-level `maxPerPage`.
|
|
71
|
+
*/
|
|
72
|
+
maxPerPage?: number;
|
|
73
|
+
name?: string;
|
|
74
|
+
only?: RouteType[];
|
|
75
|
+
}
|
|
76
|
+
type ModelsOptions<M extends string = string> = { [key in M]?: ModelOption };
|
|
77
|
+
type CreateHandler = <T, Q, Request>(parameters: HandlerParameters<T, Q> & {
|
|
78
|
+
request: Request & {
|
|
79
|
+
body: Record<string, unknown>;
|
|
80
|
+
};
|
|
81
|
+
}) => Promise<{
|
|
82
|
+
data: unknown;
|
|
83
|
+
status: number;
|
|
84
|
+
}>;
|
|
85
|
+
type DeleteHandler = <T, Q>(parameters: UniqueResourceHandlerParameters<T, Q>) => Promise<{
|
|
86
|
+
data: unknown;
|
|
87
|
+
status: number;
|
|
88
|
+
}>;
|
|
89
|
+
type GetHandler = <T, Q>(parameters: UniqueResourceHandlerParameters<T, Q>) => Promise<{
|
|
90
|
+
data: unknown;
|
|
91
|
+
status: number;
|
|
92
|
+
}>;
|
|
93
|
+
type ListHandler = <T, Q extends ParsedQueryParameters>(parameters: HandlerParameters<T, Q> & {
|
|
94
|
+
pagination: PaginationConfig;
|
|
95
|
+
}) => Promise<{
|
|
96
|
+
data: unknown;
|
|
97
|
+
status: number;
|
|
98
|
+
}>;
|
|
99
|
+
type UpdateHandler = <T, Q, Request>(parameters: UniqueResourceHandlerParameters<T, Q> & {
|
|
100
|
+
request: Request & {
|
|
101
|
+
body: Partial<T>;
|
|
102
|
+
};
|
|
103
|
+
}) => Promise<{
|
|
104
|
+
data: unknown;
|
|
105
|
+
status: number;
|
|
106
|
+
}>;
|
|
107
|
+
interface HandlerOptions<M extends string = string> {
|
|
108
|
+
exposeStrategy?: "all" | "none";
|
|
109
|
+
formatResourceId?: (resourceId: string) => number | string;
|
|
110
|
+
handlers?: {
|
|
111
|
+
create?: CreateHandler;
|
|
112
|
+
delete?: DeleteHandler;
|
|
113
|
+
get?: GetHandler;
|
|
114
|
+
list?: ListHandler;
|
|
115
|
+
update?: UpdateHandler;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Default hard cap on the number of rows a list request may return for any
|
|
119
|
+
* model, regardless of the client-supplied `limit`. Defaults to no cap.
|
|
120
|
+
* Per-model `maxPerPage` overrides this.
|
|
121
|
+
*/
|
|
122
|
+
maxPerPage?: number;
|
|
123
|
+
models?: ModelsOptions<M>;
|
|
124
|
+
/**
|
|
125
|
+
* Called once per request after the route type is resolved and before the
|
|
126
|
+
* adapter is invoked. Throw (ideally an `http-errors` error) to reject the
|
|
127
|
+
* request — a row/field access guard hook. Receives the resolved model name,
|
|
128
|
+
* route type and resource id (for single-resource routes).
|
|
129
|
+
*/
|
|
130
|
+
onRequest?: (context: {
|
|
131
|
+
method: string;
|
|
132
|
+
resourceId?: number | string;
|
|
133
|
+
resourceName: string;
|
|
134
|
+
routeType: RouteType;
|
|
135
|
+
url: string;
|
|
136
|
+
}) => Promise<void> | void;
|
|
137
|
+
pagination?: PaginationConfig;
|
|
138
|
+
}
|
|
139
|
+
interface PaginationConfig {
|
|
140
|
+
perPage: number;
|
|
141
|
+
}
|
|
142
|
+
interface HandlerParameters<T, Q> {
|
|
143
|
+
adapter: Adapter<T, Q>;
|
|
144
|
+
query: Q;
|
|
145
|
+
resourceName: string;
|
|
146
|
+
}
|
|
147
|
+
interface UniqueResourceHandlerParameters<T, Q> {
|
|
148
|
+
adapter: Adapter<T, Q>;
|
|
149
|
+
query: Q;
|
|
150
|
+
resourceId: number | string;
|
|
151
|
+
resourceName: string;
|
|
152
|
+
}
|
|
153
|
+
interface Adapter<T, Q, M extends string = string> {
|
|
154
|
+
connect?: () => Promise<void>;
|
|
155
|
+
create: (resourceName: M, data: unknown, query: Q) => Promise<T>;
|
|
156
|
+
delete: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;
|
|
157
|
+
disconnect?: () => Promise<void>;
|
|
158
|
+
getAll: (resourceName: M, query: Q) => Promise<T[]>;
|
|
159
|
+
getModels: () => M[];
|
|
160
|
+
getOne: (resourceName: M, resourceId: number | string, query: Q) => Promise<T>;
|
|
161
|
+
getPaginationData: (resourceName: M, query: Q) => Promise<PaginationData>;
|
|
162
|
+
handleError?: (error: Error) => void;
|
|
163
|
+
init?: () => Promise<void>;
|
|
164
|
+
mapModelsToRouteNames?: () => Promise<{ [key in M]?: string }>;
|
|
165
|
+
models?: M[];
|
|
166
|
+
parseQuery: (resourceName: M, query: ParsedQueryParameters) => Q;
|
|
167
|
+
update: (resourceName: M, resourceId: number | string, data: unknown, query: Q) => Promise<T>;
|
|
168
|
+
}
|
|
169
|
+
interface PaginationData {
|
|
170
|
+
page: number;
|
|
171
|
+
pageCount: number;
|
|
172
|
+
total: number;
|
|
173
|
+
}
|
|
174
|
+
type RecursiveField = Record<string, Record<string, boolean> | boolean>;
|
|
175
|
+
type WhereOperator = "$cont" | "$ends" | "$eq" | "$gt" | "$gte" | "$in" | "$isnull" | "$lt" | "$lte" | "$neq" | "$notin" | "$starts";
|
|
176
|
+
type SearchCondition = Date | boolean | number | string | null;
|
|
177
|
+
type WhereCondition = { [key in WhereOperator]?: SearchCondition };
|
|
178
|
+
type Condition = {
|
|
179
|
+
[key: string]: Condition | SearchCondition | WhereCondition;
|
|
180
|
+
};
|
|
181
|
+
type WhereField = Condition & {
|
|
182
|
+
$and?: Condition | Condition[];
|
|
183
|
+
$not?: Condition | Condition[];
|
|
184
|
+
$or?: Condition | Condition[];
|
|
185
|
+
};
|
|
186
|
+
type OrderByOperator = "$asc" | "$desc";
|
|
187
|
+
type OrderByField = Record<string, OrderByOperator>;
|
|
188
|
+
interface ParsedQueryParameters {
|
|
189
|
+
distinct?: string;
|
|
190
|
+
include?: RecursiveField;
|
|
191
|
+
limit?: number;
|
|
192
|
+
orderBy?: OrderByField;
|
|
193
|
+
originalQuery?: Record<string, string>;
|
|
194
|
+
page?: number;
|
|
195
|
+
select?: RecursiveField;
|
|
196
|
+
skip?: number;
|
|
197
|
+
where?: WhereField;
|
|
198
|
+
}
|
|
199
|
+
type ExecuteHandler<Request, Response, Result = void> = (request: Request, response: Response) => Promise<Result>;
|
|
200
|
+
interface FakePrismaClient {
|
|
201
|
+
$connect: () => Promise<void> | void;
|
|
202
|
+
$disconnect: () => Promise<void>;
|
|
203
|
+
[key: string]: unknown;
|
|
204
|
+
_dmmf?: unknown;
|
|
205
|
+
_getDmmf?: () => unknown;
|
|
206
|
+
}
|
|
207
|
+
export { Adapter as A, BodySchema as B, Condition as C, DeleteHandler as D, ExecuteHandler as E, FakePrismaClient as F, GetHandler as G, HandlerOptions as H, ListHandler as L, ModelsOptions as M, OrderByField as O, PaginationData as P, RouteType as R, SearchCondition as S, UniqueResourceHandlerParameters as U, WhereCondition as W, ParsedQueryParameters as a, CreateHandler as b, HandlerParameters as c, ModelAccessPolicy as d, ModelOption as e, OrderByOperator as f, PaginationConfig as g, RecursiveField as h, UpdateHandler as i, WhereField as j, WhereOperator as k };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@visulima/crud",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.18",
|
|
4
4
|
"description": "A comprehensive CRUD library for building RESTful APIs with Prisma, providing automatic CRUD operations, filtering, sorting, and pagination.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"anolilab",
|
|
@@ -75,13 +75,13 @@
|
|
|
75
75
|
"LICENSE.md"
|
|
76
76
|
],
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@visulima/pagination": "5.0.0-alpha.
|
|
79
|
-
"@visulima/prisma-dmmf-transformer": "3.0.0-alpha.
|
|
78
|
+
"@visulima/pagination": "5.0.0-alpha.14",
|
|
79
|
+
"@visulima/prisma-dmmf-transformer": "3.0.0-alpha.16",
|
|
80
80
|
"http-errors": "^2.0.1",
|
|
81
81
|
"path-to-regexp": "8.4.2"
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
|
-
"@prisma/client": "^3.0.0 || ^4.0.0",
|
|
84
|
+
"@prisma/client": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0",
|
|
85
85
|
"next": ">=12.0 || >=13.0 || >=14.0 || >=15.0"
|
|
86
86
|
},
|
|
87
87
|
"peerDependenciesMeta": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";var k=Object.defineProperty;var a=(r,t)=>k(r,"name",{value:t,configurable:!0});const P=require("http-errors"),O=require("./models-to-route-names-Dh2b_kIL.cjs"),C=a(r=>r&&typeof r=="object"&&"default"in r?r.default:r,"_interopDefaultCompat"),p=C(P);var j=Object.defineProperty,M=a((r,t)=>j(r,"name",{value:t,configurable:!0}),"n$1");const D=new Set(["boolean","number","string"]),m=M(r=>D.has(typeof r),"isPrimitive");var E=Object.defineProperty,R=a((r,t)=>E(r,"name",{value:t,configurable:!0}),"s$1");const q=R(r=>{const t={};if(Object.keys(r).forEach(e=>{const s=r[e];m(s)&&(t[e]=s)}),Object.keys(t).length!==1)throw new Error("cursor needs to be an object with exactly 1 property with a primitive value");return t},"parsePrismaCursor");var K=Object.defineProperty,_=a((r,t)=>K(r,"name",{value:t,configurable:!0}),"a");const B={$asc:"asc",$desc:"desc"},N=_(r=>{const t={};return Object.keys(r).forEach(e=>{const s=r[e];t[e]=B[s]}),t},"parsePrismaOrderBy");var S=Object.defineProperty,Q=a((r,t)=>S(r,"name",{value:t,configurable:!0}),"u$1");const u=Q((r,t)=>{const e={};return Object.keys(r).forEach(s=>{e[s]=r[s]===!0?!0:{[t]:u(r[s],t)}}),e},"parsePrismaRecursiveField");var A=Object.defineProperty,n=a((r,t)=>A(r,"name",{value:t,configurable:!0}),"r");const c=n(r=>r instanceof Object,"isObject"),T={$cont:"contains",$ends:"endsWith",$eq:"equals",$gt:"gt",$gte:"gte",$in:"in",$lt:"lt",$lte:"lte",$neq:"not",$notin:"notIn",$starts:"startsWith"},F=n(r=>/^\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(r),"isDateString"),W=n(r=>F(r)?new Date(r):typeof r=="string"&&r==="$isnull"?null:r,"getSearchValue"),f=n((r,t)=>{const e=r.split(".");return e.splice(-1,1),t.includes(e.join("."))},"isRelation"),g=n(r=>{const t=Object.keys(r)[0],e=T[t];if(e)return{[e]:r[t]}},"parseSimpleField"),b=n((r,t,e,s)=>{const i=t.split(".").toReversed();let o={};i.forEach((h,v)=>{v===0?w(r,h,o,s):o={[h]:{some:o}}});const l=i.toReversed()[0],$=e[l];e[l]={some:{...$?.some,...o[l]?.some}}},"parseRelation"),d=n((r,t)=>{const e={};return Object.keys(r).forEach(s=>{const i=r[s];if(f(s,t))b(i,s,e,t);else if(m(i))e[s]=i;else if(c(i)){const o=g(i);o&&(e[s]=o)}}),e},"parseObjectCombination"),w=n((r,t,e,s)=>{if(m(r))e[t]=W(r);else switch(t){case"$and":{c(r)&&(e.AND=d(r,s));break}case"$not":{c(r)&&(e.NOT=d(r,s));break}case"$or":{c(r)&&(e.OR=d(r,s));break}default:{e[t]=g(r);break}}},"basicParse"),x=n((r,t)=>{const e={};return Object.keys(r).forEach(s=>{const i=r[s];f(s,t)?b(i,s,e,t):w(i,s,e,t)}),e},"parsePrismaWhere");var J=Object.defineProperty,y=a((r,t)=>J(r,"name",{value:t,configurable:!0}),"s");class V{static{a(this,"P")}static{y(this,"PrismaAdapter")}models;ctorModels;dmmf;manyRelations;primaryKey;prismaClient;constructor({manyRelations:t={},models:e,primaryKey:s="id",prismaClient:i}){this.prismaClient=i,this.primaryKey=s,this.manyRelations=t,this.ctorModels=e}async connect(){this.prismaClient.$connect()}async create(t,e,s){return await this.getPrismaDelegate(t).create({data:e,include:s.include,select:s.select})}async delete(t,e,s){return await this.getPrismaDelegate(t).delete({include:s.include,select:s.select,where:{[this.primaryKey]:e}})}async disconnect(){await this.prismaClient.$disconnect()}async getAll(t,e){return await this.getPrismaDelegate(t).findMany({cursor:e.cursor,distinct:e.distinct,include:e.include,orderBy:e.orderBy,select:e.select,skip:e.skip,take:e.take,where:e.where})}getModels(){return this.models??[]}async getOne(t,e,s){const i=this.getPrismaDelegate(t);return await(i.findUnique??i.findOne)({include:s.include,select:s.select,where:{[this.primaryKey]:e}})}async getPaginationData(t,e){const s=await this.getPrismaDelegate(t).count({distinct:e.distinct,where:e.where});return{page:Math.ceil((e.skip??0)/(e.take??0))+1,pageCount:Math.ceil(s/(e.take??0)),total:s}}handleError(t){throw console.error(t),t instanceof Error&&t.stack&&console.error(t.stack),t.constructor.name==="PrismaClientKnownRequestError"||t.constructor.name==="PrismaClientValidationError"?p(400,"invalid request, check your server logs for more info"):p(500,"an unknown error occured, check your server logs for more info")}async init(){const t=this.ctorModels,e=await this.getPrismaClientModels();t!==void 0&&t.forEach(s=>{if(!Object.keys(e).includes(s))throw new Error(`Model name ${s} is invalid.`)}),this.models=t??Object.keys(e)}async mapModelsToRouteNames(){return O.a(await this.getPrismaClientModels(),this.getModels())}parseQuery(t,e){const s={};return e.select&&(s.select=u(e.select,"select")),e.include&&(s.include=u(e.include,"include")),e.originalQuery?.where&&(s.where=x(JSON.parse(e.originalQuery.where),this.manyRelations[t]??[])),e.orderBy&&(s.orderBy=N(e.orderBy)),e.limit!==void 0&&(s.take=e.limit),e.skip!==void 0&&(s.skip=e.skip),e.originalQuery?.cursor&&(s.cursor=q(JSON.parse(e.originalQuery.cursor))),e.distinct&&(s.distinct=e.distinct),s}async update(t,e,s,i){return await this.getPrismaDelegate(t).update({data:s,include:i.include,select:i.select,where:{[this.primaryKey]:e}})}get client(){return this.prismaClient}getPrismaClientModels=y(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")},"getPrismaClientModels");getPrismaDelegate(t){return this.prismaClient[`${t.charAt(0).toLowerCase()}${t.slice(1)}`]}}module.exports=V;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var k=Object.defineProperty;var n=(r,t)=>k(r,"name",{value:t,configurable:!0});import p from"http-errors";import{a as P}from"./models-to-route-names-UU1lZmbK.mjs";var O=Object.defineProperty,C=n((r,t)=>O(r,"name",{value:t,configurable:!0}),"n$1");const j=new Set(["boolean","number","string"]),u=C(r=>j.has(typeof r),"isPrimitive");var M=Object.defineProperty,E=n((r,t)=>M(r,"name",{value:t,configurable:!0}),"s$1");const D=E(r=>{const t={};if(Object.keys(r).forEach(e=>{const s=r[e];u(s)&&(t[e]=s)}),Object.keys(t).length!==1)throw new Error("cursor needs to be an object with exactly 1 property with a primitive value");return t},"parsePrismaCursor");var R=Object.defineProperty,K=n((r,t)=>R(r,"name",{value:t,configurable:!0}),"a");const q={$asc:"asc",$desc:"desc"},B=K(r=>{const t={};return Object.keys(r).forEach(e=>{const s=r[e];t[e]=q[s]}),t},"parsePrismaOrderBy");var S=Object.defineProperty,N=n((r,t)=>S(r,"name",{value:t,configurable:!0}),"u$1");const m=N((r,t)=>{const e={};return Object.keys(r).forEach(s=>{e[s]=r[s]===!0?!0:{[t]:m(r[s],t)}}),e},"parsePrismaRecursiveField");var Q=Object.defineProperty,a=n((r,t)=>Q(r,"name",{value:t,configurable:!0}),"r");const c=a(r=>r instanceof Object,"isObject"),A={$cont:"contains",$ends:"endsWith",$eq:"equals",$gt:"gt",$gte:"gte",$in:"in",$lt:"lt",$lte:"lte",$neq:"not",$notin:"notIn",$starts:"startsWith"},_=a(r=>/^\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(r),"isDateString"),F=a(r=>_(r)?new Date(r):typeof r=="string"&&r==="$isnull"?null:r,"getSearchValue"),g=a((r,t)=>{const e=r.split(".");return e.splice(-1,1),t.includes(e.join("."))},"isRelation"),f=a(r=>{const t=Object.keys(r)[0],e=A[t];if(e)return{[e]:r[t]}},"parseSimpleField"),b=a((r,t,e,s)=>{const i=t.split(".").toReversed();let o={};i.forEach((h,v)=>{v===0?w(r,h,o,s):o={[h]:{some:o}}});const l=i.toReversed()[0],$=e[l];e[l]={some:{...$?.some,...o[l]?.some}}},"parseRelation"),d=a((r,t)=>{const e={};return Object.keys(r).forEach(s=>{const i=r[s];if(g(s,t))b(i,s,e,t);else if(u(i))e[s]=i;else if(c(i)){const o=f(i);o&&(e[s]=o)}}),e},"parseObjectCombination"),w=a((r,t,e,s)=>{if(u(r))e[t]=F(r);else switch(t){case"$and":{c(r)&&(e.AND=d(r,s));break}case"$not":{c(r)&&(e.NOT=d(r,s));break}case"$or":{c(r)&&(e.OR=d(r,s));break}default:{e[t]=f(r);break}}},"basicParse"),T=a((r,t)=>{const e={};return Object.keys(r).forEach(s=>{const i=r[s];g(s,t)?b(i,s,e,t):w(i,s,e,t)}),e},"parsePrismaWhere");var W=Object.defineProperty,y=n((r,t)=>W(r,"name",{value:t,configurable:!0}),"s");class I{static{n(this,"P")}static{y(this,"PrismaAdapter")}models;ctorModels;dmmf;manyRelations;primaryKey;prismaClient;constructor({manyRelations:t={},models:e,primaryKey:s="id",prismaClient:i}){this.prismaClient=i,this.primaryKey=s,this.manyRelations=t,this.ctorModels=e}async connect(){this.prismaClient.$connect()}async create(t,e,s){return await this.getPrismaDelegate(t).create({data:e,include:s.include,select:s.select})}async delete(t,e,s){return await this.getPrismaDelegate(t).delete({include:s.include,select:s.select,where:{[this.primaryKey]:e}})}async disconnect(){await this.prismaClient.$disconnect()}async getAll(t,e){return await this.getPrismaDelegate(t).findMany({cursor:e.cursor,distinct:e.distinct,include:e.include,orderBy:e.orderBy,select:e.select,skip:e.skip,take:e.take,where:e.where})}getModels(){return this.models??[]}async getOne(t,e,s){const i=this.getPrismaDelegate(t);return await(i.findUnique??i.findOne)({include:s.include,select:s.select,where:{[this.primaryKey]:e}})}async getPaginationData(t,e){const s=await this.getPrismaDelegate(t).count({distinct:e.distinct,where:e.where});return{page:Math.ceil((e.skip??0)/(e.take??0))+1,pageCount:Math.ceil(s/(e.take??0)),total:s}}handleError(t){throw console.error(t),t instanceof Error&&t.stack&&console.error(t.stack),t.constructor.name==="PrismaClientKnownRequestError"||t.constructor.name==="PrismaClientValidationError"?p(400,"invalid request, check your server logs for more info"):p(500,"an unknown error occured, check your server logs for more info")}async init(){const t=this.ctorModels,e=await this.getPrismaClientModels();t!==void 0&&t.forEach(s=>{if(!Object.keys(e).includes(s))throw new Error(`Model name ${s} is invalid.`)}),this.models=t??Object.keys(e)}async mapModelsToRouteNames(){return P(await this.getPrismaClientModels(),this.getModels())}parseQuery(t,e){const s={};return e.select&&(s.select=m(e.select,"select")),e.include&&(s.include=m(e.include,"include")),e.originalQuery?.where&&(s.where=T(JSON.parse(e.originalQuery.where),this.manyRelations[t]??[])),e.orderBy&&(s.orderBy=B(e.orderBy)),e.limit!==void 0&&(s.take=e.limit),e.skip!==void 0&&(s.skip=e.skip),e.originalQuery?.cursor&&(s.cursor=D(JSON.parse(e.originalQuery.cursor))),e.distinct&&(s.distinct=e.distinct),s}async update(t,e,s,i){return await this.getPrismaDelegate(t).update({data:s,include:i.include,select:i.select,where:{[this.primaryKey]:e}})}get client(){return this.prismaClient}getPrismaClientModels=y(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")},"getPrismaClientModels");getPrismaDelegate(t){return this.prismaClient[`${t.charAt(0).toLowerCase()}${t.slice(1)}`]}}export{I as default};
|