express-model-binding 1.0.0 → 1.1.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/dist/{BaseAdapter-BjvLQijd.d.mts → BaseAdapter-Dr9a8ZUY.d.mts} +17 -1
- package/dist/{BaseAdapter-BjvLQijd.d.ts → BaseAdapter-Dr9a8ZUY.d.ts} +17 -1
- package/dist/adapters/KnexAdapter.d.mts +1 -1
- package/dist/adapters/KnexAdapter.d.ts +1 -1
- package/dist/adapters/KnexAdapter.js +1 -257
- package/dist/adapters/KnexAdapter.mjs +1 -229
- package/dist/adapters/MongooseAdapter.d.mts +1 -1
- package/dist/adapters/MongooseAdapter.d.ts +1 -1
- package/dist/adapters/MongooseAdapter.js +1 -245
- package/dist/adapters/MongooseAdapter.mjs +1 -225
- package/dist/adapters/PrismaAdapter.d.mts +1 -1
- package/dist/adapters/PrismaAdapter.d.ts +1 -1
- package/dist/adapters/PrismaAdapter.js +1 -247
- package/dist/adapters/PrismaAdapter.mjs +1 -220
- package/dist/adapters/SequelizeAdapter.d.mts +1 -1
- package/dist/adapters/SequelizeAdapter.d.ts +1 -1
- package/dist/adapters/SequelizeAdapter.js +1 -280
- package/dist/adapters/SequelizeAdapter.mjs +1 -260
- package/dist/adapters/TypeORMAdapter.d.mts +1 -1
- package/dist/adapters/TypeORMAdapter.d.ts +1 -1
- package/dist/adapters/TypeORMAdapter.js +1 -294
- package/dist/adapters/TypeORMAdapter.mjs +1 -267
- package/dist/chunk-7I3EYD6K.js +1 -0
- package/dist/chunk-7OR75DD2.mjs +1 -0
- package/dist/chunk-A7LUHNSI.mjs +1 -0
- package/dist/chunk-B3DBSP2J.mjs +1 -0
- package/dist/chunk-CKT6LD2K.js +1 -0
- package/dist/chunk-DBYMXDVA.mjs +1 -0
- package/dist/chunk-EEPSARTF.js +1 -0
- package/dist/chunk-ISSVD3WP.js +1 -0
- package/dist/chunk-LLYCNTZ7.mjs +1 -0
- package/dist/chunk-OKPAWWZN.js +1 -0
- package/dist/chunk-Z6WU7X3A.mjs +1 -0
- package/dist/chunk-ZJ2WW53U.js +1 -0
- package/dist/index.d.mts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +1 -1514
- package/dist/index.mjs +1 -1450
- package/package.json +5 -3
- package/dist/adapters/KnexAdapter.js.map +0 -1
- package/dist/adapters/KnexAdapter.mjs.map +0 -1
- package/dist/adapters/MongooseAdapter.js.map +0 -1
- package/dist/adapters/MongooseAdapter.mjs.map +0 -1
- package/dist/adapters/PrismaAdapter.js.map +0 -1
- package/dist/adapters/PrismaAdapter.mjs.map +0 -1
- package/dist/adapters/SequelizeAdapter.js.map +0 -1
- package/dist/adapters/SequelizeAdapter.mjs.map +0 -1
- package/dist/adapters/TypeORMAdapter.js.map +0 -1
- package/dist/adapters/TypeORMAdapter.mjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
|
@@ -185,6 +185,22 @@ type TypedRequestHandler<Models extends Record<string, unknown> = Record<string,
|
|
|
185
185
|
* Middleware function type
|
|
186
186
|
*/
|
|
187
187
|
type MiddlewareFunction = RequestHandler;
|
|
188
|
+
/**
|
|
189
|
+
* Validate field/column name to prevent injection
|
|
190
|
+
* Only allows alphanumeric, underscores, and dots (for nested fields)
|
|
191
|
+
*/
|
|
192
|
+
declare function isValidFieldName(name: string): boolean;
|
|
193
|
+
/**
|
|
194
|
+
* Operator condition for advanced WHERE clauses
|
|
195
|
+
*/
|
|
196
|
+
interface OperatorCondition {
|
|
197
|
+
operator: string;
|
|
198
|
+
value: unknown;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Check if value is a valid operator condition with whitelisted operator
|
|
202
|
+
*/
|
|
203
|
+
declare function isOperatorCondition(value: unknown): value is OperatorCondition;
|
|
188
204
|
|
|
189
205
|
/**
|
|
190
206
|
* Abstract base class providing common adapter functionality.
|
|
@@ -211,4 +227,4 @@ declare abstract class BaseAdapter<TModel = unknown, TResult = unknown, TQueryBu
|
|
|
211
227
|
protected applyCustomQuery(queryBuilder: TQueryBuilder, queryFn?: QueryModifier<TQueryBuilder>): TQueryBuilder;
|
|
212
228
|
}
|
|
213
229
|
|
|
214
|
-
export { type BindOptions as B, type CacheEntry as C, type ExtractModelType as E, type IORMAdapter as I, type ModelBindingsConfig as M, type QueryOptions as Q, type TypedRequest as T, type BindingResult as a, BaseAdapter as b, type BindingContext as c, type ModelMetadata as d, type ModelBindingGlobalConfig as e, type TypedRequestHandler as f, type MiddlewareFunction as g };
|
|
230
|
+
export { type BindOptions as B, type CacheEntry as C, type ExtractModelType as E, type IORMAdapter as I, type ModelBindingsConfig as M, type OperatorCondition as O, type QueryOptions as Q, type TypedRequest as T, type BindingResult as a, BaseAdapter as b, type BindingContext as c, type ModelMetadata as d, type ModelBindingGlobalConfig as e, type TypedRequestHandler as f, type MiddlewareFunction as g, isOperatorCondition as h, isValidFieldName as i };
|
|
@@ -185,6 +185,22 @@ type TypedRequestHandler<Models extends Record<string, unknown> = Record<string,
|
|
|
185
185
|
* Middleware function type
|
|
186
186
|
*/
|
|
187
187
|
type MiddlewareFunction = RequestHandler;
|
|
188
|
+
/**
|
|
189
|
+
* Validate field/column name to prevent injection
|
|
190
|
+
* Only allows alphanumeric, underscores, and dots (for nested fields)
|
|
191
|
+
*/
|
|
192
|
+
declare function isValidFieldName(name: string): boolean;
|
|
193
|
+
/**
|
|
194
|
+
* Operator condition for advanced WHERE clauses
|
|
195
|
+
*/
|
|
196
|
+
interface OperatorCondition {
|
|
197
|
+
operator: string;
|
|
198
|
+
value: unknown;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Check if value is a valid operator condition with whitelisted operator
|
|
202
|
+
*/
|
|
203
|
+
declare function isOperatorCondition(value: unknown): value is OperatorCondition;
|
|
188
204
|
|
|
189
205
|
/**
|
|
190
206
|
* Abstract base class providing common adapter functionality.
|
|
@@ -211,4 +227,4 @@ declare abstract class BaseAdapter<TModel = unknown, TResult = unknown, TQueryBu
|
|
|
211
227
|
protected applyCustomQuery(queryBuilder: TQueryBuilder, queryFn?: QueryModifier<TQueryBuilder>): TQueryBuilder;
|
|
212
228
|
}
|
|
213
229
|
|
|
214
|
-
export { type BindOptions as B, type CacheEntry as C, type ExtractModelType as E, type IORMAdapter as I, type ModelBindingsConfig as M, type QueryOptions as Q, type TypedRequest as T, type BindingResult as a, BaseAdapter as b, type BindingContext as c, type ModelMetadata as d, type ModelBindingGlobalConfig as e, type TypedRequestHandler as f, type MiddlewareFunction as g };
|
|
230
|
+
export { type BindOptions as B, type CacheEntry as C, type ExtractModelType as E, type IORMAdapter as I, type ModelBindingsConfig as M, type OperatorCondition as O, type QueryOptions as Q, type TypedRequest as T, type BindingResult as a, BaseAdapter as b, type BindingContext as c, type ModelMetadata as d, type ModelBindingGlobalConfig as e, type TypedRequestHandler as f, type MiddlewareFunction as g, isOperatorCondition as h, isValidFieldName as i };
|
|
@@ -1,257 +1 @@
|
|
|
1
|
-
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/adapters/KnexAdapter.ts
|
|
21
|
-
var KnexAdapter_exports = {};
|
|
22
|
-
__export(KnexAdapter_exports, {
|
|
23
|
-
KnexAdapter: () => KnexAdapter,
|
|
24
|
-
defineKnexModel: () => defineKnexModel
|
|
25
|
-
});
|
|
26
|
-
module.exports = __toCommonJS(KnexAdapter_exports);
|
|
27
|
-
|
|
28
|
-
// src/errors/index.ts
|
|
29
|
-
var BindingError = class extends Error {
|
|
30
|
-
constructor(message, originalError) {
|
|
31
|
-
super(message);
|
|
32
|
-
this.name = "BindingError";
|
|
33
|
-
this.originalError = originalError;
|
|
34
|
-
Error.captureStackTrace(this, this.constructor);
|
|
35
|
-
}
|
|
36
|
-
toJSON() {
|
|
37
|
-
return {
|
|
38
|
-
name: this.name,
|
|
39
|
-
message: this.message,
|
|
40
|
-
originalError: this.originalError?.message
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
var InvalidModelError = class extends Error {
|
|
45
|
-
constructor(message, model) {
|
|
46
|
-
super(message);
|
|
47
|
-
this.name = "InvalidModelError";
|
|
48
|
-
this.model = model;
|
|
49
|
-
Error.captureStackTrace(this, this.constructor);
|
|
50
|
-
}
|
|
51
|
-
toJSON() {
|
|
52
|
-
return {
|
|
53
|
-
name: this.name,
|
|
54
|
-
message: this.message,
|
|
55
|
-
model: typeof this.model === "string" ? this.model : String(this.model)
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
// src/core/BaseAdapter.ts
|
|
61
|
-
var BaseAdapter = class {
|
|
62
|
-
transformValue(_model, _key, value) {
|
|
63
|
-
if (/^\d+$/.test(value)) {
|
|
64
|
-
const num = parseInt(value, 10);
|
|
65
|
-
if (!isNaN(num) && Number.isSafeInteger(num)) {
|
|
66
|
-
return num;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return value;
|
|
70
|
-
}
|
|
71
|
-
supportsSoftDeletes(_model) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
getModelMetadata(model) {
|
|
75
|
-
return {
|
|
76
|
-
name: this.getModelName(model),
|
|
77
|
-
primaryKey: this.getPrimaryKeyName(model),
|
|
78
|
-
softDeletes: this.supportsSoftDeletes(model),
|
|
79
|
-
adapter: this.name
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
validateModel(model) {
|
|
83
|
-
if (!this.isValidModel(model)) {
|
|
84
|
-
throw new InvalidModelError(`Invalid model for ${this.name} adapter`, model);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
getModelName(model) {
|
|
88
|
-
if (typeof model === "string") {
|
|
89
|
-
return model;
|
|
90
|
-
}
|
|
91
|
-
if (model && typeof model === "object") {
|
|
92
|
-
const obj = model;
|
|
93
|
-
if (typeof obj.name === "string") return obj.name;
|
|
94
|
-
if (typeof obj.modelName === "string") return obj.modelName;
|
|
95
|
-
if (typeof obj.tableName === "string") return obj.tableName;
|
|
96
|
-
}
|
|
97
|
-
if (model && typeof model === "function") {
|
|
98
|
-
return model.name || "Unknown";
|
|
99
|
-
}
|
|
100
|
-
return "Unknown";
|
|
101
|
-
}
|
|
102
|
-
applySoftDeleteFilter(queryBuilder, _options) {
|
|
103
|
-
return queryBuilder;
|
|
104
|
-
}
|
|
105
|
-
applyIncludes(queryBuilder, _includes) {
|
|
106
|
-
return queryBuilder;
|
|
107
|
-
}
|
|
108
|
-
applySelect(queryBuilder, _select) {
|
|
109
|
-
return queryBuilder;
|
|
110
|
-
}
|
|
111
|
-
applyWhereConditions(queryBuilder, _where) {
|
|
112
|
-
return queryBuilder;
|
|
113
|
-
}
|
|
114
|
-
applyCustomQuery(queryBuilder, queryFn) {
|
|
115
|
-
if (queryFn) {
|
|
116
|
-
return queryFn(queryBuilder);
|
|
117
|
-
}
|
|
118
|
-
return queryBuilder;
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
// src/core/types.ts
|
|
123
|
-
function isOperatorCondition(value) {
|
|
124
|
-
return typeof value === "object" && value !== null && "operator" in value && "value" in value;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// src/utils/validators.ts
|
|
128
|
-
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
129
|
-
function isUUID(value) {
|
|
130
|
-
return UUID_REGEX.test(value);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// src/adapters/KnexAdapter.ts
|
|
134
|
-
function isKnexModel(value) {
|
|
135
|
-
return typeof value === "object" && value !== null && typeof value.tableName === "string";
|
|
136
|
-
}
|
|
137
|
-
var KnexAdapter = class extends BaseAdapter {
|
|
138
|
-
constructor(knex) {
|
|
139
|
-
super();
|
|
140
|
-
this.knex = knex;
|
|
141
|
-
this.name = "knex";
|
|
142
|
-
}
|
|
143
|
-
getKnex() {
|
|
144
|
-
return this.knex;
|
|
145
|
-
}
|
|
146
|
-
async findByKey(model, key, value, options = {}) {
|
|
147
|
-
this.validateModel(model);
|
|
148
|
-
const tableName = this.getTableName(model);
|
|
149
|
-
try {
|
|
150
|
-
let query = this.knex(tableName);
|
|
151
|
-
query = query.where(key, value);
|
|
152
|
-
if (this.supportsSoftDeletes(model) && !options.withTrashed && !options.onlyTrashed) {
|
|
153
|
-
const softDeleteColumn = this.getSoftDeleteColumn(model);
|
|
154
|
-
query = query.whereNull(softDeleteColumn);
|
|
155
|
-
} else if (options.onlyTrashed && this.supportsSoftDeletes(model)) {
|
|
156
|
-
const softDeleteColumn = this.getSoftDeleteColumn(model);
|
|
157
|
-
query = query.whereNotNull(softDeleteColumn);
|
|
158
|
-
}
|
|
159
|
-
if (options.where) {
|
|
160
|
-
query = this.applyWhereConditions(query, options.where);
|
|
161
|
-
}
|
|
162
|
-
if (options.select && options.select.length > 0) {
|
|
163
|
-
query = query.select(options.select);
|
|
164
|
-
} else {
|
|
165
|
-
query = query.select("*");
|
|
166
|
-
}
|
|
167
|
-
if (options.query) {
|
|
168
|
-
query = this.applyCustomQuery(
|
|
169
|
-
query,
|
|
170
|
-
options.query
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
if (options.lock === "forUpdate") {
|
|
174
|
-
query = query.forUpdate();
|
|
175
|
-
} else if (options.lock === "forShare") {
|
|
176
|
-
query = query.forShare();
|
|
177
|
-
}
|
|
178
|
-
const result = await query.first();
|
|
179
|
-
return result || null;
|
|
180
|
-
} catch (error) {
|
|
181
|
-
throw new BindingError(
|
|
182
|
-
`Failed to fetch ${this.getModelName(model)}: ${error.message}`,
|
|
183
|
-
error
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
getPrimaryKeyName(model) {
|
|
188
|
-
if (isKnexModel(model) && model.primaryKey) {
|
|
189
|
-
return model.primaryKey;
|
|
190
|
-
}
|
|
191
|
-
return "id";
|
|
192
|
-
}
|
|
193
|
-
isValidModel(model) {
|
|
194
|
-
return typeof model === "string" || isKnexModel(model);
|
|
195
|
-
}
|
|
196
|
-
transformValue(model, key, value) {
|
|
197
|
-
const primaryKey = this.getPrimaryKeyName(model);
|
|
198
|
-
if (key === primaryKey || key === "id") {
|
|
199
|
-
const num = parseInt(value, 10);
|
|
200
|
-
if (!isNaN(num) && num.toString() === value && Number.isSafeInteger(num)) {
|
|
201
|
-
return num;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
if (isUUID(value)) {
|
|
205
|
-
return value;
|
|
206
|
-
}
|
|
207
|
-
return value;
|
|
208
|
-
}
|
|
209
|
-
supportsSoftDeletes(model) {
|
|
210
|
-
return isKnexModel(model) && !!model.softDeleteColumn;
|
|
211
|
-
}
|
|
212
|
-
getModelMetadata(model) {
|
|
213
|
-
return {
|
|
214
|
-
name: this.getModelName(model),
|
|
215
|
-
primaryKey: this.getPrimaryKeyName(model),
|
|
216
|
-
tableName: this.getTableName(model),
|
|
217
|
-
softDeletes: this.supportsSoftDeletes(model),
|
|
218
|
-
adapter: this.name
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
getTableName(model) {
|
|
222
|
-
return typeof model === "string" ? model : model.tableName;
|
|
223
|
-
}
|
|
224
|
-
getSoftDeleteColumn(model) {
|
|
225
|
-
if (isKnexModel(model) && model.softDeleteColumn) {
|
|
226
|
-
return model.softDeleteColumn;
|
|
227
|
-
}
|
|
228
|
-
return "deleted_at";
|
|
229
|
-
}
|
|
230
|
-
applyWhereConditions(query, where) {
|
|
231
|
-
Object.entries(where).forEach(([column, value]) => {
|
|
232
|
-
if (value === null) {
|
|
233
|
-
query = query.whereNull(column);
|
|
234
|
-
} else if (Array.isArray(value)) {
|
|
235
|
-
query = query.whereIn(column, value);
|
|
236
|
-
} else if (isOperatorCondition(value)) {
|
|
237
|
-
query = query.where(column, value.operator, value.value);
|
|
238
|
-
} else {
|
|
239
|
-
query = query.where(column, value);
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
return query;
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
function defineKnexModel(config) {
|
|
246
|
-
return {
|
|
247
|
-
tableName: config.tableName,
|
|
248
|
-
primaryKey: config.primaryKey || "id",
|
|
249
|
-
softDeleteColumn: config.softDeleteColumn
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
253
|
-
0 && (module.exports = {
|
|
254
|
-
KnexAdapter,
|
|
255
|
-
defineKnexModel
|
|
256
|
-
});
|
|
257
|
-
//# sourceMappingURL=KnexAdapter.js.map
|
|
1
|
+
'use strict';var chunkEEPSARTF_js=require('../chunk-EEPSARTF.js');require('../chunk-7I3EYD6K.js');Object.defineProperty(exports,"KnexAdapter",{enumerable:true,get:function(){return chunkEEPSARTF_js.a}});Object.defineProperty(exports,"defineKnexModel",{enumerable:true,get:function(){return chunkEEPSARTF_js.b}});
|
|
@@ -1,229 +1 @@
|
|
|
1
|
-
|
|
2
|
-
var BindingError = class extends Error {
|
|
3
|
-
constructor(message, originalError) {
|
|
4
|
-
super(message);
|
|
5
|
-
this.name = "BindingError";
|
|
6
|
-
this.originalError = originalError;
|
|
7
|
-
Error.captureStackTrace(this, this.constructor);
|
|
8
|
-
}
|
|
9
|
-
toJSON() {
|
|
10
|
-
return {
|
|
11
|
-
name: this.name,
|
|
12
|
-
message: this.message,
|
|
13
|
-
originalError: this.originalError?.message
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
var InvalidModelError = class extends Error {
|
|
18
|
-
constructor(message, model) {
|
|
19
|
-
super(message);
|
|
20
|
-
this.name = "InvalidModelError";
|
|
21
|
-
this.model = model;
|
|
22
|
-
Error.captureStackTrace(this, this.constructor);
|
|
23
|
-
}
|
|
24
|
-
toJSON() {
|
|
25
|
-
return {
|
|
26
|
-
name: this.name,
|
|
27
|
-
message: this.message,
|
|
28
|
-
model: typeof this.model === "string" ? this.model : String(this.model)
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
// src/core/BaseAdapter.ts
|
|
34
|
-
var BaseAdapter = class {
|
|
35
|
-
transformValue(_model, _key, value) {
|
|
36
|
-
if (/^\d+$/.test(value)) {
|
|
37
|
-
const num = parseInt(value, 10);
|
|
38
|
-
if (!isNaN(num) && Number.isSafeInteger(num)) {
|
|
39
|
-
return num;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return value;
|
|
43
|
-
}
|
|
44
|
-
supportsSoftDeletes(_model) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
getModelMetadata(model) {
|
|
48
|
-
return {
|
|
49
|
-
name: this.getModelName(model),
|
|
50
|
-
primaryKey: this.getPrimaryKeyName(model),
|
|
51
|
-
softDeletes: this.supportsSoftDeletes(model),
|
|
52
|
-
adapter: this.name
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
validateModel(model) {
|
|
56
|
-
if (!this.isValidModel(model)) {
|
|
57
|
-
throw new InvalidModelError(`Invalid model for ${this.name} adapter`, model);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
getModelName(model) {
|
|
61
|
-
if (typeof model === "string") {
|
|
62
|
-
return model;
|
|
63
|
-
}
|
|
64
|
-
if (model && typeof model === "object") {
|
|
65
|
-
const obj = model;
|
|
66
|
-
if (typeof obj.name === "string") return obj.name;
|
|
67
|
-
if (typeof obj.modelName === "string") return obj.modelName;
|
|
68
|
-
if (typeof obj.tableName === "string") return obj.tableName;
|
|
69
|
-
}
|
|
70
|
-
if (model && typeof model === "function") {
|
|
71
|
-
return model.name || "Unknown";
|
|
72
|
-
}
|
|
73
|
-
return "Unknown";
|
|
74
|
-
}
|
|
75
|
-
applySoftDeleteFilter(queryBuilder, _options) {
|
|
76
|
-
return queryBuilder;
|
|
77
|
-
}
|
|
78
|
-
applyIncludes(queryBuilder, _includes) {
|
|
79
|
-
return queryBuilder;
|
|
80
|
-
}
|
|
81
|
-
applySelect(queryBuilder, _select) {
|
|
82
|
-
return queryBuilder;
|
|
83
|
-
}
|
|
84
|
-
applyWhereConditions(queryBuilder, _where) {
|
|
85
|
-
return queryBuilder;
|
|
86
|
-
}
|
|
87
|
-
applyCustomQuery(queryBuilder, queryFn) {
|
|
88
|
-
if (queryFn) {
|
|
89
|
-
return queryFn(queryBuilder);
|
|
90
|
-
}
|
|
91
|
-
return queryBuilder;
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
// src/core/types.ts
|
|
96
|
-
function isOperatorCondition(value) {
|
|
97
|
-
return typeof value === "object" && value !== null && "operator" in value && "value" in value;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// src/utils/validators.ts
|
|
101
|
-
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
102
|
-
function isUUID(value) {
|
|
103
|
-
return UUID_REGEX.test(value);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// src/adapters/KnexAdapter.ts
|
|
107
|
-
function isKnexModel(value) {
|
|
108
|
-
return typeof value === "object" && value !== null && typeof value.tableName === "string";
|
|
109
|
-
}
|
|
110
|
-
var KnexAdapter = class extends BaseAdapter {
|
|
111
|
-
constructor(knex) {
|
|
112
|
-
super();
|
|
113
|
-
this.knex = knex;
|
|
114
|
-
this.name = "knex";
|
|
115
|
-
}
|
|
116
|
-
getKnex() {
|
|
117
|
-
return this.knex;
|
|
118
|
-
}
|
|
119
|
-
async findByKey(model, key, value, options = {}) {
|
|
120
|
-
this.validateModel(model);
|
|
121
|
-
const tableName = this.getTableName(model);
|
|
122
|
-
try {
|
|
123
|
-
let query = this.knex(tableName);
|
|
124
|
-
query = query.where(key, value);
|
|
125
|
-
if (this.supportsSoftDeletes(model) && !options.withTrashed && !options.onlyTrashed) {
|
|
126
|
-
const softDeleteColumn = this.getSoftDeleteColumn(model);
|
|
127
|
-
query = query.whereNull(softDeleteColumn);
|
|
128
|
-
} else if (options.onlyTrashed && this.supportsSoftDeletes(model)) {
|
|
129
|
-
const softDeleteColumn = this.getSoftDeleteColumn(model);
|
|
130
|
-
query = query.whereNotNull(softDeleteColumn);
|
|
131
|
-
}
|
|
132
|
-
if (options.where) {
|
|
133
|
-
query = this.applyWhereConditions(query, options.where);
|
|
134
|
-
}
|
|
135
|
-
if (options.select && options.select.length > 0) {
|
|
136
|
-
query = query.select(options.select);
|
|
137
|
-
} else {
|
|
138
|
-
query = query.select("*");
|
|
139
|
-
}
|
|
140
|
-
if (options.query) {
|
|
141
|
-
query = this.applyCustomQuery(
|
|
142
|
-
query,
|
|
143
|
-
options.query
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
if (options.lock === "forUpdate") {
|
|
147
|
-
query = query.forUpdate();
|
|
148
|
-
} else if (options.lock === "forShare") {
|
|
149
|
-
query = query.forShare();
|
|
150
|
-
}
|
|
151
|
-
const result = await query.first();
|
|
152
|
-
return result || null;
|
|
153
|
-
} catch (error) {
|
|
154
|
-
throw new BindingError(
|
|
155
|
-
`Failed to fetch ${this.getModelName(model)}: ${error.message}`,
|
|
156
|
-
error
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
getPrimaryKeyName(model) {
|
|
161
|
-
if (isKnexModel(model) && model.primaryKey) {
|
|
162
|
-
return model.primaryKey;
|
|
163
|
-
}
|
|
164
|
-
return "id";
|
|
165
|
-
}
|
|
166
|
-
isValidModel(model) {
|
|
167
|
-
return typeof model === "string" || isKnexModel(model);
|
|
168
|
-
}
|
|
169
|
-
transformValue(model, key, value) {
|
|
170
|
-
const primaryKey = this.getPrimaryKeyName(model);
|
|
171
|
-
if (key === primaryKey || key === "id") {
|
|
172
|
-
const num = parseInt(value, 10);
|
|
173
|
-
if (!isNaN(num) && num.toString() === value && Number.isSafeInteger(num)) {
|
|
174
|
-
return num;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (isUUID(value)) {
|
|
178
|
-
return value;
|
|
179
|
-
}
|
|
180
|
-
return value;
|
|
181
|
-
}
|
|
182
|
-
supportsSoftDeletes(model) {
|
|
183
|
-
return isKnexModel(model) && !!model.softDeleteColumn;
|
|
184
|
-
}
|
|
185
|
-
getModelMetadata(model) {
|
|
186
|
-
return {
|
|
187
|
-
name: this.getModelName(model),
|
|
188
|
-
primaryKey: this.getPrimaryKeyName(model),
|
|
189
|
-
tableName: this.getTableName(model),
|
|
190
|
-
softDeletes: this.supportsSoftDeletes(model),
|
|
191
|
-
adapter: this.name
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
getTableName(model) {
|
|
195
|
-
return typeof model === "string" ? model : model.tableName;
|
|
196
|
-
}
|
|
197
|
-
getSoftDeleteColumn(model) {
|
|
198
|
-
if (isKnexModel(model) && model.softDeleteColumn) {
|
|
199
|
-
return model.softDeleteColumn;
|
|
200
|
-
}
|
|
201
|
-
return "deleted_at";
|
|
202
|
-
}
|
|
203
|
-
applyWhereConditions(query, where) {
|
|
204
|
-
Object.entries(where).forEach(([column, value]) => {
|
|
205
|
-
if (value === null) {
|
|
206
|
-
query = query.whereNull(column);
|
|
207
|
-
} else if (Array.isArray(value)) {
|
|
208
|
-
query = query.whereIn(column, value);
|
|
209
|
-
} else if (isOperatorCondition(value)) {
|
|
210
|
-
query = query.where(column, value.operator, value.value);
|
|
211
|
-
} else {
|
|
212
|
-
query = query.where(column, value);
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
return query;
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
function defineKnexModel(config) {
|
|
219
|
-
return {
|
|
220
|
-
tableName: config.tableName,
|
|
221
|
-
primaryKey: config.primaryKey || "id",
|
|
222
|
-
softDeleteColumn: config.softDeleteColumn
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
export {
|
|
226
|
-
KnexAdapter,
|
|
227
|
-
defineKnexModel
|
|
228
|
-
};
|
|
229
|
-
//# sourceMappingURL=KnexAdapter.mjs.map
|
|
1
|
+
export{a as KnexAdapter,b as defineKnexModel}from'../chunk-Z6WU7X3A.mjs';import'../chunk-DBYMXDVA.mjs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Model, Document, Schema, Query } from 'mongoose';
|
|
2
|
-
import { b as BaseAdapter, Q as QueryOptions, d as ModelMetadata } from '../BaseAdapter-
|
|
2
|
+
import { b as BaseAdapter, Q as QueryOptions, d as ModelMetadata } from '../BaseAdapter-Dr9a8ZUY.mjs';
|
|
3
3
|
import 'express';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Model, Document, Schema, Query } from 'mongoose';
|
|
2
|
-
import { b as BaseAdapter, Q as QueryOptions, d as ModelMetadata } from '../BaseAdapter-
|
|
2
|
+
import { b as BaseAdapter, Q as QueryOptions, d as ModelMetadata } from '../BaseAdapter-Dr9a8ZUY.js';
|
|
3
3
|
import 'express';
|
|
4
4
|
|
|
5
5
|
/**
|