bavitutor 0.1.1 → 0.1.3
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/README.md +8 -1
- package/dist/bavitutor.mjs +110 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,14 @@ npx bavitutor
|
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
That's all: it downloads BaviTutor, serves it on <http://localhost:4100> and
|
|
19
|
-
opens your browser. Data stays on your machine in `~/.bavitutor`.
|
|
19
|
+
opens your browser. Data stays on your machine in `~/.bavitutor`. If 4100 is
|
|
20
|
+
taken it moves to the next free port, and if BaviTutor is already running it
|
|
21
|
+
opens that one.
|
|
22
|
+
|
|
23
|
+
It always runs the newest version: on start it asks npm, and if a newer one is
|
|
24
|
+
out it starts that one instead, through npx or vpx like you did. (vpx inside a
|
|
25
|
+
pnpm project would otherwise reuse its download for a day.) `--no-update` skips
|
|
26
|
+
this.
|
|
20
27
|
|
|
21
28
|
Requirements: Node 24+, [Vite+](https://viteplus.dev) (`vp`), and a logged-in
|
|
22
29
|
[Claude Code](https://claude.com/claude-code) install (the Claude Agent SDK
|
package/dist/bavitutor.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { createServer } from "node:http";
|
|
|
8
8
|
import { connect, createServer as createServer$1 } from "node:net";
|
|
9
9
|
import * as NodeCrypto from "node:crypto";
|
|
10
10
|
import * as NFS from "node:fs";
|
|
11
|
-
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
12
12
|
import * as OS from "node:os";
|
|
13
13
|
import { homedir, tmpdir } from "node:os";
|
|
14
14
|
import * as Path from "node:path";
|
|
@@ -46583,7 +46583,8 @@ const codeByLiteral = {
|
|
|
46583
46583
|
const fromLiteral = (literal) => codeByLiteral[literal];
|
|
46584
46584
|
//#endregion
|
|
46585
46585
|
//#region package.json
|
|
46586
|
-
var
|
|
46586
|
+
var name = "bavitutor";
|
|
46587
|
+
var version$1 = "0.1.3";
|
|
46587
46588
|
/**
|
|
46588
46589
|
* Default Server-Sent Events encoder.
|
|
46589
46590
|
*
|
|
@@ -61758,6 +61759,7 @@ Options:
|
|
|
61758
61759
|
--host <host> interface to listen on (default: ${DEFAULT_HOST}, this machine only)
|
|
61759
61760
|
--data-dir <dir> database and settings (default: ~/.bavitutor)
|
|
61760
61761
|
--no-open don't open the browser
|
|
61762
|
+
--no-update don't switch to a newer version from npm
|
|
61761
61763
|
-v, --version print the version
|
|
61762
61764
|
-h, --help print this help
|
|
61763
61765
|
|
|
@@ -61780,6 +61782,10 @@ const parseOptions = () => {
|
|
|
61780
61782
|
type: "boolean",
|
|
61781
61783
|
default: true
|
|
61782
61784
|
},
|
|
61785
|
+
update: {
|
|
61786
|
+
type: "boolean",
|
|
61787
|
+
default: true
|
|
61788
|
+
},
|
|
61783
61789
|
version: {
|
|
61784
61790
|
type: "boolean",
|
|
61785
61791
|
short: "v"
|
|
@@ -61926,6 +61932,88 @@ const choosePort = async (requested, isExplicit, host) => {
|
|
|
61926
61932
|
}
|
|
61927
61933
|
return fail([`Ports ${requested}-${requested + SPARE_PORTS} are all in use.`, "Pick a free one: bavitutor --port <port>"]);
|
|
61928
61934
|
};
|
|
61935
|
+
/** The version npm calls latest, or undefined when npm doesn't answer quickly. */
|
|
61936
|
+
const latestVersion = async () => {
|
|
61937
|
+
if (process.env["NO_UPDATE_NOTIFIER"]) return;
|
|
61938
|
+
try {
|
|
61939
|
+
const response = await fetch(`https://registry.npmjs.org/${name}/latest`, { signal: AbortSignal.timeout(2e3) });
|
|
61940
|
+
const body = await response.json();
|
|
61941
|
+
return response.ok && body !== null && typeof body === "object" && "version" in body && typeof body.version === "string" ? body.version : void 0;
|
|
61942
|
+
} catch {
|
|
61943
|
+
return;
|
|
61944
|
+
}
|
|
61945
|
+
};
|
|
61946
|
+
const isNewer = (candidate, current) => {
|
|
61947
|
+
const parts = (version) => (version.split("-")[0] ?? "").split(".").map(Number);
|
|
61948
|
+
const [next, now] = [parts(candidate), parts(current)];
|
|
61949
|
+
const difference = [
|
|
61950
|
+
0,
|
|
61951
|
+
1,
|
|
61952
|
+
2
|
|
61953
|
+
].map((i) => (next[i] ?? 0) - (now[i] ?? 0)).find((delta) => delta !== 0);
|
|
61954
|
+
return difference !== void 0 && difference > 0;
|
|
61955
|
+
};
|
|
61956
|
+
/**
|
|
61957
|
+
* How to start another version the way this one was started: npx, and vpx
|
|
61958
|
+
* outside a pnpm project, run `npm exec`; vpx inside one runs `pnpm dlx`,
|
|
61959
|
+
* which reuses what it downloaded for a day. An exact version is always
|
|
61960
|
+
* fetched. Undefined for a global install or a checkout's own build.
|
|
61961
|
+
*/
|
|
61962
|
+
const relaunchCommand = (version) => {
|
|
61963
|
+
const runner = process.env["npm_execpath"];
|
|
61964
|
+
const spec = `${name}@${version}`;
|
|
61965
|
+
const args = process.argv.slice(2);
|
|
61966
|
+
const runnerArgs = process.env["npm_command"] === "exec" ? [
|
|
61967
|
+
"exec",
|
|
61968
|
+
"--yes",
|
|
61969
|
+
`--package=${spec}`,
|
|
61970
|
+
"--",
|
|
61971
|
+
name,
|
|
61972
|
+
...args
|
|
61973
|
+
] : process.env["npm_command"] === "dlx" ? [
|
|
61974
|
+
"dlx",
|
|
61975
|
+
spec,
|
|
61976
|
+
...args
|
|
61977
|
+
] : void 0;
|
|
61978
|
+
if (!runner || runnerArgs === void 0) return;
|
|
61979
|
+
return /\.[cm]?js$/.test(runner) ? [process.execPath, [runner, ...runnerArgs]] : [runner, runnerArgs];
|
|
61980
|
+
};
|
|
61981
|
+
/** Set for the newer version, which deletes the file once its code runs. */
|
|
61982
|
+
const RELAUNCH_MARKER = "BAVI_RELAUNCH_MARKER";
|
|
61983
|
+
/**
|
|
61984
|
+
* Runs the newer version in this terminal and resolves with its exit code,
|
|
61985
|
+
* or undefined if it never started (say npm can't serve it yet).
|
|
61986
|
+
*/
|
|
61987
|
+
const runNewer = (command, args) => new Promise((done) => {
|
|
61988
|
+
const marker = join(tmpdir(), `bavitutor-relaunch-${process.pid}`);
|
|
61989
|
+
writeFileSync(marker, "");
|
|
61990
|
+
const waitForChild = () => {};
|
|
61991
|
+
process.on("SIGINT", waitForChild);
|
|
61992
|
+
const finish = (code) => {
|
|
61993
|
+
process.off("SIGINT", waitForChild);
|
|
61994
|
+
const hasStarted = !existsSync(marker);
|
|
61995
|
+
rmSync(marker, { force: true });
|
|
61996
|
+
done(hasStarted ? code : void 0);
|
|
61997
|
+
};
|
|
61998
|
+
const child = spawn(command, args, {
|
|
61999
|
+
stdio: "inherit",
|
|
62000
|
+
env: {
|
|
62001
|
+
...process.env,
|
|
62002
|
+
[RELAUNCH_MARKER]: marker
|
|
62003
|
+
}
|
|
62004
|
+
});
|
|
62005
|
+
child.once("error", () => finish(void 0));
|
|
62006
|
+
child.once("exit", (code) => finish(code ?? 0));
|
|
62007
|
+
});
|
|
62008
|
+
/** Where starting the newest version wasn't possible, says how to. */
|
|
62009
|
+
const sayIfOutdated = (latest) => {
|
|
62010
|
+
if (latest !== void 0 && isNewer(latest, version$1)) {
|
|
62011
|
+
say(`BaviTutor ${latest} is out (this is ${version$1}). To update,`);
|
|
62012
|
+
say(`stop this one and run: npx bavitutor@${latest}`);
|
|
62013
|
+
say(` or: vpx bavitutor@${latest}`);
|
|
62014
|
+
say();
|
|
62015
|
+
}
|
|
62016
|
+
};
|
|
61929
62017
|
const openBrowser = (url) => {
|
|
61930
62018
|
const [command, args] = process.platform === "win32" ? ["cmd.exe", [
|
|
61931
62019
|
"/d",
|
|
@@ -61957,6 +62045,23 @@ const main = async () => {
|
|
|
61957
62045
|
say(version$1);
|
|
61958
62046
|
return;
|
|
61959
62047
|
}
|
|
62048
|
+
const marker = process.env[RELAUNCH_MARKER];
|
|
62049
|
+
if (marker !== void 0) {
|
|
62050
|
+
rmSync(marker, { force: true });
|
|
62051
|
+
delete process.env[RELAUNCH_MARKER];
|
|
62052
|
+
}
|
|
62053
|
+
const latest = options.update && marker === void 0 ? await latestVersion() : void 0;
|
|
62054
|
+
const relaunch = latest !== void 0 && isNewer(latest, version$1) ? relaunchCommand(latest) : void 0;
|
|
62055
|
+
if (latest !== void 0 && relaunch !== void 0) {
|
|
62056
|
+
say(`BaviTutor ${latest} is out, starting it instead of ${version$1}`);
|
|
62057
|
+
const code = await runNewer(...relaunch);
|
|
62058
|
+
if (code !== void 0) {
|
|
62059
|
+
process.exitCode = code;
|
|
62060
|
+
return;
|
|
62061
|
+
}
|
|
62062
|
+
say(` couldn't start ${latest}, so staying on ${version$1}`);
|
|
62063
|
+
say();
|
|
62064
|
+
}
|
|
61960
62065
|
const dataDir = resolve(expandHome(options["data-dir"] ?? join(homedir(), ".bavitutor")));
|
|
61961
62066
|
mkdirSync(dataDir, { recursive: true });
|
|
61962
62067
|
const envFile = join(dataDir, ".env");
|
|
@@ -61997,7 +62102,9 @@ const main = async () => {
|
|
|
61997
62102
|
if (choice.isRunning) {
|
|
61998
62103
|
say();
|
|
61999
62104
|
say(`BaviTutor is already running at ${urlFor(choice.port)}`);
|
|
62105
|
+
say();
|
|
62000
62106
|
if (options.open) openBrowser(urlFor(choice.port));
|
|
62107
|
+
sayIfOutdated(latest);
|
|
62001
62108
|
return;
|
|
62002
62109
|
}
|
|
62003
62110
|
const port = choice.port;
|
|
@@ -62009,6 +62116,7 @@ const main = async () => {
|
|
|
62009
62116
|
say(`BaviTutor is running at ${url} (Ctrl+C to stop)`);
|
|
62010
62117
|
say();
|
|
62011
62118
|
if (options.open) openBrowser(url);
|
|
62119
|
+
sayIfOutdated(latest);
|
|
62012
62120
|
})).pipe(provide(makeServer({
|
|
62013
62121
|
port,
|
|
62014
62122
|
host,
|