@islamihab/kds 0.2.1 → 0.2.2

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.
Files changed (2) hide show
  1. package/index.js +185 -93
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -14594,7 +14594,7 @@ import { join } from "path";
14594
14594
  // package.json
14595
14595
  var package_default = {
14596
14596
  name: "cli",
14597
- version: "0.2.1",
14597
+ version: "0.2.2",
14598
14598
  private: true,
14599
14599
  type: "module",
14600
14600
  bin: {
@@ -17823,59 +17823,117 @@ var auth = group({
17823
17823
  commands: [login, logout, status]
17824
17824
  });
17825
17825
 
17826
- // src/lib/attachments.ts
17827
- import { basename } from "path";
17828
- var attachFiles = async (client3, issueId, paths) => {
17829
- if (paths.length === 0)
17830
- return [];
17831
- const files = paths.map((path) => ({ path, file: Bun.file(path) }));
17832
- for (const { path, file: file2 } of files) {
17833
- if (!await file2.exists())
17834
- throw new Error(`No file at ${path}.`);
17835
- if (file2.size <= 0)
17836
- throw new Error(`${path} is empty; an attachment cannot be.`);
17837
- if (file2.size > MAX_ISSUE_ATTACHMENT_BYTES) {
17838
- throw new Error(`${path} is too large (${file2.size} bytes; max ${MAX_ISSUE_ATTACHMENT_BYTES}).`);
17839
- }
17826
+ // src/lib/activity.ts
17827
+ var SOURCE_LABELS = { github: "GitHub" };
17828
+ var issueActivityLine = (detail) => {
17829
+ const label = detail.kind.replaceAll("_", " ");
17830
+ switch (detail.kind) {
17831
+ case "created":
17832
+ case "description_changed":
17833
+ return label;
17834
+ case "title_changed":
17835
+ case "status_changed":
17836
+ case "priority_changed":
17837
+ case "disposition_changed":
17838
+ case "estimate_changed":
17839
+ case "due_date_changed":
17840
+ case "branch_changed":
17841
+ case "pr_changed":
17842
+ case "project_changed":
17843
+ case "milestone_changed":
17844
+ case "parent_changed":
17845
+ return `${label}: ${detail.from ?? "none"} \u2192 ${detail.to ?? "none"}`;
17846
+ case "label_added":
17847
+ case "label_removed":
17848
+ case "attachment_added":
17849
+ case "attachment_removed":
17850
+ return `${label}: ${detail.name}`;
17851
+ case "child_added":
17852
+ case "child_removed":
17853
+ return `${label}: ${detail.identifier}`;
17854
+ case "relation_added":
17855
+ case "relation_removed":
17856
+ return `${label}: ${detail.relation.replaceAll("_", " ")} ${detail.identifier}`;
17840
17857
  }
17841
- const created = new Set;
17842
- try {
17843
- for (const { path, file: file2 } of files) {
17844
- const uploadUrl = await client3.mutation(api2.issueAttachments.generateUploadUrl, { issueId });
17845
- const response = await fetch(uploadUrl, {
17846
- method: "POST",
17847
- headers: { "Content-Type": file2.type },
17848
- body: file2
17849
- });
17850
- if (!response.ok)
17851
- throw new Error(`Uploading ${path} failed (${response.status}).`);
17852
- const storageId = exports_external.custom((value) => typeof value === "string");
17853
- const body = exports_external.object({ storageId }).safeParse(await response.json());
17854
- if (!body.success)
17855
- throw new Error("The upload returned no file reference.");
17856
- created.add(await client3.action(api2.issueAttachments.create, {
17857
- issueId,
17858
- storageId: body.data.storageId,
17859
- name: basename(path)
17860
- }));
17861
- }
17862
- } catch (error51) {
17863
- for (const id of created) {
17864
- await client3.mutation(api2.issueAttachments.remove, { id }).catch(() => {
17865
- console.error("An attachment from this failed batch could not be removed; check the dashboard.");
17866
- });
17867
- }
17868
- throw error51;
17858
+ };
17859
+ var projectActivityLine = (detail) => {
17860
+ const label = detail.kind.replaceAll("_", " ");
17861
+ switch (detail.kind) {
17862
+ case "created":
17863
+ case "summary_changed":
17864
+ case "description_changed":
17865
+ case "milestones_reordered":
17866
+ return label;
17867
+ case "name_changed":
17868
+ case "status_changed":
17869
+ case "health_changed":
17870
+ case "target_date_changed":
17871
+ case "repo_changed":
17872
+ case "milestone_renamed":
17873
+ return `${label}: ${detail.from ?? "none"} \u2192 ${detail.to ?? "none"}`;
17874
+ case "milestone_added":
17875
+ case "milestone_removed":
17876
+ case "milestone_description_changed":
17877
+ return `${label}: ${detail.name}`;
17878
+ case "milestone_target_date_changed":
17879
+ return `${label}: ${detail.name} ${detail.from ?? "none"} \u2192 ${detail.to ?? "none"}`;
17880
+ case "issue_added":
17881
+ case "issue_removed":
17882
+ return `${label}: ${detail.identifier}`;
17869
17883
  }
17870
- const attachments = await client3.query(api2.issueAttachments.list, { issueId });
17871
- return attachments.filter((attachment) => created.has(attachment._id));
17872
17884
  };
17873
- var printAttachments = (attachments) => {
17874
- for (const attachment of attachments) {
17875
- console.log(`Attached ${attachment.name}${attachment.url ? ` \u2014 ${attachment.url}` : ""}`);
17885
+
17886
+ // src/lib/output.ts
17887
+ var printTable = (rows) => {
17888
+ if (rows.length === 0)
17889
+ return;
17890
+ const columnCount = Math.max(...rows.map((row) => row.length));
17891
+ const widths = Array.from({ length: columnCount }, (_, column) => Math.max(...rows.map((row) => (row[column] ?? "").length)));
17892
+ for (const row of rows) {
17893
+ console.log(row.map((cell, column) => cell.padEnd(widths[column] ?? 0)).join(" ").trimEnd());
17876
17894
  }
17877
17895
  };
17878
17896
 
17897
+ // src/commands/inbox/list.ts
17898
+ var inboxOptions = {
17899
+ all: exports_external.boolean().default(false).describe("Include events already marked seen"),
17900
+ json: exports_external.boolean().default(false).describe("Print as JSON")
17901
+ };
17902
+ var runInbox = async (options) => {
17903
+ const client3 = await backendClient();
17904
+ const inbox = await client3.query(api2.inbox.list, {});
17905
+ const targetLastSeen = new Map(inbox.targetLastSeen.map((state) => [state.targetId, state.lastSeenAt]));
17906
+ const events = options.all ? inbox.events : inbox.events.filter((event) => {
17907
+ const targetId = event.type === "issue" ? event.issue.id : event.project.id;
17908
+ return event.at > Math.max(inbox.lastSeenAt, targetLastSeen.get(targetId) ?? 0);
17909
+ });
17910
+ if (options.json)
17911
+ return console.log(JSON.stringify({ ...inbox, events }, null, 2));
17912
+ if (events.length === 0) {
17913
+ if (options.all)
17914
+ console.log("Nothing in the inbox.");
17915
+ else
17916
+ console.log(inbox.truncated ? "Nothing unseen in the newest events shown." : "Inbox zero.");
17917
+ if (!options.all && inbox.events.length > 0)
17918
+ console.log("Pass --all to reprint seen events.");
17919
+ return;
17920
+ }
17921
+ printTable([
17922
+ ["WHEN", "ACTOR", "WHERE", "EVENT"],
17923
+ ...events.map((event) => [
17924
+ new Date(event.at).toISOString().slice(0, 16).replace("T", " "),
17925
+ SOURCE_LABELS[event.via],
17926
+ event.type === "issue" ? event.issue.identifier : event.project.name,
17927
+ event.type === "issue" ? issueActivityLine(event.detail) : projectActivityLine(event.detail)
17928
+ ])
17929
+ ]);
17930
+ if (inbox.truncated)
17931
+ console.log(`
17932
+ (older events truncated)`);
17933
+ if (!options.all)
17934
+ console.log("\nRun `kds inbox seen` once these are handled.");
17935
+ };
17936
+
17879
17937
  // src/lib/input.ts
17880
17938
  var assertSize = (size) => {
17881
17939
  if (size > MAX_PAGE_HTML_BYTES)
@@ -18011,6 +18069,83 @@ var resolveMilestone = async (client3, projectId, name) => {
18011
18069
  return milestone;
18012
18070
  };
18013
18071
 
18072
+ // src/commands/inbox/seen.ts
18073
+ var seen = command({
18074
+ name: "seen",
18075
+ description: "Mark one issue, or the whole inbox, as seen",
18076
+ positionals: {
18077
+ id: exports_external.string().optional().describe("Issue identifier, number, or URL")
18078
+ },
18079
+ run: async ({ positionals: { id } }) => {
18080
+ const client3 = await backendClient();
18081
+ const issue2 = id === undefined ? undefined : await resolveIssue(client3, id);
18082
+ await client3.mutation(api2.inbox.markSeen, { targetId: issue2?._id });
18083
+ console.log(issue2 ? `${issue2.identifier} marked seen.` : "Inbox marked seen.");
18084
+ }
18085
+ });
18086
+
18087
+ // src/commands/inbox/index.ts
18088
+ var inbox = group({
18089
+ name: "inbox",
18090
+ description: "Automated activity across issues and projects, unseen first",
18091
+ options: inboxOptions,
18092
+ run: async ({ options }) => await runInbox(options),
18093
+ commands: [seen]
18094
+ });
18095
+
18096
+ // src/lib/attachments.ts
18097
+ import { basename } from "path";
18098
+ var attachFiles = async (client3, issueId, paths) => {
18099
+ if (paths.length === 0)
18100
+ return [];
18101
+ const files = paths.map((path) => ({ path, file: Bun.file(path) }));
18102
+ for (const { path, file: file2 } of files) {
18103
+ if (!await file2.exists())
18104
+ throw new Error(`No file at ${path}.`);
18105
+ if (file2.size <= 0)
18106
+ throw new Error(`${path} is empty; an attachment cannot be.`);
18107
+ if (file2.size > MAX_ISSUE_ATTACHMENT_BYTES) {
18108
+ throw new Error(`${path} is too large (${file2.size} bytes; max ${MAX_ISSUE_ATTACHMENT_BYTES}).`);
18109
+ }
18110
+ }
18111
+ const created = new Set;
18112
+ try {
18113
+ for (const { path, file: file2 } of files) {
18114
+ const uploadUrl = await client3.mutation(api2.issueAttachments.generateUploadUrl, { issueId });
18115
+ const response = await fetch(uploadUrl, {
18116
+ method: "POST",
18117
+ headers: { "Content-Type": file2.type },
18118
+ body: file2
18119
+ });
18120
+ if (!response.ok)
18121
+ throw new Error(`Uploading ${path} failed (${response.status}).`);
18122
+ const storageId = exports_external.custom((value) => typeof value === "string");
18123
+ const body = exports_external.object({ storageId }).safeParse(await response.json());
18124
+ if (!body.success)
18125
+ throw new Error("The upload returned no file reference.");
18126
+ created.add(await client3.action(api2.issueAttachments.create, {
18127
+ issueId,
18128
+ storageId: body.data.storageId,
18129
+ name: basename(path)
18130
+ }));
18131
+ }
18132
+ } catch (error51) {
18133
+ for (const id of created) {
18134
+ await client3.mutation(api2.issueAttachments.remove, { id }).catch(() => {
18135
+ console.error("An attachment from this failed batch could not be removed; check the dashboard.");
18136
+ });
18137
+ }
18138
+ throw error51;
18139
+ }
18140
+ const attachments = await client3.query(api2.issueAttachments.list, { issueId });
18141
+ return attachments.filter((attachment) => created.has(attachment._id));
18142
+ };
18143
+ var printAttachments = (attachments) => {
18144
+ for (const attachment of attachments) {
18145
+ console.log(`Attached ${attachment.name}${attachment.url ? ` \u2014 ${attachment.url}` : ""}`);
18146
+ }
18147
+ };
18148
+
18014
18149
  // src/commands/issues/comment.ts
18015
18150
  var comment = command({
18016
18151
  name: "comment",
@@ -18073,38 +18208,6 @@ var create = command({
18073
18208
  });
18074
18209
 
18075
18210
  // src/commands/issues/get.ts
18076
- var SOURCE_LABELS = { github: "GitHub" };
18077
- var activityLine = (detail) => {
18078
- const label = detail.kind.replaceAll("_", " ");
18079
- switch (detail.kind) {
18080
- case "created":
18081
- case "description_changed":
18082
- return label;
18083
- case "title_changed":
18084
- case "status_changed":
18085
- case "priority_changed":
18086
- case "disposition_changed":
18087
- case "estimate_changed":
18088
- case "due_date_changed":
18089
- case "branch_changed":
18090
- case "pr_changed":
18091
- case "project_changed":
18092
- case "milestone_changed":
18093
- case "parent_changed":
18094
- return `${label}: ${detail.from ?? "none"} \u2192 ${detail.to ?? "none"}`;
18095
- case "label_added":
18096
- case "label_removed":
18097
- case "attachment_added":
18098
- case "attachment_removed":
18099
- return `${label}: ${detail.name}`;
18100
- case "child_added":
18101
- case "child_removed":
18102
- return `${label}: ${detail.identifier}`;
18103
- case "relation_added":
18104
- case "relation_removed":
18105
- return `${label}: ${detail.relation.replaceAll("_", " ")} ${detail.identifier}`;
18106
- }
18107
- };
18108
18211
  var get = command({
18109
18212
  name: "get",
18110
18213
  description: "Show an issue: properties, description, and its feed",
@@ -18173,7 +18276,7 @@ Feed:`);
18173
18276
  const at = new Date(event.at).toISOString().slice(0, 16).replace("T", " ");
18174
18277
  if (event.type === "activity") {
18175
18278
  const via = event.via === undefined ? "" : ` (via ${SOURCE_LABELS[event.via]})`;
18176
- console.log(`${at} ${activityLine(event.detail)}${via}`);
18279
+ console.log(`${at} ${issueActivityLine(event.detail)}${via}`);
18177
18280
  } else {
18178
18281
  console.log(`${at} comment${event.editedAt ? " (edited)" : ""}:`);
18179
18282
  for (const line of event.bodyMarkdown.split(`
@@ -18184,17 +18287,6 @@ Feed:`);
18184
18287
  }
18185
18288
  });
18186
18289
 
18187
- // src/lib/output.ts
18188
- var printTable = (rows) => {
18189
- if (rows.length === 0)
18190
- return;
18191
- const columnCount = Math.max(...rows.map((row) => row.length));
18192
- const widths = Array.from({ length: columnCount }, (_, column) => Math.max(...rows.map((row) => (row[column] ?? "").length)));
18193
- for (const row of rows) {
18194
- console.log(row.map((cell, column) => cell.padEnd(widths[column] ?? 0)).join(" ").trimEnd());
18195
- }
18196
- };
18197
-
18198
18290
  // src/commands/issues/list.ts
18199
18291
  var list = command({
18200
18292
  name: "list",
@@ -18888,7 +18980,7 @@ var upgrade = command({
18888
18980
  var rootCommand = group({
18889
18981
  name: "kds",
18890
18982
  description: "KDS CLI",
18891
- commands: [auth, issues, pages, project, projects, upgrade],
18983
+ commands: [auth, inbox, issues, pages, project, projects, upgrade],
18892
18984
  options: {
18893
18985
  version: exports_external.boolean().default(false).describe("Show the version").meta({ short: "v" })
18894
18986
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@islamihab/kds",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Command-line client for Kai Dev Studio",
5
5
  "license": "MIT",
6
6
  "publishConfig": {