@atollhq/cli 0.1.0 → 0.1.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/README.md +12 -1
- package/dist/index.js +135 -61
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,7 +41,18 @@ atoll --org my-org issue list
|
|
|
41
41
|
atoll --team eng issue create --title "..."
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Or via env vars: `ATOLL_API_KEY`, `ATOLL_ORG`, `ATOLL_TEAM`.
|
|
44
|
+
Or via env vars: `ATOLL_API_KEY`, `ATOLL_ORG`, `ATOLL_TEAM`, `ATOLL_BASE_URL`.
|
|
45
|
+
|
|
46
|
+
## Output URLs
|
|
47
|
+
|
|
48
|
+
Issue and project JSON output includes a canonical `url` field pointing at the Atoll web app (honoring `ATOLL_BASE_URL` for self-hosted / local dev), suitable for pasting into standups, notifications, and follow-ups:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
atoll issue view ATOLL-42 | jq -r .url
|
|
52
|
+
# https://atollhq.com/acme/projects/atoll/issues/42
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`url` is `null` for orphan issues (no project) or missing identifiers, so consumers should handle that case.
|
|
45
56
|
|
|
46
57
|
## License
|
|
47
58
|
|
package/dist/index.js
CHANGED
|
@@ -235,6 +235,30 @@ var RESET = isTTY() ? "\x1B[0m" : "";
|
|
|
235
235
|
var BOLD = isTTY() ? "\x1B[1m" : "";
|
|
236
236
|
var DIM = isTTY() ? "\x1B[2m" : "";
|
|
237
237
|
|
|
238
|
+
// src/lib/urls.ts
|
|
239
|
+
function derivePrefix(name) {
|
|
240
|
+
const cleaned = name.replace(/[^a-zA-Z0-9\s]/g, " ").trim();
|
|
241
|
+
const words = cleaned.split(/\s+/).filter(Boolean);
|
|
242
|
+
if (words.length === 0) return "TSK";
|
|
243
|
+
if (words.length >= 2) {
|
|
244
|
+
return words.slice(0, 5).map((w) => w[0]).join("").toUpperCase();
|
|
245
|
+
}
|
|
246
|
+
const word = words[0];
|
|
247
|
+
if (word.length <= 4) return word.toUpperCase();
|
|
248
|
+
return word.slice(0, 3).toUpperCase();
|
|
249
|
+
}
|
|
250
|
+
function stripTrailingSlash(baseUrl) {
|
|
251
|
+
return baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
252
|
+
}
|
|
253
|
+
function buildIssueUrl(baseUrl, orgSlug, projectSlug, issueNumber) {
|
|
254
|
+
if (!orgSlug || !projectSlug || issueNumber == null) return null;
|
|
255
|
+
return `${stripTrailingSlash(baseUrl)}/${orgSlug}/projects/${projectSlug}/issues/${issueNumber}`;
|
|
256
|
+
}
|
|
257
|
+
function buildProjectUrl(baseUrl, orgSlug, projectSlug) {
|
|
258
|
+
if (!orgSlug || !projectSlug) return null;
|
|
259
|
+
return `${stripTrailingSlash(baseUrl)}/${orgSlug}/projects/${projectSlug}`;
|
|
260
|
+
}
|
|
261
|
+
|
|
238
262
|
// src/commands/issue.ts
|
|
239
263
|
function handleApiError(err) {
|
|
240
264
|
const msg = err.message ?? String(err);
|
|
@@ -249,30 +273,48 @@ function handleApiError(err) {
|
|
|
249
273
|
}
|
|
250
274
|
var VALID_STATUSES = ["backlog", "todo", "in_progress", "done", "cancelled"];
|
|
251
275
|
var PRIORITY_LABELS = { 0: "Urgent", 1: "High", 2: "Medium", 3: "Low" };
|
|
252
|
-
async function
|
|
276
|
+
async function resolveOrg(client, orgSlugOverride) {
|
|
253
277
|
const { orgs } = await client.get("/api/orgs");
|
|
254
278
|
if (!orgs || orgs.length === 0) {
|
|
255
279
|
outputError("No organizations found. Create one first.");
|
|
256
280
|
process.exit(1);
|
|
257
281
|
}
|
|
258
|
-
if (orgs.length === 1) return orgs[0]
|
|
282
|
+
if (orgs.length === 1) return orgs[0];
|
|
259
283
|
const { readConfig: readConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
260
284
|
const config = readConfig2();
|
|
261
285
|
const slug = orgSlugOverride ?? process.env.ATOLL_ORG ?? config.orgSlug;
|
|
262
286
|
if (slug) {
|
|
263
287
|
const match = orgs.find((o) => o.slug === slug);
|
|
264
|
-
if (match) return match
|
|
288
|
+
if (match) return match;
|
|
265
289
|
outputError(`Org "${slug}" not found. Available: ${orgs.map((o) => o.slug).join(", ")}`);
|
|
266
290
|
process.exit(1);
|
|
267
291
|
}
|
|
268
292
|
outputError(`Multiple orgs found. Use --org <slug> or run \`atoll config set-org <slug>\`. Available: ${orgs.map((o) => o.slug).join(", ")}`);
|
|
269
293
|
process.exit(1);
|
|
270
294
|
}
|
|
295
|
+
async function resolveOrgId(client, orgSlugOverride) {
|
|
296
|
+
return (await resolveOrg(client, orgSlugOverride)).id;
|
|
297
|
+
}
|
|
298
|
+
async function fetchProjectMap(client, orgId) {
|
|
299
|
+
const { projects } = await client.get(
|
|
300
|
+
`/api/orgs/${orgId}/projects`
|
|
301
|
+
);
|
|
302
|
+
const map = /* @__PURE__ */ new Map();
|
|
303
|
+
for (const p of projects ?? []) map.set(p.id, p);
|
|
304
|
+
return map;
|
|
305
|
+
}
|
|
306
|
+
function attachIssueUrl(issue, baseUrl, orgSlug, projects) {
|
|
307
|
+
const project = issue.project_id ? projects.get(issue.project_id) : void 0;
|
|
308
|
+
return {
|
|
309
|
+
...issue,
|
|
310
|
+
url: buildIssueUrl(baseUrl, orgSlug, project?.slug, issue.number ?? null)
|
|
311
|
+
};
|
|
312
|
+
}
|
|
271
313
|
async function resolveIssueId(client, orgId, identifier) {
|
|
272
314
|
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(identifier)) {
|
|
273
315
|
return identifier;
|
|
274
316
|
}
|
|
275
|
-
const match = identifier.match(/^(?:[A-Za-
|
|
317
|
+
const match = identifier.match(/^(?:[A-Za-z0-9]+-)?(\d+)$/);
|
|
276
318
|
if (!match) {
|
|
277
319
|
outputError(`Invalid identifier: "${identifier}". Use a UUID or PREFIX-NUMBER (e.g. ATOLL-42).`);
|
|
278
320
|
process.exit(2);
|
|
@@ -298,8 +340,13 @@ async function resolveIssueId(client, orgId, identifier) {
|
|
|
298
340
|
outputError(`Issue #${num} not found.`);
|
|
299
341
|
process.exit(1);
|
|
300
342
|
}
|
|
301
|
-
function formatIdentifier(issue) {
|
|
302
|
-
|
|
343
|
+
function formatIdentifier(issue, projects) {
|
|
344
|
+
if (issue.number == null) return issue.id.slice(0, 8);
|
|
345
|
+
if (projects && issue.project_id) {
|
|
346
|
+
const project = projects.get(issue.project_id);
|
|
347
|
+
if (project?.name) return `${derivePrefix(project.name)}-${issue.number}`;
|
|
348
|
+
}
|
|
349
|
+
return `ATOLL-${issue.number}`;
|
|
303
350
|
}
|
|
304
351
|
function padEnd(str, len) {
|
|
305
352
|
return str.length >= len ? str.slice(0, len) : str + " ".repeat(len - str.length);
|
|
@@ -315,35 +362,41 @@ Examples:
|
|
|
315
362
|
issueCommand.command("list").description("List issues").option("--status <status>", `Filter by status (${VALID_STATUSES.join(", ")})`).option("--assignee <user>", "Filter by assignee ID").option("--priority <n>", "Filter by priority (0=urgent, 1=high, 2=medium, 3=low)", parseInt).option("--limit <n>", "Max results (1-100)", parseInt).action(async (opts) => {
|
|
316
363
|
try {
|
|
317
364
|
const client = new AtollClient();
|
|
318
|
-
const
|
|
365
|
+
const org = await resolveOrg(client);
|
|
319
366
|
const params = new URLSearchParams();
|
|
320
367
|
if (opts.status) params.set("status", opts.status);
|
|
321
368
|
if (opts.assignee) params.set("assigneeId", opts.assignee);
|
|
322
369
|
if (opts.priority !== void 0) params.set("priority", String(opts.priority));
|
|
323
370
|
if (opts.limit !== void 0) params.set("limit", String(opts.limit));
|
|
324
371
|
const qs = params.toString();
|
|
325
|
-
const data = await
|
|
372
|
+
const [data, projects] = await Promise.all([
|
|
373
|
+
client.get(`/api/orgs/${org.id}/issues${qs ? `?${qs}` : ""}`),
|
|
374
|
+
fetchProjectMap(client, org.id)
|
|
375
|
+
]);
|
|
376
|
+
const enriched = data.issues.map(
|
|
377
|
+
(issue) => attachIssueUrl(issue, client.baseUrl, org.slug, projects)
|
|
378
|
+
);
|
|
326
379
|
if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === "json") {
|
|
327
|
-
for (const issue of
|
|
380
|
+
for (const issue of enriched) {
|
|
328
381
|
process.stdout.write(JSON.stringify(issue) + "\n");
|
|
329
382
|
}
|
|
330
383
|
return;
|
|
331
384
|
}
|
|
332
|
-
if (
|
|
385
|
+
if (enriched.length === 0) {
|
|
333
386
|
console.log("No issues found.");
|
|
334
387
|
return;
|
|
335
388
|
}
|
|
336
389
|
const header = bold(`${padEnd("ID", 10)} ${padEnd("STATUS", 14)} ${padEnd("PRI", 8)} TITLE`);
|
|
337
390
|
console.log(header);
|
|
338
391
|
console.log("\u2500".repeat(82));
|
|
339
|
-
for (const issue of
|
|
340
|
-
const id = formatIdentifier(issue);
|
|
392
|
+
for (const issue of enriched) {
|
|
393
|
+
const id = formatIdentifier(issue, projects);
|
|
341
394
|
const pri = PRIORITY_LABELS[issue.priority] ?? String(issue.priority);
|
|
342
395
|
const title = issue.title.length > 50 ? issue.title.slice(0, 47) + "\u2026" : issue.title;
|
|
343
396
|
const icon = priorityIcon(issue.priority);
|
|
344
397
|
console.log(`${padEnd(id, 10)} ${statusColor(issue.status, padEnd(issue.status, 14))} ${icon} ${padEnd(pri, 8)} ${title}`);
|
|
345
398
|
}
|
|
346
|
-
console.log(dim(`${
|
|
399
|
+
console.log(dim(`${enriched.length} of ${data.total} issues`));
|
|
347
400
|
} catch (err) {
|
|
348
401
|
handleApiError(err);
|
|
349
402
|
}
|
|
@@ -351,33 +404,38 @@ issueCommand.command("list").description("List issues").option("--status <status
|
|
|
351
404
|
issueCommand.command("view <identifier>").description("View issue details (UUID or PREFIX-NUMBER e.g. ATOLL-42)").action(async (identifier) => {
|
|
352
405
|
try {
|
|
353
406
|
const client = new AtollClient();
|
|
354
|
-
const
|
|
355
|
-
const issueId = await resolveIssueId(client,
|
|
356
|
-
const { issue } = await
|
|
407
|
+
const org = await resolveOrg(client);
|
|
408
|
+
const issueId = await resolveIssueId(client, org.id, identifier);
|
|
409
|
+
const [{ issue }, projects] = await Promise.all([
|
|
410
|
+
client.get(`/api/orgs/${org.id}/issues/${issueId}`),
|
|
411
|
+
fetchProjectMap(client, org.id)
|
|
412
|
+
]);
|
|
413
|
+
const enriched = attachIssueUrl(issue, client.baseUrl, org.slug, projects);
|
|
357
414
|
if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === "json") {
|
|
358
|
-
process.stdout.write(JSON.stringify(
|
|
415
|
+
process.stdout.write(JSON.stringify(enriched) + "\n");
|
|
359
416
|
return;
|
|
360
417
|
}
|
|
361
|
-
const id = formatIdentifier(
|
|
362
|
-
const pri = PRIORITY_LABELS[
|
|
363
|
-
console.log(`${bold(id)} ${
|
|
364
|
-
console.log(`Status: ${statusColor(
|
|
365
|
-
if (
|
|
366
|
-
if (
|
|
367
|
-
if (
|
|
418
|
+
const id = formatIdentifier(enriched, projects);
|
|
419
|
+
const pri = PRIORITY_LABELS[enriched.priority] ?? String(enriched.priority);
|
|
420
|
+
console.log(`${bold(id)} ${enriched.title}`);
|
|
421
|
+
console.log(`Status: ${statusColor(enriched.status, enriched.status)} Priority: ${priorityIcon(enriched.priority)} ${pri}`);
|
|
422
|
+
if (enriched.url) console.log(`URL: ${enriched.url}`);
|
|
423
|
+
if (enriched.assignee_id) console.log(`Assignee: ${enriched.assignee_id}`);
|
|
424
|
+
if (enriched.due_date) console.log(`Due: ${enriched.due_date}`);
|
|
425
|
+
if (enriched.description) {
|
|
368
426
|
console.log(`
|
|
369
|
-
${
|
|
427
|
+
${enriched.description}`);
|
|
370
428
|
}
|
|
371
|
-
if (
|
|
372
|
-
const labels =
|
|
429
|
+
if (enriched.issue_labels && enriched.issue_labels.length > 0) {
|
|
430
|
+
const labels = enriched.issue_labels.map((l) => l.labels.name).join(", ");
|
|
373
431
|
console.log(`Labels: ${labels}`);
|
|
374
432
|
}
|
|
375
|
-
if (
|
|
433
|
+
if (enriched.sub_tasks && Array.isArray(enriched.sub_tasks) && enriched.sub_tasks.length > 0) {
|
|
376
434
|
console.log(`
|
|
377
|
-
Subtasks: ${
|
|
435
|
+
Subtasks: ${enriched.sub_tasks.length}`);
|
|
378
436
|
}
|
|
379
|
-
if (
|
|
380
|
-
if (
|
|
437
|
+
if (enriched.created_at) console.log(dim(`Created: ${enriched.created_at}`));
|
|
438
|
+
if (enriched.updated_at) console.log(dim(`Updated: ${enriched.updated_at}`));
|
|
381
439
|
} catch (err) {
|
|
382
440
|
handleApiError(err);
|
|
383
441
|
}
|
|
@@ -393,15 +451,18 @@ issueCommand.command("create").description("Create a new issue").requiredOption(
|
|
|
393
451
|
process.exit(2);
|
|
394
452
|
}
|
|
395
453
|
const client = new AtollClient();
|
|
396
|
-
const
|
|
454
|
+
const org = await resolveOrg(client);
|
|
397
455
|
const body = { title: opts.title };
|
|
398
456
|
if (opts.description !== void 0) body.description = opts.description;
|
|
399
457
|
if (opts.status) body.status = opts.status;
|
|
400
458
|
if (opts.priority !== void 0) body.priority = opts.priority;
|
|
401
|
-
const { issue } = await client.post(`/api/orgs/${
|
|
459
|
+
const { issue } = await client.post(`/api/orgs/${org.id}/issues`, body);
|
|
460
|
+
const projects = await fetchProjectMap(client, org.id);
|
|
461
|
+
const enriched = attachIssueUrl(issue, client.baseUrl, org.slug, projects);
|
|
402
462
|
output(
|
|
403
|
-
{ issue },
|
|
404
|
-
success(`Created ${formatIdentifier(
|
|
463
|
+
{ issue: enriched },
|
|
464
|
+
success(`Created ${formatIdentifier(enriched, projects)}: ${enriched.title}${enriched.url ? `
|
|
465
|
+
${enriched.url}` : ""}`)
|
|
405
466
|
);
|
|
406
467
|
} catch (err) {
|
|
407
468
|
handleApiError(err);
|
|
@@ -426,12 +487,14 @@ issueCommand.command("update <identifier>").description("Update an issue").optio
|
|
|
426
487
|
process.exit(2);
|
|
427
488
|
}
|
|
428
489
|
const client = new AtollClient();
|
|
429
|
-
const
|
|
430
|
-
const issueId = await resolveIssueId(client,
|
|
431
|
-
const { issue } = await client.patch(`/api/orgs/${
|
|
490
|
+
const org = await resolveOrg(client);
|
|
491
|
+
const issueId = await resolveIssueId(client, org.id, identifier);
|
|
492
|
+
const { issue } = await client.patch(`/api/orgs/${org.id}/issues/${issueId}`, body);
|
|
493
|
+
const projects = await fetchProjectMap(client, org.id);
|
|
494
|
+
const enriched = attachIssueUrl(issue, client.baseUrl, org.slug, projects);
|
|
432
495
|
output(
|
|
433
|
-
{ issue },
|
|
434
|
-
success(`Updated ${formatIdentifier(
|
|
496
|
+
{ issue: enriched },
|
|
497
|
+
success(`Updated ${formatIdentifier(enriched, projects)}: ${enriched.title}`)
|
|
435
498
|
);
|
|
436
499
|
} catch (err) {
|
|
437
500
|
handleApiError(err);
|
|
@@ -454,8 +517,8 @@ issueCommand.command("delete <identifier>").description("Delete an issue (admin/
|
|
|
454
517
|
issueCommand.command("assign <identifier>").description("Assign an issue to a user or agent").requiredOption("--to <user>", 'User/agent ID or "self" for yourself').action(async (identifier, opts) => {
|
|
455
518
|
try {
|
|
456
519
|
const client = new AtollClient();
|
|
457
|
-
const
|
|
458
|
-
const issueId = await resolveIssueId(client,
|
|
520
|
+
const org = await resolveOrg(client);
|
|
521
|
+
const issueId = await resolveIssueId(client, org.id, identifier);
|
|
459
522
|
let assigneeId = opts.to;
|
|
460
523
|
if (assigneeId === "self") {
|
|
461
524
|
const me = await client.get("/api/auth/me");
|
|
@@ -465,7 +528,7 @@ issueCommand.command("assign <identifier>").description("Assign an issue to a us
|
|
|
465
528
|
process.exit(1);
|
|
466
529
|
}
|
|
467
530
|
const { members } = await client.get(
|
|
468
|
-
`/api/orgs/${
|
|
531
|
+
`/api/orgs/${org.id}/members`
|
|
469
532
|
);
|
|
470
533
|
const member = members.find((m) => m.id === callerUserId || m.user_id === callerUserId);
|
|
471
534
|
if (!member) {
|
|
@@ -475,12 +538,14 @@ issueCommand.command("assign <identifier>").description("Assign an issue to a us
|
|
|
475
538
|
assigneeId = member.id;
|
|
476
539
|
}
|
|
477
540
|
const { issue } = await client.patch(
|
|
478
|
-
`/api/orgs/${
|
|
541
|
+
`/api/orgs/${org.id}/issues/${issueId}`,
|
|
479
542
|
{ assignee_id: assigneeId }
|
|
480
543
|
);
|
|
544
|
+
const projects = await fetchProjectMap(client, org.id);
|
|
545
|
+
const enriched = attachIssueUrl(issue, client.baseUrl, org.slug, projects);
|
|
481
546
|
output(
|
|
482
|
-
{ issue },
|
|
483
|
-
success(`Assigned ${formatIdentifier(
|
|
547
|
+
{ issue: enriched },
|
|
548
|
+
success(`Assigned ${formatIdentifier(enriched, projects)} to ${opts.to}`)
|
|
484
549
|
);
|
|
485
550
|
} catch (err) {
|
|
486
551
|
handleApiError(err);
|
|
@@ -489,15 +554,17 @@ issueCommand.command("assign <identifier>").description("Assign an issue to a us
|
|
|
489
554
|
issueCommand.command("unassign <identifier>").description("Remove assignee from an issue").action(async (identifier) => {
|
|
490
555
|
try {
|
|
491
556
|
const client = new AtollClient();
|
|
492
|
-
const
|
|
493
|
-
const issueId = await resolveIssueId(client,
|
|
557
|
+
const org = await resolveOrg(client);
|
|
558
|
+
const issueId = await resolveIssueId(client, org.id, identifier);
|
|
494
559
|
const { issue } = await client.patch(
|
|
495
|
-
`/api/orgs/${
|
|
560
|
+
`/api/orgs/${org.id}/issues/${issueId}`,
|
|
496
561
|
{ assignee_id: null }
|
|
497
562
|
);
|
|
563
|
+
const projects = await fetchProjectMap(client, org.id);
|
|
564
|
+
const enriched = attachIssueUrl(issue, client.baseUrl, org.slug, projects);
|
|
498
565
|
output(
|
|
499
|
-
{ issue },
|
|
500
|
-
success(`Unassigned ${formatIdentifier(
|
|
566
|
+
{ issue: enriched },
|
|
567
|
+
success(`Unassigned ${formatIdentifier(enriched, projects)}`)
|
|
501
568
|
);
|
|
502
569
|
} catch (err) {
|
|
503
570
|
handleApiError(err);
|
|
@@ -602,6 +669,9 @@ commentCommand.command("delete <comment-id>").description("Delete a comment").re
|
|
|
602
669
|
|
|
603
670
|
// src/commands/project.ts
|
|
604
671
|
var import_commander4 = require("commander");
|
|
672
|
+
function attachProjectUrl(project, baseUrl, orgSlug) {
|
|
673
|
+
return { ...project, url: buildProjectUrl(baseUrl, orgSlug, project.slug) };
|
|
674
|
+
}
|
|
605
675
|
function progressBar(progress, width = 20) {
|
|
606
676
|
const filled = Math.round(progress / 100 * width);
|
|
607
677
|
const empty = width - filled;
|
|
@@ -615,9 +685,9 @@ Examples:
|
|
|
615
685
|
projectCommand.command("list").description("List all projects with progress").action(async () => {
|
|
616
686
|
const client = new AtollClient();
|
|
617
687
|
try {
|
|
618
|
-
const
|
|
619
|
-
const data = await client.get(`/api/orgs/${
|
|
620
|
-
const projects = data.projects ?? [];
|
|
688
|
+
const org = await resolveOrg(client);
|
|
689
|
+
const data = await client.get(`/api/orgs/${org.id}/projects`);
|
|
690
|
+
const projects = (data.projects ?? []).map((p) => attachProjectUrl(p, client.baseUrl, org.slug));
|
|
621
691
|
if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === "json") {
|
|
622
692
|
for (const p of projects) {
|
|
623
693
|
process.stdout.write(JSON.stringify(p) + "\n");
|
|
@@ -634,6 +704,7 @@ projectCommand.command("list").description("List all projects with progress").ac
|
|
|
634
704
|
console.log(`${bold(`${p.icon} ${p.name}`)} ${dim(`(${p.id})`)}`);
|
|
635
705
|
if (p.description) console.log(` ${dim(p.description)}`);
|
|
636
706
|
console.log(` ${cyan(bar)} ${p.issueCount ?? 0} issues, ${p.completedCount ?? 0} done`);
|
|
707
|
+
if (p.url) console.log(` ${dim(p.url)}`);
|
|
637
708
|
if (p.status === "archived") console.log(` ${dim("[archived]")}`);
|
|
638
709
|
console.log("");
|
|
639
710
|
}
|
|
@@ -644,16 +715,18 @@ projectCommand.command("list").description("List all projects with progress").ac
|
|
|
644
715
|
projectCommand.command("create").description("Create a new project").requiredOption("--name <name>", "Project name").option("--description <desc>", "Project description").option("--color <color>", "Project color (hex)", "#6366f1").option("--icon <icon>", "Project icon (emoji)", "\u{1F4C1}").action(async (opts) => {
|
|
645
716
|
const client = new AtollClient();
|
|
646
717
|
try {
|
|
647
|
-
const
|
|
648
|
-
const data = await client.post(`/api/orgs/${
|
|
718
|
+
const org = await resolveOrg(client);
|
|
719
|
+
const data = await client.post(`/api/orgs/${org.id}/projects`, {
|
|
649
720
|
name: opts.name,
|
|
650
721
|
description: opts.description ?? null,
|
|
651
722
|
color: opts.color,
|
|
652
723
|
icon: opts.icon
|
|
653
724
|
});
|
|
725
|
+
const project = attachProjectUrl(data.project, client.baseUrl, org.slug);
|
|
654
726
|
output(
|
|
655
|
-
{ project
|
|
656
|
-
success(`Created project ${
|
|
727
|
+
{ project },
|
|
728
|
+
success(`Created project ${project.icon} ${project.name} (${dim(project.id)})${project.url ? `
|
|
729
|
+
${project.url}` : ""}`)
|
|
657
730
|
);
|
|
658
731
|
} catch (err) {
|
|
659
732
|
handleApiError(err);
|
|
@@ -662,11 +735,11 @@ projectCommand.command("create").description("Create a new project").requiredOpt
|
|
|
662
735
|
projectCommand.command("view <projectId>").description("View project details and issues").action(async (projectId) => {
|
|
663
736
|
const client = new AtollClient();
|
|
664
737
|
try {
|
|
665
|
-
const
|
|
738
|
+
const org = await resolveOrg(client);
|
|
666
739
|
const data = await client.get(
|
|
667
|
-
`/api/orgs/${
|
|
740
|
+
`/api/orgs/${org.id}/projects/${projectId}`
|
|
668
741
|
);
|
|
669
|
-
const p = data.project;
|
|
742
|
+
const p = attachProjectUrl(data.project, client.baseUrl, org.slug);
|
|
670
743
|
if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === "json") {
|
|
671
744
|
process.stdout.write(JSON.stringify(p) + "\n");
|
|
672
745
|
return;
|
|
@@ -674,6 +747,7 @@ projectCommand.command("view <projectId>").description("View project details and
|
|
|
674
747
|
const progress = p.progress ?? 0;
|
|
675
748
|
console.log(bold(`${p.icon} ${p.name}`));
|
|
676
749
|
if (p.description) console.log(` ${p.description}`);
|
|
750
|
+
if (p.url) console.log(` ${dim(p.url)}`);
|
|
677
751
|
console.log(` ${cyan(progressBar(progress))}`);
|
|
678
752
|
console.log(` ${p.issueCount ?? 0} issues \xB7 ${p.completedCount ?? 0} completed`);
|
|
679
753
|
console.log("");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/config.ts","../src/index.ts","../src/commands/auth.ts","../src/lib/client.ts","../src/lib/output.ts","../src/commands/issue.ts","../src/lib/colors.ts","../src/commands/comment.ts","../src/commands/project.ts","../src/commands/milestone.ts","../src/commands/config.ts","../src/commands/webhook.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nexport interface AtollConfig {\n apiKey?: string;\n orgSlug?: string;\n defaultTeam?: string;\n}\n\nconst CONFIG_DIR = join(homedir(), '.atoll');\nconst CONFIG_PATH = join(CONFIG_DIR, 'config.json');\n\nexport function readConfig(): AtollConfig {\n if (!existsSync(CONFIG_PATH)) return {};\n try {\n return JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));\n } catch {\n return {};\n }\n}\n\nexport function writeConfig(config: AtollConfig): void {\n if (!existsSync(CONFIG_DIR)) {\n mkdirSync(CONFIG_DIR, { recursive: true });\n }\n writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function deleteConfig(): void {\n if (existsSync(CONFIG_PATH)) {\n unlinkSync(CONFIG_PATH);\n }\n}\n\nexport function getApiKey(): string | undefined {\n return process.env.ATOLL_API_KEY || readConfig().apiKey;\n}\n","import { Command } from 'commander';\nimport { authCommand } from './commands/auth.js';\nimport { issueCommand } from './commands/issue.js';\nimport { commentCommand } from './commands/comment.js';\nimport { projectCommand } from './commands/project.js';\nimport { milestoneCommand } from './commands/milestone.js';\nimport { configCommand } from './commands/config.js';\nimport { webhookCommand } from './commands/webhook.js';\n\nconst program = new Command('atoll')\n .description('Atoll CLI — project management from the terminal')\n .version('0.1.0')\n .addHelpText('after', `\nExamples:\n $ atoll issue list\n $ atoll issue create --title \"Fix login bug\" --priority 1\n $ atoll issue view ATOLL-42\n $ atoll project list\n $ atoll milestone list --project <id>\n $ atoll config show`)\n // Global overrides — passed via env vars so sub-commands can pick them up\n .option('--org <slug>', 'Override default org slug (env: ATOLL_ORG)')\n .option('--team <id>', 'Override default team slug/ID (env: ATOLL_TEAM)')\n .hook('preAction', (thisCommand) => {\n const opts = thisCommand.opts();\n if (opts.org) process.env.ATOLL_ORG = opts.org;\n if (opts.team) process.env.ATOLL_TEAM = opts.team;\n });\n\nprogram.addCommand(authCommand);\nprogram.addCommand(issueCommand);\nprogram.addCommand(commentCommand);\nprogram.addCommand(projectCommand);\nprogram.addCommand(milestoneCommand);\nprogram.addCommand(configCommand);\nprogram.addCommand(webhookCommand);\n\n// ── atoll completion ────────────────────────────────────────────────────────\n\nconst completionCommand = new Command('completion')\n .description('Output shell completion scripts')\n .addHelpText('after', `\nExamples:\n $ atoll completion bash >> ~/.bashrc\n $ atoll completion zsh >> ~/.zshrc`);\n\ncompletionCommand\n .command('bash')\n .description('Output bash completion script')\n .action(() => {\n process.stdout.write(bashCompletion());\n });\n\ncompletionCommand\n .command('zsh')\n .description('Output zsh completion script')\n .action(() => {\n process.stdout.write(zshCompletion());\n });\n\nprogram.addCommand(completionCommand);\n\nprogram.parse();\n\n// ---------------------------------------------------------------------------\n// Completion script generators\n// ---------------------------------------------------------------------------\n\nfunction bashCompletion(): string {\n return `# Atoll CLI bash completion\n# Add to ~/.bashrc: source <(atoll completion bash)\n\n_atoll_completions() {\n local cur prev words cword\n _init_completion || return\n\n local commands=\"auth issue comment project milestone config webhook completion\"\n local issue_cmds=\"list view create update delete assign unassign\"\n local project_cmds=\"list create view\"\n local milestone_cmds=\"list create\"\n local config_cmds=\"show set-org set-team\"\n local auth_cmds=\"login logout status\"\n local webhook_cmds=\"list create delete\"\n local completion_cmds=\"bash zsh\"\n\n if [ \"\\${COMP_CWORD}\" -eq 1 ]; then\n COMPREPLY=( $(compgen -W \"\\${commands}\" -- \"\\${cur}\") )\n return 0\n fi\n\n case \"\\${words[1]}\" in\n issue)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${issue_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n project)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${project_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n milestone)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${milestone_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n config)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${config_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n auth)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${auth_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n webhook)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${webhook_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n completion)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${completion_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n esac\n}\n\ncomplete -F _atoll_completions atoll\n`;\n}\n\nfunction zshCompletion(): string {\n return `#compdef atoll\n# Atoll CLI zsh completion\n# Add to ~/.zshrc: source <(atoll completion zsh)\n\n_atoll() {\n local state\n\n _arguments \\\\\n '1: :->command' \\\\\n '*: :->args'\n\n case \\$state in\n command)\n _values 'command' \\\\\n 'auth[Manage authentication]' \\\\\n 'issue[Manage issues]' \\\\\n 'comment[Manage comments]' \\\\\n 'project[Manage projects]' \\\\\n 'milestone[Manage milestones]' \\\\\n 'config[Manage CLI configuration]' \\\\\n 'webhook[Manage outbound webhooks]' \\\\\n 'completion[Output shell completion scripts]'\n ;;\n args)\n case \\$words[2] in\n issue)\n _values 'subcommand' \\\\\n 'list[List issues]' \\\\\n 'view[View issue details]' \\\\\n 'create[Create a new issue]' \\\\\n 'update[Update an issue]' \\\\\n 'delete[Delete an issue]' \\\\\n 'assign[Assign an issue]' \\\\\n 'unassign[Remove assignee]'\n ;;\n project)\n _values 'subcommand' \\\\\n 'list[List projects]' \\\\\n 'create[Create a project]' \\\\\n 'view[View project details]'\n ;;\n milestone)\n _values 'subcommand' \\\\\n 'list[List milestones]' \\\\\n 'create[Create a milestone]'\n ;;\n config)\n _values 'subcommand' \\\\\n 'show[Show configuration]' \\\\\n 'set-org[Set default org slug]' \\\\\n 'set-team[Set default team]'\n ;;\n auth)\n _values 'subcommand' \\\\\n 'login[Log in]' \\\\\n 'logout[Log out]' \\\\\n 'status[Show auth status]'\n ;;\n webhook)\n _values 'subcommand' \\\\\n 'list[List webhooks]' \\\\\n 'create[Create a webhook]' \\\\\n 'delete[Delete a webhook]'\n ;;\n completion)\n _values 'shell' 'bash' 'zsh'\n ;;\n esac\n ;;\n esac\n}\n\n_atoll \"\\$@\"\n`;\n}\n","import { Command } from 'commander';\nimport { readConfig, writeConfig, deleteConfig, getApiKey } from '../lib/config.js';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\n\nexport const authCommand = new Command('auth')\n .description('Manage authentication');\n\nauthCommand\n .command('login')\n .description('Save an API key to ~/.atoll/config.json')\n .requiredOption('--key <API_KEY>', 'API key to store')\n .action((opts: { key: string }) => {\n const config = readConfig();\n config.apiKey = opts.key;\n writeConfig(config);\n output(\n { status: 'ok', message: 'API key saved' },\n '✓ API key saved to ~/.atoll/config.json',\n );\n });\n\nauthCommand\n .command('status')\n .description('Show current auth status and user info')\n .action(async () => {\n const apiKey = getApiKey();\n if (!apiKey) {\n outputError('Not authenticated. Run `atoll auth login --key <API_KEY>` or set ATOLL_API_KEY.');\n process.exit(1);\n }\n\n try {\n const client = new AtollClient({ apiKey });\n const me = await client.get<{\n user?: { email?: string; name?: string };\n org?: { slug?: string; name?: string };\n }>('/api/auth/me');\n\n output(\n { status: 'authenticated', ...me },\n [\n '✓ Authenticated',\n me.user?.name ? ` User: ${me.user.name}` : null,\n me.user?.email ? ` Email: ${me.user.email}` : null,\n me.org?.name ? ` Org: ${me.org.name} (${me.org.slug})` : null,\n ]\n .filter(Boolean)\n .join('\\n'),\n );\n } catch (err) {\n const msg = (err as Error).message || '';\n if (/API (401|403):/.test(msg)) {\n outputError('API key is invalid or expired');\n process.exit(1);\n }\n outputError(`Auth check failed: ${msg}`);\n process.exit(1);\n }\n });\n\nauthCommand\n .command('logout')\n .description('Remove stored API key')\n .action(() => {\n // Only clear the API key — preserve org/team config settings\n const config = readConfig();\n delete config.apiKey;\n writeConfig(config);\n output(\n { status: 'ok', message: 'Logged out' },\n '✓ Logged out — API key removed (org/team config preserved)',\n );\n });\n","import { getApiKey } from './config.js';\nimport { outputError } from './output.js';\n\nconst DEFAULT_BASE_URL = 'https://atollhq.com';\n\nexport class AtollClient {\n private baseUrl: string;\n private apiKey: string;\n\n constructor(opts?: { baseUrl?: string; apiKey?: string }) {\n this.baseUrl = opts?.baseUrl || process.env.ATOLL_BASE_URL || DEFAULT_BASE_URL;\n\n const key = opts?.apiKey || getApiKey();\n if (!key) {\n outputError('No API key found. Run `atoll auth login --key <API_KEY>` or set ATOLL_API_KEY.');\n process.exit(1);\n }\n this.apiKey = key;\n }\n\n async request<T = unknown>(path: string, init?: RequestInit): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const res = await fetch(url, {\n ...init,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n ...init?.headers,\n },\n });\n\n if (!res.ok) {\n const body = await res.text();\n throw new Error(`API ${res.status}: ${body}`);\n }\n\n return res.json() as Promise<T>;\n }\n\n async get<T = unknown>(path: string): Promise<T> {\n return this.request<T>(path, { method: 'GET' });\n }\n\n async post<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, {\n method: 'POST',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n async patch<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, {\n method: 'PATCH',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n async delete<T = unknown>(path: string): Promise<T> {\n return this.request<T>(path, { method: 'DELETE' });\n }\n}\n","export type OutputRecord = Record<string, unknown>;\n\nfunction isJsonMode(): boolean {\n if (process.env.OUTPUT_FORMAT === 'json') return true;\n return !process.stdout.isTTY;\n}\n\nexport function output(data: OutputRecord, humanReadable: string): void {\n if (isJsonMode()) {\n process.stdout.write(JSON.stringify(data) + '\\n');\n } else {\n console.log(humanReadable);\n }\n}\n\nexport function outputError(message: string): void {\n if (isJsonMode()) {\n process.stdout.write(JSON.stringify({ error: message }) + '\\n');\n } else {\n console.error(`Error: ${message}`);\n }\n}\n","import { Command } from 'commander';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\nimport { bold, dim, gray, statusColor, priorityIcon, success } from '../lib/colors.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface Issue {\n id: string;\n title: string;\n description?: string | null;\n status: string;\n priority: number;\n number?: number | null;\n assignee_id?: string | null;\n team_id?: string | null;\n project_id?: string | null;\n due_date?: string | null;\n created_at?: string;\n updated_at?: string;\n sub_tasks?: unknown[];\n issue_labels?: { label_id: string; labels: { name: string; color: string } }[];\n}\n\ninterface ListResponse {\n issues: Issue[];\n total: number;\n limit: number;\n offset: number;\n}\n\ninterface SingleResponse {\n issue: Issue;\n}\n\ninterface Org {\n id: string;\n name: string;\n slug: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nexport function handleApiError(err: unknown): never {\n const msg = (err as Error).message ?? String(err);\n if (/API 401\\b/.test(msg)) {\n outputError('Session expired — run `atoll auth login` to re-authenticate.');\n } else if (/API 403\\b/.test(msg)) {\n outputError('Permission denied. You do not have access to this resource.');\n } else {\n outputError(msg);\n }\n process.exit(1);\n}\n\nconst VALID_STATUSES = ['backlog', 'todo', 'in_progress', 'done', 'cancelled'] as const;\nconst PRIORITY_LABELS: Record<number, string> = { 0: 'Urgent', 1: 'High', 2: 'Medium', 3: 'Low' };\n\nexport async function resolveOrgId(client: AtollClient, orgSlugOverride?: string): Promise<string> {\n const { orgs } = await client.get<{ orgs: Org[] }>('/api/orgs');\n if (!orgs || orgs.length === 0) {\n outputError('No organizations found. Create one first.');\n process.exit(1);\n }\n if (orgs.length === 1) return orgs[0].id;\n\n // Resolve slug: CLI override → env var (set by --org global flag) → config file\n const { readConfig } = await import('../lib/config.js');\n const config = readConfig();\n const slug = orgSlugOverride ?? process.env.ATOLL_ORG ?? config.orgSlug;\n\n if (slug) {\n const match = orgs.find((o) => o.slug === slug);\n if (match) return match.id;\n outputError(`Org \"${slug}\" not found. Available: ${orgs.map((o) => o.slug).join(', ')}`);\n process.exit(1);\n }\n outputError(`Multiple orgs found. Use --org <slug> or run \\`atoll config set-org <slug>\\`. Available: ${orgs.map((o) => o.slug).join(', ')}`);\n process.exit(1);\n}\n\n/**\n * Resolve a human-readable identifier (e.g. \"ATOLL-42\" or \"42\") to a UUID.\n * Falls back to treating the identifier as a UUID if it doesn't match the pattern.\n */\nexport async function resolveIssueId(client: AtollClient, orgId: string, identifier: string): Promise<string> {\n // If it looks like a UUID already, return as-is\n if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(identifier)) {\n return identifier;\n }\n\n // Extract number from PREFIX-NUMBER or plain number\n const match = identifier.match(/^(?:[A-Za-z]+-)?(\\d+)$/);\n if (!match) {\n outputError(`Invalid identifier: \"${identifier}\". Use a UUID or PREFIX-NUMBER (e.g. ATOLL-42).`);\n process.exit(2);\n }\n\n const num = parseInt(match[1], 10);\n\n // Use number filter to avoid pagination issues with large issue lists\n const { issues } = await client.get<ListResponse>(\n `/api/orgs/${orgId}/issues?number=${num}&limit=1`,\n );\n if (issues.length > 0 && issues[0].number === num) {\n return issues[0].id;\n }\n\n // Fallback: paginate through all issues if the API doesn't support ?number= filtering\n let offset = 0;\n const pageSize = 100;\n while (true) {\n const page = await client.get<ListResponse>(\n `/api/orgs/${orgId}/issues?limit=${pageSize}&offset=${offset}`,\n );\n const found = page.issues.find((i) => i.number === num);\n if (found) return found.id;\n offset += pageSize;\n if (offset >= page.total) break;\n }\n\n outputError(`Issue #${num} not found.`);\n process.exit(1);\n}\n\nfunction formatIdentifier(issue: Issue): string {\n return issue.number != null ? `ATOLL-${issue.number}` : issue.id.slice(0, 8);\n}\n\nfunction padEnd(str: string, len: number): string {\n return str.length >= len ? str.slice(0, len) : str + ' '.repeat(len - str.length);\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport const issueCommand = new Command('issue')\n .description('Manage issues')\n .addHelpText('after', `\nExamples:\n $ atoll issue list\n $ atoll issue list --status in_progress --priority 1\n $ atoll issue view ATOLL-42\n $ atoll issue create --title \"Fix login\" --priority 1 --status todo\n $ atoll issue update ATOLL-42 --status done\n $ atoll issue assign ATOLL-42 --to <user-id>`);\n\n// ---- list ----\nissueCommand\n .command('list')\n .description('List issues')\n .option('--status <status>', `Filter by status (${VALID_STATUSES.join(', ')})`)\n .option('--assignee <user>', 'Filter by assignee ID')\n .option('--priority <n>', 'Filter by priority (0=urgent, 1=high, 2=medium, 3=low)', parseInt)\n .option('--limit <n>', 'Max results (1-100)', parseInt)\n .action(async (opts: { status?: string; assignee?: string; priority?: number; limit?: number }) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n\n const params = new URLSearchParams();\n if (opts.status) params.set('status', opts.status);\n if (opts.assignee) params.set('assigneeId', opts.assignee);\n if (opts.priority !== undefined) params.set('priority', String(opts.priority));\n if (opts.limit !== undefined) params.set('limit', String(opts.limit));\n\n const qs = params.toString();\n const data = await client.get<ListResponse>(`/api/orgs/${orgId}/issues${qs ? `?${qs}` : ''}`);\n\n // JSON mode: NDJSON\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n for (const issue of data.issues) {\n process.stdout.write(JSON.stringify(issue) + '\\n');\n }\n return;\n }\n\n // TTY: table\n if (data.issues.length === 0) {\n console.log('No issues found.');\n return;\n }\n\n const header = bold(`${padEnd('ID', 10)} ${padEnd('STATUS', 14)} ${padEnd('PRI', 8)} TITLE`);\n console.log(header);\n console.log('─'.repeat(82));\n for (const issue of data.issues) {\n const id = formatIdentifier(issue);\n const pri = PRIORITY_LABELS[issue.priority] ?? String(issue.priority);\n const title = issue.title.length > 50 ? issue.title.slice(0, 47) + '…' : issue.title;\n const icon = priorityIcon(issue.priority);\n console.log(`${padEnd(id, 10)} ${statusColor(issue.status, padEnd(issue.status, 14))} ${icon} ${padEnd(pri, 8)} ${title}`);\n }\n console.log(dim(`${data.issues.length} of ${data.total} issues`));\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- view ----\nissueCommand\n .command('view <identifier>')\n .description('View issue details (UUID or PREFIX-NUMBER e.g. ATOLL-42)')\n .action(async (identifier: string) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, identifier);\n\n const { issue } = await client.get<SingleResponse>(`/api/orgs/${orgId}/issues/${issueId}`);\n\n // JSON mode\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n process.stdout.write(JSON.stringify(issue) + '\\n');\n return;\n }\n\n // TTY: formatted detail\n const id = formatIdentifier(issue);\n const pri = PRIORITY_LABELS[issue.priority] ?? String(issue.priority);\n console.log(`${bold(id)} ${issue.title}`);\n console.log(`Status: ${statusColor(issue.status, issue.status)} Priority: ${priorityIcon(issue.priority)} ${pri}`);\n if (issue.assignee_id) console.log(`Assignee: ${issue.assignee_id}`);\n if (issue.due_date) console.log(`Due: ${issue.due_date}`);\n if (issue.description) {\n console.log(`\\n${issue.description}`);\n }\n if (issue.issue_labels && issue.issue_labels.length > 0) {\n const labels = issue.issue_labels.map((l) => l.labels.name).join(', ');\n console.log(`Labels: ${labels}`);\n }\n if (issue.sub_tasks && Array.isArray(issue.sub_tasks) && issue.sub_tasks.length > 0) {\n console.log(`\\nSubtasks: ${issue.sub_tasks.length}`);\n }\n if (issue.created_at) console.log(dim(`Created: ${issue.created_at}`));\n if (issue.updated_at) console.log(dim(`Updated: ${issue.updated_at}`));\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- create ----\nissueCommand\n .command('create')\n .description('Create a new issue')\n .requiredOption('--title <title>', 'Issue title')\n .option('--description <text>', 'Issue description')\n .option('--status <status>', `Status (${VALID_STATUSES.join(', ')})`)\n .option('--priority <n>', 'Priority (0=urgent, 1=high, 2=medium, 3=low)', parseInt)\n .action(async (opts: { title: string; description?: string; status?: string; priority?: number }) => {\n try {\n if (opts.status && !VALID_STATUSES.includes(opts.status as typeof VALID_STATUSES[number])) {\n outputError(`Invalid status \"${opts.status}\". Must be one of: ${VALID_STATUSES.join(', ')}`);\n process.exit(2);\n }\n if (opts.priority !== undefined && ![0, 1, 2, 3].includes(opts.priority)) {\n outputError('Priority must be 0 (urgent), 1 (high), 2 (medium), or 3 (low).');\n process.exit(2);\n }\n\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n\n const body: Record<string, unknown> = { title: opts.title };\n if (opts.description !== undefined) body.description = opts.description;\n if (opts.status) body.status = opts.status;\n if (opts.priority !== undefined) body.priority = opts.priority;\n\n const { issue } = await client.post<SingleResponse>(`/api/orgs/${orgId}/issues`, body);\n\n output(\n { issue },\n success(`Created ${formatIdentifier(issue)}: ${issue.title}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- update ----\nissueCommand\n .command('update <identifier>')\n .description('Update an issue')\n .option('--title <t>', 'New title')\n .option('--status <s>', `New status (${VALID_STATUSES.join(', ')})`)\n .option('--priority <p>', 'New priority (0-3)', parseInt)\n .action(async (identifier: string, opts: { title?: string; status?: string; priority?: number }) => {\n try {\n if (opts.status && !VALID_STATUSES.includes(opts.status as typeof VALID_STATUSES[number])) {\n outputError(`Invalid status \"${opts.status}\". Must be one of: ${VALID_STATUSES.join(', ')}`);\n process.exit(2);\n }\n if (opts.priority !== undefined && ![0, 1, 2, 3].includes(opts.priority)) {\n outputError('Priority must be 0-3.');\n process.exit(2);\n }\n\n const body: Record<string, unknown> = {};\n if (opts.title !== undefined) body.title = opts.title;\n if (opts.status) body.status = opts.status;\n if (opts.priority !== undefined) body.priority = opts.priority;\n\n if (Object.keys(body).length === 0) {\n outputError('No fields to update. Provide --title, --status, or --priority.');\n process.exit(2);\n }\n\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, identifier);\n\n const { issue } = await client.patch<SingleResponse>(`/api/orgs/${orgId}/issues/${issueId}`, body);\n\n output(\n { issue },\n success(`Updated ${formatIdentifier(issue)}: ${issue.title}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- delete ----\nissueCommand\n .command('delete <identifier>')\n .description('Delete an issue (admin/owner only)')\n .action(async (identifier: string) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, identifier);\n\n await client.delete(`/api/orgs/${orgId}/issues/${issueId}`);\n\n output(\n { success: true, id: issueId },\n success(`Deleted issue ${identifier}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- assign ----\nissueCommand\n .command('assign <identifier>')\n .description('Assign an issue to a user or agent')\n .requiredOption('--to <user>', 'User/agent ID or \"self\" for yourself')\n .action(async (identifier: string, opts: { to: string }) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, identifier);\n\n let assigneeId = opts.to;\n if (assigneeId === 'self') {\n const me = await client.get<{ auth?: { userId?: string } }>('/api/auth/me');\n // For agent keys, auth.userId IS the org_members.id directly\n const callerUserId = me.auth?.userId;\n if (!callerUserId) {\n outputError('Could not resolve your user ID.');\n process.exit(1);\n }\n // Agent callers: userId is the member id — use directly\n // Human callers: userId is the supabase auth id — look up member id\n const { members } = await client.get<{ members: { id: string; user_id: string }[] }>(\n `/api/orgs/${orgId}/members`,\n );\n const member = members.find((m) => m.id === callerUserId || m.user_id === callerUserId);\n if (!member) {\n outputError('You are not a member of this organisation.');\n process.exit(1);\n }\n assigneeId = member.id;\n }\n\n const { issue } = await client.patch<SingleResponse>(\n `/api/orgs/${orgId}/issues/${issueId}`,\n { assignee_id: assigneeId },\n );\n\n output(\n { issue },\n success(`Assigned ${formatIdentifier(issue)} to ${opts.to}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- unassign ----\nissueCommand\n .command('unassign <identifier>')\n .description('Remove assignee from an issue')\n .action(async (identifier: string) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, identifier);\n\n const { issue } = await client.patch<SingleResponse>(\n `/api/orgs/${orgId}/issues/${issueId}`,\n { assignee_id: null },\n );\n\n output(\n { issue },\n success(`Unassigned ${formatIdentifier(issue)}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n","/**\n * TTY-aware ANSI color helpers.\n * Colors are only emitted when stdout is a TTY and OUTPUT_FORMAT !== 'json'.\n */\n\nfunction isTTY(): boolean {\n return process.stdout.isTTY === true && process.env.OUTPUT_FORMAT !== 'json';\n}\n\nfunction ansi(code: string, text: string): string {\n if (!isTTY()) return text;\n return `\\x1b[${code}m${text}\\x1b[0m`;\n}\n\n// Basic colors\nexport const bold = (t: string) => ansi('1', t);\nexport const dim = (t: string) => ansi('2', t);\nexport const red = (t: string) => ansi('31', t);\nexport const green = (t: string) => ansi('32', t);\nexport const yellow = (t: string) => ansi('33', t);\nexport const blue = (t: string) => ansi('34', t);\nexport const cyan = (t: string) => ansi('36', t);\nexport const gray = (t: string) => ansi('90', t);\nexport const white = (t: string) => ansi('37', t);\n\n// Status badge colors\nexport function statusColor(status: string, text: string): string {\n switch (status) {\n case 'done': return green(text);\n case 'in_progress': return yellow(text);\n case 'backlog':\n case 'todo': return gray(text);\n case 'cancelled': return red(text);\n default: return text;\n }\n}\n\n// Priority icons\nexport function priorityIcon(priority: number): string {\n switch (priority) {\n case 0: return red('⚠⚠⚠'); // urgent\n case 1: return yellow('▄▆█'); // high\n case 2: return cyan('▄▆'); // medium\n case 3: return dim('---'); // low\n default: return String(priority);\n }\n}\n\n// Helpers\nexport const success = (msg: string) => green(`✓ ${msg}`);\nexport const error = (msg: string) => red(`Error: ${msg}`);\n\n// Raw ANSI codes (for use in format strings where needed)\nexport const RESET = isTTY() ? '\\x1b[0m' : '';\nexport const BOLD = isTTY() ? '\\x1b[1m' : '';\nexport const DIM = isTTY() ? '\\x1b[2m' : '';\n","import { Command } from 'commander';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\nimport { handleApiError, resolveOrgId, resolveIssueId } from './issue.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface CommentAuthor {\n id: string;\n display_name: string;\n type: string;\n avatar_url?: string;\n}\n\ninterface Comment {\n id: string;\n body: string;\n author_id: string;\n author_type?: string;\n author?: CommentAuthor;\n created_at?: string;\n updated_at?: string;\n}\n\ninterface ListCommentsResponse {\n comments: Comment[];\n}\n\ninterface SingleCommentResponse {\n comment: Comment;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst BOLD = '\\x1b[1m';\nconst DIM = '\\x1b[2m';\nconst RESET = '\\x1b[0m';\nconst CYAN = '\\x1b[36m';\n\nfunction formatAuthor(comment: Comment): string {\n const name = comment.author?.display_name ?? comment.author_id;\n const badge = (comment.author?.type ?? comment.author_type) === 'agent' ? ' [agent]' : '';\n return `${name}${badge}`;\n}\n\nfunction formatTimestamp(ts?: string): string {\n if (!ts) return '';\n const d = new Date(ts);\n return d.toLocaleString();\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport const commentCommand = new Command('comment')\n .description('Manage issue comments');\n\n// ---- list ----\ncommentCommand\n .command('list <identifier>')\n .description('List comments on an issue (UUID or PREFIX-NUMBER e.g. ATOLL-42)')\n .action(async (identifier: string) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, identifier);\n\n const data = await client.get<ListCommentsResponse>(\n `/api/orgs/${orgId}/issues/${issueId}/comments`,\n );\n\n // JSON mode: NDJSON\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n for (const comment of data.comments) {\n process.stdout.write(JSON.stringify(comment) + '\\n');\n }\n return;\n }\n\n // TTY: human-readable\n if (data.comments.length === 0) {\n console.log('No comments found.');\n return;\n }\n\n for (const comment of data.comments) {\n const author = formatAuthor(comment);\n const time = formatTimestamp(comment.created_at);\n console.log(`${BOLD}${CYAN}${author}${RESET} ${DIM}${time}${RESET}`);\n console.log(comment.body);\n console.log();\n }\n console.log(`${DIM}${data.comments.length} comment(s)${RESET}`);\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- add ----\ncommentCommand\n .command('add <identifier>')\n .description('Add a comment to an issue')\n .requiredOption('--body <text>', 'Comment body')\n .action(async (identifier: string, opts: { body: string }) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, identifier);\n\n const { comment } = await client.post<SingleCommentResponse>(\n `/api/orgs/${orgId}/issues/${issueId}/comments`,\n { body: opts.body },\n );\n\n output(\n { comment },\n `✓ Comment added to ${identifier}`,\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- update ----\ncommentCommand\n .command('update <comment-id>')\n .description('Update a comment')\n .requiredOption('--body <text>', 'New comment body')\n .requiredOption('--issue <identifier>', 'Issue identifier (e.g. UUID or PREFIX-NUMBER)')\n .action(async (commentId: string, opts: { body: string; issue: string }) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, opts.issue);\n\n const { comment } = await client.patch<SingleCommentResponse>(\n `/api/orgs/${orgId}/issues/${issueId}/comments/${commentId}`,\n { body: opts.body },\n );\n\n output(\n { comment },\n `✓ Comment ${commentId} updated`,\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- delete ----\ncommentCommand\n .command('delete <comment-id>')\n .description('Delete a comment')\n .requiredOption('--issue <identifier>', 'Issue identifier (e.g. UUID or PREFIX-NUMBER)')\n .action(async (commentId: string, opts: { issue: string }) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, opts.issue);\n\n await client.delete(`/api/orgs/${orgId}/issues/${issueId}/comments/${commentId}`);\n\n output(\n { success: true, id: commentId },\n `✓ Comment ${commentId} deleted`,\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n","import { Command } from 'commander';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\nimport { resolveOrgId, handleApiError } from './issue.js';\nimport { bold, dim, cyan, green, success } from '../lib/colors.js';\n\ninterface Project {\n id: string;\n name: string;\n description?: string | null;\n status: 'active' | 'archived';\n color: string;\n icon: string;\n issueCount?: number;\n completedCount?: number;\n progress?: number;\n created_at?: string;\n}\n\ninterface Issue {\n id: string;\n title: string;\n status: string;\n priority: number;\n number?: number | null;\n}\n\nfunction progressBar(progress: number, width = 20): string {\n const filled = Math.round((progress / 100) * width);\n const empty = width - filled;\n return `[${'█'.repeat(filled)}${'░'.repeat(empty)}] ${progress}%`;\n}\n\nexport const projectCommand = new Command('project')\n .description('Manage projects')\n .addHelpText('after', `\nExamples:\n $ atoll project list\n $ atoll project create --name \"My Project\" --icon 🚀\n $ atoll project view <project-id>`);\n\n// ── atoll project list ──────────────────────────────────────────────────────\n\nprojectCommand\n .command('list')\n .description('List all projects with progress')\n .action(async () => {\n const client = new AtollClient();\n try {\n const orgId = await resolveOrgId(client);\n const data = await client.get<{ projects: Project[] }>(`/api/orgs/${orgId}/projects`);\n const projects = data.projects ?? [];\n\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n for (const p of projects) {\n process.stdout.write(JSON.stringify(p) + '\\n');\n }\n return;\n }\n\n if (projects.length === 0) {\n console.log(dim('No projects found.'));\n return;\n }\n\n for (const p of projects) {\n const progress = p.progress ?? 0;\n const bar = progressBar(progress);\n console.log(`${bold(`${p.icon} ${p.name}`)} ${dim(`(${p.id})`)}`);\n if (p.description) console.log(` ${dim(p.description)}`);\n console.log(` ${cyan(bar)} ${p.issueCount ?? 0} issues, ${p.completedCount ?? 0} done`);\n if (p.status === 'archived') console.log(` ${dim('[archived]')}`);\n console.log('');\n }\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ── atoll project create ────────────────────────────────────────────────────\n\nprojectCommand\n .command('create')\n .description('Create a new project')\n .requiredOption('--name <name>', 'Project name')\n .option('--description <desc>', 'Project description')\n .option('--color <color>', 'Project color (hex)', '#6366f1')\n .option('--icon <icon>', 'Project icon (emoji)', '📁')\n .action(async (opts) => {\n const client = new AtollClient();\n try {\n const orgId = await resolveOrgId(client);\n const data = await client.post<{ project: Project }>(`/api/orgs/${orgId}/projects`, {\n name: opts.name,\n description: opts.description ?? null,\n color: opts.color,\n icon: opts.icon,\n });\n\n output(\n { project: data.project },\n success(`Created project ${data.project.icon} ${data.project.name} (${dim(data.project.id)})`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ── atoll project view ──────────────────────────────────────────────────────\n\nprojectCommand\n .command('view <projectId>')\n .description('View project details and issues')\n .action(async (projectId) => {\n const client = new AtollClient();\n try {\n const orgId = await resolveOrgId(client);\n const data = await client.get<{ project: Project & { issues: Issue[] } }>(\n `/api/orgs/${orgId}/projects/${projectId}`,\n );\n const p = data.project;\n\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n process.stdout.write(JSON.stringify(p) + '\\n');\n return;\n }\n\n const progress = p.progress ?? 0;\n console.log(bold(`${p.icon} ${p.name}`));\n if (p.description) console.log(` ${p.description}`);\n console.log(` ${cyan(progressBar(progress))}`);\n console.log(` ${(p.issueCount ?? 0)} issues · ${(p.completedCount ?? 0)} completed`);\n console.log('');\n\n const issues: Issue[] = (p as unknown as { issues?: Issue[] }).issues ?? [];\n if (issues.length === 0) {\n console.log(dim('No issues in this project.'));\n return;\n }\n\n console.log(bold('Issues'));\n for (const issue of issues) {\n const num = issue.number ? `#${issue.number}` : issue.id.slice(0, 8);\n console.log(` ${dim(num)} ${issue.title} ${dim(`[${issue.status}]`)}`);\n }\n } catch (err) {\n handleApiError(err);\n }\n });\n","import { Command } from 'commander';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\nimport { resolveOrgId, handleApiError } from './issue.js';\nimport { bold, dim, cyan, red, success } from '../lib/colors.js';\n\ninterface Milestone {\n id: string;\n name: string;\n description?: string | null;\n due_date?: string | null;\n status: 'active' | 'closed';\n issueCount?: number;\n completedCount?: number;\n progress?: number;\n isOverdue?: boolean;\n}\n\nfunction progressBar(progress: number, width = 20): string {\n const filled = Math.round((progress / 100) * width);\n const empty = width - filled;\n return `[${'█'.repeat(filled)}${'░'.repeat(empty)}] ${progress}%`;\n}\n\nexport const milestoneCommand = new Command('milestone')\n .description('Manage milestones')\n .addHelpText('after', `\nExamples:\n $ atoll milestone list --project <project-id>\n $ atoll milestone create --project <project-id> --name \"v1.0\" --date 2026-06-01`);\n\n// ── atoll milestone list ────────────────────────────────────────────────────\n\nmilestoneCommand\n .command('list')\n .description('List milestones for a project')\n .requiredOption('--project <id>', 'Project ID')\n .action(async (opts) => {\n const client = new AtollClient();\n try {\n const orgId = await resolveOrgId(client);\n const data = await client.get<{ milestones: Milestone[] }>(\n `/api/orgs/${orgId}/projects/${opts.project}/milestones`,\n );\n const milestones = data.milestones ?? [];\n\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n for (const m of milestones) {\n process.stdout.write(JSON.stringify(m) + '\\n');\n }\n return;\n }\n\n if (milestones.length === 0) {\n console.log(dim('No milestones found.'));\n return;\n }\n\n for (const m of milestones) {\n const progress = m.progress ?? 0;\n const bar = progressBar(progress);\n const overdue = m.isOverdue ? ` ${red('[OVERDUE]')}` : '';\n console.log(`${bold(m.name)} ${dim(`(${m.id})`)}${overdue}`);\n if (m.due_date) console.log(` Due: ${m.due_date}`);\n if (m.description) console.log(` ${dim(m.description)}`);\n console.log(` ${cyan(bar)} ${m.issueCount ?? 0} issues, ${m.completedCount ?? 0} done`);\n if (m.status === 'closed') console.log(` ${dim('[closed]')}`);\n console.log('');\n }\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ── atoll milestone create ──────────────────────────────────────────────────\n\nmilestoneCommand\n .command('create')\n .description('Create a new milestone')\n .requiredOption('--project <id>', 'Project ID')\n .requiredOption('--name <name>', 'Milestone name')\n .option('--date <YYYY-MM-DD>', 'Due date')\n .option('--description <desc>', 'Description')\n .action(async (opts) => {\n const client = new AtollClient();\n try {\n const orgId = await resolveOrgId(client);\n const data = await client.post<{ milestone: Milestone }>(\n `/api/orgs/${orgId}/projects/${opts.project}/milestones`,\n {\n name: opts.name,\n description: opts.description ?? null,\n dueDate: opts.date ?? null,\n },\n );\n\n output(\n { milestone: data.milestone },\n success(`Milestone created: ${bold(data.milestone.name)} ${dim(`(${data.milestone.id})`)}`),\n );\n if (data.milestone.due_date) {\n console.log(` Due: ${data.milestone.due_date}`);\n }\n } catch (err) {\n handleApiError(err);\n }\n });\n","import { Command } from 'commander';\nimport { readConfig, writeConfig } from '../lib/config.js';\nimport { output, outputError } from '../lib/output.js';\nimport { success, bold, dim, gray } from '../lib/colors.js';\nimport { getApiKey } from '../lib/config.js';\n\nexport const configCommand = new Command('config')\n .description('Manage CLI configuration (org, team, API key)')\n .addHelpText('after', `\nExamples:\n $ atoll config show\n $ atoll config set-org my-org\n $ atoll config set-team team-abc123`);\n\n// ── atoll config show ───────────────────────────────────────────────────────\n\nconfigCommand\n .command('show')\n .description('Display current configuration')\n .action(() => {\n const cfg = readConfig();\n const apiKeySet = !!(process.env.ATOLL_API_KEY || cfg.apiKey);\n\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n output(\n {\n orgSlug: cfg.orgSlug ?? null,\n defaultTeam: cfg.defaultTeam ?? null,\n apiKeySet,\n },\n '',\n );\n return;\n }\n\n console.log(`${bold('Atoll CLI Configuration')}`);\n console.log(` ${dim('Org slug:')} ${cfg.orgSlug ? bold(cfg.orgSlug) : gray('(not set)')}`);\n console.log(` ${dim('Default team:')} ${cfg.defaultTeam ? bold(cfg.defaultTeam) : gray('(not set)')}`);\n console.log(` ${dim('API key:')} ${apiKeySet ? bold('set') : gray('not set — run `atoll auth login`')}`);\n });\n\n// ── atoll config set-org ────────────────────────────────────────────────────\n\nconfigCommand\n .command('set-org <slug>')\n .description('Set the default organisation slug')\n .action((slug: string) => {\n const cfg = readConfig();\n cfg.orgSlug = slug;\n writeConfig(cfg);\n\n output(\n { orgSlug: slug },\n success(`Default org set to \"${slug}\"`),\n );\n });\n\n// ── atoll config set-team ───────────────────────────────────────────────────\n\nconfigCommand\n .command('set-team <team>')\n .description('Set the default team slug or ID')\n .action((team: string) => {\n const cfg = readConfig();\n cfg.defaultTeam = team;\n writeConfig(cfg);\n\n output(\n { defaultTeam: team },\n success(`Default team set to \"${team}\"`),\n );\n });\n","import { Command } from 'commander';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\nimport { bold, dim, green, gray, success } from '../lib/colors.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface Webhook {\n id: string;\n url: string;\n events: string[];\n enabled: boolean;\n created_at: string;\n}\n\ninterface WebhookListResponse {\n webhooks: Webhook[];\n}\n\ninterface WebhookCreateResponse {\n webhook: Webhook;\n secret: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction handleApiError(err: unknown): never {\n const msg = (err as Error).message ?? String(err);\n if (/API 401\\b/.test(msg)) {\n outputError('Session expired — run `atoll auth login` to re-authenticate.');\n } else if (/API 403\\b/.test(msg)) {\n outputError('Permission denied. You do not have access to this resource.');\n } else {\n outputError(msg);\n }\n process.exit(1);\n}\n\nasync function resolveOrgId(client: AtollClient, orgSlugOverride?: string): Promise<string> {\n const { orgs } = await client.get<{ orgs: { id: string; slug: string }[] }>('/api/orgs');\n if (!orgs || orgs.length === 0) {\n outputError('No organizations found.');\n process.exit(1);\n }\n if (orgs.length === 1) return orgs[0].id;\n\n const { readConfig } = await import('../lib/config.js');\n const config = readConfig();\n const slug = orgSlugOverride ?? process.env.ATOLL_ORG ?? config.orgSlug;\n\n if (slug) {\n const match = orgs.find((o) => o.slug === slug);\n if (match) return match.id;\n outputError(`Org \"${slug}\" not found. Available: ${orgs.map((o) => o.slug).join(', ')}`);\n process.exit(1);\n }\n outputError(`Multiple orgs found. Use --org <slug>.`);\n process.exit(1);\n}\n\nfunction padEnd(str: string, len: number): string {\n return str.length >= len ? str.slice(0, len) : str + ' '.repeat(len - str.length);\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport const webhookCommand = new Command('webhook')\n .description('Manage outbound webhooks')\n .addHelpText('after', `\nExamples:\n $ atoll webhook list\n $ atoll webhook create --url https://example.com/hook --events issue.created,issue.updated\n $ atoll webhook delete <id>`);\n\n// ---- list ----\nwebhookCommand\n .command('list')\n .description('List webhooks for the current org')\n .action(async () => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n\n const data = await client.get<WebhookListResponse>(`/api/webhooks?orgId=${orgId}`);\n\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n for (const wh of data.webhooks) {\n process.stdout.write(JSON.stringify(wh) + '\\n');\n }\n return;\n }\n\n if (data.webhooks.length === 0) {\n console.log('No webhooks configured.');\n return;\n }\n\n const header = bold(`${padEnd('ID', 38)} ${padEnd('URL', 40)} ${padEnd('EVENTS', 20)} ACTIVE`);\n console.log(header);\n console.log('─'.repeat(100));\n for (const wh of data.webhooks) {\n const evts = wh.events.length === 0 ? 'all' : wh.events.join(',');\n const active = wh.enabled ? green('yes') : gray('no');\n const url = wh.url.length > 38 ? wh.url.slice(0, 35) + '…' : wh.url;\n const evtStr = evts.length > 18 ? evts.slice(0, 15) + '…' : evts;\n console.log(`${padEnd(wh.id.slice(0, 36), 38)} ${padEnd(url, 40)} ${padEnd(evtStr, 20)} ${active}`);\n }\n console.log(dim(`${data.webhooks.length} webhook(s)`));\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- create ----\nwebhookCommand\n .command('create')\n .description('Create a new webhook')\n .requiredOption('--url <url>', 'Payload URL (HTTPS)')\n .option('--events <events>', 'Comma-separated event types (default: all)', '')\n .action(async (opts: { url: string; events: string }) => {\n try {\n if (!opts.url.startsWith('https://')) {\n outputError('URL must use HTTPS.');\n process.exit(2);\n }\n\n const events = opts.events\n ? opts.events.split(',').map((e) => e.trim()).filter(Boolean)\n : [];\n\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n\n const data = await client.post<WebhookCreateResponse>(\n `/api/webhooks?orgId=${orgId}`,\n { url: opts.url, events },\n );\n\n output(\n { webhook: data.webhook, secret: data.secret },\n [\n success(`Created webhook ${data.webhook.id}`),\n '',\n bold('Signing secret (save this — shown only once):'),\n ` ${data.secret}`,\n ].join('\\n'),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- delete ----\nwebhookCommand\n .command('delete <id>')\n .description('Delete a webhook')\n .action(async (id: string) => {\n try {\n const client = new AtollClient();\n await client.delete(`/api/webhooks/${id}`);\n\n output(\n { success: true, id },\n success(`Deleted webhook ${id}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n"],"mappings":"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","names":["import_commander","import_commander","readConfig","import_commander","BOLD","DIM","RESET","import_commander","import_commander","progressBar","import_commander","import_commander","handleApiError","resolveOrgId","readConfig","padEnd"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/config.ts","../src/index.ts","../src/commands/auth.ts","../src/lib/client.ts","../src/lib/output.ts","../src/commands/issue.ts","../src/lib/colors.ts","../src/lib/urls.ts","../src/commands/comment.ts","../src/commands/project.ts","../src/commands/milestone.ts","../src/commands/config.ts","../src/commands/webhook.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nexport interface AtollConfig {\n apiKey?: string;\n orgSlug?: string;\n defaultTeam?: string;\n}\n\nconst CONFIG_DIR = join(homedir(), '.atoll');\nconst CONFIG_PATH = join(CONFIG_DIR, 'config.json');\n\nexport function readConfig(): AtollConfig {\n if (!existsSync(CONFIG_PATH)) return {};\n try {\n return JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));\n } catch {\n return {};\n }\n}\n\nexport function writeConfig(config: AtollConfig): void {\n if (!existsSync(CONFIG_DIR)) {\n mkdirSync(CONFIG_DIR, { recursive: true });\n }\n writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function deleteConfig(): void {\n if (existsSync(CONFIG_PATH)) {\n unlinkSync(CONFIG_PATH);\n }\n}\n\nexport function getApiKey(): string | undefined {\n return process.env.ATOLL_API_KEY || readConfig().apiKey;\n}\n","import { Command } from 'commander';\nimport { authCommand } from './commands/auth.js';\nimport { issueCommand } from './commands/issue.js';\nimport { commentCommand } from './commands/comment.js';\nimport { projectCommand } from './commands/project.js';\nimport { milestoneCommand } from './commands/milestone.js';\nimport { configCommand } from './commands/config.js';\nimport { webhookCommand } from './commands/webhook.js';\n\nconst program = new Command('atoll')\n .description('Atoll CLI — project management from the terminal')\n .version('0.1.0')\n .addHelpText('after', `\nExamples:\n $ atoll issue list\n $ atoll issue create --title \"Fix login bug\" --priority 1\n $ atoll issue view ATOLL-42\n $ atoll project list\n $ atoll milestone list --project <id>\n $ atoll config show`)\n // Global overrides — passed via env vars so sub-commands can pick them up\n .option('--org <slug>', 'Override default org slug (env: ATOLL_ORG)')\n .option('--team <id>', 'Override default team slug/ID (env: ATOLL_TEAM)')\n .hook('preAction', (thisCommand) => {\n const opts = thisCommand.opts();\n if (opts.org) process.env.ATOLL_ORG = opts.org;\n if (opts.team) process.env.ATOLL_TEAM = opts.team;\n });\n\nprogram.addCommand(authCommand);\nprogram.addCommand(issueCommand);\nprogram.addCommand(commentCommand);\nprogram.addCommand(projectCommand);\nprogram.addCommand(milestoneCommand);\nprogram.addCommand(configCommand);\nprogram.addCommand(webhookCommand);\n\n// ── atoll completion ────────────────────────────────────────────────────────\n\nconst completionCommand = new Command('completion')\n .description('Output shell completion scripts')\n .addHelpText('after', `\nExamples:\n $ atoll completion bash >> ~/.bashrc\n $ atoll completion zsh >> ~/.zshrc`);\n\ncompletionCommand\n .command('bash')\n .description('Output bash completion script')\n .action(() => {\n process.stdout.write(bashCompletion());\n });\n\ncompletionCommand\n .command('zsh')\n .description('Output zsh completion script')\n .action(() => {\n process.stdout.write(zshCompletion());\n });\n\nprogram.addCommand(completionCommand);\n\nprogram.parse();\n\n// ---------------------------------------------------------------------------\n// Completion script generators\n// ---------------------------------------------------------------------------\n\nfunction bashCompletion(): string {\n return `# Atoll CLI bash completion\n# Add to ~/.bashrc: source <(atoll completion bash)\n\n_atoll_completions() {\n local cur prev words cword\n _init_completion || return\n\n local commands=\"auth issue comment project milestone config webhook completion\"\n local issue_cmds=\"list view create update delete assign unassign\"\n local project_cmds=\"list create view\"\n local milestone_cmds=\"list create\"\n local config_cmds=\"show set-org set-team\"\n local auth_cmds=\"login logout status\"\n local webhook_cmds=\"list create delete\"\n local completion_cmds=\"bash zsh\"\n\n if [ \"\\${COMP_CWORD}\" -eq 1 ]; then\n COMPREPLY=( $(compgen -W \"\\${commands}\" -- \"\\${cur}\") )\n return 0\n fi\n\n case \"\\${words[1]}\" in\n issue)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${issue_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n project)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${project_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n milestone)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${milestone_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n config)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${config_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n auth)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${auth_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n webhook)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${webhook_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n completion)\n if [ \"\\${COMP_CWORD}\" -eq 2 ]; then\n COMPREPLY=( $(compgen -W \"\\${completion_cmds}\" -- \"\\${cur}\") )\n fi\n ;;\n esac\n}\n\ncomplete -F _atoll_completions atoll\n`;\n}\n\nfunction zshCompletion(): string {\n return `#compdef atoll\n# Atoll CLI zsh completion\n# Add to ~/.zshrc: source <(atoll completion zsh)\n\n_atoll() {\n local state\n\n _arguments \\\\\n '1: :->command' \\\\\n '*: :->args'\n\n case \\$state in\n command)\n _values 'command' \\\\\n 'auth[Manage authentication]' \\\\\n 'issue[Manage issues]' \\\\\n 'comment[Manage comments]' \\\\\n 'project[Manage projects]' \\\\\n 'milestone[Manage milestones]' \\\\\n 'config[Manage CLI configuration]' \\\\\n 'webhook[Manage outbound webhooks]' \\\\\n 'completion[Output shell completion scripts]'\n ;;\n args)\n case \\$words[2] in\n issue)\n _values 'subcommand' \\\\\n 'list[List issues]' \\\\\n 'view[View issue details]' \\\\\n 'create[Create a new issue]' \\\\\n 'update[Update an issue]' \\\\\n 'delete[Delete an issue]' \\\\\n 'assign[Assign an issue]' \\\\\n 'unassign[Remove assignee]'\n ;;\n project)\n _values 'subcommand' \\\\\n 'list[List projects]' \\\\\n 'create[Create a project]' \\\\\n 'view[View project details]'\n ;;\n milestone)\n _values 'subcommand' \\\\\n 'list[List milestones]' \\\\\n 'create[Create a milestone]'\n ;;\n config)\n _values 'subcommand' \\\\\n 'show[Show configuration]' \\\\\n 'set-org[Set default org slug]' \\\\\n 'set-team[Set default team]'\n ;;\n auth)\n _values 'subcommand' \\\\\n 'login[Log in]' \\\\\n 'logout[Log out]' \\\\\n 'status[Show auth status]'\n ;;\n webhook)\n _values 'subcommand' \\\\\n 'list[List webhooks]' \\\\\n 'create[Create a webhook]' \\\\\n 'delete[Delete a webhook]'\n ;;\n completion)\n _values 'shell' 'bash' 'zsh'\n ;;\n esac\n ;;\n esac\n}\n\n_atoll \"\\$@\"\n`;\n}\n","import { Command } from 'commander';\nimport { readConfig, writeConfig, deleteConfig, getApiKey } from '../lib/config.js';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\n\nexport const authCommand = new Command('auth')\n .description('Manage authentication');\n\nauthCommand\n .command('login')\n .description('Save an API key to ~/.atoll/config.json')\n .requiredOption('--key <API_KEY>', 'API key to store')\n .action((opts: { key: string }) => {\n const config = readConfig();\n config.apiKey = opts.key;\n writeConfig(config);\n output(\n { status: 'ok', message: 'API key saved' },\n '✓ API key saved to ~/.atoll/config.json',\n );\n });\n\nauthCommand\n .command('status')\n .description('Show current auth status and user info')\n .action(async () => {\n const apiKey = getApiKey();\n if (!apiKey) {\n outputError('Not authenticated. Run `atoll auth login --key <API_KEY>` or set ATOLL_API_KEY.');\n process.exit(1);\n }\n\n try {\n const client = new AtollClient({ apiKey });\n const me = await client.get<{\n user?: { email?: string; name?: string };\n org?: { slug?: string; name?: string };\n }>('/api/auth/me');\n\n output(\n { status: 'authenticated', ...me },\n [\n '✓ Authenticated',\n me.user?.name ? ` User: ${me.user.name}` : null,\n me.user?.email ? ` Email: ${me.user.email}` : null,\n me.org?.name ? ` Org: ${me.org.name} (${me.org.slug})` : null,\n ]\n .filter(Boolean)\n .join('\\n'),\n );\n } catch (err) {\n const msg = (err as Error).message || '';\n if (/API (401|403):/.test(msg)) {\n outputError('API key is invalid or expired');\n process.exit(1);\n }\n outputError(`Auth check failed: ${msg}`);\n process.exit(1);\n }\n });\n\nauthCommand\n .command('logout')\n .description('Remove stored API key')\n .action(() => {\n // Only clear the API key — preserve org/team config settings\n const config = readConfig();\n delete config.apiKey;\n writeConfig(config);\n output(\n { status: 'ok', message: 'Logged out' },\n '✓ Logged out — API key removed (org/team config preserved)',\n );\n });\n","import { getApiKey } from './config.js';\nimport { outputError } from './output.js';\n\nconst DEFAULT_BASE_URL = 'https://atollhq.com';\n\nexport class AtollClient {\n readonly baseUrl: string;\n private apiKey: string;\n\n constructor(opts?: { baseUrl?: string; apiKey?: string }) {\n this.baseUrl = opts?.baseUrl || process.env.ATOLL_BASE_URL || DEFAULT_BASE_URL;\n\n const key = opts?.apiKey || getApiKey();\n if (!key) {\n outputError('No API key found. Run `atoll auth login --key <API_KEY>` or set ATOLL_API_KEY.');\n process.exit(1);\n }\n this.apiKey = key;\n }\n\n async request<T = unknown>(path: string, init?: RequestInit): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const res = await fetch(url, {\n ...init,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n ...init?.headers,\n },\n });\n\n if (!res.ok) {\n const body = await res.text();\n throw new Error(`API ${res.status}: ${body}`);\n }\n\n return res.json() as Promise<T>;\n }\n\n async get<T = unknown>(path: string): Promise<T> {\n return this.request<T>(path, { method: 'GET' });\n }\n\n async post<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, {\n method: 'POST',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n async patch<T = unknown>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, {\n method: 'PATCH',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n async delete<T = unknown>(path: string): Promise<T> {\n return this.request<T>(path, { method: 'DELETE' });\n }\n}\n","export type OutputRecord = Record<string, unknown>;\n\nfunction isJsonMode(): boolean {\n if (process.env.OUTPUT_FORMAT === 'json') return true;\n return !process.stdout.isTTY;\n}\n\nexport function output(data: OutputRecord, humanReadable: string): void {\n if (isJsonMode()) {\n process.stdout.write(JSON.stringify(data) + '\\n');\n } else {\n console.log(humanReadable);\n }\n}\n\nexport function outputError(message: string): void {\n if (isJsonMode()) {\n process.stdout.write(JSON.stringify({ error: message }) + '\\n');\n } else {\n console.error(`Error: ${message}`);\n }\n}\n","import { Command } from 'commander';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\nimport { bold, dim, gray, statusColor, priorityIcon, success } from '../lib/colors.js';\nimport { buildIssueUrl, derivePrefix } from '../lib/urls.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface Issue {\n id: string;\n title: string;\n description?: string | null;\n status: string;\n priority: number;\n number?: number | null;\n assignee_id?: string | null;\n team_id?: string | null;\n project_id?: string | null;\n due_date?: string | null;\n created_at?: string;\n updated_at?: string;\n sub_tasks?: unknown[];\n issue_labels?: { label_id: string; labels: { name: string; color: string } }[];\n}\n\ninterface ListResponse {\n issues: Issue[];\n total: number;\n limit: number;\n offset: number;\n}\n\ninterface SingleResponse {\n issue: Issue;\n}\n\ninterface Org {\n id: string;\n name: string;\n slug: string;\n}\n\ninterface ProjectSummary {\n id: string;\n name: string;\n slug?: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nexport function handleApiError(err: unknown): never {\n const msg = (err as Error).message ?? String(err);\n if (/API 401\\b/.test(msg)) {\n outputError('Session expired — run `atoll auth login` to re-authenticate.');\n } else if (/API 403\\b/.test(msg)) {\n outputError('Permission denied. You do not have access to this resource.');\n } else {\n outputError(msg);\n }\n process.exit(1);\n}\n\nconst VALID_STATUSES = ['backlog', 'todo', 'in_progress', 'done', 'cancelled'] as const;\nconst PRIORITY_LABELS: Record<number, string> = { 0: 'Urgent', 1: 'High', 2: 'Medium', 3: 'Low' };\n\nexport async function resolveOrg(client: AtollClient, orgSlugOverride?: string): Promise<Org> {\n const { orgs } = await client.get<{ orgs: Org[] }>('/api/orgs');\n if (!orgs || orgs.length === 0) {\n outputError('No organizations found. Create one first.');\n process.exit(1);\n }\n if (orgs.length === 1) return orgs[0];\n\n // Resolve slug: CLI override → env var (set by --org global flag) → config file\n const { readConfig } = await import('../lib/config.js');\n const config = readConfig();\n const slug = orgSlugOverride ?? process.env.ATOLL_ORG ?? config.orgSlug;\n\n if (slug) {\n const match = orgs.find((o) => o.slug === slug);\n if (match) return match;\n outputError(`Org \"${slug}\" not found. Available: ${orgs.map((o) => o.slug).join(', ')}`);\n process.exit(1);\n }\n outputError(`Multiple orgs found. Use --org <slug> or run \\`atoll config set-org <slug>\\`. Available: ${orgs.map((o) => o.slug).join(', ')}`);\n process.exit(1);\n}\n\nexport async function resolveOrgId(client: AtollClient, orgSlugOverride?: string): Promise<string> {\n return (await resolveOrg(client, orgSlugOverride)).id;\n}\n\n/**\n * Fetch the org's projects and return a map keyed by project id.\n * Used to derive PREFIX-NUMBER identifiers and canonical URLs for issues.\n */\nexport async function fetchProjectMap(\n client: AtollClient,\n orgId: string,\n): Promise<Map<string, ProjectSummary>> {\n const { projects } = await client.get<{ projects: ProjectSummary[] }>(\n `/api/orgs/${orgId}/projects`,\n );\n const map = new Map<string, ProjectSummary>();\n for (const p of projects ?? []) map.set(p.id, p);\n return map;\n}\n\nexport interface IssueWithUrl extends Issue {\n url: string | null;\n}\n\nexport function attachIssueUrl(\n issue: Issue,\n baseUrl: string,\n orgSlug: string,\n projects: Map<string, ProjectSummary>,\n): IssueWithUrl {\n const project = issue.project_id ? projects.get(issue.project_id) : undefined;\n return {\n ...issue,\n url: buildIssueUrl(baseUrl, orgSlug, project?.slug, issue.number ?? null),\n };\n}\n\n/**\n * Resolve a human-readable identifier (e.g. \"ATOLL-42\" or \"42\") to a UUID.\n * Falls back to treating the identifier as a UUID if it doesn't match the pattern.\n */\nexport async function resolveIssueId(client: AtollClient, orgId: string, identifier: string): Promise<string> {\n // If it looks like a UUID already, return as-is\n if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(identifier)) {\n return identifier;\n }\n\n // Extract number from PREFIX-NUMBER or plain number. Prefix may contain\n // digits (e.g. \"Q2-42\") since derivePrefix preserves alphanumerics.\n const match = identifier.match(/^(?:[A-Za-z0-9]+-)?(\\d+)$/);\n if (!match) {\n outputError(`Invalid identifier: \"${identifier}\". Use a UUID or PREFIX-NUMBER (e.g. ATOLL-42).`);\n process.exit(2);\n }\n\n const num = parseInt(match[1], 10);\n\n // Use number filter to avoid pagination issues with large issue lists\n const { issues } = await client.get<ListResponse>(\n `/api/orgs/${orgId}/issues?number=${num}&limit=1`,\n );\n if (issues.length > 0 && issues[0].number === num) {\n return issues[0].id;\n }\n\n // Fallback: paginate through all issues if the API doesn't support ?number= filtering\n let offset = 0;\n const pageSize = 100;\n while (true) {\n const page = await client.get<ListResponse>(\n `/api/orgs/${orgId}/issues?limit=${pageSize}&offset=${offset}`,\n );\n const found = page.issues.find((i) => i.number === num);\n if (found) return found.id;\n offset += pageSize;\n if (offset >= page.total) break;\n }\n\n outputError(`Issue #${num} not found.`);\n process.exit(1);\n}\n\nfunction formatIdentifier(issue: Issue, projects?: Map<string, ProjectSummary>): string {\n if (issue.number == null) return issue.id.slice(0, 8);\n if (projects && issue.project_id) {\n const project = projects.get(issue.project_id);\n if (project?.name) return `${derivePrefix(project.name)}-${issue.number}`;\n }\n return `ATOLL-${issue.number}`;\n}\n\nfunction padEnd(str: string, len: number): string {\n return str.length >= len ? str.slice(0, len) : str + ' '.repeat(len - str.length);\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport const issueCommand = new Command('issue')\n .description('Manage issues')\n .addHelpText('after', `\nExamples:\n $ atoll issue list\n $ atoll issue list --status in_progress --priority 1\n $ atoll issue view ATOLL-42\n $ atoll issue create --title \"Fix login\" --priority 1 --status todo\n $ atoll issue update ATOLL-42 --status done\n $ atoll issue assign ATOLL-42 --to <user-id>`);\n\n// ---- list ----\nissueCommand\n .command('list')\n .description('List issues')\n .option('--status <status>', `Filter by status (${VALID_STATUSES.join(', ')})`)\n .option('--assignee <user>', 'Filter by assignee ID')\n .option('--priority <n>', 'Filter by priority (0=urgent, 1=high, 2=medium, 3=low)', parseInt)\n .option('--limit <n>', 'Max results (1-100)', parseInt)\n .action(async (opts: { status?: string; assignee?: string; priority?: number; limit?: number }) => {\n try {\n const client = new AtollClient();\n const org = await resolveOrg(client);\n\n const params = new URLSearchParams();\n if (opts.status) params.set('status', opts.status);\n if (opts.assignee) params.set('assigneeId', opts.assignee);\n if (opts.priority !== undefined) params.set('priority', String(opts.priority));\n if (opts.limit !== undefined) params.set('limit', String(opts.limit));\n\n const qs = params.toString();\n const [data, projects] = await Promise.all([\n client.get<ListResponse>(`/api/orgs/${org.id}/issues${qs ? `?${qs}` : ''}`),\n fetchProjectMap(client, org.id),\n ]);\n\n const enriched = data.issues.map((issue) =>\n attachIssueUrl(issue, client.baseUrl, org.slug, projects),\n );\n\n // JSON mode: NDJSON\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n for (const issue of enriched) {\n process.stdout.write(JSON.stringify(issue) + '\\n');\n }\n return;\n }\n\n // TTY: table\n if (enriched.length === 0) {\n console.log('No issues found.');\n return;\n }\n\n const header = bold(`${padEnd('ID', 10)} ${padEnd('STATUS', 14)} ${padEnd('PRI', 8)} TITLE`);\n console.log(header);\n console.log('─'.repeat(82));\n for (const issue of enriched) {\n const id = formatIdentifier(issue, projects);\n const pri = PRIORITY_LABELS[issue.priority] ?? String(issue.priority);\n const title = issue.title.length > 50 ? issue.title.slice(0, 47) + '…' : issue.title;\n const icon = priorityIcon(issue.priority);\n console.log(`${padEnd(id, 10)} ${statusColor(issue.status, padEnd(issue.status, 14))} ${icon} ${padEnd(pri, 8)} ${title}`);\n }\n console.log(dim(`${enriched.length} of ${data.total} issues`));\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- view ----\nissueCommand\n .command('view <identifier>')\n .description('View issue details (UUID or PREFIX-NUMBER e.g. ATOLL-42)')\n .action(async (identifier: string) => {\n try {\n const client = new AtollClient();\n const org = await resolveOrg(client);\n const issueId = await resolveIssueId(client, org.id, identifier);\n\n const [{ issue }, projects] = await Promise.all([\n client.get<SingleResponse>(`/api/orgs/${org.id}/issues/${issueId}`),\n fetchProjectMap(client, org.id),\n ]);\n\n const enriched = attachIssueUrl(issue, client.baseUrl, org.slug, projects);\n\n // JSON mode\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n process.stdout.write(JSON.stringify(enriched) + '\\n');\n return;\n }\n\n // TTY: formatted detail\n const id = formatIdentifier(enriched, projects);\n const pri = PRIORITY_LABELS[enriched.priority] ?? String(enriched.priority);\n console.log(`${bold(id)} ${enriched.title}`);\n console.log(`Status: ${statusColor(enriched.status, enriched.status)} Priority: ${priorityIcon(enriched.priority)} ${pri}`);\n if (enriched.url) console.log(`URL: ${enriched.url}`);\n if (enriched.assignee_id) console.log(`Assignee: ${enriched.assignee_id}`);\n if (enriched.due_date) console.log(`Due: ${enriched.due_date}`);\n if (enriched.description) {\n console.log(`\\n${enriched.description}`);\n }\n if (enriched.issue_labels && enriched.issue_labels.length > 0) {\n const labels = enriched.issue_labels.map((l) => l.labels.name).join(', ');\n console.log(`Labels: ${labels}`);\n }\n if (enriched.sub_tasks && Array.isArray(enriched.sub_tasks) && enriched.sub_tasks.length > 0) {\n console.log(`\\nSubtasks: ${enriched.sub_tasks.length}`);\n }\n if (enriched.created_at) console.log(dim(`Created: ${enriched.created_at}`));\n if (enriched.updated_at) console.log(dim(`Updated: ${enriched.updated_at}`));\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- create ----\nissueCommand\n .command('create')\n .description('Create a new issue')\n .requiredOption('--title <title>', 'Issue title')\n .option('--description <text>', 'Issue description')\n .option('--status <status>', `Status (${VALID_STATUSES.join(', ')})`)\n .option('--priority <n>', 'Priority (0=urgent, 1=high, 2=medium, 3=low)', parseInt)\n .action(async (opts: { title: string; description?: string; status?: string; priority?: number }) => {\n try {\n if (opts.status && !VALID_STATUSES.includes(opts.status as typeof VALID_STATUSES[number])) {\n outputError(`Invalid status \"${opts.status}\". Must be one of: ${VALID_STATUSES.join(', ')}`);\n process.exit(2);\n }\n if (opts.priority !== undefined && ![0, 1, 2, 3].includes(opts.priority)) {\n outputError('Priority must be 0 (urgent), 1 (high), 2 (medium), or 3 (low).');\n process.exit(2);\n }\n\n const client = new AtollClient();\n const org = await resolveOrg(client);\n\n const body: Record<string, unknown> = { title: opts.title };\n if (opts.description !== undefined) body.description = opts.description;\n if (opts.status) body.status = opts.status;\n if (opts.priority !== undefined) body.priority = opts.priority;\n\n const { issue } = await client.post<SingleResponse>(`/api/orgs/${org.id}/issues`, body);\n const projects = await fetchProjectMap(client, org.id);\n const enriched = attachIssueUrl(issue, client.baseUrl, org.slug, projects);\n\n output(\n { issue: enriched },\n success(`Created ${formatIdentifier(enriched, projects)}: ${enriched.title}${enriched.url ? `\\n${enriched.url}` : ''}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- update ----\nissueCommand\n .command('update <identifier>')\n .description('Update an issue')\n .option('--title <t>', 'New title')\n .option('--status <s>', `New status (${VALID_STATUSES.join(', ')})`)\n .option('--priority <p>', 'New priority (0-3)', parseInt)\n .action(async (identifier: string, opts: { title?: string; status?: string; priority?: number }) => {\n try {\n if (opts.status && !VALID_STATUSES.includes(opts.status as typeof VALID_STATUSES[number])) {\n outputError(`Invalid status \"${opts.status}\". Must be one of: ${VALID_STATUSES.join(', ')}`);\n process.exit(2);\n }\n if (opts.priority !== undefined && ![0, 1, 2, 3].includes(opts.priority)) {\n outputError('Priority must be 0-3.');\n process.exit(2);\n }\n\n const body: Record<string, unknown> = {};\n if (opts.title !== undefined) body.title = opts.title;\n if (opts.status) body.status = opts.status;\n if (opts.priority !== undefined) body.priority = opts.priority;\n\n if (Object.keys(body).length === 0) {\n outputError('No fields to update. Provide --title, --status, or --priority.');\n process.exit(2);\n }\n\n const client = new AtollClient();\n const org = await resolveOrg(client);\n const issueId = await resolveIssueId(client, org.id, identifier);\n\n const { issue } = await client.patch<SingleResponse>(`/api/orgs/${org.id}/issues/${issueId}`, body);\n const projects = await fetchProjectMap(client, org.id);\n const enriched = attachIssueUrl(issue, client.baseUrl, org.slug, projects);\n\n output(\n { issue: enriched },\n success(`Updated ${formatIdentifier(enriched, projects)}: ${enriched.title}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- delete ----\nissueCommand\n .command('delete <identifier>')\n .description('Delete an issue (admin/owner only)')\n .action(async (identifier: string) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, identifier);\n\n await client.delete(`/api/orgs/${orgId}/issues/${issueId}`);\n\n output(\n { success: true, id: issueId },\n success(`Deleted issue ${identifier}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- assign ----\nissueCommand\n .command('assign <identifier>')\n .description('Assign an issue to a user or agent')\n .requiredOption('--to <user>', 'User/agent ID or \"self\" for yourself')\n .action(async (identifier: string, opts: { to: string }) => {\n try {\n const client = new AtollClient();\n const org = await resolveOrg(client);\n const issueId = await resolveIssueId(client, org.id, identifier);\n\n let assigneeId = opts.to;\n if (assigneeId === 'self') {\n const me = await client.get<{ auth?: { userId?: string } }>('/api/auth/me');\n // For agent keys, auth.userId IS the org_members.id directly\n const callerUserId = me.auth?.userId;\n if (!callerUserId) {\n outputError('Could not resolve your user ID.');\n process.exit(1);\n }\n // Agent callers: userId is the member id — use directly\n // Human callers: userId is the supabase auth id — look up member id\n const { members } = await client.get<{ members: { id: string; user_id: string }[] }>(\n `/api/orgs/${org.id}/members`,\n );\n const member = members.find((m) => m.id === callerUserId || m.user_id === callerUserId);\n if (!member) {\n outputError('You are not a member of this organisation.');\n process.exit(1);\n }\n assigneeId = member.id;\n }\n\n const { issue } = await client.patch<SingleResponse>(\n `/api/orgs/${org.id}/issues/${issueId}`,\n { assignee_id: assigneeId },\n );\n const projects = await fetchProjectMap(client, org.id);\n const enriched = attachIssueUrl(issue, client.baseUrl, org.slug, projects);\n\n output(\n { issue: enriched },\n success(`Assigned ${formatIdentifier(enriched, projects)} to ${opts.to}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- unassign ----\nissueCommand\n .command('unassign <identifier>')\n .description('Remove assignee from an issue')\n .action(async (identifier: string) => {\n try {\n const client = new AtollClient();\n const org = await resolveOrg(client);\n const issueId = await resolveIssueId(client, org.id, identifier);\n\n const { issue } = await client.patch<SingleResponse>(\n `/api/orgs/${org.id}/issues/${issueId}`,\n { assignee_id: null },\n );\n const projects = await fetchProjectMap(client, org.id);\n const enriched = attachIssueUrl(issue, client.baseUrl, org.slug, projects);\n\n output(\n { issue: enriched },\n success(`Unassigned ${formatIdentifier(enriched, projects)}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n","/**\n * TTY-aware ANSI color helpers.\n * Colors are only emitted when stdout is a TTY and OUTPUT_FORMAT !== 'json'.\n */\n\nfunction isTTY(): boolean {\n return process.stdout.isTTY === true && process.env.OUTPUT_FORMAT !== 'json';\n}\n\nfunction ansi(code: string, text: string): string {\n if (!isTTY()) return text;\n return `\\x1b[${code}m${text}\\x1b[0m`;\n}\n\n// Basic colors\nexport const bold = (t: string) => ansi('1', t);\nexport const dim = (t: string) => ansi('2', t);\nexport const red = (t: string) => ansi('31', t);\nexport const green = (t: string) => ansi('32', t);\nexport const yellow = (t: string) => ansi('33', t);\nexport const blue = (t: string) => ansi('34', t);\nexport const cyan = (t: string) => ansi('36', t);\nexport const gray = (t: string) => ansi('90', t);\nexport const white = (t: string) => ansi('37', t);\n\n// Status badge colors\nexport function statusColor(status: string, text: string): string {\n switch (status) {\n case 'done': return green(text);\n case 'in_progress': return yellow(text);\n case 'backlog':\n case 'todo': return gray(text);\n case 'cancelled': return red(text);\n default: return text;\n }\n}\n\n// Priority icons\nexport function priorityIcon(priority: number): string {\n switch (priority) {\n case 0: return red('⚠⚠⚠'); // urgent\n case 1: return yellow('▄▆█'); // high\n case 2: return cyan('▄▆'); // medium\n case 3: return dim('---'); // low\n default: return String(priority);\n }\n}\n\n// Helpers\nexport const success = (msg: string) => green(`✓ ${msg}`);\nexport const error = (msg: string) => red(`Error: ${msg}`);\n\n// Raw ANSI codes (for use in format strings where needed)\nexport const RESET = isTTY() ? '\\x1b[0m' : '';\nexport const BOLD = isTTY() ? '\\x1b[1m' : '';\nexport const DIM = isTTY() ? '\\x1b[2m' : '';\n","// URL builders for Atoll canonical web routes.\n// Mirrors the routing and identifier conventions in agent-pm.\n\n/**\n * Derive a short uppercase prefix from a project name.\n * Mirrors agent-pm/lib/issue-identifier.ts — keep in sync.\n */\nexport function derivePrefix(name: string): string {\n const cleaned = name.replace(/[^a-zA-Z0-9\\s]/g, ' ').trim();\n const words = cleaned.split(/\\s+/).filter(Boolean);\n\n if (words.length === 0) return 'TSK';\n\n if (words.length >= 2) {\n return words\n .slice(0, 5)\n .map((w) => w[0])\n .join('')\n .toUpperCase();\n }\n\n const word = words[0];\n if (word.length <= 4) return word.toUpperCase();\n return word.slice(0, 3).toUpperCase();\n}\n\nexport function issueIdentifier(\n projectName: string | null | undefined,\n issueNumber: number | null | undefined,\n): string | null {\n if (issueNumber == null) return null;\n const prefix = projectName ? derivePrefix(projectName) : 'TSK';\n return `${prefix}-${issueNumber}`;\n}\n\nfunction stripTrailingSlash(baseUrl: string): string {\n return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;\n}\n\nexport function buildIssueUrl(\n baseUrl: string,\n orgSlug: string,\n projectSlug: string | null | undefined,\n issueNumber: number | null | undefined,\n): string | null {\n // Use the project-scoped route (/{org}/projects/{projectSlug}/issues/{number})\n // rather than the prefix-based identifier route. The prefix route is\n // ambiguous (two projects can derive the same prefix, and numeric-containing\n // prefixes like \"Q2\" fail the web app's [A-Z]{2,} regex).\n if (!orgSlug || !projectSlug || issueNumber == null) return null;\n return `${stripTrailingSlash(baseUrl)}/${orgSlug}/projects/${projectSlug}/issues/${issueNumber}`;\n}\n\nexport function buildProjectUrl(\n baseUrl: string,\n orgSlug: string,\n projectSlug: string | null | undefined,\n): string | null {\n if (!orgSlug || !projectSlug) return null;\n return `${stripTrailingSlash(baseUrl)}/${orgSlug}/projects/${projectSlug}`;\n}\n\nexport function buildInitiativeUrl(\n baseUrl: string,\n orgSlug: string,\n initiativeId: string | null | undefined,\n): string | null {\n if (!orgSlug || !initiativeId) return null;\n return `${stripTrailingSlash(baseUrl)}/${orgSlug}/initiatives/${initiativeId}`;\n}\n","import { Command } from 'commander';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\nimport { handleApiError, resolveOrgId, resolveIssueId } from './issue.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface CommentAuthor {\n id: string;\n display_name: string;\n type: string;\n avatar_url?: string;\n}\n\ninterface Comment {\n id: string;\n body: string;\n author_id: string;\n author_type?: string;\n author?: CommentAuthor;\n created_at?: string;\n updated_at?: string;\n}\n\ninterface ListCommentsResponse {\n comments: Comment[];\n}\n\ninterface SingleCommentResponse {\n comment: Comment;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst BOLD = '\\x1b[1m';\nconst DIM = '\\x1b[2m';\nconst RESET = '\\x1b[0m';\nconst CYAN = '\\x1b[36m';\n\nfunction formatAuthor(comment: Comment): string {\n const name = comment.author?.display_name ?? comment.author_id;\n const badge = (comment.author?.type ?? comment.author_type) === 'agent' ? ' [agent]' : '';\n return `${name}${badge}`;\n}\n\nfunction formatTimestamp(ts?: string): string {\n if (!ts) return '';\n const d = new Date(ts);\n return d.toLocaleString();\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport const commentCommand = new Command('comment')\n .description('Manage issue comments');\n\n// ---- list ----\ncommentCommand\n .command('list <identifier>')\n .description('List comments on an issue (UUID or PREFIX-NUMBER e.g. ATOLL-42)')\n .action(async (identifier: string) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, identifier);\n\n const data = await client.get<ListCommentsResponse>(\n `/api/orgs/${orgId}/issues/${issueId}/comments`,\n );\n\n // JSON mode: NDJSON\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n for (const comment of data.comments) {\n process.stdout.write(JSON.stringify(comment) + '\\n');\n }\n return;\n }\n\n // TTY: human-readable\n if (data.comments.length === 0) {\n console.log('No comments found.');\n return;\n }\n\n for (const comment of data.comments) {\n const author = formatAuthor(comment);\n const time = formatTimestamp(comment.created_at);\n console.log(`${BOLD}${CYAN}${author}${RESET} ${DIM}${time}${RESET}`);\n console.log(comment.body);\n console.log();\n }\n console.log(`${DIM}${data.comments.length} comment(s)${RESET}`);\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- add ----\ncommentCommand\n .command('add <identifier>')\n .description('Add a comment to an issue')\n .requiredOption('--body <text>', 'Comment body')\n .action(async (identifier: string, opts: { body: string }) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, identifier);\n\n const { comment } = await client.post<SingleCommentResponse>(\n `/api/orgs/${orgId}/issues/${issueId}/comments`,\n { body: opts.body },\n );\n\n output(\n { comment },\n `✓ Comment added to ${identifier}`,\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- update ----\ncommentCommand\n .command('update <comment-id>')\n .description('Update a comment')\n .requiredOption('--body <text>', 'New comment body')\n .requiredOption('--issue <identifier>', 'Issue identifier (e.g. UUID or PREFIX-NUMBER)')\n .action(async (commentId: string, opts: { body: string; issue: string }) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, opts.issue);\n\n const { comment } = await client.patch<SingleCommentResponse>(\n `/api/orgs/${orgId}/issues/${issueId}/comments/${commentId}`,\n { body: opts.body },\n );\n\n output(\n { comment },\n `✓ Comment ${commentId} updated`,\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- delete ----\ncommentCommand\n .command('delete <comment-id>')\n .description('Delete a comment')\n .requiredOption('--issue <identifier>', 'Issue identifier (e.g. UUID or PREFIX-NUMBER)')\n .action(async (commentId: string, opts: { issue: string }) => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n const issueId = await resolveIssueId(client, orgId, opts.issue);\n\n await client.delete(`/api/orgs/${orgId}/issues/${issueId}/comments/${commentId}`);\n\n output(\n { success: true, id: commentId },\n `✓ Comment ${commentId} deleted`,\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n","import { Command } from 'commander';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\nimport { resolveOrg, handleApiError } from './issue.js';\nimport { bold, dim, cyan, green, success } from '../lib/colors.js';\nimport { buildProjectUrl } from '../lib/urls.js';\n\ninterface Project {\n id: string;\n name: string;\n slug?: string | null;\n description?: string | null;\n status: 'active' | 'archived';\n color: string;\n icon: string;\n issueCount?: number;\n completedCount?: number;\n progress?: number;\n created_at?: string;\n}\n\nfunction attachProjectUrl<T extends Project>(project: T, baseUrl: string, orgSlug: string): T & { url: string | null } {\n return { ...project, url: buildProjectUrl(baseUrl, orgSlug, project.slug) };\n}\n\ninterface Issue {\n id: string;\n title: string;\n status: string;\n priority: number;\n number?: number | null;\n}\n\nfunction progressBar(progress: number, width = 20): string {\n const filled = Math.round((progress / 100) * width);\n const empty = width - filled;\n return `[${'█'.repeat(filled)}${'░'.repeat(empty)}] ${progress}%`;\n}\n\nexport const projectCommand = new Command('project')\n .description('Manage projects')\n .addHelpText('after', `\nExamples:\n $ atoll project list\n $ atoll project create --name \"My Project\" --icon 🚀\n $ atoll project view <project-id>`);\n\n// ── atoll project list ──────────────────────────────────────────────────────\n\nprojectCommand\n .command('list')\n .description('List all projects with progress')\n .action(async () => {\n const client = new AtollClient();\n try {\n const org = await resolveOrg(client);\n const data = await client.get<{ projects: Project[] }>(`/api/orgs/${org.id}/projects`);\n const projects = (data.projects ?? []).map((p) => attachProjectUrl(p, client.baseUrl, org.slug));\n\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n for (const p of projects) {\n process.stdout.write(JSON.stringify(p) + '\\n');\n }\n return;\n }\n\n if (projects.length === 0) {\n console.log(dim('No projects found.'));\n return;\n }\n\n for (const p of projects) {\n const progress = p.progress ?? 0;\n const bar = progressBar(progress);\n console.log(`${bold(`${p.icon} ${p.name}`)} ${dim(`(${p.id})`)}`);\n if (p.description) console.log(` ${dim(p.description)}`);\n console.log(` ${cyan(bar)} ${p.issueCount ?? 0} issues, ${p.completedCount ?? 0} done`);\n if (p.url) console.log(` ${dim(p.url)}`);\n if (p.status === 'archived') console.log(` ${dim('[archived]')}`);\n console.log('');\n }\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ── atoll project create ────────────────────────────────────────────────────\n\nprojectCommand\n .command('create')\n .description('Create a new project')\n .requiredOption('--name <name>', 'Project name')\n .option('--description <desc>', 'Project description')\n .option('--color <color>', 'Project color (hex)', '#6366f1')\n .option('--icon <icon>', 'Project icon (emoji)', '📁')\n .action(async (opts) => {\n const client = new AtollClient();\n try {\n const org = await resolveOrg(client);\n const data = await client.post<{ project: Project }>(`/api/orgs/${org.id}/projects`, {\n name: opts.name,\n description: opts.description ?? null,\n color: opts.color,\n icon: opts.icon,\n });\n const project = attachProjectUrl(data.project, client.baseUrl, org.slug);\n\n output(\n { project },\n success(`Created project ${project.icon} ${project.name} (${dim(project.id)})${project.url ? `\\n${project.url}` : ''}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ── atoll project view ──────────────────────────────────────────────────────\n\nprojectCommand\n .command('view <projectId>')\n .description('View project details and issues')\n .action(async (projectId) => {\n const client = new AtollClient();\n try {\n const org = await resolveOrg(client);\n const data = await client.get<{ project: Project & { issues: Issue[] } }>(\n `/api/orgs/${org.id}/projects/${projectId}`,\n );\n const p = attachProjectUrl(data.project, client.baseUrl, org.slug);\n\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n process.stdout.write(JSON.stringify(p) + '\\n');\n return;\n }\n\n const progress = p.progress ?? 0;\n console.log(bold(`${p.icon} ${p.name}`));\n if (p.description) console.log(` ${p.description}`);\n if (p.url) console.log(` ${dim(p.url)}`);\n console.log(` ${cyan(progressBar(progress))}`);\n console.log(` ${(p.issueCount ?? 0)} issues · ${(p.completedCount ?? 0)} completed`);\n console.log('');\n\n const issues: Issue[] = (p as unknown as { issues?: Issue[] }).issues ?? [];\n if (issues.length === 0) {\n console.log(dim('No issues in this project.'));\n return;\n }\n\n console.log(bold('Issues'));\n for (const issue of issues) {\n const num = issue.number ? `#${issue.number}` : issue.id.slice(0, 8);\n console.log(` ${dim(num)} ${issue.title} ${dim(`[${issue.status}]`)}`);\n }\n } catch (err) {\n handleApiError(err);\n }\n });\n","import { Command } from 'commander';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\nimport { resolveOrgId, handleApiError } from './issue.js';\nimport { bold, dim, cyan, red, success } from '../lib/colors.js';\n\ninterface Milestone {\n id: string;\n name: string;\n description?: string | null;\n due_date?: string | null;\n status: 'active' | 'closed';\n issueCount?: number;\n completedCount?: number;\n progress?: number;\n isOverdue?: boolean;\n}\n\nfunction progressBar(progress: number, width = 20): string {\n const filled = Math.round((progress / 100) * width);\n const empty = width - filled;\n return `[${'█'.repeat(filled)}${'░'.repeat(empty)}] ${progress}%`;\n}\n\nexport const milestoneCommand = new Command('milestone')\n .description('Manage milestones')\n .addHelpText('after', `\nExamples:\n $ atoll milestone list --project <project-id>\n $ atoll milestone create --project <project-id> --name \"v1.0\" --date 2026-06-01`);\n\n// ── atoll milestone list ────────────────────────────────────────────────────\n\nmilestoneCommand\n .command('list')\n .description('List milestones for a project')\n .requiredOption('--project <id>', 'Project ID')\n .action(async (opts) => {\n const client = new AtollClient();\n try {\n const orgId = await resolveOrgId(client);\n const data = await client.get<{ milestones: Milestone[] }>(\n `/api/orgs/${orgId}/projects/${opts.project}/milestones`,\n );\n const milestones = data.milestones ?? [];\n\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n for (const m of milestones) {\n process.stdout.write(JSON.stringify(m) + '\\n');\n }\n return;\n }\n\n if (milestones.length === 0) {\n console.log(dim('No milestones found.'));\n return;\n }\n\n for (const m of milestones) {\n const progress = m.progress ?? 0;\n const bar = progressBar(progress);\n const overdue = m.isOverdue ? ` ${red('[OVERDUE]')}` : '';\n console.log(`${bold(m.name)} ${dim(`(${m.id})`)}${overdue}`);\n if (m.due_date) console.log(` Due: ${m.due_date}`);\n if (m.description) console.log(` ${dim(m.description)}`);\n console.log(` ${cyan(bar)} ${m.issueCount ?? 0} issues, ${m.completedCount ?? 0} done`);\n if (m.status === 'closed') console.log(` ${dim('[closed]')}`);\n console.log('');\n }\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ── atoll milestone create ──────────────────────────────────────────────────\n\nmilestoneCommand\n .command('create')\n .description('Create a new milestone')\n .requiredOption('--project <id>', 'Project ID')\n .requiredOption('--name <name>', 'Milestone name')\n .option('--date <YYYY-MM-DD>', 'Due date')\n .option('--description <desc>', 'Description')\n .action(async (opts) => {\n const client = new AtollClient();\n try {\n const orgId = await resolveOrgId(client);\n const data = await client.post<{ milestone: Milestone }>(\n `/api/orgs/${orgId}/projects/${opts.project}/milestones`,\n {\n name: opts.name,\n description: opts.description ?? null,\n dueDate: opts.date ?? null,\n },\n );\n\n output(\n { milestone: data.milestone },\n success(`Milestone created: ${bold(data.milestone.name)} ${dim(`(${data.milestone.id})`)}`),\n );\n if (data.milestone.due_date) {\n console.log(` Due: ${data.milestone.due_date}`);\n }\n } catch (err) {\n handleApiError(err);\n }\n });\n","import { Command } from 'commander';\nimport { readConfig, writeConfig } from '../lib/config.js';\nimport { output, outputError } from '../lib/output.js';\nimport { success, bold, dim, gray } from '../lib/colors.js';\nimport { getApiKey } from '../lib/config.js';\n\nexport const configCommand = new Command('config')\n .description('Manage CLI configuration (org, team, API key)')\n .addHelpText('after', `\nExamples:\n $ atoll config show\n $ atoll config set-org my-org\n $ atoll config set-team team-abc123`);\n\n// ── atoll config show ───────────────────────────────────────────────────────\n\nconfigCommand\n .command('show')\n .description('Display current configuration')\n .action(() => {\n const cfg = readConfig();\n const apiKeySet = !!(process.env.ATOLL_API_KEY || cfg.apiKey);\n\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n output(\n {\n orgSlug: cfg.orgSlug ?? null,\n defaultTeam: cfg.defaultTeam ?? null,\n apiKeySet,\n },\n '',\n );\n return;\n }\n\n console.log(`${bold('Atoll CLI Configuration')}`);\n console.log(` ${dim('Org slug:')} ${cfg.orgSlug ? bold(cfg.orgSlug) : gray('(not set)')}`);\n console.log(` ${dim('Default team:')} ${cfg.defaultTeam ? bold(cfg.defaultTeam) : gray('(not set)')}`);\n console.log(` ${dim('API key:')} ${apiKeySet ? bold('set') : gray('not set — run `atoll auth login`')}`);\n });\n\n// ── atoll config set-org ────────────────────────────────────────────────────\n\nconfigCommand\n .command('set-org <slug>')\n .description('Set the default organisation slug')\n .action((slug: string) => {\n const cfg = readConfig();\n cfg.orgSlug = slug;\n writeConfig(cfg);\n\n output(\n { orgSlug: slug },\n success(`Default org set to \"${slug}\"`),\n );\n });\n\n// ── atoll config set-team ───────────────────────────────────────────────────\n\nconfigCommand\n .command('set-team <team>')\n .description('Set the default team slug or ID')\n .action((team: string) => {\n const cfg = readConfig();\n cfg.defaultTeam = team;\n writeConfig(cfg);\n\n output(\n { defaultTeam: team },\n success(`Default team set to \"${team}\"`),\n );\n });\n","import { Command } from 'commander';\nimport { AtollClient } from '../lib/client.js';\nimport { output, outputError } from '../lib/output.js';\nimport { bold, dim, green, gray, success } from '../lib/colors.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface Webhook {\n id: string;\n url: string;\n events: string[];\n enabled: boolean;\n created_at: string;\n}\n\ninterface WebhookListResponse {\n webhooks: Webhook[];\n}\n\ninterface WebhookCreateResponse {\n webhook: Webhook;\n secret: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction handleApiError(err: unknown): never {\n const msg = (err as Error).message ?? String(err);\n if (/API 401\\b/.test(msg)) {\n outputError('Session expired — run `atoll auth login` to re-authenticate.');\n } else if (/API 403\\b/.test(msg)) {\n outputError('Permission denied. You do not have access to this resource.');\n } else {\n outputError(msg);\n }\n process.exit(1);\n}\n\nasync function resolveOrgId(client: AtollClient, orgSlugOverride?: string): Promise<string> {\n const { orgs } = await client.get<{ orgs: { id: string; slug: string }[] }>('/api/orgs');\n if (!orgs || orgs.length === 0) {\n outputError('No organizations found.');\n process.exit(1);\n }\n if (orgs.length === 1) return orgs[0].id;\n\n const { readConfig } = await import('../lib/config.js');\n const config = readConfig();\n const slug = orgSlugOverride ?? process.env.ATOLL_ORG ?? config.orgSlug;\n\n if (slug) {\n const match = orgs.find((o) => o.slug === slug);\n if (match) return match.id;\n outputError(`Org \"${slug}\" not found. Available: ${orgs.map((o) => o.slug).join(', ')}`);\n process.exit(1);\n }\n outputError(`Multiple orgs found. Use --org <slug>.`);\n process.exit(1);\n}\n\nfunction padEnd(str: string, len: number): string {\n return str.length >= len ? str.slice(0, len) : str + ' '.repeat(len - str.length);\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport const webhookCommand = new Command('webhook')\n .description('Manage outbound webhooks')\n .addHelpText('after', `\nExamples:\n $ atoll webhook list\n $ atoll webhook create --url https://example.com/hook --events issue.created,issue.updated\n $ atoll webhook delete <id>`);\n\n// ---- list ----\nwebhookCommand\n .command('list')\n .description('List webhooks for the current org')\n .action(async () => {\n try {\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n\n const data = await client.get<WebhookListResponse>(`/api/webhooks?orgId=${orgId}`);\n\n if (!process.stdout.isTTY || process.env.OUTPUT_FORMAT === 'json') {\n for (const wh of data.webhooks) {\n process.stdout.write(JSON.stringify(wh) + '\\n');\n }\n return;\n }\n\n if (data.webhooks.length === 0) {\n console.log('No webhooks configured.');\n return;\n }\n\n const header = bold(`${padEnd('ID', 38)} ${padEnd('URL', 40)} ${padEnd('EVENTS', 20)} ACTIVE`);\n console.log(header);\n console.log('─'.repeat(100));\n for (const wh of data.webhooks) {\n const evts = wh.events.length === 0 ? 'all' : wh.events.join(',');\n const active = wh.enabled ? green('yes') : gray('no');\n const url = wh.url.length > 38 ? wh.url.slice(0, 35) + '…' : wh.url;\n const evtStr = evts.length > 18 ? evts.slice(0, 15) + '…' : evts;\n console.log(`${padEnd(wh.id.slice(0, 36), 38)} ${padEnd(url, 40)} ${padEnd(evtStr, 20)} ${active}`);\n }\n console.log(dim(`${data.webhooks.length} webhook(s)`));\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- create ----\nwebhookCommand\n .command('create')\n .description('Create a new webhook')\n .requiredOption('--url <url>', 'Payload URL (HTTPS)')\n .option('--events <events>', 'Comma-separated event types (default: all)', '')\n .action(async (opts: { url: string; events: string }) => {\n try {\n if (!opts.url.startsWith('https://')) {\n outputError('URL must use HTTPS.');\n process.exit(2);\n }\n\n const events = opts.events\n ? opts.events.split(',').map((e) => e.trim()).filter(Boolean)\n : [];\n\n const client = new AtollClient();\n const orgId = await resolveOrgId(client);\n\n const data = await client.post<WebhookCreateResponse>(\n `/api/webhooks?orgId=${orgId}`,\n { url: opts.url, events },\n );\n\n output(\n { webhook: data.webhook, secret: data.secret },\n [\n success(`Created webhook ${data.webhook.id}`),\n '',\n bold('Signing secret (save this — shown only once):'),\n ` ${data.secret}`,\n ].join('\\n'),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n\n// ---- delete ----\nwebhookCommand\n .command('delete <id>')\n .description('Delete a webhook')\n .action(async (id: string) => {\n try {\n const client = new AtollClient();\n await client.delete(`/api/webhooks/${id}`);\n\n output(\n { success: true, id },\n success(`Deleted webhook ${id}`),\n );\n } catch (err) {\n handleApiError(err);\n }\n });\n"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8DT;AAEA,SAAS,gBAAwB;AAC/B,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0ET;","names":["import_commander","import_commander","readConfig","import_commander","BOLD","DIM","RESET","import_commander","import_commander","progressBar","import_commander","import_commander","handleApiError","resolveOrgId","readConfig","padEnd"]}
|