@shiori-sh/cli 0.5.0 → 0.7.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.
Files changed (3) hide show
  1. package/README.md +7 -0
  2. package/dist/index.js +234 -10
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -29,6 +29,7 @@ You can also set `SHIORI_API_KEY` as an environment variable.
29
29
  ```bash
30
30
  shiori list # List recent links
31
31
  shiori list --read unread # List unread links
32
+ shiori list --tag "design" # Filter links by tag
32
33
  shiori list --since 7d # Links saved in the last 7 days
33
34
  shiori list --content --json # Include full markdown content
34
35
 
@@ -54,6 +55,12 @@ shiori delete --ids <id1,id2,...> # Bulk move to trash
54
55
  shiori trash # List trashed links
55
56
  shiori trash --empty # Permanently delete all trash
56
57
 
58
+ shiori tags list # List your tags
59
+ shiori tags create "design" # Create a tag
60
+ shiori tags update <id> --name "dev" # Rename a tag
61
+ shiori tags delete <id> # Delete a tag
62
+ shiori tags set <link-id> design,work # Set tags on a link
63
+
57
64
  shiori subscriptions list # List RSS subscriptions
58
65
  shiori subscriptions add <url> # Subscribe to an RSS feed
59
66
  shiori subscriptions add <url> --sync # Subscribe and sync recent items
package/dist/index.js CHANGED
@@ -291,7 +291,9 @@ function getPositional(args) {
291
291
  "--summary",
292
292
  "--since",
293
293
  "--format",
294
- "--ids"
294
+ "--ids",
295
+ "--tag",
296
+ "--name"
295
297
  ].includes(args[i])) {
296
298
  i++;
297
299
  }
@@ -458,6 +460,7 @@ Options:
458
460
  --offset <n> Pagination offset (default: 0)
459
461
  --sort <newest|oldest> Sort order (default: newest)
460
462
  --read <all|read|unread> Filter by read status (default: all)
463
+ --tag <name> Filter by tag name
461
464
  --since <duration> Only links saved within this period (e.g. 1h, 7d, 2w, 1m, 1y)
462
465
  --content Include extracted markdown content
463
466
  --json Output raw JSON
@@ -469,6 +472,7 @@ Options:
469
472
  const sort = getFlag(args, "--sort", "newest");
470
473
  const read = getFlag(args, "--read", "all");
471
474
  const sinceFlag = getFlag(args, "--since");
475
+ const tag = getFlag(args, "--tag");
472
476
  const includeContent = hasFlag(args, "--content");
473
477
  const params = new URLSearchParams({
474
478
  limit,
@@ -478,6 +482,7 @@ Options:
478
482
  });
479
483
  if (includeContent) params.set("include_content", "true");
480
484
  if (sinceFlag) params.set("since", parseDuration(sinceFlag));
485
+ if (tag) params.set("tag", tag);
481
486
  const { data } = await api("GET", `/api/links?${params}`);
482
487
  if (hasFlag(args, "--json")) {
483
488
  console.log(JSON.stringify(data, null, 2));
@@ -734,8 +739,226 @@ Options:
734
739
  console.log(`Synced: ${data.newItems} new, ${data.skipped} skipped, ${data.errors} errors`);
735
740
  }
736
741
 
737
- // src/commands/trash.ts
742
+ // src/commands/tags.ts
743
+ var HELP2 = `shiori tags - Manage tags
744
+
745
+ Usage: shiori tags <subcommand> [options]
746
+
747
+ Subcommands:
748
+ list List your tags
749
+ create <name> Create a tag
750
+ update <id> --name <name> Rename a tag
751
+ delete <id> Delete a tag
752
+ set <link-id> <tag1,tag2,...> Set tags on a link (by name)
753
+
754
+ Options:
755
+ --json Output raw JSON
756
+ --help, -h Show this help
757
+
758
+ Examples:
759
+ shiori tags list
760
+ shiori tags create "design"
761
+ shiori tags update <id> --name "dev"
762
+ shiori tags delete <id>
763
+ shiori tags set <link-id> design,work`;
738
764
  async function run9(args) {
765
+ if (hasFlag(args, "--help", "-h") && !args[0]) {
766
+ console.log(HELP2);
767
+ return;
768
+ }
769
+ const subcommand = args[0];
770
+ const subArgs = args.slice(1);
771
+ switch (subcommand) {
772
+ case "list":
773
+ case "ls":
774
+ return listTags(subArgs);
775
+ case "create":
776
+ return createTag(subArgs);
777
+ case "update":
778
+ return updateTag(subArgs);
779
+ case "delete":
780
+ case "rm":
781
+ return deleteTag(subArgs);
782
+ case "set":
783
+ return setLinkTags(subArgs);
784
+ default:
785
+ if (subcommand) {
786
+ console.error(`Unknown subcommand: ${subcommand}
787
+ `);
788
+ }
789
+ console.log(HELP2);
790
+ if (subcommand) process.exit(1);
791
+ }
792
+ }
793
+ async function listTags(args) {
794
+ if (hasFlag(args, "--help", "-h")) {
795
+ console.log(`shiori tags list - List your tags
796
+
797
+ Usage: shiori tags list [options]
798
+
799
+ Options:
800
+ --json Output raw JSON
801
+ --help, -h Show this help`);
802
+ return;
803
+ }
804
+ const { data } = await api("GET", "/api/tags/");
805
+ if (hasFlag(args, "--json")) {
806
+ console.log(JSON.stringify(data, null, 2));
807
+ return;
808
+ }
809
+ const tags = data.tags;
810
+ if (tags.length === 0) {
811
+ console.log("\n No tags. Create one with: shiori tags create <name>\n");
812
+ return;
813
+ }
814
+ console.log(`
815
+ Tags: ${tags.length}
816
+ `);
817
+ for (const tag of tags) {
818
+ console.log(` ${tag.id} ${tag.name}`);
819
+ }
820
+ console.log();
821
+ }
822
+ async function createTag(args) {
823
+ if (hasFlag(args, "--help", "-h")) {
824
+ console.log(`shiori tags create - Create a tag
825
+
826
+ Usage: shiori tags create <name> [options]
827
+
828
+ Options:
829
+ --json Output raw JSON
830
+ --help, -h Show this help`);
831
+ return;
832
+ }
833
+ const name = getPositional(args);
834
+ if (!name) {
835
+ console.error("Usage: shiori tags create <name>");
836
+ process.exit(1);
837
+ }
838
+ const { data } = await api("POST", "/api/tags/", { name });
839
+ if (hasFlag(args, "--json")) {
840
+ console.log(JSON.stringify(data, null, 2));
841
+ return;
842
+ }
843
+ console.log(`Created: ${data.tag.name} (${data.tag.id})`);
844
+ }
845
+ async function updateTag(args) {
846
+ if (hasFlag(args, "--help", "-h")) {
847
+ console.log(`shiori tags update - Update a tag
848
+
849
+ Usage: shiori tags update <id> [options]
850
+
851
+ Options:
852
+ --name <name> New tag name
853
+ --json Output raw JSON
854
+ --help, -h Show this help`);
855
+ return;
856
+ }
857
+ const id = getPositional(args);
858
+ if (!id) {
859
+ console.error("Usage: shiori tags update <id> --name <name>");
860
+ process.exit(1);
861
+ }
862
+ const name = getFlag(args, "--name");
863
+ if (!name) {
864
+ console.error("Provide --name to update.");
865
+ process.exit(1);
866
+ }
867
+ const { data } = await api("PATCH", `/api/tags/${id}`, { name });
868
+ if (hasFlag(args, "--json")) {
869
+ console.log(JSON.stringify(data, null, 2));
870
+ return;
871
+ }
872
+ console.log(`Updated: ${data.tag.name} (${data.tag.id})`);
873
+ }
874
+ async function deleteTag(args) {
875
+ if (hasFlag(args, "--help", "-h")) {
876
+ console.log(`shiori tags delete - Delete a tag
877
+
878
+ Usage: shiori tags delete <id> [options]
879
+
880
+ Options:
881
+ --json Output raw JSON
882
+ --help, -h Show this help`);
883
+ return;
884
+ }
885
+ const id = getPositional(args);
886
+ if (!id) {
887
+ console.error("Usage: shiori tags delete <id>");
888
+ process.exit(1);
889
+ }
890
+ const { data } = await api("DELETE", `/api/tags/${id}`);
891
+ if (hasFlag(args, "--json")) {
892
+ console.log(JSON.stringify(data, null, 2));
893
+ return;
894
+ }
895
+ console.log("Tag deleted.");
896
+ }
897
+ async function setLinkTags(args) {
898
+ if (hasFlag(args, "--help", "-h")) {
899
+ console.log(`shiori tags set - Set tags on a link
900
+
901
+ Usage: shiori tags set <link-id> <tag1,tag2,...> [options]
902
+
903
+ Pass a comma-separated list of tag names. Tags are replaced, not appended.
904
+ Pass an empty string "" to remove all tags.
905
+
906
+ Options:
907
+ --json Output raw JSON
908
+ --help, -h Show this help`);
909
+ return;
910
+ }
911
+ const positionals = [];
912
+ for (let i = 0; i < args.length; i++) {
913
+ if (args[i].startsWith("--")) {
914
+ i++;
915
+ continue;
916
+ }
917
+ positionals.push(args[i]);
918
+ }
919
+ const linkId = positionals[0];
920
+ const tagNamesRaw = positionals[1];
921
+ if (!linkId) {
922
+ console.error("Usage: shiori tags set <link-id> <tag1,tag2,...>");
923
+ process.exit(1);
924
+ }
925
+ const tagNames = tagNamesRaw === void 0 || tagNamesRaw === "" ? [] : tagNamesRaw.split(",").map((t) => t.trim()).filter(Boolean);
926
+ const tagIds = [];
927
+ if (tagNames.length > 0) {
928
+ const { data: tagsData } = await api("GET", "/api/tags/");
929
+ const tagMap = /* @__PURE__ */ new Map();
930
+ for (const tag of tagsData.tags) {
931
+ tagMap.set(tag.name.toLowerCase(), tag.id);
932
+ }
933
+ const missing = [];
934
+ for (const name of tagNames) {
935
+ const id = tagMap.get(name.toLowerCase());
936
+ if (id) {
937
+ tagIds.push(id);
938
+ } else {
939
+ missing.push(name);
940
+ }
941
+ }
942
+ if (missing.length > 0) {
943
+ console.error(`Tags not found: ${missing.join(", ")}`);
944
+ console.error("Create them first with: shiori tags create <name>");
945
+ process.exit(1);
946
+ }
947
+ }
948
+ const { data } = await api("PUT", `/api/links/${linkId}/tags`, { tagIds });
949
+ if (hasFlag(args, "--json")) {
950
+ console.log(JSON.stringify(data, null, 2));
951
+ return;
952
+ }
953
+ if (tagIds.length === 0) {
954
+ console.log("All tags removed from link.");
955
+ } else {
956
+ console.log(`Set ${tagIds.length} tag${tagIds.length === 1 ? "" : "s"} on link.`);
957
+ }
958
+ }
959
+
960
+ // src/commands/trash.ts
961
+ async function run10(args) {
739
962
  if (hasFlag(args, "--help", "-h")) {
740
963
  console.log(`shiori trash - List or empty the trash
741
964
 
@@ -786,7 +1009,7 @@ Trashed links: ${data.links.length} of ${data.total} total
786
1009
  }
787
1010
 
788
1011
  // src/commands/update.ts
789
- async function run10(args) {
1012
+ async function run11(args) {
790
1013
  if (hasFlag(args, "--help", "-h")) {
791
1014
  console.log(`shiori update - Update links
792
1015
 
@@ -858,7 +1081,7 @@ Options:
858
1081
  }
859
1082
 
860
1083
  // src/commands/whoami.ts
861
- async function run11(args) {
1084
+ async function run12(args) {
862
1085
  if (hasFlag(args, "--help", "-h")) {
863
1086
  console.log(`shiori whoami - Show current user info
864
1087
 
@@ -894,7 +1117,7 @@ function reportError(command, error) {
894
1117
  method: "POST",
895
1118
  headers: { "Content-Type": "application/json" },
896
1119
  body: JSON.stringify({
897
- version: "0.5.0",
1120
+ version: "0.7.0",
898
1121
  command,
899
1122
  error: message,
900
1123
  platform: process.platform
@@ -940,11 +1163,12 @@ var COMMANDS = {
940
1163
  get: { run: run4, desc: "Get a link by ID (includes content)" },
941
1164
  content: { run: run2, desc: "Print link content as markdown" },
942
1165
  save: { run: run6, desc: "Save a new link" },
943
- update: { run: run10, desc: "Update a link" },
1166
+ update: { run: run11, desc: "Update a link" },
944
1167
  delete: { run: run3, desc: "Delete a link (move to trash)" },
945
- trash: { run: run9, desc: "List or empty the trash" },
1168
+ trash: { run: run10, desc: "List or empty the trash" },
946
1169
  subscriptions: { run: run8, desc: "Manage RSS subscriptions" },
947
- whoami: { run: run11, desc: "Show current user info" }
1170
+ tags: { run: run9, desc: "Manage tags" },
1171
+ whoami: { run: run12, desc: "Show current user info" }
948
1172
  };
949
1173
  function printHelp() {
950
1174
  console.log(`shiori - Manage your Shiori link library from the terminal
@@ -974,7 +1198,7 @@ async function main() {
974
1198
  return;
975
1199
  }
976
1200
  if (command === "--version" || command === "-v") {
977
- console.log("0.5.0");
1201
+ console.log("0.7.0");
978
1202
  return;
979
1203
  }
980
1204
  const cmd = COMMANDS[command];
@@ -987,7 +1211,7 @@ async function main() {
987
1211
  const cmdArgs = args.slice(1);
988
1212
  const isJson = cmdArgs.includes("--json");
989
1213
  await cmd.run(cmdArgs);
990
- checkForUpdate("0.5.0", isJson).catch(() => {
1214
+ checkForUpdate("0.7.0", isJson).catch(() => {
991
1215
  });
992
1216
  }
993
1217
  main().catch((err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shiori-sh/cli",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "CLI for managing your Shiori link library",
5
5
  "author": "Brian Lovin",
6
6
  "license": "MIT",