@holochain/hc-spin 0.200.4 → 0.200.5
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/dist/main/index.js +72 -18
- package/package.json +15 -3
- package/src/main/index.ts +15 -0
package/dist/main/index.js
CHANGED
|
@@ -7,11 +7,11 @@ const commander = require("commander");
|
|
|
7
7
|
const contextMenu = require("electron-context-menu");
|
|
8
8
|
const split = require("split");
|
|
9
9
|
const childProcess = require("child_process");
|
|
10
|
-
const msgpack = require("@msgpack/msgpack");
|
|
11
10
|
const url = require("url");
|
|
12
11
|
const utils = require("@electron-toolkit/utils");
|
|
13
12
|
const net$1 = require("node:net");
|
|
14
13
|
const os = require("node:os");
|
|
14
|
+
const msgpack = require("@msgpack/msgpack");
|
|
15
15
|
const require$$0$3 = require("events");
|
|
16
16
|
const require$$1$1 = require("https");
|
|
17
17
|
const require$$2$1 = require("http");
|
|
@@ -11735,25 +11735,34 @@ function validateCliArgs(cliArgs, cliOpts, appDataRootDir) {
|
|
|
11735
11735
|
appId,
|
|
11736
11736
|
holochainPath,
|
|
11737
11737
|
numAgents,
|
|
11738
|
+
networkSeed: cliOpts.networkSeed,
|
|
11738
11739
|
uiSource: cliOpts.uiPath ? { type: "path", path: cliOpts.uiPath } : cliOpts.uiPort ? { type: "port", port: cliOpts.uiPort } : { type: "path", path: path.join(appDataRootDir, "apps", appId, "ui") },
|
|
11740
|
+
singalingUrl: cliOpts.signalingUrl,
|
|
11741
|
+
bootstrapUrl: cliOpts.bootstrapUrl,
|
|
11739
11742
|
happOrWebhappPath: isHapp ? { type: "happ", path: happOrWebhappPath } : { type: "webhapp", path: happOrWebhappPath }
|
|
11740
11743
|
};
|
|
11741
11744
|
}
|
|
11742
11745
|
const rustUtils = require("@holochain/hc-spin-rust-utils");
|
|
11743
11746
|
const cli = new commander.Command();
|
|
11744
|
-
cli.name("hc-spin").description("CLI to run Holochain
|
|
11747
|
+
cli.name("hc-spin").description("CLI to run Holochain aps during development.").version(`0.200.4 (for holochain 0.2.x)`).argument(
|
|
11745
11748
|
"<path>",
|
|
11746
11749
|
"Path to .webhapp or .happ file to launch. If a .happ file is passed, either a UI path must be specified via --ui-path or a port pointing to a localhost server via --ui-port"
|
|
11747
11750
|
).option(
|
|
11748
11751
|
"--app-id <string>",
|
|
11749
11752
|
"Install the app with a specific app id. By default the app id is derived from the name of the .webhapp/.happ file that you pass but this option allows you to set it explicitly"
|
|
11753
|
+
).option(
|
|
11754
|
+
"--bootstrap-url <url>",
|
|
11755
|
+
"Url of the bootstrap server to use. By default, hc spin spins up a local development bootstrap server for you but this argument allows you to specify a custom one."
|
|
11750
11756
|
).option("--holochain-path <path>", "Set the path to the holochain binary [default: holochain].").addOption(
|
|
11751
11757
|
new commander.Option("-n, --num-agents <number>", "How many agents to spawn the app for.").argParser(
|
|
11752
11758
|
parseInt
|
|
11753
11759
|
)
|
|
11754
|
-
).option("--ui-path <path>", "Path to the folder containing the index.html of the webhapp's UI.").option(
|
|
11760
|
+
).option("--network-seed <string>", "Install the app with a specific network seed.").option("--ui-path <path>", "Path to the folder containing the index.html of the webhapp's UI.").option(
|
|
11755
11761
|
"--ui-port <number>",
|
|
11756
11762
|
"Port pointing to a localhost dev server that serves your UI assets."
|
|
11763
|
+
).option(
|
|
11764
|
+
"--signaling-url <url>",
|
|
11765
|
+
"Url of the signaling server to use. By default, hc spin spins up a local development signaling server for you but this argument allows you to specify a custom one."
|
|
11757
11766
|
);
|
|
11758
11767
|
cli.parse();
|
|
11759
11768
|
const rl = require("readline").createInterface({
|
|
@@ -11827,7 +11836,36 @@ const handleSignZomeCallLegacy = async (e, request) => {
|
|
|
11827
11836
|
return Promise.reject("Agent public key unauthorized.");
|
|
11828
11837
|
return windowInfo.zomeCallSigner.signZomeCall(request);
|
|
11829
11838
|
};
|
|
11830
|
-
async function
|
|
11839
|
+
async function startLocalServices() {
|
|
11840
|
+
const localServicesHandle = childProcess__namespace.spawn("hc", ["run-local-services"]);
|
|
11841
|
+
return new Promise((resolve) => {
|
|
11842
|
+
let bootStrapUrl;
|
|
11843
|
+
let signalUrl;
|
|
11844
|
+
let bootstrapRunning = false;
|
|
11845
|
+
let signalRunnig = false;
|
|
11846
|
+
localServicesHandle.stdout.pipe(split()).on("data", async (line) => {
|
|
11847
|
+
console.log(`[hc-spin] | [hc run-local-services]: ${line}`);
|
|
11848
|
+
if (line.includes("HC BOOTSTRAP - ADDR:")) {
|
|
11849
|
+
bootStrapUrl = line.split("# HC BOOTSTRAP - ADDR:")[1].trim();
|
|
11850
|
+
}
|
|
11851
|
+
if (line.includes("HC SIGNAL - ADDR:")) {
|
|
11852
|
+
signalUrl = line.split("# HC SIGNAL - ADDR:")[1].trim();
|
|
11853
|
+
}
|
|
11854
|
+
if (line.includes("HC BOOTSTRAP - RUNNING")) {
|
|
11855
|
+
bootstrapRunning = true;
|
|
11856
|
+
}
|
|
11857
|
+
if (line.includes("HC SIGNAL - RUNNING")) {
|
|
11858
|
+
signalRunnig = true;
|
|
11859
|
+
}
|
|
11860
|
+
if (bootstrapRunning && signalRunnig)
|
|
11861
|
+
resolve([bootStrapUrl, signalUrl]);
|
|
11862
|
+
});
|
|
11863
|
+
localServicesHandle.stderr.pipe(split()).on("data", async (line) => {
|
|
11864
|
+
console.log(`[hc-spin] | [hc run-local-services] ERROR: ${line}`);
|
|
11865
|
+
});
|
|
11866
|
+
});
|
|
11867
|
+
}
|
|
11868
|
+
async function spawnSandboxes(nAgents, happPath, bootStrapUrl, signalUrl, appId, networkSeed) {
|
|
11831
11869
|
const generateArgs = [
|
|
11832
11870
|
"sandbox",
|
|
11833
11871
|
"--piped",
|
|
@@ -11835,18 +11873,22 @@ async function spawnSandboxes(nAgents, happPath, appId) {
|
|
|
11835
11873
|
"--num-sandboxes",
|
|
11836
11874
|
nAgents.toString(),
|
|
11837
11875
|
"--app-id",
|
|
11838
|
-
appId
|
|
11876
|
+
appId,
|
|
11877
|
+
"--run"
|
|
11839
11878
|
];
|
|
11840
|
-
|
|
11841
|
-
let appPortsString = "";
|
|
11879
|
+
let appPorts = "";
|
|
11842
11880
|
for (var i = 1; i <= nAgents; i++) {
|
|
11843
11881
|
const appPort = await getPorts();
|
|
11844
|
-
|
|
11845
|
-
|
|
11882
|
+
appPorts += `${appPort},`;
|
|
11883
|
+
}
|
|
11884
|
+
generateArgs.push(appPorts.slice(0, appPorts.length - 1));
|
|
11885
|
+
if (networkSeed) {
|
|
11886
|
+
generateArgs.push("--network-seed");
|
|
11887
|
+
generateArgs.push(networkSeed);
|
|
11846
11888
|
}
|
|
11847
|
-
generateArgs.push("--
|
|
11848
|
-
generateArgs.push(happPath, "network", "mdns");
|
|
11889
|
+
generateArgs.push(happPath, "network", "--bootstrap", bootStrapUrl, "webrtc", signalUrl);
|
|
11849
11890
|
let readyConductors = 0;
|
|
11891
|
+
const portsInfo = {};
|
|
11850
11892
|
const sandboxPaths = [];
|
|
11851
11893
|
const sandboxHandle = childProcess__namespace.spawn("hc", generateArgs);
|
|
11852
11894
|
sandboxHandle.stdin.write("pass");
|
|
@@ -11858,10 +11900,17 @@ async function spawnSandboxes(nAgents, happPath, appId) {
|
|
|
11858
11900
|
const sanboxPath = line.split("\x1B[1;4;48;5;254;38;5;4m")[1].split("\x1B[0m \x1B[1m")[0].trim();
|
|
11859
11901
|
sandboxPaths.push(sanboxPath);
|
|
11860
11902
|
}
|
|
11861
|
-
if (line.includes("
|
|
11903
|
+
if (line.includes("lair-keystore connection_url")) {
|
|
11904
|
+
line.split("#")[2].trim();
|
|
11905
|
+
}
|
|
11906
|
+
if (line.includes("Conductor launched")) {
|
|
11907
|
+
const split1 = line.split("{");
|
|
11908
|
+
const ports = JSON.parse(`{${split1[1]}`);
|
|
11909
|
+
const conductorNum = split1[0].split("#!")[1].trim();
|
|
11910
|
+
portsInfo[conductorNum] = ports;
|
|
11862
11911
|
readyConductors += 1;
|
|
11863
11912
|
if (readyConductors === nAgents)
|
|
11864
|
-
resolve([sandboxHandle, sandboxPaths,
|
|
11913
|
+
resolve([sandboxHandle, sandboxPaths, portsInfo]);
|
|
11865
11914
|
}
|
|
11866
11915
|
});
|
|
11867
11916
|
sandboxHandle.stderr.pipe(split()).on("data", async (line) => {
|
|
@@ -11883,12 +11932,14 @@ electron.app.whenReady().then(async () => {
|
|
|
11883
11932
|
happTargetDir
|
|
11884
11933
|
);
|
|
11885
11934
|
}
|
|
11886
|
-
const [
|
|
11935
|
+
const [bootstrapUrl, signalingUrl] = await startLocalServices();
|
|
11936
|
+
const [sandboxHandle, sandboxPaths, portsInfo] = await spawnSandboxes(
|
|
11887
11937
|
CLI_OPTS.numAgents,
|
|
11888
11938
|
happTargetDir ? happTargetDir : CLI_OPTS.happOrWebhappPath.path,
|
|
11939
|
+
CLI_OPTS.bootstrapUrl ? CLI_OPTS.bootstrapUrl : bootstrapUrl,
|
|
11940
|
+
CLI_OPTS.singalingUrl ? CLI_OPTS.singalingUrl : signalingUrl,
|
|
11889
11941
|
CLI_OPTS.appId
|
|
11890
11942
|
);
|
|
11891
|
-
console.log("Got app ports: ", appPorts);
|
|
11892
11943
|
const lairUrls = [];
|
|
11893
11944
|
sandboxPaths.forEach((sandbox) => {
|
|
11894
11945
|
const conductorConfigPath = path.join(sandbox, "conductor-config.yaml");
|
|
@@ -11905,14 +11956,15 @@ electron.app.whenReady().then(async () => {
|
|
|
11905
11956
|
SANDBOX_PROCESSES.push(sandboxHandle);
|
|
11906
11957
|
for (var i = 0; i < cli.opts().numAgents; i++) {
|
|
11907
11958
|
const zomeCallSigner = await rustUtils.ZomeCallSigner.connect(lairUrls[i], "pass");
|
|
11908
|
-
const
|
|
11959
|
+
const appPort = portsInfo[i].app_ports[0];
|
|
11960
|
+
const appWs = await AppWebsocket.connect(new URL(`ws://127.0.0.1:${appPort}`));
|
|
11909
11961
|
const appInfo = await appWs.appInfo({ installed_app_id: CLI_OPTS.appId });
|
|
11910
11962
|
const happWindow = await createHappWindow(
|
|
11911
11963
|
CLI_OPTS.uiSource,
|
|
11912
11964
|
CLI_OPTS.happOrWebhappPath,
|
|
11913
11965
|
CLI_OPTS.appId,
|
|
11914
11966
|
i + 1,
|
|
11915
|
-
|
|
11967
|
+
appPort,
|
|
11916
11968
|
DATA_ROOT_DIR
|
|
11917
11969
|
);
|
|
11918
11970
|
WINDOW_INFO_MAP[happWindow.webContents.id] = {
|
|
@@ -11922,7 +11974,9 @@ electron.app.whenReady().then(async () => {
|
|
|
11922
11974
|
}
|
|
11923
11975
|
});
|
|
11924
11976
|
electron.app.on("window-all-closed", () => {
|
|
11925
|
-
|
|
11977
|
+
if (process.platform !== "darwin") {
|
|
11978
|
+
electron.app.quit();
|
|
11979
|
+
}
|
|
11926
11980
|
});
|
|
11927
11981
|
electron.app.on("quit", () => {
|
|
11928
11982
|
fs.writeFileSync(
|
package/package.json
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holochain/hc-spin",
|
|
3
|
-
"version": "0.200.
|
|
3
|
+
"version": "0.200.5",
|
|
4
4
|
"description": "CLI to run Holochain aps during development.",
|
|
5
5
|
"author": "matthme",
|
|
6
6
|
"homepage": "https://developer.holochain.org",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/holochain/hc-spin.git"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"holochain",
|
|
13
|
+
"developer",
|
|
14
|
+
"tools",
|
|
15
|
+
"tooling",
|
|
16
|
+
"developer-tools",
|
|
17
|
+
"cli"
|
|
18
|
+
],
|
|
7
19
|
"license": "MIT",
|
|
8
20
|
"main": "out/main/index.js",
|
|
9
21
|
"bin": {
|
|
@@ -23,12 +35,12 @@
|
|
|
23
35
|
"@electron-toolkit/preload": "^3.0.0",
|
|
24
36
|
"@electron-toolkit/utils": "^3.0.0",
|
|
25
37
|
"@holochain/client": "^0.16.3",
|
|
38
|
+
"@holochain/hc-spin-rust-utils": "0.200.2",
|
|
39
|
+
"@msgpack/msgpack": "^2.8.0",
|
|
26
40
|
"commander": "11.1.0",
|
|
27
41
|
"electron": "^28.1.1",
|
|
28
42
|
"electron-context-menu": "3.6.1",
|
|
29
43
|
"get-port": "7.0.0",
|
|
30
|
-
"@holochain/hc-spin-rust-utils": "0.200.2",
|
|
31
|
-
"@msgpack/msgpack": "^2.8.0",
|
|
32
44
|
"nanoid": "5.0.4",
|
|
33
45
|
"split": "1.0.1"
|
|
34
46
|
},
|
package/src/main/index.ts
CHANGED
|
@@ -61,6 +61,21 @@ cli.parse();
|
|
|
61
61
|
// console.log('Got CLI opts: ', cli.opts());
|
|
62
62
|
// console.log('Got CLI args: ', cli.args);
|
|
63
63
|
|
|
64
|
+
// In nix shell and on Windows SIGINT does not seem to be emitted so it is read from the command line instead.
|
|
65
|
+
// https://stackoverflow.com/questions/10021373/what-is-the-windows-equivalent-of-process-onsigint-in-node-js
|
|
66
|
+
const rl = require('readline').createInterface({
|
|
67
|
+
input: process.stdin,
|
|
68
|
+
output: process.stdout,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
rl.on('SIGINT', function () {
|
|
72
|
+
process.emit('SIGINT');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
process.on('SIGINT', () => {
|
|
76
|
+
app.quit();
|
|
77
|
+
});
|
|
78
|
+
|
|
64
79
|
// Garbage collect unused directories of previous runs
|
|
65
80
|
const files = fs.readdirSync(app.getPath('temp'));
|
|
66
81
|
const hcSpinFolders = files.filter((file) => file.startsWith(`hc-spin-`));
|