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

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 (36) hide show
  1. package/README.md +7 -3
  2. package/dist/cjs/index.js +234 -24
  3. package/dist/esm/constants.js +3 -2
  4. package/dist/esm/core.js +11 -2
  5. package/dist/esm/errorcodes.js +97 -0
  6. package/dist/esm/index.js +1 -0
  7. package/dist/esm/modules/Api/Auth.js +3 -3
  8. package/dist/esm/modules/Api/Info.js +2 -2
  9. package/dist/esm/modules/AudioStation/{Song/index.js → Song.js} +3 -10
  10. package/dist/esm/modules/AudioStation/index.js +1 -1
  11. package/dist/esm/modules/FileStation/File.js +0 -0
  12. package/dist/esm/modules/FileStation/Info.js +20 -0
  13. package/dist/esm/modules/FileStation/List.js +32 -0
  14. package/dist/esm/modules/FileStation/index.js +11 -0
  15. package/dist/esm/modules/index.js +11 -3
  16. package/dist/esm/types/apiInfo.js +42 -0
  17. package/dist/esm/types/index.js +2 -1
  18. package/dist/esm/utils.js +6 -0
  19. package/dist/types/constants.d.ts +3 -2
  20. package/dist/types/core.d.ts +1 -1
  21. package/dist/types/errorcodes.d.ts +93 -0
  22. package/dist/types/index.d.ts +1 -0
  23. package/dist/types/modules/AudioStation/{Song/types.d.ts → Song.d.ts} +5 -1
  24. package/dist/types/modules/FileStation/File.d.ts +0 -0
  25. package/dist/types/modules/FileStation/Info.d.ts +11 -0
  26. package/dist/types/modules/FileStation/List.d.ts +59 -0
  27. package/dist/types/modules/FileStation/index.d.ts +11 -0
  28. package/dist/types/modules/index.d.ts +4 -0
  29. package/dist/types/types/apiInfo.d.ts +39 -0
  30. package/dist/types/types/index.d.ts +2 -1
  31. package/dist/types/types/{API.d.ts → request.d.ts} +3 -4
  32. package/dist/types/utils.d.ts +2 -0
  33. package/package.json +1 -1
  34. package/dist/esm/modules/AudioStation/Song/types.js +0 -1
  35. package/dist/types/modules/AudioStation/Song/index.d.ts +0 -5
  36. /package/dist/esm/types/{API.js → request.js} +0 -0
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # synology-api
1
+ # Synology Api
2
2
 
3
3
  nodejs synology api wrapper
4
4
 
@@ -14,9 +14,13 @@ const synologyApi = new SynologyApi(
14
14
  password: "password",
15
15
  );
16
16
 
17
- // Connect to the server
18
- await synologyApi.connect();
17
+ // you can now use the api by calling the methods
18
+ const info = await synologyApi.FileStation.getInfo();
19
19
 
20
20
  ```
21
21
 
22
22
  ## API
23
+
24
+ ### FileStation
25
+
26
+ ### AudioStation
package/dist/cjs/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  var __create = Object.create;
2
2
  var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
7
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
8
  var __getProtoOf = Object.getPrototypeOf;
@@ -18,6 +20,7 @@ var __spreadValues = (a, b) => {
18
20
  }
19
21
  return a;
20
22
  };
23
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21
24
  var __export = (target, all) => {
22
25
  for (var name in all)
23
26
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -63,7 +66,10 @@ var __async = (__this, __arguments, generator) => {
63
66
  // src/index.ts
64
67
  var index_exports = {};
65
68
  __export(index_exports, {
69
+ AudioStationApi: () => AudioStationApi,
70
+ FileStationApi: () => FileStationApi,
66
71
  SynologyApi: () => SynologyApi,
72
+ SynologyApiInfo: () => SynologyApiInfo,
67
73
  default: () => index_default
68
74
  });
69
75
  module.exports = __toCommonJS(index_exports);
@@ -71,16 +77,49 @@ module.exports = __toCommonJS(index_exports);
71
77
  // src/core.ts
72
78
  var import_axios4 = __toESM(require("axios"));
73
79
 
74
- // src/modules/AudioStation/Song/index.ts
80
+ // src/types/apiInfo.ts
81
+ var SynologyApiInfo = /* @__PURE__ */ ((SynologyApiInfo2) => {
82
+ SynologyApiInfo2["Auth"] = "SYNO.API.Auth";
83
+ SynologyApiInfo2["Info"] = "SYNO.API.Info";
84
+ SynologyApiInfo2["OTP"] = "SYNO.API.OTP";
85
+ return SynologyApiInfo2;
86
+ })(SynologyApiInfo || {});
87
+ var AudioStationApi = /* @__PURE__ */ ((AudioStationApi2) => {
88
+ AudioStationApi2["Song"] = "SYNO.AudioStation.Song";
89
+ AudioStationApi2["Album"] = "SYNO.AudioStation.Album";
90
+ AudioStationApi2["Artist"] = "SYNO.AudioStation.Artist";
91
+ AudioStationApi2["Genre"] = "SYNO.AudioStation.Genre";
92
+ AudioStationApi2["Playlist"] = "SYNO.AudioStation.Playlist";
93
+ AudioStationApi2["Folder"] = "SYNO.AudioStation.Folder";
94
+ AudioStationApi2["Cover"] = "SYNO.AudioStation.Cover";
95
+ AudioStationApi2["Download"] = "SYNO.AudioStation.Download";
96
+ AudioStationApi2["Info"] = "SYNO.AudioStation.Info";
97
+ AudioStationApi2["Lyrics"] = "SYNO.AudioStation.Lyrics";
98
+ AudioStationApi2["LyricsSearch"] = "SYNO.AudioStation.LyricsSearch";
99
+ AudioStationApi2["Radio"] = "SYNO.AudioStation.Radio";
100
+ AudioStationApi2["Stream"] = "SYNO.AudioStation.Stream";
101
+ AudioStationApi2["Tag"] = "SYNO.AudioStation.Tag";
102
+ return AudioStationApi2;
103
+ })(AudioStationApi || {});
104
+ var FileStationApi = /* @__PURE__ */ ((FileStationApi2) => {
105
+ FileStationApi2["File"] = "SYNO.FileStation.File";
106
+ FileStationApi2["Info"] = "SYNO.FileStation.Info";
107
+ FileStationApi2["List"] = "SYNO.FileStation.List";
108
+ FileStationApi2["Quota"] = "SYNO.FileStation.Quota";
109
+ FileStationApi2["Share"] = "SYNO.FileStation.Share";
110
+ FileStationApi2["Thumb"] = "SYNO.FileStation.Thumb";
111
+ FileStationApi2["Upload"] = "SYNO.FileStation.Upload";
112
+ return FileStationApi2;
113
+ })(FileStationApi || {});
114
+
115
+ // src/modules/AudioStation/Song.ts
75
116
  function getSongList(params) {
76
117
  return __async(this, null, function* () {
77
- const res = yield this.run("SYNO.AudioStation.Song", {
78
- params: {
118
+ const res = yield this.run("SYNO.AudioStation.Song" /* Song */, {
119
+ params: __spreadValues({
79
120
  method: "list",
80
- library: "all",
81
- limit: params.limit,
82
- offset: params.offset
83
- }
121
+ library: "all"
122
+ }, params)
84
123
  });
85
124
  return res.data;
86
125
  });
@@ -92,7 +131,75 @@ var AudioStationMethods = {
92
131
  };
93
132
  var AudioStationKey = "AudioStation";
94
133
 
134
+ // src/modules/FileStation/Info.ts
135
+ function getInfo() {
136
+ return __async(this, null, function* () {
137
+ const res = yield this.run("SYNO.FileStation.Info" /* Info */, {
138
+ params: {
139
+ method: "get"
140
+ }
141
+ });
142
+ return res.data;
143
+ });
144
+ }
145
+
146
+ // src/utils.ts
147
+ function isHttpUrl(url) {
148
+ return /^https?:\/\//.test(url);
149
+ }
150
+ function isUndfined(value) {
151
+ return value === void 0;
152
+ }
153
+ function getApiKey(apiName) {
154
+ return apiName.split(".")[1];
155
+ }
156
+
157
+ // src/modules/FileStation/List.ts
158
+ function getFileList() {
159
+ return __async(this, arguments, function* (params = {}) {
160
+ const { additional = ["real_path", "size", "owner", "time"], filetype = "all" } = params;
161
+ if (isUndfined(params.folder_path)) {
162
+ throw new Error("folder_path is required");
163
+ }
164
+ const res = yield this.run("SYNO.FileStation.List" /* List */, {
165
+ params: __spreadValues({
166
+ method: "list",
167
+ additional: JSON.stringify(additional),
168
+ filetype,
169
+ folder_path: params.folder_path
170
+ }, params)
171
+ });
172
+ return res.data;
173
+ });
174
+ }
175
+ function getFileListShare() {
176
+ return __async(this, arguments, function* (params = {}) {
177
+ const { additional = ["real_path", "size", "owner", "time"], onlywritable = false } = params;
178
+ const res = yield this.run("SYNO.FileStation.List" /* List */, {
179
+ params: __spreadValues({
180
+ method: "list_share",
181
+ additional: JSON.stringify(additional),
182
+ onlywritable
183
+ }, params)
184
+ });
185
+ return res.data;
186
+ });
187
+ }
188
+
189
+ // src/modules/FileStation/index.ts
190
+ var FileStationMethods = {
191
+ getInfo,
192
+ getFileList,
193
+ getFileListShare
194
+ };
195
+ var FileStationKey = "FileStation";
196
+
95
197
  // src/modules/index.ts
198
+ AudioStationKey, FileStationKey;
199
+ var BaseSynologyApi = class {
200
+ constructor() {
201
+ }
202
+ };
96
203
  function methodsBundler(instance, methods) {
97
204
  const output = {};
98
205
  for (const key in methods) {
@@ -100,12 +207,12 @@ function methodsBundler(instance, methods) {
100
207
  }
101
208
  return output;
102
209
  }
103
- AudioStationKey;
104
- var BaseSynologyApi = class {
105
- constructor() {
106
- }
107
- };
108
210
  Object.defineProperties(BaseSynologyApi.prototype, {
211
+ [FileStationKey]: {
212
+ get() {
213
+ return methodsBundler(this, FileStationMethods);
214
+ }
215
+ },
109
216
  [AudioStationKey]: {
110
217
  get() {
111
218
  return methodsBundler(this, AudioStationMethods);
@@ -113,17 +220,10 @@ Object.defineProperties(BaseSynologyApi.prototype, {
113
220
  }
114
221
  });
115
222
 
116
- // src/utils.ts
117
- function isHttpUrl(url) {
118
- return /^https?:\/\//.test(url);
119
- }
120
-
121
223
  // src/helpers.ts
122
224
  var import_axios = __toESM(require("axios"));
123
225
 
124
226
  // src/constants.ts
125
- var SYNOLOGY_API_AUTH = "SYNO.API.Auth";
126
- var SYNOLOGY_API_INFO = "SYNO.API.Info";
127
227
  var GLOBAL_QUICK_CONNECT_URL = "https://global.quickconnect.cn/Serv.php";
128
228
  var QUICK_CONNECT_PINGPANG_API = "/webman/pingpong.cgi?action=cors&quickconnect=true";
129
229
 
@@ -197,7 +297,7 @@ var import_axios2 = __toESM(require("axios"));
197
297
  function login(core) {
198
298
  return __async(this, null, function* () {
199
299
  const params = {
200
- api: SYNOLOGY_API_AUTH,
300
+ api: "SYNO.API.Auth" /* Auth */,
201
301
  version: 6,
202
302
  method: "login",
203
303
  account: core.username,
@@ -215,7 +315,7 @@ function login(core) {
215
315
  function logout(core) {
216
316
  return __async(this, null, function* () {
217
317
  const params = {
218
- api: SYNOLOGY_API_AUTH,
318
+ api: "SYNO.API.Auth" /* Auth */,
219
319
  version: 6,
220
320
  method: "logout"
221
321
  };
@@ -232,7 +332,7 @@ var import_axios3 = __toESM(require("axios"));
232
332
  function getApiInfo(core) {
233
333
  return __async(this, null, function* () {
234
334
  const params = {
235
- api: SYNOLOGY_API_INFO,
335
+ api: "SYNO.API.Info" /* Info */,
236
336
  version: 1,
237
337
  method: "query"
238
338
  };
@@ -245,6 +345,106 @@ function getApiInfo(core) {
245
345
  });
246
346
  }
247
347
 
348
+ // src/errorcodes.ts
349
+ var CODE_SUCCESS = 0;
350
+ var CODE_UNKNOWN = 9999;
351
+ var SYNOLOGY_ERROR_CODES = {
352
+ [FileStationKey]: {
353
+ 400: "Invalid parameter of file operation",
354
+ 401: "Unknown error of file operation",
355
+ 402: "System is too busy",
356
+ 403: "Invalid user does this file operation",
357
+ 404: "Invalid group does this file operation",
358
+ 405: "Invalid user and group does this file operation",
359
+ 406: "Can't get user/group information from the account server",
360
+ 407: "Operation not permitted",
361
+ 408: "No such file or directory",
362
+ 409: "Non-supported file system",
363
+ 410: "Failed to connect internet-based file system (e.g., CIFS)",
364
+ 411: "Read-only file system",
365
+ 412: "Filename too long in the non-encrypted file system",
366
+ 413: "Filename too long in the encrypted file system",
367
+ 414: "File already exists",
368
+ 415: "Disk quota exceeded",
369
+ 416: "No space left on device",
370
+ 417: "Input/output error",
371
+ 418: "Illegal name or path",
372
+ 419: "Illegal file name",
373
+ 420: "Illegal file name on FAT file system",
374
+ 421: "Device or resource busy",
375
+ 599: "No such task of the file operation"
376
+ },
377
+ [AudioStationKey]: {},
378
+ COMMON_CODES: {
379
+ [CODE_SUCCESS]: "Success",
380
+ 100: "Unknown error",
381
+ 101: "No parameter of API, method or version",
382
+ 102: "The requested API does not exist",
383
+ 103: "The requested method does not exist",
384
+ 104: "The requested version does not support the functionality",
385
+ 105: "The logged in session does not have permission",
386
+ 106: "Session timeout",
387
+ 107: "Session interrupted by duplicated login",
388
+ 108: "Failed to upload the file",
389
+ 109: "The network connection is unstable or the system is busy",
390
+ 110: "The network connection is unstable or the system is busy",
391
+ 111: "The network connection is unstable or the system is busy",
392
+ 112: "Preserve for other purpose",
393
+ 113: "Preserve for other purpose",
394
+ 114: "Lost parameters for this API",
395
+ 115: "Not allowed to upload a file",
396
+ 116: "Not allowed to perform for a demo site",
397
+ 117: "The network connection is unstable or the system is busy",
398
+ 118: "The network connection is unstable or the system is busy",
399
+ 119: "Invalid session / SID not found.",
400
+ // # 120-149 Preserve for other purpose
401
+ 120: "Preserve for other purpose",
402
+ 121: "Preserve for other purpose",
403
+ 122: "Preserve for other purpose",
404
+ 123: "Preserve for other purpose",
405
+ 124: "Preserve for other purpose",
406
+ 125: "Preserve for other purpose",
407
+ 126: "Preserve for other purpose",
408
+ 127: "Preserve for other purpose",
409
+ 128: "Preserve for other purpose",
410
+ 129: "Preserve for other purpose",
411
+ 130: "Preserve for other purpose",
412
+ 131: "Preserve for other purpose",
413
+ 132: "Preserve for other purpose",
414
+ 133: "Preserve for other purpose",
415
+ 134: "Preserve for other purpose",
416
+ 135: "Preserve for other purpose",
417
+ 136: "Preserve for other purpose",
418
+ 137: "Preserve for other purpose",
419
+ 138: "Preserve for other purpose",
420
+ 139: "Preserve for other purpose",
421
+ 140: "Preserve for other purpose",
422
+ 141: "Preserve for other purpose",
423
+ 142: "Preserve for other purpose",
424
+ 143: "Preserve for other purpose",
425
+ 144: "Preserve for other purpose",
426
+ 145: "Preserve for other purpose",
427
+ 146: "Preserve for other purpose",
428
+ 147: "Preserve for other purpose",
429
+ 148: "Preserve for other purpose",
430
+ 149: "Preserve for other purpose",
431
+ 150: "Request source IP does not match the login IP",
432
+ 160: "Insufficient application privilege",
433
+ [CODE_UNKNOWN]: "Unknown error"
434
+ }
435
+ };
436
+ var resWithErrorCode = (apiKey, res) => {
437
+ var _a, _b;
438
+ const errorCodes = SYNOLOGY_ERROR_CODES[apiKey];
439
+ const code = (_a = res == null ? void 0 : res.error) == null ? void 0 : _a.code;
440
+ if (isUndfined(code)) return res;
441
+ return __spreadProps(__spreadValues({}, res), {
442
+ error: __spreadProps(__spreadValues({}, res.error), {
443
+ message: ((_b = res == null ? void 0 : res.error) == null ? void 0 : _b.message) || (errorCodes == null ? void 0 : errorCodes[code]) || "Unknown error"
444
+ })
445
+ });
446
+ };
447
+
248
448
  // src/core.ts
249
449
  var SynologyApi = class extends BaseSynologyApi {
250
450
  constructor(options) {
@@ -308,7 +508,10 @@ var SynologyApi = class extends BaseSynologyApi {
308
508
  run(apiName, options) {
309
509
  return __async(this, null, function* () {
310
510
  if (!this.isConnecting) {
311
- throw new Error("Not connected");
511
+ const res = yield this.connect();
512
+ if (!res) {
513
+ throw new Error("Not connected");
514
+ }
312
515
  }
313
516
  if (!this.hasApi(apiName)) {
314
517
  throw new Error(`${apiName} not found`);
@@ -328,6 +531,10 @@ var SynologyApi = class extends BaseSynologyApi {
328
531
  if (method === "post") {
329
532
  result = yield import_axios4.default.post(url, { params: externalParams, data, headers });
330
533
  }
534
+ const apiKey = getApiKey(apiName);
535
+ if (!isUndfined(apiKey)) {
536
+ result.data = resWithErrorCode(apiKey, result.data);
537
+ }
331
538
  return result;
332
539
  });
333
540
  }
@@ -337,5 +544,8 @@ var SynologyApi = class extends BaseSynologyApi {
337
544
  var index_default = SynologyApi;
338
545
  // Annotate the CommonJS export names for ESM import in node:
339
546
  0 && (module.exports = {
340
- SynologyApi
547
+ AudioStationApi,
548
+ FileStationApi,
549
+ SynologyApi,
550
+ SynologyApiInfo
341
551
  });
@@ -1,4 +1,5 @@
1
- export const SYNOLOGY_API_AUTH = "SYNO.API.Auth";
2
- export const SYNOLOGY_API_INFO = "SYNO.API.Info";
1
+ /**
2
+ * synology constants
3
+ */
3
4
  export const GLOBAL_QUICK_CONNECT_URL = "https://global.quickconnect.cn/Serv.php";
4
5
  export const QUICK_CONNECT_PINGPANG_API = "/webman/pingpong.cgi?action=cors&quickconnect=true";
package/dist/esm/core.js CHANGED
@@ -10,9 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  // reference: https://kb.synology.com/zh-tw/DSM/tutorial/What_websites_does_Synology_NAS_connect_to_when_running_services_or_updating_software
11
11
  import axios from "axios";
12
12
  import { BaseSynologyApi } from "./modules";
13
- import { isHttpUrl } from "./utils";
13
+ import { isHttpUrl, getApiKey, isUndfined } from "./utils";
14
14
  import { getServerInfo } from "./helpers";
15
15
  import { login, logout, getApiInfo } from "./modules/Api";
16
+ import { resWithErrorCode } from "./errorcodes";
16
17
  export class SynologyApi extends BaseSynologyApi {
17
18
  constructor(options) {
18
19
  super();
@@ -80,7 +81,10 @@ export class SynologyApi extends BaseSynologyApi {
80
81
  run(apiName, options) {
81
82
  return __awaiter(this, void 0, void 0, function* () {
82
83
  if (!this.isConnecting) {
83
- throw new Error("Not connected");
84
+ const res = yield this.connect();
85
+ if (!res) {
86
+ throw new Error("Not connected");
87
+ }
84
88
  }
85
89
  if (!this.hasApi(apiName)) {
86
90
  throw new Error(`${apiName} not found`);
@@ -96,6 +100,11 @@ export class SynologyApi extends BaseSynologyApi {
96
100
  if (method === "post") {
97
101
  result = yield axios.post(url, { params: externalParams, data, headers });
98
102
  }
103
+ // match error code msg
104
+ const apiKey = getApiKey(apiName);
105
+ if (!isUndfined(apiKey)) {
106
+ result.data = resWithErrorCode(apiKey, result.data);
107
+ }
99
108
  return result;
100
109
  });
101
110
  }
@@ -0,0 +1,97 @@
1
+ import { FileStationKey, AudioStationKey } from "./modules";
2
+ import { isUndfined } from "./utils";
3
+ const CODE_SUCCESS = 0;
4
+ const CODE_UNKNOWN = 9999;
5
+ export const SYNOLOGY_ERROR_CODES = {
6
+ [FileStationKey]: {
7
+ 400: "Invalid parameter of file operation",
8
+ 401: "Unknown error of file operation",
9
+ 402: "System is too busy",
10
+ 403: "Invalid user does this file operation",
11
+ 404: "Invalid group does this file operation",
12
+ 405: "Invalid user and group does this file operation",
13
+ 406: "Can't get user/group information from the account server",
14
+ 407: "Operation not permitted",
15
+ 408: "No such file or directory",
16
+ 409: "Non-supported file system",
17
+ 410: "Failed to connect internet-based file system (e.g., CIFS)",
18
+ 411: "Read-only file system",
19
+ 412: "Filename too long in the non-encrypted file system",
20
+ 413: "Filename too long in the encrypted file system",
21
+ 414: "File already exists",
22
+ 415: "Disk quota exceeded",
23
+ 416: "No space left on device",
24
+ 417: "Input/output error",
25
+ 418: "Illegal name or path",
26
+ 419: "Illegal file name",
27
+ 420: "Illegal file name on FAT file system",
28
+ 421: "Device or resource busy",
29
+ 599: "No such task of the file operation",
30
+ },
31
+ [AudioStationKey]: {},
32
+ COMMON_CODES: {
33
+ [CODE_SUCCESS]: "Success",
34
+ 100: "Unknown error",
35
+ 101: "No parameter of API, method or version",
36
+ 102: "The requested API does not exist",
37
+ 103: "The requested method does not exist",
38
+ 104: "The requested version does not support the functionality",
39
+ 105: "The logged in session does not have permission",
40
+ 106: "Session timeout",
41
+ 107: "Session interrupted by duplicated login",
42
+ 108: "Failed to upload the file",
43
+ 109: "The network connection is unstable or the system is busy",
44
+ 110: "The network connection is unstable or the system is busy",
45
+ 111: "The network connection is unstable or the system is busy",
46
+ 112: "Preserve for other purpose",
47
+ 113: "Preserve for other purpose",
48
+ 114: "Lost parameters for this API",
49
+ 115: "Not allowed to upload a file",
50
+ 116: "Not allowed to perform for a demo site",
51
+ 117: "The network connection is unstable or the system is busy",
52
+ 118: "The network connection is unstable or the system is busy",
53
+ 119: "Invalid session / SID not found.",
54
+ // # 120-149 Preserve for other purpose
55
+ 120: "Preserve for other purpose",
56
+ 121: "Preserve for other purpose",
57
+ 122: "Preserve for other purpose",
58
+ 123: "Preserve for other purpose",
59
+ 124: "Preserve for other purpose",
60
+ 125: "Preserve for other purpose",
61
+ 126: "Preserve for other purpose",
62
+ 127: "Preserve for other purpose",
63
+ 128: "Preserve for other purpose",
64
+ 129: "Preserve for other purpose",
65
+ 130: "Preserve for other purpose",
66
+ 131: "Preserve for other purpose",
67
+ 132: "Preserve for other purpose",
68
+ 133: "Preserve for other purpose",
69
+ 134: "Preserve for other purpose",
70
+ 135: "Preserve for other purpose",
71
+ 136: "Preserve for other purpose",
72
+ 137: "Preserve for other purpose",
73
+ 138: "Preserve for other purpose",
74
+ 139: "Preserve for other purpose",
75
+ 140: "Preserve for other purpose",
76
+ 141: "Preserve for other purpose",
77
+ 142: "Preserve for other purpose",
78
+ 143: "Preserve for other purpose",
79
+ 144: "Preserve for other purpose",
80
+ 145: "Preserve for other purpose",
81
+ 146: "Preserve for other purpose",
82
+ 147: "Preserve for other purpose",
83
+ 148: "Preserve for other purpose",
84
+ 149: "Preserve for other purpose",
85
+ 150: "Request source IP does not match the login IP",
86
+ 160: "Insufficient application privilege",
87
+ [CODE_UNKNOWN]: "Unknown error",
88
+ },
89
+ };
90
+ export const resWithErrorCode = (apiKey, res) => {
91
+ var _a, _b;
92
+ const errorCodes = SYNOLOGY_ERROR_CODES[apiKey];
93
+ const code = (_a = res === null || res === void 0 ? void 0 : res.error) === null || _a === void 0 ? void 0 : _a.code;
94
+ if (isUndfined(code))
95
+ return res;
96
+ return Object.assign(Object.assign({}, res), { error: Object.assign(Object.assign({}, res.error), { message: ((_b = res === null || res === void 0 ? void 0 : res.error) === null || _b === void 0 ? void 0 : _b.message) || (errorCodes === null || errorCodes === void 0 ? void 0 : errorCodes[code]) || "Unknown error" }) });
97
+ };
package/dist/esm/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  import { SynologyApi } from "./core";
2
+ export * from "./types";
2
3
  export * from "./core";
3
4
  export default SynologyApi;
@@ -8,11 +8,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import axios from "axios";
11
- import { SYNOLOGY_API_AUTH } from "../../constants";
11
+ import { SynologyApiInfo } from "../../types";
12
12
  export function login(core) {
13
13
  return __awaiter(this, void 0, void 0, function* () {
14
14
  const params = {
15
- api: SYNOLOGY_API_AUTH,
15
+ api: SynologyApiInfo.Auth,
16
16
  version: 6,
17
17
  method: "login",
18
18
  account: core.username,
@@ -30,7 +30,7 @@ export function login(core) {
30
30
  export function logout(core) {
31
31
  return __awaiter(this, void 0, void 0, function* () {
32
32
  const params = {
33
- api: SYNOLOGY_API_AUTH,
33
+ api: SynologyApiInfo.Auth,
34
34
  version: 6,
35
35
  method: "logout",
36
36
  };
@@ -8,11 +8,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import axios from "axios";
11
- import { SYNOLOGY_API_INFO } from "../../constants";
11
+ import { SynologyApiInfo } from "../../types";
12
12
  export function getApiInfo(core) {
13
13
  return __awaiter(this, void 0, void 0, function* () {
14
14
  const params = {
15
- api: SYNOLOGY_API_INFO,
15
+ api: SynologyApiInfo.Info,
16
16
  version: 1,
17
17
  method: "query",
18
18
  };
@@ -7,18 +7,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- /**
11
- * fetch song list
12
- * */
10
+ import { AudioStationApi } from "../../types";
13
11
  export function getSongList(params) {
14
12
  return __awaiter(this, void 0, void 0, function* () {
15
- const res = yield this.run("SYNO.AudioStation.Song", {
16
- params: {
17
- method: "list",
18
- library: "all",
19
- limit: params.limit,
20
- offset: params.offset,
21
- },
13
+ const res = yield this.run(AudioStationApi.Song, {
14
+ params: Object.assign({ method: "list", library: "all" }, params),
22
15
  });
23
16
  return res.data;
24
17
  });
@@ -1,5 +1,5 @@
1
1
  import { getSongList } from "./Song";
2
2
  export const AudioStationMethods = {
3
- getSongList: getSongList,
3
+ getSongList,
4
4
  };
5
5
  export const AudioStationKey = "AudioStation";
File without changes
@@ -0,0 +1,20 @@
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 { FileStationApi } from "../../types";
11
+ export function getInfo() {
12
+ return __awaiter(this, void 0, void 0, function* () {
13
+ const res = yield this.run(FileStationApi.Info, {
14
+ params: {
15
+ method: "get",
16
+ },
17
+ });
18
+ return res.data;
19
+ });
20
+ }
@@ -0,0 +1,32 @@
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 { FileStationApi } from "../../types";
11
+ import { isUndfined } from "../../utils";
12
+ export function getFileList() {
13
+ return __awaiter(this, arguments, void 0, function* (params = {}) {
14
+ const { additional = ["real_path", "size", "owner", "time"], filetype = "all" } = params;
15
+ if (isUndfined(params.folder_path)) {
16
+ throw new Error("folder_path is required");
17
+ }
18
+ const res = yield this.run(FileStationApi.List, {
19
+ params: Object.assign({ method: "list", additional: JSON.stringify(additional), filetype: filetype, folder_path: params.folder_path }, params),
20
+ });
21
+ return res.data;
22
+ });
23
+ }
24
+ export function getFileListShare() {
25
+ return __awaiter(this, arguments, void 0, function* (params = {}) {
26
+ const { additional = ["real_path", "size", "owner", "time"], onlywritable = false } = params;
27
+ const res = yield this.run(FileStationApi.List, {
28
+ params: Object.assign({ method: "list_share", additional: JSON.stringify(additional), onlywritable: onlywritable }, params),
29
+ });
30
+ return res.data;
31
+ });
32
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * reference :https://global.download.synology.com/download/Document/Software/DeveloperGuide/Package/FileStation/All/enu/Synology_File_Station_API_Guide.pdf
3
+ */
4
+ import { getInfo } from "./Info";
5
+ import { getFileList, getFileListShare } from "./List";
6
+ export const FileStationMethods = {
7
+ getInfo,
8
+ getFileList,
9
+ getFileListShare,
10
+ };
11
+ export const FileStationKey = "FileStation";
@@ -1,4 +1,10 @@
1
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
+ }
2
8
  // bind methods to BaseSynologyApi instance
3
9
  function methodsBundler(instance, methods) {
4
10
  const output = {};
@@ -7,11 +13,13 @@ function methodsBundler(instance, methods) {
7
13
  }
8
14
  return output;
9
15
  }
10
- export class BaseSynologyApi {
11
- constructor() { }
12
- }
13
16
  // proxy methods namespace to BaseSynologyApi instance
14
17
  Object.defineProperties(BaseSynologyApi.prototype, {
18
+ [FileStationKey]: {
19
+ get() {
20
+ return methodsBundler(this, FileStationMethods);
21
+ },
22
+ },
15
23
  [AudioStationKey]: {
16
24
  get() {
17
25
  return methodsBundler(this, AudioStationMethods);
@@ -0,0 +1,42 @@
1
+ /**
2
+ * api info
3
+ * */
4
+ export var SynologyApiInfo;
5
+ (function (SynologyApiInfo) {
6
+ SynologyApiInfo["Auth"] = "SYNO.API.Auth";
7
+ SynologyApiInfo["Info"] = "SYNO.API.Info";
8
+ SynologyApiInfo["OTP"] = "SYNO.API.OTP";
9
+ })(SynologyApiInfo || (SynologyApiInfo = {}));
10
+ /**
11
+ * AudioStation
12
+ * */
13
+ export var AudioStationApi;
14
+ (function (AudioStationApi) {
15
+ AudioStationApi["Song"] = "SYNO.AudioStation.Song";
16
+ AudioStationApi["Album"] = "SYNO.AudioStation.Album";
17
+ AudioStationApi["Artist"] = "SYNO.AudioStation.Artist";
18
+ AudioStationApi["Genre"] = "SYNO.AudioStation.Genre";
19
+ AudioStationApi["Playlist"] = "SYNO.AudioStation.Playlist";
20
+ AudioStationApi["Folder"] = "SYNO.AudioStation.Folder";
21
+ AudioStationApi["Cover"] = "SYNO.AudioStation.Cover";
22
+ AudioStationApi["Download"] = "SYNO.AudioStation.Download";
23
+ AudioStationApi["Info"] = "SYNO.AudioStation.Info";
24
+ AudioStationApi["Lyrics"] = "SYNO.AudioStation.Lyrics";
25
+ AudioStationApi["LyricsSearch"] = "SYNO.AudioStation.LyricsSearch";
26
+ AudioStationApi["Radio"] = "SYNO.AudioStation.Radio";
27
+ AudioStationApi["Stream"] = "SYNO.AudioStation.Stream";
28
+ AudioStationApi["Tag"] = "SYNO.AudioStation.Tag";
29
+ })(AudioStationApi || (AudioStationApi = {}));
30
+ /**
31
+ * FileStation API
32
+ */
33
+ export var FileStationApi;
34
+ (function (FileStationApi) {
35
+ FileStationApi["File"] = "SYNO.FileStation.File";
36
+ FileStationApi["Info"] = "SYNO.FileStation.Info";
37
+ FileStationApi["List"] = "SYNO.FileStation.List";
38
+ FileStationApi["Quota"] = "SYNO.FileStation.Quota";
39
+ FileStationApi["Share"] = "SYNO.FileStation.Share";
40
+ FileStationApi["Thumb"] = "SYNO.FileStation.Thumb";
41
+ FileStationApi["Upload"] = "SYNO.FileStation.Upload";
42
+ })(FileStationApi || (FileStationApi = {}));
@@ -1 +1,2 @@
1
- export * from "./API";
1
+ export * from "./request";
2
+ export * from "./apiInfo";
package/dist/esm/utils.js CHANGED
@@ -12,3 +12,9 @@ export function queryObjToString(params) {
12
12
  export function isHttpUrl(url) {
13
13
  return /^https?:\/\//.test(url);
14
14
  }
15
+ export function isUndfined(value) {
16
+ return value === undefined;
17
+ }
18
+ export function getApiKey(apiName) {
19
+ return apiName.split('.')[1];
20
+ }
@@ -1,4 +1,5 @@
1
- export declare const SYNOLOGY_API_AUTH = "SYNO.API.Auth";
2
- export declare const SYNOLOGY_API_INFO = "SYNO.API.Info";
1
+ /**
2
+ * synology constants
3
+ */
3
4
  export declare const GLOBAL_QUICK_CONNECT_URL = "https://global.quickconnect.cn/Serv.php";
4
5
  export declare const QUICK_CONNECT_PINGPANG_API = "/webman/pingpong.cgi?action=cors&quickconnect=true";
@@ -4,7 +4,7 @@ export interface SynologyApiOptions {
4
4
  username: string;
5
5
  password: string;
6
6
  }
7
- export interface SynologyApiInfo {
7
+ export interface SynologyApiInfoData {
8
8
  maxVersion: number;
9
9
  minVersion: number;
10
10
  path: string;
@@ -0,0 +1,93 @@
1
+ import { SynologyApiResponse } from "./types";
2
+ export declare const SYNOLOGY_ERROR_CODES: {
3
+ FileStation: {
4
+ 400: string;
5
+ 401: string;
6
+ 402: string;
7
+ 403: string;
8
+ 404: string;
9
+ 405: string;
10
+ 406: string;
11
+ 407: string;
12
+ 408: string;
13
+ 409: string;
14
+ 410: string;
15
+ 411: string;
16
+ 412: string;
17
+ 413: string;
18
+ 414: string;
19
+ 415: string;
20
+ 416: string;
21
+ 417: string;
22
+ 418: string;
23
+ 419: string;
24
+ 420: string;
25
+ 421: string;
26
+ 599: string;
27
+ };
28
+ AudioStation: {};
29
+ COMMON_CODES: {
30
+ 0: string;
31
+ 100: string;
32
+ 101: string;
33
+ 102: string;
34
+ 103: string;
35
+ 104: string;
36
+ 105: string;
37
+ 106: string;
38
+ 107: string;
39
+ 108: string;
40
+ 109: string;
41
+ 110: string;
42
+ 111: string;
43
+ 112: string;
44
+ 113: string;
45
+ 114: string;
46
+ 115: string;
47
+ 116: string;
48
+ 117: string;
49
+ 118: string;
50
+ 119: string;
51
+ 120: string;
52
+ 121: string;
53
+ 122: string;
54
+ 123: string;
55
+ 124: string;
56
+ 125: string;
57
+ 126: string;
58
+ 127: string;
59
+ 128: string;
60
+ 129: string;
61
+ 130: string;
62
+ 131: string;
63
+ 132: string;
64
+ 133: string;
65
+ 134: string;
66
+ 135: string;
67
+ 136: string;
68
+ 137: string;
69
+ 138: string;
70
+ 139: string;
71
+ 140: string;
72
+ 141: string;
73
+ 142: string;
74
+ 143: string;
75
+ 144: string;
76
+ 145: string;
77
+ 146: string;
78
+ 147: string;
79
+ 148: string;
80
+ 149: string;
81
+ 150: string;
82
+ 160: string;
83
+ 9999: string;
84
+ };
85
+ };
86
+ export declare const resWithErrorCode: (apiKey: string, res: SynologyApiResponse<any>) => SynologyApiResponse<any> | {
87
+ error: {
88
+ message: any;
89
+ code: number;
90
+ };
91
+ data?: any;
92
+ success: boolean;
93
+ };
@@ -1,3 +1,4 @@
1
1
  import { SynologyApi } from "./core";
2
+ export * from "./types";
2
3
  export * from "./core";
3
4
  export default SynologyApi;
@@ -1,4 +1,7 @@
1
- import { SynologyApiResponse } from "../../../types";
1
+ import { SynologyApiResponse } from "../../types";
2
+ /**
3
+ * fetch song list
4
+ * */
2
5
  export type AudioStationSongListRequest = {
3
6
  limit?: number;
4
7
  offset?: number;
@@ -16,3 +19,4 @@ export type AudioStationSongListResponse = SynologyApiResponse<{
16
19
  [key: string]: any;
17
20
  };
18
21
  }>;
22
+ export declare function getSongList(params: AudioStationSongListRequest): Promise<AudioStationSongListResponse>;
File without changes
@@ -0,0 +1,11 @@
1
+ import { SynologyApiResponse } from "../../types";
2
+ /**
3
+ * get filestation info
4
+ */
5
+ export type FileStationInfoResponse = SynologyApiResponse<{
6
+ is_manager: boolean;
7
+ support_virtual_protocol: number;
8
+ support_sharing: boolean;
9
+ hostname: string;
10
+ }>;
11
+ export declare function getInfo(): Promise<FileStationInfoResponse>;
@@ -0,0 +1,59 @@
1
+ import { SynologyApiResponse } from "../../types";
2
+ /**
3
+ * fetch filestation list
4
+ */
5
+ export type FileStationFileListRequest = {
6
+ limit?: number;
7
+ offset?: number;
8
+ sort_by?: string;
9
+ sort_direction?: "ASC" | "DESC";
10
+ version?: number;
11
+ filetype?: "file" | "dir" | "all";
12
+ folder_path?: string;
13
+ additional?: string[];
14
+ };
15
+ export type FileStationFileListItem = {
16
+ isdir: boolean;
17
+ name: string;
18
+ path: string;
19
+ additional?: {
20
+ type: string;
21
+ size: number;
22
+ time: {
23
+ atime: number;
24
+ mtime: number;
25
+ ctime: number;
26
+ btime: number;
27
+ };
28
+ real_path: string;
29
+ mount_point_type: string;
30
+ indexed: boolean;
31
+ description: Record<string, any>;
32
+ };
33
+ };
34
+ export type FileStationFileListResponse = SynologyApiResponse<{
35
+ files: FileStationFileListItem[];
36
+ offset: number;
37
+ total: number;
38
+ }>;
39
+ export declare function getFileList(params?: FileStationFileListRequest): Promise<FileStationFileListResponse>;
40
+ /**
41
+ * fetch file share list
42
+ * */
43
+ export type FileStationFileShareListRequest = {
44
+ limit?: number;
45
+ offset?: number;
46
+ sort_by?: string;
47
+ sort_direction?: "ASC" | "DESC";
48
+ additional?: string[];
49
+ onlywritable?: boolean;
50
+ };
51
+ export type FileStationFileShareListResponse = SynologyApiResponse<{
52
+ shares: FileStationFileListItem & {
53
+ hybridshare_cache_status: number;
54
+ hybridshare_pin_status: number;
55
+ }[];
56
+ offset: number;
57
+ total: number;
58
+ }>;
59
+ export declare function getFileListShare(params?: FileStationFileShareListRequest): Promise<FileStationFileShareListResponse>;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * reference :https://global.download.synology.com/download/Document/Software/DeveloperGuide/Package/FileStation/All/enu/Synology_File_Station_API_Guide.pdf
3
+ */
4
+ import { getInfo } from "./Info";
5
+ import { getFileList, getFileListShare } from "./List";
6
+ export declare const FileStationMethods: {
7
+ getInfo: typeof getInfo;
8
+ getFileList: typeof getFileList;
9
+ getFileListShare: typeof getFileListShare;
10
+ };
11
+ export declare const FileStationKey = "FileStation";
@@ -1,5 +1,9 @@
1
1
  import { AudioStationKey, AudioStationMethods } from "./AudioStation";
2
+ import { FileStationKey, FileStationMethods } from "./FileStation";
3
+ export { AudioStationKey } from "./AudioStation";
4
+ export { FileStationKey } from "./FileStation";
2
5
  export declare class BaseSynologyApi {
3
6
  [AudioStationKey]: typeof AudioStationMethods;
7
+ [FileStationKey]: typeof FileStationMethods;
4
8
  constructor();
5
9
  }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * api info
3
+ * */
4
+ export declare enum SynologyApiInfo {
5
+ Auth = "SYNO.API.Auth",
6
+ Info = "SYNO.API.Info",
7
+ OTP = "SYNO.API.OTP"
8
+ }
9
+ /**
10
+ * AudioStation
11
+ * */
12
+ export declare enum AudioStationApi {
13
+ Song = "SYNO.AudioStation.Song",
14
+ Album = "SYNO.AudioStation.Album",
15
+ Artist = "SYNO.AudioStation.Artist",
16
+ Genre = "SYNO.AudioStation.Genre",
17
+ Playlist = "SYNO.AudioStation.Playlist",
18
+ Folder = "SYNO.AudioStation.Folder",
19
+ Cover = "SYNO.AudioStation.Cover",
20
+ Download = "SYNO.AudioStation.Download",
21
+ Info = "SYNO.AudioStation.Info",
22
+ Lyrics = "SYNO.AudioStation.Lyrics",
23
+ LyricsSearch = "SYNO.AudioStation.LyricsSearch",
24
+ Radio = "SYNO.AudioStation.Radio",
25
+ Stream = "SYNO.AudioStation.Stream",
26
+ Tag = "SYNO.AudioStation.Tag"
27
+ }
28
+ /**
29
+ * FileStation API
30
+ */
31
+ export declare enum FileStationApi {
32
+ File = "SYNO.FileStation.File",
33
+ Info = "SYNO.FileStation.Info",
34
+ List = "SYNO.FileStation.List",
35
+ Quota = "SYNO.FileStation.Quota",
36
+ Share = "SYNO.FileStation.Share",
37
+ Thumb = "SYNO.FileStation.Thumb",
38
+ Upload = "SYNO.FileStation.Upload"
39
+ }
@@ -1 +1,2 @@
1
- export * from "./API";
1
+ export * from "./request";
2
+ export * from "./apiInfo";
@@ -1,9 +1,8 @@
1
1
  export type SynologyApiResponse<T = any> = {
2
- data: T;
3
- error: {
2
+ data?: T;
3
+ error?: {
4
4
  code: number;
5
- errors: Record<string, string>;
6
- message: string;
5
+ message?: string;
7
6
  };
8
7
  success: boolean;
9
8
  };
@@ -1,3 +1,5 @@
1
1
  export declare function isObjEmpty(obj: Record<string, any>): boolean;
2
2
  export declare function queryObjToString(params: Record<string, any>): string;
3
3
  export declare function isHttpUrl(url: string): boolean;
4
+ export declare function isUndfined(value: any): boolean;
5
+ export declare function getApiKey(apiName: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fett/synology-api",
3
- "version": "0.0.1-beta.3",
3
+ "version": "0.0.1-beta.4",
4
4
  "description": "synology api for nodejs",
5
5
  "module": "./dist/esm/index.js",
6
6
  "main": "./dist/cjs/index.js",
@@ -1 +0,0 @@
1
- export {};
@@ -1,5 +0,0 @@
1
- import { AudioStationSongListRequest, AudioStationSongListResponse } from "./types";
2
- /**
3
- * fetch song list
4
- * */
5
- export declare function getSongList(params: AudioStationSongListRequest): Promise<AudioStationSongListResponse>;
File without changes