@jskit-ai/kernel 0.1.245 → 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 +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 +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 +1 -20
  57. package/shared/support/returnToPath.test.js +1 -36
  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 +3 -7
  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,336 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
3
- import path from "node:path";
4
- import { tmpdir } from "node:os";
5
- import test from "node:test";
6
- import {
7
- discoverShellOutletSourcePathsFromApp,
8
- discoverShellOutletTargetsFromApp,
9
- resolveShellOutletPlacementTargetFromApp
10
- } from "./shellOutlets.js";
11
-
12
- async function withTempApp(run) {
13
- const appRoot = await mkdtemp(path.join(tmpdir(), "kernel-shell-outlets-"));
14
- try {
15
- return await run(appRoot);
16
- } finally {
17
- await rm(appRoot, { recursive: true, force: true });
18
- }
19
- }
20
-
21
- async function writeFileInApp(appRoot, relativePath, source) {
22
- const absoluteFilePath = path.join(appRoot, relativePath);
23
- await mkdir(path.dirname(absoluteFilePath), { recursive: true });
24
- await writeFile(absoluteFilePath, source, "utf8");
25
- }
26
-
27
- test("resolveShellOutletPlacementTargetFromApp reads outlets across app Vue files", async () => {
28
- await withTempApp(async (appRoot) => {
29
- await writeFileInApp(
30
- appRoot,
31
- "src/components/ShellLayout.vue",
32
- `<template>
33
- <div>
34
- <ShellOutlet target="shell-layout:primary-menu" />
35
- <ShellOutlet target="shell-layout:top-right" />
36
- </div>
37
- </template>
38
- `
39
- );
40
- await writeFileInApp(
41
- appRoot,
42
- "src/pages/admin/workspace/settings/index.vue",
43
- `<template>
44
- <section>
45
- <ShellOutlet target="admin-settings:forms" default />
46
- </section>
47
- </template>
48
- `
49
- );
50
-
51
- const target = await resolveShellOutletPlacementTargetFromApp({
52
- appRoot,
53
- context: "ui-generator"
54
- });
55
-
56
- assert.equal(target.id, "admin-settings:forms");
57
- });
58
- });
59
-
60
- test("discoverShellOutletTargetsFromApp includes installed package placement outlets", async () => {
61
- await withTempApp(async (appRoot) => {
62
- await writeFileInApp(
63
- appRoot,
64
- "src/components/ShellLayout.vue",
65
- `<template>
66
- <div>
67
- <ShellOutlet target="shell-layout:primary-menu" default />
68
- </div>
69
- </template>
70
- `
71
- );
72
- await writeFileInApp(
73
- appRoot,
74
- "package.json",
75
- `${JSON.stringify(
76
- {
77
- name: "fixture-app",
78
- private: true,
79
- dependencies: {
80
- "@example/users-web": "1.0.0"
81
- }
82
- },
83
- null,
84
- 2
85
- )}\n`
86
- );
87
- await writeFileInApp(
88
- appRoot,
89
- "node_modules/@example/users-web/package.json",
90
- `${JSON.stringify({
91
- name: "@example/users-web",
92
- version: "1.0.0",
93
- jskit: {
94
- metadata: {
95
- ui: {
96
- placements: {
97
- outlets: [
98
- {
99
- target: "admin-cog:primary-menu",
100
- source: "src/client/components/UsersWorkspaceToolsWidget.vue"
101
- }
102
- ]
103
- }
104
- }
105
- }
106
- }
107
- }, null, 2)}\n`
108
- );
109
-
110
- const discovered = await discoverShellOutletTargetsFromApp({ appRoot });
111
- assert.deepEqual(
112
- discovered.targets.map((entry) => entry.id),
113
- ["admin-cog:primary-menu", "shell-layout:primary-menu"]
114
- );
115
- assert.deepEqual(discovered.targets[0], {
116
- id: "admin-cog:primary-menu",
117
- default: false,
118
- sourcePath: "package:@example/users-web:src/client/components/UsersWorkspaceToolsWidget.vue",
119
- sourcePackageId: "@example/users-web"
120
- });
121
-
122
- const target = await resolveShellOutletPlacementTargetFromApp({
123
- appRoot,
124
- placement: "admin-cog:primary-menu",
125
- context: "ui-generator"
126
- });
127
- assert.equal(target.id, "admin-cog:primary-menu");
128
- });
129
- });
130
-
131
- test("discoverShellOutletTargetsFromApp returns targets with sourcePath and default marker", async () => {
132
- await withTempApp(async (appRoot) => {
133
- await writeFileInApp(
134
- appRoot,
135
- "src/components/ShellLayout.vue",
136
- `<template>
137
- <div>
138
- <ShellOutlet target="shell-layout:primary-menu" />
139
- </div>
140
- </template>
141
- `
142
- );
143
- await writeFileInApp(
144
- appRoot,
145
- "src/pages/admin/toolbox/index.vue",
146
- `<template>
147
- <section>
148
- <ShellOutlet target="admin-toolbox:widgets" default />
149
- </section>
150
- </template>
151
- `
152
- );
153
-
154
- const discovered = await discoverShellOutletTargetsFromApp({ appRoot });
155
- assert.equal(discovered.defaultTargetId, "admin-toolbox:widgets");
156
- assert.deepEqual(discovered.targets, [
157
- {
158
- id: "admin-toolbox:widgets",
159
- default: true,
160
- sourcePath: "src/pages/admin/toolbox/index.vue"
161
- },
162
- {
163
- id: "shell-layout:primary-menu",
164
- default: false,
165
- sourcePath: "src/components/ShellLayout.vue"
166
- }
167
- ]);
168
- });
169
- });
170
-
171
- test("discoverShellOutletTargetsFromApp discovers route meta placement outlets", async () => {
172
- await withTempApp(async (appRoot) => {
173
- await writeFileInApp(
174
- appRoot,
175
- "src/pages/w/[workspaceSlug]/admin/contacts/[contactId]/contact-tools.vue",
176
- `<template><section /></template>
177
-
178
- <route lang="json">
179
- {
180
- "meta": {
181
- "jskit": {
182
- "placements": {
183
- "outlets": [
184
- {
185
- "target": "contact-tools:sub-pages"
186
- }
187
- ]
188
- }
189
- }
190
- }
191
- }
192
- </route>
193
- `
194
- );
195
-
196
- const discovered = await discoverShellOutletTargetsFromApp({ appRoot });
197
- assert.deepEqual(discovered.targets, [
198
- {
199
- id: "contact-tools:sub-pages",
200
- default: false,
201
- sourcePath: "src/pages/w/[workspaceSlug]/admin/contacts/[contactId]/contact-tools.vue"
202
- }
203
- ]);
204
-
205
- const target = await resolveShellOutletPlacementTargetFromApp({
206
- appRoot,
207
- placement: "contact-tools:sub-pages",
208
- context: "ui-generator"
209
- });
210
- assert.equal(target.id, "contact-tools:sub-pages");
211
- });
212
- });
213
-
214
- test("resolveShellOutletPlacementTargetFromApp supports explicit placement override", async () => {
215
- await withTempApp(async (appRoot) => {
216
- await writeFileInApp(
217
- appRoot,
218
- "src/components/ShellLayout.vue",
219
- `<template>
220
- <div>
221
- <ShellOutlet target="shell-layout:primary-menu" default />
222
- <ShellOutlet target="shell-layout:top-right" />
223
- </div>
224
- </template>
225
- `
226
- );
227
-
228
- const target = await resolveShellOutletPlacementTargetFromApp({
229
- appRoot,
230
- context: "ui-generator",
231
- placement: "shell-layout:top-right"
232
- });
233
-
234
- assert.equal(target.id, "shell-layout:top-right");
235
- });
236
- });
237
-
238
- test("resolveShellOutletPlacementTargetFromApp validates placement format", async () => {
239
- await withTempApp(async (appRoot) => {
240
- await writeFileInApp(
241
- appRoot,
242
- "src/components/ShellLayout.vue",
243
- `<template>
244
- <div>
245
- <ShellOutlet target="shell-layout:primary-menu" default />
246
- </div>
247
- </template>
248
- `
249
- );
250
-
251
- await assert.rejects(
252
- () =>
253
- resolveShellOutletPlacementTargetFromApp({
254
- appRoot,
255
- context: "ui-generator",
256
- placement: "invalid-placement"
257
- }),
258
- /option "placement" must be a target in "host:position" format/
259
- );
260
- });
261
- });
262
-
263
- test("resolveShellOutletPlacementTargetFromApp throws when multiple default outlets exist", async () => {
264
- await withTempApp(async (appRoot) => {
265
- await writeFileInApp(
266
- appRoot,
267
- "src/components/ShellLayout.vue",
268
- `<template>
269
- <div>
270
- <ShellOutlet target="shell-layout:primary-menu" default />
271
- </div>
272
- </template>
273
- `
274
- );
275
- await writeFileInApp(
276
- appRoot,
277
- "src/pages/admin/workspace/settings/index.vue",
278
- `<template>
279
- <section>
280
- <ShellOutlet target="admin-settings:forms" default />
281
- </section>
282
- </template>
283
- `
284
- );
285
-
286
- await assert.rejects(
287
- () =>
288
- resolveShellOutletPlacementTargetFromApp({
289
- appRoot,
290
- context: "ui-generator"
291
- }),
292
- /Multiple default ShellOutlet targets found in app source/
293
- );
294
- });
295
- });
296
-
297
- test("discoverShellOutletSourcePathsFromApp ignores default conflicts while keeping source paths", async () => {
298
- await withTempApp(async (appRoot) => {
299
- await writeFileInApp(
300
- appRoot,
301
- "src/components/ShellLayout.vue",
302
- `<template>
303
- <div>
304
- <ShellOutlet target="shell-layout:primary-menu" default />
305
- <ShellOutlet target="shell-layout:primary-bottom-nav" default />
306
- </div>
307
- </template>
308
- `
309
- );
310
-
311
- const discovered = await discoverShellOutletSourcePathsFromApp({ appRoot });
312
- assert.deepEqual(discovered.targets, [
313
- {
314
- id: "shell-layout:primary-bottom-nav",
315
- default: true,
316
- sourcePath: "src/components/ShellLayout.vue"
317
- },
318
- {
319
- id: "shell-layout:primary-menu",
320
- default: true,
321
- sourcePath: "src/components/ShellLayout.vue"
322
- }
323
- ]);
324
- });
325
- });
326
-
327
- test("resolveShellOutletPlacementTargetFromApp requires appRoot", async () => {
328
- await assert.rejects(
329
- () =>
330
- resolveShellOutletPlacementTargetFromApp({
331
- appRoot: "",
332
- context: "ui-generator"
333
- }),
334
- /requires appRoot/
335
- );
336
- });
@@ -1,18 +0,0 @@
1
- export { createSurfaceRegistry, normalizeSurfaceId } from "../../shared/surface/registry.js";
2
- export { createSurfacePathHelpers } from "../../shared/surface/paths.js";
3
- export { createSurfaceRuntime, filterRoutesBySurface } from "../../shared/surface/runtime.js";
4
- export { escapeRegExp } from "../../shared/surface/escapeRegExp.js";
5
- export {
6
- API_BASE_PATH,
7
- API_PREFIX,
8
- API_PREFIX_SLASH,
9
- API_DOCS_PATH,
10
- API_REALTIME_PATH,
11
- normalizePathname,
12
- isApiPath,
13
- isVersionedApiPath,
14
- toVersionedApiPath,
15
- toVersionedApiPrefix,
16
- buildVersionedApiPath,
17
- isVersionedApiPrefixMatch
18
- } from "../../shared/surface/apiPaths.js";
@@ -1,7 +0,0 @@
1
- function createNoopAuditAdapter() {
2
- return {
3
- async emitExecution() {}
4
- };
5
- }
6
-
7
- export { createNoopAuditAdapter };
@@ -1,62 +0,0 @@
1
- import { createActionRuntimeError } from "./actionDefinitions.js";
2
- import { normalizeText } from "./textNormalization.js";
3
-
4
- function resolveRequestIdempotencyKey(context) {
5
- return normalizeText(context?.requestMeta?.idempotencyKey || context?.requestMeta?.commandId || "");
6
- }
7
-
8
- function resolveActionIdempotencyKey(definition, context) {
9
- const policy = normalizeText(definition?.idempotency || "none").toLowerCase();
10
- if (policy === "none") {
11
- return "";
12
- }
13
-
14
- return resolveRequestIdempotencyKey(context);
15
- }
16
-
17
- function createNoopIdempotencyAdapter() {
18
- return {
19
- async claimOrReplay() {
20
- return {
21
- type: "proceed",
22
- idempotencyReplay: false,
23
- claim: null,
24
- replayResult: null
25
- };
26
- },
27
- async markSucceeded() {},
28
- async markFailed() {}
29
- };
30
- }
31
-
32
- function ensureIdempotencyKeyIfRequired(definition, context, key) {
33
- const policy = normalizeText(definition?.idempotency || "none").toLowerCase();
34
- if (policy !== "required") {
35
- return;
36
- }
37
-
38
- if (normalizeText(key)) {
39
- return;
40
- }
41
-
42
- throw createActionRuntimeError(400, "Validation failed.", {
43
- code: "ACTION_IDEMPOTENCY_KEY_REQUIRED",
44
- details: {
45
- fieldErrors: {
46
- idempotencyKey: "Idempotency key is required for this action."
47
- }
48
- }
49
- });
50
- }
51
-
52
- const __testables = {
53
- normalizeText,
54
- resolveRequestIdempotencyKey
55
- };
56
-
57
- export {
58
- resolveActionIdempotencyKey,
59
- ensureIdempotencyKeyIfRequired,
60
- createNoopIdempotencyAdapter,
61
- __testables
62
- };
@@ -1,10 +0,0 @@
1
- function createNoopObservabilityAdapter() {
2
- return {
3
- recordExecutionStart() {},
4
- recordExecutionFinish() {},
5
- recordValidationFailure() {},
6
- recordIdempotentReplay() {}
7
- };
8
- }
9
-
10
- export { createNoopObservabilityAdapter };