@atscript/moost-db 0.1.35 → 0.1.37
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 +113 -8
- package/dist/index.d.ts +19 -3
- package/dist/index.mjs +114 -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,10 +364,25 @@ 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 {
|
|
316
384
|
searchable: this.readable.isSearchable(),
|
|
385
|
+
vectorSearchable: this.readable.isVectorSearchable(),
|
|
317
386
|
searchIndexes: this._searchIndexes,
|
|
318
387
|
type: this._serializedType
|
|
319
388
|
};
|
|
@@ -364,6 +433,14 @@ _ts_decorate$1([
|
|
|
364
433
|
_ts_metadata$1("design:paramtypes", [String, String]),
|
|
365
434
|
_ts_metadata$1("design:returntype", Promise)
|
|
366
435
|
], AsDbReadableController.prototype, "getOne", null);
|
|
436
|
+
_ts_decorate$1([
|
|
437
|
+
(0, __moostjs_event_http.Get)("one"),
|
|
438
|
+
_ts_param$1(0, (0, __moostjs_event_http.Query)()),
|
|
439
|
+
_ts_param$1(1, (0, __moostjs_event_http.Url)()),
|
|
440
|
+
_ts_metadata$1("design:type", Function),
|
|
441
|
+
_ts_metadata$1("design:paramtypes", [typeof Record === "undefined" ? Object : Record, String]),
|
|
442
|
+
_ts_metadata$1("design:returntype", Promise)
|
|
443
|
+
], AsDbReadableController.prototype, "getOneComposite", null);
|
|
367
444
|
_ts_decorate$1([
|
|
368
445
|
(0, __moostjs_event_http.Get)("meta"),
|
|
369
446
|
_ts_metadata$1("design:type", Function),
|
|
@@ -410,26 +487,35 @@ var AsDbController = class extends AsDbReadableController {
|
|
|
410
487
|
/**
|
|
411
488
|
* **POST /** — inserts one or many records.
|
|
412
489
|
*/ async insert(payload) {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const data$1 = await this.onWrite("insert", arr[0]);
|
|
490
|
+
if (Array.isArray(payload)) {
|
|
491
|
+
const data$1 = await this.onWrite("insertMany", payload);
|
|
416
492
|
if (data$1 === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
417
|
-
return await this.table.
|
|
493
|
+
return await this.table.insertMany(data$1);
|
|
418
494
|
}
|
|
419
|
-
const data = await this.onWrite("
|
|
495
|
+
const data = await this.onWrite("insert", payload);
|
|
420
496
|
if (data === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
421
|
-
return await this.table.
|
|
497
|
+
return await this.table.insertOne(data);
|
|
422
498
|
}
|
|
423
499
|
/**
|
|
424
|
-
* **PUT /** — fully replaces
|
|
500
|
+
* **PUT /** — fully replaces one or many records matched by primary key.
|
|
425
501
|
*/ async replace(payload) {
|
|
502
|
+
if (Array.isArray(payload)) {
|
|
503
|
+
const data$1 = await this.onWrite("replaceMany", payload);
|
|
504
|
+
if (data$1 === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
505
|
+
return await this.table.bulkReplace(data$1);
|
|
506
|
+
}
|
|
426
507
|
const data = await this.onWrite("replace", payload);
|
|
427
508
|
if (data === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
428
509
|
return await this.table.replaceOne(data);
|
|
429
510
|
}
|
|
430
511
|
/**
|
|
431
|
-
* **PATCH /** — partially updates
|
|
512
|
+
* **PATCH /** — partially updates one or many records matched by primary key.
|
|
432
513
|
*/ async update(payload) {
|
|
514
|
+
if (Array.isArray(payload)) {
|
|
515
|
+
const data$1 = await this.onWrite("updateMany", payload);
|
|
516
|
+
if (data$1 === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
517
|
+
return await this.table.bulkUpdate(data$1);
|
|
518
|
+
}
|
|
433
519
|
const data = await this.onWrite("update", payload);
|
|
434
520
|
if (data === undefined) return new __moostjs_event_http.HttpError(500, "Not saved");
|
|
435
521
|
return await this.table.updateOne(data);
|
|
@@ -443,6 +529,18 @@ var AsDbController = class extends AsDbReadableController {
|
|
|
443
529
|
if (result.deletedCount < 1) return new __moostjs_event_http.HttpError(404);
|
|
444
530
|
return result;
|
|
445
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* **DELETE /?field1=val1&field2=val2** — removes a record by composite key
|
|
534
|
+
* (composite primary key or compound unique index).
|
|
535
|
+
*/ async removeComposite(query) {
|
|
536
|
+
const idObj = this.extractCompositeId(query);
|
|
537
|
+
if (idObj instanceof __moostjs_event_http.HttpError) return idObj;
|
|
538
|
+
const resolvedId = await this.onRemove(idObj);
|
|
539
|
+
if (resolvedId === undefined) return new __moostjs_event_http.HttpError(500, "Not deleted");
|
|
540
|
+
const result = await this.table.deleteOne(resolvedId);
|
|
541
|
+
if (result.deletedCount < 1) return new __moostjs_event_http.HttpError(404);
|
|
542
|
+
return result;
|
|
543
|
+
}
|
|
446
544
|
constructor(table, app) {
|
|
447
545
|
super(table, app);
|
|
448
546
|
}
|
|
@@ -475,6 +573,13 @@ _ts_decorate([
|
|
|
475
573
|
_ts_metadata("design:paramtypes", [String]),
|
|
476
574
|
_ts_metadata("design:returntype", Promise)
|
|
477
575
|
], AsDbController.prototype, "remove", null);
|
|
576
|
+
_ts_decorate([
|
|
577
|
+
(0, __moostjs_event_http.Delete)(""),
|
|
578
|
+
_ts_param(0, (0, __moostjs_event_http.Query)()),
|
|
579
|
+
_ts_metadata("design:type", Function),
|
|
580
|
+
_ts_metadata("design:paramtypes", [typeof Record === "undefined" ? Object : Record]),
|
|
581
|
+
_ts_metadata("design:returntype", Promise)
|
|
582
|
+
], AsDbController.prototype, "removeComposite", null);
|
|
478
583
|
AsDbController = _ts_decorate([
|
|
479
584
|
(0, moost.Inherit)(),
|
|
480
585
|
_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,11 +70,17 @@ 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
|
*/
|
|
71
81
|
meta(): {
|
|
72
82
|
searchable: boolean;
|
|
83
|
+
vectorSearchable: boolean;
|
|
73
84
|
searchIndexes: _atscript_utils_db.TSearchIndexInfo[];
|
|
74
85
|
type: _atscript_typescript_serialize.TSerializedAnnotatedType;
|
|
75
86
|
};
|
|
@@ -92,7 +103,7 @@ declare class AsDbController<T extends TAtscriptAnnotatedType = TAtscriptAnnotat
|
|
|
92
103
|
/**
|
|
93
104
|
* Intercepts write operations. Return `undefined` to abort.
|
|
94
105
|
*/
|
|
95
|
-
protected onWrite(action: 'insert' | 'insertMany' | 'replace' | 'update', data: unknown): unknown | Promise<unknown | undefined>;
|
|
106
|
+
protected onWrite(action: 'insert' | 'insertMany' | 'replace' | 'replaceMany' | 'update' | 'updateMany', data: unknown): unknown | Promise<unknown | undefined>;
|
|
96
107
|
/**
|
|
97
108
|
* Intercepts delete operations. Return `undefined` to abort.
|
|
98
109
|
*/
|
|
@@ -102,17 +113,22 @@ declare class AsDbController<T extends TAtscriptAnnotatedType = TAtscriptAnnotat
|
|
|
102
113
|
*/
|
|
103
114
|
insert(payload: unknown): Promise<HttpError | unknown>;
|
|
104
115
|
/**
|
|
105
|
-
* **PUT /** — fully replaces
|
|
116
|
+
* **PUT /** — fully replaces one or many records matched by primary key.
|
|
106
117
|
*/
|
|
107
118
|
replace(payload: unknown): Promise<HttpError | unknown>;
|
|
108
119
|
/**
|
|
109
|
-
* **PATCH /** — partially updates
|
|
120
|
+
* **PATCH /** — partially updates one or many records matched by primary key.
|
|
110
121
|
*/
|
|
111
122
|
update(payload: unknown): Promise<HttpError | unknown>;
|
|
112
123
|
/**
|
|
113
124
|
* **DELETE /:id** — removes a single record by primary key.
|
|
114
125
|
*/
|
|
115
126
|
remove(id: string): Promise<HttpError | unknown>;
|
|
127
|
+
/**
|
|
128
|
+
* **DELETE /?field1=val1&field2=val2** — removes a record by composite key
|
|
129
|
+
* (composite primary key or compound unique index).
|
|
130
|
+
*/
|
|
131
|
+
removeComposite(query: Record<string, string>): Promise<HttpError | unknown>;
|
|
116
132
|
}
|
|
117
133
|
|
|
118
134
|
/**
|
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,10 +340,25 @@ 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 {
|
|
292
360
|
searchable: this.readable.isSearchable(),
|
|
361
|
+
vectorSearchable: this.readable.isVectorSearchable(),
|
|
293
362
|
searchIndexes: this._searchIndexes,
|
|
294
363
|
type: this._serializedType
|
|
295
364
|
};
|
|
@@ -340,6 +409,14 @@ _ts_decorate$1([
|
|
|
340
409
|
_ts_metadata$1("design:paramtypes", [String, String]),
|
|
341
410
|
_ts_metadata$1("design:returntype", Promise)
|
|
342
411
|
], AsDbReadableController.prototype, "getOne", null);
|
|
412
|
+
_ts_decorate$1([
|
|
413
|
+
Get("one"),
|
|
414
|
+
_ts_param$1(0, Query()),
|
|
415
|
+
_ts_param$1(1, Url()),
|
|
416
|
+
_ts_metadata$1("design:type", Function),
|
|
417
|
+
_ts_metadata$1("design:paramtypes", [typeof Record === "undefined" ? Object : Record, String]),
|
|
418
|
+
_ts_metadata$1("design:returntype", Promise)
|
|
419
|
+
], AsDbReadableController.prototype, "getOneComposite", null);
|
|
343
420
|
_ts_decorate$1([
|
|
344
421
|
Get("meta"),
|
|
345
422
|
_ts_metadata$1("design:type", Function),
|
|
@@ -386,26 +463,35 @@ var AsDbController = class extends AsDbReadableController {
|
|
|
386
463
|
/**
|
|
387
464
|
* **POST /** — inserts one or many records.
|
|
388
465
|
*/ async insert(payload) {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
const data$1 = await this.onWrite("insert", arr[0]);
|
|
466
|
+
if (Array.isArray(payload)) {
|
|
467
|
+
const data$1 = await this.onWrite("insertMany", payload);
|
|
392
468
|
if (data$1 === undefined) return new HttpError(500, "Not saved");
|
|
393
|
-
return await this.table.
|
|
469
|
+
return await this.table.insertMany(data$1);
|
|
394
470
|
}
|
|
395
|
-
const data = await this.onWrite("
|
|
471
|
+
const data = await this.onWrite("insert", payload);
|
|
396
472
|
if (data === undefined) return new HttpError(500, "Not saved");
|
|
397
|
-
return await this.table.
|
|
473
|
+
return await this.table.insertOne(data);
|
|
398
474
|
}
|
|
399
475
|
/**
|
|
400
|
-
* **PUT /** — fully replaces
|
|
476
|
+
* **PUT /** — fully replaces one or many records matched by primary key.
|
|
401
477
|
*/ async replace(payload) {
|
|
478
|
+
if (Array.isArray(payload)) {
|
|
479
|
+
const data$1 = await this.onWrite("replaceMany", payload);
|
|
480
|
+
if (data$1 === undefined) return new HttpError(500, "Not saved");
|
|
481
|
+
return await this.table.bulkReplace(data$1);
|
|
482
|
+
}
|
|
402
483
|
const data = await this.onWrite("replace", payload);
|
|
403
484
|
if (data === undefined) return new HttpError(500, "Not saved");
|
|
404
485
|
return await this.table.replaceOne(data);
|
|
405
486
|
}
|
|
406
487
|
/**
|
|
407
|
-
* **PATCH /** — partially updates
|
|
488
|
+
* **PATCH /** — partially updates one or many records matched by primary key.
|
|
408
489
|
*/ async update(payload) {
|
|
490
|
+
if (Array.isArray(payload)) {
|
|
491
|
+
const data$1 = await this.onWrite("updateMany", payload);
|
|
492
|
+
if (data$1 === undefined) return new HttpError(500, "Not saved");
|
|
493
|
+
return await this.table.bulkUpdate(data$1);
|
|
494
|
+
}
|
|
409
495
|
const data = await this.onWrite("update", payload);
|
|
410
496
|
if (data === undefined) return new HttpError(500, "Not saved");
|
|
411
497
|
return await this.table.updateOne(data);
|
|
@@ -419,6 +505,18 @@ var AsDbController = class extends AsDbReadableController {
|
|
|
419
505
|
if (result.deletedCount < 1) return new HttpError(404);
|
|
420
506
|
return result;
|
|
421
507
|
}
|
|
508
|
+
/**
|
|
509
|
+
* **DELETE /?field1=val1&field2=val2** — removes a record by composite key
|
|
510
|
+
* (composite primary key or compound unique index).
|
|
511
|
+
*/ async removeComposite(query) {
|
|
512
|
+
const idObj = this.extractCompositeId(query);
|
|
513
|
+
if (idObj instanceof HttpError) return idObj;
|
|
514
|
+
const resolvedId = await this.onRemove(idObj);
|
|
515
|
+
if (resolvedId === undefined) return new HttpError(500, "Not deleted");
|
|
516
|
+
const result = await this.table.deleteOne(resolvedId);
|
|
517
|
+
if (result.deletedCount < 1) return new HttpError(404);
|
|
518
|
+
return result;
|
|
519
|
+
}
|
|
422
520
|
constructor(table, app) {
|
|
423
521
|
super(table, app);
|
|
424
522
|
}
|
|
@@ -451,6 +549,13 @@ _ts_decorate([
|
|
|
451
549
|
_ts_metadata("design:paramtypes", [String]),
|
|
452
550
|
_ts_metadata("design:returntype", Promise)
|
|
453
551
|
], AsDbController.prototype, "remove", null);
|
|
552
|
+
_ts_decorate([
|
|
553
|
+
Delete(""),
|
|
554
|
+
_ts_param(0, Query()),
|
|
555
|
+
_ts_metadata("design:type", Function),
|
|
556
|
+
_ts_metadata("design:paramtypes", [typeof Record === "undefined" ? Object : Record]),
|
|
557
|
+
_ts_metadata("design:returntype", Promise)
|
|
558
|
+
], AsDbController.prototype, "removeComposite", null);
|
|
454
559
|
AsDbController = _ts_decorate([
|
|
455
560
|
Inherit(),
|
|
456
561
|
_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.37",
|
|
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.37"
|
|
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.37",
|
|
51
|
+
"@atscript/typescript": "^0.1.37"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"pub": "pnpm publish --access public",
|