@coderook/cli 0.33.1 → 0.34.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.
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.likenessLine = likenessLine;
7
+ exports.chooseProject = chooseProject;
8
+ /*
9
+ Which project an unlinked folder's first save goes into, decided by the
10
+ person rather than by a name that happens to match.
11
+
12
+ Shared by `cbx submit` and a local history's first `cbx push`: both used to
13
+ name the project after the folder, join it if the account already had one
14
+ of that name, and start a new one otherwise, without a word either way.
15
+ */
16
+ const promises_1 = require("node:readline/promises");
17
+ const node_process_1 = __importDefault(require("node:process"));
18
+ const api_js_1 = require("./api.js");
19
+ const config_js_1 = require("./config.js");
20
+ const folder_match_js_1 = require("./folder_match.js");
21
+ const download_js_1 = require("../../cbx/src/core/download.js");
22
+ const ESC = String.fromCharCode(27);
23
+ const colour = node_process_1.default.stdout.isTTY && !node_process_1.default.env.NO_COLOR;
24
+ const paint = (code) => (value) => colour ? `${ESC}[${code}m${value}${ESC}[0m` : value;
25
+ const dim = paint("2");
26
+ const red = paint("31");
27
+ const accent = paint("33");
28
+ /**
29
+ * One line about a project an unlinked folder might be, with how much of it
30
+ * is here: the number that tells a stale copy from a separate project.
31
+ */
32
+ async function likenessLine(folder, like, width) {
33
+ const { project } = like;
34
+ let here = "";
35
+ if (project.versionCount) {
36
+ try {
37
+ const downloader = new download_js_1.Downloader(config_js_1.credentials);
38
+ const latest = (await downloader.versions(project.id))[0];
39
+ if (latest) {
40
+ const paths = (await downloader.files(project.id, latest.id)).map((file) => file.path);
41
+ here = ` · ${(0, folder_match_js_1.pathsPresent)(folder, paths)} of its ${paths.length} files are here at the same path`;
42
+ }
43
+ }
44
+ catch {
45
+ /* The list is still worth showing without the count. */
46
+ }
47
+ }
48
+ return (`${accent(project.slug.padEnd(width))} v${project.versionCount}` +
49
+ dim(`${here}${like.sameName ? " · same name as this folder" : ""}`));
50
+ }
51
+ /**
52
+ * `--into` and `--new` say it outright, which is what a script or an
53
+ * assistant must do. Without either, a folder whose name is like a project
54
+ * already on the account is asked about at a terminal and refused elsewhere,
55
+ * with the two commands that would settle it. A name like nothing on the
56
+ * account is a new project, as it always was.
57
+ *
58
+ * Returns the project to save into, a new project's name, or null to stop.
59
+ */
60
+ async function chooseProject(input) {
61
+ const { folder, name, into, startNew, command } = input;
62
+ if (into && startNew) {
63
+ console.error(red("Pass --into or --new, not both."));
64
+ return null;
65
+ }
66
+ if (into) {
67
+ const project = await (0, api_js_1.findProject)(into);
68
+ if (!project) {
69
+ console.error(red(`No project matching "${into}" on your account.`));
70
+ console.error(dim(` ${accent("cbx projects")} lists them.`));
71
+ return null;
72
+ }
73
+ return project;
74
+ }
75
+ const likes = (0, folder_match_js_1.similarProjects)(await (0, api_js_1.projects)(), name);
76
+ const taken = likes.find((like) => like.sameName);
77
+ if (startNew) {
78
+ if (!taken)
79
+ return { name };
80
+ console.error(red(`Your account already has a project called ${taken.project.slug}.`));
81
+ console.error(dim(" Save into it with ") + accent(`--into ${taken.project.slug}`) +
82
+ dim(", or give the new one another name with ") + accent("--name <name>") + dim("."));
83
+ return null;
84
+ }
85
+ if (!likes.length)
86
+ return { name };
87
+ const width = Math.max(...likes.map((like) => like.project.slug.length));
88
+ const lines = await Promise.all(likes.map((like) => likenessLine(folder, like, width)));
89
+ const interactive = Boolean(node_process_1.default.stdin.isTTY && node_process_1.default.stdout.isTTY);
90
+ const say = interactive ? console.log : console.error;
91
+ say(`This folder is not linked to a project, and your account has ${likes.length === 1 ? "one" : "some"} like it:`);
92
+ lines.forEach((line, at) => say(` ${interactive ? `${at + 1} ` : ""}${line}`));
93
+ if (!interactive) {
94
+ console.error(`\nNothing was sent. Say which:`);
95
+ console.error(` ${accent(`${command} --into ${likes[0].project.slug}`)} ${dim("save into that project")}`);
96
+ console.error(` ${accent(`${command} --new${taken ? " --name <another-name>" : ""}`)} ${dim("start a separate project")}`);
97
+ return null;
98
+ }
99
+ const reader = (0, promises_1.createInterface)({ input: node_process_1.default.stdin, output: node_process_1.default.stdout });
100
+ try {
101
+ const answer = (await reader.question(`\nSave into one of these (its number), start a new project (n), or stop (Enter): `)).trim().toLowerCase();
102
+ const picked = Number(answer);
103
+ if (Number.isInteger(picked) && picked >= 1 && picked <= likes.length) {
104
+ return likes[picked - 1].project;
105
+ }
106
+ if (answer !== "n" && answer !== "new")
107
+ return null;
108
+ if (!taken)
109
+ return { name };
110
+ const other = (await reader.question(`Name for the new project: `)).trim();
111
+ if (!other)
112
+ return null;
113
+ if (likes.some((like) => like.project.slug === (0, folder_match_js_1.slugFor)(other))) {
114
+ console.error(red(`${(0, folder_match_js_1.slugFor)(other)} is taken too.`));
115
+ return null;
116
+ }
117
+ return { name: other };
118
+ }
119
+ finally {
120
+ reader.close();
121
+ }
122
+ }
@@ -13,6 +13,7 @@ function uploadRequestFor(input) {
13
13
  message: input.message,
14
14
  projectName: input.projectName,
15
15
  repositoryId: input.repositoryId,
16
+ ...(input.joinExisting === false ? { joinExisting: false } : {}),
16
17
  baseVersionId: input.baseVersionId,
17
18
  ...(input.track ? { track: input.track } : {}),
18
19
  ...(input.allowIgnored ? { allowIgnored: true } : {}),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coderook/cli",
3
- "version": "0.33.1",
3
+ "version": "0.34.0",
4
4
  "description": "The command line for CodeRook (coderook.com): version control and project hosting for projects of any size. Every save is a compressed snapshot, private or public, never used to train AI.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://coderook.com",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: coderook
3
- description: Save, browse and restore versions of a project on CodeRook — a version host where every version is a complete snapshot and there is no git to learn. Use when asked to save or submit work to CodeRook, check what has changed, look at a project's versions or files, fetch a project, start or switch a line of work, or resolve a save that landed at the same time as somebody else's.
3
+ description: Save, browse and restore versions of a project on CodeRook — a version host where every version is a complete snapshot, reached with the cbx command or with plain git. Use when asked to save, submit or push work to CodeRook, check what has changed, look at a project's versions or files, fetch a project, start or switch a line of work, or resolve a save that landed at the same time as somebody else's.
4
4
  allowed-tools: Bash Read
5
5
  ---
6
6
 
@@ -11,7 +11,13 @@ project had at that moment, so restoring one never depends on the versions
11
11
  around it, and there is no staging area, no branches to rebase and no history
12
12
  to rewrite.
13
13
 
14
- Everything here is the `coderook` command line. Run it with Bash.
14
+ Everything here is the `cbx` command line (also installed as `coderook`), or
15
+ git itself through CodeRook's remote helper. Run them with Bash.
16
+
17
+ **Which one to use.** If the folder is a git repository (`git rev-parse` works
18
+ in it), prefer git — see *Working in a git repository* below. Each commit then
19
+ arrives with its own message, instead of one snapshot standing in for many.
20
+ Use `cbx submit` for folders that are not git repositories.
15
21
 
16
22
  ## Before anything else
17
23
 
@@ -44,6 +50,21 @@ nothing.
44
50
  cbx submit -m "What changed, in a sentence"
45
51
  ```
46
52
 
53
+ **The first save from a folder must say which project it is.** A folder that
54
+ is not linked goes to a new project named after it — unless the account has a
55
+ project with a name like it, and then `submit` stops and lists them. Do not
56
+ guess: show the person the list and ask. Then run one of:
57
+
58
+ ```bash
59
+ cbx submit --into <project> -m "…" # this folder is that project
60
+ cbx submit --new -m "…" # a separate project (add --name if the name is taken)
61
+ cbx link <project> # link only; send nothing yet
62
+ ```
63
+
64
+ Never start a second project for work that already has one. A folder copied to
65
+ another machine, another operating system or another path is still the same
66
+ project: `cbx link` it.
67
+
47
68
  Send only what changed; the version still names every file. Write the message
48
69
  yourself from the actual diff rather than asking for one — a message like
49
70
  "update" helps nobody reading the history later.
@@ -56,6 +77,33 @@ explain. Propose it, say what it would send, and let them agree.
56
77
  that freely; it is safe and it is the honest way to answer "what would this
57
78
  upload?".
58
79
 
80
+ ## Working in a git repository
81
+
82
+ CodeRook is a git remote. `npm install --global @coderook/cli` puts the helper
83
+ (`git-remote-coderook`) on PATH; the plugin and `npx` do not, so check with
84
+ `git ls-remote coderook://<project>` before relying on it.
85
+
86
+ ```bash
87
+ git remote -v # is there a coderook:// remote already?
88
+ git remote add coderook coderook://<project> # if not
89
+ git push coderook main # each new commit becomes a save
90
+ git push coderook <branch> # a branch becomes a line
91
+ git push coderook v1.2.0 # a tag names a version
92
+ git fetch coderook # bring other people's saves in
93
+ ```
94
+
95
+ If the project was started with `cbx submit` or the desktop app, the first push
96
+ is refused with a message saying so. When the repository holds that project,
97
+ `git push -o adopt coderook main` saves the current commit on top of what is
98
+ there, once; plain pushes work from then on. **Ask before adopting** — it is a
99
+ save like any other. If the project is somebody else's work under the same
100
+ name, push to a new name instead.
101
+
102
+ Git's limits here: no force pushes or branch deletions (saves are permanent), a
103
+ merge commit arrives as one save holding the merged tree, and a commit holding
104
+ a credential is refused — take the key out of history rather than looking for
105
+ a way round.
106
+
59
107
  ## Fetching
60
108
 
61
109
  ```bash
@@ -234,6 +282,20 @@ file with its size, SHA-256 and `url`. Updaters have no account, so the
234
282
  project they read must be public; keep private code in a separate project and
235
283
  ship releases from a public one.
236
284
 
285
+ ## Building executables for every platform
286
+
287
+ ```bash
288
+ cbx build --plan # how this machine would build each target
289
+ cbx build --target win,linux,mac # build them into .coderook/build/<target>/
290
+ ```
291
+
292
+ It builds on this machine, with the tools it has, and uploads nothing. Run
293
+ `--plan` first and read it out: a target marked "no" says what would build it
294
+ (Docker, a Mac, cargo-zigbuild) — pass that on rather than installing things
295
+ unasked. `--ship` attaches the results to the newest save, so **ask before
296
+ `--ship`**, as before any save. A project's own build description lives in
297
+ `coderook.build.json`.
298
+
237
299
  ## Things not to do
238
300
 
239
301
  - Do not run `cbx delete` unless the person has asked for that project to
@@ -242,6 +304,8 @@ ship releases from a public one.
242
304
  again and gains nothing.
243
305
  - Do not guess a project name. `cbx projects` lists them; a folder that is
244
306
  already linked needs no name at all.
307
+ - Do not pass `--new` to get past the question `submit` asks. It exists for a
308
+ separate project the person wants, not to avoid choosing.
245
309
  - Do not run `cbx take-down`. It destroys the files in a version and they do
246
310
  not come back. Say it exists and let its owner run it.
247
311