@fett/synology-api 0.0.1-beta.4 → 0.0.1-beta.7

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 (53) hide show
  1. package/bin/syno +6 -0
  2. package/{dist → lib}/cjs/index.js +200 -18
  3. package/lib/esm/cli/apis.js +53 -0
  4. package/lib/esm/cli/config.js +130 -0
  5. package/lib/esm/cli/helper.js +19 -0
  6. package/lib/esm/cli/index.js +30 -0
  7. package/{dist → lib}/esm/errorcodes.js +3 -3
  8. package/{dist → lib}/esm/helpers.js +5 -5
  9. package/{dist → lib}/esm/index.js +1 -0
  10. package/lib/esm/modules/AudioStation/index.js +7 -0
  11. package/{dist → lib}/esm/modules/FileStation/index.js +5 -2
  12. package/lib/esm/modules/index.js +46 -0
  13. package/lib/types/cli/apis.d.ts +6 -0
  14. package/lib/types/cli/config.d.ts +13 -0
  15. package/lib/types/cli/helper.d.ts +4 -0
  16. package/lib/types/cli/index.d.ts +1 -0
  17. package/{dist → lib}/types/errorcodes.d.ts +3 -2
  18. package/{dist → lib}/types/index.d.ts +1 -0
  19. package/lib/types/modules/AudioStation/index.d.ts +7 -0
  20. package/{dist → lib}/types/modules/FileStation/index.d.ts +4 -2
  21. package/lib/types/modules/index.d.ts +16 -0
  22. package/package.json +22 -10
  23. package/dist/esm/modules/AudioStation/index.js +0 -5
  24. package/dist/esm/modules/index.js +0 -28
  25. package/dist/types/modules/AudioStation/index.d.ts +0 -5
  26. package/dist/types/modules/index.d.ts +0 -9
  27. /package/{dist → lib}/esm/constants.js +0 -0
  28. /package/{dist → lib}/esm/core.js +0 -0
  29. /package/{dist → lib}/esm/modules/Api/Auth.js +0 -0
  30. /package/{dist → lib}/esm/modules/Api/Info.js +0 -0
  31. /package/{dist → lib}/esm/modules/Api/index.js +0 -0
  32. /package/{dist → lib}/esm/modules/AudioStation/Song.js +0 -0
  33. /package/{dist → lib}/esm/modules/FileStation/File.js +0 -0
  34. /package/{dist → lib}/esm/modules/FileStation/Info.js +0 -0
  35. /package/{dist → lib}/esm/modules/FileStation/List.js +0 -0
  36. /package/{dist → lib}/esm/types/apiInfo.js +0 -0
  37. /package/{dist → lib}/esm/types/index.js +0 -0
  38. /package/{dist → lib}/esm/types/request.js +0 -0
  39. /package/{dist → lib}/esm/utils.js +0 -0
  40. /package/{dist → lib}/types/constants.d.ts +0 -0
  41. /package/{dist → lib}/types/core.d.ts +0 -0
  42. /package/{dist → lib}/types/helpers.d.ts +0 -0
  43. /package/{dist → lib}/types/modules/Api/Auth.d.ts +0 -0
  44. /package/{dist → lib}/types/modules/Api/Info.d.ts +0 -0
  45. /package/{dist → lib}/types/modules/Api/index.d.ts +0 -0
  46. /package/{dist → lib}/types/modules/AudioStation/Song.d.ts +0 -0
  47. /package/{dist → lib}/types/modules/FileStation/File.d.ts +0 -0
  48. /package/{dist → lib}/types/modules/FileStation/Info.d.ts +0 -0
  49. /package/{dist → lib}/types/modules/FileStation/List.d.ts +0 -0
  50. /package/{dist → lib}/types/types/apiInfo.d.ts +0 -0
  51. /package/{dist → lib}/types/types/index.d.ts +0 -0
  52. /package/{dist → lib}/types/types/request.d.ts +0 -0
  53. /package/{dist → lib}/types/utils.d.ts +0 -0
package/bin/syno ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ const { loadCli } = require("../lib/cjs/index");
3
+
4
+ (async () => {
5
+ await loadCli();
6
+ })();
@@ -70,7 +70,8 @@ __export(index_exports, {
70
70
  FileStationApi: () => FileStationApi,
71
71
  SynologyApi: () => SynologyApi,
72
72
  SynologyApiInfo: () => SynologyApiInfo,
73
- default: () => index_default
73
+ default: () => index_default,
74
+ loadCli: () => loadCli
74
75
  });
75
76
  module.exports = __toCommonJS(index_exports);
76
77
 
@@ -126,10 +127,11 @@ function getSongList(params) {
126
127
  }
127
128
 
128
129
  // src/modules/AudioStation/index.ts
129
- var AudioStationMethods = {
130
+ var METHODS = {
130
131
  getSongList
131
132
  };
132
- var AudioStationKey = "AudioStation";
133
+ var SPELLING_KEY = "AudioStation";
134
+ var SIMPLIFY_KEY = "as";
133
135
 
134
136
  // src/modules/FileStation/Info.ts
135
137
  function getInfo() {
@@ -187,15 +189,22 @@ function getFileListShare() {
187
189
  }
188
190
 
189
191
  // src/modules/FileStation/index.ts
190
- var FileStationMethods = {
192
+ var METHODS2 = {
191
193
  getInfo,
192
194
  getFileList,
193
195
  getFileListShare
194
196
  };
195
- var FileStationKey = "FileStation";
197
+ var SPELLING_KEY2 = "FileStation";
198
+ var SIMPLIFY_KEY2 = "fs";
196
199
 
197
200
  // src/modules/index.ts
198
- AudioStationKey, FileStationKey;
201
+ var SynologyApiKeys = {
202
+ FileStation: SPELLING_KEY2,
203
+ fs: SIMPLIFY_KEY2,
204
+ AudioStation: SPELLING_KEY,
205
+ as: SIMPLIFY_KEY
206
+ };
207
+ SPELLING_KEY, SIMPLIFY_KEY, SPELLING_KEY2, SIMPLIFY_KEY2;
199
208
  var BaseSynologyApi = class {
200
209
  constructor() {
201
210
  }
@@ -208,14 +217,26 @@ function methodsBundler(instance, methods) {
208
217
  return output;
209
218
  }
210
219
  Object.defineProperties(BaseSynologyApi.prototype, {
211
- [FileStationKey]: {
220
+ // FileStation
221
+ [SynologyApiKeys.FileStation]: {
222
+ get() {
223
+ return methodsBundler(this, METHODS2);
224
+ }
225
+ },
226
+ [SynologyApiKeys.fs]: {
212
227
  get() {
213
- return methodsBundler(this, FileStationMethods);
228
+ return methodsBundler(this, METHODS2);
214
229
  }
215
230
  },
216
- [AudioStationKey]: {
231
+ // AudioStation
232
+ [SynologyApiKeys.AudioStation]: {
217
233
  get() {
218
- return methodsBundler(this, AudioStationMethods);
234
+ return methodsBundler(this, METHODS);
235
+ }
236
+ },
237
+ [SynologyApiKeys.as]: {
238
+ get() {
239
+ return methodsBundler(this, METHODS);
219
240
  }
220
241
  }
221
242
  });
@@ -229,22 +250,22 @@ var QUICK_CONNECT_PINGPANG_API = "/webman/pingpong.cgi?action=cors&quickconnect=
229
250
 
230
251
  // src/helpers.ts
231
252
  var getServersFromServerInfo = (serverInfo) => __async(null, null, function* () {
232
- var _a, _b;
233
- if (serverInfo.service.relay_ip) {
253
+ var _a, _b, _c, _d, _e, _f;
254
+ if ((_a = serverInfo == null ? void 0 : serverInfo.service) == null ? void 0 : _a.relay_ip) {
234
255
  const server = `http://${serverInfo.service.relay_ip}:${serverInfo.service.relay_port}`;
235
256
  const res = yield pingpang(server);
236
257
  if (res) {
237
258
  return server;
238
259
  }
239
260
  }
240
- if (serverInfo.server.external.ip) {
261
+ if ((_c = (_b = serverInfo == null ? void 0 : serverInfo.server) == null ? void 0 : _b.external) == null ? void 0 : _c.ip) {
241
262
  const server = `http://${serverInfo.server.external.ip}:${serverInfo.service.port}`;
242
263
  if (yield pingpang(server)) {
243
264
  return server;
244
265
  }
245
266
  }
246
- if ((_a = serverInfo.server.interface) == null ? void 0 : _a[0]) {
247
- const server = `http://${(_b = serverInfo.server.interface) == null ? void 0 : _b[0].ip}:${serverInfo.service.port}`;
267
+ if ((_e = (_d = serverInfo == null ? void 0 : serverInfo.server) == null ? void 0 : _d.interface) == null ? void 0 : _e[0]) {
268
+ const server = `http://${(_f = serverInfo.server.interface) == null ? void 0 : _f[0].ip}:${serverInfo.service.port}`;
248
269
  if (yield pingpang(server)) {
249
270
  return server;
250
271
  }
@@ -349,7 +370,7 @@ function getApiInfo(core) {
349
370
  var CODE_SUCCESS = 0;
350
371
  var CODE_UNKNOWN = 9999;
351
372
  var SYNOLOGY_ERROR_CODES = {
352
- [FileStationKey]: {
373
+ [SynologyApiKeys.FileStation]: {
353
374
  400: "Invalid parameter of file operation",
354
375
  401: "Unknown error of file operation",
355
376
  402: "System is too busy",
@@ -374,7 +395,7 @@ var SYNOLOGY_ERROR_CODES = {
374
395
  421: "Device or resource busy",
375
396
  599: "No such task of the file operation"
376
397
  },
377
- [AudioStationKey]: {},
398
+ [SynologyApiKeys.AudioStation]: {},
378
399
  COMMON_CODES: {
379
400
  [CODE_SUCCESS]: "Success",
380
401
  100: "Unknown error",
@@ -540,6 +561,166 @@ var SynologyApi = class extends BaseSynologyApi {
540
561
  }
541
562
  };
542
563
 
564
+ // src/cli/index.ts
565
+ var import_fs_extra2 = __toESM(require("fs-extra"));
566
+ var import_path2 = __toESM(require("path"));
567
+ var import_commander3 = require("commander");
568
+
569
+ // src/cli/config.ts
570
+ var import_fs_extra = __toESM(require("fs-extra"));
571
+ var import_path = __toESM(require("path"));
572
+ var import_os = __toESM(require("os"));
573
+ var import_commander = require("commander");
574
+ var import_chalk2 = __toESM(require("chalk"));
575
+
576
+ // src/cli/helper.ts
577
+ var import_chalk = __toESM(require("chalk"));
578
+ function printMessages(messages) {
579
+ console.log(messages.join("\n"));
580
+ }
581
+ function isLowerCaseEqual(str1, str2) {
582
+ if (str1 && str2) {
583
+ return str1.toLowerCase() === str2.toLowerCase();
584
+ }
585
+ return !str1 && !str2;
586
+ }
587
+ function padding(message = "", before = 1, after = 1) {
588
+ return new Array(before).fill(" ").join("") + message + new Array(after).fill(" ").join("");
589
+ }
590
+ function geneDashLine(message, length) {
591
+ const finalMessage = new Array(Math.max(2, length - message.length + 2)).join(
592
+ "-"
593
+ );
594
+ return padding(import_chalk.default.dim(finalMessage));
595
+ }
596
+
597
+ // src/cli/config.ts
598
+ var CONFIG_FILE_PATH = process.env.NODE_ENV === "development" ? import_path.default.join(process.cwd(), "./.userdata/.synology-api.json") : import_path.default.join(import_os.default.homedir(), "./.synology-api.json");
599
+ var loadConfig = () => __async(null, null, function* () {
600
+ if (!(yield import_fs_extra.default.pathExists(CONFIG_FILE_PATH))) {
601
+ yield import_fs_extra.default.ensureFile(CONFIG_FILE_PATH);
602
+ yield import_fs_extra.default.writeJSON(CONFIG_FILE_PATH, {
603
+ used: "",
604
+ connections: {}
605
+ });
606
+ }
607
+ const config = yield import_fs_extra.default.readJSON(CONFIG_FILE_PATH);
608
+ return config;
609
+ });
610
+ var updateConfig = (config) => __async(null, null, function* () {
611
+ yield import_fs_extra.default.writeJSON(CONFIG_FILE_PATH, config);
612
+ });
613
+ var configCmdRegister = () => {
614
+ const configCmd = import_commander.program.command("config").description("synology api config management");
615
+ configCmd.command("ls").description("List all the connection config").action(() => __async(null, null, function* () {
616
+ const config = yield loadConfig();
617
+ const keys = Object.keys(config.connections);
618
+ const dashLineLength = Math.max(...keys.map((key) => key.length)) + 3;
619
+ const messages = keys.map((key) => {
620
+ const connection = config.connections[key];
621
+ const prefix = isLowerCaseEqual(key, config.used) ? import_chalk2.default.green.bold("* ") : " ";
622
+ return prefix + key + geneDashLine(key, dashLineLength) + connection.server + ":" + connection.username + ":" + connection.password;
623
+ });
624
+ printMessages(messages);
625
+ }));
626
+ configCmd.command("add [name]").description("Add connection config").requiredOption("-s, --server <server>", "Synology server domain or QuickConnect ID ").requiredOption("-u, --username <username>", "username").requiredOption("-p, --password <password>", "password").action((name, options) => __async(null, null, function* () {
627
+ if (!name.trim()) throw new Error("Plaease input connection name");
628
+ const config = yield loadConfig();
629
+ const newConfig = __spreadProps(__spreadValues({}, config), {
630
+ connections: __spreadProps(__spreadValues({}, config.connections), {
631
+ [name]: {
632
+ server: options.server,
633
+ username: options.username,
634
+ password: options.password
635
+ }
636
+ })
637
+ });
638
+ yield updateConfig(newConfig);
639
+ }));
640
+ configCmd.command("use [name]").description("Change current connection").action((name) => __async(null, null, function* () {
641
+ const config = yield loadConfig();
642
+ if (config.used === name) return;
643
+ if (!config.connections[name]) {
644
+ console.log("Connection not found");
645
+ return;
646
+ }
647
+ config.used = name;
648
+ yield updateConfig(config);
649
+ }));
650
+ configCmd.command("del [name]").description("Remove a connection").action((name) => __async(null, null, function* () {
651
+ console.log("Remove a connection", name);
652
+ const config = yield loadConfig();
653
+ if (!config.connections[name]) {
654
+ console.log("Connection not found");
655
+ return;
656
+ }
657
+ delete config.connections[name];
658
+ if (config.used === name) {
659
+ config.used = "";
660
+ }
661
+ yield updateConfig(config);
662
+ }));
663
+ configCmd.command("rename <name> <newName>").description("Change connection name").action((name, newName) => __async(null, null, function* () {
664
+ const config = yield loadConfig();
665
+ if (!config.connections[name]) {
666
+ console.log("Connection not found");
667
+ return;
668
+ }
669
+ config.connections[newName] = config.connections[name];
670
+ delete config.connections[name];
671
+ if (config.used === name) {
672
+ config.used = newName;
673
+ }
674
+ yield updateConfig(config);
675
+ }));
676
+ };
677
+
678
+ // src/cli/apis.ts
679
+ var import_commander2 = require("commander");
680
+ var onMethodsCall = (module2) => (method, options) => __async(null, null, function* () {
681
+ var _a, _b;
682
+ const config = yield loadConfig();
683
+ const params = JSON.parse(options.params || "{}");
684
+ const pretty = options.pretty;
685
+ const synologyApi = new SynologyApi(config.connections[config.used]);
686
+ if ((_a = synologyApi[module2]) == null ? void 0 : _a[method]) {
687
+ const result = yield (_b = synologyApi[module2]) == null ? void 0 : _b[method](params);
688
+ if (pretty) {
689
+ console.log(JSON.stringify(result, null, 2));
690
+ } else {
691
+ console.log(JSON.stringify(result));
692
+ }
693
+ }
694
+ synologyApi.disconnect();
695
+ process.exit(0);
696
+ });
697
+ var apisCmdRegisterInfo = [
698
+ {
699
+ cmd: SynologyApiKeys.FileStation,
700
+ alias: SynologyApiKeys.fs
701
+ },
702
+ {
703
+ cmd: SynologyApiKeys.AudioStation,
704
+ alias: SynologyApiKeys.as
705
+ }
706
+ ];
707
+ var apiCmdRegister = () => {
708
+ apisCmdRegisterInfo.forEach((info) => {
709
+ import_commander2.program.command(`${info.cmd} [methods]`).alias(info.alias).option("-p,--params <params>", `${info.cmd} methods params`).option("--pretty", "Prettyprint JSON Output").description(`Synology ${info.cmd} method call`).action(onMethodsCall(info.cmd));
710
+ });
711
+ };
712
+
713
+ // src/cli/index.ts
714
+ function loadCli() {
715
+ return __async(this, null, function* () {
716
+ const pkg = yield import_fs_extra2.default.readJSON(import_path2.default.join(__dirname, "../../package.json"));
717
+ import_commander3.program.name("synology").usage("<command> [options]").description("synology api cli tool").version(pkg.version);
718
+ configCmdRegister();
719
+ apiCmdRegister();
720
+ import_commander3.program.parse(process.argv);
721
+ });
722
+ }
723
+
543
724
  // src/index.ts
544
725
  var index_default = SynologyApi;
545
726
  // Annotate the CommonJS export names for ESM import in node:
@@ -547,5 +728,6 @@ var index_default = SynologyApi;
547
728
  AudioStationApi,
548
729
  FileStationApi,
549
730
  SynologyApi,
550
- SynologyApiInfo
731
+ SynologyApiInfo,
732
+ loadCli
551
733
  });
@@ -0,0 +1,53 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { program } from "commander";
11
+ import { loadConfig } from "./config";
12
+ import { SynologyApi } from "../core";
13
+ import { SynologyApiKeys } from "../modules";
14
+ export const onMethodsCall = (module) => (method, options) => __awaiter(void 0, void 0, void 0, function* () {
15
+ var _a, _b;
16
+ const config = yield loadConfig();
17
+ const params = JSON.parse(options.params || "{}");
18
+ const pretty = options.pretty;
19
+ const synologyApi = new SynologyApi(config.connections[config.used]);
20
+ if ((_a = synologyApi[module]) === null || _a === void 0 ? void 0 : _a[method]) {
21
+ const result = yield ((_b = synologyApi[module]) === null || _b === void 0 ? void 0 : _b[method](params));
22
+ if (pretty) {
23
+ console.log(JSON.stringify(result, null, 2));
24
+ }
25
+ else {
26
+ console.log(JSON.stringify(result));
27
+ }
28
+ }
29
+ synologyApi.disconnect();
30
+ process.exit(0);
31
+ });
32
+ // register all modules
33
+ const apisCmdRegisterInfo = [
34
+ {
35
+ cmd: SynologyApiKeys.FileStation,
36
+ alias: SynologyApiKeys.fs,
37
+ },
38
+ {
39
+ cmd: SynologyApiKeys.AudioStation,
40
+ alias: SynologyApiKeys.as,
41
+ },
42
+ ];
43
+ export const apiCmdRegister = () => {
44
+ apisCmdRegisterInfo.forEach((info) => {
45
+ program
46
+ .command(`${info.cmd} [methods]`)
47
+ .alias(info.alias)
48
+ .option("-p,--params <params>", `${info.cmd} methods params`)
49
+ .option("--pretty", "Prettyprint JSON Output")
50
+ .description(`Synology ${info.cmd} method call`)
51
+ .action(onMethodsCall(info.cmd));
52
+ });
53
+ };
@@ -0,0 +1,130 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import fse from "fs-extra";
11
+ import path from "path";
12
+ import os from "os";
13
+ import { program } from "commander";
14
+ import chalk from "chalk";
15
+ import { isLowerCaseEqual, printMessages, geneDashLine } from "./helper";
16
+ const CONFIG_FILE_PATH = process.env.NODE_ENV === "development"
17
+ ? path.join(process.cwd(), "./.userdata/.synology-api.json") // development
18
+ : path.join(os.homedir(), "./.synology-api.json");
19
+ // load config
20
+ export const loadConfig = () => __awaiter(void 0, void 0, void 0, function* () {
21
+ if (!(yield fse.pathExists(CONFIG_FILE_PATH))) {
22
+ yield fse.ensureFile(CONFIG_FILE_PATH);
23
+ yield fse.writeJSON(CONFIG_FILE_PATH, {
24
+ used: "",
25
+ connections: {},
26
+ });
27
+ }
28
+ const config = yield fse.readJSON(CONFIG_FILE_PATH);
29
+ return config;
30
+ });
31
+ // update config
32
+ export const updateConfig = (config) => __awaiter(void 0, void 0, void 0, function* () {
33
+ yield fse.writeJSON(CONFIG_FILE_PATH, config);
34
+ });
35
+ // check config
36
+ export const checkConfig = () => __awaiter(void 0, void 0, void 0, function* () { });
37
+ export const configCmdRegister = () => {
38
+ const configCmd = program.command("config").description("synology api config management");
39
+ // list connection config
40
+ configCmd
41
+ .command("ls")
42
+ .description("List all the connection config")
43
+ .action(() => __awaiter(void 0, void 0, void 0, function* () {
44
+ const config = yield loadConfig();
45
+ const keys = Object.keys(config.connections);
46
+ const dashLineLength = Math.max(...keys.map((key) => key.length)) + 3;
47
+ const messages = keys.map((key) => {
48
+ const connection = config.connections[key];
49
+ const prefix = isLowerCaseEqual(key, config.used) ? chalk.green.bold("* ") : " ";
50
+ return (prefix +
51
+ key +
52
+ geneDashLine(key, dashLineLength) +
53
+ connection.server +
54
+ ":" +
55
+ connection.username +
56
+ ":" +
57
+ connection.password);
58
+ });
59
+ printMessages(messages);
60
+ }));
61
+ // add connection
62
+ configCmd
63
+ .command("add [name]")
64
+ .description("Add connection config")
65
+ .requiredOption("-s, --server <server>", "Synology server domain or QuickConnect ID ")
66
+ .requiredOption("-u, --username <username>", "username")
67
+ .requiredOption("-p, --password <password>", "password")
68
+ .action((name, options) => __awaiter(void 0, void 0, void 0, function* () {
69
+ if (!name.trim())
70
+ throw new Error("Plaease input connection name");
71
+ // 实际代码中应保存配置到文件
72
+ const config = yield loadConfig();
73
+ const newConfig = Object.assign(Object.assign({}, config), { connections: Object.assign(Object.assign({}, config.connections), { [name]: {
74
+ server: options.server,
75
+ username: options.username,
76
+ password: options.password,
77
+ } }) });
78
+ yield updateConfig(newConfig);
79
+ }));
80
+ // use connection
81
+ configCmd
82
+ .command("use [name]")
83
+ .description("Change current connection")
84
+ .action((name) => __awaiter(void 0, void 0, void 0, function* () {
85
+ const config = yield loadConfig();
86
+ if (config.used === name)
87
+ return;
88
+ if (!config.connections[name]) {
89
+ console.log("Connection not found");
90
+ return;
91
+ }
92
+ config.used = name;
93
+ yield updateConfig(config);
94
+ }));
95
+ // del connection
96
+ configCmd
97
+ .command("del [name]")
98
+ .description("Remove a connection")
99
+ .action((name) => __awaiter(void 0, void 0, void 0, function* () {
100
+ console.log("Remove a connection", name);
101
+ const config = yield loadConfig();
102
+ // 删除配置
103
+ if (!config.connections[name]) {
104
+ console.log("Connection not found");
105
+ return;
106
+ }
107
+ delete config.connections[name];
108
+ if (config.used === name) {
109
+ config.used = "";
110
+ }
111
+ yield updateConfig(config);
112
+ }));
113
+ // Change connection name
114
+ configCmd
115
+ .command("rename <name> <newName>")
116
+ .description("Change connection name")
117
+ .action((name, newName) => __awaiter(void 0, void 0, void 0, function* () {
118
+ const config = yield loadConfig();
119
+ if (!config.connections[name]) {
120
+ console.log("Connection not found");
121
+ return;
122
+ }
123
+ config.connections[newName] = config.connections[name];
124
+ delete config.connections[name];
125
+ if (config.used === name) {
126
+ config.used = newName;
127
+ }
128
+ yield updateConfig(config);
129
+ }));
130
+ };
@@ -0,0 +1,19 @@
1
+ import chalk from "chalk";
2
+ export function printMessages(messages) {
3
+ console.log(messages.join("\n"));
4
+ }
5
+ export function isLowerCaseEqual(str1, str2) {
6
+ if (str1 && str2) {
7
+ return str1.toLowerCase() === str2.toLowerCase();
8
+ }
9
+ return !str1 && !str2;
10
+ }
11
+ export function padding(message = '', before = 1, after = 1) {
12
+ return (new Array(before).fill(' ').join('') +
13
+ message +
14
+ new Array(after).fill(' ').join(''));
15
+ }
16
+ export function geneDashLine(message, length) {
17
+ const finalMessage = new Array(Math.max(2, length - message.length + 2)).join('-');
18
+ return padding(chalk.dim(finalMessage));
19
+ }
@@ -0,0 +1,30 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import fse from "fs-extra";
11
+ import path from "path";
12
+ import { program } from "commander";
13
+ import { configCmdRegister } from "./config";
14
+ import { apiCmdRegister } from "./apis";
15
+ export function loadCli() {
16
+ return __awaiter(this, void 0, void 0, function* () {
17
+ // git program info
18
+ const pkg = yield fse.readJSON(path.join(__dirname, "../../package.json"));
19
+ // command
20
+ program
21
+ .name("synology")
22
+ .usage("<command> [options]")
23
+ .description("synology api cli tool")
24
+ .version(pkg.version);
25
+ // register commands
26
+ configCmdRegister();
27
+ apiCmdRegister();
28
+ program.parse(process.argv);
29
+ });
30
+ }
@@ -1,9 +1,9 @@
1
- import { FileStationKey, AudioStationKey } from "./modules";
1
+ import { SynologyApiKeys } from "./modules";
2
2
  import { isUndfined } from "./utils";
3
3
  const CODE_SUCCESS = 0;
4
4
  const CODE_UNKNOWN = 9999;
5
5
  export const SYNOLOGY_ERROR_CODES = {
6
- [FileStationKey]: {
6
+ [SynologyApiKeys.FileStation]: {
7
7
  400: "Invalid parameter of file operation",
8
8
  401: "Unknown error of file operation",
9
9
  402: "System is too busy",
@@ -28,7 +28,7 @@ export const SYNOLOGY_ERROR_CODES = {
28
28
  421: "Device or resource busy",
29
29
  599: "No such task of the file operation",
30
30
  },
31
- [AudioStationKey]: {},
31
+ [SynologyApiKeys.AudioStation]: {},
32
32
  COMMON_CODES: {
33
33
  [CODE_SUCCESS]: "Success",
34
34
  100: "Unknown error",
@@ -10,9 +10,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import axios from "axios";
11
11
  import { GLOBAL_QUICK_CONNECT_URL, QUICK_CONNECT_PINGPANG_API } from "./constants";
12
12
  const getServersFromServerInfo = (serverInfo) => __awaiter(void 0, void 0, void 0, function* () {
13
- var _a, _b;
13
+ var _a, _b, _c, _d, _e, _f;
14
14
  // proxy server
15
- if (serverInfo.service.relay_ip) {
15
+ if ((_a = serverInfo === null || serverInfo === void 0 ? void 0 : serverInfo.service) === null || _a === void 0 ? void 0 : _a.relay_ip) {
16
16
  const server = `http://${serverInfo.service.relay_ip}:${serverInfo.service.relay_port}`;
17
17
  const res = yield pingpang(server);
18
18
  if (res) {
@@ -20,15 +20,15 @@ const getServersFromServerInfo = (serverInfo) => __awaiter(void 0, void 0, void
20
20
  }
21
21
  }
22
22
  // WAN IP
23
- if (serverInfo.server.external.ip) {
23
+ if ((_c = (_b = serverInfo === null || serverInfo === void 0 ? void 0 : serverInfo.server) === null || _b === void 0 ? void 0 : _b.external) === null || _c === void 0 ? void 0 : _c.ip) {
24
24
  const server = `http://${serverInfo.server.external.ip}:${serverInfo.service.port}`;
25
25
  if (yield pingpang(server)) {
26
26
  return server;
27
27
  }
28
28
  }
29
29
  // lan ip
30
- if ((_a = serverInfo.server.interface) === null || _a === void 0 ? void 0 : _a[0]) {
31
- const server = `http://${(_b = serverInfo.server.interface) === null || _b === void 0 ? void 0 : _b[0].ip}:${serverInfo.service.port}`;
30
+ if ((_e = (_d = serverInfo === null || serverInfo === void 0 ? void 0 : serverInfo.server) === null || _d === void 0 ? void 0 : _d.interface) === null || _e === void 0 ? void 0 : _e[0]) {
31
+ const server = `http://${(_f = serverInfo.server.interface) === null || _f === void 0 ? void 0 : _f[0].ip}:${serverInfo.service.port}`;
32
32
  if (yield pingpang(server)) {
33
33
  return server;
34
34
  }
@@ -1,4 +1,5 @@
1
1
  import { SynologyApi } from "./core";
2
2
  export * from "./types";
3
3
  export * from "./core";
4
+ export * from "./cli";
4
5
  export default SynologyApi;
@@ -0,0 +1,7 @@
1
+ import { getSongList } from "./Song";
2
+ export const METHODS = {
3
+ getSongList,
4
+ };
5
+ // name space
6
+ export const SPELLING_KEY = "AudioStation";
7
+ export const SIMPLIFY_KEY = "as";
@@ -3,9 +3,12 @@
3
3
  */
4
4
  import { getInfo } from "./Info";
5
5
  import { getFileList, getFileListShare } from "./List";
6
- export const FileStationMethods = {
6
+ // fs methods
7
+ export const METHODS = {
7
8
  getInfo,
8
9
  getFileList,
9
10
  getFileListShare,
10
11
  };
11
- export const FileStationKey = "FileStation";
12
+ // name space
13
+ export const SPELLING_KEY = "FileStation";
14
+ export const SIMPLIFY_KEY = "fs";
@@ -0,0 +1,46 @@
1
+ import * as AudioStation from "./AudioStation";
2
+ import * as FileStation from "./FileStation";
3
+ export const SynologyApiKeys = {
4
+ FileStation: FileStation.SPELLING_KEY,
5
+ fs: FileStation.SIMPLIFY_KEY,
6
+ AudioStation: AudioStation.SPELLING_KEY,
7
+ as: AudioStation.SIMPLIFY_KEY,
8
+ };
9
+ // export type BaseSynologyApiKeyMethods = FileStation.IKeyMethods
10
+ export class BaseSynologyApi {
11
+ constructor() { }
12
+ }
13
+ AudioStation.SPELLING_KEY, AudioStation.SIMPLIFY_KEY, FileStation.SPELLING_KEY, FileStation.SIMPLIFY_KEY;
14
+ // bind methods to BaseSynologyApi instance
15
+ function methodsBundler(instance, methods) {
16
+ const output = {};
17
+ for (const key in methods) {
18
+ output[key] = methods[key].bind(instance);
19
+ }
20
+ return output;
21
+ }
22
+ // proxy methods namespace to BaseSynologyApi instance
23
+ Object.defineProperties(BaseSynologyApi.prototype, {
24
+ // FileStation
25
+ [SynologyApiKeys.FileStation]: {
26
+ get() {
27
+ return methodsBundler(this, FileStation.METHODS);
28
+ },
29
+ },
30
+ [SynologyApiKeys.fs]: {
31
+ get() {
32
+ return methodsBundler(this, FileStation.METHODS);
33
+ },
34
+ },
35
+ // AudioStation
36
+ [SynologyApiKeys.AudioStation]: {
37
+ get() {
38
+ return methodsBundler(this, AudioStation.METHODS);
39
+ },
40
+ },
41
+ [SynologyApiKeys.as]: {
42
+ get() {
43
+ return methodsBundler(this, AudioStation.METHODS);
44
+ },
45
+ },
46
+ });
@@ -0,0 +1,6 @@
1
+ export type MethodOptions = {
2
+ params?: string;
3
+ pretty?: boolean;
4
+ };
5
+ export declare const onMethodsCall: (module: string) => (method: string, options: MethodOptions) => Promise<never>;
6
+ export declare const apiCmdRegister: () => void;
@@ -0,0 +1,13 @@
1
+ export type ConfigEntry = {
2
+ server: string;
3
+ username: string;
4
+ password: string;
5
+ };
6
+ export type Config = {
7
+ used: string;
8
+ connections: Record<string, ConfigEntry>;
9
+ };
10
+ export declare const loadConfig: () => Promise<Config>;
11
+ export declare const updateConfig: (config: Config) => Promise<void>;
12
+ export declare const checkConfig: () => Promise<void>;
13
+ export declare const configCmdRegister: () => void;
@@ -0,0 +1,4 @@
1
+ export declare function printMessages(messages: string[]): void;
2
+ export declare function isLowerCaseEqual(str1: string, str2: string): boolean;
3
+ export declare function padding(message?: string, before?: number, after?: number): string;
4
+ export declare function geneDashLine(message: string, length: number): string;
@@ -0,0 +1 @@
1
+ export declare function loadCli(): Promise<void>;
@@ -1,6 +1,7 @@
1
+ import { SynologyApiKeys } from "./modules";
1
2
  import { SynologyApiResponse } from "./types";
2
3
  export declare const SYNOLOGY_ERROR_CODES: {
3
- FileStation: {
4
+ [SynologyApiKeys.FileStation]: {
4
5
  400: string;
5
6
  401: string;
6
7
  402: string;
@@ -25,7 +26,7 @@ export declare const SYNOLOGY_ERROR_CODES: {
25
26
  421: string;
26
27
  599: string;
27
28
  };
28
- AudioStation: {};
29
+ [SynologyApiKeys.AudioStation]: {};
29
30
  COMMON_CODES: {
30
31
  0: string;
31
32
  100: string;
@@ -1,4 +1,5 @@
1
1
  import { SynologyApi } from "./core";
2
2
  export * from "./types";
3
3
  export * from "./core";
4
+ export * from "./cli";
4
5
  export default SynologyApi;
@@ -0,0 +1,7 @@
1
+ import { getSongList } from "./Song";
2
+ export declare const METHODS: {
3
+ getSongList: typeof getSongList;
4
+ };
5
+ export declare const SPELLING_KEY = "AudioStation";
6
+ export declare const SIMPLIFY_KEY = "as";
7
+ export type TMethods = typeof METHODS;
@@ -3,9 +3,11 @@
3
3
  */
4
4
  import { getInfo } from "./Info";
5
5
  import { getFileList, getFileListShare } from "./List";
6
- export declare const FileStationMethods: {
6
+ export declare const METHODS: {
7
7
  getInfo: typeof getInfo;
8
8
  getFileList: typeof getFileList;
9
9
  getFileListShare: typeof getFileListShare;
10
10
  };
11
- export declare const FileStationKey = "FileStation";
11
+ export declare const SPELLING_KEY = "FileStation";
12
+ export declare const SIMPLIFY_KEY = "fs";
13
+ export type TMethods = typeof METHODS;
@@ -0,0 +1,16 @@
1
+ import * as AudioStation from "./AudioStation";
2
+ import * as FileStation from "./FileStation";
3
+ export declare const SynologyApiKeys: {
4
+ FileStation: string;
5
+ fs: string;
6
+ AudioStation: string;
7
+ as: string;
8
+ };
9
+ export type SynologyApiMethods = FileStation.TMethods | AudioStation.TMethods;
10
+ export declare class BaseSynologyApi {
11
+ [AudioStation.SPELLING_KEY]: AudioStation.TMethods;
12
+ [AudioStation.SIMPLIFY_KEY]: AudioStation.TMethods;
13
+ [FileStation.SPELLING_KEY]: FileStation.TMethods;
14
+ [FileStation.SIMPLIFY_KEY]: FileStation.TMethods;
15
+ constructor();
16
+ }
package/package.json CHANGED
@@ -1,18 +1,23 @@
1
1
  {
2
2
  "name": "@fett/synology-api",
3
- "version": "0.0.1-beta.4",
3
+ "version": "0.0.1-beta.7",
4
4
  "description": "synology api for nodejs",
5
- "module": "./dist/esm/index.js",
6
- "main": "./dist/cjs/index.js",
7
- "types": "./dist/types/index.d.ts",
5
+ "module": "./lib/esm/index.js",
6
+ "main": "./lib/cjs/index.js",
7
+ "types": "./lib/types/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
- "require": "./dist/cjs/index.js",
11
- "import": "./dist/esm/index.js"
10
+ "require": "./lib/cjs/index.js",
11
+ "import": "./lib/esm/index.js"
12
12
  }
13
13
  },
14
+ "bin": {
15
+ "synology": "./bin/syno",
16
+ "syno": "./bin/syno"
17
+ },
14
18
  "files": [
15
- "dist"
19
+ "lib",
20
+ "bin"
16
21
  ],
17
22
  "author": "ChrisSong1994 <https://github.com/ChrisSong1994>",
18
23
  "keywords": [
@@ -26,11 +31,12 @@
26
31
  "commonjs"
27
32
  ],
28
33
  "scripts": {
29
- "dev": "tsc --sourceMap --watch && tsc-alias",
34
+ "dev:esm": "tsc --sourceMap --watch && tsc-alias",
35
+ "dev:cjs": "tsup --config tsup.config.ts --watch --env.NODE_ENV development",
30
36
  "build:cjs": "tsup --config tsup.config.ts",
31
37
  "build:esm": "tsc && tsc-alias",
32
38
  "build": "npm run clean && npm run build:cjs && npm run build:esm",
33
- "clean": "rimraf dist",
39
+ "clean": "rimraf lib",
34
40
  "lint": "eslint src --ext .ts --fix",
35
41
  "prettier": "prettier --write 'src/**/*.ts'",
36
42
  "format": "npm run prettier && npm run lint",
@@ -43,7 +49,9 @@
43
49
  "packageManager": "pnpm@10.8.1",
44
50
  "devDependencies": {
45
51
  "@eslint/js": "^9.26.0",
52
+ "cross-env": "^7.0.3",
46
53
  "eslint": "9.25.1",
54
+ "execa": "^9.6.0",
47
55
  "globals": "^16.1.0",
48
56
  "prettier": "3.5.3",
49
57
  "rimraf": "^6.0.1",
@@ -56,6 +64,10 @@
56
64
  "vitest": "^3.1.3"
57
65
  },
58
66
  "dependencies": {
59
- "axios": "^1.9.0"
67
+ "axios": "^1.9.0",
68
+ "chalk": "^5.4.1",
69
+ "commander": "^14.0.0",
70
+ "fs-extra": "^11.3.0",
71
+ "ora": "^8.2.0"
60
72
  }
61
73
  }
@@ -1,5 +0,0 @@
1
- import { getSongList } from "./Song";
2
- export const AudioStationMethods = {
3
- getSongList,
4
- };
5
- export const AudioStationKey = "AudioStation";
@@ -1,28 +0,0 @@
1
- import { AudioStationKey, AudioStationMethods } from "./AudioStation";
2
- import { FileStationKey, FileStationMethods } from "./FileStation";
3
- export { AudioStationKey } from "./AudioStation";
4
- export { FileStationKey } from "./FileStation";
5
- export class BaseSynologyApi {
6
- constructor() { }
7
- }
8
- // bind methods to BaseSynologyApi instance
9
- function methodsBundler(instance, methods) {
10
- const output = {};
11
- for (const key in methods) {
12
- output[key] = methods[key].bind(instance);
13
- }
14
- return output;
15
- }
16
- // proxy methods namespace to BaseSynologyApi instance
17
- Object.defineProperties(BaseSynologyApi.prototype, {
18
- [FileStationKey]: {
19
- get() {
20
- return methodsBundler(this, FileStationMethods);
21
- },
22
- },
23
- [AudioStationKey]: {
24
- get() {
25
- return methodsBundler(this, AudioStationMethods);
26
- },
27
- },
28
- });
@@ -1,5 +0,0 @@
1
- import { getSongList } from "./Song";
2
- export declare const AudioStationMethods: {
3
- getSongList: typeof getSongList;
4
- };
5
- export declare const AudioStationKey = "AudioStation";
@@ -1,9 +0,0 @@
1
- import { AudioStationKey, AudioStationMethods } from "./AudioStation";
2
- import { FileStationKey, FileStationMethods } from "./FileStation";
3
- export { AudioStationKey } from "./AudioStation";
4
- export { FileStationKey } from "./FileStation";
5
- export declare class BaseSynologyApi {
6
- [AudioStationKey]: typeof AudioStationMethods;
7
- [FileStationKey]: typeof FileStationMethods;
8
- constructor();
9
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes