@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.
Files changed (101) hide show
  1. package/client/appConfig.js +2 -1
  2. package/client/asyncModuleRecovery.js +2 -4
  3. package/client/index.d.ts +18 -76
  4. package/client/index.js +7 -2
  5. package/client/logging.js +8 -2
  6. package/client/moduleBootstrap.js +41 -33
  7. package/client/moduleBootstrap.test.js +35 -0
  8. package/client/shellBootstrap.js +38 -10
  9. package/client/shellBootstrap.test.js +85 -6
  10. package/client/shellRouting.js +16 -61
  11. package/client/shellRouting.test.js +30 -1
  12. package/client/vite/clientBootstrapPlugin.js +0 -6
  13. package/client/vite/clientBootstrapPlugin.test.js +2 -3
  14. package/internal/node/installedPackages.js +14 -58
  15. package/package.json +2 -4
  16. package/server/actions/actionCatalogue.js +13 -34
  17. package/{shared → server}/actions/actionContributorHelpers.js +0 -5
  18. package/{shared → server}/actions/actionDefinitions.js +24 -131
  19. package/{shared → server}/actions/actionDefinitions.test.js +75 -21
  20. package/server/actions/actionEvents.js +97 -2
  21. package/server/actions/actionEvents.test.js +79 -0
  22. package/{shared → server}/actions/executionContext.js +3 -13
  23. package/server/actions/idempotency.js +24 -0
  24. package/server/actions/pipeline.js +87 -0
  25. package/{shared → server}/actions/policies.js +20 -33
  26. package/{shared → server}/actions/policies.test.js +6 -6
  27. package/{shared → server}/actions/registry.js +3 -22
  28. package/{shared → server}/actions/registry.test.js +70 -32
  29. package/server/actions/requestMeta.js +17 -0
  30. package/server/http/capabilityHttpRuntime.js +1 -1
  31. package/server/http/capabilityHttpRuntime.test.js +56 -0
  32. package/server/http/errorHandling.js +291 -0
  33. package/server/{runtime/fastifyBootstrap.test.js → http/errorHandling.test.js} +72 -120
  34. package/server/http/lib/routeRegistration.js +36 -150
  35. package/server/http/lib/routeTransport.js +2 -0
  36. package/server/http/lib/routeValidator.js +5 -47
  37. package/server/http/lib/routeValidator.test.js +15 -17
  38. package/server/http/lib/router.js +10 -94
  39. package/server/platform/providerRuntime/capabilityProviderLoader.js +2 -1
  40. package/server/platform/providerRuntime/helpers.js +1 -34
  41. package/server/runtime/integers.js +1 -5
  42. package/server/runtime/serviceAuthorization.js +4 -9
  43. package/server/support/appConfig.js +2 -1
  44. package/server/support/appConfigFiles.js +1 -38
  45. package/server/support/appConfigFiles.test.js +3 -39
  46. package/server/support/index.js +1 -20
  47. package/shared/capabilities/defineProvider.js +1 -1
  48. package/shared/capabilities/index.js +1 -1
  49. package/shared/index.js +1 -1
  50. package/shared/support/index.js +1 -4
  51. package/shared/support/mobileConfig.js +99 -0
  52. package/shared/support/mobileConfig.test.js +113 -0
  53. package/shared/support/normalize.js +0 -108
  54. package/shared/support/normalize.test.js +0 -134
  55. package/shared/{actions/actionContributorHelpers.test.js → support/permissions.test.js} +1 -1
  56. package/shared/support/returnToPath.js +16 -20
  57. package/shared/support/returnToPath.test.js +5 -33
  58. package/shared/support/shellLayoutTargets.js +2 -140
  59. package/shared/support/shellLayoutTargets.test.js +1 -110
  60. package/shared/support/sorting.js +1 -9
  61. package/shared/surface/apiPaths.js +1 -82
  62. package/shared/surface/paths.js +38 -171
  63. package/shared/surface/registry.js +2 -1
  64. package/shared/surface/runtime.js +18 -109
  65. package/shared/surface/runtime.test.js +57 -0
  66. package/shared/validators/index.js +1 -4
  67. package/shared/validators/jsonRestSchemaSupport.js +0 -9
  68. package/shared/validators/recordIdParamsValidator.js +0 -6
  69. package/shared/validators/schemaDefinitions.js +4 -30
  70. package/shared/validators/schemaPayloadValidation.js +2 -6
  71. package/test/barrelExposure.test.js +5 -8
  72. package/test/exportsContract.test.js +1 -3
  73. package/client/mobileLaunchRouting.js +0 -231
  74. package/client/mobileLaunchRouting.test.js +0 -230
  75. package/server/http/lib/controller.js +0 -183
  76. package/server/http/lib/controller.test.js +0 -143
  77. package/server/http/lib/index.js +0 -5
  78. package/server/runtime/canonicalJson.js +0 -74
  79. package/server/runtime/entityChangeEvents.js +0 -307
  80. package/server/runtime/entityChangeEvents.test.js +0 -274
  81. package/server/runtime/fastifyBootstrap.js +0 -553
  82. package/server/runtime/moduleConfig.js +0 -223
  83. package/server/runtime/moduleConfig.test.js +0 -165
  84. package/server/runtime/pagination.js +0 -13
  85. package/server/runtime/realtimeNormalization.js +0 -21
  86. package/server/runtime/routeUtils.js +0 -20
  87. package/server/runtime/securityAudit.js +0 -269
  88. package/server/runtime/securityAudit.test.js +0 -41
  89. package/server/support/pageTargets.js +0 -772
  90. package/server/support/pageTargets.test.js +0 -659
  91. package/server/support/shellOutlets.js +0 -576
  92. package/server/support/shellOutlets.test.js +0 -336
  93. package/server/surface/index.js +0 -18
  94. package/shared/actions/audit.js +0 -7
  95. package/shared/actions/idempotency.js +0 -62
  96. package/shared/actions/observability.js +0 -10
  97. package/shared/actions/pipeline.js +0 -309
  98. package/shared/actions/requestMeta.js +0 -36
  99. package/shared/actions/textNormalization.js +0 -3
  100. package/shared/actions/withActionDefaults.js +0 -34
  101. /package/{shared → server}/actions/executionContext.test.js +0 -0
@@ -1,309 +0,0 @@
1
- import {
2
- ensureActionChannelAllowed,
3
- ensureActionSurfaceAllowed,
4
- ensureActionPermissionAllowed,
5
- normalizeActionInput,
6
- normalizeActionOutput
7
- } from "./policies.js";
8
- import {
9
- createNoopIdempotencyAdapter,
10
- resolveActionIdempotencyKey,
11
- ensureIdempotencyKeyIfRequired
12
- } from "./idempotency.js";
13
- import { createNoopAuditAdapter } from "./audit.js";
14
- import { createNoopObservabilityAdapter } from "./observability.js";
15
- import { normalizeExecutionContext } from "./executionContext.js";
16
-
17
- async function publishActionEvents(events, builders, execution) {
18
- if (!Array.isArray(builders) || builders.length === 0) return;
19
- if (!events || typeof events.publish !== "function") {
20
- throw new TypeError("Action event publishing requires runtime.events.publish().");
21
- }
22
- for (const builder of builders) {
23
- const built = await builder(execution);
24
- const values = Array.isArray(built) ? built : [built];
25
- for (const event of values) {
26
- if (event != null) await events.publish(event);
27
- }
28
- }
29
- }
30
-
31
- function normalizeOutcomeErrorCode(error) {
32
- return String(error?.code || "ACTION_EXECUTION_FAILED").trim();
33
- }
34
-
35
- function buildActionLogPayload({ definition, context, outcome, durationMs, errorCode, idempotencyReplay }) {
36
- return {
37
- action: definition?.id,
38
- version: definition?.version,
39
- channel: context?.channel,
40
- surface: context?.surface,
41
- requestId: context?.requestMeta?.requestId || null,
42
- durationMs,
43
- outcome,
44
- errorCode: errorCode || null,
45
- idempotencyReplay: Boolean(idempotencyReplay)
46
- };
47
- }
48
-
49
- async function emitAuditEvent(adapter, payload) {
50
- if (!adapter || typeof adapter.emitExecution !== "function") {
51
- return;
52
- }
53
-
54
- await adapter.emitExecution(payload);
55
- }
56
-
57
- async function executeIdempotencyClaim(adapter, payload) {
58
- if (!adapter || typeof adapter.claimOrReplay !== "function") {
59
- return {
60
- type: "proceed",
61
- idempotencyReplay: false,
62
- claim: null,
63
- replayResult: null
64
- };
65
- }
66
-
67
- const result = await adapter.claimOrReplay(payload);
68
- if (!result || typeof result !== "object") {
69
- return {
70
- type: "proceed",
71
- idempotencyReplay: false,
72
- claim: null,
73
- replayResult: null
74
- };
75
- }
76
-
77
- return {
78
- type: String(result.type || "proceed"),
79
- idempotencyReplay: result.idempotencyReplay === true,
80
- claim: result.claim || null,
81
- replayResult: Object.hasOwn(result, "replayResult") ? result.replayResult : null
82
- };
83
- }
84
-
85
- async function executeActionPipeline({
86
- definition,
87
- input,
88
- context,
89
- deps = {},
90
- idempotencyAdapter,
91
- auditAdapter,
92
- observabilityAdapter,
93
- events,
94
- logger = console
95
- } = {}) {
96
- const normalizedContext = normalizeExecutionContext(context);
97
- const normalizedIdempotencyAdapter = idempotencyAdapter || createNoopIdempotencyAdapter();
98
- const normalizedAuditAdapter = auditAdapter || createNoopAuditAdapter();
99
- const normalizedObservabilityAdapter = observabilityAdapter || createNoopObservabilityAdapter();
100
- const startedAt = Date.now();
101
-
102
- if (typeof normalizedObservabilityAdapter.recordExecutionStart === "function") {
103
- normalizedObservabilityAdapter.recordExecutionStart({
104
- definition,
105
- context: normalizedContext
106
- });
107
- }
108
-
109
- let idempotencyKey = "";
110
- let idempotencyClaim = null;
111
-
112
- try {
113
- ensureActionChannelAllowed(definition, normalizedContext);
114
- ensureActionSurfaceAllowed(definition, normalizedContext);
115
- ensureActionPermissionAllowed(definition, normalizedContext);
116
-
117
- const normalizedInput = await normalizeActionInput(definition, input, normalizedContext);
118
-
119
- idempotencyKey = resolveActionIdempotencyKey(definition, normalizedContext);
120
- ensureIdempotencyKeyIfRequired(definition, normalizedContext, idempotencyKey);
121
-
122
- const idempotencyPolicy = String(definition?.idempotency || "none").trim().toLowerCase();
123
- if (idempotencyPolicy !== "none") {
124
- const claimResult = await executeIdempotencyClaim(normalizedIdempotencyAdapter, {
125
- definition,
126
- context: normalizedContext,
127
- input: normalizedInput,
128
- idempotencyKey
129
- });
130
-
131
- idempotencyClaim = claimResult.claim;
132
- if (claimResult.type === "replay") {
133
- if (typeof normalizedObservabilityAdapter.recordIdempotentReplay === "function") {
134
- normalizedObservabilityAdapter.recordIdempotentReplay({
135
- definition,
136
- context: normalizedContext
137
- });
138
- }
139
-
140
- const replayDurationMs = Date.now() - startedAt;
141
- if (typeof normalizedObservabilityAdapter.recordExecutionFinish === "function") {
142
- normalizedObservabilityAdapter.recordExecutionFinish({
143
- definition,
144
- context: normalizedContext,
145
- outcome: "replay",
146
- durationMs: replayDurationMs,
147
- idempotencyReplay: true
148
- });
149
- }
150
-
151
- await emitAuditEvent(normalizedAuditAdapter, {
152
- definition,
153
- context: normalizedContext,
154
- outcome: "success",
155
- result: claimResult.replayResult,
156
- error: null,
157
- durationMs: replayDurationMs,
158
- idempotencyReplay: true
159
- });
160
-
161
- if (logger && typeof logger.debug === "function") {
162
- logger.debug(
163
- buildActionLogPayload({
164
- definition,
165
- context: normalizedContext,
166
- outcome: "replay",
167
- durationMs: replayDurationMs,
168
- errorCode: null,
169
- idempotencyReplay: true
170
- }),
171
- "action.execution"
172
- );
173
- }
174
-
175
- return {
176
- result: claimResult.replayResult,
177
- idempotencyReplay: true
178
- };
179
- }
180
- }
181
-
182
- const executionResult = await definition.execute(normalizedInput, normalizedContext, deps);
183
- const normalizedResult = await normalizeActionOutput(definition, executionResult, normalizedContext);
184
-
185
- await publishActionEvents(events, definition.events, Object.freeze({
186
- definition,
187
- input: normalizedInput,
188
- result: normalizedResult,
189
- context: normalizedContext
190
- }));
191
-
192
- if (idempotencyClaim && typeof normalizedIdempotencyAdapter.markSucceeded === "function") {
193
- await normalizedIdempotencyAdapter.markSucceeded({
194
- definition,
195
- context: normalizedContext,
196
- input: normalizedInput,
197
- result: normalizedResult,
198
- claim: idempotencyClaim,
199
- idempotencyKey
200
- });
201
- }
202
-
203
- const durationMs = Date.now() - startedAt;
204
- if (typeof normalizedObservabilityAdapter.recordExecutionFinish === "function") {
205
- normalizedObservabilityAdapter.recordExecutionFinish({
206
- definition,
207
- context: normalizedContext,
208
- outcome: "success",
209
- durationMs,
210
- idempotencyReplay: false
211
- });
212
- }
213
-
214
- await emitAuditEvent(normalizedAuditAdapter, {
215
- definition,
216
- context: normalizedContext,
217
- outcome: "success",
218
- result: normalizedResult,
219
- error: null,
220
- durationMs,
221
- idempotencyReplay: false
222
- });
223
-
224
- if (logger && typeof logger.debug === "function") {
225
- logger.debug(
226
- buildActionLogPayload({
227
- definition,
228
- context: normalizedContext,
229
- outcome: "success",
230
- durationMs,
231
- errorCode: null,
232
- idempotencyReplay: false
233
- }),
234
- "action.execution"
235
- );
236
- }
237
-
238
- return {
239
- result: normalizedResult,
240
- idempotencyReplay: false
241
- };
242
- } catch (error) {
243
- const executionError = error;
244
-
245
- if (executionError?.code === "ACTION_VALIDATION_FAILED") {
246
- if (typeof normalizedObservabilityAdapter.recordValidationFailure === "function") {
247
- normalizedObservabilityAdapter.recordValidationFailure({
248
- definition,
249
- context: normalizedContext,
250
- error: executionError
251
- });
252
- }
253
- }
254
-
255
- if (idempotencyClaim && typeof normalizedIdempotencyAdapter.markFailed === "function") {
256
- await normalizedIdempotencyAdapter.markFailed({
257
- definition,
258
- context: normalizedContext,
259
- input,
260
- error: executionError,
261
- claim: idempotencyClaim,
262
- idempotencyKey
263
- });
264
- }
265
-
266
- const durationMs = Date.now() - startedAt;
267
- const errorCode = normalizeOutcomeErrorCode(executionError);
268
-
269
- if (typeof normalizedObservabilityAdapter.recordExecutionFinish === "function") {
270
- normalizedObservabilityAdapter.recordExecutionFinish({
271
- definition,
272
- context: normalizedContext,
273
- outcome: "failure",
274
- durationMs,
275
- error: executionError,
276
- errorCode,
277
- idempotencyReplay: false
278
- });
279
- }
280
-
281
- await emitAuditEvent(normalizedAuditAdapter, {
282
- definition,
283
- context: normalizedContext,
284
- outcome: "failure",
285
- result: null,
286
- error: executionError,
287
- durationMs,
288
- idempotencyReplay: false
289
- });
290
-
291
- if (logger && typeof logger.debug === "function") {
292
- logger.debug(
293
- buildActionLogPayload({
294
- definition,
295
- context: normalizedContext,
296
- outcome: "failure",
297
- durationMs,
298
- errorCode,
299
- idempotencyReplay: false
300
- }),
301
- "action.execution"
302
- );
303
- }
304
-
305
- throw executionError;
306
- }
307
- }
308
-
309
- export { executeActionPipeline };
@@ -1,36 +0,0 @@
1
- import { normalizeText } from "./textNormalization.js";
2
-
3
- const DEFAULT_FIELDS = Object.freeze(["requestId", "commandId", "idempotencyKey", "ip", "userAgent", "request"]);
4
-
5
- function normalizeRequestMeta(requestMeta = {}, { fields = DEFAULT_FIELDS, emptyAsNull = false } = {}) {
6
- const source = requestMeta && typeof requestMeta === "object" ? requestMeta : {};
7
- const fieldList = Array.isArray(fields) && fields.length > 0 ? fields : DEFAULT_FIELDS;
8
-
9
- const normalizeValue = (value) => {
10
- const normalized = normalizeText(value);
11
- if (emptyAsNull && !normalized) {
12
- return null;
13
- }
14
- return normalized;
15
- };
16
-
17
- const normalized = {
18
- ...source
19
- };
20
- for (const field of fieldList) {
21
- if (field === "request") {
22
- normalized.request = source.request || null;
23
- continue;
24
- }
25
- if (field === "logger") {
26
- normalized.logger = source.logger && typeof source.logger.warn === "function" ? source.logger : null;
27
- continue;
28
- }
29
-
30
- normalized[field] = normalizeValue(source[field]);
31
- }
32
-
33
- return normalized;
34
- }
35
-
36
- export { normalizeRequestMeta };
@@ -1,3 +0,0 @@
1
- import { normalizeText, normalizeLowerText } from "../support/normalize.js";
2
-
3
- export { normalizeText, normalizeLowerText };
@@ -1,34 +0,0 @@
1
- import { normalizeObject } from "../support/normalize.js";
2
-
3
- function withActionDefaults(actions = [], defaults = {}) {
4
- const sourceActions = Array.isArray(actions) ? actions : [];
5
- const sourceDefaults = normalizeObject(defaults);
6
- const defaultDependencies = normalizeObject(sourceDefaults.dependencies);
7
- const hasDefaultDependencies = Object.keys(defaultDependencies).length > 0;
8
- const hasDefaultDomain = Object.hasOwn(sourceDefaults, "domain");
9
-
10
- return Object.freeze(
11
- sourceActions.map((entry) => {
12
- const action = normalizeObject(entry);
13
- const actionDependencies = normalizeObject(action.dependencies);
14
- const next = {
15
- ...action
16
- };
17
-
18
- if (hasDefaultDomain && !Object.hasOwn(next, "domain")) {
19
- next.domain = sourceDefaults.domain;
20
- }
21
-
22
- if (hasDefaultDependencies || Object.keys(actionDependencies).length > 0) {
23
- next.dependencies = Object.freeze({
24
- ...defaultDependencies,
25
- ...actionDependencies
26
- });
27
- }
28
-
29
- return Object.freeze(next);
30
- })
31
- );
32
- }
33
-
34
- export { withActionDefaults };