@atscript/moost-db 0.1.35 → 0.1.36
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 +112 -8
- package/dist/index.d.ts +18 -3
- package/dist/index.mjs +113 -9
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ const __atscript_typescript_utils = __toESM(require("@atscript/typescript/utils"
|
|
|
26
26
|
const __moostjs_event_http = __toESM(require("@moostjs/event-http"));
|
|
27
27
|
const moost = __toESM(require("moost"));
|
|
28
28
|
const __uniqu_url = __toESM(require("@uniqu/url"));
|
|
29
|
+
const __atscript_utils_db = __toESM(require("@atscript/utils-db"));
|
|
29
30
|
|
|
30
31
|
//#region packages/moost-db/src/decorators.ts
|
|
31
32
|
const READABLE_DEF = "__atscript_db_readable_def";
|
|
@@ -36,12 +37,21 @@ const ViewController = ReadableController;
|
|
|
36
37
|
|
|
37
38
|
//#endregion
|
|
38
39
|
//#region packages/moost-db/src/validation-interceptor.ts
|
|
40
|
+
const dbErrorCodeToStatus = { CONFLICT: 409 };
|
|
39
41
|
function transformValidationError(error, reply) {
|
|
40
42
|
if (error instanceof __atscript_typescript_utils.ValidatorError) reply(new __moostjs_event_http.HttpError(400, {
|
|
41
43
|
message: error.message,
|
|
42
44
|
statusCode: 400,
|
|
43
45
|
errors: error.errors
|
|
44
46
|
}));
|
|
47
|
+
else if (error instanceof __atscript_utils_db.DbError) {
|
|
48
|
+
const statusCode = dbErrorCodeToStatus[error.code] ?? 400;
|
|
49
|
+
reply(new __moostjs_event_http.HttpError(statusCode, {
|
|
50
|
+
message: error.message,
|
|
51
|
+
statusCode,
|
|
52
|
+
errors: error.errors
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
45
55
|
}
|
|
46
56
|
const validationErrorTransform = () => (0, moost.defineInterceptor)({ error: transformValidationError }, moost.TInterceptorPriority.CATCH_ERROR);
|
|
47
57
|
const UseValidationErrorTransform = () => (0, moost.Intercept)(validationErrorTransform());
|
|
@@ -205,6 +215,18 @@ var AsDbReadableController = class {
|
|
|
205
215
|
const insightsError = this.validateInsights(parsed.insights);
|
|
206
216
|
if (insightsError) return new __moostjs_event_http.HttpError(400, insightsError);
|
|
207
217
|
}
|
|
218
|
+
const withRelations = parsed.controls.$with;
|
|
219
|
+
if (withRelations?.length) {
|
|
220
|
+
const relations = this.readable.relations;
|
|
221
|
+
for (const rel of withRelations) if (!rel.name.includes(".") && !relations.has(rel.name)) return new __moostjs_event_http.HttpError(400, {
|
|
222
|
+
message: `Unknown relation "${rel.name}" in $with. Available relations: ${[...relations.keys()].join(", ") || "(none)"}`,
|
|
223
|
+
statusCode: 400,
|
|
224
|
+
errors: [{
|
|
225
|
+
path: "$with",
|
|
226
|
+
message: `Unknown relation "${rel.name}"`
|
|
227
|
+
}]
|
|
228
|
+
});
|
|
229
|
+
}
|
|
208
230
|
return undefined;
|
|
209
231
|
}
|
|
210
232
|
/**
|
|
@@ -227,6 +249,38 @@ var AsDbReadableController = class {
|
|
|
227
249
|
return item;
|
|
228
250
|
}
|
|
229
251
|
/**
|
|
252
|
+
* Extracts a composite identifier object from query params.
|
|
253
|
+
* Tries composite primary key first, then compound unique indexes.
|
|
254
|
+
*/ extractCompositeId(query) {
|
|
255
|
+
const pkFields = this.readable.primaryKeys;
|
|
256
|
+
if (pkFields.length > 1) {
|
|
257
|
+
const idObj = {};
|
|
258
|
+
let allPresent = true;
|
|
259
|
+
for (const field of pkFields) {
|
|
260
|
+
if (query[field] === undefined) {
|
|
261
|
+
allPresent = false;
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
idObj[field] = query[field];
|
|
265
|
+
}
|
|
266
|
+
if (allPresent) return idObj;
|
|
267
|
+
}
|
|
268
|
+
for (const index of this.readable.indexes.values()) {
|
|
269
|
+
if (index.type !== "unique" || index.fields.length < 2) continue;
|
|
270
|
+
const idObj = {};
|
|
271
|
+
let allPresent = true;
|
|
272
|
+
for (const indexField of index.fields) {
|
|
273
|
+
if (query[indexField.name] === undefined) {
|
|
274
|
+
allPresent = false;
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
idObj[indexField.name] = query[indexField.name];
|
|
278
|
+
}
|
|
279
|
+
if (allPresent) return idObj;
|
|
280
|
+
}
|
|
281
|
+
return new __moostjs_event_http.HttpError(400, "Query params do not match any composite primary key or compound unique index");
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
230
284
|
* **GET /query** — returns an array of records or a count.
|
|
231
285
|
*/ async query(url) {
|
|
232
286
|
const parsed = this.parseQueryString(url);
|
|
@@ -310,6 +364,20 @@ else result = await this.readable.findManyWithCount(query);
|
|
|
310
364
|
return this.returnOne(this.readable.findById(id, { controls }));
|
|
311
365
|
}
|
|
312
366
|
/**
|
|
367
|
+
* **GET /one?field1=val1&field2=val2** — retrieves a single record by composite key
|
|
368
|
+
* (composite primary key or compound unique index).
|
|
369
|
+
*/ async getOneComposite(query, url) {
|
|
370
|
+
const idObj = this.extractCompositeId(query);
|
|
371
|
+
if (idObj instanceof __moostjs_event_http.HttpError) return idObj;
|
|
372
|
+
const parsed = this.parseQueryString(url);
|
|
373
|
+
const select = this.transformProjection(parsed.controls.$select);
|
|
374
|
+
const controls = {
|
|
375
|
+
...parsed.controls,
|
|
376
|
+
$select: select
|
|
377
|
+
};
|
|
378
|
+
return this.returnOne(this.readable.findById(idObj, { controls }));
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
313
381
|
* **GET /meta** — returns table/view metadata for UI.
|
|
314
382
|
*/ meta() {
|
|
315
383
|
return {
|
|
@@ -364,6 +432,14 @@ _ts_decorate$1([
|
|
|
364
432
|
_ts_metadata$1("design:paramtypes", [String, String]),
|
|
365
433
|
_ts_metadata$1("design:returntype", Promise)
|
|
366
434
|
], AsDbReadableController.prototype, "getOne", null);
|
|
435
|
+
_ts_decorate$1([
|
|
436
|
+
(0, __moostjs_event_http.Get)("one"),
|
|
437
|
+
_ts_param$1(0, (0, __moostjs_event_http.Query)()),
|
|
438
|
+
_ts_param$1(1, (0, __moostjs_event_http.Url)()),
|
|
439
|
+
_ts_metadata$1("design:type", Function),
|
|
440
|
+
_ts_metadata$1("design:paramtypes", [typeof Record === "undefined" ? Object : Record, String]),
|
|
441
|
+
_ts_metadata$1("design:returntype", Promise)
|
|
442
|
+
], AsDbReadableController.prototype, "getOneComposite", null);
|
|
367
443
|
_ts_decorate$1([
|
|
368
444
|
(0, __moostjs_event_http.Get)("meta"),
|
|
369
445
|
_ts_metadata$1("design:type", Function),
|
|
@@ -410,26 +486,35 @@ var AsDbController = class extends AsDbReadableController {
|
|
|
410
486
|
/**
|
|
411
487
|
* **POST /** — inserts one or many records.
|
|
412
488
|
*/ async insert(payload) {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const data$1 = await this.onWrite("insert", arr[0]);
|
|
489
|
+
if (Array.isArray(payload)) {
|
|
490
|
+
const data$1 = await this.onWrite("insertMany", payload);
|
|
416
491
|
if (data$1 === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
417
|
-
return await this.table.
|
|
492
|
+
return await this.table.insertMany(data$1);
|
|
418
493
|
}
|
|
419
|
-
const data = await this.onWrite("
|
|
494
|
+
const data = await this.onWrite("insert", payload);
|
|
420
495
|
if (data === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
421
|
-
return await this.table.
|
|
496
|
+
return await this.table.insertOne(data);
|
|
422
497
|
}
|
|
423
498
|
/**
|
|
424
|
-
* **PUT /** — fully replaces
|
|
499
|
+
* **PUT /** — fully replaces one or many records matched by primary key.
|
|
425
500
|
*/ async replace(payload) {
|
|
501
|
+
if (Array.isArray(payload)) {
|
|
502
|
+
const data$1 = await this.onWrite("replaceMany", payload);
|
|
503
|
+
if (data$1 === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
504
|
+
return await this.table.bulkReplace(data$1);
|
|
505
|
+
}
|
|
426
506
|
const data = await this.onWrite("replace", payload);
|
|
427
507
|
if (data === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
428
508
|
return await this.table.replaceOne(data);
|
|
429
509
|
}
|
|
430
510
|
/**
|
|
431
|
-
* **PATCH /** — partially updates
|
|
511
|
+
* **PATCH /** — partially updates one or many records matched by primary key.
|
|
432
512
|
*/ async update(payload) {
|
|
513
|
+
if (Array.isArray(payload)) {
|
|
514
|
+
const data$1 = await this.onWrite("updateMany", payload);
|
|
515
|
+
if (data$1 === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
516
|
+
return await this.table.bulkUpdate(data$1);
|
|
517
|
+
}
|
|
433
518
|
const data = await this.onWrite("update", payload);
|
|
434
519
|
if (data === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
435
520
|
return await this.table.updateOne(data);
|
|
@@ -443,6 +528,18 @@ var AsDbController = class extends AsDbReadableController {
|
|
|
443
528
|
if (result.deletedCount < 1) return new __moostjs_event_http.HttpError(404);
|
|
444
529
|
return result;
|
|
445
530
|
}
|
|
531
|
+
/**
|
|
532
|
+
* **DELETE /?field1=val1&field2=val2** — removes a record by composite key
|
|
533
|
+
* (composite primary key or compound unique index).
|
|
534
|
+
*/ async removeComposite(query) {
|
|
535
|
+
const idObj = this.extractCompositeId(query);
|
|
536
|
+
if (idObj instanceof __moostjs_event_http.HttpError) return idObj;
|
|
537
|
+
const resolvedId = await this.onRemove(idObj);
|
|
538
|
+
if (resolvedId === undefined) return new __moostjs_event_http.HttpError(500, "Not deleted");
|
|
539
|
+
const result = await this.table.deleteOne(resolvedId);
|
|
540
|
+
if (result.deletedCount < 1) return new __moostjs_event_http.HttpError(404);
|
|
541
|
+
return result;
|
|
542
|
+
}
|
|
446
543
|
constructor(table, app) {
|
|
447
544
|
super(table, app);
|
|
448
545
|
}
|
|
@@ -475,6 +572,13 @@ _ts_decorate([
|
|
|
475
572
|
_ts_metadata("design:paramtypes", [String]),
|
|
476
573
|
_ts_metadata("design:returntype", Promise)
|
|
477
574
|
], AsDbController.prototype, "remove", null);
|
|
575
|
+
_ts_decorate([
|
|
576
|
+
(0, __moostjs_event_http.Delete)(""),
|
|
577
|
+
_ts_param(0, (0, __moostjs_event_http.Query)()),
|
|
578
|
+
_ts_metadata("design:type", Function),
|
|
579
|
+
_ts_metadata("design:paramtypes", [typeof Record === "undefined" ? Object : Record]),
|
|
580
|
+
_ts_metadata("design:returntype", Promise)
|
|
581
|
+
], AsDbController.prototype, "removeComposite", null);
|
|
478
582
|
AsDbController = _ts_decorate([
|
|
479
583
|
(0, moost.Inherit)(),
|
|
480
584
|
_ts_param(0, (0, moost.Inject)(TABLE_DEF)),
|
package/dist/index.d.ts
CHANGED
|
@@ -47,6 +47,11 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
|
|
|
47
47
|
protected transformProjection(projection?: UniqueryControls['$select']): UniqueryControls['$select'] | undefined;
|
|
48
48
|
protected parseQueryString(url: string): _uniqu_url.UrlQuery;
|
|
49
49
|
protected returnOne(result: Promise<DataType | null>): Promise<DataType | HttpError>;
|
|
50
|
+
/**
|
|
51
|
+
* Extracts a composite identifier object from query params.
|
|
52
|
+
* Tries composite primary key first, then compound unique indexes.
|
|
53
|
+
*/
|
|
54
|
+
protected extractCompositeId(query: Record<string, string>): Record<string, unknown> | HttpError;
|
|
50
55
|
/**
|
|
51
56
|
* **GET /query** — returns an array of records or a count.
|
|
52
57
|
*/
|
|
@@ -65,6 +70,11 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
|
|
|
65
70
|
* **GET /one/:id** — retrieves a single record by ID or unique property.
|
|
66
71
|
*/
|
|
67
72
|
getOne(id: string, url: string): Promise<DataType | HttpError>;
|
|
73
|
+
/**
|
|
74
|
+
* **GET /one?field1=val1&field2=val2** — retrieves a single record by composite key
|
|
75
|
+
* (composite primary key or compound unique index).
|
|
76
|
+
*/
|
|
77
|
+
getOneComposite(query: Record<string, string>, url: string): Promise<DataType | HttpError>;
|
|
68
78
|
/**
|
|
69
79
|
* **GET /meta** — returns table/view metadata for UI.
|
|
70
80
|
*/
|
|
@@ -92,7 +102,7 @@ declare class AsDbController<T extends TAtscriptAnnotatedType = TAtscriptAnnotat
|
|
|
92
102
|
/**
|
|
93
103
|
* Intercepts write operations. Return `undefined` to abort.
|
|
94
104
|
*/
|
|
95
|
-
protected onWrite(action: 'insert' | 'insertMany' | 'replace' | 'update', data: unknown): unknown | Promise<unknown | undefined>;
|
|
105
|
+
protected onWrite(action: 'insert' | 'insertMany' | 'replace' | 'replaceMany' | 'update' | 'updateMany', data: unknown): unknown | Promise<unknown | undefined>;
|
|
96
106
|
/**
|
|
97
107
|
* Intercepts delete operations. Return `undefined` to abort.
|
|
98
108
|
*/
|
|
@@ -102,17 +112,22 @@ declare class AsDbController<T extends TAtscriptAnnotatedType = TAtscriptAnnotat
|
|
|
102
112
|
*/
|
|
103
113
|
insert(payload: unknown): Promise<HttpError | unknown>;
|
|
104
114
|
/**
|
|
105
|
-
* **PUT /** — fully replaces
|
|
115
|
+
* **PUT /** — fully replaces one or many records matched by primary key.
|
|
106
116
|
*/
|
|
107
117
|
replace(payload: unknown): Promise<HttpError | unknown>;
|
|
108
118
|
/**
|
|
109
|
-
* **PATCH /** — partially updates
|
|
119
|
+
* **PATCH /** — partially updates one or many records matched by primary key.
|
|
110
120
|
*/
|
|
111
121
|
update(payload: unknown): Promise<HttpError | unknown>;
|
|
112
122
|
/**
|
|
113
123
|
* **DELETE /:id** — removes a single record by primary key.
|
|
114
124
|
*/
|
|
115
125
|
remove(id: string): Promise<HttpError | unknown>;
|
|
126
|
+
/**
|
|
127
|
+
* **DELETE /?field1=val1&field2=val2** — removes a record by composite key
|
|
128
|
+
* (composite primary key or compound unique index).
|
|
129
|
+
*/
|
|
130
|
+
removeComposite(query: Record<string, string>): Promise<HttpError | unknown>;
|
|
116
131
|
}
|
|
117
132
|
|
|
118
133
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ValidatorError, defineAnnotatedType, serializeAnnotatedType, throwFeatureDisabled } from "@atscript/typescript/utils";
|
|
2
|
-
import { Body, Delete, Get, HttpError, Patch, Post, Put, Url } from "@moostjs/event-http";
|
|
2
|
+
import { Body, Delete, Get, HttpError, Patch, Post, Put, Query, Url } from "@moostjs/event-http";
|
|
3
3
|
import { ApplyDecorators, Controller, Inherit, Inject, Intercept, Moost, Param, Provide, TInterceptorPriority, defineInterceptor } from "moost";
|
|
4
4
|
import { parseUrl } from "@uniqu/url";
|
|
5
|
+
import { DbError } from "@atscript/utils-db";
|
|
5
6
|
|
|
6
7
|
//#region packages/moost-db/src/decorators.ts
|
|
7
8
|
const READABLE_DEF = "__atscript_db_readable_def";
|
|
@@ -12,12 +13,21 @@ const ViewController = ReadableController;
|
|
|
12
13
|
|
|
13
14
|
//#endregion
|
|
14
15
|
//#region packages/moost-db/src/validation-interceptor.ts
|
|
16
|
+
const dbErrorCodeToStatus = { CONFLICT: 409 };
|
|
15
17
|
function transformValidationError(error, reply) {
|
|
16
18
|
if (error instanceof ValidatorError) reply(new HttpError(400, {
|
|
17
19
|
message: error.message,
|
|
18
20
|
statusCode: 400,
|
|
19
21
|
errors: error.errors
|
|
20
22
|
}));
|
|
23
|
+
else if (error instanceof DbError) {
|
|
24
|
+
const statusCode = dbErrorCodeToStatus[error.code] ?? 400;
|
|
25
|
+
reply(new HttpError(statusCode, {
|
|
26
|
+
message: error.message,
|
|
27
|
+
statusCode,
|
|
28
|
+
errors: error.errors
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
21
31
|
}
|
|
22
32
|
const validationErrorTransform = () => defineInterceptor({ error: transformValidationError }, TInterceptorPriority.CATCH_ERROR);
|
|
23
33
|
const UseValidationErrorTransform = () => Intercept(validationErrorTransform());
|
|
@@ -181,6 +191,18 @@ var AsDbReadableController = class {
|
|
|
181
191
|
const insightsError = this.validateInsights(parsed.insights);
|
|
182
192
|
if (insightsError) return new HttpError(400, insightsError);
|
|
183
193
|
}
|
|
194
|
+
const withRelations = parsed.controls.$with;
|
|
195
|
+
if (withRelations?.length) {
|
|
196
|
+
const relations = this.readable.relations;
|
|
197
|
+
for (const rel of withRelations) if (!rel.name.includes(".") && !relations.has(rel.name)) return new HttpError(400, {
|
|
198
|
+
message: `Unknown relation "${rel.name}" in $with. Available relations: ${[...relations.keys()].join(", ") || "(none)"}`,
|
|
199
|
+
statusCode: 400,
|
|
200
|
+
errors: [{
|
|
201
|
+
path: "$with",
|
|
202
|
+
message: `Unknown relation "${rel.name}"`
|
|
203
|
+
}]
|
|
204
|
+
});
|
|
205
|
+
}
|
|
184
206
|
return undefined;
|
|
185
207
|
}
|
|
186
208
|
/**
|
|
@@ -203,6 +225,38 @@ var AsDbReadableController = class {
|
|
|
203
225
|
return item;
|
|
204
226
|
}
|
|
205
227
|
/**
|
|
228
|
+
* Extracts a composite identifier object from query params.
|
|
229
|
+
* Tries composite primary key first, then compound unique indexes.
|
|
230
|
+
*/ extractCompositeId(query) {
|
|
231
|
+
const pkFields = this.readable.primaryKeys;
|
|
232
|
+
if (pkFields.length > 1) {
|
|
233
|
+
const idObj = {};
|
|
234
|
+
let allPresent = true;
|
|
235
|
+
for (const field of pkFields) {
|
|
236
|
+
if (query[field] === undefined) {
|
|
237
|
+
allPresent = false;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
idObj[field] = query[field];
|
|
241
|
+
}
|
|
242
|
+
if (allPresent) return idObj;
|
|
243
|
+
}
|
|
244
|
+
for (const index of this.readable.indexes.values()) {
|
|
245
|
+
if (index.type !== "unique" || index.fields.length < 2) continue;
|
|
246
|
+
const idObj = {};
|
|
247
|
+
let allPresent = true;
|
|
248
|
+
for (const indexField of index.fields) {
|
|
249
|
+
if (query[indexField.name] === undefined) {
|
|
250
|
+
allPresent = false;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
idObj[indexField.name] = query[indexField.name];
|
|
254
|
+
}
|
|
255
|
+
if (allPresent) return idObj;
|
|
256
|
+
}
|
|
257
|
+
return new HttpError(400, "Query params do not match any composite primary key or compound unique index");
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
206
260
|
* **GET /query** — returns an array of records or a count.
|
|
207
261
|
*/ async query(url) {
|
|
208
262
|
const parsed = this.parseQueryString(url);
|
|
@@ -286,6 +340,20 @@ else result = await this.readable.findManyWithCount(query);
|
|
|
286
340
|
return this.returnOne(this.readable.findById(id, { controls }));
|
|
287
341
|
}
|
|
288
342
|
/**
|
|
343
|
+
* **GET /one?field1=val1&field2=val2** — retrieves a single record by composite key
|
|
344
|
+
* (composite primary key or compound unique index).
|
|
345
|
+
*/ async getOneComposite(query, url) {
|
|
346
|
+
const idObj = this.extractCompositeId(query);
|
|
347
|
+
if (idObj instanceof HttpError) return idObj;
|
|
348
|
+
const parsed = this.parseQueryString(url);
|
|
349
|
+
const select = this.transformProjection(parsed.controls.$select);
|
|
350
|
+
const controls = {
|
|
351
|
+
...parsed.controls,
|
|
352
|
+
$select: select
|
|
353
|
+
};
|
|
354
|
+
return this.returnOne(this.readable.findById(idObj, { controls }));
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
289
357
|
* **GET /meta** — returns table/view metadata for UI.
|
|
290
358
|
*/ meta() {
|
|
291
359
|
return {
|
|
@@ -340,6 +408,14 @@ _ts_decorate$1([
|
|
|
340
408
|
_ts_metadata$1("design:paramtypes", [String, String]),
|
|
341
409
|
_ts_metadata$1("design:returntype", Promise)
|
|
342
410
|
], AsDbReadableController.prototype, "getOne", null);
|
|
411
|
+
_ts_decorate$1([
|
|
412
|
+
Get("one"),
|
|
413
|
+
_ts_param$1(0, Query()),
|
|
414
|
+
_ts_param$1(1, Url()),
|
|
415
|
+
_ts_metadata$1("design:type", Function),
|
|
416
|
+
_ts_metadata$1("design:paramtypes", [typeof Record === "undefined" ? Object : Record, String]),
|
|
417
|
+
_ts_metadata$1("design:returntype", Promise)
|
|
418
|
+
], AsDbReadableController.prototype, "getOneComposite", null);
|
|
343
419
|
_ts_decorate$1([
|
|
344
420
|
Get("meta"),
|
|
345
421
|
_ts_metadata$1("design:type", Function),
|
|
@@ -386,26 +462,35 @@ var AsDbController = class extends AsDbReadableController {
|
|
|
386
462
|
/**
|
|
387
463
|
* **POST /** — inserts one or many records.
|
|
388
464
|
*/ async insert(payload) {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
const data$1 = await this.onWrite("insert", arr[0]);
|
|
465
|
+
if (Array.isArray(payload)) {
|
|
466
|
+
const data$1 = await this.onWrite("insertMany", payload);
|
|
392
467
|
if (data$1 === undefined) return new HttpError(500, "Not saved");
|
|
393
|
-
return await this.table.
|
|
468
|
+
return await this.table.insertMany(data$1);
|
|
394
469
|
}
|
|
395
|
-
const data = await this.onWrite("
|
|
470
|
+
const data = await this.onWrite("insert", payload);
|
|
396
471
|
if (data === undefined) return new HttpError(500, "Not saved");
|
|
397
|
-
return await this.table.
|
|
472
|
+
return await this.table.insertOne(data);
|
|
398
473
|
}
|
|
399
474
|
/**
|
|
400
|
-
* **PUT /** — fully replaces
|
|
475
|
+
* **PUT /** — fully replaces one or many records matched by primary key.
|
|
401
476
|
*/ async replace(payload) {
|
|
477
|
+
if (Array.isArray(payload)) {
|
|
478
|
+
const data$1 = await this.onWrite("replaceMany", payload);
|
|
479
|
+
if (data$1 === undefined) return new HttpError(500, "Not saved");
|
|
480
|
+
return await this.table.bulkReplace(data$1);
|
|
481
|
+
}
|
|
402
482
|
const data = await this.onWrite("replace", payload);
|
|
403
483
|
if (data === undefined) return new HttpError(500, "Not saved");
|
|
404
484
|
return await this.table.replaceOne(data);
|
|
405
485
|
}
|
|
406
486
|
/**
|
|
407
|
-
* **PATCH /** — partially updates
|
|
487
|
+
* **PATCH /** — partially updates one or many records matched by primary key.
|
|
408
488
|
*/ async update(payload) {
|
|
489
|
+
if (Array.isArray(payload)) {
|
|
490
|
+
const data$1 = await this.onWrite("updateMany", payload);
|
|
491
|
+
if (data$1 === undefined) return new HttpError(500, "Not saved");
|
|
492
|
+
return await this.table.bulkUpdate(data$1);
|
|
493
|
+
}
|
|
409
494
|
const data = await this.onWrite("update", payload);
|
|
410
495
|
if (data === undefined) return new HttpError(500, "Not saved");
|
|
411
496
|
return await this.table.updateOne(data);
|
|
@@ -419,6 +504,18 @@ var AsDbController = class extends AsDbReadableController {
|
|
|
419
504
|
if (result.deletedCount < 1) return new HttpError(404);
|
|
420
505
|
return result;
|
|
421
506
|
}
|
|
507
|
+
/**
|
|
508
|
+
* **DELETE /?field1=val1&field2=val2** — removes a record by composite key
|
|
509
|
+
* (composite primary key or compound unique index).
|
|
510
|
+
*/ async removeComposite(query) {
|
|
511
|
+
const idObj = this.extractCompositeId(query);
|
|
512
|
+
if (idObj instanceof HttpError) return idObj;
|
|
513
|
+
const resolvedId = await this.onRemove(idObj);
|
|
514
|
+
if (resolvedId === undefined) return new HttpError(500, "Not deleted");
|
|
515
|
+
const result = await this.table.deleteOne(resolvedId);
|
|
516
|
+
if (result.deletedCount < 1) return new HttpError(404);
|
|
517
|
+
return result;
|
|
518
|
+
}
|
|
422
519
|
constructor(table, app) {
|
|
423
520
|
super(table, app);
|
|
424
521
|
}
|
|
@@ -451,6 +548,13 @@ _ts_decorate([
|
|
|
451
548
|
_ts_metadata("design:paramtypes", [String]),
|
|
452
549
|
_ts_metadata("design:returntype", Promise)
|
|
453
550
|
], AsDbController.prototype, "remove", null);
|
|
551
|
+
_ts_decorate([
|
|
552
|
+
Delete(""),
|
|
553
|
+
_ts_param(0, Query()),
|
|
554
|
+
_ts_metadata("design:type", Function),
|
|
555
|
+
_ts_metadata("design:paramtypes", [typeof Record === "undefined" ? Object : Record]),
|
|
556
|
+
_ts_metadata("design:returntype", Promise)
|
|
557
|
+
], AsDbController.prototype, "removeComposite", null);
|
|
454
558
|
AsDbController = _ts_decorate([
|
|
455
559
|
Inherit(),
|
|
456
560
|
_ts_param(0, Inject(TABLE_DEF)),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/moost-db",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.36",
|
|
4
4
|
"description": "Generic database controller for Moost with Atscript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"annotations",
|
|
@@ -35,20 +35,20 @@
|
|
|
35
35
|
"./package.json": "./package.json"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@uniqu/url": "^0.0.
|
|
38
|
+
"@uniqu/url": "^0.0.6"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@moostjs/event-http": "^0.6.2",
|
|
42
42
|
"moost": "^0.6.2",
|
|
43
43
|
"vitest": "3.2.4",
|
|
44
|
-
"@atscript/core": "^0.1.
|
|
44
|
+
"@atscript/core": "^0.1.36"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"@moostjs/event-http": "^0.6.2",
|
|
48
48
|
"moost": "^0.6.2",
|
|
49
|
-
"@uniqu/core": "^0.0.
|
|
50
|
-
"@atscript/utils-db": "^0.1.
|
|
51
|
-
"@atscript/typescript": "^0.1.
|
|
49
|
+
"@uniqu/core": "^0.0.6",
|
|
50
|
+
"@atscript/utils-db": "^0.1.36",
|
|
51
|
+
"@atscript/typescript": "^0.1.36"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"pub": "pnpm publish --access public",
|