@jskit-ai/kernel 0.1.147 → 0.1.149
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/client/moduleBootstrap.js +54 -54
- package/client/moduleBootstrap.test.js +12 -12
- package/client/{descriptorSections.js → packageMetadataSections.js} +15 -15
- package/client/vite/clientBootstrapPlugin.js +67 -100
- package/client/vite/clientBootstrapPlugin.test.js +177 -238
- package/internal/node/installedPackages.js +283 -0
- package/package.json +1 -1
- package/server/platform/providerRuntime/{descriptorCatalog.js → packageCatalog.js} +32 -47
- package/server/platform/providerRuntime/providerLoader.js +18 -18
- package/server/platform/providerRuntime.js +15 -22
- package/server/platform/providerRuntime.test.js +56 -171
- package/server/platform/surfaceRuntime.test.js +1 -1
- package/server/support/index.js +6 -0
- package/server/support/shellOutlets.js +15 -51
- package/server/support/shellOutlets.test.js +23 -26
- package/shared/support/generatedUiContract.js +1 -1
- package/shared/support/generatedUiContract.test.js +11 -1
- package/shared/validators/schemaDefinitions.test.js +39 -0
- package/internal/node/installedPackageDescriptor.js +0 -125
- package/server/platform/providerRuntime/lockfile.js +0 -27
- package/shared/support/packageDescriptor.test.js +0 -147
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { pathToFileURL } from "node:url";
|
|
3
|
-
import { normalizeObject } from "../../shared/support/normalize.js";
|
|
4
|
-
import { fileExists } from "./fileSystem.js";
|
|
5
|
-
|
|
6
|
-
function resolveNodeModulesDescriptorCandidatePaths({ appRoot, packageId }) {
|
|
7
|
-
const packageDescriptorPath = path.join(packageId, "package.descriptor.mjs");
|
|
8
|
-
const candidatePaths = [];
|
|
9
|
-
let currentRoot = path.resolve(appRoot);
|
|
10
|
-
|
|
11
|
-
while (true) {
|
|
12
|
-
const nodeModulesRoot =
|
|
13
|
-
path.basename(currentRoot) === "node_modules" ? currentRoot : path.join(currentRoot, "node_modules");
|
|
14
|
-
candidatePaths.push(path.join(nodeModulesRoot, packageDescriptorPath));
|
|
15
|
-
|
|
16
|
-
const parentRoot = path.dirname(currentRoot);
|
|
17
|
-
if (parentRoot === currentRoot) {
|
|
18
|
-
break;
|
|
19
|
-
}
|
|
20
|
-
currentRoot = parentRoot;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return candidatePaths;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function resolveDescriptorCandidatePaths({ appRoot, packageId, installedPackageState }) {
|
|
27
|
-
const normalizedAppRoot = String(appRoot || "").trim();
|
|
28
|
-
if (!normalizedAppRoot) {
|
|
29
|
-
throw new TypeError("resolveDescriptorCandidatePaths requires appRoot.");
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const normalizedPackageId = String(packageId || "").trim();
|
|
33
|
-
if (!normalizedPackageId) {
|
|
34
|
-
throw new TypeError("resolveDescriptorCandidatePaths requires packageId.");
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const source = normalizeObject(installedPackageState?.source);
|
|
38
|
-
const descriptorPathFromSource = String(source.descriptorPath || "").trim();
|
|
39
|
-
const packagePathFromSource = String(source.packagePath || "").trim();
|
|
40
|
-
const jskitRoot = path.join(normalizedAppRoot, "node_modules", "@jskit-ai", "jskit-cli");
|
|
41
|
-
|
|
42
|
-
const candidatePaths = resolveNodeModulesDescriptorCandidatePaths({
|
|
43
|
-
appRoot: normalizedAppRoot,
|
|
44
|
-
packageId: normalizedPackageId
|
|
45
|
-
});
|
|
46
|
-
if (packagePathFromSource) {
|
|
47
|
-
candidatePaths.push(path.resolve(normalizedAppRoot, packagePathFromSource, "package.descriptor.mjs"));
|
|
48
|
-
}
|
|
49
|
-
if (descriptorPathFromSource) {
|
|
50
|
-
candidatePaths.push(path.resolve(normalizedAppRoot, descriptorPathFromSource));
|
|
51
|
-
candidatePaths.push(path.resolve(jskitRoot, descriptorPathFromSource));
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const uniqueCandidatePaths = [];
|
|
55
|
-
const seenPaths = new Set();
|
|
56
|
-
for (const candidatePath of candidatePaths) {
|
|
57
|
-
const normalizedCandidatePath = String(candidatePath || "").trim();
|
|
58
|
-
if (!normalizedCandidatePath || seenPaths.has(normalizedCandidatePath)) {
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
seenPaths.add(normalizedCandidatePath);
|
|
62
|
-
uniqueCandidatePaths.push(normalizedCandidatePath);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return uniqueCandidatePaths;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async function resolveDescriptorPathForInstalledPackage({ appRoot, packageId, installedPackageState, required = false }) {
|
|
69
|
-
const candidatePaths = resolveDescriptorCandidatePaths({
|
|
70
|
-
appRoot,
|
|
71
|
-
packageId,
|
|
72
|
-
installedPackageState
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
for (const candidatePath of candidatePaths) {
|
|
76
|
-
if (await fileExists(candidatePath)) {
|
|
77
|
-
return candidatePath;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (required === true) {
|
|
82
|
-
throw new Error(`Unable to resolve package descriptor for ${String(packageId || "").trim()}.`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return "";
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function normalizeDescriptorPayload(descriptorModule) {
|
|
89
|
-
return normalizeObject(descriptorModule?.default);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async function loadInstalledPackageDescriptor({ appRoot, packageId, installedPackageState, required = false }) {
|
|
93
|
-
const descriptorPath = await resolveDescriptorPathForInstalledPackage({
|
|
94
|
-
appRoot,
|
|
95
|
-
packageId,
|
|
96
|
-
installedPackageState,
|
|
97
|
-
required
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
if (!descriptorPath) {
|
|
101
|
-
return Object.freeze({
|
|
102
|
-
descriptorPath: "",
|
|
103
|
-
descriptor: Object.freeze({})
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
try {
|
|
108
|
-
const descriptorModule = await import(pathToFileURL(descriptorPath).href);
|
|
109
|
-
return Object.freeze({
|
|
110
|
-
descriptorPath,
|
|
111
|
-
descriptor: normalizeDescriptorPayload(descriptorModule)
|
|
112
|
-
});
|
|
113
|
-
} catch (error) {
|
|
114
|
-
if (required === true) {
|
|
115
|
-
throw error;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return Object.freeze({
|
|
119
|
-
descriptorPath: "",
|
|
120
|
-
descriptor: Object.freeze({})
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export { loadInstalledPackageDescriptor, resolveDescriptorPathForInstalledPackage };
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { readFile } from "node:fs/promises";
|
|
3
|
-
import { fileExists } from "../../../internal/node/fileSystem.js";
|
|
4
|
-
|
|
5
|
-
async function readLockFromApp({ appRoot, lockPath = ".jskit/lock.json" } = {}) {
|
|
6
|
-
if (!appRoot || typeof appRoot !== "string") {
|
|
7
|
-
throw new TypeError("readLockFromApp requires appRoot.");
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const absoluteLockPath = path.resolve(appRoot, String(lockPath || ".jskit/lock.json"));
|
|
11
|
-
if (!(await fileExists(absoluteLockPath))) {
|
|
12
|
-
throw new Error(`Lock file not found: ${absoluteLockPath}`);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const source = await readFile(absoluteLockPath, "utf8");
|
|
16
|
-
const lock = JSON.parse(source);
|
|
17
|
-
if (!lock || typeof lock !== "object") {
|
|
18
|
-
throw new TypeError(`Invalid lock file payload at ${absoluteLockPath}.`);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
lock,
|
|
23
|
-
lockPath: absoluteLockPath
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export { readLockFromApp };
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import test from "node:test";
|
|
6
|
-
|
|
7
|
-
import { loadInstalledPackageDescriptor, resolveDescriptorPathForInstalledPackage } from "../../internal/node/installedPackageDescriptor.js";
|
|
8
|
-
|
|
9
|
-
async function createFixtureRoot(prefix) {
|
|
10
|
-
return mkdtemp(path.join(tmpdir(), prefix));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async function writeDescriptorFile(filePath, descriptorSource) {
|
|
14
|
-
await mkdir(path.dirname(filePath), { recursive: true });
|
|
15
|
-
await writeFile(filePath, descriptorSource, "utf8");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
test("resolveDescriptorPathForInstalledPackage returns empty string when descriptor is missing and required=false", async () => {
|
|
19
|
-
const appRoot = await createFixtureRoot("kernel-package-descriptor-missing-");
|
|
20
|
-
try {
|
|
21
|
-
const descriptorPath = await resolveDescriptorPathForInstalledPackage({
|
|
22
|
-
appRoot,
|
|
23
|
-
packageId: "@example/missing",
|
|
24
|
-
installedPackageState: {},
|
|
25
|
-
required: false
|
|
26
|
-
});
|
|
27
|
-
assert.equal(descriptorPath, "");
|
|
28
|
-
} finally {
|
|
29
|
-
await rm(appRoot, { recursive: true, force: true });
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test("resolveDescriptorPathForInstalledPackage throws when descriptor is missing and required=true", async () => {
|
|
34
|
-
const appRoot = await createFixtureRoot("kernel-package-descriptor-required-");
|
|
35
|
-
try {
|
|
36
|
-
await assert.rejects(
|
|
37
|
-
() =>
|
|
38
|
-
resolveDescriptorPathForInstalledPackage({
|
|
39
|
-
appRoot,
|
|
40
|
-
packageId: "@example/missing",
|
|
41
|
-
installedPackageState: {},
|
|
42
|
-
required: true
|
|
43
|
-
}),
|
|
44
|
-
/Unable to resolve package descriptor for @example\/missing\./
|
|
45
|
-
);
|
|
46
|
-
} finally {
|
|
47
|
-
await rm(appRoot, { recursive: true, force: true });
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test("resolveDescriptorPathForInstalledPackage resolves descriptor using source.packagePath", async () => {
|
|
52
|
-
const appRoot = await createFixtureRoot("kernel-package-descriptor-package-path-");
|
|
53
|
-
try {
|
|
54
|
-
const descriptorPath = path.join(appRoot, "packages", "local-example", "package.descriptor.mjs");
|
|
55
|
-
await writeDescriptorFile(descriptorPath, "export default { packageId: \"@local/example\" };\n");
|
|
56
|
-
|
|
57
|
-
const resolvedDescriptorPath = await resolveDescriptorPathForInstalledPackage({
|
|
58
|
-
appRoot,
|
|
59
|
-
packageId: "@local/example",
|
|
60
|
-
installedPackageState: {
|
|
61
|
-
source: {
|
|
62
|
-
packagePath: "packages/local-example"
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
required: true
|
|
66
|
-
});
|
|
67
|
-
assert.equal(resolvedDescriptorPath, descriptorPath);
|
|
68
|
-
} finally {
|
|
69
|
-
await rm(appRoot, { recursive: true, force: true });
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("resolveDescriptorPathForInstalledPackage resolves descriptor from ancestor node_modules", async () => {
|
|
74
|
-
const installRoot = await createFixtureRoot("kernel-package-descriptor-hoisted-");
|
|
75
|
-
try {
|
|
76
|
-
const appRoot = path.join(installRoot, "node_modules", "@example", "app");
|
|
77
|
-
const descriptorPath = path.join(
|
|
78
|
-
installRoot,
|
|
79
|
-
"node_modules",
|
|
80
|
-
"@jskit-ai",
|
|
81
|
-
"shell-web",
|
|
82
|
-
"package.descriptor.mjs"
|
|
83
|
-
);
|
|
84
|
-
await mkdir(appRoot, { recursive: true });
|
|
85
|
-
await writeDescriptorFile(descriptorPath, "export default { packageId: \"@jskit-ai/shell-web\" };\n");
|
|
86
|
-
|
|
87
|
-
const resolvedDescriptorPath = await resolveDescriptorPathForInstalledPackage({
|
|
88
|
-
appRoot,
|
|
89
|
-
packageId: "@jskit-ai/shell-web",
|
|
90
|
-
installedPackageState: {},
|
|
91
|
-
required: true
|
|
92
|
-
});
|
|
93
|
-
assert.equal(resolvedDescriptorPath, descriptorPath);
|
|
94
|
-
} finally {
|
|
95
|
-
await rm(installRoot, { recursive: true, force: true });
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test("resolveDescriptorPathForInstalledPackage resolves descriptor using jskit-cli descriptorPath fallback", async () => {
|
|
100
|
-
const appRoot = await createFixtureRoot("kernel-package-descriptor-jskit-root-");
|
|
101
|
-
try {
|
|
102
|
-
const descriptorPath = path.join(
|
|
103
|
-
appRoot,
|
|
104
|
-
"node_modules",
|
|
105
|
-
"@jskit-ai",
|
|
106
|
-
"jskit-cli",
|
|
107
|
-
"descriptors",
|
|
108
|
-
"example.descriptor.mjs"
|
|
109
|
-
);
|
|
110
|
-
await writeDescriptorFile(descriptorPath, "export default { packageId: \"@example/test\" };\n");
|
|
111
|
-
|
|
112
|
-
const resolvedDescriptorPath = await resolveDescriptorPathForInstalledPackage({
|
|
113
|
-
appRoot,
|
|
114
|
-
packageId: "@example/test",
|
|
115
|
-
installedPackageState: {
|
|
116
|
-
source: {
|
|
117
|
-
descriptorPath: "descriptors/example.descriptor.mjs"
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
required: true
|
|
121
|
-
});
|
|
122
|
-
assert.equal(resolvedDescriptorPath, descriptorPath);
|
|
123
|
-
} finally {
|
|
124
|
-
await rm(appRoot, { recursive: true, force: true });
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test("loadInstalledPackageDescriptor loads descriptor payload once resolved", async () => {
|
|
129
|
-
const appRoot = await createFixtureRoot("kernel-package-descriptor-load-");
|
|
130
|
-
try {
|
|
131
|
-
const descriptorPath = path.join(appRoot, "node_modules", "@example", "ready", "package.descriptor.mjs");
|
|
132
|
-
await writeDescriptorFile(descriptorPath, "export default { packageId: \"@example/ready\", version: \"1.0.0\" };\n");
|
|
133
|
-
|
|
134
|
-
const descriptorRecord = await loadInstalledPackageDescriptor({
|
|
135
|
-
appRoot,
|
|
136
|
-
packageId: "@example/ready",
|
|
137
|
-
installedPackageState: {},
|
|
138
|
-
required: true
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
assert.equal(descriptorRecord.descriptorPath, descriptorPath);
|
|
142
|
-
assert.equal(descriptorRecord.descriptor.packageId, "@example/ready");
|
|
143
|
-
assert.equal(descriptorRecord.descriptor.version, "1.0.0");
|
|
144
|
-
} finally {
|
|
145
|
-
await rm(appRoot, { recursive: true, force: true });
|
|
146
|
-
}
|
|
147
|
-
});
|