@patchgg/cli 0.1.3 → 0.2.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/README.md +2 -1
- package/dist/cli.js +701 -440
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -130,11 +130,17 @@ function exitCodeFor(status2) {
|
|
|
130
130
|
return EXIT.error;
|
|
131
131
|
}
|
|
132
132
|
function notSignedIn() {
|
|
133
|
-
|
|
133
|
+
const failure2 = new CliError(
|
|
134
134
|
EXIT.auth,
|
|
135
135
|
"not_signed_in",
|
|
136
136
|
"You're not signed in. Run pch login, or set PCH_TOKEN to an API key."
|
|
137
137
|
);
|
|
138
|
+
failure2.forPeople = {
|
|
139
|
+
title: "You're not signed in",
|
|
140
|
+
next: [["pch login", "sign in, in your browser"]],
|
|
141
|
+
also: "For an agent or CI, set PCH_TOKEN to an API key instead."
|
|
142
|
+
};
|
|
143
|
+
return failure2;
|
|
138
144
|
}
|
|
139
145
|
var EXIT, CliError;
|
|
140
146
|
var init_errors = __esm({
|
|
@@ -167,6 +173,11 @@ var init_errors = __esm({
|
|
|
167
173
|
details;
|
|
168
174
|
/** Patch's API said it, rather than pch itself. */
|
|
169
175
|
fromApi;
|
|
176
|
+
/**
|
|
177
|
+
* What a person at a terminal sees instead of the message, when that's shorter: a line, and a
|
|
178
|
+
* command or two that fix it. Agents and --json always get the whole message.
|
|
179
|
+
*/
|
|
180
|
+
forPeople;
|
|
170
181
|
};
|
|
171
182
|
}
|
|
172
183
|
});
|
|
@@ -176,17 +187,17 @@ var VERSION;
|
|
|
176
187
|
var init_version = __esm({
|
|
177
188
|
"src/version.ts"() {
|
|
178
189
|
"use strict";
|
|
179
|
-
VERSION = true ? "0.
|
|
190
|
+
VERSION = true ? "0.2.0" : JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
180
191
|
}
|
|
181
192
|
});
|
|
182
193
|
|
|
183
194
|
// src/guide-words.ts
|
|
184
|
-
function openCodeWords(name, repo,
|
|
195
|
+
function openCodeWords(name, repo, release3) {
|
|
185
196
|
if (repo?.visibility !== "open") return null;
|
|
186
|
-
if (
|
|
187
|
-
const seen =
|
|
197
|
+
if (release3.status === "yanked" || release3.status === "quarantined") return null;
|
|
198
|
+
const seen = release3.channel === "private" ? "private" : release3.status === "published" ? release3.channel : "private until it's published";
|
|
188
199
|
if (seen === "public") return null;
|
|
189
|
-
const what =
|
|
200
|
+
const what = release3.kind === "mod" ? "mod" : release3.kind === "block" ? "block" : "game";
|
|
190
201
|
const start = `The ${what} is ${seen}, but its code isn't:`;
|
|
191
202
|
const pass = "Say so when you tell anyone who can see it.";
|
|
192
203
|
if (repo.home === "github") {
|
|
@@ -654,8 +665,8 @@ var require_semver = __commonJS({
|
|
|
654
665
|
}
|
|
655
666
|
// preminor will bump the version up to the next minor release, and immediately
|
|
656
667
|
// down to pre-release. premajor and prepatch work the same way.
|
|
657
|
-
inc(
|
|
658
|
-
if (
|
|
668
|
+
inc(release3, identifier, identifierBase) {
|
|
669
|
+
if (release3.startsWith("pre")) {
|
|
659
670
|
if (!identifier && identifierBase === false) {
|
|
660
671
|
throw new Error("invalid increment argument: identifier is empty");
|
|
661
672
|
}
|
|
@@ -666,7 +677,7 @@ var require_semver = __commonJS({
|
|
|
666
677
|
}
|
|
667
678
|
}
|
|
668
679
|
}
|
|
669
|
-
switch (
|
|
680
|
+
switch (release3) {
|
|
670
681
|
case "premajor":
|
|
671
682
|
this.prerelease.length = 0;
|
|
672
683
|
this.patch = 0;
|
|
@@ -758,7 +769,7 @@ var require_semver = __commonJS({
|
|
|
758
769
|
break;
|
|
759
770
|
}
|
|
760
771
|
default:
|
|
761
|
-
throw new Error(`invalid increment argument: ${
|
|
772
|
+
throw new Error(`invalid increment argument: ${release3}`);
|
|
762
773
|
}
|
|
763
774
|
this.raw = this.format();
|
|
764
775
|
if (this.build.length) {
|
|
@@ -824,7 +835,7 @@ var require_inc = __commonJS({
|
|
|
824
835
|
"node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/inc.js"(exports, module) {
|
|
825
836
|
"use strict";
|
|
826
837
|
var SemVer = require_semver();
|
|
827
|
-
var inc = (version2,
|
|
838
|
+
var inc = (version2, release3, options, identifier, identifierBase) => {
|
|
828
839
|
if (typeof options === "string") {
|
|
829
840
|
identifierBase = identifier;
|
|
830
841
|
identifier = options;
|
|
@@ -834,7 +845,7 @@ var require_inc = __commonJS({
|
|
|
834
845
|
return new SemVer(
|
|
835
846
|
version2 instanceof SemVer ? version2.version : version2,
|
|
836
847
|
options
|
|
837
|
-
).inc(
|
|
848
|
+
).inc(release3, identifier, identifierBase).version;
|
|
838
849
|
} catch (er) {
|
|
839
850
|
return null;
|
|
840
851
|
}
|
|
@@ -35755,7 +35766,9 @@ var init_mcp = __esm({
|
|
|
35755
35766
|
});
|
|
35756
35767
|
|
|
35757
35768
|
// src/plain-when-piped.ts
|
|
35758
|
-
if (!process.stdout.isTTY
|
|
35769
|
+
if ((!process.stdout.isTTY || process.env.TERM === "dumb") && !process.env.FORCE_COLOR) {
|
|
35770
|
+
process.env.NO_COLOR = "1";
|
|
35771
|
+
}
|
|
35759
35772
|
|
|
35760
35773
|
// node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js
|
|
35761
35774
|
var CommanderError = class extends Error {
|
|
@@ -36330,13 +36343,13 @@ var Help = class {
|
|
|
36330
36343
|
(sub) => sub.helpGroup() || "Commands:"
|
|
36331
36344
|
);
|
|
36332
36345
|
commandGroups.forEach((commands, group) => {
|
|
36333
|
-
const
|
|
36346
|
+
const commandList2 = commands.map((sub) => {
|
|
36334
36347
|
return callFormatItem(
|
|
36335
36348
|
helper.styleSubcommandTerm(helper.subcommandTerm(sub)),
|
|
36336
36349
|
helper.styleSubcommandDescription(helper.subcommandDescription(sub))
|
|
36337
36350
|
);
|
|
36338
36351
|
});
|
|
36339
|
-
output2 = output2.concat(this.formatItemList(group,
|
|
36352
|
+
output2 = output2.concat(this.formatItemList(group, commandList2, helper));
|
|
36340
36353
|
});
|
|
36341
36354
|
return output2.join("\n");
|
|
36342
36355
|
}
|
|
@@ -36490,10 +36503,10 @@ ${itemIndentStr}`);
|
|
|
36490
36503
|
let sumChunks = [chunks.shift()];
|
|
36491
36504
|
let sumWidth = this.displayWidth(sumChunks[0]);
|
|
36492
36505
|
chunks.forEach((chunk) => {
|
|
36493
|
-
const
|
|
36494
|
-
if (sumWidth +
|
|
36506
|
+
const visibleWidth2 = this.displayWidth(chunk);
|
|
36507
|
+
if (sumWidth + visibleWidth2 <= width) {
|
|
36495
36508
|
sumChunks.push(chunk);
|
|
36496
|
-
sumWidth +=
|
|
36509
|
+
sumWidth += visibleWidth2;
|
|
36497
36510
|
return;
|
|
36498
36511
|
}
|
|
36499
36512
|
wrappedLines.push(sumChunks.join(""));
|
|
@@ -39126,7 +39139,7 @@ function useColor() {
|
|
|
39126
39139
|
var program = new Command();
|
|
39127
39140
|
|
|
39128
39141
|
// src/commands/account.ts
|
|
39129
|
-
var
|
|
39142
|
+
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
39130
39143
|
|
|
39131
39144
|
// node_modules/.pnpm/openapi-fetch@0.17.0/node_modules/openapi-fetch/dist/index.mjs
|
|
39132
39145
|
var PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
@@ -39970,20 +39983,188 @@ var LFS_FLAGS = [
|
|
|
39970
39983
|
];
|
|
39971
39984
|
var NO_LFS = "Git LFS isn't installed, so big files stay small pointer files. Install it from https://git-lfs.com, then run git lfs install.";
|
|
39972
39985
|
|
|
39986
|
+
// src/commands/account.ts
|
|
39987
|
+
init_guide_words();
|
|
39988
|
+
|
|
39989
|
+
// src/terminal.ts
|
|
39990
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
39991
|
+
import { spawnSync } from "node:child_process";
|
|
39992
|
+
import { release } from "node:os";
|
|
39993
|
+
function canRedraw() {
|
|
39994
|
+
return Boolean(process.stderr.isTTY) && process.env.TERM !== "dumb";
|
|
39995
|
+
}
|
|
39996
|
+
function unicode(vars = process.env, platform = process.platform) {
|
|
39997
|
+
if (platform !== "win32") return vars.TERM !== "linux";
|
|
39998
|
+
return Boolean(
|
|
39999
|
+
vars.WT_SESSION || vars.TERMINUS_SUBLIME || vars.ConEmuTask === "{cmd::Cmder}" || vars.TERM_PROGRAM === "vscode" || vars.TERM_PROGRAM === "mintty" || vars.TERM === "xterm-256color" || vars.TERM === "alacritty" || vars.TERMINAL_EMULATOR === "JetBrains-JediTerm"
|
|
40000
|
+
);
|
|
40001
|
+
}
|
|
40002
|
+
function colourDepth(vars = process.env, platform = process.platform) {
|
|
40003
|
+
if (!import_picocolors.default.isColorSupported || vars.TERM === "dumb") return 0;
|
|
40004
|
+
if (vars.COLORTERM === "truecolor" || vars.COLORTERM === "24bit") return 3;
|
|
40005
|
+
if (vars.WT_SESSION || vars.TERM_PROGRAM === "mintty" || vars.TERM_PROGRAM === "vscode") return 3;
|
|
40006
|
+
if (platform === "win32" && Number(release().split(".")[2]) >= 14931) return 3;
|
|
40007
|
+
if (vars.TERM?.includes("256")) return 2;
|
|
40008
|
+
return 1;
|
|
40009
|
+
}
|
|
40010
|
+
function pink(text, depth = colourDepth()) {
|
|
40011
|
+
if (depth === 3) return `\x1B[38;2;245;60;209m${text}\x1B[39m`;
|
|
40012
|
+
if (depth === 2) return `\x1B[38;5;206m${text}\x1B[39m`;
|
|
40013
|
+
return depth === 1 ? import_picocolors.default.magenta(text) : text;
|
|
40014
|
+
}
|
|
40015
|
+
function copyText(text, platform = process.platform) {
|
|
40016
|
+
const tools = platform === "win32" ? [["clip", []]] : platform === "darwin" ? [["pbcopy", []]] : [
|
|
40017
|
+
["wl-copy", []],
|
|
40018
|
+
["xclip", ["-selection", "clipboard"]],
|
|
40019
|
+
["xsel", ["--clipboard", "--input"]]
|
|
40020
|
+
];
|
|
40021
|
+
for (const [command, args2] of tools) {
|
|
40022
|
+
try {
|
|
40023
|
+
const done = spawnSync(command, args2, {
|
|
40024
|
+
input: text,
|
|
40025
|
+
stdio: ["pipe", "ignore", "ignore"],
|
|
40026
|
+
timeout: 2e3
|
|
40027
|
+
});
|
|
40028
|
+
if (done.status === 0) return true;
|
|
40029
|
+
} catch {
|
|
40030
|
+
}
|
|
40031
|
+
}
|
|
40032
|
+
return false;
|
|
40033
|
+
}
|
|
40034
|
+
var symbols = () => unicode() ? { done: "\u2713", failed: "\xD7", note: "!" } : { done: "\u221A", failed: "\xD7", note: "!" };
|
|
40035
|
+
var FRAMES = {
|
|
40036
|
+
unicode: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"],
|
|
40037
|
+
plain: ["|", "/", "-", "\\"]
|
|
40038
|
+
};
|
|
40039
|
+
function spinner(text, hint = "") {
|
|
40040
|
+
if (!canRedraw()) {
|
|
40041
|
+
process.stderr.write(` ${text}
|
|
40042
|
+
`);
|
|
40043
|
+
return { stop() {
|
|
40044
|
+
}, say(_) {
|
|
40045
|
+
} };
|
|
40046
|
+
}
|
|
40047
|
+
const frames = unicode() ? FRAMES.unicode : FRAMES.plain;
|
|
40048
|
+
let frame = 0;
|
|
40049
|
+
const draw = () => {
|
|
40050
|
+
const room = (process.stderr.columns || 80) - 5;
|
|
40051
|
+
const said2 = text.length > room ? `${text.slice(0, Math.max(0, room - 1))}\u2026` : text;
|
|
40052
|
+
const more = hint && said2.length + 2 + hint.length <= room ? ` ${import_picocolors.default.dim(hint)}` : "";
|
|
40053
|
+
const spin = frames[frame++ % frames.length];
|
|
40054
|
+
process.stderr.write(`\r\x1B[K ${spin} ${said2}${more}`);
|
|
40055
|
+
};
|
|
40056
|
+
const clear = () => process.stderr.write("\r\x1B[K\x1B[?25h");
|
|
40057
|
+
const cancel = () => {
|
|
40058
|
+
clear();
|
|
40059
|
+
process.stderr.write(` ${import_picocolors.default.dim("Cancelled.")}
|
|
40060
|
+
`);
|
|
40061
|
+
process.exit(130);
|
|
40062
|
+
};
|
|
40063
|
+
process.stderr.write("\x1B[?25l");
|
|
40064
|
+
draw();
|
|
40065
|
+
const timer = setInterval(draw, 80);
|
|
40066
|
+
process.once("SIGINT", cancel);
|
|
40067
|
+
let stopped = false;
|
|
40068
|
+
return {
|
|
40069
|
+
stop() {
|
|
40070
|
+
if (stopped) return;
|
|
40071
|
+
stopped = true;
|
|
40072
|
+
clearInterval(timer);
|
|
40073
|
+
process.off("SIGINT", cancel);
|
|
40074
|
+
clear();
|
|
40075
|
+
},
|
|
40076
|
+
/** Says something else from now on, such as the next thing it's waiting for. */
|
|
40077
|
+
say(next) {
|
|
40078
|
+
text = next;
|
|
40079
|
+
hint = "";
|
|
40080
|
+
draw();
|
|
40081
|
+
}
|
|
40082
|
+
};
|
|
40083
|
+
}
|
|
40084
|
+
var Block = class {
|
|
40085
|
+
lines = [];
|
|
40086
|
+
write(line = "") {
|
|
40087
|
+
this.lines.push(line);
|
|
40088
|
+
process.stderr.write(`${line}
|
|
40089
|
+
`);
|
|
40090
|
+
}
|
|
40091
|
+
/** Takes the lines back off the screen, counting the rows the window wrapped them onto. */
|
|
40092
|
+
erase() {
|
|
40093
|
+
const columns = process.stderr.columns;
|
|
40094
|
+
if (!canRedraw() || !columns || !this.lines.length) return;
|
|
40095
|
+
const rows = this.lines.reduce(
|
|
40096
|
+
(sum, line) => sum + Math.max(1, Math.ceil(visibleWidth(line) / columns)),
|
|
40097
|
+
0
|
|
40098
|
+
);
|
|
40099
|
+
process.stderr.write(`\x1B[${rows}A\r\x1B[J`);
|
|
40100
|
+
this.lines = [];
|
|
40101
|
+
}
|
|
40102
|
+
};
|
|
40103
|
+
function commandList(rows, indent = " ", columns = process.stdout.columns ?? 80) {
|
|
40104
|
+
const wide = Math.max(...rows.map(([command]) => command.length));
|
|
40105
|
+
const fits = indent.length + wide + 3 + Math.max(...rows.map(([, words2]) => words2.length));
|
|
40106
|
+
return rows.map(
|
|
40107
|
+
([command, words2]) => fits <= columns ? `${indent}${import_picocolors.default.bold(command.padEnd(wide))} ${import_picocolors.default.dim(words2)}` : `${indent}${import_picocolors.default.bold(command)}
|
|
40108
|
+
${indent} ${import_picocolors.default.dim(words2)}`
|
|
40109
|
+
);
|
|
40110
|
+
}
|
|
40111
|
+
function placeOf(origin) {
|
|
40112
|
+
try {
|
|
40113
|
+
return new URL(origin).host;
|
|
40114
|
+
} catch {
|
|
40115
|
+
return origin;
|
|
40116
|
+
}
|
|
40117
|
+
}
|
|
40118
|
+
var ESCAPES = /\x1b\[[0-9;?]*[A-Za-z]/g;
|
|
40119
|
+
function unstyled(text) {
|
|
40120
|
+
return text.replace(ESCAPES, "");
|
|
40121
|
+
}
|
|
40122
|
+
function visibleWidth(text) {
|
|
40123
|
+
return [...unstyled(text)].length;
|
|
40124
|
+
}
|
|
40125
|
+
|
|
39973
40126
|
// src/commands/login.ts
|
|
39974
|
-
var
|
|
40127
|
+
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
39975
40128
|
import { spawn as spawn2 } from "node:child_process";
|
|
39976
40129
|
import { hostname } from "node:os";
|
|
39977
40130
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
39978
40131
|
init_errors();
|
|
39979
40132
|
init_guide_words();
|
|
39980
40133
|
|
|
40134
|
+
// src/logo.ts
|
|
40135
|
+
var ROWS = [
|
|
40136
|
+
".....................#.........#....",
|
|
40137
|
+
"####.................#.........#....",
|
|
40138
|
+
"#...#...####..####..####.#####.####.",
|
|
40139
|
+
"#.+.#...#...#.....#..#...#.....#...#",
|
|
40140
|
+
"#...#...#...#.#####..#...#.....#...#",
|
|
40141
|
+
"#####...#...#.#...#..#...#.....#...#",
|
|
40142
|
+
"........#####.#####..###.#####.#...#",
|
|
40143
|
+
"........#...........................",
|
|
40144
|
+
"........#..........................."
|
|
40145
|
+
];
|
|
40146
|
+
var WIDTH = ROWS[0]?.length ?? 0;
|
|
40147
|
+
function logo(columns = process.stdout.columns ?? 80, depth = colourDepth()) {
|
|
40148
|
+
if (!canRedraw() || !unicode() || columns < WIDTH + 4) return null;
|
|
40149
|
+
const lines = [];
|
|
40150
|
+
for (let y = 0; y < ROWS.length; y += 2) {
|
|
40151
|
+
const top = ROWS[y] ?? "";
|
|
40152
|
+
const bottom = ROWS[y + 1] ?? "";
|
|
40153
|
+
let line = "";
|
|
40154
|
+
for (let x = 0; x < WIDTH; x++) {
|
|
40155
|
+
const up = top[x] ?? ".";
|
|
40156
|
+
const down = bottom[x] ?? ".";
|
|
40157
|
+
const glyph = up !== "." ? down !== "." ? "\u2588" : "\u2580" : down !== "." ? "\u2584" : " ";
|
|
40158
|
+
line += up === "+" || down === "+" ? pink(glyph, depth) : glyph;
|
|
40159
|
+
}
|
|
40160
|
+
lines.push(line.trimEnd());
|
|
40161
|
+
}
|
|
40162
|
+
return lines;
|
|
40163
|
+
}
|
|
40164
|
+
|
|
39981
40165
|
// src/output.ts
|
|
39982
|
-
var
|
|
40166
|
+
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
39983
40167
|
init_errors();
|
|
39984
|
-
var UNICODE = process.platform !== "win32" || Boolean(process.env.WT_SESSION || process.env.TERM_PROGRAM);
|
|
39985
|
-
var TICK = UNICODE ? "\u2714" : "\u221A";
|
|
39986
|
-
var SPINNER = UNICODE ? ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"] : ["-", "\\", "|", "/"];
|
|
39987
40168
|
function forAPerson(json2, agent2) {
|
|
39988
40169
|
return !json2 && Boolean(process.stdout.isTTY && process.stderr.isTTY) && !agent2;
|
|
39989
40170
|
}
|
|
@@ -40004,24 +40185,9 @@ var Output = class {
|
|
|
40004
40185
|
}
|
|
40005
40186
|
/** A progress line, e.g. "Uploading 2 files". */
|
|
40006
40187
|
step(text) {
|
|
40007
|
-
if (!this.json) process.stderr.write(`${
|
|
40188
|
+
if (!this.json) process.stderr.write(`${import_picocolors2.default.dim("\u203A")} ${text}
|
|
40008
40189
|
`);
|
|
40009
40190
|
}
|
|
40010
|
-
/**
|
|
40011
|
-
* A spinner on stderr, for a person at a terminal while pch waits on them. Call what it returns
|
|
40012
|
-
* to stop it: that takes its line away, so whatever comes next starts on a clean one.
|
|
40013
|
-
*/
|
|
40014
|
-
spin(text) {
|
|
40015
|
-
let frame = 0;
|
|
40016
|
-
const draw = () => process.stderr.write(`\r${import_picocolors.default.cyan(SPINNER[frame++ % SPINNER.length])} ${text}`);
|
|
40017
|
-
draw();
|
|
40018
|
-
const timer = setInterval(draw, 80);
|
|
40019
|
-
timer.unref();
|
|
40020
|
-
return () => {
|
|
40021
|
-
clearInterval(timer);
|
|
40022
|
-
process.stderr.write("\r\x1B[2K");
|
|
40023
|
-
};
|
|
40024
|
-
}
|
|
40025
40191
|
/**
|
|
40026
40192
|
* How far a long job has got. With --json it's a line of JSON on stderr, so whoever's waiting can
|
|
40027
40193
|
* see it's moving while stdout stays the one result.
|
|
@@ -40045,16 +40211,40 @@ var Output = class {
|
|
|
40045
40211
|
};
|
|
40046
40212
|
process.stderr.write(`${JSON.stringify(body)}
|
|
40047
40213
|
`);
|
|
40214
|
+
} else if (process.stderr.isTTY) {
|
|
40215
|
+
const failed3 = import_picocolors2.default.red(symbols().failed);
|
|
40216
|
+
const short = failure2.forPeople;
|
|
40217
|
+
if (short) process.stderr.write(`
|
|
40218
|
+
${failed3} ${short.title}
|
|
40219
|
+
|
|
40220
|
+
`);
|
|
40221
|
+
else
|
|
40222
|
+
process.stderr.write(`
|
|
40223
|
+
${failed3} ${failure2.message} ${import_picocolors2.default.dim(`(${failure2.code})`)}
|
|
40224
|
+
`);
|
|
40225
|
+
for (const issue2 of issuesOf(failure2.details)) {
|
|
40226
|
+
process.stderr.write(` ${import_picocolors2.default.dim(issue2.path || "\xB7")} ${issue2.message}
|
|
40227
|
+
`);
|
|
40228
|
+
}
|
|
40229
|
+
if (short) process.stderr.write(`${commandList(short.next, " ").join("\n")}
|
|
40230
|
+
`);
|
|
40231
|
+
if (short?.also) process.stderr.write(`
|
|
40232
|
+
${import_picocolors2.default.dim(short.also)}
|
|
40233
|
+
`);
|
|
40234
|
+
if (feedback2) process.stderr.write(`
|
|
40235
|
+
${import_picocolors2.default.dim(feedback2.say)}
|
|
40236
|
+
`);
|
|
40237
|
+
process.stderr.write("\n");
|
|
40048
40238
|
} else {
|
|
40049
40239
|
process.stderr.write(
|
|
40050
|
-
`${
|
|
40240
|
+
`${import_picocolors2.default.red("Error:")} ${failure2.message} ${import_picocolors2.default.dim(`(${failure2.code})`)}
|
|
40051
40241
|
`
|
|
40052
40242
|
);
|
|
40053
40243
|
for (const issue2 of issuesOf(failure2.details)) {
|
|
40054
|
-
process.stderr.write(` ${
|
|
40244
|
+
process.stderr.write(` ${import_picocolors2.default.dim(issue2.path || "\xB7")} ${issue2.message}
|
|
40055
40245
|
`);
|
|
40056
40246
|
}
|
|
40057
|
-
if (feedback2) process.stderr.write(`${
|
|
40247
|
+
if (feedback2) process.stderr.write(`${import_picocolors2.default.dim(feedback2.say)}
|
|
40058
40248
|
`);
|
|
40059
40249
|
}
|
|
40060
40250
|
return failure2.exitCode;
|
|
@@ -40105,29 +40295,33 @@ async function login(ctx, options) {
|
|
|
40105
40295
|
const { out, target } = ctx;
|
|
40106
40296
|
if (process.env.PCH_TOKEN) return loginWithKey(ctx);
|
|
40107
40297
|
const scopes = options.scope?.length ? options.scope : ["read", "publish"];
|
|
40108
|
-
const
|
|
40109
|
-
|
|
40110
|
-
|
|
40298
|
+
const name = ctx.target.accountName ?? (target.env === "production" ? "default" : target.env);
|
|
40299
|
+
const isDefault = name === (target.env === "production" ? "default" : target.env);
|
|
40300
|
+
const people = forAPerson(out.json, runningIn());
|
|
40301
|
+
const notes = [];
|
|
40302
|
+
const signIn = { ...options, logo: true };
|
|
40303
|
+
const { me, key, git, gitIdentity } = await withDeviceSession(ctx, signIn, async (session) => {
|
|
40304
|
+
const me2 = await unwrap(session.GET("/me"));
|
|
40305
|
+
const key2 = await unwrap(
|
|
40111
40306
|
session.POST("/tokens", {
|
|
40112
40307
|
body: { name: `${runningIn() ?? "pch"} on ${hostname()}`, scopes }
|
|
40113
40308
|
})
|
|
40114
|
-
)
|
|
40115
|
-
|
|
40116
|
-
|
|
40117
|
-
|
|
40118
|
-
|
|
40119
|
-
|
|
40120
|
-
|
|
40121
|
-
|
|
40122
|
-
|
|
40123
|
-
|
|
40124
|
-
|
|
40125
|
-
|
|
40126
|
-
|
|
40127
|
-
|
|
40128
|
-
|
|
40129
|
-
|
|
40130
|
-
const gitIdentity = await identityAdvice(ctx);
|
|
40309
|
+
);
|
|
40310
|
+
const account2 = {
|
|
40311
|
+
env: target.env,
|
|
40312
|
+
token: key2.key,
|
|
40313
|
+
token_id: key2.id,
|
|
40314
|
+
...me2.username ? { username: me2.username } : {},
|
|
40315
|
+
...target.origin !== defaultOrigin(target.env) ? { api_url: target.origin } : {},
|
|
40316
|
+
...target.gitUrl && target.gitUrl !== defaultGitUrl(target.env) ? { git_url: target.gitUrl } : {}
|
|
40317
|
+
};
|
|
40318
|
+
const config2 = ctx.config;
|
|
40319
|
+
config2.accounts = { ...config2.accounts, [name]: account2 };
|
|
40320
|
+
config2.active_account = name;
|
|
40321
|
+
await writeConfig(config2);
|
|
40322
|
+
const git2 = await setUpGit(ctx, people ? notes : void 0);
|
|
40323
|
+
return { me: me2, key: key2, git: git2, gitIdentity: await identityAdvice(ctx) };
|
|
40324
|
+
});
|
|
40131
40325
|
out.result(
|
|
40132
40326
|
{
|
|
40133
40327
|
account: name,
|
|
@@ -40139,13 +40333,21 @@ async function login(ctx, options) {
|
|
|
40139
40333
|
look_first: LOOK_FIRST
|
|
40140
40334
|
},
|
|
40141
40335
|
() => {
|
|
40142
|
-
|
|
40143
|
-
|
|
40144
|
-
const
|
|
40145
|
-
|
|
40146
|
-
|
|
40336
|
+
if (people) {
|
|
40337
|
+
const who = import_picocolors3.default.bold(me.username ? `@${me.username}` : me.email);
|
|
40338
|
+
const which = isDefault ? "" : ` ${import_picocolors3.default.dim(`(account "${name}")`)}`;
|
|
40339
|
+
return signedIn(ctx, `Signed in as ${who} on ${placeOf(target.origin)}${which}`, {
|
|
40340
|
+
git,
|
|
40341
|
+
notes: [
|
|
40342
|
+
...me.username ? [] : [`Choose a username at ${target.origin}/welcome to publish.`],
|
|
40343
|
+
...gitIdentity ? [SHORT_IDENTITY] : [],
|
|
40344
|
+
...notes
|
|
40345
|
+
]
|
|
40346
|
+
});
|
|
40147
40347
|
}
|
|
40148
|
-
out.line(
|
|
40348
|
+
out.line(
|
|
40349
|
+
`Signed in as ${import_picocolors3.default.bold(me.username ? `@${me.username}` : me.email)} on ${target.env} (account "${name}").`
|
|
40350
|
+
);
|
|
40149
40351
|
if (!me.username) out.line(`Choose a username at ${target.origin}/welcome to publish.`);
|
|
40150
40352
|
if (git.helper) out.line(`Git is signed in too: Patch repos at ${git.url} just work.`);
|
|
40151
40353
|
if (gitIdentity) out.line(gitIdentity);
|
|
@@ -40159,7 +40361,9 @@ async function login(ctx, options) {
|
|
|
40159
40361
|
async function loginWithKey(ctx) {
|
|
40160
40362
|
const { out, target } = ctx;
|
|
40161
40363
|
const me = await unwrap(ctx.api.GET("/me"));
|
|
40162
|
-
const
|
|
40364
|
+
const people = forAPerson(out.json, runningIn());
|
|
40365
|
+
const notes = [];
|
|
40366
|
+
const git = await setUpGit(ctx, people ? notes : void 0);
|
|
40163
40367
|
const gitIdentity = await identityAdvice(ctx);
|
|
40164
40368
|
out.result(
|
|
40165
40369
|
{
|
|
@@ -40172,63 +40376,57 @@ async function loginWithKey(ctx) {
|
|
|
40172
40376
|
look_first: LOOK_FIRST
|
|
40173
40377
|
},
|
|
40174
40378
|
() => {
|
|
40175
|
-
|
|
40176
|
-
|
|
40177
|
-
|
|
40178
|
-
|
|
40379
|
+
if (people) {
|
|
40380
|
+
const who = import_picocolors3.default.bold(me.username ? `@${me.username}` : me.email);
|
|
40381
|
+
return signedIn(ctx, `PCH_TOKEN works: ${who} on ${placeOf(target.origin)}`, {
|
|
40382
|
+
git,
|
|
40383
|
+
notes: [...gitIdentity ? [SHORT_IDENTITY] : [], ...notes]
|
|
40384
|
+
});
|
|
40179
40385
|
}
|
|
40180
|
-
out.line(
|
|
40386
|
+
out.line(
|
|
40387
|
+
`PCH_TOKEN works: ${import_picocolors3.default.bold(me.username ? `@${me.username}` : me.email)} on ${target.env}.`
|
|
40388
|
+
);
|
|
40181
40389
|
if (git.helper) out.line(`Git is signed in too: Patch repos at ${git.url} just work.`);
|
|
40182
40390
|
if (gitIdentity) out.line(gitIdentity);
|
|
40183
40391
|
out.line(LOOK_FIRST);
|
|
40184
40392
|
}
|
|
40185
40393
|
);
|
|
40186
40394
|
}
|
|
40187
|
-
|
|
40188
|
-
|
|
40189
|
-
}
|
|
40190
|
-
function signedIn(ctx, headline, username, git, gitIdentity) {
|
|
40395
|
+
var SHORT_IDENTITY = "Git doesn't know who you are on this PC yet: pch new and pch clone set that up for each repo.";
|
|
40396
|
+
function signedIn(ctx, headline, { git, notes }) {
|
|
40191
40397
|
const { out, target } = ctx;
|
|
40192
|
-
out.line(`${import_picocolors2.default.green(TICK)} ${headline}`);
|
|
40193
|
-
if (git.helper) out.line(import_picocolors2.default.dim(" Git works with Patch repos too."));
|
|
40194
|
-
if (!username) out.line(` Choose a username at ${target.origin}/welcome before you publish.`);
|
|
40195
|
-
if (gitIdentity) out.line(indented(gitIdentity));
|
|
40196
40398
|
const pch = pchOn(target.env);
|
|
40197
|
-
const
|
|
40198
|
-
[`${pch} search "<idea>"`, "find a game or block to start from"],
|
|
40199
|
-
[`${pch} agent install`, "give your coding agent Patch's tools"],
|
|
40200
|
-
[`${pch} guide`, "how to make, test and publish"]
|
|
40201
|
-
];
|
|
40202
|
-
const width = Math.max(...next.map(([command]) => command.length));
|
|
40399
|
+
const mark = symbols();
|
|
40203
40400
|
out.line();
|
|
40204
|
-
|
|
40205
|
-
|
|
40401
|
+
out.line(` ${import_picocolors3.default.bold(mark.done)} ${headline}`);
|
|
40402
|
+
if (git.helper && git.url) {
|
|
40403
|
+
out.line(import_picocolors3.default.dim(` Git is signed in too, for repos at ${placeOf(git.url)}.`));
|
|
40206
40404
|
}
|
|
40405
|
+
for (const note2 of notes) out.line(` ${import_picocolors3.default.bold(mark.note)} ${note2}`);
|
|
40406
|
+
out.line();
|
|
40407
|
+
out.line(` ${import_picocolors3.default.dim("Next")}`);
|
|
40408
|
+
const next = commandList(
|
|
40409
|
+
[
|
|
40410
|
+
[`${pch} search "<your idea>"`, "find a block or game to start from"],
|
|
40411
|
+
[`${pch} agent install`, "give your coding agent Patch's tools"],
|
|
40412
|
+
[`${pch} guide`, "how to make and publish a game"]
|
|
40413
|
+
],
|
|
40414
|
+
" "
|
|
40415
|
+
);
|
|
40416
|
+
for (const row of next) out.line(row);
|
|
40207
40417
|
out.line();
|
|
40208
40418
|
}
|
|
40209
|
-
function
|
|
40210
|
-
const width = Math.min(process.stdout.columns || 80, 100) - 2;
|
|
40211
|
-
const lines = [];
|
|
40212
|
-
let line = "";
|
|
40213
|
-
for (const word of text.split(" ")) {
|
|
40214
|
-
if (line && line.length + 1 + word.length > width) {
|
|
40215
|
-
lines.push(line);
|
|
40216
|
-
line = word;
|
|
40217
|
-
} else line = line ? `${line} ${word}` : word;
|
|
40218
|
-
}
|
|
40219
|
-
if (line) lines.push(line);
|
|
40220
|
-
return lines.map((each) => ` ${each}`).join("\n");
|
|
40221
|
-
}
|
|
40222
|
-
async function setUpGit(ctx) {
|
|
40419
|
+
async function setUpGit(ctx, notes) {
|
|
40223
40420
|
const { gitUrl: url2 } = ctx.target;
|
|
40421
|
+
const say = (text) => notes ? notes.push(text) : ctx.out.step(text);
|
|
40224
40422
|
if (!url2) return { url: url2, helper: false, lfs: false };
|
|
40225
40423
|
try {
|
|
40226
40424
|
await setUpGitHelper(ctx);
|
|
40227
40425
|
const lfs = await setUpLfs();
|
|
40228
|
-
if (!lfs)
|
|
40426
|
+
if (!lfs) say(NO_LFS);
|
|
40229
40427
|
return { url: url2, helper: true, lfs };
|
|
40230
40428
|
} catch (error62) {
|
|
40231
|
-
|
|
40429
|
+
say(`Git isn't set up: ${error62.message}`);
|
|
40232
40430
|
return { url: url2, helper: false, lfs: false };
|
|
40233
40431
|
}
|
|
40234
40432
|
}
|
|
@@ -40239,55 +40437,68 @@ async function withDeviceSession(ctx, options, use) {
|
|
|
40239
40437
|
if (!started.response.ok) throw authError(started.body, "Couldn't start a login");
|
|
40240
40438
|
const device = started.body;
|
|
40241
40439
|
const code = formatUserCode(device.user_code);
|
|
40242
|
-
const
|
|
40243
|
-
|
|
40244
|
-
|
|
40245
|
-
|
|
40246
|
-
if (
|
|
40247
|
-
|
|
40248
|
-
|
|
40249
|
-
|
|
40250
|
-
|
|
40251
|
-
|
|
40252
|
-
|
|
40253
|
-
${
|
|
40254
|
-
|
|
40255
|
-
|
|
40256
|
-
)
|
|
40257
|
-
|
|
40440
|
+
const opening = options.browser !== false && Boolean(process.stdout.isTTY);
|
|
40441
|
+
const people = forAPerson(out.json, runningIn());
|
|
40442
|
+
const block = new Block();
|
|
40443
|
+
const drawn = people && options.logo ? logo() : null;
|
|
40444
|
+
if (drawn) process.stderr.write(`
|
|
40445
|
+
${drawn.map((line) => ` ${line}`).join("\n")}
|
|
40446
|
+
`);
|
|
40447
|
+
if (people) {
|
|
40448
|
+
block.write();
|
|
40449
|
+
block.write(" Sign in to Patch with this code");
|
|
40450
|
+
block.write();
|
|
40451
|
+
const copied = copyText(device.user_code) ? ` ${import_picocolors3.default.dim("copied")}` : "";
|
|
40452
|
+
block.write(`${import_picocolors3.default.bold(pink(device.user_code))}${copied}`);
|
|
40453
|
+
block.write();
|
|
40454
|
+
if (opening) {
|
|
40455
|
+
const page = import_picocolors3.default.bold(`${placeOf(target.origin)}/device`);
|
|
40456
|
+
block.write(` Opening ${page} in your browser: check the code matches, then approve.`);
|
|
40457
|
+
block.write(import_picocolors3.default.dim(` Didn't open? Go to ${device.verification_uri} and enter the code.`));
|
|
40458
|
+
} else {
|
|
40459
|
+
block.write(` Go to ${import_picocolors3.default.bold(device.verification_uri)} and enter the code.`);
|
|
40460
|
+
}
|
|
40461
|
+
block.write();
|
|
40258
40462
|
} else {
|
|
40259
40463
|
process.stderr.write(
|
|
40260
40464
|
`This waits for a person to approve it in a browser, which can take a few minutes. The code only works while this keeps running, so don't put a short timeout on it.
|
|
40261
40465
|
|
|
40262
|
-
To sign in, open ${
|
|
40466
|
+
To sign in, open ${import_picocolors3.default.bold(device.verification_uri)} and enter ${import_picocolors3.default.bold(code)}
|
|
40263
40467
|
|
|
40264
40468
|
`
|
|
40265
40469
|
);
|
|
40266
|
-
out.step("Waiting for you to approve in the browser\u2026");
|
|
40267
|
-
}
|
|
40268
|
-
let sessionToken = null;
|
|
40269
|
-
try {
|
|
40270
|
-
sessionToken = await approval(ctx, device, options);
|
|
40271
|
-
} finally {
|
|
40272
|
-
stopWaiting();
|
|
40273
|
-
}
|
|
40274
|
-
if (!sessionToken) {
|
|
40275
|
-
throw new CliError(EXIT.auth, "expired_token", "The code expired. Run pch login again.");
|
|
40276
40470
|
}
|
|
40471
|
+
if (opening) openBrowser(device.verification_uri_complete);
|
|
40472
|
+
const waiting = people ? spinner("Waiting for you to approve", "Ctrl+C to cancel") : { stop() {
|
|
40473
|
+
}, say() {
|
|
40474
|
+
} };
|
|
40475
|
+
if (!people) out.step("Waiting for you to approve in the browser\u2026");
|
|
40277
40476
|
try {
|
|
40278
|
-
|
|
40477
|
+
const sessionToken = await pollForSession(ctx, device, options);
|
|
40478
|
+
waiting.say("Approved. Finishing up");
|
|
40479
|
+
let value;
|
|
40480
|
+
try {
|
|
40481
|
+
value = await use(createApi(target, { token: sessionToken }));
|
|
40482
|
+
} finally {
|
|
40483
|
+
await fetch(`${auth2}/sign-out`, {
|
|
40484
|
+
method: "POST",
|
|
40485
|
+
headers: { authorization: `Bearer ${sessionToken}`, "content-type": "application/json" },
|
|
40486
|
+
body: "{}"
|
|
40487
|
+
}).catch(() => void 0);
|
|
40488
|
+
}
|
|
40489
|
+
waiting.stop();
|
|
40490
|
+
block.erase();
|
|
40491
|
+
return value;
|
|
40279
40492
|
} finally {
|
|
40280
|
-
|
|
40281
|
-
method: "POST",
|
|
40282
|
-
headers: { authorization: `Bearer ${sessionToken}`, "content-type": "application/json" },
|
|
40283
|
-
body: "{}"
|
|
40284
|
-
}).catch(() => void 0);
|
|
40493
|
+
waiting.stop();
|
|
40285
40494
|
}
|
|
40286
40495
|
}
|
|
40287
|
-
|
|
40496
|
+
var TRY_AGAIN = [["pch login", "get a new code and try again"]];
|
|
40497
|
+
async function pollForSession(ctx, device, options) {
|
|
40288
40498
|
const auth2 = `${ctx.target.origin}/api/auth`;
|
|
40289
40499
|
let interval = (options.interval ?? device.interval) * 1e3;
|
|
40290
40500
|
const deadline = Date.now() + device.expires_in * 1e3;
|
|
40501
|
+
let sessionToken = null;
|
|
40291
40502
|
while (Date.now() < deadline) {
|
|
40292
40503
|
await sleep(interval);
|
|
40293
40504
|
const polled = await postJson(`${auth2}/device/token`, {
|
|
@@ -40295,7 +40506,10 @@ async function approval(ctx, device, options) {
|
|
|
40295
40506
|
device_code: device.device_code,
|
|
40296
40507
|
client_id: CLIENT_ID
|
|
40297
40508
|
});
|
|
40298
|
-
if (polled.response.ok)
|
|
40509
|
+
if (polled.response.ok) {
|
|
40510
|
+
sessionToken = polled.body.access_token;
|
|
40511
|
+
break;
|
|
40512
|
+
}
|
|
40299
40513
|
const error62 = polled.body.error;
|
|
40300
40514
|
if (error62 === "authorization_pending") continue;
|
|
40301
40515
|
if (error62 === "slow_down") {
|
|
@@ -40303,12 +40517,27 @@ async function approval(ctx, device, options) {
|
|
|
40303
40517
|
continue;
|
|
40304
40518
|
}
|
|
40305
40519
|
if (error62 === "access_denied") {
|
|
40306
|
-
|
|
40520
|
+
const denied = new CliError(
|
|
40521
|
+
EXIT.auth,
|
|
40522
|
+
"access_denied",
|
|
40523
|
+
"The login was denied in the browser."
|
|
40524
|
+
);
|
|
40525
|
+
denied.forPeople = { title: "The sign-in was denied in the browser", next: TRY_AGAIN };
|
|
40526
|
+
throw denied;
|
|
40307
40527
|
}
|
|
40308
40528
|
if (error62 === "expired_token") break;
|
|
40309
40529
|
throw authError(polled.body, "The login failed");
|
|
40310
40530
|
}
|
|
40311
|
-
|
|
40531
|
+
if (!sessionToken) {
|
|
40532
|
+
const expired = new CliError(
|
|
40533
|
+
EXIT.auth,
|
|
40534
|
+
"expired_token",
|
|
40535
|
+
"The code expired. Run pch login again."
|
|
40536
|
+
);
|
|
40537
|
+
expired.forPeople = { title: "The code expired before it was approved", next: TRY_AGAIN };
|
|
40538
|
+
throw expired;
|
|
40539
|
+
}
|
|
40540
|
+
return sessionToken;
|
|
40312
40541
|
}
|
|
40313
40542
|
function runningIn(vars = process.env) {
|
|
40314
40543
|
if (vars.CLAUDECODE === "1") return "Claude Code";
|
|
@@ -40347,12 +40576,25 @@ async function whoami(ctx) {
|
|
|
40347
40576
|
requireToken(ctx.target);
|
|
40348
40577
|
const me = await unwrap(ctx.api.GET("/me"));
|
|
40349
40578
|
ctx.out.result({ ...me, env: ctx.target.env, account: ctx.target.accountName }, () => {
|
|
40579
|
+
const { out, target } = ctx;
|
|
40350
40580
|
const who = me.username ? `@${me.username}` : me.email;
|
|
40351
|
-
const role = me.role === "staff" ?
|
|
40352
|
-
const via = me.auth.via === "api_key" ? `API key
|
|
40353
|
-
|
|
40354
|
-
|
|
40355
|
-
|
|
40581
|
+
const role = me.role === "staff" ? import_picocolors4.default.dim(" \xB7 staff") : "";
|
|
40582
|
+
const via = me.auth.via === "api_key" ? `an API key (${(me.auth.scopes ?? []).join(", ") || "no scopes"})` : "a session";
|
|
40583
|
+
const saved = target.accountName ? `, saved as account "${target.accountName}"` : "";
|
|
40584
|
+
out.line();
|
|
40585
|
+
out.line(
|
|
40586
|
+
` ${pink(symbols().done)} ${import_picocolors4.default.bold(who)} on ${placeOf(target.origin)} ${import_picocolors4.default.dim(`(${target.env})`)}${role}`
|
|
40587
|
+
);
|
|
40588
|
+
out.line(import_picocolors4.default.dim(` Signed in with ${via}${saved}.`));
|
|
40589
|
+
if (me.orgs.length) {
|
|
40590
|
+
out.line();
|
|
40591
|
+
out.line(` ${import_picocolors4.default.dim("Orgs")}`);
|
|
40592
|
+
const wide = Math.max(...me.orgs.map((org) => org.slug.length));
|
|
40593
|
+
for (const org of me.orgs) {
|
|
40594
|
+
out.line(` ${org.slug.padEnd(wide)} ${import_picocolors4.default.dim(`${org.kind}, ${org.role}`)}`);
|
|
40595
|
+
}
|
|
40596
|
+
}
|
|
40597
|
+
out.line();
|
|
40356
40598
|
});
|
|
40357
40599
|
}
|
|
40358
40600
|
async function logout(ctx) {
|
|
@@ -40376,11 +40618,28 @@ async function logout(ctx) {
|
|
|
40376
40618
|
}
|
|
40377
40619
|
const git = await signOutOfGit(ctx);
|
|
40378
40620
|
ctx.out.result({ account: name, revoked, git }, () => {
|
|
40379
|
-
|
|
40380
|
-
|
|
40381
|
-
|
|
40621
|
+
const { out, target } = ctx;
|
|
40622
|
+
const mark = symbols();
|
|
40623
|
+
out.line();
|
|
40624
|
+
if (name) {
|
|
40625
|
+
const which = import_picocolors4.default.dim(`(account "${name}")`);
|
|
40626
|
+
out.line(` ${pink(mark.done)} Signed out of ${placeOf(target.origin)} ${which}`);
|
|
40627
|
+
if (revoked) out.line(import_picocolors4.default.dim(" Its key is revoked, and pch keeps no copy."));
|
|
40628
|
+
else {
|
|
40629
|
+
out.line(
|
|
40630
|
+
` ${import_picocolors4.default.bold(mark.note)} The key wasn't revoked: revoke it in your settings on ${placeOf(target.origin)} if you need to.`
|
|
40631
|
+
);
|
|
40632
|
+
}
|
|
40633
|
+
} else {
|
|
40634
|
+
out.line(
|
|
40635
|
+
` ${pink(mark.done)} Nothing saved to sign out of: PCH_TOKEN stays set, and pch keeps no copy.`
|
|
40636
|
+
);
|
|
40382
40637
|
}
|
|
40383
|
-
if (git.url && !git.helper)
|
|
40638
|
+
if (git.url && !git.helper) out.line(import_picocolors4.default.dim(` Git is signed out of ${placeOf(git.url)}.`));
|
|
40639
|
+
out.line();
|
|
40640
|
+
if (name)
|
|
40641
|
+
out.line(` ${import_picocolors4.default.dim("Sign in again with")} ${import_picocolors4.default.bold(`${pchOn(target.env)} login`)}`);
|
|
40642
|
+
if (name) out.line();
|
|
40384
40643
|
});
|
|
40385
40644
|
}
|
|
40386
40645
|
async function signOutOfGit(ctx) {
|
|
@@ -40400,7 +40659,7 @@ async function accountList(ctx) {
|
|
|
40400
40659
|
ctx.out.result({ data: accounts }, () => {
|
|
40401
40660
|
if (!accounts.length) ctx.out.line("No saved logins. Run pch login.");
|
|
40402
40661
|
for (const account2 of accounts) {
|
|
40403
|
-
const marker = account2.active ?
|
|
40662
|
+
const marker = account2.active ? import_picocolors4.default.green("*") : " ";
|
|
40404
40663
|
const who = account2.username ? `@${account2.username}` : "";
|
|
40405
40664
|
ctx.out.line(`${marker} ${account2.name.padEnd(12)} ${account2.env.padEnd(10)} ${who}`);
|
|
40406
40665
|
}
|
|
@@ -40439,7 +40698,7 @@ async function tokenCreate(ctx, options) {
|
|
|
40439
40698
|
ctx.out.result(created, () => {
|
|
40440
40699
|
ctx.out.line(created.key);
|
|
40441
40700
|
process.stderr.write(
|
|
40442
|
-
|
|
40701
|
+
import_picocolors4.default.dim("Shown once. Store it as PCH_TOKEN where your agent or CI runs.\n")
|
|
40443
40702
|
);
|
|
40444
40703
|
});
|
|
40445
40704
|
}
|
|
@@ -40450,7 +40709,7 @@ async function tokenList(ctx) {
|
|
|
40450
40709
|
if (!tokens.data.length) ctx.out.line("No API keys.");
|
|
40451
40710
|
for (const token2 of tokens.data) {
|
|
40452
40711
|
ctx.out.line(
|
|
40453
|
-
`${token2.id} ${(token2.name ?? "").padEnd(24)} ${token2.scopes.join(",").padEnd(18)} ${
|
|
40712
|
+
`${token2.id} ${(token2.name ?? "").padEnd(24)} ${token2.scopes.join(",").padEnd(18)} ${import_picocolors4.default.dim(token2.start ? `${token2.start}\u2026` : "")}`
|
|
40454
40713
|
);
|
|
40455
40714
|
}
|
|
40456
40715
|
});
|
|
@@ -40462,7 +40721,7 @@ async function tokenRevoke(ctx, id) {
|
|
|
40462
40721
|
}
|
|
40463
40722
|
|
|
40464
40723
|
// src/commands/agent-brief.ts
|
|
40465
|
-
var
|
|
40724
|
+
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
40466
40725
|
import { constants } from "node:fs";
|
|
40467
40726
|
import { access as access2, copyFile, lstat, mkdir as mkdir2, readdir as readdir2, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
40468
40727
|
import { basename, dirname as dirname3, extname, join as join5, resolve as resolve4 } from "node:path";
|
|
@@ -41216,7 +41475,8 @@ function parseInstallPath(value) {
|
|
|
41216
41475
|
if (rest && !isReleasePath(rest)) return null;
|
|
41217
41476
|
return { root, game: game ?? null, path: rest };
|
|
41218
41477
|
}
|
|
41219
|
-
var
|
|
41478
|
+
var PATH_MAX = 512;
|
|
41479
|
+
var installPath = external_exports.string().max(PATH_MAX, `must be at most ${PATH_MAX} characters`).refine(
|
|
41220
41480
|
(value) => parseInstallPath(value) !== null,
|
|
41221
41481
|
`must start with a folder like {game} or {profile} (${INSTALL_ROOTS.map((root) => `{${root}}`).join(", ")}, or {game:slug} for another listed game) and never use ..`
|
|
41222
41482
|
);
|
|
@@ -41228,19 +41488,19 @@ var gameEntry = external_exports.object({
|
|
|
41228
41488
|
),
|
|
41229
41489
|
version: shortLine(80).optional().describe('The game versions it works with, in words or as a range, e.g. ">=1.6".'),
|
|
41230
41490
|
stores: external_exports.array(store).min(1).optional(),
|
|
41231
|
-
builds: external_exports.partialRecord(store, external_exports.array(external_exports.string().min(1)).min(1)).optional().describe("Exact builds per store; leave out to accept any build.")
|
|
41491
|
+
builds: external_exports.partialRecord(store, external_exports.array(external_exports.string().min(1).max(80)).min(1).max(32)).optional().describe("Exact builds per store; leave out to accept any build.")
|
|
41232
41492
|
});
|
|
41233
41493
|
var component = external_exports.object({
|
|
41234
41494
|
id: external_exports.string().regex(componentId, "must be lowercase letters, digits, . _ or -"),
|
|
41235
|
-
file: external_exports.string().refine((value) => value === "" || isReleasePath(value), "must be a path inside the release").describe('One uploaded file, a folder of them ending in "/", or "" for every file.'),
|
|
41495
|
+
file: external_exports.string().max(PATH_MAX, `must be at most ${PATH_MAX} characters`).refine((value) => value === "" || isReleasePath(value), "must be a path inside the release").describe('One uploaded file, a folder of them ending in "/", or "" for every file.'),
|
|
41236
41496
|
label: shortLine(80).optional().describe('What it is, e.g. "Main files".'),
|
|
41237
41497
|
kind: external_exports.enum(["main", "optional", "extra"]).default("main").describe("main: what players need. optional: players can turn it on. extra: not installed."),
|
|
41238
41498
|
required: external_exports.boolean().optional(),
|
|
41239
41499
|
extract: external_exports.boolean().optional().describe("The file is a zip to unpack when it's installed.")
|
|
41240
41500
|
});
|
|
41241
41501
|
var mapping = external_exports.object({
|
|
41242
|
-
component: external_exports.string(),
|
|
41243
|
-
from: external_exports.string().refine((value) => value === "" || isReleasePath(value), "must be a path inside the component").default("").describe('"" for all of the component, "folder/" for a folder of it, or one file.'),
|
|
41502
|
+
component: external_exports.string().max(64),
|
|
41503
|
+
from: external_exports.string().max(PATH_MAX, `must be at most ${PATH_MAX} characters`).refine((value) => value === "" || isReleasePath(value), "must be a path inside the component").default("").describe('"" for all of the component, "folder/" for a folder of it, or one file.'),
|
|
41244
41504
|
to: installPath
|
|
41245
41505
|
});
|
|
41246
41506
|
var requirement = external_exports.discriminatedUnion(
|
|
@@ -41399,10 +41659,11 @@ var recipeSchema = external_exports.object({
|
|
|
41399
41659
|
mode: external_exports.enum(["browser", "installed", "standalone", "workshop", "manual"]).optional().describe(
|
|
41400
41660
|
"browser: plays in Patch's game window. installed: into a game on the player's PC. standalone: a program of its own. workshop: a Steam Workshop item. manual: players install it by hand. Left out: browser, or installed when there's a host game."
|
|
41401
41661
|
),
|
|
41402
|
-
|
|
41403
|
-
|
|
41404
|
-
|
|
41405
|
-
|
|
41662
|
+
// Limits far past any real recipe, so checking one stays cheap.
|
|
41663
|
+
games: external_exports.array(gameEntry).max(16, "can have at most 16 games").default([]),
|
|
41664
|
+
components: external_exports.array(component).min(1).max(64, "can have at most 64 components").optional().describe('Left out: one main component, "main", holding every file.'),
|
|
41665
|
+
mappings: external_exports.array(mapping).max(64, "can have at most 64 mappings").default([]).describe("Where each component's files go."),
|
|
41666
|
+
requirements: external_exports.array(requirement).max(32, "can have at most 32 requirements").default([]),
|
|
41406
41667
|
launch: launch.optional().describe("Left out: index.html for a browser game, the game itself otherwise."),
|
|
41407
41668
|
settings: external_exports.array(
|
|
41408
41669
|
external_exports.object({
|
|
@@ -41455,12 +41716,12 @@ var recipeSchema = external_exports.object({
|
|
|
41455
41716
|
workshop: external_exports.object({ steam_app_id: external_exports.string().regex(/^\d+$/), file_id: external_exports.string().regex(/^\d+$/) }).optional(),
|
|
41456
41717
|
credits: external_exports.array(
|
|
41457
41718
|
external_exports.object({
|
|
41458
|
-
files: external_exports.string().min(1),
|
|
41459
|
-
license: external_exports.string().min(1).describe("SPDX id, e.g. CC0-1.0 or MIT."),
|
|
41460
|
-
source: external_exports.string().url().optional(),
|
|
41461
|
-
author: external_exports.string().optional()
|
|
41719
|
+
files: external_exports.string().min(1).max(PATH_MAX),
|
|
41720
|
+
license: external_exports.string().min(1).max(200).describe("SPDX id, e.g. CC0-1.0 or MIT."),
|
|
41721
|
+
source: external_exports.string().url().max(2e3).optional(),
|
|
41722
|
+
author: external_exports.string().max(200).optional()
|
|
41462
41723
|
})
|
|
41463
|
-
).default([])
|
|
41724
|
+
).max(500, "can have at most 500 credits").default([])
|
|
41464
41725
|
}).strict();
|
|
41465
41726
|
|
|
41466
41727
|
// src/manifest/safety.ts
|
|
@@ -42359,7 +42620,7 @@ function hashFile(path2) {
|
|
|
42359
42620
|
}
|
|
42360
42621
|
|
|
42361
42622
|
// src/commands/agent-guide.ts
|
|
42362
|
-
var
|
|
42623
|
+
var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
42363
42624
|
import { access, writeFile as writeFile2 } from "node:fs/promises";
|
|
42364
42625
|
import { join as join4, resolve as resolve3 } from "node:path";
|
|
42365
42626
|
|
|
@@ -42514,12 +42775,12 @@ async function agentGuide(ctx, dir) {
|
|
|
42514
42775
|
const { name, written } = await writeAgentGuide(root);
|
|
42515
42776
|
ctx.out.result({ path: join4(root, name), written }, () => {
|
|
42516
42777
|
if (written) {
|
|
42517
|
-
ctx.out.line(`Wrote ${
|
|
42518
|
-
ctx.out.line(
|
|
42778
|
+
ctx.out.line(`Wrote ${import_picocolors5.default.bold(join4(root, name))}, for coding agents working in this folder.`);
|
|
42779
|
+
ctx.out.line(import_picocolors5.default.dim("Commit it: in a clone, pch publish refuses files that aren't."));
|
|
42519
42780
|
} else {
|
|
42520
42781
|
ctx.out.line(`${join4(root, name)} is this folder's guide for agents, so it's left as it is.`);
|
|
42521
42782
|
ctx.out.line(
|
|
42522
|
-
|
|
42783
|
+
import_picocolors5.default.dim("pch guide has how to run, check and publish, to add to it if it helps.")
|
|
42523
42784
|
);
|
|
42524
42785
|
}
|
|
42525
42786
|
});
|
|
@@ -42545,10 +42806,10 @@ async function askForBrief(lines, say) {
|
|
|
42545
42806
|
};
|
|
42546
42807
|
const answers = [];
|
|
42547
42808
|
for (const { ask } of QUESTIONS) {
|
|
42548
|
-
say(
|
|
42809
|
+
say(import_picocolors6.default.bold(ask));
|
|
42549
42810
|
answers.push((await untilBlank()).join("\n"));
|
|
42550
42811
|
}
|
|
42551
|
-
say(
|
|
42812
|
+
say(import_picocolors6.default.bold(PICTURES_ASK));
|
|
42552
42813
|
return { answers, pictures: await untilBlank() };
|
|
42553
42814
|
}
|
|
42554
42815
|
function briefText(answers, pictures) {
|
|
@@ -42638,7 +42899,7 @@ async function agentBrief(ctx, dir) {
|
|
|
42638
42899
|
ctx.out.step(
|
|
42639
42900
|
`A brief stays with this game, and every agent that works on it reads it first. ${PUBLIC}`
|
|
42640
42901
|
);
|
|
42641
|
-
ctx.out.step(
|
|
42902
|
+
ctx.out.step(import_picocolors6.default.dim("A blank line ends an answer, or skips the question."));
|
|
42642
42903
|
const said2 = await fromTerminal(ctx);
|
|
42643
42904
|
const pictures = await gatherPictures(root, said2.pictures, (line) => ctx.out.step(line));
|
|
42644
42905
|
const text = briefText(said2.answers, pictures);
|
|
@@ -42652,13 +42913,13 @@ async function agentBrief(ctx, dir) {
|
|
|
42652
42913
|
await writeAgentGuide(root);
|
|
42653
42914
|
const silent = await guidesNotNaming(root);
|
|
42654
42915
|
ctx.out.result({ path: path2, written: true, pictures, guides_without_it: silent }, () => {
|
|
42655
|
-
ctx.out.line(`Wrote ${
|
|
42916
|
+
ctx.out.line(`Wrote ${import_picocolors6.default.bold(path2)}. Change it whenever you like: it's yours.`);
|
|
42656
42917
|
for (const name of silent) {
|
|
42657
42918
|
ctx.out.line(
|
|
42658
42919
|
`${name} doesn't mention it, so agents may not read it. Add this to it: Read ${BRIEF_FILE} first: it's my idea and rules for this game.`
|
|
42659
42920
|
);
|
|
42660
42921
|
}
|
|
42661
|
-
ctx.out.line(
|
|
42922
|
+
ctx.out.line(import_picocolors6.default.dim("Commit it, and every agent that clones this repo starts with it."));
|
|
42662
42923
|
});
|
|
42663
42924
|
}
|
|
42664
42925
|
async function guidesNotNaming(root) {
|
|
@@ -42671,9 +42932,9 @@ async function guidesNotNaming(root) {
|
|
|
42671
42932
|
}
|
|
42672
42933
|
|
|
42673
42934
|
// src/commands/agent-install.ts
|
|
42674
|
-
var
|
|
42935
|
+
var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
42675
42936
|
init_errors();
|
|
42676
|
-
import { spawnSync } from "node:child_process";
|
|
42937
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
42677
42938
|
import { existsSync as existsSync2 } from "node:fs";
|
|
42678
42939
|
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
|
|
42679
42940
|
import { homedir as homedir2 } from "node:os";
|
|
@@ -42703,14 +42964,14 @@ async function agentInstall(ctx, named, options = {}) {
|
|
|
42703
42964
|
for (const entry of agents) {
|
|
42704
42965
|
const name = AGENT_NAMES[entry.agent];
|
|
42705
42966
|
if (entry.state === "manual") {
|
|
42706
|
-
ctx.out.line(`${
|
|
42967
|
+
ctx.out.line(`${import_picocolors7.default.bold(name)}: pch can't do this here. ${entry.how}`);
|
|
42707
42968
|
} else {
|
|
42708
42969
|
ctx.out.line(
|
|
42709
|
-
`${
|
|
42970
|
+
`${import_picocolors7.default.green(`${name}:`)} ${entry.state} the ${import_picocolors7.default.bold(server.name)} MCP server, in ${entry.where}.`
|
|
42710
42971
|
);
|
|
42711
42972
|
}
|
|
42712
42973
|
}
|
|
42713
|
-
ctx.out.line(
|
|
42974
|
+
ctx.out.line(import_picocolors7.default.dim(`It runs ${commandLine(server)}, and holds no key.`));
|
|
42714
42975
|
if (!signedIn2) ctx.out.line(`Sign in first, or its tools won't work: ${pchLogin(ctx)}.`);
|
|
42715
42976
|
ctx.out.line(
|
|
42716
42977
|
"Restart your agent to load its tools. Until then, pch guide prints the same guide."
|
|
@@ -42828,11 +43089,11 @@ function onPath(bin) {
|
|
|
42828
43089
|
function run(bin, args2) {
|
|
42829
43090
|
const shell = process.platform === "win32";
|
|
42830
43091
|
const quoted = shell ? args2.map((arg) => /\s/.test(arg) ? `"${arg}"` : arg) : args2;
|
|
42831
|
-
return
|
|
43092
|
+
return spawnSync2(bin, quoted, { encoding: "utf8", shell, timeout: 6e4 });
|
|
42832
43093
|
}
|
|
42833
43094
|
|
|
42834
43095
|
// src/commands/assets.ts
|
|
42835
|
-
var
|
|
43096
|
+
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
42836
43097
|
import { createHash as createHash2 } from "node:crypto";
|
|
42837
43098
|
import { mkdir as mkdir4, readFile as readFile5, stat as stat2, writeFile as writeFile5 } from "node:fs/promises";
|
|
42838
43099
|
import { basename as basename2, dirname as dirname5, extname as extname2, isAbsolute, join as join7, relative as relative2, resolve as resolve6, sep as sep3 } from "node:path";
|
|
@@ -42873,17 +43134,17 @@ async function assetsSearch(ctx, q, options) {
|
|
|
42873
43134
|
for (const hit of found.hits) {
|
|
42874
43135
|
const size = hit.fit?.mb ? ` \xB7 ${hit.fit.mb} MB` : "";
|
|
42875
43136
|
ctx.out.line(
|
|
42876
|
-
`${
|
|
43137
|
+
`${import_picocolors8.default.bold(plain(hit.id))} ${import_picocolors8.default.dim(`${hit.type} \xB7 ${hit.license}${size}${hit.ai ? " \xB7 AI-generated" : ""}`)}`
|
|
42877
43138
|
);
|
|
42878
43139
|
ctx.out.line(` ${plain(hit.title)}`);
|
|
42879
|
-
if (hit.thumbnail_url) ctx.out.line(
|
|
43140
|
+
if (hit.thumbnail_url) ctx.out.line(import_picocolors8.default.dim(` ${plain(hit.thumbnail_url)}`));
|
|
42880
43141
|
}
|
|
42881
43142
|
ctx.out.line(
|
|
42882
|
-
|
|
43143
|
+
import_picocolors8.default.dim(
|
|
42883
43144
|
`${found.total} in all. Look at the pictures, as titles don't say how an asset looks, then pch assets add <id>\u2026`
|
|
42884
43145
|
)
|
|
42885
43146
|
);
|
|
42886
|
-
if (found.next_cursor) ctx.out.line(
|
|
43147
|
+
if (found.next_cursor) ctx.out.line(import_picocolors8.default.dim(`More: --cursor ${found.next_cursor}`));
|
|
42887
43148
|
});
|
|
42888
43149
|
}
|
|
42889
43150
|
async function assetsFacets(ctx, q, options) {
|
|
@@ -42895,11 +43156,11 @@ async function assetsFacets(ctx, q, options) {
|
|
|
42895
43156
|
async function assetsView(ctx, id) {
|
|
42896
43157
|
const asset = await unwrap(ctx.api.GET("/assets/{id}", { params: { path: { id } } }));
|
|
42897
43158
|
ctx.out.result(asset, () => {
|
|
42898
|
-
ctx.out.line(`${
|
|
43159
|
+
ctx.out.line(`${import_picocolors8.default.bold(plain(asset.title))} ${import_picocolors8.default.dim(asset.id)}`);
|
|
42899
43160
|
ctx.out.line(`${asset.type_label} \xB7 ${asset.license.spdx} \xB7 ${plain(asset.source.name)}`);
|
|
42900
43161
|
if (asset.description) ctx.out.line(plain(asset.description));
|
|
42901
43162
|
ctx.out.line(`Credit: ${plain(asset.credit)}`);
|
|
42902
|
-
ctx.out.line(
|
|
43163
|
+
ctx.out.line(import_picocolors8.default.dim(`Take it with pch assets add ${asset.id}`));
|
|
42903
43164
|
});
|
|
42904
43165
|
}
|
|
42905
43166
|
async function assetsAdd(ctx, ids, options) {
|
|
@@ -42980,13 +43241,13 @@ async function assetsAdd(ctx, ids, options) {
|
|
|
42980
43241
|
},
|
|
42981
43242
|
() => {
|
|
42982
43243
|
ctx.out.line(
|
|
42983
|
-
|
|
43244
|
+
import_picocolors8.default.green(`Copied ${copied.length} ${copied.length === 1 ? "file" : "files"} to ${root}.`)
|
|
42984
43245
|
);
|
|
42985
43246
|
for (const entry of usage3) {
|
|
42986
|
-
ctx.out.line(`${
|
|
43247
|
+
ctx.out.line(`${import_picocolors8.default.bold(entry.id)} is at ${entry.path}`);
|
|
42987
43248
|
ctx.out.line(` ${plain(entry.usage)}`);
|
|
42988
43249
|
}
|
|
42989
|
-
for (const warning of plan.warnings) ctx.out.line(
|
|
43250
|
+
for (const warning of plan.warnings) ctx.out.line(import_picocolors8.default.dim(plain(warning.msg)));
|
|
42990
43251
|
ctx.out.line("Load them by relative path, and commit them: the release carries its files.");
|
|
42991
43252
|
ctx.out.line(
|
|
42992
43253
|
`Their credits are in ${fromHere(creditsFile)}. Keep it in the release, with the licences, and show them on a credits screen in the game.`
|
|
@@ -43113,7 +43374,7 @@ async function saveChecked(url2, path2, sha256) {
|
|
|
43113
43374
|
}
|
|
43114
43375
|
|
|
43115
43376
|
// src/commands/catalog.ts
|
|
43116
|
-
var
|
|
43377
|
+
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
43117
43378
|
import { randomUUID } from "node:crypto";
|
|
43118
43379
|
import { readFile as readFile6 } from "node:fs/promises";
|
|
43119
43380
|
init_errors();
|
|
@@ -43216,18 +43477,18 @@ async function projectCreate(ctx, ref, options) {
|
|
|
43216
43477
|
) : (await ctx.api.GET("/projects/{owner}/{slug}/repo", path2)).data;
|
|
43217
43478
|
const whoCanSee = repo?.visibility === "private" ? { who_can_see: PRIVATE_REPO } : {};
|
|
43218
43479
|
ctx.out.result({ ...project2, repo_visibility: repo?.visibility ?? null, ...whoCanSee }, () => {
|
|
43219
|
-
ctx.out.line(`Created ${
|
|
43480
|
+
ctx.out.line(`Created ${import_picocolors9.default.bold(project2.handle)}`);
|
|
43220
43481
|
ctx.out.line(
|
|
43221
43482
|
` Source: ${SOURCE_LABELS[project2.source_visibility]} \xB7 code ${project2.code_license} \xB7 art ${project2.art_license}`
|
|
43222
43483
|
);
|
|
43223
43484
|
if (repo) ctx.out.line(` Repo: ${VISIBILITY_LABELS[repo.visibility]}`);
|
|
43224
43485
|
if (repo?.visibility === "private") ctx.out.line(` ${PRIVATE_REPO_NOT_LOCKED}`);
|
|
43225
43486
|
ctx.out.line(
|
|
43226
|
-
|
|
43487
|
+
import_picocolors9.default.dim(
|
|
43227
43488
|
`Change these with pch project update ${project2.handle}${repo ? ` and pch set ${project2.handle} --visibility \u2026` : ""}.`
|
|
43228
43489
|
)
|
|
43229
43490
|
);
|
|
43230
|
-
ctx.out.line(
|
|
43491
|
+
ctx.out.line(import_picocolors9.default.dim(projectUrl(ctx.target.origin, { owner, slug: slug2 })));
|
|
43231
43492
|
});
|
|
43232
43493
|
}
|
|
43233
43494
|
async function projectView(ctx, ref) {
|
|
@@ -43250,7 +43511,7 @@ async function projectView(ctx, ref) {
|
|
|
43250
43511
|
openCode
|
|
43251
43512
|
].filter(Boolean).join(" ");
|
|
43252
43513
|
ctx.out.result({ ...project2, ...whoCanSee ? { who_can_see: whoCanSee } : {} }, () => {
|
|
43253
|
-
ctx.out.line(`${
|
|
43514
|
+
ctx.out.line(`${import_picocolors9.default.bold(project2.name)} ${import_picocolors9.default.dim(project2.handle)}`);
|
|
43254
43515
|
if (project2.summary) ctx.out.line(project2.summary);
|
|
43255
43516
|
const kind = project2.kind ? KIND_LABELS[project2.kind] : "not published yet";
|
|
43256
43517
|
const games = project2.host_games.map((game) => `${game.name} (${game.role})`).join(", ");
|
|
@@ -43281,7 +43542,7 @@ async function projectView(ctx, ref) {
|
|
|
43281
43542
|
`Source: ${repo ? VISIBILITY_LABELS[repo.visibility] : SOURCE_LABELS[project2.source_visibility]} \xB7 code ${project2.code_license} \xB7 art ${project2.art_license}`
|
|
43282
43543
|
);
|
|
43283
43544
|
if (repo?.visibility === "private" && !notLocked) ctx.out.line(PRIVATE_REPO_NOT_LOCKED);
|
|
43284
|
-
ctx.out.line(
|
|
43545
|
+
ctx.out.line(import_picocolors9.default.dim(projectUrl(ctx.target.origin, { owner, slug: slug2 })));
|
|
43285
43546
|
});
|
|
43286
43547
|
}
|
|
43287
43548
|
var LINK_NAMES = ["discord", "x", "telegram", "youtube", "twitch", "github"];
|
|
@@ -43317,8 +43578,8 @@ async function projectUpdate(ctx, ref, options) {
|
|
|
43317
43578
|
})
|
|
43318
43579
|
);
|
|
43319
43580
|
ctx.out.result(updated, () => {
|
|
43320
|
-
ctx.out.line(`Updated ${
|
|
43321
|
-
ctx.out.line(
|
|
43581
|
+
ctx.out.line(`Updated ${import_picocolors9.default.bold(updated.handle)}`);
|
|
43582
|
+
ctx.out.line(import_picocolors9.default.dim(updated.urls?.page ?? projectUrl(ctx.target.origin, updated)));
|
|
43322
43583
|
});
|
|
43323
43584
|
}
|
|
43324
43585
|
function parseLinks(values) {
|
|
@@ -43352,7 +43613,7 @@ async function myProjects(ctx) {
|
|
|
43352
43613
|
if (!data.length) ctx.out.line("No projects yet. Start one with pch new <you>/<slug>.");
|
|
43353
43614
|
for (const project2 of data) {
|
|
43354
43615
|
ctx.out.line(
|
|
43355
|
-
`${project2.handle.padEnd(32)} ${(project2.kind ?? "").padEnd(14)} ${project2.latest_version?.version ??
|
|
43616
|
+
`${project2.handle.padEnd(32)} ${(project2.kind ?? "").padEnd(14)} ${project2.latest_version?.version ?? import_picocolors9.default.dim("nothing published")}`
|
|
43356
43617
|
);
|
|
43357
43618
|
}
|
|
43358
43619
|
});
|
|
@@ -43392,41 +43653,41 @@ async function releaseList(ctx, ref) {
|
|
|
43392
43653
|
} while (cursor);
|
|
43393
43654
|
ctx.out.result({ data }, () => {
|
|
43394
43655
|
if (!data.length) ctx.out.line("No releases.");
|
|
43395
|
-
for (const
|
|
43656
|
+
for (const release3 of data) {
|
|
43396
43657
|
ctx.out.line(
|
|
43397
|
-
`${
|
|
43658
|
+
`${release3.version.padEnd(12)} ${release3.channel.padEnd(9)} ${release3.status.padEnd(10)} ${import_picocolors9.default.dim(release3.published_at ?? release3.created_at)}`
|
|
43398
43659
|
);
|
|
43399
43660
|
}
|
|
43400
43661
|
});
|
|
43401
43662
|
}
|
|
43402
43663
|
async function releaseView(ctx, ref) {
|
|
43403
43664
|
const { owner, slug: slug2, version: version2 } = parseReleaseRef(ref);
|
|
43404
|
-
const
|
|
43665
|
+
const release3 = await unwrap(
|
|
43405
43666
|
ctx.api.GET("/projects/{owner}/{slug}/releases/{version}", {
|
|
43406
43667
|
params: { path: { owner, slug: slug2, version: version2 } }
|
|
43407
43668
|
})
|
|
43408
43669
|
);
|
|
43409
|
-
const repo =
|
|
43410
|
-
const openCode = openCodeWords(`${owner}/${slug2}`, repo?.data,
|
|
43411
|
-
ctx.out.result({ ...
|
|
43412
|
-
ctx.out.line(`${
|
|
43670
|
+
const repo = release3.channel === "private" ? await ctx.api.GET("/projects/{owner}/{slug}/repo", { params: { path: { owner, slug: slug2 } } }).catch(() => null) : null;
|
|
43671
|
+
const openCode = openCodeWords(`${owner}/${slug2}`, repo?.data, release3);
|
|
43672
|
+
ctx.out.result({ ...release3, ...openCode ? { who_can_see: openCode } : {} }, () => {
|
|
43673
|
+
ctx.out.line(`${import_picocolors9.default.bold(`${release3.project}@${release3.version}`)} ${release3.kind ?? ""}`);
|
|
43413
43674
|
ctx.out.line(
|
|
43414
|
-
`Channel ${
|
|
43675
|
+
`Channel ${release3.channel} \xB7 ${release3.status} \xB7 ${TRUST_LABELS[release3.trust_tier]}`
|
|
43415
43676
|
);
|
|
43416
43677
|
if (openCode) ctx.out.line(openCode);
|
|
43417
|
-
if (
|
|
43418
|
-
ctx.out.line(`From commit ${
|
|
43678
|
+
if (release3.commit) {
|
|
43679
|
+
ctx.out.line(`From commit ${release3.commit}${release3.tag ? `, tag ${release3.tag}` : ""}`);
|
|
43419
43680
|
}
|
|
43420
|
-
for (const requirement2 of
|
|
43681
|
+
for (const requirement2 of release3.requirements) {
|
|
43421
43682
|
ctx.out.line(`Needs ${requirement2.name} (${requirement2.role})`);
|
|
43422
43683
|
}
|
|
43423
|
-
if (
|
|
43424
|
-
for (const file2 of
|
|
43684
|
+
if (release3.changelog) ctx.out.line(plain(release3.changelog));
|
|
43685
|
+
for (const file2 of release3.files) {
|
|
43425
43686
|
ctx.out.line(
|
|
43426
|
-
` ${file2.path.padEnd(40)} ${formatSize(file2.size).padStart(8)} ${
|
|
43687
|
+
` ${file2.path.padEnd(40)} ${formatSize(file2.size).padStart(8)} ${import_picocolors9.default.dim(file2.sha256)}`
|
|
43427
43688
|
);
|
|
43428
43689
|
if (file2.url) ctx.out.line(` ${file2.url}`);
|
|
43429
|
-
else if (file2.url === null) ctx.out.line(
|
|
43690
|
+
else if (file2.url === null) ctx.out.line(import_picocolors9.default.dim(" can't be had right now"));
|
|
43430
43691
|
}
|
|
43431
43692
|
});
|
|
43432
43693
|
}
|
|
@@ -43435,7 +43696,7 @@ async function hostGameSearch(ctx, q, limit2) {
|
|
|
43435
43696
|
ctx.out.result(games, () => {
|
|
43436
43697
|
if (!games.data.length) ctx.out.line("No host games found.");
|
|
43437
43698
|
for (const game of games.data) ctx.out.line(`${game.slug.padEnd(28)} ${game.name}`);
|
|
43438
|
-
if (games.next_cursor) ctx.out.line(
|
|
43699
|
+
if (games.next_cursor) ctx.out.line(import_picocolors9.default.dim("More match; narrow the search or raise --limit."));
|
|
43439
43700
|
});
|
|
43440
43701
|
}
|
|
43441
43702
|
var WIKI_PAGE = /^(engines|methods)\/([a-z0-9][a-z0-9-]*)(?:\.md)?$/;
|
|
@@ -43449,7 +43710,7 @@ function showWikiPage(ctx, page) {
|
|
|
43449
43710
|
page.build_seen && `build: ${page.build_seen}`
|
|
43450
43711
|
].filter(Boolean).join(" \xB7 ");
|
|
43451
43712
|
ctx.out.line();
|
|
43452
|
-
ctx.out.line(`${
|
|
43713
|
+
ctx.out.line(`${import_picocolors9.default.bold(page.path)} ${import_picocolors9.default.dim(plain(about))}`);
|
|
43453
43714
|
ctx.out.line(plain(page.text));
|
|
43454
43715
|
}
|
|
43455
43716
|
async function hostGameView(ctx, slug2) {
|
|
@@ -43477,13 +43738,13 @@ async function hostGameView(ctx, slug2) {
|
|
|
43477
43738
|
...unavailable ? { wiki_pages_unavailable: unavailable } : {}
|
|
43478
43739
|
};
|
|
43479
43740
|
ctx.out.result(result, () => {
|
|
43480
|
-
ctx.out.line(`${
|
|
43741
|
+
ctx.out.line(`${import_picocolors9.default.bold(game.name)} ${import_picocolors9.default.dim(game.slug)}`);
|
|
43481
43742
|
for (const store2 of game.stores) ctx.out.line(` ${store2.store} ${store2.ref}`);
|
|
43482
43743
|
for (const build of game.builds) {
|
|
43483
43744
|
ctx.out.line(` build ${build.store} ${build.build_ref} ${build.version_label ?? ""}`);
|
|
43484
43745
|
}
|
|
43485
|
-
if (!ctx.target.token) ctx.out.line(
|
|
43486
|
-
if (unavailable) ctx.out.line(
|
|
43746
|
+
if (!ctx.target.token) ctx.out.line(import_picocolors9.default.dim("Sign in with pch login for Patch's wiki pages."));
|
|
43747
|
+
if (unavailable) ctx.out.line(import_picocolors9.default.dim(`No wiki pages this time: ${plain(unavailable)}`));
|
|
43487
43748
|
for (const page of pages) showWikiPage(ctx, page);
|
|
43488
43749
|
});
|
|
43489
43750
|
}
|
|
@@ -43506,11 +43767,11 @@ async function noteSuggest(ctx, about, fact, options) {
|
|
|
43506
43767
|
}
|
|
43507
43768
|
const note2 = data;
|
|
43508
43769
|
ctx.out.result(note2, () => {
|
|
43509
|
-
ctx.out.line(`Suggested for ${
|
|
43770
|
+
ctx.out.line(`Suggested for ${import_picocolors9.default.bold(plain(note2.page))}. ${plain(note2.next)}`);
|
|
43510
43771
|
for (const finding of note2.findings) {
|
|
43511
43772
|
ctx.out.line(` ${finding.rule_id}: ${plain(finding.message)}`);
|
|
43512
|
-
if (finding.line) ctx.out.line(
|
|
43513
|
-
if (finding.suggestion) ctx.out.line(
|
|
43773
|
+
if (finding.line) ctx.out.line(import_picocolors9.default.dim(` ${plain(finding.line)}`));
|
|
43774
|
+
if (finding.suggestion) ctx.out.line(import_picocolors9.default.dim(` ${plain(finding.suggestion)}`));
|
|
43514
43775
|
}
|
|
43515
43776
|
});
|
|
43516
43777
|
}
|
|
@@ -43519,7 +43780,7 @@ function titleCase(slug2) {
|
|
|
43519
43780
|
}
|
|
43520
43781
|
|
|
43521
43782
|
// src/commands/change-requests.ts
|
|
43522
|
-
var
|
|
43783
|
+
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
43523
43784
|
init_errors();
|
|
43524
43785
|
var handle = (ref) => `${ref.owner}/${ref.slug}`;
|
|
43525
43786
|
var counted = (count, thing) => `${count} ${thing}${count === 1 ? "" : "s"}`;
|
|
@@ -43561,7 +43822,7 @@ async function changeRequestOpen(ctx, ref, options) {
|
|
|
43561
43822
|
const name = `${handle(project2)}#${request.number}`;
|
|
43562
43823
|
out.result({ project: handle(project2), ...request, ...ahead.fields }, () => {
|
|
43563
43824
|
const shown = plain(request);
|
|
43564
|
-
out.line(`Opened ${
|
|
43825
|
+
out.line(`Opened ${import_picocolors10.default.bold(name)}: ${shown.title}`);
|
|
43565
43826
|
out.line(`${handle(from)}'s ${shown.branch} into ${shown.into}`);
|
|
43566
43827
|
showStanding(ctx, shown, ahead);
|
|
43567
43828
|
});
|
|
@@ -43637,19 +43898,19 @@ function updateAdvice(request, steps) {
|
|
|
43637
43898
|
];
|
|
43638
43899
|
}
|
|
43639
43900
|
function showStanding({ out }, request, { fields }) {
|
|
43640
|
-
if (fields.up_to_date === true) out.line(
|
|
43901
|
+
if (fields.up_to_date === true) out.line(import_picocolors10.default.green("Up to date: it can merge."));
|
|
43641
43902
|
if (fields.up_to_date === false) {
|
|
43642
|
-
out.line(
|
|
43903
|
+
out.line(import_picocolors10.default.yellow(`Out of date: ${outOfDate(request)}`));
|
|
43643
43904
|
if (fields.update) for (const line of updateAdvice(request, fields.update)) out.line(line);
|
|
43644
43905
|
}
|
|
43645
43906
|
if (fields.up_to_date === null && request.state === "open") {
|
|
43646
43907
|
out.line(
|
|
43647
|
-
|
|
43908
|
+
import_picocolors10.default.yellow("Patch can't tell whether it's up to date just now. Try again in a moment.")
|
|
43648
43909
|
);
|
|
43649
43910
|
}
|
|
43650
43911
|
if (request.problems.length) {
|
|
43651
43912
|
out.line(
|
|
43652
|
-
|
|
43913
|
+
import_picocolors10.default.yellow(
|
|
43653
43914
|
"The latest push to its branch hasn't reached this request, so it stays where it was:"
|
|
43654
43915
|
)
|
|
43655
43916
|
);
|
|
@@ -43684,20 +43945,20 @@ async function changeRequestList(ctx, ref, options) {
|
|
|
43684
43945
|
}
|
|
43685
43946
|
for (const request of plain(data)) {
|
|
43686
43947
|
const open3 = request.state === "open";
|
|
43687
|
-
const state = request.up_to_date === false ?
|
|
43948
|
+
const state = request.up_to_date === false ? import_picocolors10.default.yellow("out of date".padEnd(12)) : open3 && request.up_to_date === null ? import_picocolors10.default.yellow("not checked".padEnd(12)) : request.state.padEnd(12);
|
|
43688
43949
|
const from = request.from ? `${request.from} ${request.branch}` : request.branch;
|
|
43689
43950
|
out.line(
|
|
43690
|
-
`#${String(request.number).padEnd(4)} ${state} ${request.title} ${
|
|
43951
|
+
`#${String(request.number).padEnd(4)} ${state} ${request.title} ${import_picocolors10.default.dim(`(${from} \u2192 ${request.into})`)}`
|
|
43691
43952
|
);
|
|
43692
43953
|
}
|
|
43693
43954
|
if (data.some((request) => request.up_to_date === false)) {
|
|
43694
43955
|
out.line(
|
|
43695
|
-
|
|
43956
|
+
import_picocolors10.default.dim(
|
|
43696
43957
|
`Out of date ones can't merge yet. pch change-request view ${handle(project2)}#<number> says how to update one.`
|
|
43697
43958
|
)
|
|
43698
43959
|
);
|
|
43699
43960
|
}
|
|
43700
|
-
if (cursor) out.line(
|
|
43961
|
+
if (cursor) out.line(import_picocolors10.default.dim("There are more; raise --limit."));
|
|
43701
43962
|
});
|
|
43702
43963
|
}
|
|
43703
43964
|
async function mapInTurn(items, size, run3) {
|
|
@@ -43743,7 +44004,7 @@ async function readRequest(ctx, ref) {
|
|
|
43743
44004
|
function showHeader(ctx, project2, request, diff, fetch2) {
|
|
43744
44005
|
const { out } = ctx;
|
|
43745
44006
|
out.line(
|
|
43746
|
-
`${
|
|
44007
|
+
`${import_picocolors10.default.bold(`${handle(project2)}#${request.number}`)} ${request.title} ${import_picocolors10.default.dim(request.state)}`
|
|
43747
44008
|
);
|
|
43748
44009
|
const parts = [
|
|
43749
44010
|
`${request.from ? `${request.from}'s ` : ""}${request.branch} into ${request.into}`,
|
|
@@ -43762,15 +44023,15 @@ function showHeader(ctx, project2, request, diff, fetch2) {
|
|
|
43762
44023
|
} else if (request.closed_by) {
|
|
43763
44024
|
out.line(`${request.state === "declined" ? "Declined" : "Withdrawn"} by ${request.closed_by}`);
|
|
43764
44025
|
}
|
|
43765
|
-
if (fetch2) out.line(
|
|
44026
|
+
if (fetch2) out.line(import_picocolors10.default.dim(`To get its commits: ${fetch2}`));
|
|
43766
44027
|
}
|
|
43767
44028
|
function showTalk({ out }, talk) {
|
|
43768
44029
|
if (!talk.length) return;
|
|
43769
44030
|
out.line();
|
|
43770
|
-
out.line(
|
|
44031
|
+
out.line(import_picocolors10.default.bold("Talk"));
|
|
43771
44032
|
for (const post of talk) {
|
|
43772
44033
|
const who = `${post.author ?? "someone"}${post.via === "api_key" ? " (with a key)" : ""}`;
|
|
43773
|
-
out.line(`${
|
|
44034
|
+
out.line(`${import_picocolors10.default.dim(`${who}, ${post.created_at}`)}`);
|
|
43774
44035
|
out.line(post.body);
|
|
43775
44036
|
}
|
|
43776
44037
|
}
|
|
@@ -43803,18 +44064,18 @@ async function changeRequestView(ctx, ref) {
|
|
|
43803
44064
|
function showFiles({ out }, diff) {
|
|
43804
44065
|
if (tooBigToList(diff)) {
|
|
43805
44066
|
out.line();
|
|
43806
|
-
out.line(
|
|
44067
|
+
out.line(import_picocolors10.default.yellow("There's more in this request than can show here."));
|
|
43807
44068
|
}
|
|
43808
44069
|
if (!diff.files.length) return;
|
|
43809
44070
|
out.line();
|
|
43810
44071
|
for (const file2 of diff.files.slice(0, FILES_SHOWN)) {
|
|
43811
44072
|
out.line(
|
|
43812
|
-
`${file2.status.padEnd(9)} ${file2.path} ${
|
|
44073
|
+
`${file2.status.padEnd(9)} ${file2.path} ${import_picocolors10.default.dim(`+${file2.additions} -${file2.deletions}`)}`
|
|
43813
44074
|
);
|
|
43814
44075
|
}
|
|
43815
44076
|
if (diff.files.length > FILES_SHOWN) {
|
|
43816
44077
|
out.line(
|
|
43817
|
-
|
|
44078
|
+
import_picocolors10.default.dim(
|
|
43818
44079
|
`And ${diff.files.length - FILES_SHOWN} more: pch change-request review has them all.`
|
|
43819
44080
|
)
|
|
43820
44081
|
);
|
|
@@ -43834,7 +44095,7 @@ async function changeRequestReview(ctx, ref) {
|
|
|
43834
44095
|
}
|
|
43835
44096
|
if (shown.diff) showDiff(ctx, shown.diff, shown.fetch);
|
|
43836
44097
|
else
|
|
43837
|
-
out.line(
|
|
44098
|
+
out.line(import_picocolors10.default.yellow("Patch couldn't read what it changes just now. Try again in a moment."));
|
|
43838
44099
|
showTalk(ctx, shown.talk);
|
|
43839
44100
|
});
|
|
43840
44101
|
}
|
|
@@ -43846,30 +44107,30 @@ var NO_PATCH = {
|
|
|
43846
44107
|
};
|
|
43847
44108
|
function showDiff({ out }, diff, fetch2) {
|
|
43848
44109
|
out.line();
|
|
43849
|
-
out.line(
|
|
44110
|
+
out.line(import_picocolors10.default.bold("Commits"));
|
|
43850
44111
|
for (const commit of diff.commits) {
|
|
43851
|
-
out.line(`${
|
|
44112
|
+
out.line(`${import_picocolors10.default.dim(commit.id.slice(0, 7))} ${commit.subject} ${import_picocolors10.default.dim(commit.author)}`);
|
|
43852
44113
|
}
|
|
43853
44114
|
if (diff.commit_count > diff.commits.length) {
|
|
43854
|
-
out.line(
|
|
44115
|
+
out.line(import_picocolors10.default.dim(`The newest ${diff.commits.length} of ${diff.commit_count}.`));
|
|
43855
44116
|
}
|
|
43856
44117
|
for (const file2 of diff.files) {
|
|
43857
44118
|
const moved2 = file2.old_path ? `${file2.old_path} \u2192 ` : "";
|
|
43858
44119
|
out.line();
|
|
43859
44120
|
out.line(
|
|
43860
|
-
`${
|
|
44121
|
+
`${import_picocolors10.default.bold(`${moved2}${file2.path}`)} ${import_picocolors10.default.dim(`${file2.status}, +${file2.additions} -${file2.deletions}`)}`
|
|
43861
44122
|
);
|
|
43862
44123
|
if (file2.big_file) {
|
|
43863
44124
|
const size = (side) => side ? formatSize(side.size) : "nothing";
|
|
43864
44125
|
out.line(`Big file: ${size(file2.big_file.old)} \u2192 ${size(file2.big_file.new)}`);
|
|
43865
44126
|
}
|
|
43866
44127
|
if (file2.patch) out.line(file2.patch.trimEnd());
|
|
43867
|
-
else if (file2.no_patch) out.line(
|
|
44128
|
+
else if (file2.no_patch) out.line(import_picocolors10.default.dim(NO_PATCH[file2.no_patch]));
|
|
43868
44129
|
}
|
|
43869
44130
|
if (diff.truncated) {
|
|
43870
44131
|
out.line();
|
|
43871
44132
|
out.line(
|
|
43872
|
-
|
|
44133
|
+
import_picocolors10.default.yellow(
|
|
43873
44134
|
tooBigToList(diff) ? `None of it can be shown here: there's more in this request than can show.${fetch2 ? ` To read it yourself: ${fetch2}` : ""}` : "Some of it isn't shown: patches stop at 300 files or 2 MiB, and the list at 3,000."
|
|
43874
44135
|
)
|
|
43875
44136
|
);
|
|
@@ -43911,7 +44172,7 @@ async function changeRequestMerge(ctx, ref, options) {
|
|
|
43911
44172
|
const request = merged.data;
|
|
43912
44173
|
out.result({ project: handle(project2), ...request }, () => {
|
|
43913
44174
|
const at = request.merge_commit ? ` at ${request.merge_commit.slice(0, 7)}` : "";
|
|
43914
|
-
out.line(`Merged ${
|
|
44175
|
+
out.line(`Merged ${import_picocolors10.default.bold(`${handle(project2)}#${number4}`)} into ${request.into}${at}.`);
|
|
43915
44176
|
});
|
|
43916
44177
|
}
|
|
43917
44178
|
async function cantMergeYet(ctx, project2, number4) {
|
|
@@ -43941,7 +44202,7 @@ async function changeRequestDecline(ctx, ref) {
|
|
|
43941
44202
|
})
|
|
43942
44203
|
);
|
|
43943
44204
|
out.result({ project: handle(project2), ...request }, () => {
|
|
43944
|
-
out.line(`Declined ${
|
|
44205
|
+
out.line(`Declined ${import_picocolors10.default.bold(`${handle(project2)}#${number4}`)}.`);
|
|
43945
44206
|
});
|
|
43946
44207
|
}
|
|
43947
44208
|
async function changeRequestWithdraw(ctx, ref) {
|
|
@@ -43954,12 +44215,12 @@ async function changeRequestWithdraw(ctx, ref) {
|
|
|
43954
44215
|
})
|
|
43955
44216
|
);
|
|
43956
44217
|
out.result({ project: handle(project2), ...request }, () => {
|
|
43957
|
-
out.line(`Withdrew ${
|
|
44218
|
+
out.line(`Withdrew ${import_picocolors10.default.bold(`${handle(project2)}#${number4}`)}.`);
|
|
43958
44219
|
});
|
|
43959
44220
|
}
|
|
43960
44221
|
|
|
43961
44222
|
// src/commands/check.ts
|
|
43962
|
-
var
|
|
44223
|
+
var import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
43963
44224
|
import { existsSync as existsSync4 } from "node:fs";
|
|
43964
44225
|
import { mkdir as mkdir6, mkdtemp as mkdtemp2 } from "node:fs/promises";
|
|
43965
44226
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
@@ -45170,10 +45431,10 @@ function gpuName(renderer) {
|
|
|
45170
45431
|
init_errors();
|
|
45171
45432
|
var usage2 = (code, message) => new CliError(EXIT.usage, code, message);
|
|
45172
45433
|
var SAYS = {
|
|
45173
|
-
pass: (text) =>
|
|
45174
|
-
fail: (text) =>
|
|
45175
|
-
warn: (text) =>
|
|
45176
|
-
cant_check: (text) =>
|
|
45434
|
+
pass: (text) => import_picocolors11.default.green(text),
|
|
45435
|
+
fail: (text) => import_picocolors11.default.red(text),
|
|
45436
|
+
warn: (text) => import_picocolors11.default.yellow(text),
|
|
45437
|
+
cant_check: (text) => import_picocolors11.default.yellow(text)
|
|
45177
45438
|
};
|
|
45178
45439
|
var LABELS = {
|
|
45179
45440
|
pass: "pass ",
|
|
@@ -45292,23 +45553,23 @@ async function check2(ctx, dir, options) {
|
|
|
45292
45553
|
},
|
|
45293
45554
|
() => {
|
|
45294
45555
|
const on = rendering.software ? "no GPU, in software" : rendering.webgl ? gpuName(rendering.webgl) : "no WebGL";
|
|
45295
|
-
out.line(`Checked ${
|
|
45556
|
+
out.line(`Checked ${import_picocolors11.default.bold(game.entry)} in ${version2.product} with ${on}.`);
|
|
45296
45557
|
out.line();
|
|
45297
45558
|
for (const entry of checks) {
|
|
45298
45559
|
out.line(` ${SAYS[entry.result](LABELS[entry.result])} ${entry.detail}`);
|
|
45299
45560
|
}
|
|
45300
45561
|
if (frames) {
|
|
45301
45562
|
out.line(
|
|
45302
|
-
` ${
|
|
45563
|
+
` ${import_picocolors11.default.dim("note ")} ${frames.perSecond} frames a second over ${frames.seconds} s, the longest ${frames.longestMs} ms, ${frames.slow} over 100 ms. That's only for you: no frame rate fails anything.`
|
|
45303
45564
|
);
|
|
45304
45565
|
}
|
|
45305
45566
|
if (observed.changedWithInput !== null && observed.changedWithInput < 1e-3) {
|
|
45306
45567
|
out.line(
|
|
45307
|
-
` ${
|
|
45568
|
+
` ${import_picocolors11.default.dim("note ")} The picture didn't change between the first look and the second, with input going in. It may be waiting for something scripted input doesn't do.`
|
|
45308
45569
|
);
|
|
45309
45570
|
}
|
|
45310
45571
|
for (const entry of observed.errors.slice(1, 5)) {
|
|
45311
|
-
out.line(
|
|
45572
|
+
out.line(import_picocolors11.default.dim(` also: ${entry.message}`));
|
|
45312
45573
|
}
|
|
45313
45574
|
out.line();
|
|
45314
45575
|
out.line("Look at these, as a look is what can tell you it's right:");
|
|
@@ -45321,7 +45582,7 @@ async function check2(ctx, dir, options) {
|
|
|
45321
45582
|
printModels(ctx, models);
|
|
45322
45583
|
}
|
|
45323
45584
|
out.line();
|
|
45324
|
-
out.line(
|
|
45585
|
+
out.line(import_picocolors11.default.dim(ADVICE));
|
|
45325
45586
|
}
|
|
45326
45587
|
);
|
|
45327
45588
|
return failed3.length || brokenModels.length ? EXIT.blocked : EXIT.ok;
|
|
@@ -45334,8 +45595,8 @@ async function serve(ctx, game) {
|
|
|
45334
45595
|
const server = await serveGame(game.root, game.files);
|
|
45335
45596
|
const url2 = `${server.origin}/${game.entry.split("/").map(encodeURIComponent).join("/")}`;
|
|
45336
45597
|
ctx.out.result({ url: url2, folder: game.root }, () => {
|
|
45337
|
-
ctx.out.line(`Serving ${game.root} as Patch's game host does, at ${
|
|
45338
|
-
ctx.out.line(
|
|
45598
|
+
ctx.out.line(`Serving ${game.root} as Patch's game host does, at ${import_picocolors11.default.bold(url2)}`);
|
|
45599
|
+
ctx.out.line(import_picocolors11.default.dim("Paths have to match exactly here, as they do on Patch. Ctrl+C stops it."));
|
|
45339
45600
|
});
|
|
45340
45601
|
return EXIT.ok;
|
|
45341
45602
|
}
|
|
@@ -45356,23 +45617,23 @@ function showModels(ctx, models) {
|
|
|
45356
45617
|
function printModels(ctx, models) {
|
|
45357
45618
|
for (const model of models) {
|
|
45358
45619
|
if (model.error) {
|
|
45359
|
-
ctx.out.line(` ${
|
|
45620
|
+
ctx.out.line(` ${import_picocolors11.default.red("FAIL ")} ${model.file}: ${model.error}`);
|
|
45360
45621
|
continue;
|
|
45361
45622
|
}
|
|
45362
45623
|
const textures = model.textures ?? [];
|
|
45363
45624
|
const size = textures.reduce((sum, texture) => sum + texture.size, 0);
|
|
45364
45625
|
ctx.out.line(
|
|
45365
|
-
` ${
|
|
45626
|
+
` ${import_picocolors11.default.green("read ")} ${model.file}: ${formatSize(model.size)}, ${model.triangles} triangles, ${model.meshes} meshes (${model.skinned} skinned), ${model.materials} materials, ${textures.length} textures (${formatSize(size)}), ${model.animations?.length} animations`
|
|
45366
45627
|
);
|
|
45367
45628
|
if (model.needs?.length) {
|
|
45368
|
-
ctx.out.line(
|
|
45629
|
+
ctx.out.line(import_picocolors11.default.dim(` needs a loader with ${model.needs.join(", ")}`));
|
|
45369
45630
|
}
|
|
45370
45631
|
}
|
|
45371
|
-
ctx.out.line(
|
|
45632
|
+
ctx.out.line(import_picocolors11.default.dim(" Read, not drawn: what they look like takes a look in the game."));
|
|
45372
45633
|
}
|
|
45373
45634
|
|
|
45374
45635
|
// src/commands/connect.ts
|
|
45375
|
-
var
|
|
45636
|
+
var import_picocolors15 = __toESM(require_picocolors(), 1);
|
|
45376
45637
|
import { readFile as readFile12, writeFile as writeFile10 } from "node:fs/promises";
|
|
45377
45638
|
import { join as join15, resolve as resolve11 } from "node:path";
|
|
45378
45639
|
import { setTimeout as sleep5 } from "node:timers/promises";
|
|
@@ -45419,7 +45680,7 @@ function sameName(a, b) {
|
|
|
45419
45680
|
}
|
|
45420
45681
|
|
|
45421
45682
|
// src/commands/repos.ts
|
|
45422
|
-
var
|
|
45683
|
+
var import_picocolors14 = __toESM(require_picocolors(), 1);
|
|
45423
45684
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
45424
45685
|
import { mkdir as mkdir7, readdir as readdir3, readFile as readFile11, rm as rm2, writeFile as writeFile9 } from "node:fs/promises";
|
|
45425
45686
|
import { join as join14, resolve as resolve10 } from "node:path";
|
|
@@ -45489,9 +45750,9 @@ function reviewing(progress) {
|
|
|
45489
45750
|
const usual = `usually about ${minutes(progress.usual_minutes)}, ${soFar}`;
|
|
45490
45751
|
return progress.slow ? `Patch is reviewing it: ${step}. It's taking longer than usual: ${usual}. It finishes by itself.` : `Patch is reviewing it: ${step}. ${capital(usual)}.`;
|
|
45491
45752
|
}
|
|
45492
|
-
function nextStep(
|
|
45493
|
-
const follow4 = `pch test view ${
|
|
45494
|
-
const startOne2 = `pch test start ${
|
|
45753
|
+
function nextStep(release3, status2, test2, cloud) {
|
|
45754
|
+
const follow4 = `pch test view ${release3} --wait`;
|
|
45755
|
+
const startOne2 = `pch test start ${release3}`;
|
|
45495
45756
|
switch (status2) {
|
|
45496
45757
|
case "draft":
|
|
45497
45758
|
return {
|
|
@@ -45513,12 +45774,12 @@ function nextStep(release2, status2, test2, cloud) {
|
|
|
45513
45774
|
case "recorded":
|
|
45514
45775
|
return {
|
|
45515
45776
|
say: "It has been played and recorded. Look at the footage, then send your review.",
|
|
45516
|
-
command: `pch test footage ${
|
|
45777
|
+
command: `pch test footage ${release3}`
|
|
45517
45778
|
};
|
|
45518
45779
|
case "passed":
|
|
45519
45780
|
return {
|
|
45520
45781
|
say: "It passed its test, and it's still private. Publish it once you're happy it's ready.",
|
|
45521
|
-
command: `pch release submit ${
|
|
45782
|
+
command: `pch release submit ${release3}`
|
|
45522
45783
|
};
|
|
45523
45784
|
default:
|
|
45524
45785
|
return { say: "It needs a test that passes.", command: startOne2 };
|
|
@@ -45532,12 +45793,12 @@ function nextStep(release2, status2, test2, cloud) {
|
|
|
45532
45793
|
case "cloud_review":
|
|
45533
45794
|
return {
|
|
45534
45795
|
say: reviewing(cloud) ?? "Patch is reviewing it, which can take several minutes, and nothing tells you when it's done: pch status says.",
|
|
45535
|
-
command: `pch status ${
|
|
45796
|
+
command: `pch status ${release3} --wait 50`
|
|
45536
45797
|
};
|
|
45537
45798
|
case "in_review":
|
|
45538
45799
|
return {
|
|
45539
45800
|
say: "It's waiting for a staff member at Patch, and nothing tells you when that's done: pch status says.",
|
|
45540
|
-
command: `pch status ${
|
|
45801
|
+
command: `pch status ${release3} --wait 50`
|
|
45541
45802
|
};
|
|
45542
45803
|
case "published":
|
|
45543
45804
|
return { say: "It's published.", command: null };
|
|
@@ -45548,11 +45809,11 @@ function nextStep(release2, status2, test2, cloud) {
|
|
|
45548
45809
|
var PLAY_FIRST = "This would be its first public release, and a passed test shows it starts and runs, not that it plays well, so play it yourself first: pch guide says how.";
|
|
45549
45810
|
async function playFirst(ctx, ref) {
|
|
45550
45811
|
const { owner, slug: slug2 } = ref;
|
|
45551
|
-
const [
|
|
45812
|
+
const [release3, project2] = await Promise.all([
|
|
45552
45813
|
ctx.api.GET("/projects/{owner}/{slug}/releases/{version}", { params: { path: ref } }),
|
|
45553
45814
|
ctx.api.GET("/projects/{owner}/{slug}", { params: { path: { owner, slug: slug2 } } })
|
|
45554
45815
|
]);
|
|
45555
|
-
const first =
|
|
45816
|
+
const first = release3.data?.channel === "public" && release3.data.kind !== "block" && project2.data && !project2.data.latest_release;
|
|
45556
45817
|
return first ? PLAY_FIRST : null;
|
|
45557
45818
|
}
|
|
45558
45819
|
function sayNext(next) {
|
|
@@ -45597,7 +45858,7 @@ async function versionTaken(ctx, ref, failure2) {
|
|
|
45597
45858
|
}
|
|
45598
45859
|
|
|
45599
45860
|
// src/commands/init.ts
|
|
45600
|
-
var
|
|
45861
|
+
var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
45601
45862
|
import { readFile as readFile10, stat as stat4, writeFile as writeFile8 } from "node:fs/promises";
|
|
45602
45863
|
import { basename as basename4, join as join13, resolve as resolve9 } from "node:path";
|
|
45603
45864
|
init_errors();
|
|
@@ -45645,17 +45906,17 @@ async function init(ctx, dir, options) {
|
|
|
45645
45906
|
const agentGuide2 = { path: join13(root, guide2.name), written: guide2.written };
|
|
45646
45907
|
const result = { path: path2, ...contents, on_patch: onPatch2, agent_guide: agentGuide2 };
|
|
45647
45908
|
ctx.out.result({ ...result, next, look_first: LOOK_FIRST }, () => {
|
|
45648
|
-
ctx.out.line(`Wrote ${
|
|
45909
|
+
ctx.out.line(`Wrote ${import_picocolors12.default.bold(path2)} for ${import_picocolors12.default.bold(name)}.`);
|
|
45649
45910
|
ctx.out.line(
|
|
45650
45911
|
guide2.written ? `Wrote ${guide2.name}, for coding agents working in this folder.` : `Left ${guide2.name} as it is: it's this folder's guide for agents.`
|
|
45651
45912
|
);
|
|
45652
|
-
ctx.out.line(
|
|
45653
|
-
if (files) ctx.out.line(
|
|
45913
|
+
ctx.out.line(import_picocolors12.default.dim(BRIEF_WORDS));
|
|
45914
|
+
if (files) ctx.out.line(import_picocolors12.default.dim(`The release is what's in ${files}/.`));
|
|
45654
45915
|
ctx.out.line(LOOK_FIRST);
|
|
45655
45916
|
ctx.out.line("Then:");
|
|
45656
45917
|
for (const step of next) ctx.out.line(` ${step}`);
|
|
45657
45918
|
ctx.out.line(
|
|
45658
|
-
|
|
45919
|
+
import_picocolors12.default.dim(
|
|
45659
45920
|
`A browser game whose page is index.html needs no recipe. A test's length and your credits go in one, in patch.json: ${RECIPE_EXAMPLE}. For anything else: pch guide`
|
|
45660
45921
|
)
|
|
45661
45922
|
);
|
|
@@ -45698,7 +45959,7 @@ async function existsOnPatch(ctx, name) {
|
|
|
45698
45959
|
}
|
|
45699
45960
|
|
|
45700
45961
|
// src/commands/scan.ts
|
|
45701
|
-
var
|
|
45962
|
+
var import_picocolors13 = __toESM(require_picocolors(), 1);
|
|
45702
45963
|
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
45703
45964
|
init_errors();
|
|
45704
45965
|
var handle2 = (ref) => `${ref.owner}/${ref.slug}`;
|
|
@@ -45761,19 +46022,19 @@ function show(ctx, project2, scan2) {
|
|
|
45761
46022
|
out.result({ project: name, ...scan2 }, () => {
|
|
45762
46023
|
if (scan2.status === "running") {
|
|
45763
46024
|
out.line(
|
|
45764
|
-
`${
|
|
46025
|
+
`${import_picocolors13.default.bold(name)}: still reading its history. Follow it: pch scan view ${name} --wait`
|
|
45765
46026
|
);
|
|
45766
46027
|
return;
|
|
45767
46028
|
}
|
|
45768
46029
|
if (!scan2.up_to_date) {
|
|
45769
46030
|
out.line(
|
|
45770
|
-
|
|
45771
|
-
`${
|
|
46031
|
+
import_picocolors13.default.yellow(
|
|
46032
|
+
`${import_picocolors13.default.bold(name)}: a push has landed since this scan started, so it says nothing about what the repo holds now. Start a new one: ${start}`
|
|
45772
46033
|
)
|
|
45773
46034
|
);
|
|
45774
46035
|
}
|
|
45775
46036
|
if (scan2.status === "failed") {
|
|
45776
|
-
out.line(
|
|
46037
|
+
out.line(import_picocolors13.default.yellow(`${import_picocolors13.default.bold(name)}: the scan didn't finish, so it can't go open yet.`));
|
|
45777
46038
|
if (scan2.failure) out.line(plain(scan2.failure));
|
|
45778
46039
|
out.line(`Start a new one: ${start}`);
|
|
45779
46040
|
return;
|
|
@@ -45790,7 +46051,7 @@ function show(ctx, project2, scan2) {
|
|
|
45790
46051
|
function showClean({ out }, name, scan2) {
|
|
45791
46052
|
const big = scan2.will_become_public?.big_files;
|
|
45792
46053
|
const where = !big?.count || big.scanned ? "in its whole history" : "in what it read";
|
|
45793
|
-
out.line(`${
|
|
46054
|
+
out.line(`${import_picocolors13.default.bold(name)}: ${import_picocolors13.default.green("no secrets found")} ${where}.`);
|
|
45794
46055
|
if (!scan2.up_to_date) return;
|
|
45795
46056
|
const open3 = `pch set ${name} --visibility open`;
|
|
45796
46057
|
const unread = big?.not_read?.count;
|
|
@@ -45800,18 +46061,18 @@ function showClean({ out }, name, scan2) {
|
|
|
45800
46061
|
}
|
|
45801
46062
|
function showSecrets({ out }, name, scan2) {
|
|
45802
46063
|
out.line(
|
|
45803
|
-
`${
|
|
46064
|
+
`${import_picocolors13.default.bold(name)}: ${import_picocolors13.default.red(`${counted2(scan2.secret_count, "secret")} found`)}, which going open would publish.`
|
|
45804
46065
|
);
|
|
45805
46066
|
for (const secret of plain(scan2.secrets)) {
|
|
45806
46067
|
const where = secret.path ? `${secret.path}:${secret.line}` : `its message, line ${secret.line}`;
|
|
45807
46068
|
const commit = secret.commit ? `${secret.commit.slice(0, 7)} ` : "";
|
|
45808
|
-
out.line(` ${
|
|
46069
|
+
out.line(` ${import_picocolors13.default.dim(commit)}${where}: ${secret.rule} (${secret.masked})`);
|
|
45809
46070
|
}
|
|
45810
46071
|
if (scan2.secrets.length < scan2.secret_count) {
|
|
45811
|
-
out.line(
|
|
46072
|
+
out.line(import_picocolors13.default.dim(` The first ${scan2.secrets.length} of them.`));
|
|
45812
46073
|
}
|
|
45813
46074
|
out.line();
|
|
45814
|
-
out.line(
|
|
46075
|
+
out.line(import_picocolors13.default.bold("How to take them out of its history:"));
|
|
45815
46076
|
for (const step of plain(scan2.fix)) {
|
|
45816
46077
|
out.line(step.step);
|
|
45817
46078
|
for (const command of step.commands) out.line(` ${command}`);
|
|
@@ -45823,7 +46084,7 @@ function showWhatsPublished({ out }, scan2) {
|
|
|
45823
46084
|
scan2.will_become_public
|
|
45824
46085
|
);
|
|
45825
46086
|
out.line();
|
|
45826
|
-
out.line(
|
|
46087
|
+
out.line(import_picocolors13.default.bold("Going open publishes:"));
|
|
45827
46088
|
const unread = big_files.not_read?.count;
|
|
45828
46089
|
const bigFiles = big_files.count ? [
|
|
45829
46090
|
`${counted2(big_files.count, "big file")} (${formatSize(big_files.total_size)}${unread ? `, ${unread} not read` : ""})`
|
|
@@ -45839,14 +46100,14 @@ function showWhatsPublished({ out }, scan2) {
|
|
|
45839
46100
|
);
|
|
45840
46101
|
if (big_files.count) {
|
|
45841
46102
|
const said2 = big_files.coverage ?? "This answer doesn't say whether they were read for secrets.";
|
|
45842
|
-
out.line(unread ?
|
|
46103
|
+
out.line(unread ? import_picocolors13.default.yellow(said2) : said2);
|
|
45843
46104
|
}
|
|
45844
46105
|
out.line("Everyone in its history, with the emails git history publishes:");
|
|
45845
46106
|
for (const person of authors.people.slice(0, PEOPLE_SHOWN)) {
|
|
45846
46107
|
out.line(` ${person.name} <${person.email}>`);
|
|
45847
46108
|
}
|
|
45848
46109
|
if (authors.count > PEOPLE_SHOWN) {
|
|
45849
|
-
out.line(
|
|
46110
|
+
out.line(import_picocolors13.default.dim(` And ${authors.count - PEOPLE_SHOWN} more: --json has them all.`));
|
|
45850
46111
|
}
|
|
45851
46112
|
}
|
|
45852
46113
|
|
|
@@ -45937,17 +46198,17 @@ async function newRepo(ctx, ref, dir, options) {
|
|
|
45937
46198
|
...options.visibility === "private" ? { who_can_see: PRIVATE_REPO } : {}
|
|
45938
46199
|
},
|
|
45939
46200
|
() => {
|
|
45940
|
-
out.line(`Made ${
|
|
46201
|
+
out.line(`Made ${import_picocolors14.default.bold(handle3(project2))} in ${folder}, under the ${licenceName(licence)}.`);
|
|
45941
46202
|
out.line(
|
|
45942
46203
|
options.visibility === "private" ? `Its repo is private: only your team can find it or read its source. ${PRIVATE_REPO_NOT_LOCKED}` : options.visibility && options.visibility !== "open" ? `Its repo is ${options.visibility}.` : "Its repo opens by itself once that scan is clean: then anyone can read, clone and remix it, with what you push. To keep it to your team: pch set --visibility private."
|
|
45943
46204
|
);
|
|
45944
46205
|
if (commitsAs) out.line(saidCommitsAs(commitsAs));
|
|
45945
46206
|
out.line(`${AGENT_GUIDE_FILE}, in its first commit, tells coding agents how to work here.`);
|
|
45946
|
-
out.line(
|
|
46207
|
+
out.line(import_picocolors14.default.dim(BRIEF_WORDS));
|
|
45947
46208
|
out.line(LOOK_FIRST);
|
|
45948
46209
|
out.line("Fill in README.md, add your work, then commit and push with plain git.");
|
|
45949
46210
|
out.line(`To release it: pch validate, then pch publish, in ${folder}.`);
|
|
45950
|
-
out.line(
|
|
46211
|
+
out.line(import_picocolors14.default.dim(url2));
|
|
45951
46212
|
}
|
|
45952
46213
|
);
|
|
45953
46214
|
}
|
|
@@ -46018,7 +46279,7 @@ async function remix(ctx, ref, options) {
|
|
|
46018
46279
|
...address ? { address } : {}
|
|
46019
46280
|
};
|
|
46020
46281
|
out.result(said2, () => {
|
|
46021
|
-
out.line(`Remixed ${
|
|
46282
|
+
out.line(`Remixed ${import_picocolors14.default.bold(handle3(from))} to ${import_picocolors14.default.bold(name)}.`);
|
|
46022
46283
|
if (address) out.line(address);
|
|
46023
46284
|
out.line(words2 ?? `Its repo is ${repo.visibility}.`);
|
|
46024
46285
|
if (ready) out.line(`Clone it with pch clone ${name}`);
|
|
@@ -46026,7 +46287,7 @@ async function remix(ctx, ref, options) {
|
|
|
46026
46287
|
out.line(
|
|
46027
46288
|
`A patch.json in it still names ${handle3(from)}: change "project" to ${name} before you publish.`
|
|
46028
46289
|
);
|
|
46029
|
-
out.line(
|
|
46290
|
+
out.line(import_picocolors14.default.dim(repo.clone_url));
|
|
46030
46291
|
});
|
|
46031
46292
|
}
|
|
46032
46293
|
async function yourOrg(ctx, what) {
|
|
@@ -46068,23 +46329,23 @@ async function status(ctx, ref, options) {
|
|
|
46068
46329
|
const repoAnswer = await api.GET("/projects/{owner}/{slug}/repo", { params: { path: project2 } });
|
|
46069
46330
|
const repo = repoAnswer.response.ok ? repoAnswer.data : null;
|
|
46070
46331
|
const latest2 = version2 ?? await latestVersion(ctx, project2, repo);
|
|
46071
|
-
const
|
|
46072
|
-
const next =
|
|
46073
|
-
const standing2 = repo?.visibility === "open" &&
|
|
46074
|
-
params: { path: { ...project2, version:
|
|
46332
|
+
const release3 = latest2 ? await releaseStanding(ctx, project2, latest2, options.wait) : null;
|
|
46333
|
+
const next = release3 && "next" in release3 ? nextStep(`${handle3(project2)}@${release3.version}`, release3.status, release3.test).command : null;
|
|
46334
|
+
const standing2 = repo?.visibility === "open" && release3 && "next" in release3 ? await api.GET("/projects/{owner}/{slug}/releases/{version}", {
|
|
46335
|
+
params: { path: { ...project2, version: release3.version } }
|
|
46075
46336
|
}) : null;
|
|
46076
46337
|
const openCode = standing2?.data ? openCodeWords(handle3(project2), repo, standing2.data) : null;
|
|
46077
46338
|
const whoCanSee = repo?.visibility === "private" ? { who_can_see: PRIVATE_REPO } : openCode ? { who_can_see: openCode } : {};
|
|
46078
|
-
const play2 =
|
|
46339
|
+
const play2 = release3 && "next" in release3 && release3.status === "testing" && release3.test?.state === "passed" ? await playFirst(ctx, { ...project2, version: release3.version }) : null;
|
|
46079
46340
|
const ask = play2 ? { ask: play2 } : {};
|
|
46080
|
-
out.result({ project: handle3(project2), repo, release:
|
|
46081
|
-
out.line(
|
|
46341
|
+
out.result({ project: handle3(project2), repo, release: release3, next, ...whoCanSee, ...ask }, () => {
|
|
46342
|
+
out.line(import_picocolors14.default.bold(handle3(project2)));
|
|
46082
46343
|
if (repo) out.line(repoLine(repo));
|
|
46083
46344
|
if (repo?.visibility === "private") out.line(PRIVATE_REPO);
|
|
46084
46345
|
if (repo?.home === "github") out.line(homeLine(repo.github));
|
|
46085
|
-
if (!
|
|
46086
|
-
else if ("next" in
|
|
46087
|
-
else out.line(`Release ${
|
|
46346
|
+
if (!release3) out.line("No releases yet. Make one with pch publish.");
|
|
46347
|
+
else if ("next" in release3) showReview(ctx, project2, release3);
|
|
46348
|
+
else out.line(`Release ${release3.version}: ${import_picocolors14.default.bold(release3.status)}`);
|
|
46088
46349
|
if (openCode) out.line(openCode);
|
|
46089
46350
|
if (play2) out.line(` ${play2}`);
|
|
46090
46351
|
if (next) out.line(` Next: ${next}`);
|
|
@@ -46163,10 +46424,10 @@ function repoLine(repo) {
|
|
|
46163
46424
|
function homeLine(github) {
|
|
46164
46425
|
if (!github) return "Home: GitHub";
|
|
46165
46426
|
const seen = github.private ? " (private)" : "";
|
|
46166
|
-
return `Home: GitHub, ${plain(github.full_name)}${seen} \xB7 ${
|
|
46427
|
+
return `Home: GitHub, ${plain(github.full_name)}${seen} \xB7 ${import_picocolors14.default.dim(plain(github.html_url))}`;
|
|
46167
46428
|
}
|
|
46168
46429
|
function showReview({ out }, project2, review) {
|
|
46169
|
-
out.line(`Release ${review.version}: ${
|
|
46430
|
+
out.line(`Release ${review.version}: ${import_picocolors14.default.bold(review.status)}`);
|
|
46170
46431
|
const ours = ["draft", "testing", "rejected", "checking", "cloud_review", "in_review"].includes(
|
|
46171
46432
|
review.status
|
|
46172
46433
|
);
|
|
@@ -46185,7 +46446,7 @@ function showReview({ out }, project2, review) {
|
|
|
46185
46446
|
for (const finding of run3.findings) {
|
|
46186
46447
|
const where = finding.path ? ` ${finding.path}:` : "";
|
|
46187
46448
|
out.line(` ${finding.severity} ${finding.rule_id}${where} ${finding.message}`);
|
|
46188
|
-
if (finding.suggestion) out.line(` ${
|
|
46449
|
+
if (finding.suggestion) out.line(` ${import_picocolors14.default.dim(finding.suggestion)}`);
|
|
46189
46450
|
}
|
|
46190
46451
|
}
|
|
46191
46452
|
if (review.test) out.line(` Test: ${review.test.state}`);
|
|
@@ -46252,7 +46513,7 @@ async function set2(ctx, ref, options) {
|
|
|
46252
46513
|
const whoCanSee = repo.visibility === "private" ? { who_can_see: PRIVATE_REPO } : {};
|
|
46253
46514
|
const said2 = { project: handle3(project2), ...repo, ...licence ? { licence } : {}, ...whoCanSee };
|
|
46254
46515
|
out.result(said2, () => {
|
|
46255
|
-
out.line(`Updated ${
|
|
46516
|
+
out.line(`Updated ${import_picocolors14.default.bold(handle3(project2))}.`);
|
|
46256
46517
|
out.line(` Visibility: ${repo.visibility}`);
|
|
46257
46518
|
if (repo.visibility === "private") out.line(` ${PRIVATE_REPO}`);
|
|
46258
46519
|
out.line(` Training: ${repo.training_opt_out ? "off" : "on"}`);
|
|
@@ -46260,7 +46521,7 @@ async function set2(ctx, ref, options) {
|
|
|
46260
46521
|
if (licence) {
|
|
46261
46522
|
out.line(` Licence: ${licenceName(licence)}`);
|
|
46262
46523
|
out.line(
|
|
46263
|
-
|
|
46524
|
+
import_picocolors14.default.dim(" Patch lists it now. Commit a LICENSE file to match: that's in your hands.")
|
|
46264
46525
|
);
|
|
46265
46526
|
}
|
|
46266
46527
|
});
|
|
@@ -46328,7 +46589,7 @@ async function connect(ctx, ref, options) {
|
|
|
46328
46589
|
out.result(
|
|
46329
46590
|
{ project: handle4(project2), github: shown, already: !posted, patch_json: written, url: url2 },
|
|
46330
46591
|
() => {
|
|
46331
|
-
const name =
|
|
46592
|
+
const name = import_picocolors15.default.bold(handle4(project2));
|
|
46332
46593
|
const repoName = plain(repo.full_name);
|
|
46333
46594
|
out.line(
|
|
46334
46595
|
posted ? `Connected ${repoName} on GitHub to ${name}. Its home is GitHub: Patch keeps none of its files until you release one.` : `${repoName} on GitHub is connected to ${name} already.`
|
|
@@ -46338,7 +46599,7 @@ async function connect(ctx, ref, options) {
|
|
|
46338
46599
|
out.line(
|
|
46339
46600
|
"Next: pch publish tags a commit on GitHub with your own git login, and releases it."
|
|
46340
46601
|
);
|
|
46341
|
-
out.line(
|
|
46602
|
+
out.line(import_picocolors15.default.dim(url2));
|
|
46342
46603
|
}
|
|
46343
46604
|
);
|
|
46344
46605
|
}
|
|
@@ -46756,7 +47017,7 @@ async function nameInManifest(manifest, project2) {
|
|
|
46756
47017
|
}
|
|
46757
47018
|
|
|
46758
47019
|
// src/commands/covers.ts
|
|
46759
|
-
var
|
|
47020
|
+
var import_picocolors16 = __toESM(require_picocolors(), 1);
|
|
46760
47021
|
import { mkdir as mkdir8, readFile as readFile13, writeFile as writeFile11 } from "node:fs/promises";
|
|
46761
47022
|
import { basename as basename5, extname as extname3, join as join16, resolve as resolve12 } from "node:path";
|
|
46762
47023
|
import { setTimeout as sleep7 } from "node:timers/promises";
|
|
@@ -46924,7 +47185,7 @@ async function call(ctx, method, path2, body) {
|
|
|
46924
47185
|
var coversPath = (project2) => `/projects/${project2.owner}/${project2.slug}/covers`;
|
|
46925
47186
|
function freeLine(allowance) {
|
|
46926
47187
|
const left = `${allowance.takes_left} of ${allowance.takes_per_game} free takes and ${allowance.fixes_left} of ${allowance.fixes_per_game} fixes left for this game`;
|
|
46927
|
-
return `${
|
|
47188
|
+
return `${import_picocolors16.default.green("Free")}: Patch pays for covers, and they cost you nothing. ${left}.`;
|
|
46928
47189
|
}
|
|
46929
47190
|
async function uploadStill(ctx, project2, file2) {
|
|
46930
47191
|
const absolute = resolve12(file2);
|
|
@@ -47003,16 +47264,16 @@ async function save(ctx, job, folder) {
|
|
|
47003
47264
|
}
|
|
47004
47265
|
function show2(ctx, job, saved) {
|
|
47005
47266
|
ctx.out.result({ ...job, saved }, () => {
|
|
47006
|
-
ctx.out.line(`${
|
|
47267
|
+
ctx.out.line(`${import_picocolors16.default.bold(job.project)}: ${job.kind === "fix" ? "a fix" : "covers"} (${job.id})`);
|
|
47007
47268
|
for (const take of job.takes) {
|
|
47008
47269
|
const file2 = saved.find((entry) => entry.take === take.id)?.file;
|
|
47009
|
-
const state = take.state === "ready" ?
|
|
47010
|
-
const set3 = take.set_as ?
|
|
47270
|
+
const state = take.state === "ready" ? import_picocolors16.default.green("ready") : take.state === "failed" ? import_picocolors16.default.red(`failed: ${take.error ?? "no reason given"}`) : import_picocolors16.default.yellow("making");
|
|
47271
|
+
const set3 = take.set_as ? import_picocolors16.default.cyan(` set as the ${take.set_as.replace("_", " ")}`) : "";
|
|
47011
47272
|
ctx.out.line(
|
|
47012
|
-
` ${take.shape.padEnd(4)} ${take.id} ${state}${set3}${file2 ?
|
|
47273
|
+
` ${take.shape.padEnd(4)} ${take.id} ${state}${set3}${file2 ? import_picocolors16.default.dim(` ${file2}`) : ""}`
|
|
47013
47274
|
);
|
|
47014
47275
|
}
|
|
47015
|
-
if (job.next) ctx.out.line(
|
|
47276
|
+
if (job.next) ctx.out.line(import_picocolors16.default.dim(job.next));
|
|
47016
47277
|
ctx.out.line(freeLine(job.allowance));
|
|
47017
47278
|
});
|
|
47018
47279
|
if (job.takes.length && job.takes.every((take) => take.state === "failed")) {
|
|
@@ -47087,9 +47348,9 @@ async function coversSet(ctx, ref, take, options) {
|
|
|
47087
47348
|
const answer = await call(ctx, "POST", `${coversPath(project2)}/takes/${take}/set`, { as: options.as });
|
|
47088
47349
|
ctx.out.result(answer, () => {
|
|
47089
47350
|
ctx.out.line(
|
|
47090
|
-
`${
|
|
47351
|
+
`${import_picocolors16.default.green(`Set the ${answer.media.kind.replace("_", " ")}`)} of ${import_picocolors16.default.bold(ref)}: ${answer.media.status}.`
|
|
47091
47352
|
);
|
|
47092
|
-
ctx.out.line(
|
|
47353
|
+
ctx.out.line(import_picocolors16.default.dim("It shows on the game's page once it's ready, in a few seconds."));
|
|
47093
47354
|
ctx.out.line(freeLine(answer.allowance));
|
|
47094
47355
|
});
|
|
47095
47356
|
return EXIT.ok;
|
|
@@ -47101,7 +47362,7 @@ function outFolder(out, byDefault) {
|
|
|
47101
47362
|
}
|
|
47102
47363
|
|
|
47103
47364
|
// src/commands/feedback.ts
|
|
47104
|
-
var
|
|
47365
|
+
var import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
47105
47366
|
var FEEDBACK_KINDS = ["failed", "bug", "call_error", "unhelpful", "idea"];
|
|
47106
47367
|
var FEEDBACK_SEVERITIES = ["blocked", "slowed", "annoyed"];
|
|
47107
47368
|
async function feedbackSend(ctx, summary, options) {
|
|
@@ -47131,7 +47392,7 @@ async function feedbackSend(ctx, summary, options) {
|
|
|
47131
47392
|
const shown = { ...sent, next: sent.next.replaceAll("send_feedback", "pch feedback send") };
|
|
47132
47393
|
ctx.out.result(shown, () => {
|
|
47133
47394
|
ctx.out.line(
|
|
47134
|
-
`${options.addTo ? "Added to your report" : "Told Patch's team"}: ${
|
|
47395
|
+
`${options.addTo ? "Added to your report" : "Told Patch's team"}: ${import_picocolors17.default.bold(plain(sent.summary))}`
|
|
47135
47396
|
);
|
|
47136
47397
|
if (sent.known) {
|
|
47137
47398
|
ctx.out.line(`Patch's team already answered a report like it: ${plain(sent.known.answer)}`);
|
|
@@ -47140,12 +47401,12 @@ async function feedbackSend(ctx, summary, options) {
|
|
|
47140
47401
|
const flag = sent.follow_up.field.replaceAll("_", "-");
|
|
47141
47402
|
ctx.out.line(`One more thing would help most: ${plain(sent.follow_up.question)}`);
|
|
47142
47403
|
ctx.out.line(
|
|
47143
|
-
|
|
47404
|
+
import_picocolors17.default.dim(
|
|
47144
47405
|
` pch feedback send --kind ${sent.kind} --add-to ${sent.id} --${flag} "..." "${plain(sent.summary)}"`
|
|
47145
47406
|
)
|
|
47146
47407
|
);
|
|
47147
47408
|
} else {
|
|
47148
|
-
ctx.out.line(
|
|
47409
|
+
ctx.out.line(import_picocolors17.default.dim(plain(shown.next)));
|
|
47149
47410
|
}
|
|
47150
47411
|
});
|
|
47151
47412
|
}
|
|
@@ -47159,24 +47420,24 @@ async function feedbackList(ctx) {
|
|
|
47159
47420
|
}
|
|
47160
47421
|
for (const report of data) {
|
|
47161
47422
|
ctx.out.line(
|
|
47162
|
-
`${
|
|
47423
|
+
`${import_picocolors17.default.dim(report.created_at.slice(0, 10))} ${statusWord(report.status)} ${plain(report.summary)}`
|
|
47163
47424
|
);
|
|
47164
|
-
if (report.answer) ctx.out.line(` ${
|
|
47425
|
+
if (report.answer) ctx.out.line(` ${import_picocolors17.default.dim("Patch:")} ${plain(report.answer)}`);
|
|
47165
47426
|
if (report.status === "open" && report.quality < 50) {
|
|
47166
|
-
ctx.out.line(
|
|
47427
|
+
ctx.out.line(import_picocolors17.default.dim(` Add to it: pch feedback send --add-to ${report.id} ...`));
|
|
47167
47428
|
}
|
|
47168
47429
|
}
|
|
47169
47430
|
});
|
|
47170
47431
|
}
|
|
47171
47432
|
function statusWord(status2) {
|
|
47172
|
-
if (status2 === "fixed") return
|
|
47173
|
-
if (status2 === "planned") return
|
|
47174
|
-
if (status2 === "declined") return
|
|
47175
|
-
return
|
|
47433
|
+
if (status2 === "fixed") return import_picocolors17.default.green("fixed ");
|
|
47434
|
+
if (status2 === "planned") return import_picocolors17.default.cyan("planned ");
|
|
47435
|
+
if (status2 === "declined") return import_picocolors17.default.dim("declined");
|
|
47436
|
+
return import_picocolors17.default.yellow("open ");
|
|
47176
47437
|
}
|
|
47177
47438
|
|
|
47178
47439
|
// src/commands/git.ts
|
|
47179
|
-
var
|
|
47440
|
+
var import_picocolors18 = __toESM(require_picocolors(), 1);
|
|
47180
47441
|
import { stat as stat5 } from "node:fs/promises";
|
|
47181
47442
|
import { basename as basename6, join as join17, resolve as resolve13 } from "node:path";
|
|
47182
47443
|
|
|
@@ -47911,8 +48172,8 @@ async function push(ctx, given) {
|
|
|
47911
48172
|
},
|
|
47912
48173
|
() => {
|
|
47913
48174
|
const list = sent.map(({ ref, status: status2 }) => `${shortRef(ref)}${status2 === "deleted" ? " (deleted)" : ""}`).join(", ");
|
|
47914
|
-
if (list) out.line(`${dryRun ? "Would push" : "Pushed"} ${list} to ${
|
|
47915
|
-
else if (!quiet) out.line(`Nothing new to push to ${
|
|
48175
|
+
if (list) out.line(`${dryRun ? "Would push" : "Pushed"} ${list} to ${import_picocolors18.default.bold(repo)}.`);
|
|
48176
|
+
else if (!quiet) out.line(`Nothing new to push to ${import_picocolors18.default.bold(repo)}.`);
|
|
47916
48177
|
if (pushed.notice) out.line(pushed.notice);
|
|
47917
48178
|
}
|
|
47918
48179
|
);
|
|
@@ -47959,10 +48220,10 @@ async function clone2(ctx, ref, dir) {
|
|
|
47959
48220
|
brief: brief ? BRIEF_FILE : null
|
|
47960
48221
|
},
|
|
47961
48222
|
() => {
|
|
47962
|
-
out.line(`Cloned ${
|
|
48223
|
+
out.line(`Cloned ${import_picocolors18.default.bold(`${project2.owner}/${project2.slug}`)} into ${basename6(into)}`);
|
|
47963
48224
|
if (commitsAs) out.line(saidCommitsAs(commitsAs));
|
|
47964
|
-
out.line(
|
|
47965
|
-
if (!guide2) out.line(
|
|
48225
|
+
out.line(import_picocolors18.default.dim("Commit and push with plain git."));
|
|
48226
|
+
if (!guide2) out.line(import_picocolors18.default.dim("It has no guide for coding agents: pch agent guide adds one."));
|
|
47966
48227
|
if (brief) {
|
|
47967
48228
|
out.line(
|
|
47968
48229
|
repo.forked_from ? `Its ${BRIEF_FILE} came from ${repo.forked_from}, so it's that game's idea: keep what you want, then change or delete it.` : `Its ${BRIEF_FILE} is this game's idea and rules: read it first.`
|
|
@@ -47973,7 +48234,7 @@ async function clone2(ctx, ref, dir) {
|
|
|
47973
48234
|
}
|
|
47974
48235
|
|
|
47975
48236
|
// src/commands/media.ts
|
|
47976
|
-
var
|
|
48237
|
+
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
47977
48238
|
import { readFile as readFile14 } from "node:fs/promises";
|
|
47978
48239
|
import { basename as basename7, extname as extname4, resolve as resolve14 } from "node:path";
|
|
47979
48240
|
import { setTimeout as sleep8 } from "node:timers/promises";
|
|
@@ -48069,11 +48330,11 @@ function showAdded(ctx, ref, media2) {
|
|
|
48069
48330
|
);
|
|
48070
48331
|
}
|
|
48071
48332
|
ctx.out.result(media2, () => {
|
|
48072
|
-
ctx.out.line(`${
|
|
48073
|
-
if (media2.status === "ready") ctx.out.line(
|
|
48333
|
+
ctx.out.line(`${import_picocolors19.default.green(`Added the ${media2.kind}`)} to ${import_picocolors19.default.bold(ref)}: ${media2.status}.`);
|
|
48334
|
+
if (media2.status === "ready") ctx.out.line(import_picocolors19.default.dim(media2.url));
|
|
48074
48335
|
else {
|
|
48075
48336
|
ctx.out.line(
|
|
48076
|
-
|
|
48337
|
+
import_picocolors19.default.dim(
|
|
48077
48338
|
`It shows once it's ready, which takes seconds for a picture, and for a clip about as long as it plays. Check with pch media list ${ref}.`
|
|
48078
48339
|
)
|
|
48079
48340
|
);
|
|
@@ -48093,7 +48354,7 @@ async function mediaList(ctx, ref) {
|
|
|
48093
48354
|
for (const entry of media2.data) {
|
|
48094
48355
|
const failed3 = entry.status === "failed" && entry.error ? `: ${entry.error}` : "";
|
|
48095
48356
|
ctx.out.line(
|
|
48096
|
-
`${entry.id} ${entry.kind.padEnd(10)} ${entry.status.padEnd(10)} ${formatSize(entry.size).padStart(8)}${failed3}${entry.alt ?
|
|
48357
|
+
`${entry.id} ${entry.kind.padEnd(10)} ${entry.status.padEnd(10)} ${formatSize(entry.size).padStart(8)}${failed3}${entry.alt ? import_picocolors19.default.dim(` ${entry.alt}`) : ""}`
|
|
48097
48358
|
);
|
|
48098
48359
|
}
|
|
48099
48360
|
});
|
|
@@ -48121,7 +48382,7 @@ async function mediaOrder(ctx, ref, ids) {
|
|
|
48121
48382
|
}
|
|
48122
48383
|
|
|
48123
48384
|
// src/commands/publish.ts
|
|
48124
|
-
var
|
|
48385
|
+
var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
48125
48386
|
var import_semver2 = __toESM(require_semver2(), 1);
|
|
48126
48387
|
import { open as open2, readFile as readFile15 } from "node:fs/promises";
|
|
48127
48388
|
init_errors();
|
|
@@ -48204,21 +48465,21 @@ async function publish(ctx, dir, options) {
|
|
|
48204
48465
|
out.step("Submitting");
|
|
48205
48466
|
const name = releaseName({ ...ref, version: version2 });
|
|
48206
48467
|
const submitted = await submit(ctx, { ...ref, version: version2 }).catch(draftUntilTested);
|
|
48207
|
-
const
|
|
48468
|
+
const release3 = await unwrap(
|
|
48208
48469
|
api.GET("/projects/{owner}/{slug}/releases/{version}", { params: { path: path2 } })
|
|
48209
48470
|
);
|
|
48210
48471
|
const url2 = projectUrl(ctx.target.origin, ref);
|
|
48211
48472
|
const branch = await source?.bringBranch();
|
|
48212
48473
|
const branchSaid = branch ? { branch } : {};
|
|
48213
48474
|
const next = nextStep(name, submitted?.status ?? "draft", null).command;
|
|
48214
|
-
const openCode = await openCodeOf(ctx, ref,
|
|
48475
|
+
const openCode = await openCodeOf(ctx, ref, release3);
|
|
48215
48476
|
const whoCanSee = whoCanSeeIt(
|
|
48216
48477
|
// A draft is private whichever channel it's for, as the words for a person say.
|
|
48217
|
-
!submitted ||
|
|
48478
|
+
!submitted || release3.channel === "private" ? privateWords(release3.kind, !submitted) : null,
|
|
48218
48479
|
openCode
|
|
48219
48480
|
);
|
|
48220
48481
|
const result = {
|
|
48221
|
-
release:
|
|
48482
|
+
release: release3,
|
|
48222
48483
|
uploaded: draft.uploads.length,
|
|
48223
48484
|
url: url2,
|
|
48224
48485
|
next,
|
|
@@ -48228,25 +48489,25 @@ async function publish(ctx, dir, options) {
|
|
|
48228
48489
|
out.result(result, () => {
|
|
48229
48490
|
if (!submitted) {
|
|
48230
48491
|
out.line(
|
|
48231
|
-
`Uploaded ${
|
|
48492
|
+
`Uploaded ${import_picocolors20.default.bold(name)} as a private draft. It can't be published until it has passed a test on your PC, in Patch Desktop, where someone presses Start.`
|
|
48232
48493
|
);
|
|
48233
|
-
out.line(privateWords(
|
|
48494
|
+
out.line(privateWords(release3.kind, true));
|
|
48234
48495
|
if (openCode) out.line(openCode);
|
|
48235
48496
|
if (source) out.line(fromCommit(source));
|
|
48236
48497
|
if (branch?.say) out.line(branch.say);
|
|
48237
48498
|
out.line(`Next: ${next}`);
|
|
48238
48499
|
return;
|
|
48239
48500
|
}
|
|
48240
|
-
showSubmitted(ctx, { ...ref, version: version2 }, submitted.status,
|
|
48501
|
+
showSubmitted(ctx, { ...ref, version: version2 }, submitted.status, release3);
|
|
48241
48502
|
if (openCode) out.line(openCode);
|
|
48242
48503
|
if (source) out.line(fromCommit(source));
|
|
48243
48504
|
if (branch?.say) out.line(branch.say);
|
|
48244
|
-
for (const entry of
|
|
48505
|
+
for (const entry of release3.files) {
|
|
48245
48506
|
out.line(
|
|
48246
48507
|
` ${entry.path.padEnd(40)} ${formatSize(entry.size).padStart(8)} sha256 ${entry.sha256}`
|
|
48247
48508
|
);
|
|
48248
48509
|
}
|
|
48249
|
-
out.line(
|
|
48510
|
+
out.line(import_picocolors20.default.dim(url2));
|
|
48250
48511
|
});
|
|
48251
48512
|
}
|
|
48252
48513
|
function fromCommit(source) {
|
|
@@ -48255,36 +48516,36 @@ function fromCommit(source) {
|
|
|
48255
48516
|
}
|
|
48256
48517
|
async function releaseSubmit(ctx, ref) {
|
|
48257
48518
|
requireToken(ctx.target);
|
|
48258
|
-
const
|
|
48259
|
-
const submitted = await submit(ctx,
|
|
48260
|
-
const next = nextStep(releaseName(
|
|
48261
|
-
const openCode = await openCodeOf(ctx,
|
|
48519
|
+
const release3 = parseReleaseRef(ref);
|
|
48520
|
+
const submitted = await submit(ctx, release3);
|
|
48521
|
+
const next = nextStep(releaseName(release3), submitted.status, null).command;
|
|
48522
|
+
const openCode = await openCodeOf(ctx, release3, submitted);
|
|
48262
48523
|
const whoCanSee = whoCanSeeIt(
|
|
48263
48524
|
submitted.channel === "private" && submitted.status === "published" ? privateWords(submitted.kind, false) : null,
|
|
48264
48525
|
openCode
|
|
48265
48526
|
);
|
|
48266
48527
|
ctx.out.result({ ...submitted, next, ...whoCanSee }, () => {
|
|
48267
|
-
showSubmitted(ctx,
|
|
48528
|
+
showSubmitted(ctx, release3, submitted.status, submitted);
|
|
48268
48529
|
if (openCode) ctx.out.line(openCode);
|
|
48269
|
-
ctx.out.line(
|
|
48530
|
+
ctx.out.line(import_picocolors20.default.dim(projectUrl(ctx.target.origin, release3)));
|
|
48270
48531
|
});
|
|
48271
48532
|
}
|
|
48272
48533
|
async function releasePromote(ctx, ref, options) {
|
|
48273
48534
|
requireToken(ctx.target);
|
|
48274
48535
|
const from = parseReleaseRef(ref);
|
|
48275
48536
|
const project2 = { owner: from.owner, slug: from.slug };
|
|
48276
|
-
const
|
|
48537
|
+
const release3 = await unwrap(
|
|
48277
48538
|
ctx.api.GET("/projects/{owner}/{slug}/releases/{version}", { params: { path: from } })
|
|
48278
48539
|
);
|
|
48279
|
-
if (
|
|
48280
|
-
const next = nextStep(ref,
|
|
48540
|
+
if (release3.status !== "published") {
|
|
48541
|
+
const next = nextStep(ref, release3.status, null);
|
|
48281
48542
|
throw new CliError(
|
|
48282
48543
|
EXIT.conflict,
|
|
48283
48544
|
"not_published",
|
|
48284
|
-
`${ref} is ${
|
|
48545
|
+
`${ref} is ${release3.status}, and only a published release can move to another channel. ${next.say}${next.command ? ` Next: ${next.command}` : ""} To release it elsewhere instead, set "channel" in patch.json, move the version on, and run pch publish.`
|
|
48285
48546
|
);
|
|
48286
48547
|
}
|
|
48287
|
-
if (
|
|
48548
|
+
if (release3.channel === options.channel) {
|
|
48288
48549
|
throw new CliError(
|
|
48289
48550
|
EXIT.conflict,
|
|
48290
48551
|
"already_on_channel",
|
|
@@ -48298,10 +48559,10 @@ async function releasePromote(ctx, ref, options) {
|
|
|
48298
48559
|
body: {
|
|
48299
48560
|
version: version2,
|
|
48300
48561
|
channel: options.channel,
|
|
48301
|
-
changelog: options.changelog ??
|
|
48302
|
-
...
|
|
48303
|
-
...
|
|
48304
|
-
files:
|
|
48562
|
+
changelog: options.changelog ?? release3.changelog ?? void 0,
|
|
48563
|
+
...release3.recipe ? { recipe: release3.recipe } : {},
|
|
48564
|
+
...release3.commit ? { commit: release3.commit } : {},
|
|
48565
|
+
files: release3.files.map(({ path: path2, sha256, size }) => ({ path: path2, sha256, size }))
|
|
48305
48566
|
}
|
|
48306
48567
|
})
|
|
48307
48568
|
);
|
|
@@ -48320,7 +48581,7 @@ async function releasePromote(ctx, ref, options) {
|
|
|
48320
48581
|
const next = nextStep(name, "draft", null).command;
|
|
48321
48582
|
ctx.out.result({ from: ref, release: { version: version2, status: "draft" }, url: url2, next }, () => {
|
|
48322
48583
|
ctx.out.line(
|
|
48323
|
-
`Made ${
|
|
48584
|
+
`Made ${import_picocolors20.default.bold(name)} from ${ref}, as a draft for ${options.channel}. It needs a passed test of its own.`
|
|
48324
48585
|
);
|
|
48325
48586
|
ctx.out.line(`Next: ${next}`);
|
|
48326
48587
|
});
|
|
@@ -48328,7 +48589,7 @@ async function releasePromote(ctx, ref, options) {
|
|
|
48328
48589
|
}
|
|
48329
48590
|
ctx.out.result({ from: ref, release: submitted, url: url2 }, () => {
|
|
48330
48591
|
showSubmitted(ctx, to, submitted.status, submitted);
|
|
48331
|
-
ctx.out.line(
|
|
48592
|
+
ctx.out.line(import_picocolors20.default.dim(url2));
|
|
48332
48593
|
});
|
|
48333
48594
|
}
|
|
48334
48595
|
function draftUntilTested(error62) {
|
|
@@ -48344,7 +48605,7 @@ async function nextVersion(ctx, project2) {
|
|
|
48344
48605
|
params: { path: project2, query: { limit: 100, cursor } }
|
|
48345
48606
|
})
|
|
48346
48607
|
);
|
|
48347
|
-
versions.push(...page.data.map((
|
|
48608
|
+
versions.push(...page.data.map((release3) => release3.version));
|
|
48348
48609
|
cursor = page.next_cursor ?? void 0;
|
|
48349
48610
|
} while (cursor);
|
|
48350
48611
|
const newest2 = import_semver2.default.rsort(versions.filter((version2) => import_semver2.default.valid(version2)))[0];
|
|
@@ -48354,9 +48615,9 @@ function privateWords(kind, draft) {
|
|
|
48354
48615
|
if (!onGameHost(kind)) return "Only your team can find it.";
|
|
48355
48616
|
return draft ? PRIVATE_DRAFT : PRIVATE_GAME;
|
|
48356
48617
|
}
|
|
48357
|
-
async function openCodeOf(ctx, { owner, slug: slug2 },
|
|
48618
|
+
async function openCodeOf(ctx, { owner, slug: slug2 }, release3) {
|
|
48358
48619
|
const repo = await ctx.api.GET("/projects/{owner}/{slug}/repo", { params: { path: { owner, slug: slug2 } } }).catch(() => null);
|
|
48359
|
-
return openCodeWords(`${owner}/${slug2}`, repo?.data,
|
|
48620
|
+
return openCodeWords(`${owner}/${slug2}`, repo?.data, release3);
|
|
48360
48621
|
}
|
|
48361
48622
|
function whoCanSeeIt(...words2) {
|
|
48362
48623
|
const said2 = words2.filter(Boolean).join(" ");
|
|
@@ -48365,7 +48626,7 @@ function whoCanSeeIt(...words2) {
|
|
|
48365
48626
|
function showSubmitted(ctx, ref, status2, { channel, kind }) {
|
|
48366
48627
|
const name = releaseName(ref);
|
|
48367
48628
|
if (status2 === "published") {
|
|
48368
|
-
ctx.out.line(
|
|
48629
|
+
ctx.out.line(import_picocolors20.default.green(`Published ${name} to ${channel}`));
|
|
48369
48630
|
if (channel === "private") {
|
|
48370
48631
|
ctx.out.line(privateWords(kind, false));
|
|
48371
48632
|
ctx.out.line(`pch status ${name} says whether your team can play it yet, and where.`);
|
|
@@ -48519,7 +48780,7 @@ async function uploadFailed(file2, upload, response) {
|
|
|
48519
48780
|
}
|
|
48520
48781
|
|
|
48521
48782
|
// src/commands/release-test.ts
|
|
48522
|
-
var
|
|
48783
|
+
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
48523
48784
|
import { createHash as createHash3 } from "node:crypto";
|
|
48524
48785
|
import { mkdir as mkdir9, mkdtemp as mkdtemp3, writeFile as writeFile12 } from "node:fs/promises";
|
|
48525
48786
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
@@ -48531,23 +48792,23 @@ var ASK_EVERY_MS2 = 5e3;
|
|
|
48531
48792
|
var OPEN = /* @__PURE__ */ new Set(["waiting", "running", "recorded"]);
|
|
48532
48793
|
var GOING = /* @__PURE__ */ new Set(["waiting", "running"]);
|
|
48533
48794
|
var REVIEW_ROUTE = "/projects/{owner}/{slug}/releases/{version}/review";
|
|
48534
|
-
var reviewOf = (ctx,
|
|
48795
|
+
var reviewOf = (ctx, release3) => ctx.api.GET(REVIEW_ROUTE, { params: { path: release3 } });
|
|
48535
48796
|
async function testStart(ctx, ref, options) {
|
|
48536
48797
|
requireToken(ctx.target);
|
|
48537
|
-
const
|
|
48798
|
+
const release3 = parseReleaseRef(ref);
|
|
48538
48799
|
const wait2 = waitOf(options.wait);
|
|
48539
|
-
const before = await reviewOf(ctx,
|
|
48800
|
+
const before = await reviewOf(ctx, release3);
|
|
48540
48801
|
const open3 = before.data?.test && OPEN.has(before.data.test.state) ? before.data.test : null;
|
|
48541
|
-
const test2 = open3 ?? await startOne(ctx,
|
|
48542
|
-
return show3(ctx,
|
|
48802
|
+
const test2 = open3 ?? await startOne(ctx, release3, before.data?.status);
|
|
48803
|
+
return show3(ctx, release3, wait2 === null ? test2 : await follow3(ctx, test2, wait2), {
|
|
48543
48804
|
started: !open3,
|
|
48544
48805
|
followed: wait2 !== null
|
|
48545
48806
|
});
|
|
48546
48807
|
}
|
|
48547
|
-
async function startOne(ctx,
|
|
48548
|
-
const name = releaseName(
|
|
48808
|
+
async function startOne(ctx, release3, status2) {
|
|
48809
|
+
const name = releaseName(release3);
|
|
48549
48810
|
const answer = await ctx.api.POST("/projects/{owner}/{slug}/releases/{version}/tests", {
|
|
48550
|
-
params: { path:
|
|
48811
|
+
params: { path: release3 }
|
|
48551
48812
|
});
|
|
48552
48813
|
if (answer.response.ok) return answer.data;
|
|
48553
48814
|
const failure2 = fromResponse(answer.response, answer.error);
|
|
@@ -48577,17 +48838,17 @@ async function startOne(ctx, release2, status2) {
|
|
|
48577
48838
|
}
|
|
48578
48839
|
async function testView(ctx, ref, options) {
|
|
48579
48840
|
requireToken(ctx.target);
|
|
48580
|
-
const
|
|
48841
|
+
const release3 = parseReleaseRef(ref);
|
|
48581
48842
|
const wait2 = waitOf(options.wait);
|
|
48582
|
-
const test2 = await newest(ctx,
|
|
48583
|
-
return show3(ctx,
|
|
48843
|
+
const test2 = await newest(ctx, release3);
|
|
48844
|
+
return show3(ctx, release3, wait2 === null ? test2 : await follow3(ctx, test2, wait2), {
|
|
48584
48845
|
followed: wait2 !== null
|
|
48585
48846
|
});
|
|
48586
48847
|
}
|
|
48587
|
-
async function newest(ctx,
|
|
48588
|
-
const review = await unwrap(reviewOf(ctx,
|
|
48848
|
+
async function newest(ctx, release3) {
|
|
48849
|
+
const review = await unwrap(reviewOf(ctx, release3));
|
|
48589
48850
|
if (review.test) return review.test;
|
|
48590
|
-
const name = releaseName(
|
|
48851
|
+
const name = releaseName(release3);
|
|
48591
48852
|
const next = `pch test start ${name}`;
|
|
48592
48853
|
throw new CliError(EXIT.error, "not_found", `${name} has no test yet. Start one: ${next}`, {
|
|
48593
48854
|
next
|
|
@@ -48623,12 +48884,12 @@ function whatsHappening(test2) {
|
|
|
48623
48884
|
if (test2.needs_person) return plain(test2.needs_person.ask);
|
|
48624
48885
|
return "Waiting for you to press Start in Patch Desktop";
|
|
48625
48886
|
}
|
|
48626
|
-
async function show3(ctx,
|
|
48887
|
+
async function show3(ctx, release3, test2, { followed, ...extra } = {}) {
|
|
48627
48888
|
const { out } = ctx;
|
|
48628
|
-
const name = releaseName(
|
|
48889
|
+
const name = releaseName(release3);
|
|
48629
48890
|
const next = nextStep(name, test2.state === "failed" ? "rejected" : "testing", test2);
|
|
48630
48891
|
const command = next.command;
|
|
48631
|
-
const play2 = test2.state === "passed" ? await playFirst(ctx,
|
|
48892
|
+
const play2 = test2.state === "passed" ? await playFirst(ctx, release3) : null;
|
|
48632
48893
|
const ask = test2.state === "waiting" ? askThePerson(test2) : play2;
|
|
48633
48894
|
const noteAsk = test2.note_ask?.replaceAll("suggest_note", "pch note suggest");
|
|
48634
48895
|
const feedbackAsk = test2.feedback_ask ? {
|
|
@@ -48643,7 +48904,7 @@ async function show3(ctx, release2, test2, { followed, ...extra } = {}) {
|
|
|
48643
48904
|
...feedbackAsk ? { feedback_ask: feedbackAsk } : {}
|
|
48644
48905
|
};
|
|
48645
48906
|
out.result({ ...shown, ...ask ? { ask } : {} }, () => {
|
|
48646
|
-
const bold =
|
|
48907
|
+
const bold = import_picocolors21.default.bold(name);
|
|
48647
48908
|
if (test2.state === "waiting") {
|
|
48648
48909
|
out.line(
|
|
48649
48910
|
!test2.needs_person ? `${extra.started ? "Started a test of" : "The test of"} ${bold}. It's waiting for Patch Desktop to take it on.` : extra.started ? `Started a test of ${bold}. It's waiting for you in Patch Desktop: press Start on it there.` : `${bold}: its test is waiting for you in Patch Desktop. Press Start on it there.`
|
|
@@ -48659,19 +48920,19 @@ async function show3(ctx, release2, test2, { followed, ...extra } = {}) {
|
|
|
48659
48920
|
`${bold}: it has been played and recorded. Look at the footage, then send your review.`
|
|
48660
48921
|
);
|
|
48661
48922
|
} else if (test2.state === "passed") {
|
|
48662
|
-
out.line(`${bold}: ${
|
|
48923
|
+
out.line(`${bold}: ${import_picocolors21.default.green("its test passed.")} It's still private.`);
|
|
48663
48924
|
if (test2.review) out.line(plain(test2.review.summary));
|
|
48664
48925
|
if (play2) out.line(play2);
|
|
48665
48926
|
out.line(
|
|
48666
48927
|
"Publish it once you're happy it's ready: that's your yes, and nothing does it for you."
|
|
48667
48928
|
);
|
|
48668
48929
|
} else if (test2.state === "failed") {
|
|
48669
|
-
out.line(`${bold}: ${
|
|
48930
|
+
out.line(`${bold}: ${import_picocolors21.default.red("its test failed")}, so this version can't be published.`);
|
|
48670
48931
|
showWhatFailed(ctx, test2);
|
|
48671
48932
|
out.line(`pch status ${name} says how to fix it.`);
|
|
48672
48933
|
out.line("Then move the version on in patch.json and publish that.");
|
|
48673
48934
|
} else if (test2.state === "couldnt_run") {
|
|
48674
|
-
out.line(`${bold}: ${
|
|
48935
|
+
out.line(`${bold}: ${import_picocolors21.default.yellow("its test couldn't run.")}`);
|
|
48675
48936
|
if (test2.outcome) out.line(plain(test2.outcome.reason));
|
|
48676
48937
|
} else {
|
|
48677
48938
|
out.line(`${bold}: its test was cancelled.`);
|
|
@@ -48683,7 +48944,7 @@ async function show3(ctx, release2, test2, { followed, ...extra } = {}) {
|
|
|
48683
48944
|
}
|
|
48684
48945
|
if (command) out.line(`Next: ${command}`);
|
|
48685
48946
|
if (OPEN.has(test2.state) && !extra.started) {
|
|
48686
|
-
out.line(
|
|
48947
|
+
out.line(import_picocolors21.default.dim(`To start over: pch test cancel ${name}, then pch test start ${name}`));
|
|
48687
48948
|
}
|
|
48688
48949
|
});
|
|
48689
48950
|
if (test2.state === "failed") return EXIT.blocked;
|
|
@@ -48706,10 +48967,10 @@ function showWhatFailed({ out }, test2) {
|
|
|
48706
48967
|
async function testFootage(ctx, ref, options) {
|
|
48707
48968
|
requireToken(ctx.target);
|
|
48708
48969
|
const { out } = ctx;
|
|
48709
|
-
const
|
|
48710
|
-
const name = releaseName(
|
|
48970
|
+
const release3 = parseReleaseRef(ref);
|
|
48971
|
+
const name = releaseName(release3);
|
|
48711
48972
|
const run3 = options.run === void 0 ? void 0 : positive(options.run, "--run");
|
|
48712
|
-
const test2 = await newest(ctx,
|
|
48973
|
+
const test2 = await newest(ctx, release3);
|
|
48713
48974
|
const { data } = await unwrap(
|
|
48714
48975
|
ctx.api.GET("/tests/{id}/footage", { params: { path: { id: test2.id }, query: { run: run3 } } })
|
|
48715
48976
|
);
|
|
@@ -48720,7 +48981,7 @@ async function testFootage(ctx, ref, options) {
|
|
|
48720
48981
|
const next = data.length ? reviewCommand(name) : nextStep(name, "testing", test2).command;
|
|
48721
48982
|
out.result({ test: test2.id, state: test2.state, data: sheets, next }, () => {
|
|
48722
48983
|
if (!sheets.length) {
|
|
48723
|
-
out.line(`${
|
|
48984
|
+
out.line(`${import_picocolors21.default.bold(name)} has no footage yet: its test is ${test2.state.replace("_", " ")}.`);
|
|
48724
48985
|
for (const result of test2.results) {
|
|
48725
48986
|
if (result.footage_error) out.line(plain(result.footage_error));
|
|
48726
48987
|
}
|
|
@@ -48757,9 +49018,9 @@ async function saveSheets(sheets, folder) {
|
|
|
48757
49018
|
}
|
|
48758
49019
|
async function testReview(ctx, ref, options) {
|
|
48759
49020
|
requireToken(ctx.target);
|
|
48760
|
-
const
|
|
49021
|
+
const release3 = parseReleaseRef(ref);
|
|
48761
49022
|
const moments = options.moment.map(parseMoment);
|
|
48762
|
-
const test2 = await newest(ctx,
|
|
49023
|
+
const test2 = await newest(ctx, release3);
|
|
48763
49024
|
const answer = await ctx.api.POST("/tests/{id}/review", {
|
|
48764
49025
|
params: { path: { id: test2.id } },
|
|
48765
49026
|
body: {
|
|
@@ -48770,8 +49031,8 @@ async function testReview(ctx, ref, options) {
|
|
|
48770
49031
|
moments
|
|
48771
49032
|
}
|
|
48772
49033
|
});
|
|
48773
|
-
if (answer.response.ok) return show3(ctx,
|
|
48774
|
-
throw withNext(fromResponse(answer.response, answer.error),
|
|
49034
|
+
if (answer.response.ok) return show3(ctx, release3, answer.data);
|
|
49035
|
+
throw withNext(fromResponse(answer.response, answer.error), release3, test2);
|
|
48775
49036
|
}
|
|
48776
49037
|
function parseMoment(text) {
|
|
48777
49038
|
const match = /^(\d+)\s+(\d{1,3}:\d{2})\s+(\S.*)$/s.exec(text.trim());
|
|
@@ -48786,21 +49047,21 @@ function parseMoment(text) {
|
|
|
48786
49047
|
}
|
|
48787
49048
|
async function testCancel(ctx, ref) {
|
|
48788
49049
|
requireToken(ctx.target);
|
|
48789
|
-
const
|
|
48790
|
-
const name = releaseName(
|
|
48791
|
-
const test2 = await newest(ctx,
|
|
49050
|
+
const release3 = parseReleaseRef(ref);
|
|
49051
|
+
const name = releaseName(release3);
|
|
49052
|
+
const test2 = await newest(ctx, release3);
|
|
48792
49053
|
const answer = await ctx.api.POST("/tests/{id}/cancel", { params: { path: { id: test2.id } } });
|
|
48793
49054
|
if (!answer.response.ok) {
|
|
48794
|
-
throw withNext(fromResponse(answer.response, answer.error),
|
|
49055
|
+
throw withNext(fromResponse(answer.response, answer.error), release3, test2);
|
|
48795
49056
|
}
|
|
48796
49057
|
const next = `pch test start ${name}`;
|
|
48797
49058
|
ctx.out.result({ ...answer.data, next }, () => {
|
|
48798
|
-
ctx.out.line(`Cancelled ${
|
|
49059
|
+
ctx.out.line(`Cancelled ${import_picocolors21.default.bold(name)}'s test. Start another: ${next}`);
|
|
48799
49060
|
});
|
|
48800
49061
|
}
|
|
48801
|
-
function withNext(failure2,
|
|
49062
|
+
function withNext(failure2, release3, test2) {
|
|
48802
49063
|
if (failure2.code !== "test_state") return failure2;
|
|
48803
|
-
const next = nextStep(releaseName(
|
|
49064
|
+
const next = nextStep(releaseName(release3), "testing", test2);
|
|
48804
49065
|
return new CliError(failure2.exitCode, failure2.code, `${failure2.message}. ${sayNext(next)}`, {
|
|
48805
49066
|
next: next.command
|
|
48806
49067
|
});
|
|
@@ -48825,7 +49086,7 @@ async function testAutostart(ctx, state) {
|
|
|
48825
49086
|
}
|
|
48826
49087
|
|
|
48827
49088
|
// src/commands/search.ts
|
|
48828
|
-
var
|
|
49089
|
+
var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
48829
49090
|
init_guide_words();
|
|
48830
49091
|
var filter = (values) => values?.flatMap((value) => value.split(",")).map((value) => value.trim()).filter(Boolean).join(",") || void 0;
|
|
48831
49092
|
var licences = (values) => values.flatMap((value) => value.split(",")).map((value) => licenceId(value.trim()) ?? value.trim());
|
|
@@ -48863,13 +49124,13 @@ async function search(ctx, q, options) {
|
|
|
48863
49124
|
out.result({ ...answer, ...aboutBlocks }, () => {
|
|
48864
49125
|
if (!data.length) out.line("Nothing found.");
|
|
48865
49126
|
for (const result of plain(data)) {
|
|
48866
|
-
out.line(`${
|
|
49127
|
+
out.line(`${import_picocolors22.default.bold(result.handle)} ${import_picocolors22.default.dim(facts(result))}`);
|
|
48867
49128
|
if (result.summary) out.line(` ${result.summary}`);
|
|
48868
49129
|
if (result.demo) out.line(` Live demo: ${ctx.target.origin}/${result.owner}/${result.slug}`);
|
|
48869
|
-
out.line(
|
|
49130
|
+
out.line(import_picocolors22.default.dim(` ${result.clone_url}`));
|
|
48870
49131
|
}
|
|
48871
49132
|
if (blocks) out.line(BLOCK_WORDS);
|
|
48872
|
-
if (cursor) out.line(
|
|
49133
|
+
if (cursor) out.line(import_picocolors22.default.dim("There are more; raise --limit."));
|
|
48873
49134
|
});
|
|
48874
49135
|
}
|
|
48875
49136
|
function facts(result) {
|
|
@@ -48894,16 +49155,16 @@ async function categories(ctx, options) {
|
|
|
48894
49155
|
const width = Math.max(0, ...data.map((category) => category.id.length));
|
|
48895
49156
|
for (const category of data) {
|
|
48896
49157
|
ctx.out.line(
|
|
48897
|
-
`${
|
|
49158
|
+
`${import_picocolors22.default.bold(category.id.padEnd(width))} ${category.name} ${import_picocolors22.default.dim(`\xB7 ${category.for.join(", ")} \xB7 ${category.projects === 1 ? "1 project" : `${category.projects} projects`}`)}`
|
|
48898
49159
|
);
|
|
48899
49160
|
}
|
|
48900
49161
|
});
|
|
48901
49162
|
}
|
|
48902
49163
|
|
|
48903
49164
|
// src/commands/update.ts
|
|
48904
|
-
var
|
|
49165
|
+
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
48905
49166
|
var import_semver3 = __toESM(require_semver2(), 1);
|
|
48906
|
-
import { spawnSync as
|
|
49167
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
48907
49168
|
import { createHash as createHash4 } from "node:crypto";
|
|
48908
49169
|
import { mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
48909
49170
|
import { chmod as chmod3, rename as rename2, rm as rm3, writeFile as writeFile13 } from "node:fs/promises";
|
|
@@ -49016,7 +49277,7 @@ async function update(ctx) {
|
|
|
49016
49277
|
const fresh = `${target}.new`;
|
|
49017
49278
|
await writeFile13(fresh, gunzipSync(packed), { mode: 493 });
|
|
49018
49279
|
await chmod3(fresh, 493);
|
|
49019
|
-
const said2 =
|
|
49280
|
+
const said2 = spawnSync3(fresh, ["--version"], { encoding: "utf8", timeout: 6e4 });
|
|
49020
49281
|
if (said2.status !== 0 || said2.stdout.trim() !== latest2) {
|
|
49021
49282
|
await whenFree(() => rm3(fresh, { force: true })).catch(() => void 0);
|
|
49022
49283
|
throw new CliError(
|
|
@@ -49100,7 +49361,7 @@ function startUpdateNotice(ctx, command, now = Date.now()) {
|
|
|
49100
49361
|
if (version2 && import_semver3.default.gt(version2, VERSION)) {
|
|
49101
49362
|
process.stderr.write(
|
|
49102
49363
|
`
|
|
49103
|
-
${
|
|
49364
|
+
${import_picocolors23.default.dim("\u203A")} pch ${version2} is out (you have ${VERSION}). To update, run: ${how}
|
|
49104
49365
|
`
|
|
49105
49366
|
);
|
|
49106
49367
|
}
|
|
@@ -49109,7 +49370,7 @@ ${import_picocolors22.default.dim("\u203A")} pch ${version2} is out (you have ${
|
|
|
49109
49370
|
}
|
|
49110
49371
|
|
|
49111
49372
|
// src/commands/validate.ts
|
|
49112
|
-
var
|
|
49373
|
+
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
49113
49374
|
init_errors();
|
|
49114
49375
|
async function validate2(ctx, dir) {
|
|
49115
49376
|
const project2 = await loadProject(dir);
|
|
@@ -49168,12 +49429,12 @@ async function validate2(ctx, dir) {
|
|
|
49168
49429
|
notes
|
|
49169
49430
|
};
|
|
49170
49431
|
ctx.out.result(result, () => {
|
|
49171
|
-
const mark = result.ok ?
|
|
49432
|
+
const mark = result.ok ? import_picocolors24.default.green("\u2713") : import_picocolors24.default.red("\u2717");
|
|
49172
49433
|
ctx.out.line(
|
|
49173
49434
|
`${mark} ${file2.project}@${file2.version} \xB7 ${project2.kind} \xB7 ${result.trust_tier} \xB7 ${project2.files.length} files, ${formatSize(total)}`
|
|
49174
49435
|
);
|
|
49175
|
-
for (const issue2 of issues) ctx.out.line(` ${
|
|
49176
|
-
for (const note2 of notes) ctx.out.line(` ${
|
|
49436
|
+
for (const issue2 of issues) ctx.out.line(` ${import_picocolors24.default.red(issue2.path || "\xB7")} ${issue2.message}`);
|
|
49437
|
+
for (const note2 of notes) ctx.out.line(` ${import_picocolors24.default.dim(note2)}`);
|
|
49177
49438
|
});
|
|
49178
49439
|
return result.ok ? EXIT.ok : EXIT.usage;
|
|
49179
49440
|
}
|
|
@@ -49617,10 +49878,10 @@ assets.command("add <ids...>").description(
|
|
|
49617
49878
|
(ctx, ids, options) => assetsAdd(ctx, ids, options)
|
|
49618
49879
|
)
|
|
49619
49880
|
);
|
|
49620
|
-
var
|
|
49621
|
-
|
|
49622
|
-
|
|
49623
|
-
|
|
49881
|
+
var release2 = program2.command("release").description("A project's releases");
|
|
49882
|
+
release2.command("list <project>").action(action((ctx, ref) => releaseList(ctx, ref)));
|
|
49883
|
+
release2.command("view <release>").description("owner/slug@version").action(action((ctx, ref) => releaseView(ctx, ref)));
|
|
49884
|
+
release2.command("submit <release>").description(
|
|
49624
49885
|
"Send a release on to be published, owner/slug@version: this is your yes. A browser game or a mod Patch installs has to have passed a test"
|
|
49625
49886
|
).action(action((ctx, ref) => releaseSubmit(ctx, ref)));
|
|
49626
49887
|
var test = program2.command("test").description(
|
|
@@ -49667,7 +49928,7 @@ test.command("review <release>").description("Send your review of a test's foota
|
|
|
49667
49928
|
)
|
|
49668
49929
|
);
|
|
49669
49930
|
test.command("cancel <release>").description("Cancel a release's test, if it hasn't been decided").action(action((ctx, ref) => testCancel(ctx, ref)));
|
|
49670
|
-
|
|
49931
|
+
release2.command("promote <release>").description(
|
|
49671
49932
|
"Put owner/slug@version on another channel: a new version with the same files, which uploads nothing"
|
|
49672
49933
|
).addOption(
|
|
49673
49934
|
new Option("--channel <channel>", `where it goes. ${NOT_LOCKED_HELP}`).choices(["private", "unlisted", "public"]).default("public")
|