@coderook/cli 0.9.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/src/api.js +172 -0
- package/dist/cli/src/cli.js +430 -63
- package/dist/cli/src/help.js +88 -0
- package/dist/cli/src/project_commands.js +150 -0
- package/dist/cli/src/registry.js +73 -0
- package/dist/cli/src/runner.js +423 -0
- package/dist/cli/src/service_commands.js +238 -0
- package/package.json +48 -47
package/dist/cli/src/api.js
CHANGED
|
@@ -9,6 +9,20 @@ exports.mergeTrack = mergeTrack;
|
|
|
9
9
|
exports.resolveMergeConflict = resolveMergeConflict;
|
|
10
10
|
exports.applyMerge = applyMerge;
|
|
11
11
|
exports.cancelMerge = cancelMerge;
|
|
12
|
+
exports.aiAccess = aiAccess;
|
|
13
|
+
exports.setAiAccess = setAiAccess;
|
|
14
|
+
exports.versions = versions;
|
|
15
|
+
exports.issues = issues;
|
|
16
|
+
exports.createIssue = createIssue;
|
|
17
|
+
exports.releases = releases;
|
|
18
|
+
exports.collaborators = collaborators;
|
|
19
|
+
exports.invite = invite;
|
|
20
|
+
exports.watch = watch;
|
|
21
|
+
exports.setWatch = setWatch;
|
|
22
|
+
exports.workflows = workflows;
|
|
23
|
+
exports.tokens = tokens;
|
|
24
|
+
exports.revokeToken = revokeToken;
|
|
25
|
+
exports.deleteProject = deleteProject;
|
|
12
26
|
/** The small part of the API the command-line tool needs directly. */
|
|
13
27
|
const identify_js_1 = require("../../desktop-app/src/main/identify.js");
|
|
14
28
|
const config_js_1 = require("./config.js");
|
|
@@ -91,3 +105,161 @@ async function applyMerge(mergeTrackId) {
|
|
|
91
105
|
async function cancelMerge(mergeTrackId) {
|
|
92
106
|
await call(`/v1/merge-tracks/${mergeTrackId}/cancel`, { method: "POST" });
|
|
93
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Read one project's machine-access answers.
|
|
110
|
+
*
|
|
111
|
+
* Taken from the project record rather than a dedicated endpoint, because
|
|
112
|
+
* that is where they live — four columns on the repository, not a separate
|
|
113
|
+
* resource. Defaults to permissive, matching the service: a project that has
|
|
114
|
+
* never been touched allows everything.
|
|
115
|
+
*/
|
|
116
|
+
async function aiAccess(repositoryId) {
|
|
117
|
+
const body = await call(`/v1/repositories/${encodeURIComponent(repositoryId)}`);
|
|
118
|
+
const project = (body.repository ?? body);
|
|
119
|
+
/*
|
|
120
|
+
Read from the nested object the service actually sends, not from flat
|
|
121
|
+
fields beside it. Writing uses `aiRead`; reading returns `ai.read`, and
|
|
122
|
+
binding to the write shape made every setting report as allowed — a
|
|
123
|
+
missing field is not false, so a project with reading switched off said
|
|
124
|
+
it was on. The asymmetry is the API's; the mistake was assuming it away
|
|
125
|
+
rather than looking.
|
|
126
|
+
*/
|
|
127
|
+
const ai = (project.ai ?? {});
|
|
128
|
+
const allowed = (key) => ai[key] !== false;
|
|
129
|
+
return {
|
|
130
|
+
aiRead: allowed("read"),
|
|
131
|
+
aiDownload: allowed("download"),
|
|
132
|
+
aiContribute: allowed("contribute"),
|
|
133
|
+
aiRequest: allowed("request"),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Change one answer.
|
|
138
|
+
*
|
|
139
|
+
* One at a time, matching the site: each is a separate decision, and sending
|
|
140
|
+
* all four would make turning off downloads look like it needed a view about
|
|
141
|
+
* indexing as well.
|
|
142
|
+
*/
|
|
143
|
+
async function setAiAccess(repositoryId, change) {
|
|
144
|
+
await call(`/v1/repositories/${encodeURIComponent(repositoryId)}`, {
|
|
145
|
+
method: "PATCH",
|
|
146
|
+
body: change,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
/** Every saved version of a project, newest first. */
|
|
150
|
+
async function versions(repositoryId) {
|
|
151
|
+
const body = await call(`/v1/repositories/${encodeURIComponent(repositoryId)}/versions`);
|
|
152
|
+
return (body.versions ?? []).map((row) => ({
|
|
153
|
+
id: String(row.id ?? ""),
|
|
154
|
+
sequence: Number(row.sequence ?? 0),
|
|
155
|
+
message: String(row.message ?? ""),
|
|
156
|
+
fileCount: Number(row.fileCount ?? 0),
|
|
157
|
+
storedSize: Number(row.storedSize ?? row.sourceSize ?? 0),
|
|
158
|
+
createdAt: String(row.createdAt ?? ""),
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
async function issues(repositoryId) {
|
|
162
|
+
const body = await call(`/v1/repositories/${encodeURIComponent(repositoryId)}/issues`);
|
|
163
|
+
return {
|
|
164
|
+
issues: (body.issues ?? []).map((row) => ({
|
|
165
|
+
number: Number(row.number ?? 0),
|
|
166
|
+
title: String(row.title ?? ""),
|
|
167
|
+
state: String(row.state ?? "open"),
|
|
168
|
+
labels: Array.isArray(row.labels) ? row.labels : [],
|
|
169
|
+
commentCount: Number(row.commentCount ?? 0),
|
|
170
|
+
createdAt: String(row.createdAt ?? ""),
|
|
171
|
+
})),
|
|
172
|
+
openCount: Number(body.openCount ?? 0),
|
|
173
|
+
closedCount: Number(body.closedCount ?? 0),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
async function createIssue(repositoryId, input) {
|
|
177
|
+
/*
|
|
178
|
+
The number comes back at the top level, not nested under an `issue` key.
|
|
179
|
+
Reading the wrong shape reported every new issue as #0 — harmless in
|
|
180
|
+
itself, and exactly the kind of small wrongness that makes somebody stop
|
|
181
|
+
trusting the rest of the output.
|
|
182
|
+
*/
|
|
183
|
+
const created = await call(`/v1/repositories/${encodeURIComponent(repositoryId)}/issues`, { method: "POST", body: { title: input.title, body: input.body ?? "" } });
|
|
184
|
+
return { number: Number(created.number ?? 0) };
|
|
185
|
+
}
|
|
186
|
+
async function releases(repositoryId) {
|
|
187
|
+
const body = await call(`/v1/repositories/${encodeURIComponent(repositoryId)}/releases`);
|
|
188
|
+
return (body.releases ?? []).map((row) => ({
|
|
189
|
+
sequence: Number(row.sequence ?? 0),
|
|
190
|
+
name: String(row.name ?? ""),
|
|
191
|
+
notes: String(row.notes ?? ""),
|
|
192
|
+
releasedAt: String(row.releasedAt ?? ""),
|
|
193
|
+
releasedBy: String(row.releasedBy ?? ""),
|
|
194
|
+
assets: Array.isArray(row.assets) ? row.assets : [],
|
|
195
|
+
}));
|
|
196
|
+
}
|
|
197
|
+
async function collaborators(repositoryId) {
|
|
198
|
+
const body = await call(`/v1/repositories/${encodeURIComponent(repositoryId)}/collaborators`);
|
|
199
|
+
return {
|
|
200
|
+
collaborators: (body.collaborators ?? []).map((row) => ({
|
|
201
|
+
displayName: String(row.displayName ?? ""),
|
|
202
|
+
email: String(row.email ?? ""),
|
|
203
|
+
role: String(row.role ?? "member"),
|
|
204
|
+
})),
|
|
205
|
+
invites: (body.invites ?? []).map((row) => ({
|
|
206
|
+
email: String(row.email ?? ""),
|
|
207
|
+
role: String(row.role ?? "member"),
|
|
208
|
+
expiresAt: String(row.expiresAt ?? row.expires_at ?? ""),
|
|
209
|
+
})),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
async function invite(repositoryId, input) {
|
|
213
|
+
await call(`/v1/repositories/${encodeURIComponent(repositoryId)}/invites`, {
|
|
214
|
+
method: "POST",
|
|
215
|
+
body: input,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
async function watch(repositoryId) {
|
|
219
|
+
const body = await call(`/v1/repositories/${encodeURIComponent(repositoryId)}/watch`);
|
|
220
|
+
return {
|
|
221
|
+
level: String(body.level ?? "versions"),
|
|
222
|
+
inApp: body.inApp !== false,
|
|
223
|
+
desktop: body.desktop === true,
|
|
224
|
+
emailDigest: body.emailDigest === true,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
async function setWatch(repositoryId, change) {
|
|
228
|
+
await call(`/v1/repositories/${encodeURIComponent(repositoryId)}/watch`, {
|
|
229
|
+
method: "PUT",
|
|
230
|
+
body: change,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
async function workflows(repositoryId) {
|
|
234
|
+
const body = await call(`/v1/repositories/${encodeURIComponent(repositoryId)}/workflows`);
|
|
235
|
+
return (body.workflows ?? []).map((row) => ({
|
|
236
|
+
name: String(row.name ?? ""),
|
|
237
|
+
trigger: String(row.trigger ?? ""),
|
|
238
|
+
command: String(row.command ?? ""),
|
|
239
|
+
runsOn: String(row.runsOn ?? "hosted"),
|
|
240
|
+
runs: Number(row.runs ?? 0),
|
|
241
|
+
passing: Number(row.passing ?? 0),
|
|
242
|
+
archivedAt: row.archivedAt ? String(row.archivedAt) : null,
|
|
243
|
+
}));
|
|
244
|
+
}
|
|
245
|
+
/** Personal access tokens on the account. */
|
|
246
|
+
async function tokens() {
|
|
247
|
+
const body = await call("/v1/account/tokens");
|
|
248
|
+
return (body.tokens ?? []).map((row) => ({
|
|
249
|
+
id: String(row.id ?? ""),
|
|
250
|
+
name: String(row.name ?? ""),
|
|
251
|
+
lastUsedAt: String(row.lastUsedAt ?? ""),
|
|
252
|
+
createdAt: String(row.createdAt ?? ""),
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
255
|
+
async function revokeToken(tokenId) {
|
|
256
|
+
await call(`/v1/account/tokens/${encodeURIComponent(tokenId)}`, {
|
|
257
|
+
method: "DELETE",
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
/** Remove a project. The service keeps it for its retention window. */
|
|
261
|
+
async function deleteProject(repositoryId) {
|
|
262
|
+
await call(`/v1/repositories/${encodeURIComponent(repositoryId)}`, {
|
|
263
|
+
method: "DELETE",
|
|
264
|
+
});
|
|
265
|
+
}
|