rshow 0.0.7 → 0.0.9
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.js +648 -82
- package/package.json +1 -1
- package/skills/rshow/SKILL.md +7 -5
- package/skills/rshow/reference/cli.md +13 -6
- package/skills/rshow/reference/dashboard.md +5 -5
- package/skills/rshow/reference/page-contract.md +2 -1
- package/skills/rshow/reference/pages.md +7 -7
- package/skills/rshow/reference/poster.md +5 -5
- package/skills/rshow/reference/project-page.md +5 -5
- package/skills/rshow/reference/reports.md +5 -5
- package/skills/rshow/reference/sketch.md +5 -5
- package/skills/rshow/reference/terminal.md +5 -5
- package/skills/rshow-slides/SKILL.md +8 -10
- package/worker/index.js +127 -76
- package/worker/migrations/0005_version_counters.sql +3 -0
- package/worker/migrations/0006_retired_slugs.sql +5 -0
package/dist/main.js
CHANGED
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
// src/main.ts
|
|
29
|
-
import
|
|
30
|
-
import
|
|
29
|
+
import path28 from "node:path";
|
|
30
|
+
import process25 from "node:process";
|
|
31
31
|
|
|
32
32
|
// src/binary.ts
|
|
33
33
|
import { mkdir, mkdtemp, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
@@ -38,7 +38,7 @@ import process from "node:process";
|
|
|
38
38
|
// src/version.ts
|
|
39
39
|
import { readFileSync } from "node:fs";
|
|
40
40
|
import { fileURLToPath } from "node:url";
|
|
41
|
-
var VERSION = true ? "0.0.
|
|
41
|
+
var VERSION = true ? "0.0.9" : versionFromPackage();
|
|
42
42
|
|
|
43
43
|
// src/binary.ts
|
|
44
44
|
var ASSET_MANIFEST = "assets.json";
|
|
@@ -382,8 +382,12 @@ var Client = class {
|
|
|
382
382
|
async patchArtifact(slug, patch) {
|
|
383
383
|
return (await this.send("PATCH", `/api/artifacts/${encodeURIComponent(slug)}`, { json: patch })).body;
|
|
384
384
|
}
|
|
385
|
-
async deleteArtifact(slug) {
|
|
386
|
-
await this.send("DELETE", `/api/artifacts/${encodeURIComponent(slug)}`);
|
|
385
|
+
async deleteArtifact(slug, force = false) {
|
|
386
|
+
await this.send("DELETE", `/api/artifacts/${encodeURIComponent(slug)}${force ? "?force=1" : ""}`);
|
|
387
|
+
}
|
|
388
|
+
async deleteVersion(slug, n, force = false) {
|
|
389
|
+
const pathname = `/api/artifacts/${encodeURIComponent(slug)}/versions/${n}${force ? "?force=1" : ""}`;
|
|
390
|
+
return (await this.send("DELETE", pathname)).body;
|
|
387
391
|
}
|
|
388
392
|
async putShare(slug, email, role) {
|
|
389
393
|
const pathname = `/api/artifacts/${encodeURIComponent(slug)}/shares/${encodeURIComponent(email)}`;
|
|
@@ -444,6 +448,7 @@ var SLUG_PATTERN = /^[a-z0-9][a-z0-9-]{0,62}$/;
|
|
|
444
448
|
var TAG_PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/;
|
|
445
449
|
var THEME_NAME_PATTERN = /^[a-z0-9-]{1,40}$/;
|
|
446
450
|
var THEME_VERSION_PATTERN = /^([a-z0-9-]{1,40})@([0-9]{1,9})$/;
|
|
451
|
+
var THEME_LATEST_PATTERN = /^([a-z0-9-]{1,40})@latest$/;
|
|
447
452
|
var DATA_KEY_PATTERN = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
448
453
|
var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
449
454
|
var TOKEN_PREFIX = "rsh_";
|
|
@@ -991,7 +996,9 @@ commands:
|
|
|
991
996
|
show <slug> artifact, versions and shares
|
|
992
997
|
share <slug> set mode or change shares
|
|
993
998
|
pin <slug> <n|live> serve version n, or live for the newest
|
|
994
|
-
delete <slug> --
|
|
999
|
+
delete <slug> [--version n] [--force] --yes
|
|
1000
|
+
delete an artifact, or one version of it
|
|
1001
|
+
upgrade [--check] update rshow to the newest release
|
|
995
1002
|
login [--url u] save the API token for this account
|
|
996
1003
|
logout [--url u] remove the saved token for a server
|
|
997
1004
|
completion <shell> print a completion script for bash, zsh or fish
|
|
@@ -1041,8 +1048,10 @@ usage error. --offline skips the theme version lookup on the art host.
|
|
|
1041
1048
|
errors:
|
|
1042
1049
|
no index.html at the root, unless theme.json makes the folder a theme
|
|
1043
1050
|
a local href, src, poster, srcset, CSS url() or @import with no file behind it
|
|
1044
|
-
a root-relative reference other than /_themes/<name>@<n>/<path>
|
|
1045
|
-
|
|
1051
|
+
a root-relative reference other than /_themes/<name>@<n>/<path> or
|
|
1052
|
+
/_themes/<name>@latest/<path>
|
|
1053
|
+
a /_themes/<name>@<n>/ path whose version the art host does not have, or an
|
|
1054
|
+
@latest whose theme it does not have
|
|
1046
1055
|
a script from a host other than cdnjs.cloudflare.com, cdn.jsdelivr.net,
|
|
1047
1056
|
unpkg.com, or one of those without an exact version (@1.2.3, /1.2.3/ on cdnjs)
|
|
1048
1057
|
a stylesheet from a host other than fonts.googleapis.com, cdn.jsdelivr.net,
|
|
@@ -1101,9 +1110,9 @@ Style warnings:
|
|
|
1101
1110
|
var PREVIEW_USAGE = `usage: rshow preview <dir> [--theme <dir>] [--offline] [--no-reload] [--port 4321]
|
|
1102
1111
|
|
|
1103
1112
|
Serves <dir> on 127.0.0.1: index.html for a folder, content types for files.
|
|
1104
|
-
Works offline: /_themes/<name>@<n>/
|
|
1105
|
-
theme, then from the built-in themes on disk,
|
|
1106
|
-
URL from config, which --offline turns off.
|
|
1113
|
+
Works offline: /_themes/<name>@<n>/ and /_themes/<name>@latest/ are served
|
|
1114
|
+
from --theme when it names that theme, then from the built-in themes on disk,
|
|
1115
|
+
and only then proxied to the art URL from config, which --offline turns off.
|
|
1107
1116
|
The page is reloaded on its own when a file changes; --no-reload turns that off.
|
|
1108
1117
|
Scripts that use <artifact>/_data/<key> get a local store in that same session.`;
|
|
1109
1118
|
var CONFIG_USAGE = `usage: rshow config [dir] [--offline]
|
|
@@ -1112,9 +1121,10 @@ Prints the merged config as JSON: ~/.config/rshow/config.json first, then
|
|
|
1112
1121
|
<dir>/rshow.json (default: the current folder). RSHOW_URL overrides url and
|
|
1113
1122
|
RSHOW_ART overrides art. <dir>/rshow.json also takes project and tags; later
|
|
1114
1123
|
files win. Run rshow init to write url and art.
|
|
1115
|
-
A theme with no version, or @latest,
|
|
1116
|
-
as <name>@<n>; when
|
|
1117
|
-
|
|
1124
|
+
A theme with no version, or @latest, prints as <name>@latest, and with the
|
|
1125
|
+
network its lookup adds theme_resolved as <name>@<n>; when the lookup fails a
|
|
1126
|
+
warning goes to stderr and the key is left out. --offline prints the loaded
|
|
1127
|
+
config as it is, and so does a config with no art host.
|
|
1118
1128
|
The token is RSHOW_TOKEN, else the token rshow login saved in the macOS
|
|
1119
1129
|
Keychain, the Linux keyring or a file with mode 600.`;
|
|
1120
1130
|
var INIT_USAGE = `usage: rshow init --url <admin-url> --art <viewer-url> [--theme <name>] [--force]
|
|
@@ -1174,11 +1184,11 @@ var THEME_PREVIEW_USAGE = `usage: rshow theme preview <dir> [--offline] [--no-re
|
|
|
1174
1184
|
|
|
1175
1185
|
Builds the theme folder into a temporary folder, serves that on 127.0.0.1 and
|
|
1176
1186
|
prints the URL of index.html, the preview page that shows every layout. The
|
|
1177
|
-
built folder answers /_themes/<name>@<n>/ and
|
|
1178
|
-
when the folder changes; --no-reload turns the
|
|
1179
|
-
another theme comes from the built-in themes
|
|
1180
|
-
from config, which --offline turns off. The
|
|
1181
|
-
server stops.`;
|
|
1187
|
+
built folder answers /_themes/<name>@<n>/ and /_themes/<name>@latest/ and is
|
|
1188
|
+
rebuilt, and the page reloaded, when the folder changes; --no-reload turns the
|
|
1189
|
+
reload off. A /_themes/ path for another theme comes from the built-in themes
|
|
1190
|
+
on disk, then from the art URL from config, which --offline turns off. The
|
|
1191
|
+
temporary folder goes when the server stops.`;
|
|
1182
1192
|
var THEME_PUBLISH_USAGE = `usage: rshow theme publish <dir> [--label l] [--build cmd] [--no-check] [--force]
|
|
1183
1193
|
|
|
1184
1194
|
<dir> needs theme.json with a name. The folder is published as theme-<name>,
|
|
@@ -1190,7 +1200,8 @@ built on top of its base theme, and the built folder is what gets published.
|
|
|
1190
1200
|
When the newest version already holds the built folder's paths and hashes, it
|
|
1191
1201
|
prints unchanged: theme-<name> is already v<n> and publishes nothing.
|
|
1192
1202
|
--force publishes a new version anyway.
|
|
1193
|
-
Prints /_themes/<name>@<n
|
|
1203
|
+
Prints /_themes/<name>@<n>/. Pages link /_themes/<name>@latest/ by default, so
|
|
1204
|
+
they follow every version you publish here.`;
|
|
1194
1205
|
var THEME_LIST_USAGE = `usage: rshow theme list
|
|
1195
1206
|
|
|
1196
1207
|
Lists artifacts whose slug starts with theme- and their served version.`;
|
|
@@ -1258,9 +1269,38 @@ var SHARE_USAGE = `usage: rshow share <slug> [--mode private|people|public] [--a
|
|
|
1258
1269
|
var PIN_USAGE = `usage: rshow pin <slug> <n|live>
|
|
1259
1270
|
|
|
1260
1271
|
Pins version n, or live to serve the newest version again.`;
|
|
1261
|
-
var DELETE_USAGE = `usage: rshow delete <slug> --yes
|
|
1272
|
+
var DELETE_USAGE = `usage: rshow delete <slug> [--version n] [--force] --yes
|
|
1273
|
+
|
|
1274
|
+
Deletes the artifact, or with --version n only that version, and needs --yes.
|
|
1275
|
+
A theme or a theme version also needs --force, because pages link to it.
|
|
1276
|
+
A pinned version and the only version of an artifact cannot be deleted.
|
|
1277
|
+
A public version can stay visible for up to 5 minutes after the delete, and a
|
|
1278
|
+
theme file for longer.`;
|
|
1279
|
+
var UPGRADE_USAGE = `usage: rshow upgrade [--check] [--version <x.y.z>] [--force]
|
|
1262
1280
|
|
|
1263
|
-
|
|
1281
|
+
Updates rshow to the newest release, or to the release --version names, which
|
|
1282
|
+
may be an older one.
|
|
1283
|
+
A single executable is replaced in place, and an npm global install runs
|
|
1284
|
+
npm install -g rshow@<version>.
|
|
1285
|
+
Any other install, such as a source checkout, an npx cache or a local
|
|
1286
|
+
dependency, is left alone and named with the tool that owns it.
|
|
1287
|
+
Running the command is the consent: there is no --yes.
|
|
1288
|
+
No config and no token are read, so it works before rshow init.
|
|
1289
|
+
|
|
1290
|
+
--check prints the current and the newest version and changes nothing, and
|
|
1291
|
+
exits 0 either way; --json prints {current, latest, upgrade_available}.
|
|
1292
|
+
A run prints upgraded <old> -> <new>, or already at <version>. --json prints
|
|
1293
|
+
{previous, version, upgraded, kind}, where kind is binary or npm.
|
|
1294
|
+
--version takes x.y.z with an optional leading v; --force reinstalls the same
|
|
1295
|
+
version, which is how a broken binary comes back.
|
|
1296
|
+
Skills that rshow installed are refreshed by the new rshow, and a bash, zsh or
|
|
1297
|
+
fish completion that is already there is replaced; RSHOW_NO_COMPLETIONS=1
|
|
1298
|
+
leaves the completions alone.
|
|
1299
|
+
RSHOW_DOWNLOAD_BASE downloads from a mirror instead of the release, and takes
|
|
1300
|
+
an http or https url; it cannot be used with --check.
|
|
1301
|
+
|
|
1302
|
+
A release older than this one has no upgrade command, so after a downgrade
|
|
1303
|
+
come back with curl -fsSL https://rslib.github.io/rshow/install.sh | sh.`;
|
|
1264
1304
|
var LOGIN_USAGE = `usage: rshow login [--url u]
|
|
1265
1305
|
|
|
1266
1306
|
Reads the token from stdin, checks it with the API, then saves it in the macOS
|
|
@@ -1954,27 +1994,27 @@ var sqrtTall = function sqrtTall2(extraVinculum, hLinePad2, viewBoxHeight) {
|
|
|
1954
1994
|
};
|
|
1955
1995
|
var sqrtPath = function sqrtPath2(size, extraVinculum, viewBoxHeight) {
|
|
1956
1996
|
extraVinculum = 1e3 * extraVinculum;
|
|
1957
|
-
var
|
|
1997
|
+
var path29 = "";
|
|
1958
1998
|
switch (size) {
|
|
1959
1999
|
case "sqrtMain":
|
|
1960
|
-
|
|
2000
|
+
path29 = sqrtMain(extraVinculum, hLinePad);
|
|
1961
2001
|
break;
|
|
1962
2002
|
case "sqrtSize1":
|
|
1963
|
-
|
|
2003
|
+
path29 = sqrtSize1(extraVinculum, hLinePad);
|
|
1964
2004
|
break;
|
|
1965
2005
|
case "sqrtSize2":
|
|
1966
|
-
|
|
2006
|
+
path29 = sqrtSize2(extraVinculum, hLinePad);
|
|
1967
2007
|
break;
|
|
1968
2008
|
case "sqrtSize3":
|
|
1969
|
-
|
|
2009
|
+
path29 = sqrtSize3(extraVinculum, hLinePad);
|
|
1970
2010
|
break;
|
|
1971
2011
|
case "sqrtSize4":
|
|
1972
|
-
|
|
2012
|
+
path29 = sqrtSize4(extraVinculum, hLinePad);
|
|
1973
2013
|
break;
|
|
1974
2014
|
case "sqrtTall":
|
|
1975
|
-
|
|
2015
|
+
path29 = sqrtTall(extraVinculum, hLinePad, viewBoxHeight);
|
|
1976
2016
|
}
|
|
1977
|
-
return
|
|
2017
|
+
return path29;
|
|
1978
2018
|
};
|
|
1979
2019
|
var innerPath = function innerPath2(name, height) {
|
|
1980
2020
|
switch (name) {
|
|
@@ -6188,8 +6228,8 @@ var svgData = {
|
|
|
6188
6228
|
};
|
|
6189
6229
|
var staticSvg = function staticSvg2(value, options) {
|
|
6190
6230
|
var _svgData$value = svgData[value], pathName = _svgData$value[0], width = _svgData$value[1], height = _svgData$value[2];
|
|
6191
|
-
var
|
|
6192
|
-
var svgNode = new SvgNode([
|
|
6231
|
+
var path29 = new PathNode(pathName);
|
|
6232
|
+
var svgNode = new SvgNode([path29], {
|
|
6193
6233
|
"width": makeEm(width),
|
|
6194
6234
|
"height": makeEm(height),
|
|
6195
6235
|
// Override CSS rule `.katex svg { width: 100% }`
|
|
@@ -7332,8 +7372,8 @@ var stretchySvg = function stretchySvg2(group, options) {
|
|
|
7332
7372
|
pathName = "tilde" + imgIndex;
|
|
7333
7373
|
}
|
|
7334
7374
|
}
|
|
7335
|
-
var
|
|
7336
|
-
var svgNode = new SvgNode([
|
|
7375
|
+
var path29 = new PathNode(pathName);
|
|
7376
|
+
var svgNode = new SvgNode([path29], {
|
|
7337
7377
|
"width": "100%",
|
|
7338
7378
|
"height": makeEm(_height),
|
|
7339
7379
|
"viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight,
|
|
@@ -8547,8 +8587,8 @@ var makeGlyphSpan = function makeGlyphSpan2(symbol, font, mode, options) {
|
|
|
8547
8587
|
};
|
|
8548
8588
|
var makeInner = function makeInner2(ch2, height, options) {
|
|
8549
8589
|
var width = fontMetricsData["Size4-Regular"][ch2.charCodeAt(0)] ? fontMetricsData["Size4-Regular"][ch2.charCodeAt(0)][4] : fontMetricsData["Size1-Regular"][ch2.charCodeAt(0)][4];
|
|
8550
|
-
var
|
|
8551
|
-
var svgNode = new SvgNode([
|
|
8590
|
+
var path29 = new PathNode("inner", innerPath(ch2, Math.round(1e3 * height)));
|
|
8591
|
+
var svgNode = new SvgNode([path29], {
|
|
8552
8592
|
"width": makeEm(width),
|
|
8553
8593
|
"height": makeEm(height),
|
|
8554
8594
|
// Override CSS rule `.katex svg { width: 100% }`
|
|
@@ -8717,10 +8757,10 @@ var makeStackedDelim = function makeStackedDelim2(delim, heightTotal, center, op
|
|
|
8717
8757
|
var midHeight = realHeightTotal - topHeightTotal - bottomHeightTotal;
|
|
8718
8758
|
var viewBoxHeight = Math.round(realHeightTotal * 1e3);
|
|
8719
8759
|
var pathStr = tallDelim(svgLabel, Math.round(midHeight * 1e3));
|
|
8720
|
-
var
|
|
8760
|
+
var path29 = new PathNode(svgLabel, pathStr);
|
|
8721
8761
|
var width = makeEm(viewBoxWidth / 1e3);
|
|
8722
8762
|
var height = makeEm(viewBoxHeight / 1e3);
|
|
8723
|
-
var svg = new SvgNode([
|
|
8763
|
+
var svg = new SvgNode([path29], {
|
|
8724
8764
|
"width": width,
|
|
8725
8765
|
"height": height,
|
|
8726
8766
|
"viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight
|
|
@@ -8761,8 +8801,8 @@ var makeStackedDelim = function makeStackedDelim2(delim, heightTotal, center, op
|
|
|
8761
8801
|
var vbPad = 80;
|
|
8762
8802
|
var emPad = 0.08;
|
|
8763
8803
|
var sqrtSvg = function sqrtSvg2(sqrtName, height, viewBoxHeight, extraVinculum, options) {
|
|
8764
|
-
var
|
|
8765
|
-
var pathNode = new PathNode(sqrtName,
|
|
8804
|
+
var path29 = sqrtPath(sqrtName, extraVinculum, viewBoxHeight);
|
|
8805
|
+
var pathNode = new PathNode(sqrtName, path29);
|
|
8766
8806
|
var svg = new SvgNode([pathNode], {
|
|
8767
8807
|
// Note: 1000:1 ratio of viewBox to document em width.
|
|
8768
8808
|
"width": "400em",
|
|
@@ -9261,8 +9301,8 @@ var htmlBuilder$7 = (group, options) => {
|
|
|
9261
9301
|
var angleHeight = inner2.height + inner2.depth + lineWeight + clearance;
|
|
9262
9302
|
inner2.style.paddingLeft = makeEm(angleHeight / 2 + lineWeight);
|
|
9263
9303
|
var viewBoxHeight = Math.floor(1e3 * angleHeight * scale);
|
|
9264
|
-
var
|
|
9265
|
-
var svgNode = new SvgNode([new PathNode("phase",
|
|
9304
|
+
var path29 = phasePath(viewBoxHeight);
|
|
9305
|
+
var svgNode = new SvgNode([new PathNode("phase", path29)], {
|
|
9266
9306
|
"width": "400em",
|
|
9267
9307
|
"height": makeEm(viewBoxHeight / 1e3),
|
|
9268
9308
|
"viewBox": "0 0 400000 " + viewBoxHeight,
|
|
@@ -13291,11 +13331,11 @@ var newcommand = (context, existsOK, nonexistsOK, skipIfExists) => {
|
|
|
13291
13331
|
throw new ParseError("\\newcommand's first argument must be a macro name");
|
|
13292
13332
|
}
|
|
13293
13333
|
var name = arg[0].text;
|
|
13294
|
-
var
|
|
13295
|
-
if (
|
|
13334
|
+
var exists3 = context.isDefined(name);
|
|
13335
|
+
if (exists3 && !existsOK) {
|
|
13296
13336
|
throw new ParseError("\\newcommand{" + name + "} attempting to redefine " + (name + "; use \\renewcommand"));
|
|
13297
13337
|
}
|
|
13298
|
-
if (!
|
|
13338
|
+
if (!exists3 && !nonexistsOK) {
|
|
13299
13339
|
throw new ParseError("\\renewcommand{" + name + "} when command " + name + " does not yet exist; use \\newcommand");
|
|
13300
13340
|
}
|
|
13301
13341
|
var numArgs = 0;
|
|
@@ -13313,7 +13353,7 @@ var newcommand = (context, existsOK, nonexistsOK, skipIfExists) => {
|
|
|
13313
13353
|
numArgs = parseInt(argText);
|
|
13314
13354
|
arg = context.consumeArg().tokens;
|
|
13315
13355
|
}
|
|
13316
|
-
if (!(
|
|
13356
|
+
if (!(exists3 && skipIfExists)) {
|
|
13317
13357
|
context.macros.set(name, {
|
|
13318
13358
|
tokens: arg,
|
|
13319
13359
|
numArgs
|
|
@@ -15984,7 +16024,7 @@ var EMOJI = new RegExp("\\p{Emoji_Presentation}", "gu");
|
|
|
15984
16024
|
var COLOR = /#[0-9a-f]{3,8}\b|\b(?:rgba?|hsla?)\([^()]*\)/gi;
|
|
15985
16025
|
var GOOGLE_URL = /fonts\.googleapis\.com\/[^"'\s)>]*/gi;
|
|
15986
16026
|
var GOOGLE_FAMILY = /[?&]family=([^&"'\s]+)/gi;
|
|
15987
|
-
var THEME_LINK = /\/_themes\/[a-z0-9][a-z0-9-]*@[0-9]
|
|
16027
|
+
var THEME_LINK = /\/_themes\/[a-z0-9][a-z0-9-]*@(?:[0-9]+|latest)\//i;
|
|
15988
16028
|
function stylePathSkipped(rel2) {
|
|
15989
16029
|
const parts2 = rel2.toLowerCase().split("/");
|
|
15990
16030
|
const name = parts2[parts2.length - 1] ?? "";
|
|
@@ -16372,7 +16412,7 @@ var VERSION_AT = /@[0-9]+\.[0-9]+\.[0-9]+/;
|
|
|
16372
16412
|
var VERSION_PATH = /\/[0-9]+\.[0-9]+\.[0-9]+\//;
|
|
16373
16413
|
var EXTERNAL = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
16374
16414
|
var IGNORED = /^(?:#|data:|blob:|mailto:|tel:|javascript:)/i;
|
|
16375
|
-
var THEME_REF = /^\/_themes\/([a-z0-9][a-z0-9-]*)@([0-9]+)\//;
|
|
16415
|
+
var THEME_REF = /^\/_themes\/([a-z0-9][a-z0-9-]*)@(latest|[0-9]+)\//;
|
|
16376
16416
|
var TAG_PATTERN2 = /<([a-zA-Z][a-zA-Z0-9:-]*)((?:[^>"']|"[^"]*"|'[^']*')*)>/g;
|
|
16377
16417
|
var ATTR_PATTERN = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
|
|
16378
16418
|
var CSS_URL = /url\(\s*(?:"([^"]*)"|'([^']*)'|([^)'"\s]*))\s*\)/gi;
|
|
@@ -16498,7 +16538,7 @@ function resolveRef(scan, file, raw, line) {
|
|
|
16498
16538
|
file,
|
|
16499
16539
|
line,
|
|
16500
16540
|
"error",
|
|
16501
|
-
`root-relative reference ${value} (only /_themes/<name>@<n>/ paths may start with a slash)`
|
|
16541
|
+
`root-relative reference ${value} (only /_themes/<name>@<n>/ or /_themes/<name>@latest/ paths may start with a slash)`
|
|
16502
16542
|
);
|
|
16503
16543
|
return;
|
|
16504
16544
|
}
|
|
@@ -17032,7 +17072,7 @@ function sameFiles(local, remote) {
|
|
|
17032
17072
|
const paths = Object.keys(local);
|
|
17033
17073
|
const other = remote;
|
|
17034
17074
|
if (paths.length !== Object.keys(other).length) return false;
|
|
17035
|
-
return paths.every((
|
|
17075
|
+
return paths.every((path29) => other[path29]?.hash === local[path29]?.hash);
|
|
17036
17076
|
}
|
|
17037
17077
|
function reportUnchanged(out, result) {
|
|
17038
17078
|
out.data({ unchanged: true, slug: result.slug, version: result.version.n });
|
|
@@ -17770,8 +17810,8 @@ function keyLine(text2, key2, mode) {
|
|
|
17770
17810
|
}
|
|
17771
17811
|
return 0;
|
|
17772
17812
|
}
|
|
17773
|
-
function finding(
|
|
17774
|
-
return { path:
|
|
17813
|
+
function finding(path29, line, severity, message) {
|
|
17814
|
+
return { path: path29, line: Math.max(1, line), severity, message };
|
|
17775
17815
|
}
|
|
17776
17816
|
function resolveValue(name, map, fallback) {
|
|
17777
17817
|
let current = map[name] ?? fallback[name];
|
|
@@ -18093,7 +18133,7 @@ async function handleTheme(req, res, session, raw, pathname, method) {
|
|
|
18093
18133
|
const rest = pathname.slice(PROXY_PREFIX.length);
|
|
18094
18134
|
const slash = rest.indexOf("/");
|
|
18095
18135
|
const segment = slash < 0 ? rest : rest.slice(0, slash);
|
|
18096
|
-
const match = THEME_VERSION_PATTERN.exec(segment);
|
|
18136
|
+
const match = THEME_VERSION_PATTERN.exec(segment) ?? THEME_LATEST_PATTERN.exec(segment);
|
|
18097
18137
|
if (match === null) {
|
|
18098
18138
|
if (session.art !== "" && !session.offline) {
|
|
18099
18139
|
await proxy(session.art, raw, method, res);
|
|
@@ -18488,15 +18528,16 @@ async function resolveTheme2(config) {
|
|
|
18488
18528
|
const theme = config.theme ?? "default";
|
|
18489
18529
|
const ref = themeRefOf(theme);
|
|
18490
18530
|
if (ref.version !== void 0 && ref.version !== "latest") return config;
|
|
18531
|
+
const latest = { ...config, theme: `${ref.name}@latest` };
|
|
18491
18532
|
if (config.art === void 0) {
|
|
18492
18533
|
warn("no art host configured; skipping theme version lookup");
|
|
18493
|
-
return config;
|
|
18534
|
+
return config.theme === void 0 ? config : latest;
|
|
18494
18535
|
}
|
|
18495
18536
|
try {
|
|
18496
|
-
return { ...
|
|
18537
|
+
return { ...latest, theme_resolved: await resolvedTheme(config.art, theme) };
|
|
18497
18538
|
} catch (err) {
|
|
18498
18539
|
warn(`cannot resolve theme ${ref.name}: ${messageOf8(err)}`);
|
|
18499
|
-
return config.theme === void 0 ? config :
|
|
18540
|
+
return config.theme === void 0 ? config : latest;
|
|
18500
18541
|
}
|
|
18501
18542
|
}
|
|
18502
18543
|
async function run4(argv, ctx) {
|
|
@@ -19156,8 +19197,8 @@ async function create(argv, ctx) {
|
|
|
19156
19197
|
if (baseDir === void 0) throw new UsageError(`no built-in theme: ${from}`);
|
|
19157
19198
|
const parent = path18.resolve(stringValue(args, "dir") ?? ".");
|
|
19158
19199
|
const target = path18.join(parent, name);
|
|
19159
|
-
const
|
|
19160
|
-
if (
|
|
19200
|
+
const exists3 = await stat13(target).catch(() => void 0);
|
|
19201
|
+
if (exists3 !== void 0) throw new UsageError(`${target} already exists`);
|
|
19161
19202
|
const values = await baseRoleValues(baseDir, ROLE_TOKENS);
|
|
19162
19203
|
const doc = { name, extends: from, tokens: {}, modeTokens: values };
|
|
19163
19204
|
await mkdir6(target, { recursive: true });
|
|
@@ -19473,13 +19514,35 @@ async function run12(argv, ctx) {
|
|
|
19473
19514
|
|
|
19474
19515
|
// src/commands/delete.ts
|
|
19475
19516
|
async function run13(argv, ctx) {
|
|
19476
|
-
const args = parseCommandArgs(
|
|
19517
|
+
const args = parseCommandArgs(
|
|
19518
|
+
argv,
|
|
19519
|
+
{ version: { type: "string" }, force: { type: "boolean" }, yes: { type: "boolean" } },
|
|
19520
|
+
1,
|
|
19521
|
+
1,
|
|
19522
|
+
DELETE_USAGE
|
|
19523
|
+
);
|
|
19477
19524
|
const slug = validateSlug(args.positionals[0]);
|
|
19525
|
+
const raw = stringValue(args, "version");
|
|
19526
|
+
let version2 = null;
|
|
19527
|
+
if (raw !== void 0) {
|
|
19528
|
+
if (!/^[0-9]+$/.test(raw) || Number(raw) < 1) {
|
|
19529
|
+
throw new UsageError(`expected a version number, got: ${raw}`);
|
|
19530
|
+
}
|
|
19531
|
+
version2 = Number(raw);
|
|
19532
|
+
}
|
|
19478
19533
|
if (!boolValue(args, "yes")) throw new UsageError(`delete needs --yes (try: ${usageLine(DELETE_USAGE)})`);
|
|
19479
19534
|
const api = await ctx.api();
|
|
19480
|
-
|
|
19481
|
-
|
|
19482
|
-
|
|
19535
|
+
const force = boolValue(args, "force");
|
|
19536
|
+
if (version2 === null) {
|
|
19537
|
+
await api.deleteArtifact(slug, force);
|
|
19538
|
+
ctx.out.data(null);
|
|
19539
|
+
ctx.out.line(`deleted: ${slug}`);
|
|
19540
|
+
return;
|
|
19541
|
+
}
|
|
19542
|
+
const artifact = await api.deleteVersion(slug, version2, force);
|
|
19543
|
+
ctx.out.data(artifact);
|
|
19544
|
+
ctx.out.line(`deleted: ${slug} v${version2}`);
|
|
19545
|
+
ctx.out.line(`served: ${artifact?.served === null || artifact?.served === void 0 ? "-" : artifact.served}`);
|
|
19483
19546
|
}
|
|
19484
19547
|
|
|
19485
19548
|
// src/commands/project.ts
|
|
@@ -22692,6 +22755,7 @@ var USAGE = {
|
|
|
22692
22755
|
delete: DELETE_USAGE,
|
|
22693
22756
|
login: LOGIN_USAGE,
|
|
22694
22757
|
logout: LOGOUT_USAGE,
|
|
22758
|
+
upgrade: UPGRADE_USAGE,
|
|
22695
22759
|
completion: COMPLETION_USAGE
|
|
22696
22760
|
};
|
|
22697
22761
|
var WHEN = {
|
|
@@ -22713,8 +22777,15 @@ function listLines(usage) {
|
|
|
22713
22777
|
if (start < 0) return [];
|
|
22714
22778
|
const out = [];
|
|
22715
22779
|
for (const line of lines.slice(start)) {
|
|
22716
|
-
if (
|
|
22717
|
-
|
|
22780
|
+
if (/^\s{2}\S/.test(line)) {
|
|
22781
|
+
out.push(line);
|
|
22782
|
+
continue;
|
|
22783
|
+
}
|
|
22784
|
+
if (out.length > 0 && /^\s{3,}\S/.test(line)) {
|
|
22785
|
+
out[out.length - 1] = `${out[out.length - 1].trimEnd()} ${line.trim()}`;
|
|
22786
|
+
continue;
|
|
22787
|
+
}
|
|
22788
|
+
break;
|
|
22718
22789
|
}
|
|
22719
22790
|
return out;
|
|
22720
22791
|
}
|
|
@@ -23061,6 +23132,7 @@ var SPECS = {
|
|
|
23061
23132
|
delete: { usage: DELETE_USAGE },
|
|
23062
23133
|
login: { usage: LOGIN_USAGE },
|
|
23063
23134
|
logout: { usage: LOGOUT_USAGE },
|
|
23135
|
+
upgrade: { usage: UPGRADE_USAGE },
|
|
23064
23136
|
completion: { usage: COMPLETION_USAGE, choices: [...SHELLS] }
|
|
23065
23137
|
};
|
|
23066
23138
|
function optionsOf(usage) {
|
|
@@ -23426,15 +23498,507 @@ async function run20(argv, ctx, platform = process21.platform) {
|
|
|
23426
23498
|
ctx.out.line(`logged in as ${email} (scope ${scope}) for ${url}, saved in ${store2.description}`);
|
|
23427
23499
|
}
|
|
23428
23500
|
|
|
23429
|
-
// src/commands/
|
|
23501
|
+
// src/commands/upgrade.ts
|
|
23502
|
+
import { realpath as realpath2 } from "node:fs/promises";
|
|
23503
|
+
import path27 from "node:path";
|
|
23504
|
+
import process23 from "node:process";
|
|
23505
|
+
|
|
23506
|
+
// src/upgrade.ts
|
|
23507
|
+
import { execFile, spawn as spawn6 } from "node:child_process";
|
|
23508
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
23509
|
+
import { createReadStream, createWriteStream } from "node:fs";
|
|
23510
|
+
import { chmod as chmod2, copyFile as copyFile2, lstat as lstat2, mkdtemp as mkdtemp5, readFile as readFile19, realpath, rename as rename3, rm as rm8, stat as stat15 } from "node:fs/promises";
|
|
23511
|
+
import path26 from "node:path";
|
|
23430
23512
|
import process22 from "node:process";
|
|
23431
|
-
|
|
23513
|
+
import { Readable } from "node:stream";
|
|
23514
|
+
import { pipeline } from "node:stream/promises";
|
|
23515
|
+
var REPO = "rslib/rshow";
|
|
23516
|
+
var NPM_HINT = "npm i -g rshow";
|
|
23517
|
+
var INSTALLER_ELSEWHERE = `curl -fsSL https://rslib.github.io/rshow/install.sh | RSHOW_INSTALL_DIR=$HOME/.local/bin sh`;
|
|
23518
|
+
var LATEST_URL = `https://github.com/${REPO}/releases/latest`;
|
|
23519
|
+
var RELEASES = `https://github.com/${REPO}/releases/download/v`;
|
|
23520
|
+
var TARGETS = ["linux-x64", "linux-arm64", "darwin-arm64"];
|
|
23521
|
+
var VERSION_PATTERN = /^v?([0-9]+\.[0-9]+\.[0-9]+)$/;
|
|
23522
|
+
var TAG_PATH = /\/tag\/v([0-9]+\.[0-9]+\.[0-9]+)$/;
|
|
23523
|
+
var LOOKUP_TIMEOUT_MS = 15e3;
|
|
23524
|
+
var DOWNLOAD_TIMEOUT_MS = 6e5;
|
|
23525
|
+
var UNPACK_TIMEOUT_MS = 12e4;
|
|
23526
|
+
var RUN_TIMEOUT_MS = 2e4;
|
|
23527
|
+
var NPM_TIMEOUT_MS = 3e5;
|
|
23528
|
+
var SKILLS_TIMEOUT_MS = 12e4;
|
|
23529
|
+
var UpgradeFailure = class extends Error {
|
|
23530
|
+
exit;
|
|
23531
|
+
constructor(message, exit = EXIT.api) {
|
|
23532
|
+
super(message);
|
|
23533
|
+
this.name = "UpgradeFailure";
|
|
23534
|
+
this.exit = exit;
|
|
23535
|
+
}
|
|
23536
|
+
};
|
|
23537
|
+
function messageOf12(err) {
|
|
23538
|
+
return err instanceof Error ? err.message : String(err);
|
|
23539
|
+
}
|
|
23540
|
+
function codeOf(err) {
|
|
23541
|
+
const code = typeof err === "object" && err !== null ? err.code : void 0;
|
|
23542
|
+
if (typeof code === "number") return `exit ${code}`;
|
|
23543
|
+
if (typeof code === "string" && code !== "") return code;
|
|
23544
|
+
return messageOf12(err);
|
|
23545
|
+
}
|
|
23546
|
+
function runProgram(file, args, options = {}) {
|
|
23547
|
+
return new Promise((resolve2, reject) => {
|
|
23548
|
+
const run23 = { timeout: options.timeoutMs, maxBuffer: 16 * 1024 * 1024 };
|
|
23549
|
+
execFile(file, [...args], run23, (err, stdout) => {
|
|
23550
|
+
if (err !== null) {
|
|
23551
|
+
reject(err);
|
|
23552
|
+
return;
|
|
23553
|
+
}
|
|
23554
|
+
resolve2(stdout);
|
|
23555
|
+
});
|
|
23556
|
+
});
|
|
23557
|
+
}
|
|
23558
|
+
function parseVersion(raw) {
|
|
23559
|
+
const found = VERSION_PATTERN.exec(raw.trim());
|
|
23560
|
+
if (found === null) throw new UsageError(`--version needs x.y.z, got: ${raw}`);
|
|
23561
|
+
return found[1];
|
|
23562
|
+
}
|
|
23563
|
+
function compareVersions(left, right) {
|
|
23564
|
+
const a = left.split(".").map(Number);
|
|
23565
|
+
const b = right.split(".").map(Number);
|
|
23566
|
+
for (let index = 0; index < 3; index += 1) {
|
|
23567
|
+
const diff = (a[index] ?? 0) - (b[index] ?? 0);
|
|
23568
|
+
if (diff !== 0) return diff < 0 ? -1 : 1;
|
|
23569
|
+
}
|
|
23570
|
+
return 0;
|
|
23571
|
+
}
|
|
23572
|
+
function targetOf2(platform, arch) {
|
|
23573
|
+
const name = `${platform}-${arch}`;
|
|
23574
|
+
return TARGETS.includes(name) ? name : void 0;
|
|
23575
|
+
}
|
|
23576
|
+
function releaseTagOf(location) {
|
|
23577
|
+
if (location === null || location.trim() === "") return void 0;
|
|
23578
|
+
let pathname;
|
|
23579
|
+
try {
|
|
23580
|
+
pathname = new URL(location, LATEST_URL).pathname;
|
|
23581
|
+
} catch {
|
|
23582
|
+
return void 0;
|
|
23583
|
+
}
|
|
23584
|
+
return TAG_PATH.exec(pathname)?.[1];
|
|
23585
|
+
}
|
|
23586
|
+
async function latestVersion(options) {
|
|
23587
|
+
const reply = await sendRequest(
|
|
23588
|
+
options.fetch,
|
|
23589
|
+
LATEST_URL,
|
|
23590
|
+
{ redirect: "manual", signal: AbortSignal.timeout(LOOKUP_TIMEOUT_MS) },
|
|
23591
|
+
options.env
|
|
23592
|
+
);
|
|
23593
|
+
const location = reply.headers.get("location");
|
|
23594
|
+
const version2 = releaseTagOf(location);
|
|
23595
|
+
if (version2 === void 0) {
|
|
23596
|
+
throw new UpgradeFailure(`${LATEST_URL} did not name a release (location: ${location ?? "none"})`);
|
|
23597
|
+
}
|
|
23598
|
+
return version2;
|
|
23599
|
+
}
|
|
23600
|
+
function mirrorOf(options) {
|
|
23601
|
+
const raw = (options.env.RSHOW_DOWNLOAD_BASE ?? "").trim();
|
|
23602
|
+
if (raw === "") return void 0;
|
|
23603
|
+
const base = raw.replace(/\/+$/, "");
|
|
23604
|
+
let protocol;
|
|
23605
|
+
try {
|
|
23606
|
+
protocol = new URL(base).protocol;
|
|
23607
|
+
} catch {
|
|
23608
|
+
throw new UsageError(`RSHOW_DOWNLOAD_BASE is not a url: ${raw}`);
|
|
23609
|
+
}
|
|
23610
|
+
if (protocol !== "http:" && protocol !== "https:") {
|
|
23611
|
+
throw new UsageError(`RSHOW_DOWNLOAD_BASE needs an http or https url, got: ${raw}`);
|
|
23612
|
+
}
|
|
23613
|
+
return base;
|
|
23614
|
+
}
|
|
23615
|
+
function otherError(options) {
|
|
23616
|
+
const from = options.install.argv1 ?? options.install.execPath;
|
|
23617
|
+
const version2 = options.wanted ?? "<version>";
|
|
23618
|
+
const where = from.split(path26.sep).join("/");
|
|
23619
|
+
if (where.includes("/_npx/")) {
|
|
23620
|
+
return new UsageError(`rshow runs from ${from}, an npx cache that npm owns; run npx rshow@${version2}`);
|
|
23621
|
+
}
|
|
23622
|
+
if (where.includes("/node_modules/")) {
|
|
23623
|
+
return new UsageError(
|
|
23624
|
+
`rshow runs from ${from}, a local dependency that npm owns; run npm install rshow@${version2} to update it`
|
|
23625
|
+
);
|
|
23626
|
+
}
|
|
23627
|
+
return new UsageError(`rshow runs from ${from}, a source checkout; update it with git pull and npm run build`);
|
|
23628
|
+
}
|
|
23629
|
+
function dataHome(env) {
|
|
23630
|
+
const xdg = (env.XDG_DATA_HOME ?? "").trim();
|
|
23631
|
+
return xdg !== "" ? xdg : path26.join(homeDir(env), ".local", "share");
|
|
23632
|
+
}
|
|
23633
|
+
function configHome(env) {
|
|
23634
|
+
const xdg = (env.XDG_CONFIG_HOME ?? "").trim();
|
|
23635
|
+
return xdg !== "" ? xdg : path26.join(homeDir(env), ".config");
|
|
23636
|
+
}
|
|
23637
|
+
function completionPaths(env) {
|
|
23638
|
+
const data = dataHome(env);
|
|
23639
|
+
const config = configHome(env);
|
|
23640
|
+
return [
|
|
23641
|
+
{ name: "rshow.bash", dst: path26.join(data, "bash-completion", "completions", "rshow") },
|
|
23642
|
+
{ name: "_rshow", dst: path26.join(data, "zsh", "site-functions", "_rshow") },
|
|
23643
|
+
{ name: "rshow.fish", dst: path26.join(config, "fish", "completions", "rshow.fish") }
|
|
23644
|
+
];
|
|
23645
|
+
}
|
|
23646
|
+
async function exists2(file) {
|
|
23647
|
+
return await stat15(file).catch(() => void 0) !== void 0;
|
|
23648
|
+
}
|
|
23649
|
+
function missingFile(name, url, named) {
|
|
23650
|
+
if (named === void 0) {
|
|
23651
|
+
return new UpgradeFailure(
|
|
23652
|
+
`this release has no ${name} (${url}); a new release attaches its binaries a few minutes after it appears, so try again`
|
|
23653
|
+
);
|
|
23654
|
+
}
|
|
23655
|
+
return new UpgradeFailure(
|
|
23656
|
+
`release v${named} has no ${name} (${url}); it may not exist, and a release before 0.0.6 has no tarball, so use the installer with RSHOW_VERSION=${named}`
|
|
23657
|
+
);
|
|
23658
|
+
}
|
|
23659
|
+
async function download(options, url, file, name, named) {
|
|
23660
|
+
const reply = await sendRequest(options.fetch, url, { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS) }, options.env);
|
|
23661
|
+
if (reply.status === 404) throw missingFile(name, url, named);
|
|
23662
|
+
if (reply.status !== 200 || reply.body === null) {
|
|
23663
|
+
throw new UpgradeFailure(`cannot download ${url}: HTTP ${reply.status}`);
|
|
23664
|
+
}
|
|
23665
|
+
try {
|
|
23666
|
+
await pipeline(Readable.fromWeb(reply.body), createWriteStream(file));
|
|
23667
|
+
} catch (err) {
|
|
23668
|
+
throw new UpgradeFailure(`cannot write ${file}: ${messageOf12(err)}`);
|
|
23669
|
+
}
|
|
23670
|
+
}
|
|
23671
|
+
function sumOf(text2, name) {
|
|
23672
|
+
for (const line of text2.split("\n")) {
|
|
23673
|
+
const parts2 = line.trim().split(/\s+/);
|
|
23674
|
+
if (parts2.length < 2) continue;
|
|
23675
|
+
if (parts2[1].replace(/^\*/, "") === name) return parts2[0];
|
|
23676
|
+
}
|
|
23677
|
+
return void 0;
|
|
23678
|
+
}
|
|
23679
|
+
async function sha256Of(file) {
|
|
23680
|
+
const hash = createHash3("sha256");
|
|
23681
|
+
await pipeline(createReadStream(file), hash);
|
|
23682
|
+
return hash.digest("hex");
|
|
23683
|
+
}
|
|
23684
|
+
async function checkSum(file, name, sumsFile) {
|
|
23685
|
+
const expected = sumOf(await readFile19(sumsFile, "utf8"), name);
|
|
23686
|
+
const actual = await sha256Of(file);
|
|
23687
|
+
if (expected === void 0) {
|
|
23688
|
+
throw new UpgradeFailure(`SHA256SUMS holds no line for ${name}, and the download is ${actual}`);
|
|
23689
|
+
}
|
|
23690
|
+
if (expected !== actual) {
|
|
23691
|
+
throw new UpgradeFailure(`checksum mismatch for ${name}: SHA256SUMS says ${expected}, the download is ${actual}`);
|
|
23692
|
+
}
|
|
23693
|
+
}
|
|
23694
|
+
async function unpack2(file, dir, tarball) {
|
|
23695
|
+
try {
|
|
23696
|
+
await runProgram("tar", ["-xzf", file, "-C", dir], { timeoutMs: UNPACK_TIMEOUT_MS });
|
|
23697
|
+
} catch (err) {
|
|
23698
|
+
throw new UpgradeFailure(`cannot unpack ${tarball}: ${codeOf(err)}`);
|
|
23699
|
+
}
|
|
23700
|
+
}
|
|
23701
|
+
async function printedVersion(file) {
|
|
23702
|
+
try {
|
|
23703
|
+
return (await runProgram(file, ["--version"], { timeoutMs: RUN_TIMEOUT_MS })).trim();
|
|
23704
|
+
} catch (err) {
|
|
23705
|
+
throw new UpgradeFailure(`the new rshow does not run (${codeOf(err)}); the old rshow is still in place`);
|
|
23706
|
+
}
|
|
23707
|
+
}
|
|
23708
|
+
async function replaceCompletions(options, dir, target) {
|
|
23709
|
+
if ((options.env.RSHOW_NO_COMPLETIONS ?? "").trim() === "1") return;
|
|
23710
|
+
for (const entry of completionPaths(options.env)) {
|
|
23711
|
+
const src = path26.join(dir, `rshow-${target}`, "completions", entry.name);
|
|
23712
|
+
try {
|
|
23713
|
+
if (!await exists2(entry.dst) || !await exists2(src)) continue;
|
|
23714
|
+
await copyFile2(src, entry.dst);
|
|
23715
|
+
} catch (err) {
|
|
23716
|
+
warn(`cannot replace the completion ${entry.dst}: ${messageOf12(err)}`);
|
|
23717
|
+
}
|
|
23718
|
+
}
|
|
23719
|
+
}
|
|
23720
|
+
function modeOf(target, statuses) {
|
|
23721
|
+
const kinds = statuses.filter((entry) => entry.target === target).map((entry) => entry.state.kind);
|
|
23722
|
+
if (kinds.includes("copy")) return "copy";
|
|
23723
|
+
if (kinds.includes("link")) return "link";
|
|
23724
|
+
return void 0;
|
|
23725
|
+
}
|
|
23726
|
+
async function refreshSkills(options, file, prefix) {
|
|
23727
|
+
const targets = await detectedTargets(options.home);
|
|
23728
|
+
if (targets.length === 0) return;
|
|
23729
|
+
let source;
|
|
23730
|
+
try {
|
|
23731
|
+
source = await skillsSource(options.env);
|
|
23732
|
+
} catch {
|
|
23733
|
+
return;
|
|
23734
|
+
}
|
|
23735
|
+
if (source === void 0) return;
|
|
23736
|
+
const statuses = await skillsStatus({ home: options.home, source, targets });
|
|
23737
|
+
const groups = { copy: [], link: [] };
|
|
23738
|
+
for (const target of targets) {
|
|
23739
|
+
const mode = modeOf(target, statuses);
|
|
23740
|
+
if (mode !== void 0) groups[mode].push(target);
|
|
23741
|
+
}
|
|
23742
|
+
for (const mode of ["copy", "link"]) {
|
|
23743
|
+
if (groups[mode].length === 0) continue;
|
|
23744
|
+
try {
|
|
23745
|
+
await runProgram(file, [...prefix, "skills", "install", `--${mode}`, ...groups[mode]], {
|
|
23746
|
+
timeoutMs: SKILLS_TIMEOUT_MS
|
|
23747
|
+
});
|
|
23748
|
+
} catch (err) {
|
|
23749
|
+
warn(`the new rshow could not refresh the skills (${codeOf(err)}); run rshow skills install`);
|
|
23750
|
+
}
|
|
23751
|
+
}
|
|
23752
|
+
}
|
|
23753
|
+
function versionIn(printed) {
|
|
23754
|
+
return /^rshow ([0-9]+\.[0-9]+\.[0-9]+)/.exec(printed)?.[1];
|
|
23755
|
+
}
|
|
23756
|
+
async function replaceBinary(job, dest) {
|
|
23757
|
+
const dir = path26.dirname(dest);
|
|
23758
|
+
let tmp;
|
|
23759
|
+
try {
|
|
23760
|
+
tmp = await mkdtemp5(path26.join(dir, ".rshow-upgrade-"));
|
|
23761
|
+
} catch (err) {
|
|
23762
|
+
const code = err.code;
|
|
23763
|
+
if (code === "EACCES" || code === "EPERM" || code === "EROFS") {
|
|
23764
|
+
throw new UpgradeFailure(`${dir} is not writable; install elsewhere instead: ${INSTALLER_ELSEWHERE}`);
|
|
23765
|
+
}
|
|
23766
|
+
throw new UpgradeFailure(`cannot write next to ${dest}: ${messageOf12(err)}`);
|
|
23767
|
+
}
|
|
23768
|
+
try {
|
|
23769
|
+
const tarball = `rshow-${job.target}.tar.gz`;
|
|
23770
|
+
const file = path26.join(tmp, tarball);
|
|
23771
|
+
const sums = path26.join(tmp, "SHA256SUMS");
|
|
23772
|
+
const url = `${job.base}/${tarball}`;
|
|
23773
|
+
process22.stderr.write(`rshow: downloading ${url}
|
|
23774
|
+
`);
|
|
23775
|
+
await download(job.options, url, file, tarball, job.named);
|
|
23776
|
+
await download(job.options, `${job.base}/SHA256SUMS`, sums, "SHA256SUMS", job.named);
|
|
23777
|
+
await checkSum(file, tarball, sums);
|
|
23778
|
+
await unpack2(file, tmp, tarball);
|
|
23779
|
+
const folder = `rshow-${job.target}`;
|
|
23780
|
+
const unpacked = path26.join(tmp, folder, "rshow");
|
|
23781
|
+
const info = await lstat2(unpacked).catch(() => void 0);
|
|
23782
|
+
if (info === void 0) {
|
|
23783
|
+
throw new UpgradeFailure(`${tarball} holds no ${folder}/rshow; the old rshow is still in place`);
|
|
23784
|
+
}
|
|
23785
|
+
if (!info.isFile()) {
|
|
23786
|
+
throw new UpgradeFailure(`${tarball} holds a ${folder}/rshow that is not a file; the old rshow is still in place`);
|
|
23787
|
+
}
|
|
23788
|
+
await chmod2(unpacked, 493);
|
|
23789
|
+
const printed = await printedVersion(unpacked);
|
|
23790
|
+
let version2;
|
|
23791
|
+
if (job.version === void 0) {
|
|
23792
|
+
const found = versionIn(printed);
|
|
23793
|
+
if (found === void 0) {
|
|
23794
|
+
throw new UpgradeFailure(`the new rshow printed ${printed || "no version"}; the old rshow is still in place`);
|
|
23795
|
+
}
|
|
23796
|
+
if (!job.force && found === job.options.current) return { replaced: false, version: found };
|
|
23797
|
+
version2 = found;
|
|
23798
|
+
} else {
|
|
23799
|
+
if (!printed.startsWith(`rshow ${job.version}`)) {
|
|
23800
|
+
throw new UpgradeFailure(
|
|
23801
|
+
`the new rshow printed ${printed || "no version"}, not rshow ${job.version}; the old rshow is still in place`
|
|
23802
|
+
);
|
|
23803
|
+
}
|
|
23804
|
+
version2 = job.version;
|
|
23805
|
+
}
|
|
23806
|
+
await rename3(unpacked, dest);
|
|
23807
|
+
await replaceCompletions(job.options, tmp, job.target);
|
|
23808
|
+
return { replaced: true, version: version2 };
|
|
23809
|
+
} finally {
|
|
23810
|
+
await rm8(tmp, { recursive: true, force: true });
|
|
23811
|
+
}
|
|
23812
|
+
}
|
|
23813
|
+
async function installPath(options) {
|
|
23814
|
+
try {
|
|
23815
|
+
return await realpath(options.install.execPath);
|
|
23816
|
+
} catch (err) {
|
|
23817
|
+
throw new UpgradeFailure(`cannot read ${options.install.execPath}: ${messageOf12(err)}`);
|
|
23818
|
+
}
|
|
23819
|
+
}
|
|
23820
|
+
function targetOrFail(options) {
|
|
23821
|
+
const platform = options.platform ?? process22.platform;
|
|
23822
|
+
const arch = options.arch ?? process22.arch;
|
|
23823
|
+
const target = targetOf2(platform, arch);
|
|
23824
|
+
if (target === void 0) {
|
|
23825
|
+
throw new UsageError(`no rshow single executable for ${platform}-${arch}; run ${NPM_HINT}`);
|
|
23826
|
+
}
|
|
23827
|
+
return target;
|
|
23828
|
+
}
|
|
23829
|
+
async function installBinary(job) {
|
|
23830
|
+
const dest = await installPath(job.options);
|
|
23831
|
+
const outcome = await replaceBinary(job, dest);
|
|
23832
|
+
if (!outcome.replaced) return { status: "current", kind: "binary", version: outcome.version };
|
|
23833
|
+
await refreshSkills(job.options, dest, []);
|
|
23834
|
+
return { status: "upgraded", kind: "binary", previous: job.options.current, version: outcome.version };
|
|
23835
|
+
}
|
|
23836
|
+
function runNpm(args) {
|
|
23837
|
+
return new Promise((resolve2, reject) => {
|
|
23838
|
+
const child = spawn6("npm", [...args], { stdio: ["ignore", 2, 2], timeout: NPM_TIMEOUT_MS });
|
|
23839
|
+
child.on("error", (err) => {
|
|
23840
|
+
child.emit("exit", null, null);
|
|
23841
|
+
reject(err);
|
|
23842
|
+
});
|
|
23843
|
+
child.on("close", (code, signal) => {
|
|
23844
|
+
if (code === 0) {
|
|
23845
|
+
resolve2();
|
|
23846
|
+
return;
|
|
23847
|
+
}
|
|
23848
|
+
if (code !== null) {
|
|
23849
|
+
const err = Object.assign(new Error(`npm exited ${code}`), { code });
|
|
23850
|
+
reject(err);
|
|
23851
|
+
return;
|
|
23852
|
+
}
|
|
23853
|
+
reject(new Error(`npm stopped on ${signal ?? "a timeout"}`));
|
|
23854
|
+
});
|
|
23855
|
+
});
|
|
23856
|
+
}
|
|
23857
|
+
async function npmInstall(version2) {
|
|
23858
|
+
const command = `npm install -g rshow@${version2}`;
|
|
23859
|
+
try {
|
|
23860
|
+
await runNpm(["install", "-g", `rshow@${version2}`]);
|
|
23861
|
+
} catch (err) {
|
|
23862
|
+
const code = err.code;
|
|
23863
|
+
if (typeof code === "number") throw new UpgradeFailure(`${command} failed (exit ${code})`, code);
|
|
23864
|
+
throw new UpgradeFailure(`cannot run npm (${codeOf(err)}); run ${command}`, EXIT.usage);
|
|
23865
|
+
}
|
|
23866
|
+
}
|
|
23867
|
+
async function upgrade(options) {
|
|
23868
|
+
const mirror = mirrorOf(options);
|
|
23869
|
+
const force = options.force === true;
|
|
23870
|
+
const kind = options.install.kind;
|
|
23871
|
+
if (options.check === true) {
|
|
23872
|
+
if (mirror !== void 0) {
|
|
23873
|
+
throw new UsageError(`--check cannot be used with RSHOW_DOWNLOAD_BASE (${mirror}), which names no release`);
|
|
23874
|
+
}
|
|
23875
|
+
const latest = options.wanted ?? await latestVersion(options);
|
|
23876
|
+
return {
|
|
23877
|
+
status: "check",
|
|
23878
|
+
current: options.current,
|
|
23879
|
+
latest,
|
|
23880
|
+
upgrade: compareVersions(latest, options.current) > 0
|
|
23881
|
+
};
|
|
23882
|
+
}
|
|
23883
|
+
if (kind === "other") throw otherError(options);
|
|
23884
|
+
if (kind === "binary" && mirror !== void 0 && options.wanted === void 0) {
|
|
23885
|
+
return installBinary({ options, base: mirror, target: targetOrFail(options), force });
|
|
23886
|
+
}
|
|
23887
|
+
let version2 = options.wanted;
|
|
23888
|
+
if (version2 === void 0) {
|
|
23889
|
+
const latest = await latestVersion(options);
|
|
23890
|
+
if (compareVersions(latest, options.current) < 0) {
|
|
23891
|
+
return { status: "newer", kind, current: options.current, latest };
|
|
23892
|
+
}
|
|
23893
|
+
version2 = latest;
|
|
23894
|
+
}
|
|
23895
|
+
if (version2 === options.current && !force) {
|
|
23896
|
+
return { status: "current", kind, version: version2 };
|
|
23897
|
+
}
|
|
23898
|
+
if (kind === "binary") {
|
|
23899
|
+
const base = mirror ?? `${RELEASES}${version2}`;
|
|
23900
|
+
return installBinary({ options, base, target: targetOrFail(options), version: version2, named: options.wanted, force });
|
|
23901
|
+
}
|
|
23902
|
+
await npmInstall(version2);
|
|
23903
|
+
const argv1 = options.install.argv1;
|
|
23904
|
+
if (argv1 !== void 0) await refreshSkills(options, process22.execPath, [argv1]);
|
|
23905
|
+
return { status: "upgraded", kind: "npm", previous: options.current, version: version2 };
|
|
23906
|
+
}
|
|
23907
|
+
function reportOf(result) {
|
|
23908
|
+
if (result.status === "check") {
|
|
23909
|
+
return {
|
|
23910
|
+
data: { current: result.current, latest: result.latest, upgrade_available: result.upgrade },
|
|
23911
|
+
lines: [`current: ${result.current}`, `latest: ${result.latest}`]
|
|
23912
|
+
};
|
|
23913
|
+
}
|
|
23914
|
+
if (result.status === "newer") {
|
|
23915
|
+
return {
|
|
23916
|
+
data: { previous: result.current, version: result.current, upgraded: false, kind: result.kind },
|
|
23917
|
+
lines: [`rshow: ${result.current} is newer than the newest release, ${result.latest}`]
|
|
23918
|
+
};
|
|
23919
|
+
}
|
|
23920
|
+
if (result.status === "current") {
|
|
23921
|
+
return {
|
|
23922
|
+
data: { previous: result.version, version: result.version, upgraded: false, kind: result.kind },
|
|
23923
|
+
lines: [`rshow: already at ${result.version}`]
|
|
23924
|
+
};
|
|
23925
|
+
}
|
|
23926
|
+
return {
|
|
23927
|
+
data: { previous: result.previous, version: result.version, upgraded: true, kind: result.kind },
|
|
23928
|
+
lines: [`rshow: upgraded ${result.previous} -> ${result.version}`]
|
|
23929
|
+
};
|
|
23930
|
+
}
|
|
23931
|
+
|
|
23932
|
+
// src/commands/upgrade.ts
|
|
23933
|
+
var TIMEOUT_MS2 = 6e4;
|
|
23934
|
+
function isUnder2(file, dir) {
|
|
23935
|
+
const rel2 = path27.relative(dir, file);
|
|
23936
|
+
return rel2 !== "" && rel2 !== ".." && !rel2.startsWith(`..${path27.sep}`) && !path27.isAbsolute(rel2);
|
|
23937
|
+
}
|
|
23938
|
+
async function npmRoot() {
|
|
23939
|
+
try {
|
|
23940
|
+
const root2 = (await runProgram("npm", ["root", "-g"], { timeoutMs: TIMEOUT_MS2 })).trim();
|
|
23941
|
+
return root2 === "" ? void 0 : await realpath2(root2);
|
|
23942
|
+
} catch {
|
|
23943
|
+
return void 0;
|
|
23944
|
+
}
|
|
23945
|
+
}
|
|
23946
|
+
async function installKind() {
|
|
23947
|
+
if (await isBinary()) return { kind: "binary", execPath: process23.execPath };
|
|
23948
|
+
const argv1 = process23.argv[1];
|
|
23949
|
+
const root2 = await npmRoot();
|
|
23950
|
+
if (root2 !== void 0 && argv1 !== void 0) {
|
|
23951
|
+
const script3 = await realpath2(argv1).catch(() => void 0);
|
|
23952
|
+
if (script3 !== void 0 && isUnder2(script3, root2)) {
|
|
23953
|
+
return { kind: "npm", execPath: process23.execPath, argv1: script3 };
|
|
23954
|
+
}
|
|
23955
|
+
}
|
|
23956
|
+
return { kind: "other", execPath: process23.execPath, argv1 };
|
|
23957
|
+
}
|
|
23958
|
+
async function run21(argv, ctx) {
|
|
23959
|
+
const args = parseCommandArgs(
|
|
23960
|
+
argv,
|
|
23961
|
+
{ check: { type: "boolean" }, version: { type: "string" }, force: { type: "boolean" } },
|
|
23962
|
+
0,
|
|
23963
|
+
0,
|
|
23964
|
+
UPGRADE_USAGE
|
|
23965
|
+
);
|
|
23966
|
+
const raw = stringValue(args, "version");
|
|
23967
|
+
const wanted = raw === void 0 ? void 0 : parseVersion(raw);
|
|
23968
|
+
const env = process23.env;
|
|
23969
|
+
let result;
|
|
23970
|
+
try {
|
|
23971
|
+
result = await upgrade({
|
|
23972
|
+
current: VERSION,
|
|
23973
|
+
wanted,
|
|
23974
|
+
check: boolValue(args, "check"),
|
|
23975
|
+
force: boolValue(args, "force"),
|
|
23976
|
+
install: await installKind(),
|
|
23977
|
+
fetch,
|
|
23978
|
+
env,
|
|
23979
|
+
home: homeDir(env)
|
|
23980
|
+
});
|
|
23981
|
+
} catch (err) {
|
|
23982
|
+
if (!(err instanceof UpgradeFailure)) throw err;
|
|
23983
|
+
process23.stderr.write(`rshow: ${err.message}
|
|
23984
|
+
`);
|
|
23985
|
+
return err.exit;
|
|
23986
|
+
}
|
|
23987
|
+
const report = reportOf(result);
|
|
23988
|
+
ctx.out.data(report.data);
|
|
23989
|
+
for (const line of report.lines) ctx.out.line(line);
|
|
23990
|
+
return EXIT.ok;
|
|
23991
|
+
}
|
|
23992
|
+
|
|
23993
|
+
// src/commands/logout.ts
|
|
23994
|
+
import process24 from "node:process";
|
|
23995
|
+
async function run22(argv, ctx, platform = process24.platform) {
|
|
23432
23996
|
const args = parseCommandArgs(argv, { url: { type: "string" } }, 0, 0, LOGOUT_USAGE);
|
|
23433
23997
|
const settings = await ctx.config();
|
|
23434
23998
|
const given = (stringValue(args, "url") ?? "").trim();
|
|
23435
23999
|
const url = (given === "" ? requireUrl(settings) : given).replace(/\/+$/, "");
|
|
23436
24000
|
const removed = [];
|
|
23437
|
-
for (const store2 of await every(
|
|
24001
|
+
for (const store2 of await every(process24.env, platform)) {
|
|
23438
24002
|
if (await store2.remove(url)) removed.push(store2.description);
|
|
23439
24003
|
}
|
|
23440
24004
|
if (removed.length === 0) {
|
|
@@ -23464,14 +24028,15 @@ var COMMANDS = {
|
|
|
23464
24028
|
pin: { usage: PIN_USAGE, run: run12 },
|
|
23465
24029
|
delete: { usage: DELETE_USAGE, run: run13 },
|
|
23466
24030
|
login: { usage: LOGIN_USAGE, run: run20 },
|
|
23467
|
-
logout: { usage: LOGOUT_USAGE, run:
|
|
24031
|
+
logout: { usage: LOGOUT_USAGE, run: run22 },
|
|
24032
|
+
upgrade: { usage: UPGRADE_USAGE, run: run21 },
|
|
23468
24033
|
completion: { usage: COMPLETION_USAGE, run: run19 },
|
|
23469
24034
|
// Kept out of the general help: the docs site runs it, a person rarely does.
|
|
23470
24035
|
docs: { usage: DOCS_USAGE, run: run18 }
|
|
23471
24036
|
};
|
|
23472
24037
|
function fail(err) {
|
|
23473
24038
|
const message = err instanceof Error ? err.message : String(err);
|
|
23474
|
-
|
|
24039
|
+
process25.stderr.write(`rshow: ${message}
|
|
23475
24040
|
`);
|
|
23476
24041
|
if (err instanceof UsageError) return EXIT.usage;
|
|
23477
24042
|
if (err instanceof CheckError) return EXIT.check;
|
|
@@ -23483,39 +24048,40 @@ function fail(err) {
|
|
|
23483
24048
|
async function main2(argv) {
|
|
23484
24049
|
const wantsJson = argv.includes("--json");
|
|
23485
24050
|
const args = argv.filter((arg) => arg !== "--json");
|
|
23486
|
-
const wantsVersion = args.includes("--version") || args.includes("-v");
|
|
23487
24051
|
const wantsHelp = args.includes("--help") || args.includes("-h");
|
|
23488
|
-
const
|
|
24052
|
+
const commandAt = args.findIndex((arg) => !arg.startsWith("-"));
|
|
24053
|
+
const name = commandAt < 0 ? void 0 : args[commandAt];
|
|
23489
24054
|
const spec = name === void 0 ? void 0 : COMMANDS[name];
|
|
24055
|
+
const versionAt = args.findIndex((arg) => arg === "--version" || arg === "-v");
|
|
24056
|
+
const wantsVersion = versionAt >= 0 && (commandAt < 0 || versionAt < commandAt);
|
|
23490
24057
|
if (wantsVersion) {
|
|
23491
24058
|
const suffix = await isBinary() ? " (binary)" : "";
|
|
23492
|
-
|
|
24059
|
+
process25.stdout.write(`rshow ${VERSION}${suffix}
|
|
23493
24060
|
`);
|
|
23494
24061
|
return EXIT.ok;
|
|
23495
24062
|
}
|
|
23496
24063
|
if (wantsHelp) {
|
|
23497
|
-
|
|
24064
|
+
process25.stdout.write(`${spec === void 0 ? GENERAL_USAGE : spec.usage}
|
|
23498
24065
|
`);
|
|
23499
24066
|
return EXIT.ok;
|
|
23500
24067
|
}
|
|
23501
24068
|
if (name === void 0) {
|
|
23502
|
-
|
|
24069
|
+
process25.stderr.write(`${GENERAL_USAGE}
|
|
23503
24070
|
`);
|
|
23504
24071
|
return EXIT.usage;
|
|
23505
24072
|
}
|
|
23506
24073
|
if (spec === void 0) {
|
|
23507
24074
|
throw new UsageError(`unknown command: ${name} (try: rshow --help)`);
|
|
23508
24075
|
}
|
|
23509
|
-
const
|
|
23510
|
-
const rest = [...args.slice(0, index), ...args.slice(index + 1)];
|
|
24076
|
+
const rest = [...args.slice(0, commandAt), ...args.slice(commandAt + 1)];
|
|
23511
24077
|
const configs = /* @__PURE__ */ new Map();
|
|
23512
24078
|
const clients = /* @__PURE__ */ new Map();
|
|
23513
|
-
const keyOf = (dir) => dir === void 0 ? "" :
|
|
24079
|
+
const keyOf = (dir) => dir === void 0 ? "" : path28.resolve(dir);
|
|
23514
24080
|
const configFor = (dir) => {
|
|
23515
24081
|
const key2 = keyOf(dir);
|
|
23516
24082
|
let pending = configs.get(key2);
|
|
23517
24083
|
if (pending === void 0) {
|
|
23518
|
-
pending = loadConfig(
|
|
24084
|
+
pending = loadConfig(process25.env, dir);
|
|
23519
24085
|
configs.set(key2, pending);
|
|
23520
24086
|
}
|
|
23521
24087
|
return pending;
|
|
@@ -23528,7 +24094,7 @@ async function main2(argv) {
|
|
|
23528
24094
|
if (cached !== void 0) return cached;
|
|
23529
24095
|
const settings = await configFor(dir);
|
|
23530
24096
|
const url = requireUrl(settings);
|
|
23531
|
-
const client = new Client(url, await readToken(
|
|
24097
|
+
const client = new Client(url, await readToken(process25.env, url));
|
|
23532
24098
|
clients.set(key2, client);
|
|
23533
24099
|
return client;
|
|
23534
24100
|
},
|
|
@@ -23537,11 +24103,11 @@ async function main2(argv) {
|
|
|
23537
24103
|
const code = await spec.run(rest, ctx);
|
|
23538
24104
|
return code ?? EXIT.ok;
|
|
23539
24105
|
}
|
|
23540
|
-
main2(
|
|
24106
|
+
main2(process25.argv.slice(2)).then(
|
|
23541
24107
|
(code) => {
|
|
23542
|
-
|
|
24108
|
+
process25.exitCode = code;
|
|
23543
24109
|
},
|
|
23544
24110
|
(err) => {
|
|
23545
|
-
|
|
24111
|
+
process25.exitCode = fail(err);
|
|
23546
24112
|
}
|
|
23547
24113
|
);
|