@coderook/cli 0.31.11 → 0.31.12
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/.claude-plugin/plugin.json +1 -1
- package/dist/cli/src/api.js +32 -0
- package/dist/cli/src/cli.js +32 -5
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "coderook",
|
|
3
3
|
"displayName": "CodeRook",
|
|
4
4
|
"description": "Save, browse and restore whole-snapshot versions of a project on CodeRook, from Claude Code.",
|
|
5
|
-
"version": "0.31.
|
|
5
|
+
"version": "0.31.12",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "ACCA Gaming Productions",
|
|
8
8
|
"url": "https://coderook.com"
|
package/dist/cli/src/api.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.completeUpload = completeUpload;
|
|
|
7
7
|
exports.attachToVersion = attachToVersion;
|
|
8
8
|
exports.whoami = whoami;
|
|
9
9
|
exports.projects = projects;
|
|
10
|
+
exports.projectById = projectById;
|
|
10
11
|
exports.findPublicProject = findPublicProject;
|
|
11
12
|
exports.findProject = findProject;
|
|
12
13
|
exports.health = health;
|
|
@@ -184,6 +185,37 @@ async function projects() {
|
|
|
184
185
|
updatedAt: String(row.updatedAt ?? row.createdAt ?? ""),
|
|
185
186
|
}));
|
|
186
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* One project by its id, including somebody else's public or unlisted one.
|
|
190
|
+
*
|
|
191
|
+
* The account's own list holds only projects it is in, so a folder cloned
|
|
192
|
+
* from somebody else's public project had no way back to it: every command
|
|
193
|
+
* after the clone said the project was "no longer on your account". The
|
|
194
|
+
* service answers this route for anybody signed in when the project is open,
|
|
195
|
+
* and says whether the caller is one of its people.
|
|
196
|
+
*/
|
|
197
|
+
async function projectById(repositoryId) {
|
|
198
|
+
try {
|
|
199
|
+
const row = await call(`/v1/repositories/${encodeURIComponent(repositoryId)}`);
|
|
200
|
+
if (!row.id)
|
|
201
|
+
return null;
|
|
202
|
+
return {
|
|
203
|
+
id: String(row.id),
|
|
204
|
+
slug: String(row.slug ?? ""),
|
|
205
|
+
name: String(row.displayName || row.slug || "Untitled"),
|
|
206
|
+
visibility: String(row.visibility ?? "public"),
|
|
207
|
+
defaultBranch: String(row.defaultBranch || "main"),
|
|
208
|
+
versionCount: Number(row.versionCount ?? 0),
|
|
209
|
+
fileCount: Number(row.fileCount ?? 0),
|
|
210
|
+
storedBytes: Number(row.storedSize ?? 0),
|
|
211
|
+
updatedAt: String(row.updatedAt ?? row.createdAt ?? ""),
|
|
212
|
+
member: row.member !== false,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
187
219
|
/**
|
|
188
220
|
* One public project, by the two names that identify it.
|
|
189
221
|
*
|
package/dist/cli/src/cli.js
CHANGED
|
@@ -195,9 +195,23 @@ const folderFor = (parsed, index = 0) => node_path_1.default.resolve(parsed.posi
|
|
|
195
195
|
async function reconcile(folder, options = {}) {
|
|
196
196
|
const link = await (0, config_js_1.readLink)(folder);
|
|
197
197
|
const reference = link?.slug ?? node_path_1.default.basename(folder);
|
|
198
|
-
|
|
198
|
+
let member = true;
|
|
199
|
+
let project = link
|
|
199
200
|
? (await (0, api_js_2.projects)()).find((candidate) => candidate.id === link.repositoryId)
|
|
200
201
|
: await (0, api_js_2.findProject)(reference);
|
|
202
|
+
/*
|
|
203
|
+
Not on the account's own list, which holds only projects it is in. A
|
|
204
|
+
folder cloned from somebody else's public project is exactly that, and
|
|
205
|
+
it was told the project had gone. Asked by id instead, the service still
|
|
206
|
+
answers for an open project and says the caller is a visitor.
|
|
207
|
+
*/
|
|
208
|
+
if (link && !project) {
|
|
209
|
+
const visited = await (0, api_js_2.projectById)(link.repositoryId);
|
|
210
|
+
if (visited) {
|
|
211
|
+
project = visited;
|
|
212
|
+
member = visited.member;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
201
215
|
/*
|
|
202
216
|
A link that has outlived the project it points at.
|
|
203
217
|
|
|
@@ -217,12 +231,12 @@ async function reconcile(folder, options = {}) {
|
|
|
217
231
|
}
|
|
218
232
|
if (!project?.versionCount) {
|
|
219
233
|
// Nothing saved on the account, so everything here is outstanding.
|
|
220
|
-
return { link: link ?? null, baseline: null, behind: null };
|
|
234
|
+
return { link: link ?? null, baseline: null, behind: null, member };
|
|
221
235
|
}
|
|
222
236
|
const downloader = new download_js_1.Downloader(config_js_1.credentials);
|
|
223
237
|
const latest = (await downloader.versions(project.id))[0];
|
|
224
238
|
if (!latest)
|
|
225
|
-
return { link: link ?? null, baseline: null, behind: null };
|
|
239
|
+
return { link: link ?? null, baseline: null, behind: null, member };
|
|
226
240
|
/*
|
|
227
241
|
A folder that already knows which version it stands on keeps it. Only a
|
|
228
242
|
folder that has never been reconciled — or was linked before versions
|
|
@@ -250,6 +264,7 @@ async function reconcile(folder, options = {}) {
|
|
|
250
264
|
*/
|
|
251
265
|
baseline: new Map(Object.entries(known.local ?? known.manifest)),
|
|
252
266
|
behind,
|
|
267
|
+
member,
|
|
253
268
|
};
|
|
254
269
|
}
|
|
255
270
|
const baseline = new Map();
|
|
@@ -271,7 +286,7 @@ async function reconcile(folder, options = {}) {
|
|
|
271
286
|
if (!options.quiet && !link) {
|
|
272
287
|
console.log(dim(`Linked this folder to ${project.slug}.`));
|
|
273
288
|
}
|
|
274
|
-
return { link: fresh, baseline, behind: null };
|
|
289
|
+
return { link: fresh, baseline, behind: null, member };
|
|
275
290
|
}
|
|
276
291
|
// ── commands ────────────────────────────────────────────────────────────────
|
|
277
292
|
async function commandSignIn(parsed) {
|
|
@@ -585,7 +600,19 @@ async function commandImport(parsed) {
|
|
|
585
600
|
async function commandSubmit(parsed) {
|
|
586
601
|
const folder = folderFor(parsed);
|
|
587
602
|
const message = flagText(parsed, "m", "message") ?? "";
|
|
588
|
-
const { link, baseline, behind } = await reconcile(folder);
|
|
603
|
+
const { link, baseline, behind, member } = await reconcile(folder);
|
|
604
|
+
/*
|
|
605
|
+
Somebody else's project, cloned from its public page. Reading and
|
|
606
|
+
fetching are fine; saving into it is not this account's to do, and the
|
|
607
|
+
service would refuse it anyway, less clearly.
|
|
608
|
+
*/
|
|
609
|
+
if (link && !member) {
|
|
610
|
+
console.error(red(`Access denied: you are not a collaborator on ${link.slug}.`) +
|
|
611
|
+
"\n" +
|
|
612
|
+
dim(` Ask its owner to invite you, or run ${accent("cbx unlink")} to start a project of ` +
|
|
613
|
+
"your own from these files."));
|
|
614
|
+
return 1;
|
|
615
|
+
}
|
|
589
616
|
/*
|
|
590
617
|
A first save gets a licence unless it is turned down.
|
|
591
618
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coderook/cli",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.12",
|
|
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": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"homepage": "https://coderook.com",
|