@jskit-ai/jskit-cli 0.2.34 → 0.2.36
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/jskit-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.36",
|
|
4
4
|
"description": "Bundle and package orchestration CLI for JSKIT apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"test": "node --test"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@jskit-ai/jskit-catalog": "0.1.
|
|
24
|
-
"@jskit-ai/kernel": "0.1.
|
|
23
|
+
"@jskit-ai/jskit-catalog": "0.1.36",
|
|
24
|
+
"@jskit-ai/kernel": "0.1.28"
|
|
25
25
|
},
|
|
26
26
|
"engines": {
|
|
27
27
|
"node": "20.x"
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import {
|
|
3
|
+
mkdir,
|
|
4
|
+
readdir,
|
|
5
|
+
writeFile
|
|
6
|
+
} from "node:fs/promises";
|
|
2
7
|
import path from "node:path";
|
|
3
8
|
import { createCliError } from "../shared/cliError.js";
|
|
4
9
|
import { CLI_PACKAGE_ROOT } from "../shared/pathResolution.js";
|
|
@@ -8,8 +13,150 @@ import {
|
|
|
8
13
|
} from "./ioAndMigrations.js";
|
|
9
14
|
|
|
10
15
|
const LOCAL_WORKSPACE_PACKAGE_ROOTS = new Map();
|
|
16
|
+
const MATERIALIZED_PACKAGE_ROOTS = new Map();
|
|
11
17
|
let LOCAL_WORKSPACE_PACKAGE_ID_INDEX = null;
|
|
12
18
|
|
|
19
|
+
function isInternalCatalogPackageEntry(packageEntry = {}) {
|
|
20
|
+
return (
|
|
21
|
+
String(packageEntry?.sourceType || "").trim() === "catalog" &&
|
|
22
|
+
String(packageEntry?.packageId || "").trim().startsWith("@jskit-ai/")
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function encodePackageCacheSegment(value = "") {
|
|
27
|
+
return encodeURIComponent(String(value || "").trim() || "unknown");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function buildMaterializedCacheKey(packageEntry = {}) {
|
|
31
|
+
const packageId = String(packageEntry?.packageId || "").trim();
|
|
32
|
+
const version = String(packageEntry?.version || "").trim() || "latest";
|
|
33
|
+
return `${packageId}@${version}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function buildMaterializedInstallRoot({ appRoot, packageEntry }) {
|
|
37
|
+
const packageId = String(packageEntry?.packageId || "").trim();
|
|
38
|
+
const version = String(packageEntry?.version || "").trim() || "latest";
|
|
39
|
+
return path.resolve(
|
|
40
|
+
String(appRoot || "").trim(),
|
|
41
|
+
".jskit",
|
|
42
|
+
"cache",
|
|
43
|
+
"package-sources",
|
|
44
|
+
encodePackageCacheSegment(packageId),
|
|
45
|
+
encodePackageCacheSegment(version)
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function ensureMaterializedInstallWorkspace(installRoot) {
|
|
50
|
+
await mkdir(installRoot, { recursive: true });
|
|
51
|
+
const packageJsonPath = path.join(installRoot, "package.json");
|
|
52
|
+
if (await fileExists(packageJsonPath)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await writeFile(
|
|
57
|
+
packageJsonPath,
|
|
58
|
+
`${JSON.stringify(
|
|
59
|
+
{
|
|
60
|
+
name: "jskit-package-source-cache",
|
|
61
|
+
private: true,
|
|
62
|
+
type: "module"
|
|
63
|
+
},
|
|
64
|
+
null,
|
|
65
|
+
2
|
|
66
|
+
)}\n`,
|
|
67
|
+
"utf8"
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function installCatalogPackageIntoCache({ installRoot, packageEntry }) {
|
|
72
|
+
const packageId = String(packageEntry?.packageId || "").trim();
|
|
73
|
+
const version = String(packageEntry?.version || "").trim();
|
|
74
|
+
const packageSpec = version ? `${packageId}@${version}` : packageId;
|
|
75
|
+
await ensureMaterializedInstallWorkspace(installRoot);
|
|
76
|
+
|
|
77
|
+
await new Promise((resolve, reject) => {
|
|
78
|
+
const child = spawn(
|
|
79
|
+
"npm",
|
|
80
|
+
[
|
|
81
|
+
"install",
|
|
82
|
+
"--no-save",
|
|
83
|
+
"--ignore-scripts",
|
|
84
|
+
"--package-lock=false",
|
|
85
|
+
"--no-audit",
|
|
86
|
+
"--no-fund",
|
|
87
|
+
packageSpec
|
|
88
|
+
],
|
|
89
|
+
{
|
|
90
|
+
cwd: installRoot,
|
|
91
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
let stderr = "";
|
|
96
|
+
child.stderr.on("data", (chunk) => {
|
|
97
|
+
stderr += String(chunk || "");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
child.on("error", (error) => {
|
|
101
|
+
reject(
|
|
102
|
+
createCliError(
|
|
103
|
+
`Unable to materialize template source for ${packageId}: ${String(error?.message || error || "unknown error")}`
|
|
104
|
+
)
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
child.on("exit", (code) => {
|
|
108
|
+
if (code === 0) {
|
|
109
|
+
resolve();
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const detail = stderr.trim();
|
|
114
|
+
reject(
|
|
115
|
+
createCliError(
|
|
116
|
+
`Unable to materialize template source for ${packageId}. npm install failed` +
|
|
117
|
+
`${detail ? `: ${detail}` : "."}`
|
|
118
|
+
)
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function materializeCatalogPackageRoot({
|
|
125
|
+
packageEntry,
|
|
126
|
+
appRoot,
|
|
127
|
+
installCatalogPackage = installCatalogPackageIntoCache
|
|
128
|
+
} = {}) {
|
|
129
|
+
if (!isInternalCatalogPackageEntry(packageEntry)) {
|
|
130
|
+
return "";
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const packageId = String(packageEntry?.packageId || "").trim();
|
|
134
|
+
const cacheKey = buildMaterializedCacheKey(packageEntry);
|
|
135
|
+
if (MATERIALIZED_PACKAGE_ROOTS.has(cacheKey)) {
|
|
136
|
+
return MATERIALIZED_PACKAGE_ROOTS.get(cacheKey);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const installRoot = buildMaterializedInstallRoot({ appRoot, packageEntry });
|
|
140
|
+
const candidateRoot = path.join(installRoot, "node_modules", ...packageId.split("/"));
|
|
141
|
+
const descriptorPath = path.join(candidateRoot, "package.descriptor.mjs");
|
|
142
|
+
|
|
143
|
+
if (!(await fileExists(descriptorPath))) {
|
|
144
|
+
await installCatalogPackage({
|
|
145
|
+
installRoot,
|
|
146
|
+
packageEntry
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!(await fileExists(descriptorPath))) {
|
|
151
|
+
throw createCliError(
|
|
152
|
+
`Unable to resolve template source for ${packageId} after materialization. Missing package.descriptor.mjs in cache.`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
MATERIALIZED_PACKAGE_ROOTS.set(cacheKey, candidateRoot);
|
|
157
|
+
return candidateRoot;
|
|
158
|
+
}
|
|
159
|
+
|
|
13
160
|
async function resolvePackageRootFromNodeModules({ appRoot, packageId }) {
|
|
14
161
|
const normalizedAppRoot = path.resolve(String(appRoot || "").trim());
|
|
15
162
|
const normalizedPackageId = String(packageId || "").trim();
|
|
@@ -93,7 +240,11 @@ async function resolvePackageRootFromLocalWorkspace({ packageId }) {
|
|
|
93
240
|
return packageRoot;
|
|
94
241
|
}
|
|
95
242
|
|
|
96
|
-
async function resolvePackageTemplateRoot({
|
|
243
|
+
async function resolvePackageTemplateRoot({
|
|
244
|
+
packageEntry,
|
|
245
|
+
appRoot,
|
|
246
|
+
materializeCatalogRoot = materializeCatalogPackageRoot
|
|
247
|
+
} = {}) {
|
|
97
248
|
const packageRoot = String(packageEntry?.rootDir || "").trim();
|
|
98
249
|
if (packageRoot) {
|
|
99
250
|
return packageRoot;
|
|
@@ -114,6 +265,14 @@ async function resolvePackageTemplateRoot({ packageEntry, appRoot }) {
|
|
|
114
265
|
return localWorkspacePackageRoot;
|
|
115
266
|
}
|
|
116
267
|
|
|
268
|
+
const materializedCatalogPackageRoot = await materializeCatalogRoot({
|
|
269
|
+
packageEntry,
|
|
270
|
+
appRoot
|
|
271
|
+
});
|
|
272
|
+
if (materializedCatalogPackageRoot) {
|
|
273
|
+
return materializedCatalogPackageRoot;
|
|
274
|
+
}
|
|
275
|
+
|
|
117
276
|
throw createCliError(
|
|
118
277
|
`Unable to resolve local template source for ${String(packageEntry?.packageId || "unknown package")}. ` +
|
|
119
278
|
"Install it in node_modules or ensure it exists in the local jskit-ai workspace."
|
|
@@ -122,10 +281,12 @@ async function resolvePackageTemplateRoot({ packageEntry, appRoot }) {
|
|
|
122
281
|
|
|
123
282
|
async function cleanupMaterializedPackageRoots() {
|
|
124
283
|
LOCAL_WORKSPACE_PACKAGE_ROOTS.clear();
|
|
284
|
+
MATERIALIZED_PACKAGE_ROOTS.clear();
|
|
125
285
|
LOCAL_WORKSPACE_PACKAGE_ID_INDEX = null;
|
|
126
286
|
}
|
|
127
287
|
|
|
128
288
|
export {
|
|
129
289
|
cleanupMaterializedPackageRoots,
|
|
290
|
+
materializeCatalogPackageRoot,
|
|
130
291
|
resolvePackageTemplateRoot
|
|
131
292
|
};
|
|
@@ -75,6 +75,7 @@ async function runPackageGenerateCommand(
|
|
|
75
75
|
mergePackageRegistries,
|
|
76
76
|
resolvePackageIdFromRegistryOrNodeModules,
|
|
77
77
|
hydratePackageRegistryFromInstalledNodeModules,
|
|
78
|
+
resolvePackageTemplateRoot,
|
|
78
79
|
resolvePackageKind,
|
|
79
80
|
resolveGeneratorPrimarySubcommand,
|
|
80
81
|
hasGeneratorSubcommandDefinition,
|
|
@@ -231,8 +232,20 @@ async function runPackageGenerateCommand(
|
|
|
231
232
|
});
|
|
232
233
|
}
|
|
233
234
|
|
|
234
|
-
|
|
235
|
+
const templateRoot = await resolvePackageTemplateRoot({
|
|
235
236
|
packageEntry,
|
|
237
|
+
appRoot
|
|
238
|
+
});
|
|
239
|
+
const executablePackageEntry =
|
|
240
|
+
templateRoot === packageEntry.rootDir
|
|
241
|
+
? packageEntry
|
|
242
|
+
: {
|
|
243
|
+
...packageEntry,
|
|
244
|
+
rootDir: templateRoot
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
return runGeneratorSubcommand({
|
|
248
|
+
packageEntry: executablePackageEntry,
|
|
236
249
|
subcommandName,
|
|
237
250
|
subcommandArgs,
|
|
238
251
|
inlineOptions: options.inlineOptions,
|
|
@@ -16,6 +16,7 @@ function createCommandHandlerDeps(deps = {}) {
|
|
|
16
16
|
resolveInstalledPackageIdInput: deps.resolveInstalledPackageIdInput,
|
|
17
17
|
resolveInstalledNodeModulePackageEntry: deps.resolveInstalledNodeModulePackageEntry,
|
|
18
18
|
hydratePackageRegistryFromInstalledNodeModules: deps.hydratePackageRegistryFromInstalledNodeModules,
|
|
19
|
+
resolvePackageTemplateRoot: deps.resolvePackageTemplateRoot,
|
|
19
20
|
validateInlineOptionsForPackage: deps.validateInlineOptionsForPackage,
|
|
20
21
|
resolveLocalDependencyOrder: deps.resolveLocalDependencyOrder,
|
|
21
22
|
validatePlannedCapabilityClosure: deps.validatePlannedCapabilityClosure,
|
|
@@ -70,6 +70,7 @@ import {
|
|
|
70
70
|
validateInlineOptionsForPackage
|
|
71
71
|
} from "../cliRuntime/packageOptions.js";
|
|
72
72
|
import {
|
|
73
|
+
resolvePackageTemplateRoot,
|
|
73
74
|
cleanupMaterializedPackageRoots
|
|
74
75
|
} from "../cliRuntime/packageTemplateResolution.js";
|
|
75
76
|
import {
|
|
@@ -100,6 +101,7 @@ const commandHandlers = createCommandHandlers(
|
|
|
100
101
|
resolveInstalledPackageIdInput,
|
|
101
102
|
resolveInstalledNodeModulePackageEntry,
|
|
102
103
|
hydratePackageRegistryFromInstalledNodeModules,
|
|
104
|
+
resolvePackageTemplateRoot,
|
|
103
105
|
validateInlineOptionsForPackage,
|
|
104
106
|
resolveLocalDependencyOrder,
|
|
105
107
|
validatePlannedCapabilityClosure,
|