@sharpe-jupyter/connect 0.2.0 → 0.3.0
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 +75 -17
- 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
|
[
|
|
@@ -130,9 +180,10 @@ function startJupyter(port2) {
|
|
|
130
180
|
"--ServerApp.token=",
|
|
131
181
|
"--ServerApp.password=",
|
|
132
182
|
"--ServerApp.allow_remote_access=True",
|
|
133
|
-
"--ServerApp.disable_check_xsrf=True"
|
|
183
|
+
"--ServerApp.disable_check_xsrf=True",
|
|
184
|
+
'--ServerApp.jpserver_extensions={"sharpe_log_handler.handler": true}'
|
|
134
185
|
],
|
|
135
|
-
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
186
|
+
{ stdio: ["ignore", "pipe", "pipe"], env }
|
|
136
187
|
);
|
|
137
188
|
}
|
|
138
189
|
function parseJupyterLine(line) {
|
|
@@ -321,12 +372,12 @@ function App({ connectionCode: connectionCode2, port: port2 }) {
|
|
|
321
372
|
let cancelled = false;
|
|
322
373
|
async function run() {
|
|
323
374
|
try {
|
|
324
|
-
await ensureCloudflared();
|
|
375
|
+
await Promise.all([ensureCloudflared(), ensureRipgrep()]);
|
|
325
376
|
} catch {
|
|
326
377
|
if (cancelled) return;
|
|
327
378
|
setSetupStep("error");
|
|
328
379
|
setError({
|
|
329
|
-
message: "Could not set up
|
|
380
|
+
message: "Could not set up required tools.",
|
|
330
381
|
hint: "Check your internet connection and try again."
|
|
331
382
|
});
|
|
332
383
|
return;
|
|
@@ -368,7 +419,7 @@ function App({ connectionCode: connectionCode2, port: port2 }) {
|
|
|
368
419
|
if (cancelled) return;
|
|
369
420
|
pushEvent("Installing Jupyter...");
|
|
370
421
|
const installResult = await new Promise((resolve) => {
|
|
371
|
-
const proc2 = installPackages(["jupyter", "jupyter-resource-usage"]);
|
|
422
|
+
const proc2 = installPackages(["jupyter", "jupyter-resource-usage", "sharpe-log-handler"]);
|
|
372
423
|
proc2.on("error", (err) => resolve(err.message));
|
|
373
424
|
proc2.on("exit", (code) => resolve(code === 0 ? null : "install-failed"));
|
|
374
425
|
});
|
|
@@ -608,7 +659,14 @@ Close whatever is using it and try again, or use a different port:
|
|
|
608
659
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
609
660
|
setupStep === "done" && /* @__PURE__ */ jsx(Step, { status: "done", label: "Setting up" }),
|
|
610
661
|
setupStep === "error" && /* @__PURE__ */ jsx(Step, { status: "error", label: "Setting up" }),
|
|
611
|
-
jupyterStep === "done" && /* @__PURE__ */ jsx(
|
|
662
|
+
jupyterStep === "done" && /* @__PURE__ */ jsx(
|
|
663
|
+
Step,
|
|
664
|
+
{
|
|
665
|
+
status: "done",
|
|
666
|
+
label: "Notebook server running",
|
|
667
|
+
detail: `http://localhost:${port2}`
|
|
668
|
+
}
|
|
669
|
+
),
|
|
612
670
|
jupyterStep === "error" && /* @__PURE__ */ jsx(Step, { status: "error", label: "Could not start notebook server" }),
|
|
613
671
|
tunnelStep === "error" && /* @__PURE__ */ jsx(Step, { status: "error", label: "Connecting to Sharpe" })
|
|
614
672
|
] }),
|