@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.
- package/README.md +7 -0
- package/dist/index.js +234 -10
- 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/
|
|
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
|
|
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
|
|
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.
|
|
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:
|
|
1166
|
+
update: { run: run11, desc: "Update a link" },
|
|
944
1167
|
delete: { run: run3, desc: "Delete a link (move to trash)" },
|
|
945
|
-
trash: { run:
|
|
1168
|
+
trash: { run: run10, desc: "List or empty the trash" },
|
|
946
1169
|
subscriptions: { run: run8, desc: "Manage RSS subscriptions" },
|
|
947
|
-
|
|
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.
|
|
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.
|
|
1214
|
+
checkForUpdate("0.7.0", isJson).catch(() => {
|
|
991
1215
|
});
|
|
992
1216
|
}
|
|
993
1217
|
main().catch((err) => {
|