elseware-nodejs 1.8.7 → 1.9.1
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/index.cjs +593 -319
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +228 -102
- package/dist/index.d.ts +228 -102
- package/dist/index.js +576 -312
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var mongoose = require('mongoose');
|
|
4
3
|
var dotenv = require('dotenv');
|
|
4
|
+
var mongoose = require('mongoose');
|
|
5
5
|
var storageBlob = require('@azure/storage-blob');
|
|
6
6
|
var fs3 = require('fs');
|
|
7
7
|
var cloudinaryModule = require('cloudinary');
|
|
@@ -14,8 +14,8 @@ var multer = require('multer');
|
|
|
14
14
|
|
|
15
15
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
16
|
|
|
17
|
-
var mongoose__default = /*#__PURE__*/_interopDefault(mongoose);
|
|
18
17
|
var dotenv__default = /*#__PURE__*/_interopDefault(dotenv);
|
|
18
|
+
var mongoose__default = /*#__PURE__*/_interopDefault(mongoose);
|
|
19
19
|
var fs3__default = /*#__PURE__*/_interopDefault(fs3);
|
|
20
20
|
var cloudinaryModule__default = /*#__PURE__*/_interopDefault(cloudinaryModule);
|
|
21
21
|
var nodemailer__default = /*#__PURE__*/_interopDefault(nodemailer);
|
|
@@ -25,252 +25,7 @@ var juice__default = /*#__PURE__*/_interopDefault(juice);
|
|
|
25
25
|
var jwt__default = /*#__PURE__*/_interopDefault(jwt);
|
|
26
26
|
var multer__default = /*#__PURE__*/_interopDefault(multer);
|
|
27
27
|
|
|
28
|
-
// src/
|
|
29
|
-
var AppError = class extends Error {
|
|
30
|
-
statusCode;
|
|
31
|
-
status;
|
|
32
|
-
isOperational;
|
|
33
|
-
code;
|
|
34
|
-
details;
|
|
35
|
-
constructor(message, statusCode = 500, options) {
|
|
36
|
-
super(message);
|
|
37
|
-
this.statusCode = statusCode;
|
|
38
|
-
this.status = `${statusCode}`.startsWith("4") ? "fail" : "error";
|
|
39
|
-
this.isOperational = true;
|
|
40
|
-
this.code = options?.code;
|
|
41
|
-
this.details = options?.details;
|
|
42
|
-
Error.captureStackTrace(this, this.constructor);
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// src/api/apiResponse.ts
|
|
47
|
-
var APIResponse = class _APIResponse {
|
|
48
|
-
static send(res, options) {
|
|
49
|
-
const {
|
|
50
|
-
statusCode = 200,
|
|
51
|
-
success = true,
|
|
52
|
-
message = "Success",
|
|
53
|
-
data,
|
|
54
|
-
meta
|
|
55
|
-
} = options;
|
|
56
|
-
if (statusCode === 204) {
|
|
57
|
-
return res.status(204).send();
|
|
58
|
-
}
|
|
59
|
-
const body = {
|
|
60
|
-
success,
|
|
61
|
-
message,
|
|
62
|
-
...data !== void 0 && { data },
|
|
63
|
-
...meta !== void 0 && { meta }
|
|
64
|
-
};
|
|
65
|
-
return res.status(statusCode).json(body);
|
|
66
|
-
}
|
|
67
|
-
static ok(res, data, message = "Success", meta) {
|
|
68
|
-
return _APIResponse.send(res, { statusCode: 200, data, message, meta });
|
|
69
|
-
}
|
|
70
|
-
static created(res, data, message = "Resource created successfully") {
|
|
71
|
-
return _APIResponse.send(res, { statusCode: 201, data, message });
|
|
72
|
-
}
|
|
73
|
-
static noContent(res) {
|
|
74
|
-
return _APIResponse.send(res, { statusCode: 204 });
|
|
75
|
-
}
|
|
76
|
-
static error(res, message = "Internal Server Error", statusCode = 500, meta) {
|
|
77
|
-
return _APIResponse.send(res, {
|
|
78
|
-
success: false,
|
|
79
|
-
statusCode,
|
|
80
|
-
message,
|
|
81
|
-
meta
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
static paginated(res, data, options, message = "Data fetched successfully") {
|
|
85
|
-
return _APIResponse.ok(res, data, message, {
|
|
86
|
-
total: options.total,
|
|
87
|
-
page: options.page,
|
|
88
|
-
limit: options.limit,
|
|
89
|
-
totalPages: Math.ceil(options.total / options.limit)
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
// src/api/asyncHandler.ts
|
|
95
|
-
var asyncHandler = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
|
|
96
|
-
|
|
97
|
-
// src/api/apiFeatures.ts
|
|
98
|
-
var APIFeatures = class {
|
|
99
|
-
query;
|
|
100
|
-
queryString;
|
|
101
|
-
page;
|
|
102
|
-
limit;
|
|
103
|
-
constructor(query, queryString) {
|
|
104
|
-
this.query = query;
|
|
105
|
-
this.queryString = queryString;
|
|
106
|
-
this.page = 1;
|
|
107
|
-
this.limit = 100;
|
|
108
|
-
}
|
|
109
|
-
filter() {
|
|
110
|
-
const queryObj = { ...this.queryString };
|
|
111
|
-
["page", "sort", "limit", "fields"].forEach((el) => delete queryObj[el]);
|
|
112
|
-
let queryStr = JSON.stringify(queryObj);
|
|
113
|
-
queryStr = queryStr.replace(
|
|
114
|
-
/\b(gte|gt|lte|lt|in)\b/g,
|
|
115
|
-
(match) => `$${match}`
|
|
116
|
-
);
|
|
117
|
-
this.query = this.query.find(JSON.parse(queryStr));
|
|
118
|
-
return this;
|
|
119
|
-
}
|
|
120
|
-
sort() {
|
|
121
|
-
if (this.queryString.sort) {
|
|
122
|
-
const sortBy = String(this.queryString.sort).split(",").join(" ");
|
|
123
|
-
this.query = this.query.sort(sortBy);
|
|
124
|
-
} else {
|
|
125
|
-
this.query = this.query.sort("-createdAt");
|
|
126
|
-
}
|
|
127
|
-
return this;
|
|
128
|
-
}
|
|
129
|
-
limitFields() {
|
|
130
|
-
if (this.queryString.fields) {
|
|
131
|
-
const fields = String(this.queryString.fields).split(",").join(" ");
|
|
132
|
-
this.query = this.query.select(fields);
|
|
133
|
-
} else {
|
|
134
|
-
this.query = this.query.select("-__v");
|
|
135
|
-
}
|
|
136
|
-
return this;
|
|
137
|
-
}
|
|
138
|
-
paginate() {
|
|
139
|
-
this.page = Number(this.queryString.page) || 1;
|
|
140
|
-
this.limit = Number(this.queryString.limit) || 100;
|
|
141
|
-
const skip = (this.page - 1) * this.limit;
|
|
142
|
-
this.query = this.query.skip(skip).limit(this.limit);
|
|
143
|
-
return this;
|
|
144
|
-
}
|
|
145
|
-
populate(populateOptions) {
|
|
146
|
-
if (populateOptions) {
|
|
147
|
-
this.query = this.query.populate(populateOptions);
|
|
148
|
-
}
|
|
149
|
-
return this;
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
var apiFeatures_default = APIFeatures;
|
|
153
|
-
|
|
154
|
-
// src/api/apiFactory.ts
|
|
155
|
-
var APIFactory = class {
|
|
156
|
-
static getAll(Model, options = {}) {
|
|
157
|
-
return asyncHandler(async (req, res) => {
|
|
158
|
-
const filter = options.filter ? options.filter(req) : {};
|
|
159
|
-
const features = new apiFeatures_default(Model.find(filter), req.query).filter().sort().limitFields().paginate().populate(options.populate);
|
|
160
|
-
const docs = await features.query;
|
|
161
|
-
APIResponse.ok(
|
|
162
|
-
res,
|
|
163
|
-
docs,
|
|
164
|
-
options.message ?? "Records fetched successfully",
|
|
165
|
-
{
|
|
166
|
-
count: docs.length,
|
|
167
|
-
page: features.page,
|
|
168
|
-
limit: features.limit
|
|
169
|
-
}
|
|
170
|
-
);
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
static getOne(Model, options = {}) {
|
|
174
|
-
return asyncHandler(async (req, res) => {
|
|
175
|
-
let query = Model.findById(req.params.id);
|
|
176
|
-
if (options.populate) {
|
|
177
|
-
query = query.populate(
|
|
178
|
-
options.populate
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
const doc = await query;
|
|
182
|
-
if (!doc) {
|
|
183
|
-
throw new AppError(
|
|
184
|
-
options.notFoundMessage ?? "Resource not found",
|
|
185
|
-
404,
|
|
186
|
-
{ code: "RESOURCE_NOT_FOUND" }
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
APIResponse.ok(res, doc);
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
static createOne(Model, options = {}) {
|
|
193
|
-
return asyncHandler(async (req, res) => {
|
|
194
|
-
const doc = await Model.create(req.body);
|
|
195
|
-
APIResponse.created(
|
|
196
|
-
res,
|
|
197
|
-
doc,
|
|
198
|
-
options.message ?? "Resource created successfully"
|
|
199
|
-
);
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
static updateOne(Model, options = {}) {
|
|
203
|
-
return asyncHandler(async (req, res) => {
|
|
204
|
-
const doc = await Model.findByIdAndUpdate(
|
|
205
|
-
req.params.id,
|
|
206
|
-
req.body,
|
|
207
|
-
{
|
|
208
|
-
new: true,
|
|
209
|
-
runValidators: true
|
|
210
|
-
}
|
|
211
|
-
);
|
|
212
|
-
if (!doc) {
|
|
213
|
-
throw new AppError(
|
|
214
|
-
options.notFoundMessage ?? "Resource not found",
|
|
215
|
-
404
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
|
-
APIResponse.ok(
|
|
219
|
-
res,
|
|
220
|
-
doc,
|
|
221
|
-
options.message ?? "Resource updated successfully"
|
|
222
|
-
);
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
static deleteOne(Model, options = {}) {
|
|
226
|
-
return asyncHandler(async (req, res) => {
|
|
227
|
-
const doc = await Model.findByIdAndDelete(req.params.id);
|
|
228
|
-
if (!doc) {
|
|
229
|
-
throw new AppError(
|
|
230
|
-
options.notFoundMessage ?? "Resource not found",
|
|
231
|
-
404
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
APIResponse.noContent(res);
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
// src/api/pickFields.ts
|
|
240
|
-
function pickFields(obj, fields, options = {}) {
|
|
241
|
-
const removeUndefined = options.removeUndefined ?? false;
|
|
242
|
-
const removeNull = options.removeNull ?? false;
|
|
243
|
-
const removeEmptyString = options.removeEmptyString ?? false;
|
|
244
|
-
const strict = options.strict ?? false;
|
|
245
|
-
const defaults = options.defaults ?? {};
|
|
246
|
-
const rename = options.rename ?? {};
|
|
247
|
-
const transform = options.transform ?? {};
|
|
248
|
-
const result = {};
|
|
249
|
-
if (strict) {
|
|
250
|
-
for (const key of Object.keys(obj)) {
|
|
251
|
-
if (!fields.includes(key)) {
|
|
252
|
-
throw new Error(`Unknown field: ${key}`);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
for (const field of fields) {
|
|
257
|
-
let value = obj[field];
|
|
258
|
-
if (value === void 0 && field in defaults) {
|
|
259
|
-
value = defaults[field];
|
|
260
|
-
}
|
|
261
|
-
if (removeUndefined && value === void 0) continue;
|
|
262
|
-
if (removeNull && value === null) continue;
|
|
263
|
-
if (removeEmptyString && value === "") continue;
|
|
264
|
-
if (transform[field]) {
|
|
265
|
-
value = transform[field](value);
|
|
266
|
-
}
|
|
267
|
-
const outputKey = rename[field] ?? field;
|
|
268
|
-
if (Object.prototype.hasOwnProperty.call(obj, field) || field in defaults) {
|
|
269
|
-
result[outputKey] = value;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return result;
|
|
273
|
-
}
|
|
28
|
+
// src/configs/env.ts
|
|
274
29
|
|
|
275
30
|
// src/utils/errorToString.ts
|
|
276
31
|
function errorToString(error) {
|
|
@@ -329,25 +84,7 @@ ${errorToString(error)}`);
|
|
|
329
84
|
};
|
|
330
85
|
var logger = new Logger();
|
|
331
86
|
|
|
332
|
-
// src/configs/
|
|
333
|
-
async function connectMongoDB(config) {
|
|
334
|
-
try {
|
|
335
|
-
mongoose__default.default.set("strictQuery", true);
|
|
336
|
-
await mongoose__default.default.connect(config.uri);
|
|
337
|
-
logger.success("Database connected successfully");
|
|
338
|
-
process.on("SIGINT", async () => {
|
|
339
|
-
await mongoose__default.default.connection.close();
|
|
340
|
-
logger.success("Database connection closed");
|
|
341
|
-
process.exit(0);
|
|
342
|
-
});
|
|
343
|
-
} catch (error) {
|
|
344
|
-
logger.danger("Database connection failed");
|
|
345
|
-
if (error instanceof Error) {
|
|
346
|
-
logger.danger(error.message);
|
|
347
|
-
}
|
|
348
|
-
process.exit(1);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
87
|
+
// src/configs/env.ts
|
|
351
88
|
dotenv__default.default.config({ quiet: true });
|
|
352
89
|
function loadEnv(options) {
|
|
353
90
|
const result = options.schema.safeParse(process.env);
|
|
@@ -2182,6 +1919,7 @@ var CircularQueue = class {
|
|
|
2182
1919
|
}
|
|
2183
1920
|
this.data = new Array(capacity);
|
|
2184
1921
|
}
|
|
1922
|
+
capacity;
|
|
2185
1923
|
data;
|
|
2186
1924
|
head = 0;
|
|
2187
1925
|
tail = 0;
|
|
@@ -5102,22 +4840,403 @@ var SegmentTree = class {
|
|
|
5102
4840
|
}
|
|
5103
4841
|
};
|
|
5104
4842
|
|
|
5105
|
-
// src/
|
|
4843
|
+
// src/database/DatabaseManager.ts
|
|
4844
|
+
var DatabaseManager = class {
|
|
4845
|
+
constructor(provider, options = {
|
|
4846
|
+
enableShutdownHooks: true
|
|
4847
|
+
}) {
|
|
4848
|
+
this.provider = provider;
|
|
4849
|
+
this.options = options;
|
|
4850
|
+
}
|
|
4851
|
+
provider;
|
|
4852
|
+
options;
|
|
4853
|
+
async connect() {
|
|
4854
|
+
try {
|
|
4855
|
+
await this.provider.connect();
|
|
4856
|
+
logger.success("Database connected successfully");
|
|
4857
|
+
if (this.options.enableShutdownHooks) {
|
|
4858
|
+
this.registerShutdownHooks();
|
|
4859
|
+
}
|
|
4860
|
+
} catch (error) {
|
|
4861
|
+
logger.danger("Database connection failed", error);
|
|
4862
|
+
throw error;
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
4865
|
+
async disconnect() {
|
|
4866
|
+
try {
|
|
4867
|
+
await this.provider.disconnect();
|
|
4868
|
+
logger.success("Database connection closed");
|
|
4869
|
+
} catch (error) {
|
|
4870
|
+
logger.danger("Database disconnect failed", error);
|
|
4871
|
+
throw error;
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4874
|
+
isConnected() {
|
|
4875
|
+
return this.provider.isConnected();
|
|
4876
|
+
}
|
|
4877
|
+
getConnectionState() {
|
|
4878
|
+
return this.provider.getConnectionState();
|
|
4879
|
+
}
|
|
4880
|
+
registerShutdownHooks() {
|
|
4881
|
+
process.once("SIGINT", async () => {
|
|
4882
|
+
await this.disconnect();
|
|
4883
|
+
process.exit(0);
|
|
4884
|
+
});
|
|
4885
|
+
process.once("SIGTERM", async () => {
|
|
4886
|
+
await this.disconnect();
|
|
4887
|
+
process.exit(0);
|
|
4888
|
+
});
|
|
4889
|
+
}
|
|
4890
|
+
};
|
|
4891
|
+
var MongoDatabaseProvider = class {
|
|
4892
|
+
constructor(config) {
|
|
4893
|
+
this.config = config;
|
|
4894
|
+
}
|
|
4895
|
+
config;
|
|
4896
|
+
async connect() {
|
|
4897
|
+
mongoose__default.default.set("strictQuery", this.config.strictQuery ?? true);
|
|
4898
|
+
await mongoose__default.default.connect(this.config.uri);
|
|
4899
|
+
}
|
|
4900
|
+
async disconnect() {
|
|
4901
|
+
await mongoose__default.default.disconnect();
|
|
4902
|
+
}
|
|
4903
|
+
isConnected() {
|
|
4904
|
+
return mongoose__default.default.connection.readyState === 1;
|
|
4905
|
+
}
|
|
4906
|
+
getConnectionState() {
|
|
4907
|
+
switch (mongoose__default.default.connection.readyState) {
|
|
4908
|
+
case 0:
|
|
4909
|
+
return "disconnected";
|
|
4910
|
+
case 1:
|
|
4911
|
+
return "connected";
|
|
4912
|
+
case 2:
|
|
4913
|
+
return "connecting";
|
|
4914
|
+
case 3:
|
|
4915
|
+
return "disconnecting";
|
|
4916
|
+
default:
|
|
4917
|
+
return "unknown";
|
|
4918
|
+
}
|
|
4919
|
+
}
|
|
4920
|
+
};
|
|
4921
|
+
|
|
4922
|
+
// src/errors/appError.ts
|
|
4923
|
+
var AppError = class extends Error {
|
|
4924
|
+
statusCode;
|
|
4925
|
+
status;
|
|
4926
|
+
isOperational;
|
|
4927
|
+
code;
|
|
4928
|
+
details;
|
|
4929
|
+
constructor(message, statusCode = 500, options) {
|
|
4930
|
+
super(message);
|
|
4931
|
+
this.statusCode = statusCode;
|
|
4932
|
+
this.status = `${statusCode}`.startsWith("4") ? "fail" : "error";
|
|
4933
|
+
this.isOperational = true;
|
|
4934
|
+
this.code = options?.code;
|
|
4935
|
+
this.details = options?.details;
|
|
4936
|
+
Error.captureStackTrace(this, this.constructor);
|
|
4937
|
+
}
|
|
4938
|
+
};
|
|
4939
|
+
|
|
4940
|
+
// src/http/handlers/AsyncHandler.ts
|
|
4941
|
+
var AsyncHandler = (fn) => (req, res, next) => {
|
|
4942
|
+
Promise.resolve(fn(req, res, next)).catch(next);
|
|
4943
|
+
};
|
|
4944
|
+
|
|
4945
|
+
// src/http/query/QueryConstants.ts
|
|
4946
|
+
var QUERY_RESERVED_FIELDS = [
|
|
4947
|
+
"page",
|
|
4948
|
+
"limit",
|
|
4949
|
+
"sort",
|
|
4950
|
+
"fields",
|
|
4951
|
+
"populate"
|
|
4952
|
+
];
|
|
4953
|
+
var DEFAULT_PAGE = 1;
|
|
4954
|
+
var DEFAULT_LIMIT = 100;
|
|
4955
|
+
var DEFAULT_SORT_DIRECTION = "asc";
|
|
4956
|
+
var SUPPORTED_OPERATORS = [
|
|
4957
|
+
"eq",
|
|
4958
|
+
"ne",
|
|
4959
|
+
"gt",
|
|
4960
|
+
"gte",
|
|
4961
|
+
"lt",
|
|
4962
|
+
"lte",
|
|
4963
|
+
"in",
|
|
4964
|
+
"nin",
|
|
4965
|
+
"contains",
|
|
4966
|
+
"startsWith",
|
|
4967
|
+
"endsWith"
|
|
4968
|
+
];
|
|
4969
|
+
|
|
4970
|
+
// src/http/query/ApiFeatures.ts
|
|
4971
|
+
var ApiFeatures = class {
|
|
4972
|
+
static parse(query) {
|
|
4973
|
+
return {
|
|
4974
|
+
filters: this.parseFilters(query),
|
|
4975
|
+
sort: this.parseSort(query),
|
|
4976
|
+
fields: this.parseFields(query),
|
|
4977
|
+
pagination: this.parsePagination(query),
|
|
4978
|
+
populate: this.parsePopulate(query)
|
|
4979
|
+
};
|
|
4980
|
+
}
|
|
4981
|
+
static parseFilters(query) {
|
|
4982
|
+
const filters = [];
|
|
4983
|
+
Object.entries(query).forEach(([key, value]) => {
|
|
4984
|
+
if (QUERY_RESERVED_FIELDS.includes(key)) {
|
|
4985
|
+
return;
|
|
4986
|
+
}
|
|
4987
|
+
const match = key.match(
|
|
4988
|
+
/^(.+)\[(eq|ne|gt|gte|lt|lte|in|nin|contains|startsWith|endsWith)\]$/
|
|
4989
|
+
);
|
|
4990
|
+
if (match) {
|
|
4991
|
+
filters.push({
|
|
4992
|
+
field: match[1],
|
|
4993
|
+
operator: match[2],
|
|
4994
|
+
value
|
|
4995
|
+
});
|
|
4996
|
+
return;
|
|
4997
|
+
}
|
|
4998
|
+
filters.push({
|
|
4999
|
+
field: key,
|
|
5000
|
+
operator: "eq",
|
|
5001
|
+
value
|
|
5002
|
+
});
|
|
5003
|
+
});
|
|
5004
|
+
return filters;
|
|
5005
|
+
}
|
|
5006
|
+
static parseSort(query) {
|
|
5007
|
+
const sort = query.sort?.toString();
|
|
5008
|
+
if (!sort) {
|
|
5009
|
+
return [];
|
|
5010
|
+
}
|
|
5011
|
+
return sort.split(",").filter(Boolean).map((item) => {
|
|
5012
|
+
if (item.startsWith("-")) {
|
|
5013
|
+
return {
|
|
5014
|
+
field: item.substring(1),
|
|
5015
|
+
direction: "desc"
|
|
5016
|
+
};
|
|
5017
|
+
}
|
|
5018
|
+
return {
|
|
5019
|
+
field: item,
|
|
5020
|
+
direction: "asc"
|
|
5021
|
+
};
|
|
5022
|
+
});
|
|
5023
|
+
}
|
|
5024
|
+
static parseFields(query) {
|
|
5025
|
+
const fields = query.fields?.toString();
|
|
5026
|
+
if (!fields) {
|
|
5027
|
+
return [];
|
|
5028
|
+
}
|
|
5029
|
+
return fields.split(",").map((field) => field.trim()).filter(Boolean);
|
|
5030
|
+
}
|
|
5031
|
+
static parsePopulate(query) {
|
|
5032
|
+
const populate = query.populate?.toString();
|
|
5033
|
+
if (!populate) {
|
|
5034
|
+
return [];
|
|
5035
|
+
}
|
|
5036
|
+
return populate.split(",").map((field) => field.trim()).filter(Boolean);
|
|
5037
|
+
}
|
|
5038
|
+
static parsePagination(query) {
|
|
5039
|
+
const page = Number(query.page) || DEFAULT_PAGE;
|
|
5040
|
+
const limit = Number(query.limit) || DEFAULT_LIMIT;
|
|
5041
|
+
return {
|
|
5042
|
+
page,
|
|
5043
|
+
limit
|
|
5044
|
+
};
|
|
5045
|
+
}
|
|
5046
|
+
};
|
|
5047
|
+
|
|
5048
|
+
// src/http/responses/ApiResponse.ts
|
|
5049
|
+
var ApiResponse = class _ApiResponse {
|
|
5050
|
+
static send(res, options) {
|
|
5051
|
+
const {
|
|
5052
|
+
statusCode = 200,
|
|
5053
|
+
success = true,
|
|
5054
|
+
message = "Success",
|
|
5055
|
+
data,
|
|
5056
|
+
meta
|
|
5057
|
+
} = options;
|
|
5058
|
+
if (statusCode === 204) {
|
|
5059
|
+
return res.status(204).send();
|
|
5060
|
+
}
|
|
5061
|
+
const body = {
|
|
5062
|
+
success,
|
|
5063
|
+
message
|
|
5064
|
+
};
|
|
5065
|
+
if (data !== void 0) {
|
|
5066
|
+
body.data = data;
|
|
5067
|
+
}
|
|
5068
|
+
if (meta !== void 0) {
|
|
5069
|
+
body.meta = meta;
|
|
5070
|
+
}
|
|
5071
|
+
return res.status(statusCode).json(body);
|
|
5072
|
+
}
|
|
5073
|
+
static ok(res, data, message = "Success", meta) {
|
|
5074
|
+
return _ApiResponse.send(res, {
|
|
5075
|
+
statusCode: 200,
|
|
5076
|
+
success: true,
|
|
5077
|
+
message,
|
|
5078
|
+
data,
|
|
5079
|
+
meta
|
|
5080
|
+
});
|
|
5081
|
+
}
|
|
5082
|
+
static created(res, data, message = "Resource created successfully") {
|
|
5083
|
+
return _ApiResponse.send(res, {
|
|
5084
|
+
statusCode: 201,
|
|
5085
|
+
success: true,
|
|
5086
|
+
message,
|
|
5087
|
+
data
|
|
5088
|
+
});
|
|
5089
|
+
}
|
|
5090
|
+
static accepted(res, data, message = "Request accepted") {
|
|
5091
|
+
return _ApiResponse.send(res, {
|
|
5092
|
+
statusCode: 202,
|
|
5093
|
+
success: true,
|
|
5094
|
+
message,
|
|
5095
|
+
data
|
|
5096
|
+
});
|
|
5097
|
+
}
|
|
5098
|
+
static noContent(res) {
|
|
5099
|
+
return _ApiResponse.send(res, {
|
|
5100
|
+
statusCode: 204
|
|
5101
|
+
});
|
|
5102
|
+
}
|
|
5103
|
+
static error(res, message = "Internal Server Error", statusCode = 500, meta) {
|
|
5104
|
+
return _ApiResponse.send(res, {
|
|
5105
|
+
success: false,
|
|
5106
|
+
statusCode,
|
|
5107
|
+
message,
|
|
5108
|
+
meta
|
|
5109
|
+
});
|
|
5110
|
+
}
|
|
5111
|
+
static paginated(res, data, options, message = "Data fetched successfully") {
|
|
5112
|
+
const meta = {
|
|
5113
|
+
total: options.total,
|
|
5114
|
+
page: options.page,
|
|
5115
|
+
limit: options.limit,
|
|
5116
|
+
totalPages: Math.ceil(options.total / options.limit)
|
|
5117
|
+
};
|
|
5118
|
+
return _ApiResponse.ok(res, data, message, meta);
|
|
5119
|
+
}
|
|
5120
|
+
};
|
|
5121
|
+
|
|
5122
|
+
// src/http/controllers/CrudControllerFactory.ts
|
|
5123
|
+
var CrudControllerFactory = class {
|
|
5124
|
+
static create(repository, options = {}) {
|
|
5125
|
+
const resourceName = options.resourceName ?? "Resource";
|
|
5126
|
+
return {
|
|
5127
|
+
/**
|
|
5128
|
+
* GET /
|
|
5129
|
+
*/
|
|
5130
|
+
getAll: AsyncHandler(async (req, res) => {
|
|
5131
|
+
const parsed = ApiFeatures.parse(req.query);
|
|
5132
|
+
const baseFilter = options.filter?.(req) ?? {};
|
|
5133
|
+
const filter = {
|
|
5134
|
+
...baseFilter
|
|
5135
|
+
};
|
|
5136
|
+
parsed.filters.forEach((item) => {
|
|
5137
|
+
if (item.operator === "eq") {
|
|
5138
|
+
filter[item.field] = item.value;
|
|
5139
|
+
}
|
|
5140
|
+
});
|
|
5141
|
+
const queryOptions = {
|
|
5142
|
+
limit: parsed.pagination.limit,
|
|
5143
|
+
skip: (parsed.pagination.page - 1) * parsed.pagination.limit,
|
|
5144
|
+
populate: parsed.populate
|
|
5145
|
+
};
|
|
5146
|
+
if (parsed.sort.length > 0) {
|
|
5147
|
+
queryOptions.sort = Object.fromEntries(
|
|
5148
|
+
parsed.sort.map((item) => [
|
|
5149
|
+
item.field,
|
|
5150
|
+
item.direction === "asc" ? 1 : -1
|
|
5151
|
+
])
|
|
5152
|
+
);
|
|
5153
|
+
}
|
|
5154
|
+
if (parsed.fields.length > 0) {
|
|
5155
|
+
queryOptions.select = parsed.fields;
|
|
5156
|
+
}
|
|
5157
|
+
const docs = await repository.findAll(filter, queryOptions);
|
|
5158
|
+
const total = await repository.count(filter);
|
|
5159
|
+
return ApiResponse.paginated(
|
|
5160
|
+
res,
|
|
5161
|
+
docs,
|
|
5162
|
+
{
|
|
5163
|
+
total,
|
|
5164
|
+
page: parsed.pagination.page,
|
|
5165
|
+
limit: parsed.pagination.limit
|
|
5166
|
+
},
|
|
5167
|
+
`${resourceName} list fetched successfully`
|
|
5168
|
+
);
|
|
5169
|
+
}),
|
|
5170
|
+
/**
|
|
5171
|
+
* GET /:id
|
|
5172
|
+
*/
|
|
5173
|
+
getOne: AsyncHandler(async (req, res) => {
|
|
5174
|
+
const id = String(req.params.id);
|
|
5175
|
+
const doc = await repository.findById(id);
|
|
5176
|
+
if (!doc) {
|
|
5177
|
+
throw new AppError(`${resourceName} not found`, 404, {
|
|
5178
|
+
code: "RESOURCE_NOT_FOUND"
|
|
5179
|
+
});
|
|
5180
|
+
}
|
|
5181
|
+
return ApiResponse.ok(res, doc, `${resourceName} fetched successfully`);
|
|
5182
|
+
}),
|
|
5183
|
+
/**
|
|
5184
|
+
* POST /
|
|
5185
|
+
*/
|
|
5186
|
+
create: AsyncHandler(async (req, res) => {
|
|
5187
|
+
const doc = await repository.create(req.body);
|
|
5188
|
+
return ApiResponse.created(
|
|
5189
|
+
res,
|
|
5190
|
+
doc,
|
|
5191
|
+
`${resourceName} created successfully`
|
|
5192
|
+
);
|
|
5193
|
+
}),
|
|
5194
|
+
/**
|
|
5195
|
+
* PATCH /:id
|
|
5196
|
+
*/
|
|
5197
|
+
update: AsyncHandler(async (req, res) => {
|
|
5198
|
+
const id = String(req.params.id);
|
|
5199
|
+
const doc = await repository.updateById(id, req.body);
|
|
5200
|
+
if (!doc) {
|
|
5201
|
+
throw new AppError(`${resourceName} not found`, 404, {
|
|
5202
|
+
code: "RESOURCE_NOT_FOUND"
|
|
5203
|
+
});
|
|
5204
|
+
}
|
|
5205
|
+
return ApiResponse.ok(res, doc, `${resourceName} updated successfully`);
|
|
5206
|
+
}),
|
|
5207
|
+
/**
|
|
5208
|
+
* DELETE /:id
|
|
5209
|
+
*/
|
|
5210
|
+
delete: AsyncHandler(async (req, res) => {
|
|
5211
|
+
const id = String(req.params.id);
|
|
5212
|
+
const doc = await repository.deleteById(id);
|
|
5213
|
+
if (!doc) {
|
|
5214
|
+
throw new AppError(`${resourceName} not found`, 404, {
|
|
5215
|
+
code: "RESOURCE_NOT_FOUND"
|
|
5216
|
+
});
|
|
5217
|
+
}
|
|
5218
|
+
return ApiResponse.noContent(res);
|
|
5219
|
+
})
|
|
5220
|
+
};
|
|
5221
|
+
}
|
|
5222
|
+
};
|
|
5223
|
+
|
|
5224
|
+
// src/http/middleware/AuthMiddleware.ts
|
|
5106
5225
|
var authMiddleware = (_req, _res, next) => {
|
|
5107
5226
|
next();
|
|
5108
5227
|
};
|
|
5109
5228
|
|
|
5110
|
-
// src/
|
|
5111
|
-
var
|
|
5229
|
+
// src/http/middleware/ErrorMiddleware.ts
|
|
5230
|
+
var handleCastError = (err) => new AppError(`Invalid ${err.path}: ${err.value}`, 400, {
|
|
5112
5231
|
code: "INVALID_ID"
|
|
5113
5232
|
});
|
|
5114
|
-
var
|
|
5233
|
+
var handleDuplicateKey = (err) => {
|
|
5115
5234
|
const field = err.keyValue ? Object.keys(err.keyValue)[0] : "field";
|
|
5116
5235
|
return new AppError(`${field} already exists`, 400, {
|
|
5117
5236
|
code: "DUPLICATE_FIELD"
|
|
5118
5237
|
});
|
|
5119
5238
|
};
|
|
5120
|
-
var
|
|
5239
|
+
var handleValidationError = (err) => {
|
|
5121
5240
|
const errors = Object.entries(err.errors).reduce(
|
|
5122
5241
|
(acc, [key, value]) => {
|
|
5123
5242
|
acc[key] = value.message;
|
|
@@ -5128,12 +5247,11 @@ var handleValidationErrorDB = (err) => {
|
|
|
5128
5247
|
return new AppError("Validation failed", 400, {
|
|
5129
5248
|
code: "VALIDATION_ERROR",
|
|
5130
5249
|
details: errors
|
|
5131
|
-
// structured field errors
|
|
5132
5250
|
});
|
|
5133
5251
|
};
|
|
5134
|
-
var handleJWTError = () => new AppError("Invalid token
|
|
5135
|
-
var handleJWTExpiredError = () => new AppError("
|
|
5136
|
-
var
|
|
5252
|
+
var handleJWTError = () => new AppError("Invalid token", 401);
|
|
5253
|
+
var handleJWTExpiredError = () => new AppError("Token expired", 401);
|
|
5254
|
+
var ErrorMiddleware = (isProduction = false) => (err, _req, res, _next) => {
|
|
5137
5255
|
let error;
|
|
5138
5256
|
if (err instanceof AppError) {
|
|
5139
5257
|
error = err;
|
|
@@ -5145,15 +5263,15 @@ var GlobalErrorHandler = (isProd = false) => (err, _req, res, _next) => {
|
|
|
5145
5263
|
error.isOperational = false;
|
|
5146
5264
|
}
|
|
5147
5265
|
if (err && err.name === "CastError") {
|
|
5148
|
-
error =
|
|
5266
|
+
error = handleCastError(err);
|
|
5149
5267
|
}
|
|
5150
5268
|
if (err && typeof err === "object" && err.code === 11e3) {
|
|
5151
|
-
error =
|
|
5269
|
+
error = handleDuplicateKey(
|
|
5152
5270
|
err
|
|
5153
5271
|
);
|
|
5154
5272
|
}
|
|
5155
5273
|
if (err && err.name === "ValidationError") {
|
|
5156
|
-
error =
|
|
5274
|
+
error = handleValidationError(err);
|
|
5157
5275
|
}
|
|
5158
5276
|
if (err?.name === "JsonWebTokenError") {
|
|
5159
5277
|
error = handleJWTError();
|
|
@@ -5164,9 +5282,11 @@ var GlobalErrorHandler = (isProd = false) => (err, _req, res, _next) => {
|
|
|
5164
5282
|
if (!error.isOperational) {
|
|
5165
5283
|
logger.danger("Programming error", err);
|
|
5166
5284
|
} else {
|
|
5167
|
-
logger.danger("Operational error", {
|
|
5285
|
+
logger.danger("Operational error", {
|
|
5286
|
+
message: error.message
|
|
5287
|
+
});
|
|
5168
5288
|
}
|
|
5169
|
-
const
|
|
5289
|
+
const response = {
|
|
5170
5290
|
success: false,
|
|
5171
5291
|
message: error.isOperational ? error.message : "Something went wrong",
|
|
5172
5292
|
...error.details && {
|
|
@@ -5175,38 +5295,152 @@ var GlobalErrorHandler = (isProd = false) => (err, _req, res, _next) => {
|
|
|
5175
5295
|
}
|
|
5176
5296
|
}
|
|
5177
5297
|
};
|
|
5178
|
-
if (!
|
|
5179
|
-
return
|
|
5298
|
+
if (!isProduction) {
|
|
5299
|
+
return ApiResponse.send(res, {
|
|
5180
5300
|
statusCode: error.statusCode,
|
|
5181
|
-
...
|
|
5301
|
+
...response,
|
|
5182
5302
|
data: {
|
|
5183
5303
|
stack: err?.stack
|
|
5184
5304
|
}
|
|
5185
5305
|
});
|
|
5186
5306
|
}
|
|
5187
|
-
return
|
|
5307
|
+
return ApiResponse.send(res, {
|
|
5188
5308
|
statusCode: error.statusCode,
|
|
5189
|
-
...
|
|
5309
|
+
...response
|
|
5190
5310
|
});
|
|
5191
5311
|
};
|
|
5192
5312
|
|
|
5193
|
-
// src/
|
|
5313
|
+
// src/http/validation/Validator.ts
|
|
5314
|
+
var isJoiSchema = (schema) => {
|
|
5315
|
+
return typeof schema === "object" && schema !== null && "validate" in schema;
|
|
5316
|
+
};
|
|
5317
|
+
var isZodSchema = (schema) => {
|
|
5318
|
+
return typeof schema === "object" && schema !== null && "safeParse" in schema;
|
|
5319
|
+
};
|
|
5320
|
+
|
|
5321
|
+
// src/http/validation/JoiValidator.ts
|
|
5322
|
+
var JoiValidator = class {
|
|
5323
|
+
constructor(schema) {
|
|
5324
|
+
this.schema = schema;
|
|
5325
|
+
}
|
|
5326
|
+
schema;
|
|
5327
|
+
validate(data) {
|
|
5328
|
+
const result = this.schema.validate(data, {
|
|
5329
|
+
abortEarly: false,
|
|
5330
|
+
stripUnknown: true
|
|
5331
|
+
});
|
|
5332
|
+
if (result.error) {
|
|
5333
|
+
const errors = {};
|
|
5334
|
+
result.error.details.forEach((detail) => {
|
|
5335
|
+
const field = detail.path.join(".");
|
|
5336
|
+
errors[field] = detail.message;
|
|
5337
|
+
});
|
|
5338
|
+
return {
|
|
5339
|
+
success: false,
|
|
5340
|
+
errors
|
|
5341
|
+
};
|
|
5342
|
+
}
|
|
5343
|
+
return {
|
|
5344
|
+
success: true,
|
|
5345
|
+
data: result.value
|
|
5346
|
+
};
|
|
5347
|
+
}
|
|
5348
|
+
};
|
|
5349
|
+
|
|
5350
|
+
// src/http/validation/ZodValidator.ts
|
|
5351
|
+
var ZodValidator = class {
|
|
5352
|
+
constructor(schema) {
|
|
5353
|
+
this.schema = schema;
|
|
5354
|
+
}
|
|
5355
|
+
schema;
|
|
5356
|
+
validate(data) {
|
|
5357
|
+
const result = this.schema.safeParse(data);
|
|
5358
|
+
if (!result.success) {
|
|
5359
|
+
const errors = {};
|
|
5360
|
+
result.error.issues.forEach((issue) => {
|
|
5361
|
+
const field = issue.path.join(".");
|
|
5362
|
+
errors[field] = issue.message;
|
|
5363
|
+
});
|
|
5364
|
+
return {
|
|
5365
|
+
success: false,
|
|
5366
|
+
errors
|
|
5367
|
+
};
|
|
5368
|
+
}
|
|
5369
|
+
return {
|
|
5370
|
+
success: true,
|
|
5371
|
+
data: result.data
|
|
5372
|
+
};
|
|
5373
|
+
}
|
|
5374
|
+
};
|
|
5375
|
+
|
|
5376
|
+
// src/http/middleware/ValidationMiddleware.ts
|
|
5194
5377
|
var validate = (schema) => (req, _res, next) => {
|
|
5195
|
-
|
|
5196
|
-
if (
|
|
5197
|
-
|
|
5378
|
+
let result;
|
|
5379
|
+
if (isJoiSchema(schema)) {
|
|
5380
|
+
result = new JoiValidator(schema).validate(req.body);
|
|
5381
|
+
} else if (isZodSchema(schema)) {
|
|
5382
|
+
result = new ZodValidator(schema).validate(req.body);
|
|
5383
|
+
} else {
|
|
5384
|
+
return next(new AppError("Unsupported validation schema", 500));
|
|
5198
5385
|
}
|
|
5386
|
+
if (!result.success) {
|
|
5387
|
+
return next(
|
|
5388
|
+
new AppError("Validation failed", 400, {
|
|
5389
|
+
code: "VALIDATION_ERROR",
|
|
5390
|
+
details: result.errors
|
|
5391
|
+
})
|
|
5392
|
+
);
|
|
5393
|
+
}
|
|
5394
|
+
req.body = result.data;
|
|
5199
5395
|
next();
|
|
5200
5396
|
};
|
|
5201
5397
|
|
|
5202
|
-
// src/
|
|
5203
|
-
|
|
5398
|
+
// src/http/utils/PickFields.ts
|
|
5399
|
+
function pickFields(obj, fields, options = {}) {
|
|
5400
|
+
const removeUndefined = options.removeUndefined ?? false;
|
|
5401
|
+
const removeNull = options.removeNull ?? false;
|
|
5402
|
+
const removeEmptyString = options.removeEmptyString ?? false;
|
|
5403
|
+
const strict = options.strict ?? false;
|
|
5404
|
+
const defaults = options.defaults ?? {};
|
|
5405
|
+
const rename = options.rename ?? {};
|
|
5406
|
+
const transform = options.transform ?? {};
|
|
5407
|
+
const result = {};
|
|
5408
|
+
if (strict) {
|
|
5409
|
+
for (const key of Object.keys(obj)) {
|
|
5410
|
+
if (!fields.includes(key)) {
|
|
5411
|
+
throw new Error(`Unknown field: ${key}`);
|
|
5412
|
+
}
|
|
5413
|
+
}
|
|
5414
|
+
}
|
|
5415
|
+
for (const field of fields) {
|
|
5416
|
+
let value = obj[field];
|
|
5417
|
+
if (value === void 0 && field in defaults) {
|
|
5418
|
+
value = defaults[field];
|
|
5419
|
+
}
|
|
5420
|
+
if (removeUndefined && value === void 0) continue;
|
|
5421
|
+
if (removeNull && value === null) continue;
|
|
5422
|
+
if (removeEmptyString && value === "") continue;
|
|
5423
|
+
if (transform[field]) {
|
|
5424
|
+
value = transform[field](value);
|
|
5425
|
+
}
|
|
5426
|
+
const outputKey = rename[field] ?? field;
|
|
5427
|
+
if (Object.prototype.hasOwnProperty.call(obj, field) || field in defaults) {
|
|
5428
|
+
result[outputKey] = value;
|
|
5429
|
+
}
|
|
5430
|
+
}
|
|
5431
|
+
return result;
|
|
5432
|
+
}
|
|
5433
|
+
|
|
5434
|
+
// src/repositories/providers/MongoRepository.ts
|
|
5435
|
+
var MongoRepository = class {
|
|
5204
5436
|
model;
|
|
5205
5437
|
constructor(model) {
|
|
5206
5438
|
this.model = model;
|
|
5207
5439
|
}
|
|
5208
5440
|
buildSelect(select) {
|
|
5209
|
-
if (!select)
|
|
5441
|
+
if (!select) {
|
|
5442
|
+
return void 0;
|
|
5443
|
+
}
|
|
5210
5444
|
if (Array.isArray(select)) {
|
|
5211
5445
|
return select.join(" ");
|
|
5212
5446
|
}
|
|
@@ -5214,14 +5448,22 @@ var BaseMongoRepository = class {
|
|
|
5214
5448
|
}
|
|
5215
5449
|
applyQueryOptions(query, options) {
|
|
5216
5450
|
const select = this.buildSelect(options.select);
|
|
5217
|
-
if (select)
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
if (options.
|
|
5451
|
+
if (select) {
|
|
5452
|
+
query = query.select(select);
|
|
5453
|
+
}
|
|
5454
|
+
if (options.sort) {
|
|
5455
|
+
query = query.sort(options.sort);
|
|
5456
|
+
}
|
|
5457
|
+
if (options.limit) {
|
|
5458
|
+
query = query.limit(options.limit);
|
|
5459
|
+
}
|
|
5460
|
+
if (options.skip) {
|
|
5461
|
+
query = query.skip(options.skip);
|
|
5462
|
+
}
|
|
5221
5463
|
if (options.populate) {
|
|
5222
5464
|
if (Array.isArray(options.populate)) {
|
|
5223
|
-
options.populate.forEach((
|
|
5224
|
-
query = query.populate(
|
|
5465
|
+
options.populate.forEach((item) => {
|
|
5466
|
+
query = query.populate(item);
|
|
5225
5467
|
});
|
|
5226
5468
|
} else {
|
|
5227
5469
|
query = query.populate(options.populate);
|
|
@@ -5230,7 +5472,13 @@ var BaseMongoRepository = class {
|
|
|
5230
5472
|
return query;
|
|
5231
5473
|
}
|
|
5232
5474
|
toPlain(doc) {
|
|
5233
|
-
|
|
5475
|
+
if (!doc) {
|
|
5476
|
+
return doc;
|
|
5477
|
+
}
|
|
5478
|
+
return typeof doc.toObject === "function" ? doc.toObject() : doc;
|
|
5479
|
+
}
|
|
5480
|
+
toPlainArray(docs) {
|
|
5481
|
+
return docs.map((doc) => this.toPlain(doc));
|
|
5234
5482
|
}
|
|
5235
5483
|
/**
|
|
5236
5484
|
* Create
|
|
@@ -5241,7 +5489,7 @@ var BaseMongoRepository = class {
|
|
|
5241
5489
|
}
|
|
5242
5490
|
async createMany(data) {
|
|
5243
5491
|
const docs = await this.model.insertMany(data);
|
|
5244
|
-
return
|
|
5492
|
+
return this.toPlainArray(docs);
|
|
5245
5493
|
}
|
|
5246
5494
|
/**
|
|
5247
5495
|
* Read
|
|
@@ -5249,22 +5497,26 @@ var BaseMongoRepository = class {
|
|
|
5249
5497
|
async findAll(filter = {}, options = {}) {
|
|
5250
5498
|
let query = this.model.find(filter);
|
|
5251
5499
|
query = this.applyQueryOptions(query, options);
|
|
5252
|
-
return query.exec();
|
|
5500
|
+
return query.lean().exec();
|
|
5253
5501
|
}
|
|
5254
5502
|
async findById(id, options = {}) {
|
|
5255
5503
|
let query = this.model.findById(id);
|
|
5256
5504
|
query = this.applyQueryOptions(query, options);
|
|
5257
|
-
return query.exec();
|
|
5505
|
+
return query.lean().exec();
|
|
5258
5506
|
}
|
|
5259
5507
|
async findOne(filter = {}, options = {}) {
|
|
5260
5508
|
let query = this.model.findOne(filter);
|
|
5261
5509
|
query = this.applyQueryOptions(query, options);
|
|
5262
|
-
return query.exec();
|
|
5510
|
+
return query.lean().exec();
|
|
5263
5511
|
}
|
|
5264
5512
|
async findManyByIds(ids, options = {}) {
|
|
5265
|
-
let query = this.model.find({
|
|
5513
|
+
let query = this.model.find({
|
|
5514
|
+
_id: {
|
|
5515
|
+
$in: ids
|
|
5516
|
+
}
|
|
5517
|
+
});
|
|
5266
5518
|
query = this.applyQueryOptions(query, options);
|
|
5267
|
-
return query.exec();
|
|
5519
|
+
return query.lean().exec();
|
|
5268
5520
|
}
|
|
5269
5521
|
async count(filter) {
|
|
5270
5522
|
return this.model.countDocuments(filter).exec();
|
|
@@ -5277,12 +5529,22 @@ var BaseMongoRepository = class {
|
|
|
5277
5529
|
* Update
|
|
5278
5530
|
*/
|
|
5279
5531
|
async updateById(id, data, options) {
|
|
5280
|
-
const finalOptions = {
|
|
5281
|
-
|
|
5532
|
+
const finalOptions = {
|
|
5533
|
+
new: true,
|
|
5534
|
+
runValidators: true,
|
|
5535
|
+
...options
|
|
5536
|
+
};
|
|
5537
|
+
const doc = await this.model.findByIdAndUpdate(id, data, finalOptions).exec();
|
|
5538
|
+
return doc ? this.toPlain(doc) : null;
|
|
5282
5539
|
}
|
|
5283
5540
|
async updateOne(filter, data, options) {
|
|
5284
|
-
const finalOptions = {
|
|
5285
|
-
|
|
5541
|
+
const finalOptions = {
|
|
5542
|
+
new: true,
|
|
5543
|
+
runValidators: true,
|
|
5544
|
+
...options
|
|
5545
|
+
};
|
|
5546
|
+
const doc = await this.model.findOneAndUpdate(filter, data, finalOptions).exec();
|
|
5547
|
+
return doc ? this.toPlain(doc) : null;
|
|
5286
5548
|
}
|
|
5287
5549
|
async updateMany(filter, data) {
|
|
5288
5550
|
const result = await this.model.updateMany(filter, data).exec();
|
|
@@ -5292,10 +5554,12 @@ var BaseMongoRepository = class {
|
|
|
5292
5554
|
* Delete
|
|
5293
5555
|
*/
|
|
5294
5556
|
async deleteById(id) {
|
|
5295
|
-
|
|
5557
|
+
const doc = await this.model.findByIdAndDelete(id).exec();
|
|
5558
|
+
return doc ? this.toPlain(doc) : null;
|
|
5296
5559
|
}
|
|
5297
5560
|
async deleteOne(filter) {
|
|
5298
|
-
|
|
5561
|
+
const doc = await this.model.findOneAndDelete(filter).exec();
|
|
5562
|
+
return doc ? this.toPlain(doc) : null;
|
|
5299
5563
|
}
|
|
5300
5564
|
async deleteMany(filter) {
|
|
5301
5565
|
const result = await this.model.deleteMany(filter).exec();
|
|
@@ -5754,17 +6018,16 @@ function sleep(ms) {
|
|
|
5754
6018
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5755
6019
|
}
|
|
5756
6020
|
|
|
5757
|
-
exports.APIFactory = APIFactory;
|
|
5758
|
-
exports.APIFeatures = apiFeatures_default;
|
|
5759
|
-
exports.APIResponse = APIResponse;
|
|
5760
6021
|
exports.AVLTree = AVLTree;
|
|
5761
6022
|
exports.AdjacencyList = AdjacencyList;
|
|
5762
6023
|
exports.AdjacencyMatrix = AdjacencyMatrix;
|
|
6024
|
+
exports.ApiFeatures = ApiFeatures;
|
|
6025
|
+
exports.ApiResponse = ApiResponse;
|
|
5763
6026
|
exports.AppError = AppError;
|
|
6027
|
+
exports.AsyncHandler = AsyncHandler;
|
|
5764
6028
|
exports.AzureBlobStorageService = AzureBlobStorageService;
|
|
5765
6029
|
exports.BPlusTree = BPlusTree;
|
|
5766
6030
|
exports.BTree = BTree;
|
|
5767
|
-
exports.BaseMongoRepository = BaseMongoRepository;
|
|
5768
6031
|
exports.BinaryHeap = BinaryHeap;
|
|
5769
6032
|
exports.BinarySearchTree = BinarySearchTree;
|
|
5770
6033
|
exports.BinaryTree = BinaryTree;
|
|
@@ -5775,22 +6038,28 @@ exports.CircularQueue = CircularQueue;
|
|
|
5775
6038
|
exports.CloudinaryService = CloudinaryService;
|
|
5776
6039
|
exports.ConsistentHash = ConsistentHash;
|
|
5777
6040
|
exports.CountMinSketch = CountMinSketch;
|
|
6041
|
+
exports.CrudControllerFactory = CrudControllerFactory;
|
|
6042
|
+
exports.DEFAULT_LIMIT = DEFAULT_LIMIT;
|
|
6043
|
+
exports.DEFAULT_PAGE = DEFAULT_PAGE;
|
|
6044
|
+
exports.DEFAULT_SORT_DIRECTION = DEFAULT_SORT_DIRECTION;
|
|
6045
|
+
exports.DatabaseManager = DatabaseManager;
|
|
5778
6046
|
exports.Deque = Deque;
|
|
5779
6047
|
exports.DirectedGraph = DirectedGraph;
|
|
5780
6048
|
exports.DisjointSetUnion = DisjointSetUnion;
|
|
5781
6049
|
exports.DoublyLinkedList = DoublyLinkedList;
|
|
5782
6050
|
exports.DynamicArray = DynamicArray;
|
|
5783
6051
|
exports.EmailService = EmailService;
|
|
6052
|
+
exports.ErrorMiddleware = ErrorMiddleware;
|
|
5784
6053
|
exports.FenwickTree = FenwickTree;
|
|
5785
6054
|
exports.FibNode = FibNode;
|
|
5786
6055
|
exports.FibonacciHeap = FibonacciHeap;
|
|
5787
|
-
exports.GlobalErrorHandler = GlobalErrorHandler;
|
|
5788
6056
|
exports.Graph = Graph;
|
|
5789
6057
|
exports.HashMap = HashMap;
|
|
5790
6058
|
exports.HashSet = HashSet;
|
|
5791
6059
|
exports.HyperLogLog = HyperLogLog;
|
|
5792
6060
|
exports.IntervalTree = IntervalTree;
|
|
5793
6061
|
exports.JWTService = JWTService;
|
|
6062
|
+
exports.JoiValidator = JoiValidator;
|
|
5794
6063
|
exports.KDTree = KDTree;
|
|
5795
6064
|
exports.LFUCache = LFUCache;
|
|
5796
6065
|
exports.LRUCache = LRUCache;
|
|
@@ -5798,6 +6067,8 @@ exports.MaxHeap = MaxHeap;
|
|
|
5798
6067
|
exports.MaxStack = MaxStack;
|
|
5799
6068
|
exports.MinHeap = MinHeap;
|
|
5800
6069
|
exports.MinStack = MinStack;
|
|
6070
|
+
exports.MongoDatabaseProvider = MongoDatabaseProvider;
|
|
6071
|
+
exports.MongoRepository = MongoRepository;
|
|
5801
6072
|
exports.MulterFileHandlerService = MulterFileHandlerService;
|
|
5802
6073
|
exports.MultiSet = MultiSet;
|
|
5803
6074
|
exports.Node = Node;
|
|
@@ -5805,11 +6076,13 @@ exports.OrderedSet = OrderedSet;
|
|
|
5805
6076
|
exports.PairingHeap = PairingHeap;
|
|
5806
6077
|
exports.PairingNode = PairingNode;
|
|
5807
6078
|
exports.PriorityQueue = PriorityQueue;
|
|
6079
|
+
exports.QUERY_RESERVED_FIELDS = QUERY_RESERVED_FIELDS;
|
|
5808
6080
|
exports.QuadTree = QuadTree;
|
|
5809
6081
|
exports.Queue = Queue;
|
|
5810
6082
|
exports.RadixTree = RadixTree;
|
|
5811
6083
|
exports.RedBlackTree = RedBlackTree;
|
|
5812
6084
|
exports.SMTPProvider = SMTPProvider;
|
|
6085
|
+
exports.SUPPORTED_OPERATORS = SUPPORTED_OPERATORS;
|
|
5813
6086
|
exports.SegmentTree = SegmentTree;
|
|
5814
6087
|
exports.Set = Set2;
|
|
5815
6088
|
exports.SinglyLinkedList = SinglyLinkedList;
|
|
@@ -5823,14 +6096,15 @@ exports.TemplateEngine = TemplateEngine;
|
|
|
5823
6096
|
exports.TernarySearchTree = TernarySearchTree;
|
|
5824
6097
|
exports.TreeNode = TreeNode;
|
|
5825
6098
|
exports.Trie = Trie;
|
|
5826
|
-
exports.
|
|
6099
|
+
exports.ZodValidator = ZodValidator;
|
|
5827
6100
|
exports.authMiddleware = authMiddleware;
|
|
5828
|
-
exports.connectMongoDB = connectMongoDB;
|
|
5829
6101
|
exports.createAllowedOrigins = createAllowedOrigins;
|
|
5830
6102
|
exports.createCorsOptions = createCorsOptions;
|
|
5831
6103
|
exports.days = days;
|
|
5832
6104
|
exports.errorToString = errorToString;
|
|
5833
6105
|
exports.hours = hours;
|
|
6106
|
+
exports.isJoiSchema = isJoiSchema;
|
|
6107
|
+
exports.isZodSchema = isZodSchema;
|
|
5834
6108
|
exports.loadEnv = loadEnv;
|
|
5835
6109
|
exports.logger = logger;
|
|
5836
6110
|
exports.milliseconds = milliseconds;
|