@jskit-ai/kernel 0.1.245 → 0.1.247

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 (102) hide show
  1. package/client/appConfig.js +2 -1
  2. package/client/asyncModuleRecovery.js +2 -4
  3. package/client/index.d.ts +13 -75
  4. package/client/index.js +1 -1
  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 +1 -8
  9. package/client/shellBootstrap.test.js +32 -5
  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 +19 -62
  15. package/internal/node/installedPackages.test.js +33 -0
  16. package/package.json +2 -4
  17. package/server/actions/actionCatalogue.js +13 -34
  18. package/{shared → server}/actions/actionContributorHelpers.js +0 -5
  19. package/{shared → server}/actions/actionDefinitions.js +24 -131
  20. package/{shared → server}/actions/actionDefinitions.test.js +75 -21
  21. package/server/actions/actionEvents.js +97 -2
  22. package/server/actions/actionEvents.test.js +79 -0
  23. package/{shared → server}/actions/executionContext.js +3 -13
  24. package/server/actions/idempotency.js +24 -0
  25. package/server/actions/pipeline.js +87 -0
  26. package/{shared → server}/actions/policies.js +20 -33
  27. package/{shared → server}/actions/policies.test.js +6 -6
  28. package/{shared → server}/actions/registry.js +3 -22
  29. package/{shared → server}/actions/registry.test.js +70 -32
  30. package/server/actions/requestMeta.js +17 -0
  31. package/server/http/capabilityHttpRuntime.js +1 -1
  32. package/server/http/capabilityHttpRuntime.test.js +56 -0
  33. package/server/http/errorHandling.js +291 -0
  34. package/server/{runtime/fastifyBootstrap.test.js → http/errorHandling.test.js} +72 -120
  35. package/server/http/lib/routeRegistration.js +36 -150
  36. package/server/http/lib/routeTransport.js +2 -0
  37. package/server/http/lib/routeValidator.js +5 -47
  38. package/server/http/lib/routeValidator.test.js +15 -17
  39. package/server/http/lib/router.js +10 -94
  40. package/server/platform/providerRuntime/capabilityProviderLoader.js +2 -1
  41. package/server/platform/providerRuntime/helpers.js +1 -34
  42. package/server/runtime/integers.js +1 -5
  43. package/server/runtime/serviceAuthorization.js +4 -9
  44. package/server/support/appConfig.js +2 -1
  45. package/server/support/appConfigFiles.js +1 -38
  46. package/server/support/appConfigFiles.test.js +3 -39
  47. package/server/support/index.js +1 -20
  48. package/shared/capabilities/defineProvider.js +1 -1
  49. package/shared/capabilities/index.js +1 -1
  50. package/shared/index.js +1 -1
  51. package/shared/support/index.js +1 -4
  52. package/shared/support/mobileConfig.js +99 -0
  53. package/shared/support/mobileConfig.test.js +113 -0
  54. package/shared/support/normalize.js +0 -108
  55. package/shared/support/normalize.test.js +0 -134
  56. package/shared/{actions/actionContributorHelpers.test.js → support/permissions.test.js} +1 -1
  57. package/shared/support/returnToPath.js +1 -20
  58. package/shared/support/returnToPath.test.js +1 -36
  59. package/shared/support/shellLayoutTargets.js +2 -140
  60. package/shared/support/shellLayoutTargets.test.js +1 -110
  61. package/shared/support/sorting.js +1 -9
  62. package/shared/surface/apiPaths.js +1 -82
  63. package/shared/surface/paths.js +38 -171
  64. package/shared/surface/registry.js +2 -1
  65. package/shared/surface/runtime.js +18 -109
  66. package/shared/surface/runtime.test.js +57 -0
  67. package/shared/validators/index.js +1 -4
  68. package/shared/validators/jsonRestSchemaSupport.js +0 -9
  69. package/shared/validators/recordIdParamsValidator.js +0 -6
  70. package/shared/validators/schemaDefinitions.js +4 -30
  71. package/shared/validators/schemaPayloadValidation.js +2 -6
  72. package/test/barrelExposure.test.js +3 -7
  73. package/test/exportsContract.test.js +1 -3
  74. package/client/mobileLaunchRouting.js +0 -231
  75. package/client/mobileLaunchRouting.test.js +0 -230
  76. package/server/http/lib/controller.js +0 -183
  77. package/server/http/lib/controller.test.js +0 -143
  78. package/server/http/lib/index.js +0 -5
  79. package/server/runtime/canonicalJson.js +0 -74
  80. package/server/runtime/entityChangeEvents.js +0 -307
  81. package/server/runtime/entityChangeEvents.test.js +0 -274
  82. package/server/runtime/fastifyBootstrap.js +0 -553
  83. package/server/runtime/moduleConfig.js +0 -223
  84. package/server/runtime/moduleConfig.test.js +0 -165
  85. package/server/runtime/pagination.js +0 -13
  86. package/server/runtime/realtimeNormalization.js +0 -21
  87. package/server/runtime/routeUtils.js +0 -20
  88. package/server/runtime/securityAudit.js +0 -269
  89. package/server/runtime/securityAudit.test.js +0 -41
  90. package/server/support/pageTargets.js +0 -772
  91. package/server/support/pageTargets.test.js +0 -659
  92. package/server/support/shellOutlets.js +0 -576
  93. package/server/support/shellOutlets.test.js +0 -336
  94. package/server/surface/index.js +0 -18
  95. package/shared/actions/audit.js +0 -7
  96. package/shared/actions/idempotency.js +0 -62
  97. package/shared/actions/observability.js +0 -10
  98. package/shared/actions/pipeline.js +0 -309
  99. package/shared/actions/requestMeta.js +0 -36
  100. package/shared/actions/textNormalization.js +0 -3
  101. package/shared/actions/withActionDefaults.js +0 -34
  102. /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 };