sfora-cli 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/SforaFs.js CHANGED
@@ -73,6 +73,9 @@ function classify(path) {
73
73
  if (seg.length === 2)
74
74
  return { kind: "projectDir", slug };
75
75
  const dir = seg[2];
76
+ if (dir === "links.md" && seg.length === 3) {
77
+ return { kind: "linksFile", slug };
78
+ }
76
79
  if (dir === "posts" || dir === "drafts") {
77
80
  if (seg.length === 3)
78
81
  return { kind: "postsDir", slug, dir };
@@ -276,6 +279,13 @@ export class SforaFs {
276
279
  catch (e) {
277
280
  throw fromApi(e, "open", normalize(path));
278
281
  }
282
+ case "linksFile":
283
+ try {
284
+ return await this.#client.getProjectLinks(loc.slug);
285
+ }
286
+ catch (e) {
287
+ throw fromApi(e, "open", normalize(path));
288
+ }
279
289
  case "root":
280
290
  case "projectsDir":
281
291
  case "inboxDir":
@@ -306,6 +316,15 @@ export class SforaFs {
306
316
  if (loc.kind === "inboxFile" || loc.kind === "meFile") {
307
317
  throw eacces("open", norm);
308
318
  }
319
+ if (loc.kind === "linksFile") {
320
+ try {
321
+ await this.#client.setProjectLinks(loc.slug, toText(content));
322
+ }
323
+ catch (e) {
324
+ throw fromApi(e, "open", norm);
325
+ }
326
+ return;
327
+ }
309
328
  if (loc.kind === "root" ||
310
329
  loc.kind === "projectsDir" ||
311
330
  loc.kind === "inboxDir" ||
@@ -416,6 +435,10 @@ export class SforaFs {
416
435
  case "inboxFile":
417
436
  case "meFile":
418
437
  return this.#fileStat(new Date());
438
+ case "linksFile":
439
+ if (!(await this.#projectExists(loc.slug)))
440
+ throw enoent("stat", norm);
441
+ return this.#fileStat(new Date());
419
442
  case "projectDir":
420
443
  case "postsDir":
421
444
  case "boardDir":
@@ -489,6 +512,7 @@ export class SforaFs {
489
512
  return [
490
513
  dirent("board", true),
491
514
  dirent("drafts", true),
515
+ dirent("links.md", false),
492
516
  dirent("posts", true),
493
517
  ];
494
518
  case "postsDir": {
@@ -75,6 +75,10 @@ export declare class SforaApiClient {
75
75
  slug: string;
76
76
  name: string;
77
77
  }>;
78
+ /** `GET …/links.md` — the project's external links as markdown. */
79
+ getProjectLinks(slug: string): Promise<string>;
80
+ /** `PUT …/links.md` — replace the project's links from a markdown list. */
81
+ setProjectLinks(slug: string, markdown: string): Promise<void>;
78
82
  /**
79
83
  * `GET …/posts` or `…/drafts`. `scheduled` lists drafts that have a
80
84
  * (future) `scheduledFor` set.
@@ -90,6 +90,14 @@ export class SforaApiClient {
90
90
  const res = await this.#request("POST", "/v1/fs/projects", JSON.stringify({ name }));
91
91
  return (await res.json());
92
92
  }
93
+ /** `GET …/links.md` — the project's external links as markdown. */
94
+ async getProjectLinks(slug) {
95
+ return this.#text(`/v1/fs/projects/${encodeURIComponent(slug)}/links.md`);
96
+ }
97
+ /** `PUT …/links.md` — replace the project's links from a markdown list. */
98
+ async setProjectLinks(slug, markdown) {
99
+ await this.#request("PUT", `/v1/fs/projects/${encodeURIComponent(slug)}/links.md`, markdown);
100
+ }
93
101
  /**
94
102
  * `GET …/posts` or `…/drafts`. `scheduled` lists drafts that have a
95
103
  * (future) `scheduledFor` set.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sfora-cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "Your sfora workspace as a markdown filesystem — a CLI + MCP server. Post/task/doc, ls/cat/grep, and a shell so agents operate sfora natively.",
6
6
  "keywords": [