skyboard-cli 0.1.0 → 0.1.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 (138) hide show
  1. package/dist/__tests__/auth-state.test.d.ts +1 -0
  2. package/dist/__tests__/auth-state.test.js +86 -0
  3. package/dist/__tests__/auth-state.test.js.map +1 -0
  4. package/dist/__tests__/card-ref.test.d.ts +1 -0
  5. package/dist/__tests__/card-ref.test.js +36 -0
  6. package/dist/__tests__/card-ref.test.js.map +1 -0
  7. package/dist/__tests__/column-match.test.d.ts +1 -0
  8. package/dist/__tests__/column-match.test.js +49 -0
  9. package/dist/__tests__/column-match.test.js.map +1 -0
  10. package/dist/__tests__/commands.test.d.ts +1 -0
  11. package/dist/__tests__/commands.test.js +243 -0
  12. package/dist/__tests__/commands.test.js.map +1 -0
  13. package/dist/__tests__/helpers.d.ts +50 -0
  14. package/dist/__tests__/helpers.js +135 -0
  15. package/dist/__tests__/helpers.js.map +1 -0
  16. package/dist/__tests__/materialize.test.d.ts +1 -0
  17. package/dist/__tests__/materialize.test.js +186 -0
  18. package/dist/__tests__/materialize.test.js.map +1 -0
  19. package/dist/__tests__/pds.test.d.ts +1 -0
  20. package/dist/__tests__/pds.test.js +172 -0
  21. package/dist/__tests__/pds.test.js.map +1 -0
  22. package/dist/commands/add.d.ts +1 -0
  23. package/dist/commands/add.js +41 -0
  24. package/dist/commands/add.js.map +1 -0
  25. package/dist/commands/boards.d.ts +3 -0
  26. package/dist/commands/boards.js +54 -0
  27. package/dist/commands/boards.js.map +1 -0
  28. package/dist/commands/cards.d.ts +7 -0
  29. package/dist/commands/cards.js +54 -0
  30. package/dist/commands/cards.js.map +1 -0
  31. package/dist/commands/cols.d.ts +4 -0
  32. package/dist/commands/cols.js +44 -0
  33. package/dist/commands/cols.js.map +1 -0
  34. package/dist/commands/comment.d.ts +4 -0
  35. package/dist/commands/comment.js +55 -0
  36. package/dist/commands/comment.js.map +1 -0
  37. package/dist/commands/edit.d.ts +7 -0
  38. package/dist/commands/edit.js +80 -0
  39. package/dist/commands/edit.js.map +1 -0
  40. package/dist/commands/login.d.ts +1 -0
  41. package/dist/commands/login.js +20 -0
  42. package/dist/commands/login.js.map +1 -0
  43. package/dist/commands/logout.d.ts +1 -0
  44. package/dist/commands/logout.js +14 -0
  45. package/dist/commands/logout.js.map +1 -0
  46. package/dist/commands/mv.d.ts +4 -0
  47. package/dist/commands/mv.js +74 -0
  48. package/dist/commands/mv.js.map +1 -0
  49. package/dist/commands/new.d.ts +6 -0
  50. package/dist/commands/new.js +72 -0
  51. package/dist/commands/new.js.map +1 -0
  52. package/dist/commands/rm.d.ts +5 -0
  53. package/dist/commands/rm.js +67 -0
  54. package/dist/commands/rm.js.map +1 -0
  55. package/dist/commands/show.d.ts +4 -0
  56. package/dist/commands/show.js +90 -0
  57. package/dist/commands/show.js.map +1 -0
  58. package/dist/commands/status.d.ts +3 -0
  59. package/dist/commands/status.js +71 -0
  60. package/dist/commands/status.js.map +1 -0
  61. package/dist/commands/use.d.ts +1 -0
  62. package/dist/commands/use.js +61 -0
  63. package/dist/commands/use.js.map +1 -0
  64. package/dist/commands/whoami.d.ts +3 -0
  65. package/dist/commands/whoami.js +23 -0
  66. package/dist/commands/whoami.js.map +1 -0
  67. package/dist/index.d.ts +2 -0
  68. package/dist/index.js +126 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/lib/auth.d.ts +28 -0
  71. package/dist/lib/auth.js +219 -0
  72. package/dist/lib/auth.js.map +1 -0
  73. package/dist/lib/card-ref.d.ts +7 -0
  74. package/dist/lib/card-ref.js +23 -0
  75. package/dist/lib/card-ref.js.map +1 -0
  76. package/dist/lib/column-match.d.ts +6 -0
  77. package/dist/lib/column-match.js +35 -0
  78. package/dist/lib/column-match.js.map +1 -0
  79. package/dist/lib/config.d.ts +32 -0
  80. package/dist/lib/config.js +153 -0
  81. package/dist/lib/config.js.map +1 -0
  82. package/dist/lib/display.d.ts +11 -0
  83. package/dist/lib/display.js +97 -0
  84. package/dist/lib/display.js.map +1 -0
  85. package/dist/lib/materialize.d.ts +2 -0
  86. package/dist/lib/materialize.js +111 -0
  87. package/dist/lib/materialize.js.map +1 -0
  88. package/dist/lib/pds.d.ts +48 -0
  89. package/dist/lib/pds.js +355 -0
  90. package/dist/lib/pds.js.map +1 -0
  91. package/dist/lib/permissions.d.ts +4 -0
  92. package/dist/lib/permissions.js +13 -0
  93. package/dist/lib/permissions.js.map +1 -0
  94. package/dist/lib/schemas.d.ts +209 -0
  95. package/dist/lib/schemas.js +82 -0
  96. package/dist/lib/schemas.js.map +1 -0
  97. package/dist/lib/tid.d.ts +9 -0
  98. package/{src/lib/tid.ts → dist/lib/tid.js} +5 -11
  99. package/dist/lib/tid.js.map +1 -0
  100. package/dist/lib/types.d.ts +129 -0
  101. package/dist/lib/types.js +3 -0
  102. package/dist/lib/types.js.map +1 -0
  103. package/package.json +6 -2
  104. package/src/__tests__/auth-state.test.ts +0 -111
  105. package/src/__tests__/card-ref.test.ts +0 -42
  106. package/src/__tests__/column-match.test.ts +0 -57
  107. package/src/__tests__/commands.test.ts +0 -326
  108. package/src/__tests__/helpers.ts +0 -154
  109. package/src/__tests__/materialize.test.ts +0 -257
  110. package/src/__tests__/pds.test.ts +0 -213
  111. package/src/commands/add.ts +0 -47
  112. package/src/commands/boards.ts +0 -64
  113. package/src/commands/cards.ts +0 -65
  114. package/src/commands/cols.ts +0 -51
  115. package/src/commands/comment.ts +0 -64
  116. package/src/commands/edit.ts +0 -89
  117. package/src/commands/login.ts +0 -19
  118. package/src/commands/logout.ts +0 -14
  119. package/src/commands/mv.ts +0 -84
  120. package/src/commands/new.ts +0 -80
  121. package/src/commands/rm.ts +0 -79
  122. package/src/commands/show.ts +0 -100
  123. package/src/commands/status.ts +0 -78
  124. package/src/commands/use.ts +0 -72
  125. package/src/commands/whoami.ts +0 -22
  126. package/src/index.ts +0 -143
  127. package/src/lib/auth.ts +0 -244
  128. package/src/lib/card-ref.ts +0 -32
  129. package/src/lib/column-match.ts +0 -45
  130. package/src/lib/config.ts +0 -182
  131. package/src/lib/display.ts +0 -112
  132. package/src/lib/materialize.ts +0 -138
  133. package/src/lib/pds.ts +0 -440
  134. package/src/lib/permissions.ts +0 -28
  135. package/src/lib/schemas.ts +0 -97
  136. package/src/lib/types.ts +0 -144
  137. package/tsconfig.json +0 -15
  138. package/vitest.config.ts +0 -7
@@ -0,0 +1,219 @@
1
+ import { Agent } from "@atproto/api";
2
+ import { NodeOAuthClient } from "@atproto/oauth-client-node";
3
+ import { requestLocalLock } from "@atproto/oauth-client";
4
+ import { createServer } from "node:http";
5
+ import { writeStateFile, readStateFile, deleteStateFile, writeSessionFile, readSessionFile, deleteSessionFile, loadAuthInfo, saveAuthInfo, clearAuthInfo, } from "./config.js";
6
+ const OAUTH_SCOPE = "atproto repo:dev.skyboard.board repo:dev.skyboard.task repo:dev.skyboard.op repo:dev.skyboard.trust repo:dev.skyboard.comment repo:dev.skyboard.approval repo:dev.skyboard.reaction";
7
+ // File-based stores implementing the NodeOAuthClient interfaces
8
+ const stateStore = {
9
+ async set(key, state) {
10
+ writeStateFile(key, state);
11
+ },
12
+ async get(key) {
13
+ return readStateFile(key);
14
+ },
15
+ async del(key) {
16
+ deleteStateFile(key);
17
+ },
18
+ };
19
+ const sessionStore = {
20
+ async set(sub, session) {
21
+ writeSessionFile(sub, session);
22
+ },
23
+ async get(sub) {
24
+ return readSessionFile(sub);
25
+ },
26
+ async del(sub) {
27
+ deleteSessionFile(sub);
28
+ },
29
+ };
30
+ function createOAuthClient(port) {
31
+ const redirectUri = `http://127.0.0.1:${port}/callback`;
32
+ return new NodeOAuthClient({
33
+ clientMetadata: {
34
+ client_id: `http://localhost?redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(OAUTH_SCOPE)}`,
35
+ client_name: "Skyboard CLI",
36
+ redirect_uris: [redirectUri],
37
+ scope: OAUTH_SCOPE,
38
+ grant_types: ["authorization_code", "refresh_token"],
39
+ response_types: ["code"],
40
+ token_endpoint_auth_method: "none",
41
+ application_type: "native",
42
+ dpop_bound_access_tokens: true,
43
+ },
44
+ stateStore,
45
+ sessionStore,
46
+ requestLock: requestLocalLock,
47
+ });
48
+ }
49
+ /**
50
+ * Find a free port by binding to port 0.
51
+ */
52
+ async function findFreePort() {
53
+ return new Promise((resolve, reject) => {
54
+ const srv = createServer();
55
+ srv.listen(0, "127.0.0.1", () => {
56
+ const addr = srv.address();
57
+ if (addr && typeof addr === "object") {
58
+ const port = addr.port;
59
+ srv.close(() => resolve(port));
60
+ }
61
+ else {
62
+ srv.close(() => reject(new Error("Could not determine port")));
63
+ }
64
+ });
65
+ srv.on("error", reject);
66
+ });
67
+ }
68
+ /**
69
+ * Perform OAuth loopback login. Opens browser for authorization,
70
+ * starts a local HTTP server for the callback.
71
+ * Returns the DID and handle of the authenticated user.
72
+ */
73
+ export async function login(handle) {
74
+ const port = await findFreePort();
75
+ const client = createOAuthClient(port);
76
+ const authUrl = await client.authorize(handle, {
77
+ scope: OAUTH_SCOPE,
78
+ });
79
+ // Start callback server
80
+ return new Promise((resolve, reject) => {
81
+ const timeout = setTimeout(() => {
82
+ server.close();
83
+ reject(new Error("Login timed out after 120 seconds"));
84
+ }, 120_000);
85
+ const server = createServer(async (req, res) => {
86
+ if (!req.url?.startsWith("/callback")) {
87
+ res.writeHead(404);
88
+ res.end("Not found");
89
+ return;
90
+ }
91
+ try {
92
+ const url = new URL(req.url, `http://127.0.0.1:${port}`);
93
+ const { session } = await client.callback(url.searchParams);
94
+ const did = session.did;
95
+ // Resolve handle from DID
96
+ const agent = new Agent(session);
97
+ let resolvedHandle = handle;
98
+ try {
99
+ const profile = await agent.getProfile({ actor: did });
100
+ resolvedHandle = profile.data.handle;
101
+ }
102
+ catch {
103
+ // Use the provided handle as fallback
104
+ }
105
+ // Find the PDS endpoint for this DID
106
+ let service = "https://bsky.social";
107
+ try {
108
+ const didDoc = await resolveDIDDocument(did);
109
+ if (didDoc) {
110
+ const services = didDoc.service;
111
+ const pds = services?.find((s) => s.id === "#atproto_pds" || s.type === "AtprotoPersonalDataServer");
112
+ if (pds?.serviceEndpoint) {
113
+ service = pds.serviceEndpoint;
114
+ }
115
+ }
116
+ }
117
+ catch {
118
+ // fallback to default
119
+ }
120
+ saveAuthInfo({ did, handle: resolvedHandle, service });
121
+ res.writeHead(200, { "Content-Type": "text/html" });
122
+ res.end(`
123
+ <html><body style="font-family: system-ui; text-align: center; padding: 40px;">
124
+ <h2>Logged in to Skyboard CLI</h2>
125
+ <p>You can close this tab and return to your terminal.</p>
126
+ </body></html>
127
+ `);
128
+ clearTimeout(timeout);
129
+ server.close();
130
+ resolve({ did, handle: resolvedHandle });
131
+ }
132
+ catch (err) {
133
+ res.writeHead(500, { "Content-Type": "text/html" });
134
+ res.end(`
135
+ <html><body style="font-family: system-ui; text-align: center; padding: 40px;">
136
+ <h2>Login failed</h2>
137
+ <p>${err instanceof Error ? err.message : "Unknown error"}</p>
138
+ </body></html>
139
+ `);
140
+ clearTimeout(timeout);
141
+ server.close();
142
+ reject(err);
143
+ }
144
+ });
145
+ server.listen(port, "127.0.0.1", async () => {
146
+ // Open browser
147
+ try {
148
+ const open = (await import("open")).default;
149
+ await open(authUrl.toString());
150
+ console.log(`\nOpened browser for login. Waiting for authorization...`);
151
+ console.log(`If the browser didn't open, visit:\n${authUrl.toString()}\n`);
152
+ }
153
+ catch {
154
+ console.log(`\nOpen this URL in your browser to log in:\n${authUrl.toString()}\n`);
155
+ }
156
+ });
157
+ });
158
+ }
159
+ /**
160
+ * Get an authenticated Agent for the currently logged-in user.
161
+ * Restores the OAuth session and returns an Agent that auto-refreshes tokens.
162
+ */
163
+ export async function getAgent() {
164
+ const authInfo = loadAuthInfo();
165
+ if (!authInfo)
166
+ return null;
167
+ try {
168
+ // We need to create a client to restore the session.
169
+ // Since we don't know the original port, use a dummy port — session
170
+ // restoration doesn't need the redirect_uri to match.
171
+ const client = createOAuthClient(0);
172
+ const session = await client.restore(authInfo.did);
173
+ const agent = new Agent(session);
174
+ return { agent, did: authInfo.did, handle: authInfo.handle };
175
+ }
176
+ catch {
177
+ return null;
178
+ }
179
+ }
180
+ /**
181
+ * Require authentication — exit with error if not logged in.
182
+ */
183
+ export async function requireAgent() {
184
+ const result = await getAgent();
185
+ if (!result) {
186
+ console.error("Not logged in. Run `sb login <handle>` first.");
187
+ process.exit(1);
188
+ }
189
+ return result;
190
+ }
191
+ export function logout() {
192
+ const authInfo = loadAuthInfo();
193
+ if (authInfo) {
194
+ deleteSessionFile(authInfo.did);
195
+ }
196
+ clearAuthInfo();
197
+ }
198
+ async function resolveDIDDocument(did) {
199
+ try {
200
+ if (did.startsWith("did:plc:")) {
201
+ const res = await fetch(`https://plc.directory/${did}`);
202
+ if (!res.ok)
203
+ return null;
204
+ return await res.json();
205
+ }
206
+ else if (did.startsWith("did:web:")) {
207
+ const host = did.slice("did:web:".length).replaceAll(":", "/");
208
+ const res = await fetch(`https://${host}/.well-known/did.json`);
209
+ if (!res.ok)
210
+ return null;
211
+ return await res.json();
212
+ }
213
+ return null;
214
+ }
215
+ catch {
216
+ return null;
217
+ }
218
+ }
219
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { MaterializedTask } from "./types.js";
2
+ /**
3
+ * Resolve a card reference (TID rkey prefix) to a unique task.
4
+ * Returns the matching task, or throws with a helpful message if
5
+ * ambiguous or not found.
6
+ */
7
+ export declare function resolveCardRef(ref: string, tasks: MaterializedTask[]): MaterializedTask;
@@ -0,0 +1,23 @@
1
+ const MIN_PREFIX_LEN = 4;
2
+ /**
3
+ * Resolve a card reference (TID rkey prefix) to a unique task.
4
+ * Returns the matching task, or throws with a helpful message if
5
+ * ambiguous or not found.
6
+ */
7
+ export function resolveCardRef(ref, tasks) {
8
+ if (ref.length < MIN_PREFIX_LEN) {
9
+ throw new Error(`Card reference too short (min ${MIN_PREFIX_LEN} chars): ${ref}`);
10
+ }
11
+ const matches = tasks.filter((t) => t.rkey.startsWith(ref));
12
+ if (matches.length === 0) {
13
+ throw new Error(`No card found matching "${ref}"`);
14
+ }
15
+ if (matches.length > 1) {
16
+ const list = matches
17
+ .map((t) => ` ${t.rkey.slice(0, 7)} ${t.effectiveTitle}`)
18
+ .join("\n");
19
+ throw new Error(`Ambiguous reference "${ref}". Matches:\n${list}`);
20
+ }
21
+ return matches[0];
22
+ }
23
+ //# sourceMappingURL=card-ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-ref.js","sourceRoot":"","sources":["../../src/lib/card-ref.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAW,EACX,KAAyB;IAEzB,IAAI,GAAG,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,iCAAiC,cAAc,YAAY,GAAG,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAE5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,OAAO;aACjB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,cAAc,EAAE,CAAC;aAC1D,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,gBAAgB,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { Column } from "./types.js";
2
+ /**
3
+ * Match a column reference (name, prefix, or 1-based index) to a column.
4
+ * Throws with a helpful message if no match found.
5
+ */
6
+ export declare function resolveColumn(ref: string, columns: Column[]): Column;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Match a column reference (name, prefix, or 1-based index) to a column.
3
+ * Throws with a helpful message if no match found.
4
+ */
5
+ export function resolveColumn(ref, columns) {
6
+ const sorted = [...columns].sort((a, b) => a.order - b.order);
7
+ // Try numeric index (1-based)
8
+ const idx = parseInt(ref, 10);
9
+ if (!isNaN(idx) && idx >= 1 && idx <= sorted.length) {
10
+ return sorted[idx - 1];
11
+ }
12
+ // Try exact match (case-insensitive)
13
+ const exact = sorted.find((c) => c.name.toLowerCase() === ref.toLowerCase());
14
+ if (exact)
15
+ return exact;
16
+ // Try prefix match
17
+ const prefixMatches = sorted.filter((c) => c.name.toLowerCase().startsWith(ref.toLowerCase()));
18
+ if (prefixMatches.length === 1)
19
+ return prefixMatches[0];
20
+ if (prefixMatches.length > 1) {
21
+ const list = prefixMatches.map((c, i) => ` ${i + 1}. ${c.name}`).join("\n");
22
+ throw new Error(`Ambiguous column "${ref}". Matches:\n${list}`);
23
+ }
24
+ // Try substring match
25
+ const subMatches = sorted.filter((c) => c.name.toLowerCase().includes(ref.toLowerCase()));
26
+ if (subMatches.length === 1)
27
+ return subMatches[0];
28
+ if (subMatches.length > 1) {
29
+ const list = subMatches.map((c, i) => ` ${i + 1}. ${c.name}`).join("\n");
30
+ throw new Error(`Ambiguous column "${ref}". Matches:\n${list}`);
31
+ }
32
+ const allCols = sorted.map((c, i) => ` ${i + 1}. ${c.name}`).join("\n");
33
+ throw new Error(`No column matching "${ref}". Available columns:\n${allCols}`);
34
+ }
35
+ //# sourceMappingURL=column-match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column-match.js","sourceRoot":"","sources":["../../src/lib/column-match.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAW,EACX,OAAiB;IAEjB,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAE9D,8BAA8B;IAC9B,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QACpD,OAAO,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IACzB,CAAC;IAED,qCAAqC;IACrC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7E,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IAExB,mBAAmB;IACnB,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACxC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CACnD,CAAC;IACF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC;IACxD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,gBAAgB,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,sBAAsB;IACtB,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACrC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CACjD,CAAC;IACF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;IAClD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,gBAAgB,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzE,MAAM,IAAI,KAAK,CAAC,uBAAuB,GAAG,0BAA0B,OAAO,EAAE,CAAC,CAAC;AACjF,CAAC"}
@@ -0,0 +1,32 @@
1
+ export interface BoardRef {
2
+ did: string;
3
+ rkey: string;
4
+ name: string;
5
+ }
6
+ export interface Config {
7
+ defaultBoard?: BoardRef;
8
+ knownBoards: BoardRef[];
9
+ }
10
+ export declare function getConfigDir(): string;
11
+ export declare function getAuthDir(): string;
12
+ export declare function getStateDir(): string;
13
+ export declare function loadConfig(): Config;
14
+ export declare function saveConfig(config: Config): void;
15
+ export declare function setDefaultBoard(board: BoardRef): void;
16
+ export declare function getDefaultBoard(): BoardRef | undefined;
17
+ export declare function clearDefaultBoard(): void;
18
+ export declare function addKnownBoard(board: BoardRef): void;
19
+ export declare function writeStateFile(key: string, data: unknown): void;
20
+ export declare function readStateFile(key: string): unknown | undefined;
21
+ export declare function deleteStateFile(key: string): void;
22
+ export declare function writeSessionFile(sub: string, data: unknown): void;
23
+ export declare function readSessionFile(sub: string): unknown | undefined;
24
+ export declare function deleteSessionFile(sub: string): void;
25
+ export interface AuthInfo {
26
+ did: string;
27
+ handle: string;
28
+ service: string;
29
+ }
30
+ export declare function loadAuthInfo(): AuthInfo | null;
31
+ export declare function saveAuthInfo(info: AuthInfo): void;
32
+ export declare function clearAuthInfo(): void;
@@ -0,0 +1,153 @@
1
+ import { mkdirSync, readFileSync, writeFileSync, existsSync, unlinkSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ const CONFIG_DIR = join(homedir(), ".config", "skyboard");
5
+ const CONFIG_PATH = join(CONFIG_DIR, "config.json");
6
+ const AUTH_DIR = join(CONFIG_DIR, "auth");
7
+ const STATE_DIR = join(CONFIG_DIR, "state");
8
+ export function getConfigDir() {
9
+ return CONFIG_DIR;
10
+ }
11
+ export function getAuthDir() {
12
+ return AUTH_DIR;
13
+ }
14
+ export function getStateDir() {
15
+ return STATE_DIR;
16
+ }
17
+ function ensureConfigDir() {
18
+ mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
19
+ }
20
+ function ensureAuthDir() {
21
+ ensureConfigDir();
22
+ mkdirSync(AUTH_DIR, { recursive: true, mode: 0o700 });
23
+ }
24
+ function ensureStateDir() {
25
+ ensureConfigDir();
26
+ mkdirSync(STATE_DIR, { recursive: true, mode: 0o700 });
27
+ }
28
+ export function loadConfig() {
29
+ ensureConfigDir();
30
+ if (!existsSync(CONFIG_PATH)) {
31
+ return { knownBoards: [] };
32
+ }
33
+ try {
34
+ const raw = readFileSync(CONFIG_PATH, "utf-8");
35
+ return JSON.parse(raw);
36
+ }
37
+ catch {
38
+ return { knownBoards: [] };
39
+ }
40
+ }
41
+ export function saveConfig(config) {
42
+ ensureConfigDir();
43
+ writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), {
44
+ mode: 0o600,
45
+ });
46
+ }
47
+ export function setDefaultBoard(board) {
48
+ const config = loadConfig();
49
+ config.defaultBoard = board;
50
+ if (!config.knownBoards.some((b) => b.did === board.did && b.rkey === board.rkey)) {
51
+ config.knownBoards.push(board);
52
+ }
53
+ saveConfig(config);
54
+ }
55
+ export function getDefaultBoard() {
56
+ return loadConfig().defaultBoard;
57
+ }
58
+ export function clearDefaultBoard() {
59
+ const config = loadConfig();
60
+ delete config.defaultBoard;
61
+ saveConfig(config);
62
+ }
63
+ export function addKnownBoard(board) {
64
+ const config = loadConfig();
65
+ if (!config.knownBoards.some((b) => b.did === board.did && b.rkey === board.rkey)) {
66
+ config.knownBoards.push(board);
67
+ }
68
+ saveConfig(config);
69
+ }
70
+ // File-based state store for OAuth CSRF tokens
71
+ export function writeStateFile(key, data) {
72
+ ensureStateDir();
73
+ writeFileSync(join(STATE_DIR, `${key}.json`), JSON.stringify(data), {
74
+ mode: 0o600,
75
+ });
76
+ }
77
+ export function readStateFile(key) {
78
+ const path = join(STATE_DIR, `${key}.json`);
79
+ if (!existsSync(path))
80
+ return undefined;
81
+ try {
82
+ return JSON.parse(readFileSync(path, "utf-8"));
83
+ }
84
+ catch {
85
+ return undefined;
86
+ }
87
+ }
88
+ export function deleteStateFile(key) {
89
+ const path = join(STATE_DIR, `${key}.json`);
90
+ try {
91
+ unlinkSync(path);
92
+ }
93
+ catch {
94
+ // ignore
95
+ }
96
+ }
97
+ // File-based session store for OAuth sessions
98
+ export function writeSessionFile(sub, data) {
99
+ ensureAuthDir();
100
+ const filename = Buffer.from(sub).toString("base64url");
101
+ writeFileSync(join(AUTH_DIR, `${filename}.json`), JSON.stringify(data), {
102
+ mode: 0o600,
103
+ });
104
+ }
105
+ export function readSessionFile(sub) {
106
+ const filename = Buffer.from(sub).toString("base64url");
107
+ const path = join(AUTH_DIR, `${filename}.json`);
108
+ if (!existsSync(path))
109
+ return undefined;
110
+ try {
111
+ return JSON.parse(readFileSync(path, "utf-8"));
112
+ }
113
+ catch {
114
+ return undefined;
115
+ }
116
+ }
117
+ export function deleteSessionFile(sub) {
118
+ const filename = Buffer.from(sub).toString("base64url");
119
+ const path = join(AUTH_DIR, `${filename}.json`);
120
+ try {
121
+ unlinkSync(path);
122
+ }
123
+ catch {
124
+ // ignore
125
+ }
126
+ }
127
+ // Simple auth info storage (which DID is logged in)
128
+ const AUTH_INFO_PATH = join(CONFIG_DIR, "session.json");
129
+ export function loadAuthInfo() {
130
+ if (!existsSync(AUTH_INFO_PATH))
131
+ return null;
132
+ try {
133
+ return JSON.parse(readFileSync(AUTH_INFO_PATH, "utf-8"));
134
+ }
135
+ catch {
136
+ return null;
137
+ }
138
+ }
139
+ export function saveAuthInfo(info) {
140
+ ensureConfigDir();
141
+ writeFileSync(AUTH_INFO_PATH, JSON.stringify(info, null, 2), {
142
+ mode: 0o600,
143
+ });
144
+ }
145
+ export function clearAuthInfo() {
146
+ try {
147
+ unlinkSync(AUTH_INFO_PATH);
148
+ }
149
+ catch {
150
+ // ignore
151
+ }
152
+ }
153
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { MaterializedTask, Board, Column } from "./types.js";
2
+ export declare function formatDate(iso: string): string;
3
+ export declare function shortRkey(rkey: string): string;
4
+ export declare function formatTask(task: MaterializedTask, board: Board): string;
5
+ export declare function formatBoardHeader(board: Board): string;
6
+ export declare function formatColumnHeader(col: Column, taskCount: number): string;
7
+ export declare function printBoardCards(board: Board, tasks: MaterializedTask[], opts: {
8
+ column?: string;
9
+ label?: string;
10
+ search?: string;
11
+ }): void;
@@ -0,0 +1,97 @@
1
+ import chalk from "chalk";
2
+ export function formatDate(iso) {
3
+ const d = new Date(iso);
4
+ const now = new Date();
5
+ const diffMs = now.getTime() - d.getTime();
6
+ const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
7
+ if (diffDays === 0) {
8
+ return d.toLocaleTimeString(undefined, { hour: "2-digit", minute: "2-digit" });
9
+ }
10
+ else if (diffDays < 7) {
11
+ return `${diffDays}d ago`;
12
+ }
13
+ else {
14
+ return d.toLocaleDateString(undefined, { month: "short", day: "numeric" });
15
+ }
16
+ }
17
+ export function shortRkey(rkey) {
18
+ return rkey.slice(0, 7);
19
+ }
20
+ export function formatTask(task, board) {
21
+ const col = board.columns.find((c) => c.id === task.effectiveColumnId);
22
+ const colName = col?.name ?? "?";
23
+ const labels = task.effectiveLabelIds
24
+ .map((id) => board.labels?.find((l) => l.id === id))
25
+ .filter(Boolean)
26
+ .map((l) => chalk.hex(l.color)(`[${l.name}]`))
27
+ .join(" ");
28
+ const ref = chalk.dim(shortRkey(task.rkey));
29
+ const title = task.effectiveTitle;
30
+ const date = chalk.dim(formatDate(task.lastModifiedAt));
31
+ let line = ` ${ref} ${title}`;
32
+ if (labels)
33
+ line += ` ${labels}`;
34
+ line += ` ${date}`;
35
+ return line;
36
+ }
37
+ export function formatBoardHeader(board) {
38
+ let header = chalk.bold(board.name);
39
+ if (board.description) {
40
+ header += chalk.dim(` ${board.description}`);
41
+ }
42
+ return header;
43
+ }
44
+ export function formatColumnHeader(col, taskCount) {
45
+ return `\n${chalk.bold.underline(col.name)} ${chalk.dim(`(${taskCount})`)}`;
46
+ }
47
+ export function printBoardCards(board, tasks, opts) {
48
+ // Sort columns by order
49
+ const sortedColumns = [...board.columns].sort((a, b) => a.order - b.order);
50
+ for (const col of sortedColumns) {
51
+ // Filter tasks for this column
52
+ let colTasks = tasks.filter((t) => t.effectiveColumnId === col.id);
53
+ // Apply filters
54
+ if (opts.column && !matchesColumn(col, opts.column, sortedColumns))
55
+ continue;
56
+ if (opts.label) {
57
+ const label = board.labels?.find((l) => l.name.toLowerCase().includes(opts.label.toLowerCase()));
58
+ if (label) {
59
+ colTasks = colTasks.filter((t) => t.effectiveLabelIds.includes(label.id));
60
+ }
61
+ else {
62
+ colTasks = [];
63
+ }
64
+ }
65
+ if (opts.search) {
66
+ const s = opts.search.toLowerCase();
67
+ colTasks = colTasks.filter((t) => t.effectiveTitle.toLowerCase().includes(s) ||
68
+ (t.effectiveDescription?.toLowerCase().includes(s) ?? false));
69
+ }
70
+ // Sort by position
71
+ colTasks.sort((a, b) => a.effectivePosition.localeCompare(b.effectivePosition));
72
+ console.log(formatColumnHeader(col, colTasks.length));
73
+ if (colTasks.length === 0) {
74
+ console.log(chalk.dim(" (empty)"));
75
+ }
76
+ else {
77
+ for (const task of colTasks) {
78
+ console.log(formatTask(task, board));
79
+ }
80
+ }
81
+ }
82
+ }
83
+ function matchesColumn(col, query, allColumns) {
84
+ // Check numeric index (1-based)
85
+ const idx = parseInt(query, 10);
86
+ if (!isNaN(idx) && idx >= 1 && idx <= allColumns.length) {
87
+ return allColumns[idx - 1].id === col.id;
88
+ }
89
+ // Check exact match (case-insensitive)
90
+ if (col.name.toLowerCase() === query.toLowerCase())
91
+ return true;
92
+ // Check prefix match
93
+ if (col.name.toLowerCase().startsWith(query.toLowerCase()))
94
+ return true;
95
+ return false;
96
+ }
97
+ //# sourceMappingURL=display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/lib/display.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Task, Op, MaterializedTask } from "./types.js";
2
+ export declare function materializeTasks(tasks: Task[], ops: Op[], ownerTrustedDids: Set<string>, currentUserDid: string, boardOwnerDid: string): MaterializedTask[];