@atscript/moost-db 0.1.62 → 0.1.64

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 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);
@@ -955,14 +991,27 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
955
991
  _gates;
956
992
  _preferredIdSet;
957
993
  _overlayIsNoOp;
994
+ /** path → sibling-ref path for `@db.amount.currency.ref` / `@db.unit.ref`. */
995
+ _quantityRefByPath;
958
996
  constructor(readable, app) {
959
997
  super(readable.type, readable.tableName, app, readable.isView ? "view" : "table");
960
998
  this.readable = readable;
961
999
  this._gates = this._buildGates();
962
1000
  this._preferredIdSet = new Set(readable.preferredId ?? []);
1001
+ this._quantityRefByPath = this._collectQuantityRefs();
963
1002
  const defaultOverlay = AsReadableController.prototype.applyMetaOverlay;
964
1003
  this._overlayIsNoOp = this.applyMetaOverlay === defaultOverlay;
965
1004
  }
1005
+ _collectQuantityRefs() {
1006
+ const out = /* @__PURE__ */ new Map();
1007
+ if (!this.readable.flatMap) return out;
1008
+ for (const [path, entry] of this.readable.flatMap) {
1009
+ const meta = entry?.metadata;
1010
+ const ref = meta?.get("db.amount.currency.ref") ?? meta?.get("db.unit.ref");
1011
+ if (ref) out.set(path, ref);
1012
+ }
1013
+ return out;
1014
+ }
966
1015
  _buildGates() {
967
1016
  const meta = this.readable.type.metadata;
968
1017
  const gates = {};
@@ -1030,9 +1079,11 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
1030
1079
  return projection;
1031
1080
  }
1032
1081
  widenPreferredIdProjection(projection) {
1033
- if (this._preferredIdSet.size === 0 || projection === void 0) return projection;
1034
- if (Array.isArray(projection)) return this._widenArrayProjection(projection);
1035
- return this._widenMapProjection(projection);
1082
+ const widened = this.widenQuantityRefProjection(projection);
1083
+ if (widened instanceof _moostjs_event_http.HttpError) return widened;
1084
+ if (this._preferredIdSet.size === 0 || widened === void 0) return widened;
1085
+ if (Array.isArray(widened)) return this._widenArrayProjection(widened);
1086
+ return this._widenMapProjection(widened);
1036
1087
  }
1037
1088
  _widenArrayProjection(projection) {
1038
1089
  const stringItems = /* @__PURE__ */ new Set();
@@ -1072,6 +1123,46 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
1072
1123
  for (const field of this._preferredIdSet) widened[field] = 1;
1073
1124
  return widened;
1074
1125
  }
1126
+ /**
1127
+ * Auto-includes the sibling-ref field whenever its `@db.amount.currency.ref`
1128
+ * / `@db.unit.ref` quantity is selected — UI must never get a value without
1129
+ * its dimension. No-op when `$select` is undefined (full row covers it).
1130
+ */
1131
+ widenQuantityRefProjection(projection) {
1132
+ if (this._quantityRefByPath.size === 0 || projection === void 0) return projection;
1133
+ if (Array.isArray(projection)) return this._widenQuantityArrayProjection(projection);
1134
+ return this._widenQuantityMapProjection(projection);
1135
+ }
1136
+ _widenQuantityArrayProjection(projection) {
1137
+ const stringItems = /* @__PURE__ */ new Set();
1138
+ for (const item of projection) if (typeof item === "string") stringItems.add(item);
1139
+ const toAdd = [];
1140
+ for (const [valuePath, refPath] of this._quantityRefByPath) if (stringItems.has(valuePath) && !stringItems.has(refPath)) {
1141
+ toAdd.push(refPath);
1142
+ stringItems.add(refPath);
1143
+ }
1144
+ if (toAdd.length === 0) return projection;
1145
+ return [...projection, ...toAdd];
1146
+ }
1147
+ _widenQuantityMapProjection(projection) {
1148
+ const entries = Object.entries(projection);
1149
+ if (entries.length === 0) return projection;
1150
+ const included = /* @__PURE__ */ new Set();
1151
+ const excluded = /* @__PURE__ */ new Set();
1152
+ for (const [k, v] of entries) if (v === 1 || v === true) included.add(k);
1153
+ else if (v === 0 || v === false) excluded.add(k);
1154
+ if (included.size > 0 && excluded.size > 0) return new _moostjs_event_http.HttpError(400, "Mixed inclusion/exclusion $select maps are not supported");
1155
+ if (excluded.size === 0) {
1156
+ const toAdd = [];
1157
+ for (const [valuePath, refPath] of this._quantityRefByPath) if (included.has(valuePath) && !included.has(refPath)) toAdd.push(refPath);
1158
+ if (toAdd.length === 0) return projection;
1159
+ const widened = {};
1160
+ for (const k of included) widened[k] = 1;
1161
+ for (const k of toAdd) widened[k] = 1;
1162
+ return widened;
1163
+ }
1164
+ return projection;
1165
+ }
1075
1166
  /** WHY: the URL parser only auto-coerces `$count`; every other boolean control reaches us as `"true"`/`"1"` and would fail DTO validation. */
1076
1167
  _coerceActionsControl(controls) {
1077
1168
  const v = controls.$actions;
@@ -1298,9 +1389,9 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
1298
1389
  * **GET /one/:id** — retrieves a single record by ID or unique property.
1299
1390
  */
1300
1391
  async getOne(id, url) {
1301
- const parsed = this.parseQueryString(url);
1392
+ const { parsed, hasNonControl } = this.parseControlsOnlyFromUrl(url);
1393
+ if (hasNonControl) return new _moostjs_event_http.HttpError(400, "Filtering is not allowed for \"one\" endpoint");
1302
1394
  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
1395
  const error = this.validateParsed(parsed, "getOne");
1305
1396
  if (error) return error;
1306
1397
  const rawSelect = await this.transformProjection(parsed.controls.$select);
@@ -1315,7 +1406,7 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
1315
1406
  async getOneComposite(query, url) {
1316
1407
  const idObj = this.extractIdShape(query);
1317
1408
  if (idObj instanceof _moostjs_event_http.HttpError) return idObj;
1318
- const parsed = this.parseQueryString(url);
1409
+ const { parsed } = this.parseControlsOnlyFromUrl(url);
1319
1410
  this._coerceActionsControl(parsed.controls);
1320
1411
  const rawSelect = await this.transformProjection(parsed.controls.$select);
1321
1412
  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
@@ -166,7 +180,10 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
166
180
  private readonly _gates;
167
181
  private readonly _preferredIdSet;
168
182
  private readonly _overlayIsNoOp;
183
+ /** path → sibling-ref path for `@db.amount.currency.ref` / `@db.unit.ref`. */
184
+ private readonly _quantityRefByPath;
169
185
  constructor(readable: AtscriptDbReadable<T>, app: Moost);
186
+ private _collectQuantityRefs;
170
187
  private _buildGates;
171
188
  private _collectAnnotated;
172
189
  protected hasField(path: string): boolean;
@@ -191,6 +208,14 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
191
208
  private widenPreferredIdProjection;
192
209
  private _widenArrayProjection;
193
210
  private _widenMapProjection;
211
+ /**
212
+ * Auto-includes the sibling-ref field whenever its `@db.amount.currency.ref`
213
+ * / `@db.unit.ref` quantity is selected — UI must never get a value without
214
+ * its dimension. No-op when `$select` is undefined (full row covers it).
215
+ */
216
+ private widenQuantityRefProjection;
217
+ private _widenQuantityArrayProjection;
218
+ private _widenQuantityMapProjection;
194
219
  /** WHY: the URL parser only auto-coerces `$count`; every other boolean control reaches us as `"true"`/`"1"` and would fail DTO validation. */
195
220
  private _coerceActionsControl;
196
221
  /** Normalize a post-`widenPreferredIdProjection` $select into `string[] | null` (`null` = all fields). */
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
@@ -166,7 +180,10 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
166
180
  private readonly _gates;
167
181
  private readonly _preferredIdSet;
168
182
  private readonly _overlayIsNoOp;
183
+ /** path → sibling-ref path for `@db.amount.currency.ref` / `@db.unit.ref`. */
184
+ private readonly _quantityRefByPath;
169
185
  constructor(readable: AtscriptDbReadable<T>, app: Moost);
186
+ private _collectQuantityRefs;
170
187
  private _buildGates;
171
188
  private _collectAnnotated;
172
189
  protected hasField(path: string): boolean;
@@ -191,6 +208,14 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
191
208
  private widenPreferredIdProjection;
192
209
  private _widenArrayProjection;
193
210
  private _widenMapProjection;
211
+ /**
212
+ * Auto-includes the sibling-ref field whenever its `@db.amount.currency.ref`
213
+ * / `@db.unit.ref` quantity is selected — UI must never get a value without
214
+ * its dimension. No-op when `$select` is undefined (full row covers it).
215
+ */
216
+ private widenQuantityRefProjection;
217
+ private _widenQuantityArrayProjection;
218
+ private _widenQuantityMapProjection;
194
219
  /** WHY: the URL parser only auto-coerces `$count`; every other boolean control reaches us as `"true"`/`"1"` and would fail DTO validation. */
195
220
  private _coerceActionsControl;
196
221
  /** Normalize a post-`widenPreferredIdProjection` $select into `string[] | null` (`null` = all fields). */
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);
@@ -954,14 +990,27 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
954
990
  _gates;
955
991
  _preferredIdSet;
956
992
  _overlayIsNoOp;
993
+ /** path → sibling-ref path for `@db.amount.currency.ref` / `@db.unit.ref`. */
994
+ _quantityRefByPath;
957
995
  constructor(readable, app) {
958
996
  super(readable.type, readable.tableName, app, readable.isView ? "view" : "table");
959
997
  this.readable = readable;
960
998
  this._gates = this._buildGates();
961
999
  this._preferredIdSet = new Set(readable.preferredId ?? []);
1000
+ this._quantityRefByPath = this._collectQuantityRefs();
962
1001
  const defaultOverlay = AsReadableController.prototype.applyMetaOverlay;
963
1002
  this._overlayIsNoOp = this.applyMetaOverlay === defaultOverlay;
964
1003
  }
1004
+ _collectQuantityRefs() {
1005
+ const out = /* @__PURE__ */ new Map();
1006
+ if (!this.readable.flatMap) return out;
1007
+ for (const [path, entry] of this.readable.flatMap) {
1008
+ const meta = entry?.metadata;
1009
+ const ref = meta?.get("db.amount.currency.ref") ?? meta?.get("db.unit.ref");
1010
+ if (ref) out.set(path, ref);
1011
+ }
1012
+ return out;
1013
+ }
965
1014
  _buildGates() {
966
1015
  const meta = this.readable.type.metadata;
967
1016
  const gates = {};
@@ -1029,9 +1078,11 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
1029
1078
  return projection;
1030
1079
  }
1031
1080
  widenPreferredIdProjection(projection) {
1032
- if (this._preferredIdSet.size === 0 || projection === void 0) return projection;
1033
- if (Array.isArray(projection)) return this._widenArrayProjection(projection);
1034
- return this._widenMapProjection(projection);
1081
+ const widened = this.widenQuantityRefProjection(projection);
1082
+ if (widened instanceof HttpError) return widened;
1083
+ if (this._preferredIdSet.size === 0 || widened === void 0) return widened;
1084
+ if (Array.isArray(widened)) return this._widenArrayProjection(widened);
1085
+ return this._widenMapProjection(widened);
1035
1086
  }
1036
1087
  _widenArrayProjection(projection) {
1037
1088
  const stringItems = /* @__PURE__ */ new Set();
@@ -1071,6 +1122,46 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
1071
1122
  for (const field of this._preferredIdSet) widened[field] = 1;
1072
1123
  return widened;
1073
1124
  }
1125
+ /**
1126
+ * Auto-includes the sibling-ref field whenever its `@db.amount.currency.ref`
1127
+ * / `@db.unit.ref` quantity is selected — UI must never get a value without
1128
+ * its dimension. No-op when `$select` is undefined (full row covers it).
1129
+ */
1130
+ widenQuantityRefProjection(projection) {
1131
+ if (this._quantityRefByPath.size === 0 || projection === void 0) return projection;
1132
+ if (Array.isArray(projection)) return this._widenQuantityArrayProjection(projection);
1133
+ return this._widenQuantityMapProjection(projection);
1134
+ }
1135
+ _widenQuantityArrayProjection(projection) {
1136
+ const stringItems = /* @__PURE__ */ new Set();
1137
+ for (const item of projection) if (typeof item === "string") stringItems.add(item);
1138
+ const toAdd = [];
1139
+ for (const [valuePath, refPath] of this._quantityRefByPath) if (stringItems.has(valuePath) && !stringItems.has(refPath)) {
1140
+ toAdd.push(refPath);
1141
+ stringItems.add(refPath);
1142
+ }
1143
+ if (toAdd.length === 0) return projection;
1144
+ return [...projection, ...toAdd];
1145
+ }
1146
+ _widenQuantityMapProjection(projection) {
1147
+ const entries = Object.entries(projection);
1148
+ if (entries.length === 0) return projection;
1149
+ const included = /* @__PURE__ */ new Set();
1150
+ const excluded = /* @__PURE__ */ new Set();
1151
+ for (const [k, v] of entries) if (v === 1 || v === true) included.add(k);
1152
+ else if (v === 0 || v === false) excluded.add(k);
1153
+ if (included.size > 0 && excluded.size > 0) return new HttpError(400, "Mixed inclusion/exclusion $select maps are not supported");
1154
+ if (excluded.size === 0) {
1155
+ const toAdd = [];
1156
+ for (const [valuePath, refPath] of this._quantityRefByPath) if (included.has(valuePath) && !included.has(refPath)) toAdd.push(refPath);
1157
+ if (toAdd.length === 0) return projection;
1158
+ const widened = {};
1159
+ for (const k of included) widened[k] = 1;
1160
+ for (const k of toAdd) widened[k] = 1;
1161
+ return widened;
1162
+ }
1163
+ return projection;
1164
+ }
1074
1165
  /** WHY: the URL parser only auto-coerces `$count`; every other boolean control reaches us as `"true"`/`"1"` and would fail DTO validation. */
1075
1166
  _coerceActionsControl(controls) {
1076
1167
  const v = controls.$actions;
@@ -1297,9 +1388,9 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
1297
1388
  * **GET /one/:id** — retrieves a single record by ID or unique property.
1298
1389
  */
1299
1390
  async getOne(id, url) {
1300
- const parsed = this.parseQueryString(url);
1391
+ const { parsed, hasNonControl } = this.parseControlsOnlyFromUrl(url);
1392
+ if (hasNonControl) return new HttpError(400, "Filtering is not allowed for \"one\" endpoint");
1301
1393
  this._coerceActionsControl(parsed.controls);
1302
- if (Object.keys(parsed.filter).length > 0) return new HttpError(400, "Filtering is not allowed for \"one\" endpoint");
1303
1394
  const error = this.validateParsed(parsed, "getOne");
1304
1395
  if (error) return error;
1305
1396
  const rawSelect = await this.transformProjection(parsed.controls.$select);
@@ -1314,7 +1405,7 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
1314
1405
  async getOneComposite(query, url) {
1315
1406
  const idObj = this.extractIdShape(query);
1316
1407
  if (idObj instanceof HttpError) return idObj;
1317
- const parsed = this.parseQueryString(url);
1408
+ const { parsed } = this.parseControlsOnlyFromUrl(url);
1318
1409
  this._coerceActionsControl(parsed.controls);
1319
1410
  const rawSelect = await this.transformProjection(parsed.controls.$select);
1320
1411
  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.62",
3
+ "version": "0.1.64",
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.62"
61
+ "@atscript/db": "^0.1.64"
62
62
  },
63
63
  "scripts": {
64
64
  "postinstall": "asc -f dts",