@jskit-ai/kernel 0.1.244 → 0.1.246
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/client/appConfig.js +2 -1
- package/client/asyncModuleRecovery.js +2 -4
- package/client/index.d.ts +18 -76
- package/client/index.js +7 -2
- package/client/logging.js +8 -2
- package/client/moduleBootstrap.js +41 -33
- package/client/moduleBootstrap.test.js +35 -0
- package/client/shellBootstrap.js +38 -10
- package/client/shellBootstrap.test.js +85 -6
- package/client/shellRouting.js +16 -61
- package/client/shellRouting.test.js +30 -1
- package/client/vite/clientBootstrapPlugin.js +0 -6
- package/client/vite/clientBootstrapPlugin.test.js +2 -3
- package/internal/node/installedPackages.js +14 -58
- package/package.json +2 -4
- package/server/actions/actionCatalogue.js +13 -34
- package/{shared → server}/actions/actionContributorHelpers.js +0 -5
- package/{shared → server}/actions/actionDefinitions.js +24 -131
- package/{shared → server}/actions/actionDefinitions.test.js +75 -21
- package/server/actions/actionEvents.js +97 -2
- package/server/actions/actionEvents.test.js +79 -0
- package/{shared → server}/actions/executionContext.js +3 -13
- package/server/actions/idempotency.js +24 -0
- package/server/actions/pipeline.js +87 -0
- package/{shared → server}/actions/policies.js +20 -33
- package/{shared → server}/actions/policies.test.js +6 -6
- package/{shared → server}/actions/registry.js +3 -22
- package/{shared → server}/actions/registry.test.js +70 -32
- package/server/actions/requestMeta.js +17 -0
- package/server/http/capabilityHttpRuntime.js +1 -1
- package/server/http/capabilityHttpRuntime.test.js +56 -0
- package/server/http/errorHandling.js +291 -0
- package/server/{runtime/fastifyBootstrap.test.js → http/errorHandling.test.js} +72 -120
- package/server/http/lib/routeRegistration.js +36 -150
- package/server/http/lib/routeTransport.js +2 -0
- package/server/http/lib/routeValidator.js +5 -47
- package/server/http/lib/routeValidator.test.js +15 -17
- package/server/http/lib/router.js +10 -94
- package/server/platform/providerRuntime/capabilityProviderLoader.js +2 -1
- package/server/platform/providerRuntime/helpers.js +1 -34
- package/server/runtime/integers.js +1 -5
- package/server/runtime/serviceAuthorization.js +4 -9
- package/server/support/appConfig.js +2 -1
- package/server/support/appConfigFiles.js +1 -38
- package/server/support/appConfigFiles.test.js +3 -39
- package/server/support/index.js +1 -20
- package/shared/capabilities/defineProvider.js +1 -1
- package/shared/capabilities/index.js +1 -1
- package/shared/index.js +1 -1
- package/shared/support/index.js +1 -4
- package/shared/support/mobileConfig.js +99 -0
- package/shared/support/mobileConfig.test.js +113 -0
- package/shared/support/normalize.js +0 -108
- package/shared/support/normalize.test.js +0 -134
- package/shared/{actions/actionContributorHelpers.test.js → support/permissions.test.js} +1 -1
- package/shared/support/returnToPath.js +16 -20
- package/shared/support/returnToPath.test.js +5 -33
- package/shared/support/shellLayoutTargets.js +2 -140
- package/shared/support/shellLayoutTargets.test.js +1 -110
- package/shared/support/sorting.js +1 -9
- package/shared/surface/apiPaths.js +1 -82
- package/shared/surface/paths.js +38 -171
- package/shared/surface/registry.js +2 -1
- package/shared/surface/runtime.js +18 -109
- package/shared/surface/runtime.test.js +57 -0
- package/shared/validators/index.js +1 -4
- package/shared/validators/jsonRestSchemaSupport.js +0 -9
- package/shared/validators/recordIdParamsValidator.js +0 -6
- package/shared/validators/schemaDefinitions.js +4 -30
- package/shared/validators/schemaPayloadValidation.js +2 -6
- package/test/barrelExposure.test.js +5 -8
- package/test/exportsContract.test.js +1 -3
- package/client/mobileLaunchRouting.js +0 -231
- package/client/mobileLaunchRouting.test.js +0 -230
- package/server/http/lib/controller.js +0 -183
- package/server/http/lib/controller.test.js +0 -143
- package/server/http/lib/index.js +0 -5
- package/server/runtime/canonicalJson.js +0 -74
- package/server/runtime/entityChangeEvents.js +0 -307
- package/server/runtime/entityChangeEvents.test.js +0 -274
- package/server/runtime/fastifyBootstrap.js +0 -553
- package/server/runtime/moduleConfig.js +0 -223
- package/server/runtime/moduleConfig.test.js +0 -165
- package/server/runtime/pagination.js +0 -13
- package/server/runtime/realtimeNormalization.js +0 -21
- package/server/runtime/routeUtils.js +0 -20
- package/server/runtime/securityAudit.js +0 -269
- package/server/runtime/securityAudit.test.js +0 -41
- package/server/support/pageTargets.js +0 -772
- package/server/support/pageTargets.test.js +0 -659
- package/server/support/shellOutlets.js +0 -576
- package/server/support/shellOutlets.test.js +0 -336
- package/server/surface/index.js +0 -18
- package/shared/actions/audit.js +0 -7
- package/shared/actions/idempotency.js +0 -62
- package/shared/actions/observability.js +0 -10
- package/shared/actions/pipeline.js +0 -309
- package/shared/actions/requestMeta.js +0 -36
- package/shared/actions/textNormalization.js +0 -3
- package/shared/actions/withActionDefaults.js +0 -34
- /package/{shared → server}/actions/executionContext.test.js +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import test from "node:test";
|
|
3
3
|
import { createSurfaceRuntime } from "../shared/surface/runtime.js";
|
|
4
|
-
import { buildSurfaceAwareRoutes } from "./shellRouting.js";
|
|
4
|
+
import { DEFAULT_GUARD_EVALUATOR_KEY, buildSurfaceAwareRoutes, createShellBeforeEachGuard } from "./shellRouting.js";
|
|
5
5
|
|
|
6
6
|
test("buildSurfaceAwareRoutes keeps declared route paths and filters by surface mode", () => {
|
|
7
7
|
const surfaceRuntime = createSurfaceRuntime({
|
|
@@ -111,3 +111,32 @@ test("buildSurfaceAwareRoutes preserves parent path when nested descendants are
|
|
|
111
111
|
const routePaths = routes.map((route) => route.path);
|
|
112
112
|
assert.equal(routePaths.includes("/account"), true);
|
|
113
113
|
});
|
|
114
|
+
|
|
115
|
+
test("createShellBeforeEachGuard reads surfaces and the default root from the surface runtime", () => {
|
|
116
|
+
const surfaceRuntime = createSurfaceRuntime({
|
|
117
|
+
defaultSurfaceId: "app",
|
|
118
|
+
surfaces: {
|
|
119
|
+
home: { pagesRoot: "" },
|
|
120
|
+
app: { pagesRoot: "w/app", requiresAuth: true }
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
const evaluations = [];
|
|
124
|
+
const previousEvaluator = globalThis[DEFAULT_GUARD_EVALUATOR_KEY];
|
|
125
|
+
globalThis[DEFAULT_GUARD_EVALUATOR_KEY] = ({ guard, context }) => {
|
|
126
|
+
evaluations.push({ policy: guard.policy, pathname: context.location.pathname });
|
|
127
|
+
return { allow: false, redirectTo: "/auth/login" };
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const guard = createShellBeforeEachGuard({ surfaceRuntime, webRootAllowed: "no" });
|
|
132
|
+
assert.equal(guard({ path: "/", fullPath: "/?next=1#top", hash: "#top" }), "/w/app?next=1#top");
|
|
133
|
+
assert.equal(guard({ path: "/about", fullPath: "/about", matched: [] }), true);
|
|
134
|
+
assert.equal(guard({ path: "/w/app/projects", fullPath: "/w/app/projects", matched: [] }), "/auth/login");
|
|
135
|
+
assert.deepEqual(evaluations, [{ policy: "authenticated", pathname: "/w/app/projects" }]);
|
|
136
|
+
|
|
137
|
+
const openGuard = createShellBeforeEachGuard({ surfaceRuntime });
|
|
138
|
+
assert.equal(openGuard({ path: "/", fullPath: "/", matched: [] }), true);
|
|
139
|
+
} finally {
|
|
140
|
+
globalThis[DEFAULT_GUARD_EVALUATOR_KEY] = previousEvaluator;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
@@ -234,11 +234,6 @@ function resolveInstalledViteProxyEntries(installedPackages = [], { proxyTarget
|
|
|
234
234
|
return proxyEntries;
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
async function resolveInstalledClientPackageIds(options) {
|
|
238
|
-
const modules = await resolveInstalledClientModules(options);
|
|
239
|
-
return Object.freeze(modules.map((entry) => entry.packageId));
|
|
240
|
-
}
|
|
241
|
-
|
|
242
237
|
async function resolveLocalScopePackageIds({ appRoot }) {
|
|
243
238
|
const appPackageJson = await readJsonFile(path.resolve(appRoot, "package.json"), {});
|
|
244
239
|
return Object.freeze(
|
|
@@ -487,7 +482,6 @@ export {
|
|
|
487
482
|
resolveCanonicalLocalPackageId,
|
|
488
483
|
resolveLocalPackageForSpecifier,
|
|
489
484
|
resolveLocalPackageSources,
|
|
490
|
-
resolveInstalledClientPackageIds,
|
|
491
485
|
resolveLocalScopePackageIds,
|
|
492
486
|
resolveInstalledClientModules,
|
|
493
487
|
resolveInstalledViteProxyEntries,
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
resolveClientOptimizeIncludeSpecifiers,
|
|
15
15
|
resolveClientOptimizeExcludeSpecifiers,
|
|
16
16
|
resolveLocalScopePackageIds,
|
|
17
|
-
resolveInstalledClientPackageIds,
|
|
18
17
|
resolveInstalledClientModules,
|
|
19
18
|
resolveInstalledViteProxyEntries
|
|
20
19
|
} from "./clientBootstrapPlugin.js";
|
|
@@ -260,7 +259,7 @@ test("resolveClientOptimizeIncludeSpecifiers omits excluded package clients", ()
|
|
|
260
259
|
assert.deepEqual(include, ["@c/pkg/client"]);
|
|
261
260
|
});
|
|
262
261
|
|
|
263
|
-
test("
|
|
262
|
+
test("resolveInstalledClientModules returns only installed packages with a client export", async () => {
|
|
264
263
|
const tempRoot = await mkdtemp(path.join(os.tmpdir(), "jskit-client-bootstrap-"));
|
|
265
264
|
const appRoot = tempRoot;
|
|
266
265
|
|
|
@@ -289,7 +288,7 @@ test("resolveInstalledClientPackageIds returns only installed packages with a cl
|
|
|
289
288
|
}
|
|
290
289
|
});
|
|
291
290
|
|
|
292
|
-
const packageIds = await
|
|
291
|
+
const packageIds = (await resolveInstalledClientModules({ appRoot })).map((entry) => entry.packageId);
|
|
293
292
|
|
|
294
293
|
assert.deepEqual(packageIds, ["@example/has-client"]);
|
|
295
294
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { realpath } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { normalizeObject } from "../../shared/support/normalize.js";
|
|
4
4
|
import { sortStrings } from "../../shared/support/sorting.js";
|
|
5
|
-
import { fileExists } from "./fileSystem.js";
|
|
5
|
+
import { fileExists, readJsonFile } from "./fileSystem.js";
|
|
6
6
|
|
|
7
7
|
const ROOT_DEPENDENCY_SECTIONS = Object.freeze([
|
|
8
8
|
"dependencies",
|
|
@@ -18,14 +18,6 @@ const JSKIT_PACKAGE_CONFIG_KEYS = Object.freeze([
|
|
|
18
18
|
"vite"
|
|
19
19
|
]);
|
|
20
20
|
|
|
21
|
-
async function readJsonFile(filePath, fallback = {}) {
|
|
22
|
-
try {
|
|
23
|
-
return JSON.parse(await readFile(filePath, "utf8"));
|
|
24
|
-
} catch {
|
|
25
|
-
return fallback;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
21
|
function collectRootDependencySpecifiers(packageJson = {}) {
|
|
30
22
|
const specifiers = new Map();
|
|
31
23
|
for (const sectionName of ROOT_DEPENDENCY_SECTIONS) {
|
|
@@ -42,7 +34,7 @@ function collectRootDependencySpecifiers(packageJson = {}) {
|
|
|
42
34
|
|
|
43
35
|
function collectPackageDependencyIds(packageJson = {}) {
|
|
44
36
|
const dependencyIds = new Set();
|
|
45
|
-
for (const sectionName of
|
|
37
|
+
for (const sectionName of ROOT_DEPENDENCY_SECTIONS) {
|
|
46
38
|
for (const packageId of Object.keys(normalizeObject(packageJson?.[sectionName]))) {
|
|
47
39
|
const normalizedPackageId = String(packageId || "").trim();
|
|
48
40
|
if (normalizedPackageId) {
|
|
@@ -175,56 +167,27 @@ async function discoverInstalledPackages({ appRoot } = {}) {
|
|
|
175
167
|
const rootPackageJson = await readJsonFile(path.resolve(normalizedAppRoot, "package.json"), {});
|
|
176
168
|
const directSpecifiers = collectRootDependencySpecifiers(rootPackageJson);
|
|
177
169
|
const directPackageIds = new Set(directSpecifiers.keys());
|
|
178
|
-
const runtimeRootPackageIds = new Set(
|
|
179
|
-
["dependencies", "optionalDependencies", "peerDependencies"]
|
|
180
|
-
.flatMap((sectionName) => Object.keys(normalizeObject(rootPackageJson?.[sectionName])))
|
|
181
|
-
);
|
|
182
170
|
const visited = new Set();
|
|
171
|
+
// Breadth-first walk of the dependency graph; the queue stays ordered by packageId.
|
|
183
172
|
const queue = [];
|
|
184
|
-
const queued = new
|
|
173
|
+
const queued = new Set();
|
|
185
174
|
const packages = [];
|
|
186
175
|
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
if (left.traverseDependencies !== right.traverseDependencies) {
|
|
190
|
-
return left.traverseDependencies ? -1 : 1;
|
|
191
|
-
}
|
|
192
|
-
return left.packageId.localeCompare(right.packageId);
|
|
193
|
-
});
|
|
194
|
-
};
|
|
195
|
-
const enqueue = ({ packageId, parentPackageRoot = "", traverseDependencies = false }) => {
|
|
196
|
-
const normalizedPackageId = String(packageId || "").trim();
|
|
197
|
-
if (!normalizedPackageId || visited.has(normalizedPackageId)) {
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
const existing = queued.get(normalizedPackageId);
|
|
201
|
-
if (existing) {
|
|
202
|
-
if (traverseDependencies && !existing.traverseDependencies) {
|
|
203
|
-
existing.traverseDependencies = true;
|
|
204
|
-
existing.parentPackageRoot = parentPackageRoot || existing.parentPackageRoot;
|
|
205
|
-
sortQueue();
|
|
206
|
-
}
|
|
176
|
+
const enqueue = ({ packageId, parentPackageRoot = "" }) => {
|
|
177
|
+
if (!packageId || visited.has(packageId) || queued.has(packageId)) {
|
|
207
178
|
return;
|
|
208
179
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
traverseDependencies: Boolean(traverseDependencies)
|
|
213
|
-
};
|
|
214
|
-
queue.push(entry);
|
|
215
|
-
queued.set(normalizedPackageId, entry);
|
|
216
|
-
sortQueue();
|
|
180
|
+
queue.push({ packageId, parentPackageRoot });
|
|
181
|
+
queued.add(packageId);
|
|
182
|
+
queue.sort((left, right) => left.packageId.localeCompare(right.packageId));
|
|
217
183
|
};
|
|
218
184
|
|
|
219
185
|
for (const packageId of sortStrings([...directPackageIds])) {
|
|
220
|
-
enqueue({
|
|
221
|
-
packageId,
|
|
222
|
-
traverseDependencies: runtimeRootPackageIds.has(packageId)
|
|
223
|
-
});
|
|
186
|
+
enqueue({ packageId });
|
|
224
187
|
}
|
|
225
188
|
|
|
226
189
|
while (queue.length > 0) {
|
|
227
|
-
const { packageId, parentPackageRoot
|
|
190
|
+
const { packageId, parentPackageRoot } = queue.shift();
|
|
228
191
|
queued.delete(packageId);
|
|
229
192
|
if (!packageId || visited.has(packageId)) {
|
|
230
193
|
continue;
|
|
@@ -252,15 +215,8 @@ async function discoverInstalledPackages({ appRoot } = {}) {
|
|
|
252
215
|
}
|
|
253
216
|
|
|
254
217
|
const dependencyIds = collectPackageDependencyIds(packageJson);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const normalizedDependencyId = String(dependencyId || "").trim();
|
|
258
|
-
enqueue({
|
|
259
|
-
packageId: normalizedDependencyId,
|
|
260
|
-
parentPackageRoot: roots.packageRoot,
|
|
261
|
-
traverseDependencies: true
|
|
262
|
-
});
|
|
263
|
-
}
|
|
218
|
+
for (const dependencyId of dependencyIds) {
|
|
219
|
+
enqueue({ packageId: dependencyId, parentPackageRoot: roots.packageRoot });
|
|
264
220
|
}
|
|
265
221
|
|
|
266
222
|
const packageMetadata = createPackageMetadata(packageJson);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/kernel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.246",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"json-rest-schema": "^1.0.17"
|
|
@@ -25,18 +25,16 @@
|
|
|
25
25
|
"./client/moduleBootstrap": "./client/moduleBootstrap.js",
|
|
26
26
|
"./client/vite": "./client/vite/index.js",
|
|
27
27
|
"./server/actions": "./server/actions/index.js",
|
|
28
|
+
"./server/actions/actionContributorHelpers": "./server/actions/actionContributorHelpers.js",
|
|
28
29
|
"./server/features": "./server/features/index.js",
|
|
29
30
|
"./server/http": "./server/http/index.js",
|
|
30
31
|
"./server/platform": "./server/platform/index.js",
|
|
31
32
|
"./server/runtime": "./server/runtime/index.js",
|
|
32
|
-
"./server/runtime/entityChangeEvents": "./server/runtime/entityChangeEvents.js",
|
|
33
33
|
"./server/runtime/errors": "./server/runtime/errors.js",
|
|
34
34
|
"./server/runtime/requestUrl": "./server/runtime/requestUrl.js",
|
|
35
35
|
"./server/support": "./server/support/index.js",
|
|
36
36
|
"./shared": "./shared/index.js",
|
|
37
37
|
"./shared/capabilities": "./shared/capabilities/index.js",
|
|
38
|
-
"./shared/actions/actionContributorHelpers": "./shared/actions/actionContributorHelpers.js",
|
|
39
|
-
"./shared/actions/textNormalization": "./shared/actions/textNormalization.js",
|
|
40
38
|
"./shared/validators": "./shared/validators/index.js",
|
|
41
39
|
"./shared/validators/inputNormalization": "./shared/validators/inputNormalization.js",
|
|
42
40
|
"./shared/support": "./shared/support/index.js",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createActionRegistry } from "
|
|
1
|
+
import { createActionRegistry } from "./registry.js";
|
|
2
2
|
import { isRecord } from "../../shared/support/normalize.js";
|
|
3
3
|
|
|
4
4
|
function normalizeRegistration(value) {
|
|
@@ -9,21 +9,12 @@ function normalizeRegistration(value) {
|
|
|
9
9
|
return value;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
function createActionCatalogue({
|
|
13
|
-
idempotencyAdapter,
|
|
14
|
-
auditAdapter,
|
|
15
|
-
observabilityAdapter,
|
|
16
|
-
events,
|
|
17
|
-
logger = null
|
|
18
|
-
} = {}) {
|
|
12
|
+
function createActionCatalogue({ events, logger = null } = {}) {
|
|
19
13
|
const contributors = [];
|
|
20
14
|
const contextContributors = [];
|
|
21
15
|
const contextContributorIds = new Set();
|
|
22
16
|
let registry = createActionRegistry({
|
|
23
17
|
contributors,
|
|
24
|
-
idempotencyAdapter,
|
|
25
|
-
auditAdapter,
|
|
26
|
-
observabilityAdapter,
|
|
27
18
|
events,
|
|
28
19
|
logger
|
|
29
20
|
});
|
|
@@ -36,9 +27,6 @@ function createActionCatalogue({
|
|
|
36
27
|
const nextContributors = [...contributors, normalizeRegistration(contributor)];
|
|
37
28
|
const nextRegistry = createActionRegistry({
|
|
38
29
|
contributors: nextContributors,
|
|
39
|
-
idempotencyAdapter,
|
|
40
|
-
auditAdapter,
|
|
41
|
-
observabilityAdapter,
|
|
42
30
|
events,
|
|
43
31
|
logger
|
|
44
32
|
});
|
|
@@ -104,40 +92,31 @@ function createActionCatalogue({
|
|
|
104
92
|
return Object.freeze(enriched);
|
|
105
93
|
}
|
|
106
94
|
|
|
107
|
-
async function
|
|
95
|
+
async function run(method, payload = {}) {
|
|
108
96
|
const source = payload && typeof payload === "object" ? payload : {};
|
|
109
97
|
const input = source.input && typeof source.input === "object" ? source.input : {};
|
|
98
|
+
const version = source.version == null ? null : source.version;
|
|
110
99
|
const context = await buildExecutionContext({
|
|
111
100
|
actionId: source.actionId,
|
|
112
|
-
version
|
|
101
|
+
version,
|
|
113
102
|
input,
|
|
114
103
|
context: source.context
|
|
115
104
|
});
|
|
116
|
-
return currentRegistry()
|
|
105
|
+
return currentRegistry()[method]({
|
|
117
106
|
actionId: source.actionId,
|
|
118
|
-
version
|
|
107
|
+
version,
|
|
119
108
|
input,
|
|
120
109
|
context,
|
|
121
110
|
deps: isRecord(source.deps) ? source.deps : {}
|
|
122
111
|
});
|
|
123
112
|
}
|
|
124
113
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
input,
|
|
132
|
-
context: source.context
|
|
133
|
-
});
|
|
134
|
-
return currentRegistry().executeStream({
|
|
135
|
-
actionId: source.actionId,
|
|
136
|
-
version: source.version == null ? null : source.version,
|
|
137
|
-
input,
|
|
138
|
-
context,
|
|
139
|
-
deps: isRecord(source.deps) ? source.deps : {}
|
|
140
|
-
});
|
|
114
|
+
function execute(payload) {
|
|
115
|
+
return run("execute", payload);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function executeStream(payload) {
|
|
119
|
+
return run("executeStream", payload);
|
|
141
120
|
}
|
|
142
121
|
|
|
143
122
|
function listDefinitions() {
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { createSchema } from "json-rest-schema";
|
|
2
|
-
import { normalizeObject, normalizePositiveInteger as toPositiveInteger } from "../support/normalize.js";
|
|
3
|
-
import { hasPermission } from "../support/permissions.js";
|
|
4
2
|
|
|
5
3
|
function requireServiceMethod(service, methodName, contributorId, { serviceLabel } = {}) {
|
|
6
4
|
if (!service || typeof service[methodName] !== "function") {
|
|
@@ -19,10 +17,7 @@ const emptyInputValidator = Object.freeze({
|
|
|
19
17
|
});
|
|
20
18
|
|
|
21
19
|
export {
|
|
22
|
-
normalizeObject,
|
|
23
|
-
toPositiveInteger,
|
|
24
20
|
requireServiceMethod,
|
|
25
21
|
resolveRequest,
|
|
26
|
-
hasPermission,
|
|
27
22
|
emptyInputValidator
|
|
28
23
|
};
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
} from "
|
|
4
|
-
import {
|
|
5
|
-
import { normalizePermissionList } from "../support/permissions.js";
|
|
6
|
-
import { normalizeText } from "./textNormalization.js";
|
|
1
|
+
import { normalizeSingleSchemaDefinition } from "../../shared/validators/index.js";
|
|
2
|
+
import { isRecord as isPlainObject, normalizePositiveInteger, normalizeText } from "../../shared/support/normalize.js";
|
|
3
|
+
import { normalizePermissionList } from "../../shared/support/permissions.js";
|
|
4
|
+
import { ARCHITECTURE_ID_PATTERN } from "../../shared/capabilities/defineProvider.js";
|
|
7
5
|
|
|
8
6
|
const ACTION_KINDS = Object.freeze(["query", "command", "stream"]);
|
|
9
7
|
const ACTION_IDEMPOTENCY_POLICIES = Object.freeze(["none", "optional", "required", "domain_native"]);
|
|
@@ -12,7 +10,6 @@ const ACTION_PERMISSION_REQUIRE_MODES = Object.freeze(["none", "authenticated",
|
|
|
12
10
|
const ACTION_KIND_SET = new Set(ACTION_KINDS);
|
|
13
11
|
const ACTION_IDEMPOTENCY_SET = new Set(ACTION_IDEMPOTENCY_POLICIES);
|
|
14
12
|
const ACTION_PERMISSION_REQUIRE_SET = new Set(ACTION_PERMISSION_REQUIRE_MODES);
|
|
15
|
-
const ACTION_DOMAIN_PATTERN = /^[a-z][a-z0-9_.-]*$/;
|
|
16
13
|
|
|
17
14
|
class ActionRuntimeError extends Error {
|
|
18
15
|
constructor(status, message, options = {}) {
|
|
@@ -38,10 +35,10 @@ function normalizeActionDomain(value, { context = "domain", errorCode = "ACTION_
|
|
|
38
35
|
code: errorCode
|
|
39
36
|
});
|
|
40
37
|
}
|
|
41
|
-
if (!
|
|
38
|
+
if (!ARCHITECTURE_ID_PATTERN.test(domain)) {
|
|
42
39
|
throw createActionRuntimeError(
|
|
43
40
|
500,
|
|
44
|
-
`${context} must match ${
|
|
41
|
+
`${context} must match ${ARCHITECTURE_ID_PATTERN.toString()} (lowercase letters, digits, _, -, .).`,
|
|
45
42
|
{
|
|
46
43
|
code: errorCode
|
|
47
44
|
}
|
|
@@ -51,23 +48,13 @@ function normalizeActionDomain(value, { context = "domain", errorCode = "ACTION_
|
|
|
51
48
|
return domain;
|
|
52
49
|
}
|
|
53
50
|
|
|
54
|
-
function normalizeStringArray(value,
|
|
51
|
+
function normalizeStringArray(value, fieldName) {
|
|
55
52
|
const source = Array.isArray(value) ? value : [];
|
|
56
53
|
const normalized = Array.from(
|
|
57
|
-
new Set(
|
|
58
|
-
source
|
|
59
|
-
.map((entry) => normalizeText(entry).toLowerCase())
|
|
60
|
-
.filter(Boolean)
|
|
61
|
-
.filter((entry) => {
|
|
62
|
-
if (!(allowedSet instanceof Set)) {
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
return allowedSet.has(entry);
|
|
66
|
-
})
|
|
67
|
-
)
|
|
54
|
+
new Set(source.map((entry) => normalizeText(entry).toLowerCase()).filter(Boolean))
|
|
68
55
|
);
|
|
69
56
|
|
|
70
|
-
if (
|
|
57
|
+
if (normalized.length < 1) {
|
|
71
58
|
throw createActionRuntimeError(500, `Action definition ${fieldName} must include at least one value.`, {
|
|
72
59
|
code: "ACTION_DEFINITION_INVALID"
|
|
73
60
|
});
|
|
@@ -76,7 +63,7 @@ function normalizeStringArray(value, { fieldName, allowedSet, allowEmpty = false
|
|
|
76
63
|
return normalized;
|
|
77
64
|
}
|
|
78
65
|
|
|
79
|
-
function
|
|
66
|
+
function normalizeActionSchema(value, fieldName, { required = false, defaultMode = "" } = {}) {
|
|
80
67
|
if (value == null) {
|
|
81
68
|
if (!required) {
|
|
82
69
|
return null;
|
|
@@ -87,6 +74,12 @@ function normalizeSingleActionSchema(value, fieldName, { required = false, defau
|
|
|
87
74
|
});
|
|
88
75
|
}
|
|
89
76
|
|
|
77
|
+
if (Array.isArray(value)) {
|
|
78
|
+
throw createActionRuntimeError(500, `Action definition ${fieldName} must be a single schema definition.`, {
|
|
79
|
+
code: "ACTION_DEFINITION_INVALID"
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
90
83
|
if (!isPlainObject(value)) {
|
|
91
84
|
throw createActionRuntimeError(500, `Action definition ${fieldName} must be a json-rest-schema schema definition.`, {
|
|
92
85
|
code: "ACTION_DEFINITION_INVALID"
|
|
@@ -105,52 +98,6 @@ function normalizeSingleActionSchema(value, fieldName, { required = false, defau
|
|
|
105
98
|
}
|
|
106
99
|
}
|
|
107
100
|
|
|
108
|
-
function normalizeActionInputDefinition(value, fieldName, { required = false } = {}) {
|
|
109
|
-
if (value == null) {
|
|
110
|
-
if (!required) {
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
throw createActionRuntimeError(500, `Action definition ${fieldName} is required.`, {
|
|
115
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (Array.isArray(value)) {
|
|
120
|
-
throw createActionRuntimeError(500, `Action definition ${fieldName} must be a single schema definition.`, {
|
|
121
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return normalizeSingleActionSchema(value, fieldName, {
|
|
126
|
-
required,
|
|
127
|
-
defaultMode: "patch"
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function normalizeActionOutputDefinition(value, fieldName, { required = false } = {}) {
|
|
132
|
-
if (value == null) {
|
|
133
|
-
if (!required) {
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
throw createActionRuntimeError(500, `Action definition ${fieldName} is required.`, {
|
|
138
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (Array.isArray(value)) {
|
|
143
|
-
throw createActionRuntimeError(500, `Action definition ${fieldName} must be a single schema definition.`, {
|
|
144
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return normalizeSingleActionSchema(value, fieldName, {
|
|
149
|
-
required,
|
|
150
|
-
defaultMode: "replace"
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
101
|
function normalizeActionPermission(permission, actionId) {
|
|
155
102
|
if (permission == null) {
|
|
156
103
|
return Object.freeze({
|
|
@@ -190,42 +137,6 @@ function normalizeActionPermission(permission, actionId) {
|
|
|
190
137
|
});
|
|
191
138
|
}
|
|
192
139
|
|
|
193
|
-
function normalizeAuditConfig(audit, { actionId }) {
|
|
194
|
-
const source = audit && typeof audit === "object" ? audit : {};
|
|
195
|
-
const actionName = normalizeText(source.actionName || actionId);
|
|
196
|
-
const metadataBuilder = source.metadataBuilder;
|
|
197
|
-
const piiTags = normalizeStringArray(source.piiTags, {
|
|
198
|
-
fieldName: "audit.piiTags",
|
|
199
|
-
allowEmpty: true
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
if (metadataBuilder != null && typeof metadataBuilder !== "function") {
|
|
203
|
-
throw createActionRuntimeError(500, "Action definition audit.metadataBuilder must be a function when provided.", {
|
|
204
|
-
code: "ACTION_DEFINITION_INVALID"
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return Object.freeze({
|
|
209
|
-
actionName,
|
|
210
|
-
metadataBuilder: typeof metadataBuilder === "function" ? metadataBuilder : null,
|
|
211
|
-
piiTags
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
function normalizeObservabilityConfig(observability) {
|
|
216
|
-
const source = observability && typeof observability === "object" ? observability : {};
|
|
217
|
-
const metricTags = normalizeStringArray(source.metricTags, {
|
|
218
|
-
fieldName: "observability.metricTags",
|
|
219
|
-
allowEmpty: true
|
|
220
|
-
});
|
|
221
|
-
const sampleRate = Number(source.sampleRate);
|
|
222
|
-
|
|
223
|
-
return Object.freeze({
|
|
224
|
-
metricTags,
|
|
225
|
-
sampleRate: Number.isFinite(sampleRate) && sampleRate >= 0 && sampleRate <= 1 ? sampleRate : null
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
|
|
229
140
|
function normalizeActionExtensions(value) {
|
|
230
141
|
if (value == null) {
|
|
231
142
|
return Object.freeze({});
|
|
@@ -286,13 +197,8 @@ function normalizeActionDefinition(definition, { contributorId = "", contributor
|
|
|
286
197
|
});
|
|
287
198
|
}
|
|
288
199
|
|
|
289
|
-
const channels = normalizeStringArray(source.channels,
|
|
290
|
-
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
const surfaces = normalizeStringArray(source.surfaces, {
|
|
294
|
-
fieldName: "surfaces"
|
|
295
|
-
});
|
|
200
|
+
const channels = normalizeStringArray(source.channels, "channels");
|
|
201
|
+
const surfaces = normalizeStringArray(source.surfaces, "surfaces");
|
|
296
202
|
|
|
297
203
|
const idempotency = normalizeText(source.idempotency || "none").toLowerCase();
|
|
298
204
|
if (!ACTION_IDEMPOTENCY_SET.has(idempotency)) {
|
|
@@ -318,18 +224,15 @@ function normalizeActionDefinition(definition, { contributorId = "", contributor
|
|
|
318
224
|
kind,
|
|
319
225
|
channels,
|
|
320
226
|
surfaces,
|
|
321
|
-
input:
|
|
322
|
-
required: true
|
|
227
|
+
input: normalizeActionSchema(source.input, "input", {
|
|
228
|
+
required: true,
|
|
229
|
+
defaultMode: "patch"
|
|
323
230
|
}),
|
|
324
|
-
output:
|
|
325
|
-
|
|
231
|
+
output: normalizeActionSchema(source.output, "output", {
|
|
232
|
+
defaultMode: "replace"
|
|
326
233
|
}),
|
|
327
234
|
idempotency,
|
|
328
235
|
permission: normalizeActionPermission(source.permission, id),
|
|
329
|
-
audit: normalizeAuditConfig(source.audit, {
|
|
330
|
-
actionId: id
|
|
331
|
-
}),
|
|
332
|
-
observability: normalizeObservabilityConfig(source.observability),
|
|
333
236
|
extensions: normalizeActionExtensions(source.extensions),
|
|
334
237
|
events: normalizeActionEvents(source.events, id),
|
|
335
238
|
execute: source.execute,
|
|
@@ -371,15 +274,7 @@ function createActionVersionKey(actionId, version) {
|
|
|
371
274
|
}
|
|
372
275
|
|
|
373
276
|
const __testables = {
|
|
374
|
-
|
|
375
|
-
isPlainObject,
|
|
376
|
-
normalizeStringArray,
|
|
377
|
-
normalizeSingleActionSchema,
|
|
378
|
-
normalizeActionInputDefinition,
|
|
379
|
-
normalizeActionOutputDefinition,
|
|
380
|
-
normalizeActionPermission,
|
|
381
|
-
normalizeAuditConfig,
|
|
382
|
-
normalizeObservabilityConfig,
|
|
277
|
+
normalizeActionSchema,
|
|
383
278
|
normalizeActionExtensions
|
|
384
279
|
};
|
|
385
280
|
|
|
@@ -388,8 +283,6 @@ export {
|
|
|
388
283
|
createActionRuntimeError,
|
|
389
284
|
normalizeActionDefinition,
|
|
390
285
|
normalizeActionContributor,
|
|
391
|
-
normalizeActionDomain,
|
|
392
286
|
createActionVersionKey,
|
|
393
|
-
isPlainObject,
|
|
394
287
|
__testables
|
|
395
288
|
};
|