@atscript/moost-db 0.1.63 → 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 +58 -3
- package/dist/index.d.cts +11 -0
- package/dist/index.d.mts +11 -0
- package/dist/index.mjs +58 -3
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -991,14 +991,27 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
|
|
|
991
991
|
_gates;
|
|
992
992
|
_preferredIdSet;
|
|
993
993
|
_overlayIsNoOp;
|
|
994
|
+
/** path → sibling-ref path for `@db.amount.currency.ref` / `@db.unit.ref`. */
|
|
995
|
+
_quantityRefByPath;
|
|
994
996
|
constructor(readable, app) {
|
|
995
997
|
super(readable.type, readable.tableName, app, readable.isView ? "view" : "table");
|
|
996
998
|
this.readable = readable;
|
|
997
999
|
this._gates = this._buildGates();
|
|
998
1000
|
this._preferredIdSet = new Set(readable.preferredId ?? []);
|
|
1001
|
+
this._quantityRefByPath = this._collectQuantityRefs();
|
|
999
1002
|
const defaultOverlay = AsReadableController.prototype.applyMetaOverlay;
|
|
1000
1003
|
this._overlayIsNoOp = this.applyMetaOverlay === defaultOverlay;
|
|
1001
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
|
+
}
|
|
1002
1015
|
_buildGates() {
|
|
1003
1016
|
const meta = this.readable.type.metadata;
|
|
1004
1017
|
const gates = {};
|
|
@@ -1066,9 +1079,11 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
|
|
|
1066
1079
|
return projection;
|
|
1067
1080
|
}
|
|
1068
1081
|
widenPreferredIdProjection(projection) {
|
|
1069
|
-
|
|
1070
|
-
if (
|
|
1071
|
-
|
|
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);
|
|
1072
1087
|
}
|
|
1073
1088
|
_widenArrayProjection(projection) {
|
|
1074
1089
|
const stringItems = /* @__PURE__ */ new Set();
|
|
@@ -1108,6 +1123,46 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
|
|
|
1108
1123
|
for (const field of this._preferredIdSet) widened[field] = 1;
|
|
1109
1124
|
return widened;
|
|
1110
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
|
+
}
|
|
1111
1166
|
/** WHY: the URL parser only auto-coerces `$count`; every other boolean control reaches us as `"true"`/`"1"` and would fail DTO validation. */
|
|
1112
1167
|
_coerceActionsControl(controls) {
|
|
1113
1168
|
const v = controls.$actions;
|
package/dist/index.d.cts
CHANGED
|
@@ -180,7 +180,10 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
|
|
|
180
180
|
private readonly _gates;
|
|
181
181
|
private readonly _preferredIdSet;
|
|
182
182
|
private readonly _overlayIsNoOp;
|
|
183
|
+
/** path → sibling-ref path for `@db.amount.currency.ref` / `@db.unit.ref`. */
|
|
184
|
+
private readonly _quantityRefByPath;
|
|
183
185
|
constructor(readable: AtscriptDbReadable<T>, app: Moost);
|
|
186
|
+
private _collectQuantityRefs;
|
|
184
187
|
private _buildGates;
|
|
185
188
|
private _collectAnnotated;
|
|
186
189
|
protected hasField(path: string): boolean;
|
|
@@ -205,6 +208,14 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
|
|
|
205
208
|
private widenPreferredIdProjection;
|
|
206
209
|
private _widenArrayProjection;
|
|
207
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;
|
|
208
219
|
/** WHY: the URL parser only auto-coerces `$count`; every other boolean control reaches us as `"true"`/`"1"` and would fail DTO validation. */
|
|
209
220
|
private _coerceActionsControl;
|
|
210
221
|
/** Normalize a post-`widenPreferredIdProjection` $select into `string[] | null` (`null` = all fields). */
|
package/dist/index.d.mts
CHANGED
|
@@ -180,7 +180,10 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
|
|
|
180
180
|
private readonly _gates;
|
|
181
181
|
private readonly _preferredIdSet;
|
|
182
182
|
private readonly _overlayIsNoOp;
|
|
183
|
+
/** path → sibling-ref path for `@db.amount.currency.ref` / `@db.unit.ref`. */
|
|
184
|
+
private readonly _quantityRefByPath;
|
|
183
185
|
constructor(readable: AtscriptDbReadable<T>, app: Moost);
|
|
186
|
+
private _collectQuantityRefs;
|
|
184
187
|
private _buildGates;
|
|
185
188
|
private _collectAnnotated;
|
|
186
189
|
protected hasField(path: string): boolean;
|
|
@@ -205,6 +208,14 @@ declare class AsDbReadableController<T extends TAtscriptAnnotatedType = TAtscrip
|
|
|
205
208
|
private widenPreferredIdProjection;
|
|
206
209
|
private _widenArrayProjection;
|
|
207
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;
|
|
208
219
|
/** WHY: the URL parser only auto-coerces `$count`; every other boolean control reaches us as `"true"`/`"1"` and would fail DTO validation. */
|
|
209
220
|
private _coerceActionsControl;
|
|
210
221
|
/** Normalize a post-`widenPreferredIdProjection` $select into `string[] | null` (`null` = all fields). */
|
package/dist/index.mjs
CHANGED
|
@@ -990,14 +990,27 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
|
|
|
990
990
|
_gates;
|
|
991
991
|
_preferredIdSet;
|
|
992
992
|
_overlayIsNoOp;
|
|
993
|
+
/** path → sibling-ref path for `@db.amount.currency.ref` / `@db.unit.ref`. */
|
|
994
|
+
_quantityRefByPath;
|
|
993
995
|
constructor(readable, app) {
|
|
994
996
|
super(readable.type, readable.tableName, app, readable.isView ? "view" : "table");
|
|
995
997
|
this.readable = readable;
|
|
996
998
|
this._gates = this._buildGates();
|
|
997
999
|
this._preferredIdSet = new Set(readable.preferredId ?? []);
|
|
1000
|
+
this._quantityRefByPath = this._collectQuantityRefs();
|
|
998
1001
|
const defaultOverlay = AsReadableController.prototype.applyMetaOverlay;
|
|
999
1002
|
this._overlayIsNoOp = this.applyMetaOverlay === defaultOverlay;
|
|
1000
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
|
+
}
|
|
1001
1014
|
_buildGates() {
|
|
1002
1015
|
const meta = this.readable.type.metadata;
|
|
1003
1016
|
const gates = {};
|
|
@@ -1065,9 +1078,11 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
|
|
|
1065
1078
|
return projection;
|
|
1066
1079
|
}
|
|
1067
1080
|
widenPreferredIdProjection(projection) {
|
|
1068
|
-
|
|
1069
|
-
if (
|
|
1070
|
-
|
|
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);
|
|
1071
1086
|
}
|
|
1072
1087
|
_widenArrayProjection(projection) {
|
|
1073
1088
|
const stringItems = /* @__PURE__ */ new Set();
|
|
@@ -1107,6 +1122,46 @@ let AsDbReadableController = class AsDbReadableController extends AsReadableCont
|
|
|
1107
1122
|
for (const field of this._preferredIdSet) widened[field] = 1;
|
|
1108
1123
|
return widened;
|
|
1109
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
|
+
}
|
|
1110
1165
|
/** WHY: the URL parser only auto-coerces `$count`; every other boolean control reaches us as `"true"`/`"1"` and would fail DTO validation. */
|
|
1111
1166
|
_coerceActionsControl(controls) {
|
|
1112
1167
|
const v = controls.$actions;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/moost-db",
|
|
3
|
-
"version": "0.1.
|
|
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.
|
|
61
|
+
"@atscript/db": "^0.1.64"
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
64
|
"postinstall": "asc -f dts",
|