@sharpe-jupyter/connect 0.2.0 → 0.3.1
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/index.js +73 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import Spinner from "ink-spinner";
|
|
|
10
10
|
import { spawn as spawn2 } from "child_process";
|
|
11
11
|
|
|
12
12
|
// src/cloudflared.ts
|
|
13
|
-
import { createWriteStream, existsSync, mkdirSync, chmodSync } from "fs";
|
|
13
|
+
import { createWriteStream, existsSync, mkdirSync, chmodSync, unlinkSync } from "fs";
|
|
14
14
|
import { join } from "path";
|
|
15
15
|
import { homedir, platform, arch } from "os";
|
|
16
16
|
import { pipeline } from "stream/promises";
|
|
@@ -61,7 +61,7 @@ async function ensureCloudflared() {
|
|
|
61
61
|
fileStream
|
|
62
62
|
);
|
|
63
63
|
execSync(`tar -xzf "${tgzPath}" -C "${binDir}" cloudflared`, { stdio: "ignore" });
|
|
64
|
-
|
|
64
|
+
unlinkSync(tgzPath);
|
|
65
65
|
} else {
|
|
66
66
|
const fileStream = createWriteStream(binPath);
|
|
67
67
|
await pipeline(
|
|
@@ -75,6 +75,53 @@ async function ensureCloudflared() {
|
|
|
75
75
|
return { path: binPath, downloaded: true };
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
// src/ripgrep.ts
|
|
79
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, chmodSync as chmodSync2, unlinkSync as unlinkSync2, createWriteStream as createWriteStream2 } from "fs";
|
|
80
|
+
import { join as join2 } from "path";
|
|
81
|
+
import { homedir as homedir2, arch as arch2 } from "os";
|
|
82
|
+
import { pipeline as pipeline2 } from "stream/promises";
|
|
83
|
+
import { Readable as Readable2 } from "stream";
|
|
84
|
+
import { execSync as execSync2 } from "child_process";
|
|
85
|
+
var RIPGREP_VERSION = "15.1.0";
|
|
86
|
+
function getAssetName() {
|
|
87
|
+
const cpu = arch2();
|
|
88
|
+
const triple = cpu === "arm64" ? "aarch64-apple-darwin" : "x86_64-apple-darwin";
|
|
89
|
+
return `ripgrep-${RIPGREP_VERSION}-${triple}.tar.gz`;
|
|
90
|
+
}
|
|
91
|
+
function getBinDir2() {
|
|
92
|
+
return join2(homedir2(), ".sharpe", "bin");
|
|
93
|
+
}
|
|
94
|
+
function getRipgrepPath() {
|
|
95
|
+
return join2(getBinDir2(), "rg");
|
|
96
|
+
}
|
|
97
|
+
async function ensureRipgrep() {
|
|
98
|
+
const binPath = getRipgrepPath();
|
|
99
|
+
if (existsSync2(binPath)) {
|
|
100
|
+
return { path: binPath, downloaded: false };
|
|
101
|
+
}
|
|
102
|
+
const binDir = getBinDir2();
|
|
103
|
+
mkdirSync2(binDir, { recursive: true });
|
|
104
|
+
const assetName = getAssetName();
|
|
105
|
+
const url = `https://github.com/BurntSushi/ripgrep/releases/download/${RIPGREP_VERSION}/${assetName}`;
|
|
106
|
+
const response = await fetch(url, { redirect: "follow" });
|
|
107
|
+
if (!response.ok || !response.body) {
|
|
108
|
+
throw new Error(`Failed to download ripgrep: ${response.status} ${response.statusText}`);
|
|
109
|
+
}
|
|
110
|
+
const tgzPath = join2(binDir, assetName);
|
|
111
|
+
const fileStream = createWriteStream2(tgzPath);
|
|
112
|
+
await pipeline2(
|
|
113
|
+
Readable2.fromWeb(response.body),
|
|
114
|
+
fileStream
|
|
115
|
+
);
|
|
116
|
+
const dirName = assetName.replace(".tar.gz", "");
|
|
117
|
+
execSync2(`tar -xzf "${tgzPath}" -C "${binDir}" "${dirName}/rg"`, { stdio: "ignore" });
|
|
118
|
+
execSync2(`mv "${join2(binDir, dirName, "rg")}" "${binPath}"`, { stdio: "ignore" });
|
|
119
|
+
unlinkSync2(tgzPath);
|
|
120
|
+
execSync2(`rm -rf "${join2(binDir, dirName)}"`, { stdio: "ignore" });
|
|
121
|
+
chmodSync2(binPath, 493);
|
|
122
|
+
return { path: binPath, downloaded: true };
|
|
123
|
+
}
|
|
124
|
+
|
|
78
125
|
// src/health.ts
|
|
79
126
|
async function checkJupyterHealth(port2) {
|
|
80
127
|
try {
|
|
@@ -88,20 +135,22 @@ async function checkJupyterHealth(port2) {
|
|
|
88
135
|
}
|
|
89
136
|
|
|
90
137
|
// src/jupyter.ts
|
|
91
|
-
import { execSync as
|
|
92
|
-
import { existsSync as
|
|
93
|
-
import { join as
|
|
94
|
-
import { homedir as
|
|
95
|
-
var
|
|
138
|
+
import { execSync as execSync3, spawn } from "child_process";
|
|
139
|
+
import { existsSync as existsSync3 } from "fs";
|
|
140
|
+
import { join as join3 } from "path";
|
|
141
|
+
import { homedir as homedir3, platform as platform2 } from "os";
|
|
142
|
+
var SHARPE_DIR = join3(homedir3(), ".sharpe");
|
|
143
|
+
var VENV_DIR = join3(SHARPE_DIR, "venv");
|
|
144
|
+
var SHARPE_BIN_DIR = join3(SHARPE_DIR, "bin");
|
|
96
145
|
var IS_WIN = platform2() === "win32";
|
|
97
146
|
var BIN_DIR = IS_WIN ? "Scripts" : "bin";
|
|
98
147
|
function venvBin(name) {
|
|
99
|
-
return
|
|
148
|
+
return join3(VENV_DIR, BIN_DIR, IS_WIN ? `${name}.exe` : name);
|
|
100
149
|
}
|
|
101
150
|
function findPython() {
|
|
102
151
|
for (const cmd of ["python3", "python"]) {
|
|
103
152
|
try {
|
|
104
|
-
const version =
|
|
153
|
+
const version = execSync3(`${cmd} --version`, { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
105
154
|
if (version.startsWith("Python 3")) return cmd;
|
|
106
155
|
} catch {
|
|
107
156
|
}
|
|
@@ -109,10 +158,10 @@ function findPython() {
|
|
|
109
158
|
return null;
|
|
110
159
|
}
|
|
111
160
|
function venvExists() {
|
|
112
|
-
return
|
|
161
|
+
return existsSync3(venvBin("python"));
|
|
113
162
|
}
|
|
114
163
|
function createVenv(pythonCmd) {
|
|
115
|
-
|
|
164
|
+
execSync3(`${pythonCmd} -m venv "${VENV_DIR}"`, { stdio: "ignore" });
|
|
116
165
|
}
|
|
117
166
|
function installPackages(packages) {
|
|
118
167
|
return spawn(venvBin("pip"), ["install", "--quiet", ...packages], {
|
|
@@ -120,6 +169,7 @@ function installPackages(packages) {
|
|
|
120
169
|
});
|
|
121
170
|
}
|
|
122
171
|
function startJupyter(port2) {
|
|
172
|
+
const env = { ...process.env, PATH: `${SHARPE_BIN_DIR}:${process.env.PATH ?? ""}` };
|
|
123
173
|
return spawn(
|
|
124
174
|
venvBin("jupyter"),
|
|
125
175
|
[
|
|
@@ -132,7 +182,7 @@ function startJupyter(port2) {
|
|
|
132
182
|
"--ServerApp.allow_remote_access=True",
|
|
133
183
|
"--ServerApp.disable_check_xsrf=True"
|
|
134
184
|
],
|
|
135
|
-
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
185
|
+
{ stdio: ["ignore", "pipe", "pipe"], env }
|
|
136
186
|
);
|
|
137
187
|
}
|
|
138
188
|
function parseJupyterLine(line) {
|
|
@@ -321,12 +371,12 @@ function App({ connectionCode: connectionCode2, port: port2 }) {
|
|
|
321
371
|
let cancelled = false;
|
|
322
372
|
async function run() {
|
|
323
373
|
try {
|
|
324
|
-
await ensureCloudflared();
|
|
374
|
+
await Promise.all([ensureCloudflared(), ensureRipgrep()]);
|
|
325
375
|
} catch {
|
|
326
376
|
if (cancelled) return;
|
|
327
377
|
setSetupStep("error");
|
|
328
378
|
setError({
|
|
329
|
-
message: "Could not set up
|
|
379
|
+
message: "Could not set up required tools.",
|
|
330
380
|
hint: "Check your internet connection and try again."
|
|
331
381
|
});
|
|
332
382
|
return;
|
|
@@ -368,7 +418,7 @@ function App({ connectionCode: connectionCode2, port: port2 }) {
|
|
|
368
418
|
if (cancelled) return;
|
|
369
419
|
pushEvent("Installing Jupyter...");
|
|
370
420
|
const installResult = await new Promise((resolve) => {
|
|
371
|
-
const proc2 = installPackages(["jupyter", "jupyter-resource-usage"]);
|
|
421
|
+
const proc2 = installPackages(["jupyter", "jupyter-resource-usage", "sharpe-log-handler"]);
|
|
372
422
|
proc2.on("error", (err) => resolve(err.message));
|
|
373
423
|
proc2.on("exit", (code) => resolve(code === 0 ? null : "install-failed"));
|
|
374
424
|
});
|
|
@@ -608,7 +658,14 @@ Close whatever is using it and try again, or use a different port:
|
|
|
608
658
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
609
659
|
setupStep === "done" && /* @__PURE__ */ jsx(Step, { status: "done", label: "Setting up" }),
|
|
610
660
|
setupStep === "error" && /* @__PURE__ */ jsx(Step, { status: "error", label: "Setting up" }),
|
|
611
|
-
jupyterStep === "done" && /* @__PURE__ */ jsx(
|
|
661
|
+
jupyterStep === "done" && /* @__PURE__ */ jsx(
|
|
662
|
+
Step,
|
|
663
|
+
{
|
|
664
|
+
status: "done",
|
|
665
|
+
label: "Notebook server running",
|
|
666
|
+
detail: `http://localhost:${port2}`
|
|
667
|
+
}
|
|
668
|
+
),
|
|
612
669
|
jupyterStep === "error" && /* @__PURE__ */ jsx(Step, { status: "error", label: "Could not start notebook server" }),
|
|
613
670
|
tunnelStep === "error" && /* @__PURE__ */ jsx(Step, { status: "error", label: "Connecting to Sharpe" })
|
|
614
671
|
] }),
|