@atscript/moost-db 0.1.62 → 0.1.63
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 +39 -3
- package/dist/index.d.cts +14 -0
- package/dist/index.d.mts +14 -0
- package/dist/index.mjs +39 -3
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -691,6 +691,42 @@ let AsReadableController = class AsReadableController {
|
|
|
691
691
|
const idx = url.indexOf("?");
|
|
692
692
|
return (0, _uniqu_url.parseUrl)(idx >= 0 ? url.slice(idx + 1) : "");
|
|
693
693
|
}
|
|
694
|
+
/**
|
|
695
|
+
* Parse a URL keeping only `$*` control keywords; report whether any
|
|
696
|
+
* non-control parts were present. Used by `/one` routes where the
|
|
697
|
+
* uniquery lexer cannot tokenise PK values containing `-` and other
|
|
698
|
+
* reserved chars, so non-control parts must be stripped before lexing.
|
|
699
|
+
* `/one/:id` rejects stray filter params with 400 via `hasNonControl`;
|
|
700
|
+
* `/one` (composite) ignores it because the composite-key params have
|
|
701
|
+
* already been extracted via `@Query()`.
|
|
702
|
+
*/
|
|
703
|
+
parseControlsOnlyFromUrl(url) {
|
|
704
|
+
const idx = url.indexOf("?");
|
|
705
|
+
const qs = idx >= 0 ? url.slice(idx + 1) : "";
|
|
706
|
+
if (!qs) return {
|
|
707
|
+
parsed: (0, _uniqu_url.parseUrl)(""),
|
|
708
|
+
hasNonControl: false
|
|
709
|
+
};
|
|
710
|
+
const kept = [];
|
|
711
|
+
let hasNonControl = false;
|
|
712
|
+
for (const part of qs.split("&")) {
|
|
713
|
+
if (!part) continue;
|
|
714
|
+
const eq = part.indexOf("=");
|
|
715
|
+
const rawKey = eq === -1 ? part : part.slice(0, eq);
|
|
716
|
+
let key;
|
|
717
|
+
try {
|
|
718
|
+
key = decodeURIComponent(rawKey);
|
|
719
|
+
} catch {
|
|
720
|
+
key = rawKey;
|
|
721
|
+
}
|
|
722
|
+
if (key.startsWith("$")) kept.push(part);
|
|
723
|
+
else hasNonControl = true;
|
|
724
|
+
}
|
|
725
|
+
return {
|
|
726
|
+
parsed: (0, _uniqu_url.parseUrl)(kept.join("&")),
|
|
727
|
+
hasNonControl
|
|
728
|
+
};
|
|
729
|
+
}
|
|
694
730
|
async returnOne(result) {
|
|
695
731
|
const item = await result;
|
|
696
732
|
if (!item) return new _moostjs_event_http.HttpError(404);
|
|
@@ -1298,9 +1334,9 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
|
|
|
1298
1334
|
* **GET /one/:id** — retrieves a single record by ID or unique property.
|
|
1299
1335
|
*/
|
|
1300
1336
|
async getOne(id, url) {
|
|
1301
|
-
const parsed = this.
|
|
1337
|
+
const { parsed, hasNonControl } = this.parseControlsOnlyFromUrl(url);
|
|
1338
|
+
if (hasNonControl) return new _moostjs_event_http.HttpError(400, "Filtering is not allowed for \"one\" endpoint");
|
|
1302
1339
|
this._coerceActionsControl(parsed.controls);
|
|
1303
|
-
if (Object.keys(parsed.filter).length > 0) return new _moostjs_event_http.HttpError(400, "Filtering is not allowed for \"one\" endpoint");
|
|
1304
1340
|
const error = this.validateParsed(parsed, "getOne");
|
|
1305
1341
|
if (error) return error;
|
|
1306
1342
|
const rawSelect = await this.transformProjection(parsed.controls.$select);
|
|
@@ -1315,7 +1351,7 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
|
|
|
1315
1351
|
async getOneComposite(query, url) {
|
|
1316
1352
|
const idObj = this.extractIdShape(query);
|
|
1317
1353
|
if (idObj instanceof _moostjs_event_http.HttpError) return idObj;
|
|
1318
|
-
const parsed = this.
|
|
1354
|
+
const { parsed } = this.parseControlsOnlyFromUrl(url);
|
|
1319
1355
|
this._coerceActionsControl(parsed.controls);
|
|
1320
1356
|
const rawSelect = await this.transformProjection(parsed.controls.$select);
|
|
1321
1357
|
const select = this.widenPreferredIdProjection(rawSelect);
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as _uniqu_url0 from "@uniqu/url";
|
|
2
|
+
import { parseUrl } from "@uniqu/url";
|
|
2
3
|
import { TAtscriptAnnotatedType, TAtscriptDataType, TSerializeOptions, TSerializedAnnotatedType, Validator } from "@atscript/typescript/utils";
|
|
3
4
|
import { AtscriptDbReadable, AtscriptDbTable, FilterExpr, FlatOf, TCrudOp, TCrudPermissions, TCrudPermissions as TCrudPermissions$1, TDbActionInfo, TDbActionInfo as TDbActionInfo$1, TDbActionIntent, TDbActionIntent as TDbActionIntent$1, TDbActionLevel, TDbActionLevel as TDbActionLevel$1, TDbActionProcessor, TDbFieldMeta, TIdentification, TMetaResponse, Uniquery, UniqueryControls } from "@atscript/db";
|
|
4
5
|
import { HttpError } from "@moostjs/event-http";
|
|
@@ -106,6 +107,19 @@ declare abstract class AsReadableController<T extends TAtscriptAnnotatedType = T
|
|
|
106
107
|
*/
|
|
107
108
|
protected checkGates(filter: FilterExpr | undefined, controls: Record<string, unknown>, gates: ReadableGates): HttpError | undefined;
|
|
108
109
|
protected parseQueryString(url: string): _uniqu_url0.UrlQuery;
|
|
110
|
+
/**
|
|
111
|
+
* Parse a URL keeping only `$*` control keywords; report whether any
|
|
112
|
+
* non-control parts were present. Used by `/one` routes where the
|
|
113
|
+
* uniquery lexer cannot tokenise PK values containing `-` and other
|
|
114
|
+
* reserved chars, so non-control parts must be stripped before lexing.
|
|
115
|
+
* `/one/:id` rejects stray filter params with 400 via `hasNonControl`;
|
|
116
|
+
* `/one` (composite) ignores it because the composite-key params have
|
|
117
|
+
* already been extracted via `@Query()`.
|
|
118
|
+
*/
|
|
119
|
+
protected parseControlsOnlyFromUrl(url: string): {
|
|
120
|
+
parsed: ReturnType<typeof parseUrl>;
|
|
121
|
+
hasNonControl: boolean;
|
|
122
|
+
};
|
|
109
123
|
protected returnOne(result: Promise<DataType | null>): Promise<DataType | HttpError>;
|
|
110
124
|
/**
|
|
111
125
|
* **GET /meta** — returns the bound interface's metadata envelope. The
|
package/dist/index.d.mts
CHANGED
|
@@ -3,6 +3,7 @@ import { HttpError } from "@moostjs/event-http";
|
|
|
3
3
|
import * as moost from "moost";
|
|
4
4
|
import { Moost, TConsoleBase } from "moost";
|
|
5
5
|
import * as _uniqu_url0 from "@uniqu/url";
|
|
6
|
+
import { parseUrl } from "@uniqu/url";
|
|
6
7
|
import { AtscriptDbReadable, AtscriptDbTable, FilterExpr, FlatOf, TCrudOp, TCrudPermissions, TCrudPermissions as TCrudPermissions$1, TDbActionInfo, TDbActionInfo as TDbActionInfo$1, TDbActionIntent, TDbActionIntent as TDbActionIntent$1, TDbActionLevel, TDbActionLevel as TDbActionLevel$1, TDbActionProcessor, TDbFieldMeta, TIdentification, TMetaResponse, Uniquery, UniqueryControls } from "@atscript/db";
|
|
7
8
|
import * as _wooksjs_event_core0 from "@wooksjs/event-core";
|
|
8
9
|
|
|
@@ -106,6 +107,19 @@ declare abstract class AsReadableController<T extends TAtscriptAnnotatedType = T
|
|
|
106
107
|
*/
|
|
107
108
|
protected checkGates(filter: FilterExpr | undefined, controls: Record<string, unknown>, gates: ReadableGates): HttpError | undefined;
|
|
108
109
|
protected parseQueryString(url: string): _uniqu_url0.UrlQuery;
|
|
110
|
+
/**
|
|
111
|
+
* Parse a URL keeping only `$*` control keywords; report whether any
|
|
112
|
+
* non-control parts were present. Used by `/one` routes where the
|
|
113
|
+
* uniquery lexer cannot tokenise PK values containing `-` and other
|
|
114
|
+
* reserved chars, so non-control parts must be stripped before lexing.
|
|
115
|
+
* `/one/:id` rejects stray filter params with 400 via `hasNonControl`;
|
|
116
|
+
* `/one` (composite) ignores it because the composite-key params have
|
|
117
|
+
* already been extracted via `@Query()`.
|
|
118
|
+
*/
|
|
119
|
+
protected parseControlsOnlyFromUrl(url: string): {
|
|
120
|
+
parsed: ReturnType<typeof parseUrl>;
|
|
121
|
+
hasNonControl: boolean;
|
|
122
|
+
};
|
|
109
123
|
protected returnOne(result: Promise<DataType | null>): Promise<DataType | HttpError>;
|
|
110
124
|
/**
|
|
111
125
|
* **GET /meta** — returns the bound interface's metadata envelope. The
|
package/dist/index.mjs
CHANGED
|
@@ -690,6 +690,42 @@ let AsReadableController = class AsReadableController {
|
|
|
690
690
|
const idx = url.indexOf("?");
|
|
691
691
|
return parseUrl(idx >= 0 ? url.slice(idx + 1) : "");
|
|
692
692
|
}
|
|
693
|
+
/**
|
|
694
|
+
* Parse a URL keeping only `$*` control keywords; report whether any
|
|
695
|
+
* non-control parts were present. Used by `/one` routes where the
|
|
696
|
+
* uniquery lexer cannot tokenise PK values containing `-` and other
|
|
697
|
+
* reserved chars, so non-control parts must be stripped before lexing.
|
|
698
|
+
* `/one/:id` rejects stray filter params with 400 via `hasNonControl`;
|
|
699
|
+
* `/one` (composite) ignores it because the composite-key params have
|
|
700
|
+
* already been extracted via `@Query()`.
|
|
701
|
+
*/
|
|
702
|
+
parseControlsOnlyFromUrl(url) {
|
|
703
|
+
const idx = url.indexOf("?");
|
|
704
|
+
const qs = idx >= 0 ? url.slice(idx + 1) : "";
|
|
705
|
+
if (!qs) return {
|
|
706
|
+
parsed: parseUrl(""),
|
|
707
|
+
hasNonControl: false
|
|
708
|
+
};
|
|
709
|
+
const kept = [];
|
|
710
|
+
let hasNonControl = false;
|
|
711
|
+
for (const part of qs.split("&")) {
|
|
712
|
+
if (!part) continue;
|
|
713
|
+
const eq = part.indexOf("=");
|
|
714
|
+
const rawKey = eq === -1 ? part : part.slice(0, eq);
|
|
715
|
+
let key;
|
|
716
|
+
try {
|
|
717
|
+
key = decodeURIComponent(rawKey);
|
|
718
|
+
} catch {
|
|
719
|
+
key = rawKey;
|
|
720
|
+
}
|
|
721
|
+
if (key.startsWith("$")) kept.push(part);
|
|
722
|
+
else hasNonControl = true;
|
|
723
|
+
}
|
|
724
|
+
return {
|
|
725
|
+
parsed: parseUrl(kept.join("&")),
|
|
726
|
+
hasNonControl
|
|
727
|
+
};
|
|
728
|
+
}
|
|
693
729
|
async returnOne(result) {
|
|
694
730
|
const item = await result;
|
|
695
731
|
if (!item) return new HttpError(404);
|
|
@@ -1297,9 +1333,9 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
|
|
|
1297
1333
|
* **GET /one/:id** — retrieves a single record by ID or unique property.
|
|
1298
1334
|
*/
|
|
1299
1335
|
async getOne(id, url) {
|
|
1300
|
-
const parsed = this.
|
|
1336
|
+
const { parsed, hasNonControl } = this.parseControlsOnlyFromUrl(url);
|
|
1337
|
+
if (hasNonControl) return new HttpError(400, "Filtering is not allowed for \"one\" endpoint");
|
|
1301
1338
|
this._coerceActionsControl(parsed.controls);
|
|
1302
|
-
if (Object.keys(parsed.filter).length > 0) return new HttpError(400, "Filtering is not allowed for \"one\" endpoint");
|
|
1303
1339
|
const error = this.validateParsed(parsed, "getOne");
|
|
1304
1340
|
if (error) return error;
|
|
1305
1341
|
const rawSelect = await this.transformProjection(parsed.controls.$select);
|
|
@@ -1314,7 +1350,7 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
|
|
|
1314
1350
|
async getOneComposite(query, url) {
|
|
1315
1351
|
const idObj = this.extractIdShape(query);
|
|
1316
1352
|
if (idObj instanceof HttpError) return idObj;
|
|
1317
|
-
const parsed = this.
|
|
1353
|
+
const { parsed } = this.parseControlsOnlyFromUrl(url);
|
|
1318
1354
|
this._coerceActionsControl(parsed.controls);
|
|
1319
1355
|
const rawSelect = await this.transformProjection(parsed.controls.$select);
|
|
1320
1356
|
const select = this.widenPreferredIdProjection(rawSelect);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/moost-db",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.63",
|
|
4
4
|
"description": "Generic database controller for Moost with Atscript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"annotations",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"@wooksjs/event-core": "^0.7.10",
|
|
59
59
|
"@wooksjs/http-body": "^0.7.10",
|
|
60
60
|
"moost": "^0.6.8",
|
|
61
|
-
"@atscript/db": "^0.1.
|
|
61
|
+
"@atscript/db": "^0.1.63"
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
64
|
"postinstall": "asc -f dts",
|