@jskit-ai/kernel 0.1.4
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 +24 -0
- package/_testable/index.js +4 -0
- package/client/appConfig.js +33 -0
- package/client/componentInteraction.js +51 -0
- package/client/componentInteraction.test.js +111 -0
- package/client/descriptorSections.js +75 -0
- package/client/index.d.ts +70 -0
- package/client/index.js +3 -0
- package/client/logging.js +38 -0
- package/client/moduleBootstrap.js +670 -0
- package/client/moduleBootstrap.test.js +403 -0
- package/client/shellBootstrap.js +233 -0
- package/client/shellBootstrap.test.js +185 -0
- package/client/shellRouting.js +321 -0
- package/client/shellRouting.test.js +113 -0
- package/client/vite/clientBootstrapPlugin.js +259 -0
- package/client/vite/clientBootstrapPlugin.test.js +563 -0
- package/client/vite/index.js +3 -0
- package/internal/node/fileSystem.js +21 -0
- package/internal/node/installedPackageDescriptor.js +104 -0
- package/package.json +43 -0
- package/server/actions/ActionRuntimeServiceProvider.js +309 -0
- package/server/actions/ActionRuntimeServiceProvider.test.js +551 -0
- package/server/actions/index.js +8 -0
- package/server/container/ContainerCoreServiceProvider.js +27 -0
- package/server/container/index.js +10 -0
- package/server/exportPolicy.test.js +68 -0
- package/server/http/HttpFastifyServiceProvider.js +25 -0
- package/server/http/_testable/index.js +2 -0
- package/server/http/index.js +1 -0
- package/server/http/lib/controller.js +183 -0
- package/server/http/lib/controller.test.js +143 -0
- package/server/http/lib/errors.js +12 -0
- package/server/http/lib/httpRuntime.js +82 -0
- package/server/http/lib/index.js +18 -0
- package/server/http/lib/kernel.js +15 -0
- package/server/http/lib/kernel.test.js +880 -0
- package/server/http/lib/middlewareRuntime.js +149 -0
- package/server/http/lib/requestActionExecutor.js +258 -0
- package/server/http/lib/requestScope.js +59 -0
- package/server/http/lib/routeRegistration.js +165 -0
- package/server/http/lib/routeSupport.js +45 -0
- package/server/http/lib/routeValidator.js +469 -0
- package/server/http/lib/routeValidator.test.js +474 -0
- package/server/http/lib/router.js +206 -0
- package/server/kernel/KernelCoreServiceProvider.js +27 -0
- package/server/kernel/index.js +10 -0
- package/server/platform/PlatformServerRuntimeServiceProvider.js +30 -0
- package/server/platform/index.js +5 -0
- package/server/platform/providerRuntime/descriptorCatalog.js +170 -0
- package/server/platform/providerRuntime/helpers.js +45 -0
- package/server/platform/providerRuntime/lockfile.js +27 -0
- package/server/platform/providerRuntime/providerLoader.js +283 -0
- package/server/platform/providerRuntime.js +142 -0
- package/server/platform/providerRuntime.test.js +217 -0
- package/server/platform/runtime.js +40 -0
- package/server/platform/surfaceRuntime.js +150 -0
- package/server/platform/surfaceRuntime.test.js +136 -0
- package/server/registries/actionSurfaceSourceRegistry.js +150 -0
- package/server/registries/bootstrapPayloadContributorRegistry.js +41 -0
- package/server/registries/domainEventListenerRegistry.js +61 -0
- package/server/registries/index.js +36 -0
- package/server/registries/primitives.js +63 -0
- package/server/registries/routeVisibilityResolverRegistry.js +87 -0
- package/server/registries/serviceRegistrationRegistry.js +431 -0
- package/server/runtime/ServerRuntimeCoreServiceProvider.js +65 -0
- package/server/runtime/ServerRuntimeCoreServiceProvider.test.js +53 -0
- package/server/runtime/apiRoutePolicyParity.test.js +109 -0
- package/server/runtime/apiRouteRegistration.js +65 -0
- package/server/runtime/bootBootstrapRoutes.js +46 -0
- package/server/runtime/bootBootstrapRoutes.test.js +79 -0
- package/server/runtime/bootstrapContributors.test.js +114 -0
- package/server/runtime/canonicalJson.js +74 -0
- package/server/runtime/composition.js +142 -0
- package/server/runtime/domainEvents.test.js +114 -0
- package/server/runtime/domainRules.js +50 -0
- package/server/runtime/domainRules.test.js +87 -0
- package/server/runtime/entityChangeEvents.js +182 -0
- package/server/runtime/entityChangeEvents.test.js +211 -0
- package/server/runtime/errors.js +68 -0
- package/server/runtime/errors.test.js +73 -0
- package/server/runtime/fastifyBootstrap.js +372 -0
- package/server/runtime/fastifyBootstrap.test.js +194 -0
- package/server/runtime/index.js +6 -0
- package/server/runtime/integers.js +13 -0
- package/server/runtime/moduleConfig.js +269 -0
- package/server/runtime/moduleConfig.test.js +141 -0
- package/server/runtime/pagination.js +13 -0
- package/server/runtime/realtimeNormalization.js +21 -0
- package/server/runtime/requestUrl.js +38 -0
- package/server/runtime/routeUtils.js +20 -0
- package/server/runtime/runtimeAssembly.js +113 -0
- package/server/runtime/runtimeKernel.js +55 -0
- package/server/runtime/securityAudit.js +269 -0
- package/server/runtime/securityAudit.test.js +41 -0
- package/server/runtime/serviceAuthorization.js +113 -0
- package/server/runtime/serviceAuthorization.test.js +100 -0
- package/server/runtime/serviceRegistration.test.js +197 -0
- package/server/support/SupportCoreServiceProvider.js +25 -0
- package/server/support/appConfig.js +37 -0
- package/server/support/appConfig.test.js +94 -0
- package/server/support/defaultMissingHandler.js +7 -0
- package/server/support/index.js +2 -0
- package/server/support/routePolicyConfig.js +51 -0
- package/server/support/symlinkSafeRequire.js +78 -0
- package/server/support/symlinkSafeRequire.test.js +27 -0
- package/server/surface/SurfaceRoutingServiceProvider.js +27 -0
- package/server/surface/index.js +19 -0
- package/shared/actions/actionContributorHelpers.js +34 -0
- package/shared/actions/actionContributorHelpers.test.js +16 -0
- package/shared/actions/actionDefinitions.js +488 -0
- package/shared/actions/actionDefinitions.test.js +212 -0
- package/shared/actions/audit.js +7 -0
- package/shared/actions/executionContext.js +97 -0
- package/shared/actions/executionContext.test.js +66 -0
- package/shared/actions/idempotency.js +62 -0
- package/shared/actions/index.js +2 -0
- package/shared/actions/observability.js +10 -0
- package/shared/actions/pipeline.js +287 -0
- package/shared/actions/policies.js +342 -0
- package/shared/actions/policies.test.js +233 -0
- package/shared/actions/registry.js +187 -0
- package/shared/actions/registry.test.js +381 -0
- package/shared/actions/requestMeta.js +36 -0
- package/shared/actions/textNormalization.js +3 -0
- package/shared/actions/withActionDefaults.js +34 -0
- package/shared/index.js +2 -0
- package/shared/runtime/application.js +323 -0
- package/shared/runtime/container.js +261 -0
- package/shared/runtime/containerErrors.js +22 -0
- package/shared/runtime/index.js +18 -0
- package/shared/runtime/kernelErrors.js +20 -0
- package/shared/runtime/serviceProvider.js +13 -0
- package/shared/support/formatDateTime.js +10 -0
- package/shared/support/formatDateTime.test.js +15 -0
- package/shared/support/index.js +14 -0
- package/shared/support/linkPath.js +67 -0
- package/shared/support/linkPath.test.js +35 -0
- package/shared/support/normalize.js +116 -0
- package/shared/support/normalize.test.js +48 -0
- package/shared/support/packageDescriptor.test.js +121 -0
- package/shared/support/permissions.js +50 -0
- package/shared/support/pickOwnProperties.js +17 -0
- package/shared/support/pickOwnProperties.test.js +25 -0
- package/shared/support/policies.js +11 -0
- package/shared/support/queryPath.js +33 -0
- package/shared/support/queryPath.test.js +19 -0
- package/shared/support/queryResilience.js +34 -0
- package/shared/support/queryResilience.test.js +33 -0
- package/shared/support/returnToPath.js +153 -0
- package/shared/support/returnToPath.test.js +123 -0
- package/shared/support/sorting.js +15 -0
- package/shared/support/tokens.js +23 -0
- package/shared/support/tokens.test.js +17 -0
- package/shared/support/visibility.js +56 -0
- package/shared/support/visibility.test.js +45 -0
- package/shared/surface/apiPaths.js +84 -0
- package/shared/surface/escapeRegExp.js +5 -0
- package/shared/surface/index.js +6 -0
- package/shared/surface/paths.js +273 -0
- package/shared/surface/registry.js +135 -0
- package/shared/surface/registry.test.js +44 -0
- package/shared/surface/runtime.js +357 -0
- package/shared/surface/runtime.test.js +319 -0
- package/shared/validators/createCursorListValidator.js +42 -0
- package/shared/validators/createCursorListValidator.test.js +34 -0
- package/shared/validators/cursorPaginationQueryValidator.js +31 -0
- package/shared/validators/cursorPaginationQueryValidator.test.js +21 -0
- package/shared/validators/index.js +12 -0
- package/shared/validators/inputNormalization.js +13 -0
- package/shared/validators/mergeObjectSchemas.js +31 -0
- package/shared/validators/mergeObjectSchemas.test.js +67 -0
- package/shared/validators/mergeValidators.js +89 -0
- package/shared/validators/mergeValidators.test.js +116 -0
- package/shared/validators/nestValidator.js +53 -0
- package/shared/validators/nestValidator.test.js +60 -0
- package/shared/validators/recordIdParamsValidator.js +36 -0
- package/shared/validators/recordIdParamsValidator.test.js +20 -0
- package/shared/validators/resourceRequiredMetadata.js +41 -0
- package/shared/validators/resourceRequiredMetadata.test.js +49 -0
- package/test/barrelExposure.test.js +106 -0
- package/test/dynamicImportPolicy.test.js +89 -0
- package/test/exportsContract.test.js +168 -0
- package/test/routeInputContractGuard.test.js +78 -0
- package/test/surfaceIndependence.test.js +109 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { KERNEL_TOKENS } from "../../shared/support/tokens.js";
|
|
2
|
+
import { assertTaggableApp } from "./primitives.js";
|
|
3
|
+
|
|
4
|
+
const ACTION_SURFACE_SOURCE_REGISTRY_TOKEN = Symbol.for("jskit.runtime.actions.surfaceSourceRegistry");
|
|
5
|
+
const ACTION_SURFACE_SOURCE_NAME_PATTERN = /^[a-z][a-z0-9_.-]*$/;
|
|
6
|
+
|
|
7
|
+
function normalizeSurfaceIdValue(value) {
|
|
8
|
+
return String(value || "").trim().toLowerCase();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function normalizeSurfaceSourceName(sourceName, { context = "action surface source" } = {}) {
|
|
12
|
+
const normalizedSourceName = normalizeSurfaceIdValue(sourceName);
|
|
13
|
+
if (!ACTION_SURFACE_SOURCE_NAME_PATTERN.test(normalizedSourceName)) {
|
|
14
|
+
throw new Error(`${context} must match ${ACTION_SURFACE_SOURCE_NAME_PATTERN.toString()}.`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return normalizedSourceName;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function resolveSurfaceRuntime(scope) {
|
|
21
|
+
if (!scope || typeof scope.has !== "function" || typeof scope.make !== "function") {
|
|
22
|
+
throw new Error("Action definition materialization requires scope.has()/make().");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!scope.has(KERNEL_TOKENS.SurfaceRuntime)) {
|
|
26
|
+
throw new Error("Action definition surfacesFrom requires KERNEL_TOKENS.SurfaceRuntime.");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return scope.make(KERNEL_TOKENS.SurfaceRuntime);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resolveEnabledSurfaceIds(surfaceRuntime) {
|
|
33
|
+
return Array.isArray(surfaceRuntime?.listEnabledSurfaceIds?.()) ? surfaceRuntime.listEnabledSurfaceIds() : [];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizeSurfaceIdList(surfaceIds, { context = "action.surfacesFrom", surfaceRuntime = null } = {}) {
|
|
37
|
+
const sourceSurfaceIds = Array.isArray(surfaceIds) ? surfaceIds : [];
|
|
38
|
+
const enabledSurfaceIds = new Set(
|
|
39
|
+
resolveEnabledSurfaceIds(surfaceRuntime).map((entry) => normalizeSurfaceIdValue(entry)).filter(Boolean)
|
|
40
|
+
);
|
|
41
|
+
const seen = new Set();
|
|
42
|
+
const normalized = [];
|
|
43
|
+
|
|
44
|
+
for (const sourceSurfaceId of sourceSurfaceIds) {
|
|
45
|
+
const normalizedSurfaceId = normalizeSurfaceIdValue(sourceSurfaceId);
|
|
46
|
+
if (!normalizedSurfaceId || seen.has(normalizedSurfaceId)) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!enabledSurfaceIds.has(normalizedSurfaceId)) {
|
|
51
|
+
throw new Error(`${context} resolved non-enabled surface "${normalizedSurfaceId}".`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
seen.add(normalizedSurfaceId);
|
|
55
|
+
normalized.push(normalizedSurfaceId);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return Object.freeze(normalized);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function createActionSurfaceSourceRegistry() {
|
|
62
|
+
const sourceResolvers = new Map();
|
|
63
|
+
|
|
64
|
+
const register = (sourceName, resolver, { allowOverride = false } = {}) => {
|
|
65
|
+
const normalizedSourceName = normalizeSurfaceSourceName(sourceName);
|
|
66
|
+
if (typeof resolver !== "function") {
|
|
67
|
+
throw new Error(`action surface source "${normalizedSourceName}" resolver must be a function.`);
|
|
68
|
+
}
|
|
69
|
+
if (!allowOverride && sourceResolvers.has(normalizedSourceName)) {
|
|
70
|
+
throw new Error(`action surface source "${normalizedSourceName}" is already registered.`);
|
|
71
|
+
}
|
|
72
|
+
sourceResolvers.set(normalizedSourceName, resolver);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
register("enabled", ({ surfaceRuntime }) => resolveEnabledSurfaceIds(surfaceRuntime));
|
|
76
|
+
|
|
77
|
+
return Object.freeze({
|
|
78
|
+
register,
|
|
79
|
+
resolve(scope, sourceName, { context = "action.surfacesFrom" } = {}) {
|
|
80
|
+
const normalizedSourceName = normalizeSurfaceSourceName(sourceName, { context });
|
|
81
|
+
const resolver = sourceResolvers.get(normalizedSourceName);
|
|
82
|
+
if (typeof resolver !== "function") {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`${context} references unknown surface source "${normalizedSourceName}". Register it via app.actionSurfaceSource().`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const surfaceRuntime = resolveSurfaceRuntime(scope);
|
|
89
|
+
const resolvedSurfaceIds = resolver({
|
|
90
|
+
scope,
|
|
91
|
+
sourceName: normalizedSourceName,
|
|
92
|
+
surfaceRuntime
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return normalizeSurfaceIdList(resolvedSurfaceIds, {
|
|
96
|
+
context,
|
|
97
|
+
surfaceRuntime
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function resolveActionSurfaceSourceRegistry(scope) {
|
|
104
|
+
if (!scope || typeof scope.has !== "function" || typeof scope.make !== "function") {
|
|
105
|
+
throw new Error("Action surface source resolution requires scope.has()/make().");
|
|
106
|
+
}
|
|
107
|
+
if (!scope.has(ACTION_SURFACE_SOURCE_REGISTRY_TOKEN)) {
|
|
108
|
+
throw new Error("Action surface source registry is not registered.");
|
|
109
|
+
}
|
|
110
|
+
return scope.make(ACTION_SURFACE_SOURCE_REGISTRY_TOKEN);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function resolveActionSurfaceSourceIds(scope, sourceName, { context = "action.surfacesFrom" } = {}) {
|
|
114
|
+
const sourceRegistry = resolveActionSurfaceSourceRegistry(scope);
|
|
115
|
+
return sourceRegistry.resolve(scope, sourceName, { context });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function installActionSurfaceSourceRegistrationApi(app) {
|
|
119
|
+
if (typeof app.actionSurfaceSource === "function") {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const registerActionSurfaceSource = function registerActionSurfaceSource(sourceName, resolver) {
|
|
124
|
+
const sourceRegistry = resolveActionSurfaceSourceRegistry(this);
|
|
125
|
+
sourceRegistry.register(sourceName, resolver);
|
|
126
|
+
return this;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
Object.defineProperty(app, "actionSurfaceSource", {
|
|
130
|
+
configurable: true,
|
|
131
|
+
writable: true,
|
|
132
|
+
value: registerActionSurfaceSource
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function ensureActionSurfaceSourceRegistry(app) {
|
|
137
|
+
assertTaggableApp(app, {
|
|
138
|
+
context: "ensureActionSurfaceSourceRegistry"
|
|
139
|
+
});
|
|
140
|
+
if (typeof app.has !== "function") {
|
|
141
|
+
throw new Error("ensureActionSurfaceSourceRegistry requires app.has().");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (!app.has(ACTION_SURFACE_SOURCE_REGISTRY_TOKEN)) {
|
|
145
|
+
app.singleton(ACTION_SURFACE_SOURCE_REGISTRY_TOKEN, () => createActionSurfaceSourceRegistry());
|
|
146
|
+
}
|
|
147
|
+
installActionSurfaceSourceRegistrationApi(app);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export { ensureActionSurfaceSourceRegistry, resolveActionSurfaceSourceIds };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { normalizeObject } from "../../shared/support/normalize.js";
|
|
2
|
+
import { normalizeContributorEntry, registerTaggedSingleton, resolveTaggedEntries } from "./primitives.js";
|
|
3
|
+
|
|
4
|
+
const BOOTSTRAP_PAYLOAD_CONTRIBUTOR_TAG = Symbol.for("jskit.runtime.bootstrap.payloadContributors");
|
|
5
|
+
|
|
6
|
+
function registerBootstrapPayloadContributor(app, token, factory) {
|
|
7
|
+
registerTaggedSingleton(app, token, factory, BOOTSTRAP_PAYLOAD_CONTRIBUTOR_TAG, {
|
|
8
|
+
context: "registerBootstrapPayloadContributor"
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function resolveBootstrapPayloadContributors(scope) {
|
|
13
|
+
return resolveTaggedEntries(scope, BOOTSTRAP_PAYLOAD_CONTRIBUTOR_TAG)
|
|
14
|
+
.map((entry) => normalizeContributorEntry(entry))
|
|
15
|
+
.filter(Boolean);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function resolveBootstrapPayload(scope, context = {}) {
|
|
19
|
+
const contributors = resolveBootstrapPayloadContributors(scope);
|
|
20
|
+
let payload = {};
|
|
21
|
+
|
|
22
|
+
for (const contributor of contributors) {
|
|
23
|
+
const contribution = await contributor.contribute({
|
|
24
|
+
...normalizeObject(context),
|
|
25
|
+
payload: Object.freeze({ ...payload })
|
|
26
|
+
});
|
|
27
|
+
payload = {
|
|
28
|
+
...payload,
|
|
29
|
+
...normalizeObject(contribution)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return payload;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
BOOTSTRAP_PAYLOAD_CONTRIBUTOR_TAG,
|
|
38
|
+
registerBootstrapPayloadContributor,
|
|
39
|
+
resolveBootstrapPayloadContributors,
|
|
40
|
+
resolveBootstrapPayload
|
|
41
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { normalizeObject } from "../../shared/support/normalize.js";
|
|
2
|
+
import { registerTaggedSingleton, resolveTaggedEntries } from "./primitives.js";
|
|
3
|
+
|
|
4
|
+
const DOMAIN_EVENT_LISTENER_TAG = Symbol.for("jskit.runtime.domainEvent.listeners");
|
|
5
|
+
|
|
6
|
+
function normalizeDomainEventListener(entry) {
|
|
7
|
+
if (typeof entry === "function") {
|
|
8
|
+
return {
|
|
9
|
+
listenerId: String(entry.name || "anonymous"),
|
|
10
|
+
matches: null,
|
|
11
|
+
handle: entry
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (entry && typeof entry === "object" && typeof entry.handle === "function") {
|
|
16
|
+
return {
|
|
17
|
+
...entry,
|
|
18
|
+
listenerId: String(entry.listenerId || "anonymous"),
|
|
19
|
+
matches: typeof entry.matches === "function" ? entry.matches : null
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function registerDomainEventListener(app, token, factory) {
|
|
27
|
+
registerTaggedSingleton(app, token, factory, DOMAIN_EVENT_LISTENER_TAG, {
|
|
28
|
+
context: "registerDomainEventListener"
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resolveDomainEventListeners(scope) {
|
|
33
|
+
return resolveTaggedEntries(scope, DOMAIN_EVENT_LISTENER_TAG)
|
|
34
|
+
.map((entry) => normalizeDomainEventListener(entry))
|
|
35
|
+
.filter(Boolean);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function createDomainEvents(scope) {
|
|
39
|
+
return Object.freeze({
|
|
40
|
+
async publish(event = {}) {
|
|
41
|
+
const payload = normalizeObject(event);
|
|
42
|
+
const listeners = resolveDomainEventListeners(scope);
|
|
43
|
+
|
|
44
|
+
for (const listener of listeners) {
|
|
45
|
+
if (listener.matches && listener.matches(payload) !== true) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
await listener.handle(payload);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
DOMAIN_EVENT_LISTENER_TAG,
|
|
58
|
+
registerDomainEventListener,
|
|
59
|
+
resolveDomainEventListeners,
|
|
60
|
+
createDomainEvents
|
|
61
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export {
|
|
2
|
+
BOOTSTRAP_PAYLOAD_CONTRIBUTOR_TAG,
|
|
3
|
+
registerBootstrapPayloadContributor,
|
|
4
|
+
resolveBootstrapPayloadContributors,
|
|
5
|
+
resolveBootstrapPayload
|
|
6
|
+
} from "./bootstrapPayloadContributorRegistry.js";
|
|
7
|
+
export {
|
|
8
|
+
DOMAIN_EVENT_LISTENER_TAG,
|
|
9
|
+
registerDomainEventListener,
|
|
10
|
+
resolveDomainEventListeners,
|
|
11
|
+
createDomainEvents
|
|
12
|
+
} from "./domainEventListenerRegistry.js";
|
|
13
|
+
export {
|
|
14
|
+
SERVICE_REGISTRATION_TAG,
|
|
15
|
+
normalizeServiceRegistration,
|
|
16
|
+
materializeServiceRegistration,
|
|
17
|
+
registerServiceRegistration,
|
|
18
|
+
resolveServiceRegistrations,
|
|
19
|
+
installServiceRegistrationApi
|
|
20
|
+
} from "./serviceRegistrationRegistry.js";
|
|
21
|
+
export {
|
|
22
|
+
ROUTE_VISIBILITY_RESOLVER_TAG,
|
|
23
|
+
resolveRouteVisibilityResolvers,
|
|
24
|
+
registerRouteVisibilityResolver,
|
|
25
|
+
resolveRouteVisibilityContext
|
|
26
|
+
} from "./routeVisibilityResolverRegistry.js";
|
|
27
|
+
export {
|
|
28
|
+
ensureActionSurfaceSourceRegistry,
|
|
29
|
+
resolveActionSurfaceSourceIds
|
|
30
|
+
} from "./actionSurfaceSourceRegistry.js";
|
|
31
|
+
export {
|
|
32
|
+
normalizeNestedEntries,
|
|
33
|
+
assertTaggableApp,
|
|
34
|
+
registerTaggedSingleton,
|
|
35
|
+
resolveTaggedEntries
|
|
36
|
+
} from "./primitives.js";
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
function normalizeNestedEntries(value) {
|
|
2
|
+
const queue = Array.isArray(value) ? [...value] : [value];
|
|
3
|
+
const entries = [];
|
|
4
|
+
|
|
5
|
+
while (queue.length > 0) {
|
|
6
|
+
const entry = queue.shift();
|
|
7
|
+
if (Array.isArray(entry)) {
|
|
8
|
+
queue.push(...entry);
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
if (entry == null) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
entries.push(entry);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return entries;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function assertTaggableApp(app, { context = "registry", ErrorType = Error } = {}) {
|
|
21
|
+
if (!app || typeof app.singleton !== "function" || typeof app.tag !== "function") {
|
|
22
|
+
throw new ErrorType(`${context} requires application singleton()/tag().`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function registerTaggedSingleton(app, token, factory, tag, { context = "registry", ErrorType = Error } = {}) {
|
|
27
|
+
assertTaggableApp(app, { context, ErrorType });
|
|
28
|
+
app.singleton(token, factory);
|
|
29
|
+
app.tag(token, tag);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resolveTaggedEntries(scope, tag) {
|
|
33
|
+
if (!scope || typeof scope.resolveTag !== "function") {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
return normalizeNestedEntries(scope.resolveTag(tag));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function normalizeContributorEntry(entry) {
|
|
40
|
+
if (typeof entry === "function") {
|
|
41
|
+
return {
|
|
42
|
+
contributorId: String(entry.name || "anonymous"),
|
|
43
|
+
contribute: entry
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (entry && typeof entry === "object" && typeof entry.contribute === "function") {
|
|
48
|
+
return {
|
|
49
|
+
...entry,
|
|
50
|
+
contributorId: String(entry.contributorId || "anonymous")
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export {
|
|
58
|
+
normalizeNestedEntries,
|
|
59
|
+
assertTaggableApp,
|
|
60
|
+
registerTaggedSingleton,
|
|
61
|
+
resolveTaggedEntries,
|
|
62
|
+
normalizeContributorEntry
|
|
63
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { normalizeRouteVisibility, normalizeRouteVisibilityToken, normalizeVisibilityContext } from "../../shared/support/visibility.js";
|
|
2
|
+
import { normalizeText } from "../../shared/support/normalize.js";
|
|
3
|
+
import { ROUTE_VISIBILITY_PUBLIC } from "../../shared/support/policies.js";
|
|
4
|
+
import { RouteRegistrationError } from "../http/lib/errors.js";
|
|
5
|
+
import { registerTaggedSingleton, resolveTaggedEntries } from "./primitives.js";
|
|
6
|
+
|
|
7
|
+
const ROUTE_VISIBILITY_RESOLVER_TAG = Symbol.for("jskit.runtime.http.visibilityResolvers");
|
|
8
|
+
|
|
9
|
+
function normalizeRouteVisibilityResolver(entry) {
|
|
10
|
+
if (typeof entry === "function") {
|
|
11
|
+
return {
|
|
12
|
+
resolverId: normalizeText(entry.name) || "anonymous",
|
|
13
|
+
resolve: entry
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.resolve !== "function") {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
resolverId: normalizeText(entry.resolverId) || "anonymous",
|
|
23
|
+
resolve: entry.resolve
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function resolveRouteVisibilityResolvers(scope) {
|
|
28
|
+
return resolveTaggedEntries(scope, ROUTE_VISIBILITY_RESOLVER_TAG)
|
|
29
|
+
.map((entry) => normalizeRouteVisibilityResolver(entry))
|
|
30
|
+
.filter(Boolean);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function registerRouteVisibilityResolver(app, token, factory) {
|
|
34
|
+
registerTaggedSingleton(app, token, factory, ROUTE_VISIBILITY_RESOLVER_TAG, {
|
|
35
|
+
context: "registerRouteVisibilityResolver",
|
|
36
|
+
ErrorType: RouteRegistrationError
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function resolveRouteVisibilityContext({
|
|
41
|
+
resolutionScope = null,
|
|
42
|
+
request = null,
|
|
43
|
+
routeVisibility = ROUTE_VISIBILITY_PUBLIC,
|
|
44
|
+
context = {},
|
|
45
|
+
input = {},
|
|
46
|
+
deps = {},
|
|
47
|
+
actionId = "",
|
|
48
|
+
version = null,
|
|
49
|
+
channel = "api"
|
|
50
|
+
} = {}) {
|
|
51
|
+
const normalizedRouteVisibility = normalizeRouteVisibilityToken(routeVisibility);
|
|
52
|
+
const normalizedCoreVisibility = normalizeRouteVisibility(normalizedRouteVisibility);
|
|
53
|
+
const resolvers = resolveRouteVisibilityResolvers(resolutionScope);
|
|
54
|
+
const patch = {};
|
|
55
|
+
|
|
56
|
+
for (const resolver of resolvers) {
|
|
57
|
+
const contribution = await resolver.resolve({
|
|
58
|
+
request,
|
|
59
|
+
visibility: normalizedRouteVisibility,
|
|
60
|
+
context,
|
|
61
|
+
input,
|
|
62
|
+
deps,
|
|
63
|
+
actionId: normalizeText(actionId),
|
|
64
|
+
version: version == null ? null : version,
|
|
65
|
+
channel: normalizeText(channel).toLowerCase() || "api"
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (!contribution || typeof contribution !== "object" || Array.isArray(contribution)) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Object.assign(patch, contribution);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return normalizeVisibilityContext({
|
|
76
|
+
...patch,
|
|
77
|
+
visibility: normalizedRouteVisibility,
|
|
78
|
+
requiresActorScope: patch.requiresActorScope === true || normalizedCoreVisibility === "user"
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export {
|
|
83
|
+
ROUTE_VISIBILITY_RESOLVER_TAG,
|
|
84
|
+
resolveRouteVisibilityResolvers,
|
|
85
|
+
registerRouteVisibilityResolver,
|
|
86
|
+
resolveRouteVisibilityContext
|
|
87
|
+
};
|