@jskit-ai/json-rest-api-core 0.1.63 → 0.1.65
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/package.descriptor.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export default Object.freeze({
|
|
2
2
|
packageVersion: 1,
|
|
3
3
|
packageId: "@jskit-ai/json-rest-api-core",
|
|
4
|
-
version: "0.1.
|
|
4
|
+
version: "0.1.65",
|
|
5
5
|
kind: "runtime",
|
|
6
|
-
description: "Shared internal json-rest-api host runtime
|
|
6
|
+
description: "Shared internal json-rest-api host runtime with autofilter, query-projection, and row-policy support.",
|
|
7
7
|
dependsOn: [
|
|
8
8
|
"@jskit-ai/database-runtime",
|
|
9
9
|
"@jskit-ai/kernel"
|
|
@@ -34,7 +34,7 @@ export default Object.freeze({
|
|
|
34
34
|
surfaces: [
|
|
35
35
|
{
|
|
36
36
|
subpath: "./server",
|
|
37
|
-
summary: "Exports the shared internal json-rest-api host token and
|
|
37
|
+
summary: "Exports the shared internal json-rest-api host token and resource registration helpers, including server-only row policies."
|
|
38
38
|
}
|
|
39
39
|
],
|
|
40
40
|
containerTokens: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/json-rest-api-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.65",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"hooked-api": "1.x.x",
|
|
13
|
-
"json-rest-api": "1.
|
|
14
|
-
"@jskit-ai/kernel": "0.1.
|
|
13
|
+
"json-rest-api": "^1.0.25",
|
|
14
|
+
"@jskit-ai/kernel": "0.1.121"
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { Api } from "hooked-api";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AutoFilterPlugin,
|
|
4
|
+
QueryProjectionsPlugin,
|
|
5
|
+
RestApiKnexPlugin,
|
|
6
|
+
RestApiPlugin,
|
|
7
|
+
RowPolicyPlugin
|
|
8
|
+
} from "json-rest-api";
|
|
3
9
|
import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
|
|
4
10
|
import { resolveCrudResourceScopeName } from "@jskit-ai/kernel/shared/support/crudLookup";
|
|
5
11
|
|
|
@@ -464,6 +470,7 @@ function createJsonRestResourceScopeOptions(
|
|
|
464
470
|
{
|
|
465
471
|
writeSerializers = {},
|
|
466
472
|
normalizeId = null,
|
|
473
|
+
rowPolicy = undefined,
|
|
467
474
|
searchSchema = null,
|
|
468
475
|
queryFields = null
|
|
469
476
|
} = {}
|
|
@@ -499,6 +506,9 @@ function createJsonRestResourceScopeOptions(
|
|
|
499
506
|
if (typeof normalizeId === "function") {
|
|
500
507
|
scopeOptions.normalizeId = normalizeId;
|
|
501
508
|
}
|
|
509
|
+
if (rowPolicy !== undefined) {
|
|
510
|
+
scopeOptions.rowPolicy = rowPolicy;
|
|
511
|
+
}
|
|
502
512
|
|
|
503
513
|
return scopeOptions;
|
|
504
514
|
}
|
|
@@ -591,6 +601,7 @@ async function createJsonRestApiHost({ knex }) {
|
|
|
591
601
|
|
|
592
602
|
await api.use(QueryProjectionsPlugin);
|
|
593
603
|
await api.use(RestApiKnexPlugin, { knex });
|
|
604
|
+
await api.use(RowPolicyPlugin);
|
|
594
605
|
await api.use(AutoFilterPlugin, {
|
|
595
606
|
resolvers: {
|
|
596
607
|
workspace: ({ context }) => resolveWorkspaceScopeValue(context),
|
|
@@ -26,6 +26,7 @@ test("package exports include explicit server jsonRestApiHost entrypoint only",
|
|
|
26
26
|
const exportsMap = packageJson && typeof packageJson === "object" ? packageJson.exports : {};
|
|
27
27
|
assert.equal(exportsMap["./server/jsonRestApiHost"], "./src/server/jsonRestApiHost.js");
|
|
28
28
|
assert.equal(exportsMap["./server"], undefined);
|
|
29
|
+
assert.equal(packageJson.dependencies?.["json-rest-api"], "^1.0.25");
|
|
29
30
|
});
|
|
30
31
|
|
|
31
32
|
test("server jsonRestApiHost entrypoint no longer exports host-side JSON:API simplification helpers", async () => {
|
|
@@ -157,6 +158,46 @@ test("createJsonRestApiHost configures the internal json-rest logger at error le
|
|
|
157
158
|
assert.equal(api.options.logging.level, "error");
|
|
158
159
|
});
|
|
159
160
|
|
|
161
|
+
test("createJsonRestApiHost installs row policies before resources are added", async () => {
|
|
162
|
+
const fakeKnex = Object.assign(() => {}, {
|
|
163
|
+
client: {
|
|
164
|
+
config: {
|
|
165
|
+
client: "sqlite3"
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
async raw() {
|
|
169
|
+
return [
|
|
170
|
+
{
|
|
171
|
+
version: "3.35.5"
|
|
172
|
+
}
|
|
173
|
+
];
|
|
174
|
+
},
|
|
175
|
+
transaction() {}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const api = await createJsonRestApiHost({ knex: fakeKnex });
|
|
179
|
+
const rowPolicy = () => false;
|
|
180
|
+
const scopeOptions = createJsonRestResourceScopeOptions({
|
|
181
|
+
tableName: "private_contacts",
|
|
182
|
+
schema: {
|
|
183
|
+
id: { type: "id", primary: true }
|
|
184
|
+
}
|
|
185
|
+
}, {
|
|
186
|
+
rowPolicy
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
await api.addResource("privateContacts", scopeOptions);
|
|
190
|
+
|
|
191
|
+
assert.deepEqual(api.rowPolicies.getConfig(), {
|
|
192
|
+
policies: []
|
|
193
|
+
});
|
|
194
|
+
assert.deepEqual(api.rowPolicies.getScopeConfig("privateContacts"), {
|
|
195
|
+
policy: "<inline>",
|
|
196
|
+
source: "inline"
|
|
197
|
+
});
|
|
198
|
+
assert.equal(scopeOptions.rowPolicy, rowPolicy);
|
|
199
|
+
});
|
|
200
|
+
|
|
160
201
|
test("shared query/document helpers build json-rest-api request shapes", () => {
|
|
161
202
|
assert.deepEqual(
|
|
162
203
|
buildJsonRestQueryParams("contacts", {
|
|
@@ -284,6 +325,7 @@ test("buildJsonRestQueryParams preserves structured filter values", () => {
|
|
|
284
325
|
test("createJsonRestResourceScopeOptions clones canonical resource metadata and resolves symbolic write serializers", () => {
|
|
285
326
|
const serializer = (value) => value;
|
|
286
327
|
const normalizeId = (value) => String(value || "").trim() || null;
|
|
328
|
+
const rowPolicy = () => false;
|
|
287
329
|
const source = Object.freeze({
|
|
288
330
|
namespace: "contacts",
|
|
289
331
|
tableName: "contacts",
|
|
@@ -353,6 +395,7 @@ test("createJsonRestResourceScopeOptions clones canonical resource metadata and
|
|
|
353
395
|
|
|
354
396
|
const result = createJsonRestResourceScopeOptions(source, {
|
|
355
397
|
normalizeId,
|
|
398
|
+
rowPolicy,
|
|
356
399
|
writeSerializers: {
|
|
357
400
|
"datetime-utc": serializer
|
|
358
401
|
}
|
|
@@ -368,6 +411,7 @@ test("createJsonRestResourceScopeOptions clones canonical resource metadata and
|
|
|
368
411
|
assert.equal(result.schema.bookingSteps.virtual, true);
|
|
369
412
|
assert.equal(result.schema.pets.virtual, true);
|
|
370
413
|
assert.equal(result.normalizeId, normalizeId);
|
|
414
|
+
assert.equal(result.rowPolicy, rowPolicy);
|
|
371
415
|
assert.equal(result.schema.name.maxLength, 190);
|
|
372
416
|
assert.equal(result.schema.name.operations.output.required, true);
|
|
373
417
|
assert.equal(result.operations.view.method, "GET");
|