@antelopejs/interface-data-api 0.1.8 → 0.1.10
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/antelope.test.js +11 -10
- package/dist/antelope.test.js.map +1 -1
- package/dist/components.d.ts +4 -2
- package/dist/components.js +13 -8
- package/dist/components.js.map +1 -1
- package/dist/index.d.ts +25 -33
- package/dist/index.js +30 -15
- package/dist/index.js.map +1 -1
- package/dist/metadata.d.ts +20 -3
- package/dist/metadata.js +5 -1
- package/dist/metadata.js.map +1 -1
- package/dist/tests/components/access_control.test.js +2 -2
- package/dist/tests/components/access_control.test.js.map +1 -1
- package/dist/tests/components/computed.test.js +2 -2
- package/dist/tests/components/computed.test.js.map +1 -1
- package/dist/tests/components/deferred_joined.test.js +3 -3
- package/dist/tests/components/deferred_joined.test.js.map +1 -1
- package/dist/tests/components/filter_options.test.d.ts +1 -0
- package/dist/tests/components/filter_options.test.js +78 -0
- package/dist/tests/components/filter_options.test.js.map +1 -0
- package/dist/tests/components/foreign_joined.test.js +2 -2
- package/dist/tests/components/foreign_joined.test.js.map +1 -1
- package/dist/tests/components/joined.test.js +3 -3
- package/dist/tests/components/joined.test.js.map +1 -1
- package/dist/tests/components/listable.test.js +2 -2
- package/dist/tests/components/listable.test.js.map +1 -1
- package/dist/tests/components/mandatory.test.js +2 -2
- package/dist/tests/components/mandatory.test.js.map +1 -1
- package/dist/tests/components/modifier_key.test.js +2 -2
- package/dist/tests/components/modifier_key.test.js.map +1 -1
- package/dist/tests/components/per_action_access.test.js +1 -1
- package/dist/tests/components/per_action_access.test.js.map +1 -1
- package/dist/tests/components/validator.test.js +1 -1
- package/dist/tests/components/validator.test.js.map +1 -1
- package/dist/tests/index/get_guard.test.d.ts +1 -0
- package/dist/tests/index/get_guard.test.js +112 -0
- package/dist/tests/index/get_guard.test.js.map +1 -0
- package/dist/tests/index/routes.test.js +2 -2
- package/dist/tests/index/routes.test.js.map +1 -1
- package/dist/tests/integration.test.js +1 -1
- package/dist/tests/integration.test.js.map +1 -1
- package/dist/tests/utils.d.ts +7 -0
- package/dist/tests/utils.js +48 -6
- package/dist/tests/utils.js.map +1 -1
- package/dist/tests/utils.test.d.ts +1 -0
- package/dist/tests/utils.test.js +28 -0
- package/dist/tests/utils.test.js.map +1 -0
- package/docs/1.introduction.md +7 -7
- package/docs/10.joined.md +13 -13
- package/docs/11.computed.md +11 -15
- package/docs/2.data-controllers.md +4 -4
- package/docs/3.routes.md +48 -48
- package/docs/4.access-rights.md +5 -5
- package/docs/6.listable.md +7 -7
- package/docs/7.foreign-keys.md +7 -7
- package/docs/8.filters.md +16 -16
- package/docs/9.modifiers.md +2 -2
- package/package.json +44 -35
- package/skills/data-api-interface/SKILL.md +51 -7
package/dist/tests/utils.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.getFunctionName = getFunctionName;
|
|
4
7
|
exports.request = request;
|
|
@@ -10,15 +13,54 @@ exports.deleteRequest = deleteRequest;
|
|
|
10
13
|
exports.validateObject = validateObject;
|
|
11
14
|
exports.getSchemaInstance = getSchemaInstance;
|
|
12
15
|
exports.validateObjectList = validateObjectList;
|
|
13
|
-
const
|
|
16
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
14
17
|
const chai_1 = require("chai");
|
|
18
|
+
const interface_database_1 = require("@antelopejs/interface-database");
|
|
15
19
|
const constants_1 = require("./constants");
|
|
20
|
+
const UNKNOWN_FUNCTION_NAME = "unknown";
|
|
21
|
+
const PREPARE_STACK_TRACE = "prepareStackTrace";
|
|
22
|
+
const TESTS_FOLDER_PREFIX = `${__dirname}${node_path_1.default.sep}`;
|
|
23
|
+
function readCallSites(_error, callSites) {
|
|
24
|
+
return callSites;
|
|
25
|
+
}
|
|
26
|
+
function isCallSiteList(stack) {
|
|
27
|
+
return Array.isArray(stack);
|
|
28
|
+
}
|
|
29
|
+
function restoreErrorProperty(property, descriptor) {
|
|
30
|
+
if (!descriptor) {
|
|
31
|
+
Reflect.deleteProperty(Error, property);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
Object.defineProperty(Error, property, descriptor);
|
|
35
|
+
}
|
|
36
|
+
function captureCallSites() {
|
|
37
|
+
const { stackTraceLimit } = Error;
|
|
38
|
+
const prepareStackTrace = Object.getOwnPropertyDescriptor(Error, PREPARE_STACK_TRACE);
|
|
39
|
+
Error.stackTraceLimit = Infinity;
|
|
40
|
+
Error.prepareStackTrace = readCallSites;
|
|
41
|
+
try {
|
|
42
|
+
const stack = new Error().stack;
|
|
43
|
+
return isCallSiteList(stack) ? stack : [];
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
restoreErrorProperty(PREPARE_STACK_TRACE, prepareStackTrace);
|
|
47
|
+
Error.stackTraceLimit = stackTraceLimit;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function isTestCallSite(callSite) {
|
|
51
|
+
const fileName = callSite.getFileName();
|
|
52
|
+
return fileName !== __filename && !!fileName?.startsWith(TESTS_FOLDER_PREFIX);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Returns the name of the test function that called it.
|
|
56
|
+
*
|
|
57
|
+
* The caller is the first stack frame located in the tests folder, so frames
|
|
58
|
+
* added between the test and this helper (module loader facades, async
|
|
59
|
+
* context wrappers) do not change the result.
|
|
60
|
+
*/
|
|
16
61
|
function getFunctionName() {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
const line = stack?.[2] ?? "";
|
|
20
|
-
const match = line.match(/at (\w+)/);
|
|
21
|
-
return match?.[1] ?? "unknown";
|
|
62
|
+
const caller = captureCallSites().find(isTestCallSite);
|
|
63
|
+
return caller?.getFunctionName() ?? UNKNOWN_FUNCTION_NAME;
|
|
22
64
|
}
|
|
23
65
|
async function request(functionName, uri, method, payload, queryParams) {
|
|
24
66
|
return await fetch(`${constants_1.URL_BASE}/${functionName}/${uri}?${new URLSearchParams(queryParams).toString()}`, {
|
package/dist/tests/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/tests/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/tests/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const node_async_hooks_1 = require("node:async_hooks");
|
|
4
|
+
const chai_1 = require("chai");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
const WRAPPER_DEPTHS = [1, 2, 5, 20];
|
|
7
|
+
describe("Test utils", () => {
|
|
8
|
+
it("returns the name of the calling function", () => returnsTheCallerName());
|
|
9
|
+
it("skips frames added outside the tests folder", () => skipsFramesAddedOutsideTheTestsFolder());
|
|
10
|
+
});
|
|
11
|
+
function returnsTheCallerName() {
|
|
12
|
+
(0, chai_1.expect)((0, utils_1.getFunctionName)()).to.equal("returnsTheCallerName");
|
|
13
|
+
}
|
|
14
|
+
function nameSeenThroughAsyncContexts(depth) {
|
|
15
|
+
const storage = new node_async_hooks_1.AsyncLocalStorage();
|
|
16
|
+
const run = storage.run.bind(storage);
|
|
17
|
+
const nestedRuns = Array.from({ length: depth - 1 }, (_, store) => [
|
|
18
|
+
run,
|
|
19
|
+
store,
|
|
20
|
+
]).flat();
|
|
21
|
+
return run(depth, ...nestedRuns, utils_1.getFunctionName);
|
|
22
|
+
}
|
|
23
|
+
function skipsFramesAddedOutsideTheTestsFolder() {
|
|
24
|
+
for (const depth of WRAPPER_DEPTHS) {
|
|
25
|
+
(0, chai_1.expect)(nameSeenThroughAsyncContexts(depth)).to.equal("nameSeenThroughAsyncContexts");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../src/tests/utils.test.ts"],"names":[],"mappings":";;AAAA,uDAAqD;AACrD,+BAA8B;AAE9B,mCAA0C;AAI1C,MAAM,cAAc,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AAErC,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAC7E,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE,CACrD,qCAAqC,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,SAAS,oBAAoB;IAC3B,IAAA,aAAM,EAAC,IAAA,uBAAe,GAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,4BAA4B,CAAC,KAAa;IACjD,MAAM,OAAO,GAAG,IAAI,oCAAiB,EAAU,CAAC;IAChD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAa,CAAC;IAClD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QACjE,GAAG;QACH,KAAK;KACN,CAAC,CAAC,IAAI,EAAE,CAAC;IACV,OAAO,GAAG,CAAC,KAAK,EAAE,GAAG,UAAU,EAAE,uBAAe,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,qCAAqC;IAC5C,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,IAAA,aAAM,EAAC,4BAA4B,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAClD,8BAA8B,CAC/B,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/docs/1.introduction.md
CHANGED
|
@@ -106,13 +106,13 @@ class UserAPI extends DataController(
|
|
|
106
106
|
|
|
107
107
|
This generates the following REST endpoints:
|
|
108
108
|
|
|
109
|
-
| Method | Endpoint
|
|
110
|
-
| ------ |
|
|
111
|
-
| GET
|
|
112
|
-
| GET
|
|
113
|
-
| POST
|
|
114
|
-
| PUT
|
|
115
|
-
| DELETE | `/users/delete?id=<id>` | Delete a user
|
|
109
|
+
| Method | Endpoint | Description |
|
|
110
|
+
| ------ | ----------------------- | -------------------------- |
|
|
111
|
+
| GET | `/users/get?id=<id>` | Retrieve a single user |
|
|
112
|
+
| GET | `/users/list?limit=10` | List users with pagination |
|
|
113
|
+
| POST | `/users/new` | Create a new user |
|
|
114
|
+
| PUT | `/users/edit?id=<id>` | Update an existing user |
|
|
115
|
+
| DELETE | `/users/delete?id=<id>` | Delete a user |
|
|
116
116
|
|
|
117
117
|
## Documentation Sections
|
|
118
118
|
|
package/docs/10.joined.md
CHANGED
|
@@ -91,13 +91,13 @@ A GET request to `/orders/get?id=order-123` returns the joined value at the top
|
|
|
91
91
|
@Joined({ table, localKey, remoteField, remoteIndex?, schema? })
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
| Option
|
|
95
|
-
|
|
|
96
|
-
| `table`
|
|
97
|
-
| `localKey`
|
|
98
|
-
| `remoteField` | `string`
|
|
99
|
-
| `remoteIndex` | `string`
|
|
100
|
-
| `schema`
|
|
94
|
+
| Option | Type | Required | Default | Description |
|
|
95
|
+
| ------------- | -------------------------- | -------- | ----------------- | -------------------------------------------------------------------------------------------------- |
|
|
96
|
+
| `table` | `Class<Table>` or `string` | Yes | - | The remote table class or registered table name string |
|
|
97
|
+
| `localKey` | `string` | Yes | - | The field on the local row holding the value matched against the remote table |
|
|
98
|
+
| `remoteField` | `string` | Yes | - | The remote field whose value is flattened onto the row |
|
|
99
|
+
| `remoteIndex` | `string` | No | `"_id"` | The index on the remote table to match `localKey` against |
|
|
100
|
+
| `schema` | `string` | No | Controller schema | Name of the schema the remote table is registered in, when it differs from the controller's schema |
|
|
101
101
|
|
|
102
102
|
## Sorting and Filtering
|
|
103
103
|
|
|
@@ -145,12 +145,12 @@ When a table class is passed, its schema is inferred from its `@RegisterTable` m
|
|
|
145
145
|
|
|
146
146
|
## Joined vs. Foreign
|
|
147
147
|
|
|
148
|
-
| Aspect
|
|
149
|
-
|
|
|
150
|
-
| Result shape
|
|
151
|
-
| Access
|
|
152
|
-
| Sort / filter
|
|
153
|
-
| Multiple references | One remote field per decorator
|
|
148
|
+
| Aspect | `@Joined` | `@Foreign` |
|
|
149
|
+
| ------------------- | -------------------------------------------- | --------------------------------------------------------------------- |
|
|
150
|
+
| Result shape | A single scalar value flattened onto the row | The full referenced record (or plucked subset) nested under the field |
|
|
151
|
+
| Access | Read-only (enforced) | Configurable via `@Access` |
|
|
152
|
+
| Sort / filter | Native (join applied before sort/filter) | Not natively sortable/filterable on remote fields |
|
|
153
|
+
| Multiple references | One remote field per decorator | Single or array (`multi`) references |
|
|
154
154
|
|
|
155
155
|
## Next Steps
|
|
156
156
|
|
package/docs/11.computed.md
CHANGED
|
@@ -54,11 +54,7 @@ class GroupAPI extends DataController(
|
|
|
54
54
|
// Aggregate: number of devices referencing this group, computed in DB
|
|
55
55
|
@Listable()
|
|
56
56
|
@Computed(
|
|
57
|
-
(row, db) =>
|
|
58
|
-
db
|
|
59
|
-
.table("devices")
|
|
60
|
-
.getAll(row.key("_id"), "group_id")
|
|
61
|
-
.count(),
|
|
57
|
+
(row, db) => db.table("devices").getAll(row.key("_id"), "group_id").count(),
|
|
62
58
|
{ default: 0 },
|
|
63
59
|
)
|
|
64
60
|
@Sortable()
|
|
@@ -88,10 +84,10 @@ A GET request to `/groups/get?id=group-123` returns the computed values at the t
|
|
|
88
84
|
@Computed(expr, options?)
|
|
89
85
|
```
|
|
90
86
|
|
|
91
|
-
| Parameter
|
|
92
|
-
|
|
|
93
|
-
| `expr`
|
|
94
|
-
| `options.default` | `unknown`
|
|
87
|
+
| Parameter | Type | Required | Description |
|
|
88
|
+
| ----------------- | ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
89
|
+
| `expr` | `(row, db) => expression` | Yes | Expression receiving the row proxy and the schema instance; returns a `ValueProxy` expression or a subquery (`Datum`) |
|
|
90
|
+
| `options.default` | `unknown` | No | Fallback merged over the computed value when the expression yields `null` |
|
|
95
91
|
|
|
96
92
|
### The `default` option
|
|
97
93
|
|
|
@@ -134,12 +130,12 @@ declare devices_count: number;
|
|
|
134
130
|
|
|
135
131
|
## Computed vs. Joined
|
|
136
132
|
|
|
137
|
-
| Aspect
|
|
138
|
-
|
|
|
139
|
-
| Source
|
|
140
|
-
| Typical use
|
|
141
|
-
| Access
|
|
142
|
-
| Sort / filter | Native, lazily injected only where needed
|
|
133
|
+
| Aspect | `@Computed` | `@Joined` |
|
|
134
|
+
| ------------- | --------------------------------------------------------------- | ------------------------------------------------------------ |
|
|
135
|
+
| Source | Arbitrary expression: row-local computation or per-row subquery | One scalar field from another table matched by a foreign key |
|
|
136
|
+
| Typical use | Aggregates (`count`, `sum`), derived values | Flattening a referenced record's field |
|
|
137
|
+
| Access | Read-only (enforced) | Read-only (enforced) |
|
|
138
|
+
| Sort / filter | Native, lazily injected only where needed | Native, always applied before sort/filter |
|
|
143
139
|
|
|
144
140
|
`@Joined` remains the simpler choice for the 1:1 flattening case; `@Computed` generalizes the same merge mechanism to arbitrary expressions.
|
|
145
141
|
|
|
@@ -81,11 +81,11 @@ DataController(
|
|
|
81
81
|
)
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
| Parameter
|
|
85
|
-
|
|
|
84
|
+
| Parameter | Description |
|
|
85
|
+
| ------------ | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
86
86
|
| `tableClass` | The database table class decorated with `@RegisterTable`. The controller validates that this table exists in the database schema. |
|
|
87
|
-
| `routes`
|
|
88
|
-
| `base`
|
|
87
|
+
| `routes` | An object mapping endpoint names to route callbacks. Use `DefaultRoutes.All` for standard CRUD or pass a custom subset. |
|
|
88
|
+
| `base` | The controller base, typically created with `Controller("/path")`, which sets the URL prefix for all endpoints. |
|
|
89
89
|
|
|
90
90
|
## Required Components
|
|
91
91
|
|
package/docs/3.routes.md
CHANGED
|
@@ -12,13 +12,13 @@ The `DefaultRoutes` namespace provides five built-in routes covering standard CR
|
|
|
12
12
|
import { DefaultRoutes } from "@antelopejs/interface-data-api";
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
| Route
|
|
16
|
-
|
|
|
17
|
-
| Get
|
|
18
|
-
| List
|
|
19
|
-
| New
|
|
20
|
-
| Edit
|
|
21
|
-
| Delete | `DefaultRoutes.Delete` | DELETE
|
|
15
|
+
| Route | Object | HTTP Method | Endpoint Pattern |
|
|
16
|
+
| ------ | ---------------------- | ----------- | -------------------------- |
|
|
17
|
+
| Get | `DefaultRoutes.Get` | GET | `/resource/get?id=<id>` |
|
|
18
|
+
| List | `DefaultRoutes.List` | GET | `/resource/list` |
|
|
19
|
+
| New | `DefaultRoutes.New` | POST | `/resource/new` |
|
|
20
|
+
| Edit | `DefaultRoutes.Edit` | PUT | `/resource/edit?id=<id>` |
|
|
21
|
+
| Delete | `DefaultRoutes.Delete` | DELETE | `/resource/delete?id=<id>` |
|
|
22
22
|
|
|
23
23
|
Use `DefaultRoutes.All` to include all five routes at once.
|
|
24
24
|
|
|
@@ -62,9 +62,9 @@ Retrieves a single record by its identifier.
|
|
|
62
62
|
|
|
63
63
|
**Query Parameters:**
|
|
64
64
|
|
|
65
|
-
| Parameter | Required | Description
|
|
66
|
-
| --------- | -------- |
|
|
67
|
-
| `id`
|
|
65
|
+
| Parameter | Required | Description |
|
|
66
|
+
| --------- | -------- | ----------------- |
|
|
67
|
+
| `id` | Yes | Record identifier |
|
|
68
68
|
|
|
69
69
|
**Example:**
|
|
70
70
|
|
|
@@ -90,12 +90,12 @@ Retrieves multiple records with pagination, sorting, and filtering support.
|
|
|
90
90
|
|
|
91
91
|
**Query Parameters:**
|
|
92
92
|
|
|
93
|
-
| Parameter
|
|
94
|
-
|
|
|
95
|
-
| `limit`
|
|
96
|
-
| `offset`
|
|
97
|
-
| `sortKey`
|
|
98
|
-
| `sortDirection` | No
|
|
93
|
+
| Parameter | Required | Default | Description |
|
|
94
|
+
| --------------- | -------- | ------- | --------------------------------------------- |
|
|
95
|
+
| `limit` | No | `10` | Maximum number of records to return |
|
|
96
|
+
| `offset` | No | `0` | Number of records to skip |
|
|
97
|
+
| `sortKey` | No | - | Field to sort by (must be marked `@Sortable`) |
|
|
98
|
+
| `sortDirection` | No | `asc` | Sort direction: `asc` or `desc` |
|
|
99
99
|
|
|
100
100
|
**Example:**
|
|
101
101
|
|
|
@@ -154,9 +154,9 @@ Updates an existing record by its identifier.
|
|
|
154
154
|
|
|
155
155
|
**Query Parameters:**
|
|
156
156
|
|
|
157
|
-
| Parameter | Required | Description
|
|
158
|
-
| --------- | -------- |
|
|
159
|
-
| `id`
|
|
157
|
+
| Parameter | Required | Description |
|
|
158
|
+
| --------- | -------- | ----------------- |
|
|
159
|
+
| `id` | Yes | Record identifier |
|
|
160
160
|
|
|
161
161
|
**Body:** JSON object with fields to update.
|
|
162
162
|
|
|
@@ -188,9 +188,9 @@ Deletes one or more records by their identifiers.
|
|
|
188
188
|
|
|
189
189
|
**Query Parameters:**
|
|
190
190
|
|
|
191
|
-
| Parameter | Required | Description
|
|
192
|
-
| --------- | -------- |
|
|
193
|
-
| `id`
|
|
191
|
+
| Parameter | Required | Description |
|
|
192
|
+
| --------- | -------- | -------------------------------------------------------------------------------------- |
|
|
193
|
+
| `id` | Yes | Record identifier(s). Pass multiple `id` parameters to delete several records at once. |
|
|
194
194
|
|
|
195
195
|
**Example:**
|
|
196
196
|
|
|
@@ -212,11 +212,11 @@ The `DefaultRoutes.WithOptions` function customizes route behavior by overriding
|
|
|
212
212
|
DefaultRoutes.WithOptions(callback, options?, endpoint?)
|
|
213
213
|
```
|
|
214
214
|
|
|
215
|
-
| Parameter
|
|
216
|
-
|
|
|
217
|
-
| `callback` | The route callback to customize (e.g., `DefaultRoutes.Edit`).
|
|
218
|
-
| `options`
|
|
219
|
-
| `endpoint` | An optional custom endpoint path. Defaults to the route key name.
|
|
215
|
+
| Parameter | Description |
|
|
216
|
+
| ---------- | ------------------------------------------------------------------------------------ |
|
|
217
|
+
| `callback` | The route callback to customize (e.g., `DefaultRoutes.Edit`). |
|
|
218
|
+
| `options` | An object with option overrides. These values take precedence over query parameters. |
|
|
219
|
+
| `endpoint` | An optional custom endpoint path. Defaults to the route key name. |
|
|
220
220
|
|
|
221
221
|
### Example
|
|
222
222
|
|
|
@@ -239,32 +239,32 @@ class UserAPI extends DataController(User, routes, Controller("/users")) {
|
|
|
239
239
|
|
|
240
240
|
**Get:**
|
|
241
241
|
|
|
242
|
-
| Option
|
|
243
|
-
|
|
|
244
|
-
| `index`
|
|
245
|
-
| `noForeign` | `string` | Skip foreign key resolution
|
|
242
|
+
| Option | Type | Description |
|
|
243
|
+
| ----------- | -------- | ------------------------------------------------ |
|
|
244
|
+
| `index` | `string` | Use a secondary index instead of the primary key |
|
|
245
|
+
| `noForeign` | `string` | Skip foreign key resolution |
|
|
246
246
|
|
|
247
247
|
**List:**
|
|
248
248
|
|
|
249
|
-
| Option
|
|
250
|
-
|
|
|
251
|
-
| `maxPage`
|
|
252
|
-
| `noForeign` | `boolean` | Skip foreign key resolution
|
|
253
|
-
| `noPluck`
|
|
254
|
-
| `pluckMode` | `string`
|
|
249
|
+
| Option | Type | Description |
|
|
250
|
+
| ----------- | --------- | ------------------------------------------------------ |
|
|
251
|
+
| `maxPage` | `number` | Maximum allowed value for `limit` (caps the page size) |
|
|
252
|
+
| `noForeign` | `boolean` | Skip foreign key resolution |
|
|
253
|
+
| `noPluck` | `boolean` | Return all database fields instead of plucked fields |
|
|
254
|
+
| `pluckMode` | `string` | Select a named pluck mode (see `@Listable`) |
|
|
255
255
|
|
|
256
256
|
**New:**
|
|
257
257
|
|
|
258
|
-
| Option
|
|
259
|
-
|
|
|
258
|
+
| Option | Type | Description |
|
|
259
|
+
| ------------- | -------- | ------------------------------- |
|
|
260
260
|
| `noMandatory` | `string` | Skip mandatory field validation |
|
|
261
261
|
|
|
262
262
|
**Edit:**
|
|
263
263
|
|
|
264
|
-
| Option
|
|
265
|
-
|
|
|
266
|
-
| `index`
|
|
267
|
-
| `noMandatory` | `string` | Skip mandatory field validation
|
|
264
|
+
| Option | Type | Description |
|
|
265
|
+
| ------------- | -------- | ------------------------------------------------ |
|
|
266
|
+
| `index` | `string` | Use a secondary index instead of the primary key |
|
|
267
|
+
| `noMandatory` | `string` | Skip mandatory field validation |
|
|
268
268
|
|
|
269
269
|
## Custom Routes
|
|
270
270
|
|
|
@@ -307,11 +307,11 @@ The `args` array contains parameter decorators that extract values from the requ
|
|
|
307
307
|
|
|
308
308
|
Default routes return standard HTTP error responses:
|
|
309
309
|
|
|
310
|
-
| Status
|
|
311
|
-
|
|
|
312
|
-
| `400 Bad Request`
|
|
313
|
-
| `404 Not Found`
|
|
314
|
-
| `500 Internal Server Error` | Database operation fails
|
|
310
|
+
| Status | Condition |
|
|
311
|
+
| --------------------------- | ---------------------------------------------------------------- |
|
|
312
|
+
| `400 Bad Request` | Validation fails, missing required fields, or invalid parameters |
|
|
313
|
+
| `404 Not Found` | Record does not exist |
|
|
314
|
+
| `500 Internal Server Error` | Database operation fails |
|
|
315
315
|
|
|
316
316
|
Error messages are returned as plain text in the response body.
|
|
317
317
|
|
package/docs/4.access-rights.md
CHANGED
|
@@ -12,11 +12,11 @@ The `AccessMode` enum defines three permission levels:
|
|
|
12
12
|
import { Access, AccessMode } from "@antelopejs/interface-data-api/metadata";
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
| Mode
|
|
16
|
-
|
|
|
17
|
-
| `AccessMode.ReadOnly`
|
|
18
|
-
| `AccessMode.WriteOnly` | `2`
|
|
19
|
-
| `AccessMode.ReadWrite` | `3`
|
|
15
|
+
| Mode | Value | Description |
|
|
16
|
+
| ---------------------- | ----- | ----------------------------------------------------------------------------- |
|
|
17
|
+
| `AccessMode.ReadOnly` | `1` | Field appears in GET and LIST responses but is ignored in POST and PUT bodies |
|
|
18
|
+
| `AccessMode.WriteOnly` | `2` | Field is accepted in POST and PUT bodies but never appears in responses |
|
|
19
|
+
| `AccessMode.ReadWrite` | `3` | Field is both readable and writable |
|
|
20
20
|
|
|
21
21
|
## Basic Usage
|
|
22
22
|
|
package/docs/6.listable.md
CHANGED
|
@@ -140,10 +140,10 @@ List responses include pagination metadata. The response structure is:
|
|
|
140
140
|
|
|
141
141
|
### Query Parameters
|
|
142
142
|
|
|
143
|
-
| Parameter | Default | Description
|
|
144
|
-
| --------- | ------- |
|
|
145
|
-
| `limit`
|
|
146
|
-
| `offset`
|
|
143
|
+
| Parameter | Default | Description |
|
|
144
|
+
| --------- | ------- | ----------------------------------- |
|
|
145
|
+
| `limit` | `10` | Maximum number of records to return |
|
|
146
|
+
| `offset` | `0` | Number of records to skip |
|
|
147
147
|
|
|
148
148
|
### Example
|
|
149
149
|
|
|
@@ -214,9 +214,9 @@ class UserAPI extends DataController(
|
|
|
214
214
|
|
|
215
215
|
### Sort Query Parameters
|
|
216
216
|
|
|
217
|
-
| Parameter
|
|
218
|
-
|
|
|
219
|
-
| `sortKey`
|
|
217
|
+
| Parameter | Description |
|
|
218
|
+
| --------------- | ------------------------------------------------------------------ |
|
|
219
|
+
| `sortKey` | The field name to sort by. Must be decorated with `@Sortable`. |
|
|
220
220
|
| `sortDirection` | `"asc"` (ascending) or `"desc"` (descending). Defaults to `"asc"`. |
|
|
221
221
|
|
|
222
222
|
### The `noIndex` Option
|
package/docs/7.foreign-keys.md
CHANGED
|
@@ -90,13 +90,13 @@ A GET request to `/orders/get?id=order-123` returns the full user object instead
|
|
|
90
90
|
@Foreign(table, index?, multi?, pluck?, schema?)
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
| Parameter | Type
|
|
94
|
-
| --------- |
|
|
95
|
-
| `table`
|
|
96
|
-
| `index`
|
|
97
|
-
| `multi`
|
|
98
|
-
| `pluck`
|
|
99
|
-
| `schema`
|
|
93
|
+
| Parameter | Type | Required | Default | Description |
|
|
94
|
+
| --------- | -------------------------- | -------- | ----------------- | -------------------------------------------------------------------------------------------------- |
|
|
95
|
+
| `table` | `Class<Table>` or `string` | Yes | - | The target table class or table name string |
|
|
96
|
+
| `index` | `string` | No | `"_id"` | The index on the target table to match against |
|
|
97
|
+
| `multi` | `boolean` | No | `false` | Set to `true` when the field holds an array of foreign keys |
|
|
98
|
+
| `pluck` | `string[]` | No | All fields | List of fields to include from the referenced record |
|
|
99
|
+
| `schema` | `string` | No | Controller schema | Name of the schema the target table is registered in, when it differs from the controller's schema |
|
|
100
100
|
|
|
101
101
|
## Table Reference Methods
|
|
102
102
|
|
package/docs/8.filters.md
CHANGED
|
@@ -52,14 +52,14 @@ When no operator is specified, `eq` (equal) is used by default.
|
|
|
52
52
|
|
|
53
53
|
### Comparison Operators
|
|
54
54
|
|
|
55
|
-
| Operator | Description
|
|
56
|
-
| -------- |
|
|
57
|
-
| `eq`
|
|
58
|
-
| `ne`
|
|
59
|
-
| `gt`
|
|
60
|
-
| `ge`
|
|
61
|
-
| `lt`
|
|
62
|
-
| `le`
|
|
55
|
+
| Operator | Description |
|
|
56
|
+
| -------- | ------------------------ |
|
|
57
|
+
| `eq` | Equal to (default) |
|
|
58
|
+
| `ne` | Not equal to |
|
|
59
|
+
| `gt` | Greater than |
|
|
60
|
+
| `ge` | Greater than or equal to |
|
|
61
|
+
| `lt` | Less than |
|
|
62
|
+
| `le` | Less than or equal to |
|
|
63
63
|
|
|
64
64
|
### Examples
|
|
65
65
|
|
|
@@ -98,14 +98,14 @@ type FilterFunction<T, U> = (
|
|
|
98
98
|
) => ValueProxyOrValue<boolean>;
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
| Parameter | Description
|
|
102
|
-
| --------- |
|
|
103
|
-
| `context` | The request context, extended with `this` referencing the controller instance
|
|
104
|
-
| `proxy`
|
|
105
|
-
| `key`
|
|
106
|
-
| `value`
|
|
107
|
-
| `mode`
|
|
108
|
-
| `row`
|
|
101
|
+
| Parameter | Description |
|
|
102
|
+
| --------- | -------------------------------------------------------------------------------------------------------------- |
|
|
103
|
+
| `context` | The request context, extended with `this` referencing the controller instance |
|
|
104
|
+
| `proxy` | A `ValueProxy` representing the field value with modifier transformations applied (e.g., decrypted, localized) |
|
|
105
|
+
| `key` | The field name being filtered |
|
|
106
|
+
| `value` | The filter value from the query parameter |
|
|
107
|
+
| `mode` | The comparison operator from the query parameter |
|
|
108
|
+
| `row` | The full database row as a `ValueProxy` |
|
|
109
109
|
|
|
110
110
|
### Example: Pattern Matching Filter
|
|
111
111
|
|
package/docs/9.modifiers.md
CHANGED
|
@@ -20,8 +20,8 @@ import { ModifierKey } from "@antelopejs/interface-data-api/metadata";
|
|
|
20
20
|
@ModifierKey(modifierClass: typeof ContainerModifier<any>)
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
| Parameter
|
|
24
|
-
|
|
|
23
|
+
| Parameter | Description |
|
|
24
|
+
| --------------- | ----------------------------------------------------------------------------- |
|
|
25
25
|
| `modifierClass` | The modifier class that requires a runtime key (e.g., `LocalizationModifier`) |
|
|
26
26
|
|
|
27
27
|
### Example: Localized Content
|