@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,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 };