@antelopejs/interface-data-api 0.6.2 → 0.7.0
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/README.md +28 -7
- package/dist/components.d.ts +6 -6
- package/dist/components.js +1 -1
- package/dist/components.js.map +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/internal/deferred-joined-stream.js +11 -5
- package/dist/internal/deferred-joined-stream.js.map +1 -1
- package/dist/internal/field-types.d.ts +12 -5
- package/dist/internal/filters.js +1 -1
- package/dist/internal/filters.js.map +1 -1
- package/dist/internal/guards.d.ts +2 -2
- package/dist/internal/guards.js +5 -0
- package/dist/internal/guards.js.map +1 -1
- package/dist/internal/properties.d.ts +2 -2
- package/dist/internal/properties.js +24 -13
- package/dist/internal/properties.js.map +1 -1
- package/dist/internal/prototypes.d.ts +13 -5
- package/dist/internal/prototypes.js +21 -9
- package/dist/internal/prototypes.js.map +1 -1
- package/dist/internal/read-properties.d.ts +2 -2
- package/dist/internal/read-properties.js +8 -5
- package/dist/internal/read-properties.js.map +1 -1
- package/dist/internal/tables.d.ts +6 -7
- package/dist/internal/tables.js +1 -3
- package/dist/internal/tables.js.map +1 -1
- package/dist/internal/validation.d.ts +3 -3
- package/dist/internal/validation.js +32 -19
- package/dist/internal/validation.js.map +1 -1
- package/dist/metadata.d.ts +1 -1
- package/dist/tests/components/filter_comparisons.test.js +10 -0
- package/dist/tests/components/filter_comparisons.test.js.map +1 -1
- package/dist/tests/components/parse_body.test.js +1 -22
- package/dist/tests/components/parse_body.test.js.map +1 -1
- package/dist/tests/components/parse_body.untyped.spec.d.ts +1 -0
- package/dist/tests/components/parse_body.untyped.spec.js +42 -0
- package/dist/tests/components/parse_body.untyped.spec.js.map +1 -0
- package/dist/tests/components/stored_row.test.d.ts +1 -0
- package/dist/tests/components/stored_row.test.js +117 -0
- package/dist/tests/components/stored_row.test.js.map +1 -0
- package/dist/tests/internal/controller-fields.test.js +8 -6
- package/dist/tests/internal/controller-fields.test.js.map +1 -1
- package/docs/3.routes.md +4 -2
- package/docs/6.listable.md +2 -0
- package/package.json +3 -3
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/** @internal @packageDocumentation */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.ReadProperties = ReadProperties;
|
|
5
|
+
const interface_api_util_1 = require("@antelopejs/interface-api-util");
|
|
5
6
|
const guards_1 = require("./guards");
|
|
6
7
|
const meta_records_1 = require("./meta-records");
|
|
7
8
|
const prototypes_1 = require("./prototypes");
|
|
@@ -10,17 +11,17 @@ function listedIn(field, mode) {
|
|
|
10
11
|
}
|
|
11
12
|
async function ReadProperties(obj, meta, dbData, action, { onlyList, listMode } = {}) {
|
|
12
13
|
const readable = meta.readable[action ?? "_default"] ?? meta.readable._default;
|
|
13
|
-
const
|
|
14
|
+
const fields = {};
|
|
14
15
|
const res = {};
|
|
15
16
|
for (const [key, field] of readable.props) {
|
|
16
17
|
if (onlyList && !field.listable) {
|
|
17
18
|
continue;
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
+
fields[key] = dbData[field.dbName || key];
|
|
20
21
|
res[key] = dbData[field.dbName || key];
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
fields.table = dbData;
|
|
24
|
+
const instance = (0, prototypes_1.controllerReceiver)(obj, meta.target, fields);
|
|
24
25
|
for (const [key, field] of readable.getters) {
|
|
25
26
|
if (onlyList && !field.listable) {
|
|
26
27
|
continue;
|
|
@@ -29,7 +30,9 @@ async function ReadProperties(obj, meta, dbData, action, { onlyList, listMode }
|
|
|
29
30
|
continue;
|
|
30
31
|
}
|
|
31
32
|
const val = field.desc?.get?.apply(instance);
|
|
32
|
-
|
|
33
|
+
const result = await ((0, guards_1.isFunction)(val) ? val() : val);
|
|
34
|
+
(0, interface_api_util_1.assert)((0, guards_1.isWriteValue)(result), 500, `Getter '${key}' returned a bigint, a symbol or a function, which a response cannot hold`);
|
|
35
|
+
res[key] = result;
|
|
33
36
|
}
|
|
34
37
|
return res;
|
|
35
38
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-properties.js","sourceRoot":"","sources":["../../src/internal/read-properties.ts"],"names":[],"mappings":";AAAA,sCAAsC;;
|
|
1
|
+
{"version":3,"file":"read-properties.js","sourceRoot":"","sources":["../../src/internal/read-properties.ts"],"names":[],"mappings":";AAAA,sCAAsC;;AA4BtC,wCAqCC;AA/DD,uEAAwD;AAQxD,qCAAoD;AACpD,iDAA0C;AAC1C,6CAAkD;AAUlD,SAAS,QAAQ,CAAC,KAAgB,EAAE,IAAY;IAC9C,OAAO,CACL,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAA,uBAAQ,EAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,SAAS,CAC7E,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,cAAc,CAClC,GAA2B,EAC3B,IAAiB,EACjB,MAAiB,EACjB,MAAe,EACf,EAAE,QAAQ,EAAE,QAAQ,KAAiB,EAAE;IAEvC,MAAM,QAAQ,GACZ,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;IAChE,MAAM,MAAM,GAAc,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAC1C,IAAI,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YAChC,SAAS;QACX,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;QAC1C,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC;IACtB,MAAM,QAAQ,GAAG,IAAA,+BAAkB,EAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QAC5C,IAAI,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YAChC,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC;YACzD,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAY,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QACtD,MAAM,MAAM,GAAY,MAAM,CAAC,IAAA,mBAAU,EAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC9D,IAAA,2BAAM,EACJ,IAAA,qBAAY,EAAC,MAAM,CAAC,EACpB,GAAG,EACH,WAAW,GAAG,2EAA2E,CAC1F,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IACpB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/** @internal @packageDocumentation */
|
|
2
2
|
import type { Constructible } from "@antelopejs/interface-database-decorators/common";
|
|
3
3
|
import type { DataModel } from "@antelopejs/interface-database-decorators/model";
|
|
4
|
-
import type { SchemaInstance, Table, ValueProxy } from "@antelopejs/interface-database";
|
|
5
|
-
import type { ComputedFieldData,
|
|
4
|
+
import type { SchemaInstance, Stream, Table, ValueProxy } from "@antelopejs/interface-database";
|
|
5
|
+
import type { ComputedFieldData, StoredRow } from "../metadata";
|
|
6
6
|
export type TableRow = Parameters<ComputedFieldData["expr"]>[0];
|
|
7
7
|
/**
|
|
8
8
|
* The database model a controller holds under its `@ModelReference` field,
|
|
9
9
|
* typed by the table rows it reads.
|
|
10
10
|
*/
|
|
11
|
-
export type ModelInstance = InstanceType<DataModel<
|
|
12
|
-
constructor: DataModel<
|
|
11
|
+
export type ModelInstance = InstanceType<DataModel<StoredRow>> & {
|
|
12
|
+
constructor: DataModel<StoredRow>;
|
|
13
13
|
};
|
|
14
14
|
/** Whether a value is a database model: its table, and its row conversion. */
|
|
15
15
|
export declare function isModelInstance(value: unknown): value is ModelInstance;
|
|
@@ -21,8 +21,7 @@ export interface TableTargetReference {
|
|
|
21
21
|
export declare function targetTable(sourceDb: SchemaInstance<any>, target: TableTargetReference): Table<any>;
|
|
22
22
|
/**
|
|
23
23
|
* The lookup side of a relation: `table` reduced to `fields`, with the
|
|
24
|
-
* internal fields the modifiers keep
|
|
25
|
-
* the database accepts wherever it takes a table, but its type is a stream.
|
|
24
|
+
* internal fields the modifiers keep, as the stream `lookup` takes.
|
|
26
25
|
*/
|
|
27
|
-
export declare function pluckedTable(table: Table<any>, ...fields: string[]):
|
|
26
|
+
export declare function pluckedTable(table: Table<any>, ...fields: string[]): Stream<any>;
|
|
28
27
|
export declare function Get<T extends object>(table: Table<T>, id: string | ValueProxy<string>, index?: string): import("@antelopejs/interface-database").SingleSelection<T> | import("@antelopejs/interface-database").Datum<T | null>;
|
package/dist/internal/tables.js
CHANGED
|
@@ -32,11 +32,9 @@ function targetTable(sourceDb, target) {
|
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* The lookup side of a relation: `table` reduced to `fields`, with the
|
|
35
|
-
* internal fields the modifiers keep
|
|
36
|
-
* the database accepts wherever it takes a table, but its type is a stream.
|
|
35
|
+
* internal fields the modifiers keep, as the stream `lookup` takes.
|
|
37
36
|
*/
|
|
38
37
|
function pluckedTable(table, ...fields) {
|
|
39
|
-
// SAFETY: pluck returns a Stream, which has none of Table's own methods; pluckedTable is only called in joined.ts and foreign.ts to build the right-hand side of lookup, and lookup reads that argument only through its stage list (build()), which the pluck stage extends.
|
|
40
38
|
return table.pluck("_internal", ...fields);
|
|
41
39
|
}
|
|
42
40
|
function Get(table, id, index) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tables.js","sourceRoot":"","sources":["../../src/internal/tables.ts"],"names":[],"mappings":";AAAA,sCAAsC;;
|
|
1
|
+
{"version":3,"file":"tables.js","sourceRoot":"","sources":["../../src/internal/tables.ts"],"names":[],"mappings":";AAAA,sCAAsC;;AA2BtC,0CAUC;AAoBD,kCAWC;AAMD,oCAKC;AAED,kBAQC;AAvFD,uEAAwD;AAYxD,qCAA0D;AAY1D,8EAA8E;AAC9E,SAAgB,eAAe,CAAC,KAAc;IAC5C,OAAO,CACL,IAAA,iBAAQ,EAAC,KAAK,CAAC;QACf,OAAO,IAAI,KAAK;QAChB,IAAA,iBAAQ,EAAC,KAAK,CAAC,KAAK,CAAC;QACrB,UAAU,IAAI,KAAK;QACnB,IAAA,iBAAQ,EAAC,KAAK,CAAC,QAAQ,CAAC;QACxB,cAAc,IAAI,KAAK,CAAC,WAAW;QACnC,IAAA,mBAAU,EAAC,KAAK,CAAC,WAAW,CAAC,YAAY,CAAC,CAC3C,CAAC;AACJ,CAAC;AAQD,SAAS,YAAY,CACnB,KAAgC;IAEhC,OAAO,CACL,IAAA,mBAAU,EAAC,KAAK,CAAC;QACjB,OAAO,IAAI,KAAK;QAChB,IAAA,mBAAU,EAAC,KAAK,CAAC,KAAK,CAAC;QACvB,MAAM,IAAI,KAAK;QACf,IAAA,mBAAU,EAAC,KAAK,CAAC,IAAI,CAAC,CACvB,CAAC;AACJ,CAAC;AAED,SAAgB,WAAW,CACzB,QAA6B,EAC7B,MAA4B;IAE5B,IAAI,CAAC,MAAM,CAAC,UAAU;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5D,IAAA,2BAAM,EACJ,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,EAC/B,GAAG,EACH,UAAU,MAAM,CAAC,KAAK,gBAAgB,MAAM,CAAC,UAAU,iCAAiC,CACzF,CAAC;IACF,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAC1B,KAAiB,EACjB,GAAG,MAAgB;IAEnB,OAAO,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED,SAAgB,GAAG,CACjB,KAAe,EACf,EAA+B,EAC/B,KAAc;IAEd,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjC,MAAM,GAAG,GAAG,IAAA,iBAAQ,EAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAA6B,CAAC;IACrE,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/** @internal @packageDocumentation */
|
|
2
2
|
import type { ValueProxy } from "@antelopejs/interface-database";
|
|
3
3
|
import type { Validation } from "../components";
|
|
4
|
-
import type { DataAPIMeta, DataControllerInstance,
|
|
4
|
+
import type { DataAPIMeta, DataControllerInstance, StoredRow } from "../metadata";
|
|
5
5
|
type RequestBody = Validation.RequestBody;
|
|
6
6
|
type WrittenBody = Validation.WrittenBody;
|
|
7
7
|
export declare function ParseBody(body: WrittenBody): RequestBody;
|
|
8
|
-
export declare function Lock(obj: DataControllerInstance, meta: DataAPIMeta, data:
|
|
9
|
-
export declare function Unlock(obj: DataControllerInstance, meta: DataAPIMeta, dbData:
|
|
8
|
+
export declare function Lock(obj: DataControllerInstance, meta: DataAPIMeta, data: StoredRow, written: string[]): void;
|
|
9
|
+
export declare function Unlock(obj: DataControllerInstance, meta: DataAPIMeta, dbData: StoredRow): void;
|
|
10
10
|
export declare function UnlockRequest<T extends {}, K extends keyof T>(obj: DataControllerInstance, meta: DataAPIMeta, row: ValueProxy<T>, field: K): ValueProxy<T[K]>;
|
|
11
11
|
export declare function ClearInternal(meta: DataAPIMeta, obj: Parameters<typeof Validation.ClearInternal>[1]): void;
|
|
12
12
|
export {};
|
|
@@ -10,6 +10,23 @@ const interface_api_util_1 = require("@antelopejs/interface-api-util");
|
|
|
10
10
|
const common_1 = require("@antelopejs/interface-database-decorators/modifiers/common");
|
|
11
11
|
const prototypes_1 = require("./prototypes");
|
|
12
12
|
const guards_1 = require("./guards");
|
|
13
|
+
/**
|
|
14
|
+
* The fields `keys` of a related row, refused with 500 when one holds a value
|
|
15
|
+
* no response can.
|
|
16
|
+
*/
|
|
17
|
+
function relatedRow(plain, keys) {
|
|
18
|
+
const row = {};
|
|
19
|
+
for (const key of keys) {
|
|
20
|
+
const value = plain[key];
|
|
21
|
+
(0, interface_api_util_1.assert)((0, guards_1.isWriteValue)(value), 500, `Field '${key}' of a related row holds a bigint, a symbol or a function, which a response cannot hold`);
|
|
22
|
+
row[key] = value;
|
|
23
|
+
}
|
|
24
|
+
return row;
|
|
25
|
+
}
|
|
26
|
+
/** Whether a row value is a list, whose items are row values too. */
|
|
27
|
+
function isStoredList(value) {
|
|
28
|
+
return Array.isArray(value);
|
|
29
|
+
}
|
|
13
30
|
function ParseBody(body) {
|
|
14
31
|
let data = body;
|
|
15
32
|
if (Buffer.isBuffer(body)) {
|
|
@@ -26,27 +43,27 @@ function ParseBody(body) {
|
|
|
26
43
|
function Lock(obj, meta, data, written) {
|
|
27
44
|
for (const [modifier, field] of meta.modifierKeys.entries()) {
|
|
28
45
|
const keyed = modifier;
|
|
29
|
-
|
|
30
|
-
(0, common_1.lock)(data, keyed, written, key);
|
|
46
|
+
(0, common_1.lock)(data, keyed, written, ...(0, prototypes_1.controllerField)(obj, field));
|
|
31
47
|
}
|
|
32
48
|
}
|
|
33
49
|
function Unlock(obj, meta, dbData) {
|
|
34
50
|
for (const [name, field] of Object.entries(meta.fields)) {
|
|
35
51
|
if (field.foreign && (0, guards_1.isObject)(dbData[name]) && field.foreign[1]) {
|
|
36
52
|
const foreignSchema = field.foreign[1];
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
53
|
+
const related = dbData[name];
|
|
54
|
+
dbData[name] = isStoredList(related)
|
|
55
|
+
? related.map((entry) => (0, guards_1.isObject)(entry) ? (0, common_1.fromDatabase)(entry, foreignSchema) : entry)
|
|
56
|
+
: (0, common_1.fromDatabase)(related, foreignSchema);
|
|
40
57
|
}
|
|
41
58
|
}
|
|
42
59
|
for (const [modifier, field] of meta.modifierKeys.entries()) {
|
|
43
60
|
const keyed = modifier;
|
|
44
|
-
const key = (0, prototypes_1.
|
|
45
|
-
(0, common_1.unlock)(dbData, keyed, undefined, key);
|
|
61
|
+
const key = (0, prototypes_1.controllerField)(obj, field);
|
|
62
|
+
(0, common_1.unlock)(dbData, keyed, undefined, ...key);
|
|
46
63
|
for (const [foreign, fieldData] of Object.entries(meta.fields)) {
|
|
47
64
|
const related = dbData[foreign];
|
|
48
65
|
if (fieldData.foreign && (0, guards_1.isObject)(related)) {
|
|
49
|
-
(0, common_1.unlock)(related, keyed, undefined, key);
|
|
66
|
+
(0, common_1.unlock)(related, keyed, undefined, ...key);
|
|
50
67
|
}
|
|
51
68
|
}
|
|
52
69
|
}
|
|
@@ -54,7 +71,7 @@ function Unlock(obj, meta, dbData) {
|
|
|
54
71
|
function UnlockRequest(obj, meta, row, field) {
|
|
55
72
|
const modifiers = Array.from(meta.modifierKeys.entries()).map(([modifier, field]) => ({
|
|
56
73
|
modifier,
|
|
57
|
-
args:
|
|
74
|
+
args: (0, prototypes_1.controllerField)(obj, field),
|
|
58
75
|
}));
|
|
59
76
|
return (0, common_1.unlockrequest)(meta.tableClass, row, field, modifiers);
|
|
60
77
|
}
|
|
@@ -72,7 +89,7 @@ function ClearInternal(meta, obj) {
|
|
|
72
89
|
const processForeign = (data) => {
|
|
73
90
|
const plain = (0, common_1.toPlainData)(data);
|
|
74
91
|
if (!foreign?.[4]) {
|
|
75
|
-
return plain;
|
|
92
|
+
return relatedRow(plain, Object.keys(plain));
|
|
76
93
|
}
|
|
77
94
|
const targetJoined = foreign[6];
|
|
78
95
|
if (targetJoined?.length) {
|
|
@@ -83,16 +100,12 @@ function ClearInternal(meta, obj) {
|
|
|
83
100
|
return null;
|
|
84
101
|
}
|
|
85
102
|
}
|
|
86
|
-
|
|
87
|
-
for (const key of foreign[4]) {
|
|
88
|
-
const value = plain[key];
|
|
89
|
-
plainPlucked[key] = value;
|
|
90
|
-
}
|
|
91
|
-
return plainPlucked;
|
|
103
|
+
return relatedRow(plain, foreign[4]);
|
|
92
104
|
};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
105
|
+
const related = entry[name];
|
|
106
|
+
entry[name] = isStoredList(related)
|
|
107
|
+
? related.map((item) => (0, guards_1.isObject)(item) ? processForeign(item) : item)
|
|
108
|
+
: processForeign(related);
|
|
96
109
|
}
|
|
97
110
|
}
|
|
98
111
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/internal/validation.ts"],"names":[],"mappings":";AAAA,sCAAsC;;
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/internal/validation.ts"],"names":[],"mappings":"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"}
|
package/dist/metadata.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { DataControllerCallbackWithOptions, DataControllerInstance } from "
|
|
|
5
5
|
import type { FieldValidator, FieldData, ComputedExpression, ComputedOptions, FilterFunction, ForeignOptions, ReadableAccessFields, WritableAccessFields } from "./internal/field-types";
|
|
6
6
|
export { FilterValuesOf } from "./internal/filters";
|
|
7
7
|
export type { DataControllerCallback, DataControllerCallbackWithOptions, DataControllerInstance, ExtractCallback, DataControllerDef, ExtractDefCallbacks, } from "./internal/controller-types";
|
|
8
|
-
export type { ForeignJoinedRef, FieldParseSuccess, FieldParseFailure, FieldParseResult, FieldValidationResult, FieldValue, FieldValues,
|
|
8
|
+
export type { ForeignJoinedRef, FieldParseSuccess, FieldParseFailure, FieldParseResult, FieldValidationResult, FieldValue, FieldValues, StoredRow, ForeignOptions, FieldValidator, FieldData, ComputedExpression, ComputedOptions, ComputedFieldData, FilterValue, FieldFilter, FilterFunction, ReadableAccessFields, WritableAccessFields, } from "./internal/field-types";
|
|
9
9
|
/**
|
|
10
10
|
* Field access mode enum.
|
|
11
11
|
*/
|
|
@@ -30,5 +30,15 @@ describe("Parameters.ExtractFilters - comparisons", () => {
|
|
|
30
30
|
it("hands an unnamed value that contains a colon to a custom filter", () => {
|
|
31
31
|
(0, chai_1.expect)(components_1.Parameters.ExtractFilters(context("filter_title=http://example.com"), meta)).to.eql({ title: ["//example.com", "http"] });
|
|
32
32
|
});
|
|
33
|
+
it("reads the comparison after the colons a value opens with", () => {
|
|
34
|
+
(0, chai_1.expect)(components_1.Parameters.ExtractFilters(context("filter_title=::is:abc"), meta)).to.eql({ title: ["abc", "is"] });
|
|
35
|
+
});
|
|
36
|
+
it("reads a long value without a colon in linear time", () => {
|
|
37
|
+
const value = "a".repeat(64_000);
|
|
38
|
+
const start = performance.now();
|
|
39
|
+
const filters = components_1.Parameters.ExtractFilters(context(`filter_title=${value}`), meta);
|
|
40
|
+
(0, chai_1.expect)(performance.now() - start).to.be.below(250);
|
|
41
|
+
(0, chai_1.expect)(filters).to.eql({ title: [value, "eq"] });
|
|
42
|
+
});
|
|
33
43
|
});
|
|
34
44
|
//# sourceMappingURL=filter_comparisons.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter_comparisons.test.js","sourceRoot":"","sources":["../../../src/tests/components/filter_comparisons.test.ts"],"names":[],"mappings":";;AAAA,+BAA8B;AAE9B,iDAA8C;AAC9C,6CAA6C;AAE7C,2CAAwD;AAExD,MAAM,IAAI,GAAG,IAAI,sBAAW,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AAEpE,SAAS,OAAO,CAAC,KAAa;IAC5B,OAAO,MAAM,CAAC,MAAM,CAAC,IAAA,2BAAoB,EAAC,qBAAqB,KAAK,EAAE,CAAC,EAAE;QACvE,YAAY,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE;KACrC,CAAC,CAAC;AACL,CAAC;AAED,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACvD,KAAK,MAAM,UAAU,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QAC9D,EAAE,CAAC,aAAa,UAAU,aAAa,EAAE,GAAG,EAAE;YAC5C,IAAA,aAAM,EACJ,uBAAU,CAAC,cAAc,CACvB,OAAO,CAAC,gBAAgB,UAAU,MAAM,CAAC,EACzC,IAAI,CACL,CACF,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC;IAED,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,IAAA,aAAM,EAAC,uBAAU,CAAC,cAAc,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CACzE,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CACzB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,IAAA,aAAM,EACJ,uBAAU,CAAC,cAAc,CACvB,OAAO,CAAC,oCAAoC,CAAC,EAC7C,IAAI,CACL,CACF,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,oBAAoB,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,KAAK,MAAM,UAAU,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC;YAC3D,IAAA,aAAM,EACJ,uBAAU,CAAC,cAAc,CACvB,OAAO,CAAC,gBAAgB,UAAU,MAAM,CAAC,EACzC,IAAI,CACL,EACD,UAAU,CACX,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,IAAA,aAAM,EACJ,uBAAU,CAAC,cAAc,CACvB,OAAO,CAAC,iCAAiC,CAAC,EAC1C,IAAI,CACL,CACF,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"filter_comparisons.test.js","sourceRoot":"","sources":["../../../src/tests/components/filter_comparisons.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,9 +15,6 @@ function statusOfRefusal(body) {
|
|
|
15
15
|
function body(fields) {
|
|
16
16
|
return Buffer.from(JSON.stringify(fields));
|
|
17
17
|
}
|
|
18
|
-
class Money {
|
|
19
|
-
amount = 1;
|
|
20
|
-
}
|
|
21
18
|
describe("Validation.ParseBody", () => {
|
|
22
19
|
it("parses a JSON object", () => (0, chai_1.expect)(components_1.Validation.ParseBody(body({ name: "a", tags: [1, null] }))).to.eql({
|
|
23
20
|
name: "a",
|
|
@@ -45,31 +42,13 @@ describe("Validation.ParseBody", () => {
|
|
|
45
42
|
"a",
|
|
46
43
|
]);
|
|
47
44
|
});
|
|
48
|
-
it("refuses a body nested deeper than the call stack allows that ends in a function", () => {
|
|
49
|
-
const deepest = { __proto__: null, run: () => 1 };
|
|
50
|
-
const nested = Array.from({ length: 50000 }).reduce((inner) => ({ next: inner }), deepest);
|
|
51
|
-
// @ts-expect-error a function deep in the body is off-contract input, and the body is refused with 400
|
|
52
|
-
(0, chai_1.expect)(statusOfRefusal(nested)).to.equal(400);
|
|
53
|
-
});
|
|
54
45
|
it("accepts a body without a prototype", () => {
|
|
55
46
|
const bare = { __proto__: null, name: "a" };
|
|
56
47
|
(0, chai_1.expect)(components_1.Validation.ParseBody(bare)).to.equal(bare);
|
|
57
48
|
});
|
|
58
|
-
it("refuses a parsed body
|
|
59
|
-
const withFunction = { __proto__: null, run: () => 1 };
|
|
60
|
-
const withInstance = { __proto__: null, price: new Money() };
|
|
61
|
-
const withBigInt = { __proto__: null, count: 1n };
|
|
62
|
-
const withUndefined = { __proto__: null, list: [1, undefined] };
|
|
49
|
+
it("refuses a cyclic parsed body", () => {
|
|
63
50
|
const cyclic = {};
|
|
64
51
|
cyclic.self = cyclic;
|
|
65
|
-
// @ts-expect-error a function value is off-contract input, and the body is refused with 400
|
|
66
|
-
(0, chai_1.expect)(statusOfRefusal(withFunction)).to.equal(400);
|
|
67
|
-
// @ts-expect-error a class instance value is off-contract input, and the body is refused with 400
|
|
68
|
-
(0, chai_1.expect)(statusOfRefusal(withInstance)).to.equal(400);
|
|
69
|
-
// @ts-expect-error a bigint value is off-contract input, and the body is refused with 400
|
|
70
|
-
(0, chai_1.expect)(statusOfRefusal(withBigInt)).to.equal(400);
|
|
71
|
-
// @ts-expect-error an undefined array item is off-contract input, and the body is refused with 400
|
|
72
|
-
(0, chai_1.expect)(statusOfRefusal(withUndefined)).to.equal(400);
|
|
73
52
|
(0, chai_1.expect)(statusOfRefusal(cyclic)).to.equal(400);
|
|
74
53
|
});
|
|
75
54
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse_body.test.js","sourceRoot":"","sources":["../../../src/tests/components/parse_body.test.ts"],"names":[],"mappings":";;AAAA,+BAA8B;AAC9B,6DAAuD;AAEvD,iDAA8C;AAG9C,SAAS,eAAe,CAAC,IAAgD;IACvE,IAAI,CAAC;QACH,uBAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,KAAK,YAAY,0BAAU,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACrE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,IAAI,CAAC,MAAkB;IAC9B,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"parse_body.test.js","sourceRoot":"","sources":["../../../src/tests/components/parse_body.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const chai_1 = require("chai");
|
|
4
|
+
const interface_api_1 = require("@antelopejs/interface-api");
|
|
5
|
+
const components_1 = require("../../components");
|
|
6
|
+
/**
|
|
7
|
+
* The HTTP status `Validation.ParseBody` refuses `body` with, or 200 when it
|
|
8
|
+
* accepts it.
|
|
9
|
+
*
|
|
10
|
+
* @param {unknown} body A value outside the body types the route declares.
|
|
11
|
+
*/
|
|
12
|
+
function statusOfRefusal(body) {
|
|
13
|
+
try {
|
|
14
|
+
components_1.Validation.ParseBody(body);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
return error instanceof interface_api_1.HTTPResult ? error.getStatus() : undefined;
|
|
18
|
+
}
|
|
19
|
+
return 200;
|
|
20
|
+
}
|
|
21
|
+
class Money {
|
|
22
|
+
amount = 1;
|
|
23
|
+
}
|
|
24
|
+
describe("Validation.ParseBody on a parsed body its types forbid", () => {
|
|
25
|
+
it("refuses a body nested deeper than the call stack allows that ends in a function", () => {
|
|
26
|
+
const deepest = { __proto__: null, run: () => 1 };
|
|
27
|
+
let nested = { next: deepest };
|
|
28
|
+
for (let depth = 1; depth < 50000; depth += 1) {
|
|
29
|
+
nested = { next: nested };
|
|
30
|
+
}
|
|
31
|
+
(0, chai_1.expect)(statusOfRefusal(nested)).to.equal(400);
|
|
32
|
+
});
|
|
33
|
+
it("refuses a parsed body holding what JSON cannot", () => {
|
|
34
|
+
(0, chai_1.expect)([
|
|
35
|
+
statusOfRefusal({ __proto__: null, run: () => 1 }),
|
|
36
|
+
statusOfRefusal({ __proto__: null, price: new Money() }),
|
|
37
|
+
statusOfRefusal({ __proto__: null, count: 1n }),
|
|
38
|
+
statusOfRefusal({ __proto__: null, list: [1, undefined] }),
|
|
39
|
+
]).to.eql([400, 400, 400, 400]);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=parse_body.untyped.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse_body.untyped.spec.js","sourceRoot":"","sources":["../../../src/tests/components/parse_body.untyped.spec.js"],"names":[],"mappings":";;AAAA,+BAA8B;AAC9B,6DAAuD;AAEvD,iDAA8C;AAE9C;;;;;GAKG;AACH,SAAS,eAAe,CAAC,IAAI;IAC3B,IAAI,CAAC;QACH,uBAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,KAAK,YAAY,0BAAU,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACrE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,KAAK;IACT,MAAM,GAAG,CAAC,CAAC;CACZ;AAED,QAAQ,CAAC,wDAAwD,EAAE,GAAG,EAAE;IACtE,EAAE,CAAC,iFAAiF,EAAE,GAAG,EAAE;QACzF,MAAM,OAAO,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;QAClD,IAAI,MAAM,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC/B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC9C,MAAM,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC5B,CAAC;QACD,IAAA,aAAM,EAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,IAAA,aAAM,EAAC;YACL,eAAe,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;YAClD,eAAe,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,EAAE,EAAE,CAAC;YACxD,eAAe,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;YAC/C,eAAe,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC;SAC3D,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
const chai_1 = require("chai");
|
|
10
|
+
const interface_api_1 = require("@antelopejs/interface-api");
|
|
11
|
+
const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
|
|
12
|
+
const components_1 = require("../../components");
|
|
13
|
+
const metadata_1 = require("../../metadata");
|
|
14
|
+
async function statusOf(run) {
|
|
15
|
+
try {
|
|
16
|
+
await run();
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
if (!(error instanceof interface_api_1.HTTPResult))
|
|
20
|
+
throw error;
|
|
21
|
+
return error.getStatus();
|
|
22
|
+
}
|
|
23
|
+
return 200;
|
|
24
|
+
}
|
|
25
|
+
function metaOf(target) {
|
|
26
|
+
const meta = new metadata_1.DataAPIMeta(target);
|
|
27
|
+
meta.tableClass = class TableRow {
|
|
28
|
+
};
|
|
29
|
+
meta.schemaName = "default";
|
|
30
|
+
return meta;
|
|
31
|
+
}
|
|
32
|
+
class Tally {
|
|
33
|
+
get total() {
|
|
34
|
+
return 1n;
|
|
35
|
+
}
|
|
36
|
+
get label() {
|
|
37
|
+
return "tally";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
class Stamped {
|
|
41
|
+
stamp = () => "now";
|
|
42
|
+
}
|
|
43
|
+
class Hooked {
|
|
44
|
+
onSave = () => "saved";
|
|
45
|
+
title = "draft";
|
|
46
|
+
}
|
|
47
|
+
class Counted {
|
|
48
|
+
set count(value) {
|
|
49
|
+
this.table.count = BigInt(value);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
let Owner = class Owner extends interface_database_decorators_1.Table {
|
|
53
|
+
name = "ada";
|
|
54
|
+
count = 1n;
|
|
55
|
+
};
|
|
56
|
+
Owner = __decorate([
|
|
57
|
+
(0, interface_database_decorators_1.RegisterTable)("stored-row-owners", "default")
|
|
58
|
+
], Owner);
|
|
59
|
+
describe("A row value no database stores", () => {
|
|
60
|
+
before(() => (0, interface_database_decorators_1.RegisterSchema)("default"));
|
|
61
|
+
it("refuses a getter that returns a bigint on read", async () => {
|
|
62
|
+
const meta = metaOf(Tally);
|
|
63
|
+
meta
|
|
64
|
+
.setDescriptor("total", Object.getOwnPropertyDescriptor(Tally.prototype, "total"))
|
|
65
|
+
.setMode("total", metadata_1.AccessMode.ReadOnly);
|
|
66
|
+
(0, chai_1.expect)(await statusOf(() => components_1.Query.ReadProperties(new Tally(), meta, {}))).to.equal(500);
|
|
67
|
+
});
|
|
68
|
+
it("reads a getter that returns text", async () => {
|
|
69
|
+
const meta = metaOf(Tally);
|
|
70
|
+
meta
|
|
71
|
+
.setDescriptor("label", Object.getOwnPropertyDescriptor(Tally.prototype, "label"))
|
|
72
|
+
.setMode("label", metadata_1.AccessMode.ReadOnly);
|
|
73
|
+
(0, chai_1.expect)(await components_1.Query.ReadProperties(new Tally(), meta, {})).to.eql({
|
|
74
|
+
label: "tally",
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
it("refuses a field default that is a function on write", async () => {
|
|
78
|
+
const meta = metaOf(Stamped);
|
|
79
|
+
meta.setMode("stamp", metadata_1.AccessMode.ReadOnly);
|
|
80
|
+
(0, chai_1.expect)(await statusOf(() => components_1.Query.WriteProperties(new Stamped(), meta, {}))).to.equal(500);
|
|
81
|
+
});
|
|
82
|
+
it("writes a field default beside a member default that is a function", async () => {
|
|
83
|
+
const meta = metaOf(Hooked);
|
|
84
|
+
meta.setMode("title", metadata_1.AccessMode.ReadOnly);
|
|
85
|
+
(0, chai_1.expect)(await components_1.Query.WriteProperties(new Hooked(), meta, {})).to.eql({
|
|
86
|
+
title: "draft",
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
it("refuses a setter that writes a bigint into the row", async () => {
|
|
90
|
+
const meta = metaOf(Counted);
|
|
91
|
+
meta
|
|
92
|
+
.setDescriptor("count", Object.getOwnPropertyDescriptor(Counted.prototype, "count"))
|
|
93
|
+
.setMode("count", metadata_1.AccessMode.WriteOnly);
|
|
94
|
+
(0, chai_1.expect)(await statusOf(() => components_1.Query.WriteProperties(new Counted(), meta, { count: 2 }))).to.equal(500);
|
|
95
|
+
});
|
|
96
|
+
it("refuses a related row that holds a bigint", async () => {
|
|
97
|
+
const meta = metaOf(Stamped);
|
|
98
|
+
meta.setForeign("owner", "stored-row-owners");
|
|
99
|
+
(0, chai_1.expect)(await statusOf(() => components_1.Validation.ClearInternal(meta, { owner: new Owner() }))).to.equal(500);
|
|
100
|
+
});
|
|
101
|
+
it("refuses a plucked related row that holds a bigint", async () => {
|
|
102
|
+
const meta = metaOf(Stamped);
|
|
103
|
+
meta.setForeign("owner", "stored-row-owners", undefined, undefined, [
|
|
104
|
+
"name",
|
|
105
|
+
"count",
|
|
106
|
+
]);
|
|
107
|
+
(0, chai_1.expect)(await statusOf(() => components_1.Validation.ClearInternal(meta, { owner: new Owner() }))).to.equal(500);
|
|
108
|
+
});
|
|
109
|
+
it("keeps a related row that holds stored values", () => {
|
|
110
|
+
const meta = metaOf(Stamped);
|
|
111
|
+
meta.setForeign("owner", "stored-row-owners");
|
|
112
|
+
const row = { owner: { name: "ada" } };
|
|
113
|
+
components_1.Validation.ClearInternal(meta, row);
|
|
114
|
+
(0, chai_1.expect)(row).to.eql({ owner: { name: "ada" } });
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
//# sourceMappingURL=stored_row.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored_row.test.js","sourceRoot":"","sources":["../../../src/tests/components/stored_row.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,15 +11,17 @@ class Holder {
|
|
|
11
11
|
return `read from ${this.own}`;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
describe("
|
|
14
|
+
describe("controllerField", () => {
|
|
15
15
|
it("answers own fields and inherited accessors by name", () => {
|
|
16
|
-
const
|
|
17
|
-
node_assert_1.default.
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
const holder = new Holder();
|
|
17
|
+
node_assert_1.default.deepStrictEqual([
|
|
18
|
+
(0, prototypes_1.controllerField)(holder, "own"),
|
|
19
|
+
(0, prototypes_1.controllerField)(holder, "inherited"),
|
|
20
|
+
(0, prototypes_1.controllerField)(holder, "absent"),
|
|
21
|
+
], [["own value"], ["read from own value"], [undefined]]);
|
|
20
22
|
});
|
|
21
23
|
it("refuses a value that is not an object", () => {
|
|
22
|
-
node_assert_1.default.throws(() => (0, prototypes_1.
|
|
24
|
+
node_assert_1.default.throws(() => (0, prototypes_1.controllerField)(() => undefined, "own"), /A data controller must be an object/);
|
|
23
25
|
});
|
|
24
26
|
});
|
|
25
27
|
//# sourceMappingURL=controller-fields.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller-fields.test.js","sourceRoot":"","sources":["../../../src/tests/internal/controller-fields.test.ts"],"names":[],"mappings":";;;;;AAAA,8DAAiC;AAEjC,
|
|
1
|
+
{"version":3,"file":"controller-fields.test.js","sourceRoot":"","sources":["../../../src/tests/internal/controller-fields.test.ts"],"names":[],"mappings":";;;;;AAAA,8DAAiC;AAEjC,0DAA4D;AAE5D,MAAM,MAAM;IACV,GAAG,GAAG,WAAW,CAAC;IAElB,IAAI,SAAS;QACX,OAAO,aAAa,IAAI,CAAC,GAAG,EAAE,CAAC;IACjC,CAAC;CACF;AAED,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QAE5B,qBAAM,CAAC,eAAe,CACpB;YACE,IAAA,4BAAe,EAAC,MAAM,EAAE,KAAK,CAAC;YAC9B,IAAA,4BAAe,EAAC,MAAM,EAAE,WAAW,CAAC;YACpC,IAAA,4BAAe,EAAC,MAAM,EAAE,QAAQ,CAAC;SAClC,EACD,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,qBAAqB,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CACtD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,qBAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,IAAA,4BAAe,EAAC,GAAG,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,EAC7C,qCAAqC,CACtC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/docs/3.routes.md
CHANGED
|
@@ -323,7 +323,7 @@ const routes = {
|
|
|
323
323
|
};
|
|
324
324
|
```
|
|
325
325
|
|
|
326
|
-
The `GetGuard` callback receives `(ctx, current, params)`. Declare it as a regular function to reach the controller through `this`, typed `DataControllerInstance`. That type is `object`, with no string index, so narrow `this` (with `instanceof` your controller class, for example) before you read a controller field. `current` is `
|
|
326
|
+
The `GetGuard` callback receives `(ctx, current, params)`. Declare it as a regular function to reach the controller through `this`, typed `DataControllerInstance`. That type is `object`, with no string index, so narrow `this` (with `instanceof` your controller class, for example) before you read a controller field. `current` is a `StoredRow`: each value is one a database stores (`WriteValue`), a relation's row instance, a nested `StoredRow` or a list of those.
|
|
327
327
|
|
|
328
328
|
| Argument | Contents | Use it for |
|
|
329
329
|
| --------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------- |
|
|
@@ -419,7 +419,9 @@ The default routes answer with these HTTP errors.
|
|
|
419
419
|
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
420
420
|
| `400 Bad Request` | A field fails its validator, a mandatory field is missing, the body is not a JSON object, or a parameter is missing or invalid |
|
|
421
421
|
| `404 Not Found` | The record does not exist |
|
|
422
|
-
| `500 Internal Server Error` | The database operation fails,
|
|
422
|
+
| `500 Internal Server Error` | The database operation fails, the controller holds no model, or a row holds a value no database stores (see below) |
|
|
423
|
+
|
|
424
|
+
A row holds only values a database stores: text, numbers, booleans, `null`, `undefined`, dates, and arrays or objects of those. A route answers `500` when a getter it reads returns a `bigint`, a `symbol` or a function, when the default the controller class declares for a decorated field is one, when a setter writes one into the row, or when a related row holds one. Convert the value in the getter, default or setter, for example `String(total)` for a `bigint`, or keep a callback out of the decorated fields.
|
|
423
425
|
|
|
424
426
|
A failed mandatory or validator check answers a JSON body with a `code` and the `fields` concerned (see [validators](./5.validators.md#error-handling)). Every other error the routes raise answers its message as text, such as `Missing id.` or `Not Found`.
|
|
425
427
|
|
package/docs/6.listable.md
CHANGED
|
@@ -132,6 +132,8 @@ get fullName() {
|
|
|
132
132
|
}
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
+
A getter returns a value a database could store: text, a number, a boolean, `null`, `undefined`, a `Date`, or an array or object of those. A getter that returns a `bigint`, a `symbol` or a function, or an object holding one (an own `toJSON` method or arrow-function field counts), fails the read with `500`. Convert such a value before you return it, for example `String(total)` for a `bigint`.
|
|
136
|
+
|
|
135
137
|
## Pagination
|
|
136
138
|
|
|
137
139
|
Every list response carries pagination metadata. The response has this shape:
|