@fett/synology-api 0.1.0 → 0.1.2
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 +3 -1
- package/lib/cli/apis.js +1 -1
- package/lib/core.d.ts +4 -0
- package/lib/core.js +5 -1
- package/lib/helpers.d.ts +1 -1
- package/lib/helpers.js +10 -4
- package/lib/modules/FileStation/Download.d.ts +2 -4
- package/lib/modules/FileStation/Download.js +33 -17
- package/lib/modules/FileStation/Thumb.d.ts +2 -3
- package/lib/modules/FileStation/Thumb.js +5 -9
- package/lib/modules/FileStation/Upload.js +1 -1
- package/lib/modules/FileStation/Upload.rn.js +1 -1
- package/lib/modules/FileStation/index.base.d.ts +4 -4
- package/lib/modules/FileStation/index.base.js +5 -4
- package/lib/modules/FileStation/index.d.ts +2 -2
- package/lib/modules/FileStation/index.rn.d.ts +2 -2
- package/lib/modules/VideoStation/Streaming.js +2 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
   
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
📖 [中文 README](./README_zh.md)
|
|
11
|
+
🔎 [API Document ](https://chrissong1994.github.io/synology-api)
|
|
11
12
|
|
|
12
13
|
Synology Api Javascript wrapper can be used in Browser、CLI or Nodejs to interact with Synology NAS.
|
|
13
14
|
You can use domain or ip address, also supports Synology Quick Connect connect Synology server.
|
|
@@ -27,6 +28,7 @@ npm install @fett/synology-api
|
|
|
27
28
|
| :--------------------: | :-----------------: | :----------------------------------------------------------- | :-----: |
|
|
28
29
|
| server | string | Synology NAS address or QuickConnectId | - |
|
|
29
30
|
| quickConnectServerType | proxy \| wan \| lan | QuickConnect server type when connecting via QuickConnect ID | proxy |
|
|
31
|
+
| lanPriority | boolean | Prioritize LAN IP when quickConnectServerType is not lan | false |
|
|
30
32
|
| username | string | Synology NAS username | - |
|
|
31
33
|
| password | string | Synology NAS password | - |
|
|
32
34
|
|
package/lib/cli/apis.js
CHANGED
|
@@ -42,7 +42,7 @@ export const onMethodCall = (module) => async (method, options) => {
|
|
|
42
42
|
}
|
|
43
43
|
if (options.output) {
|
|
44
44
|
try {
|
|
45
|
-
|
|
45
|
+
const out_path = path.resolve(options.output);
|
|
46
46
|
if (!fse.existsSync(out_path)) {
|
|
47
47
|
fse.ensureFileSync(out_path);
|
|
48
48
|
console.log(chalk.yellowBright(`Output file created: ${out_path}`));
|
package/lib/core.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface SynologyApiOptions {
|
|
|
17
17
|
password: string;
|
|
18
18
|
quickConnectServerType?: QuickConnectServerType;
|
|
19
19
|
agent?: Agent;
|
|
20
|
+
lanPriority?: boolean;
|
|
20
21
|
}
|
|
21
22
|
export interface SynologyApiInfoData {
|
|
22
23
|
maxVersion: number;
|
|
@@ -38,6 +39,7 @@ export declare class SynologyApi extends BaseModuleSynologyApi {
|
|
|
38
39
|
baseUrl: string;
|
|
39
40
|
isConnecting: boolean;
|
|
40
41
|
quickConnectServerType?: QuickConnectServerType;
|
|
42
|
+
lanPriority?: boolean;
|
|
41
43
|
private authInfo;
|
|
42
44
|
private apiInfo;
|
|
43
45
|
constructor(options: SynologyApiOptions);
|
|
@@ -52,12 +54,14 @@ export declare class SynologyApi extends BaseModuleSynologyApi {
|
|
|
52
54
|
params?: Record<string, any>;
|
|
53
55
|
data?: Record<string, any>;
|
|
54
56
|
headers?: Record<string, any>;
|
|
57
|
+
responseType?: AxiosRequestConfig["responseType"];
|
|
55
58
|
}): Promise<AxiosRequestConfig>;
|
|
56
59
|
protected run(apiName: string, options: {
|
|
57
60
|
method?: "get" | "post";
|
|
58
61
|
params?: Record<string, any>;
|
|
59
62
|
data?: Record<string, any>;
|
|
60
63
|
headers?: Record<string, any>;
|
|
64
|
+
responseType?: AxiosRequestConfig["responseType"];
|
|
61
65
|
}): Promise<any>;
|
|
62
66
|
}
|
|
63
67
|
export {};
|
package/lib/core.js
CHANGED
|
@@ -17,13 +17,14 @@ export class SynologyApi extends BaseModuleSynologyApi {
|
|
|
17
17
|
this.username = options.username;
|
|
18
18
|
this.password = options.password;
|
|
19
19
|
this.quickConnectServerType = options.quickConnectServerType ?? QuickConnectServerType.proxy;
|
|
20
|
+
this.lanPriority = options.lanPriority ?? false;
|
|
20
21
|
this.baseUrl = `${this.server}/webapi/`;
|
|
21
22
|
this.agent = options.agent ?? undefined;
|
|
22
23
|
}
|
|
23
24
|
async connect() {
|
|
24
25
|
// if quickconnect id
|
|
25
26
|
if (!isHttpUrl(this.server)) {
|
|
26
|
-
this.server = await getServerInfo(this.server, this.quickConnectServerType);
|
|
27
|
+
this.server = await getServerInfo(this.server, this.quickConnectServerType, this.lanPriority);
|
|
27
28
|
this.baseUrl = `${this.server}/webapi/`;
|
|
28
29
|
}
|
|
29
30
|
try {
|
|
@@ -103,6 +104,9 @@ export class SynologyApi extends BaseModuleSynologyApi {
|
|
|
103
104
|
},
|
|
104
105
|
data: options.data ?? null,
|
|
105
106
|
};
|
|
107
|
+
if (options.responseType) {
|
|
108
|
+
requestOptions.responseType = options.responseType;
|
|
109
|
+
}
|
|
106
110
|
// https agent for node
|
|
107
111
|
if (isNode) {
|
|
108
112
|
if (this.agent?.https) {
|
package/lib/helpers.d.ts
CHANGED
|
@@ -16,5 +16,5 @@ export type ServerInfo = {
|
|
|
16
16
|
relay_port: number;
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
|
-
export declare const getServerInfo: (quickConnectId: string, quickConnectServerType: QuickConnectServerType) => Promise<any>;
|
|
19
|
+
export declare const getServerInfo: (quickConnectId: string, quickConnectServerType: QuickConnectServerType, lanPriority?: boolean) => Promise<any>;
|
|
20
20
|
export declare const pingpang: (server: string) => Promise<boolean>;
|
package/lib/helpers.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Axios from "axios";
|
|
2
2
|
import { GLOBAL_QUICK_CONNECT_URL, QUICK_CONNECT_PINGPANG_API } from "./constants.js";
|
|
3
3
|
import { QuickConnectServerType } from "./types/index.js";
|
|
4
|
-
const getServersFromServerInfo = async (serverInfo, quickConnectServerType) => {
|
|
4
|
+
const getServersFromServerInfo = async (serverInfo, quickConnectServerType, lanPriority) => {
|
|
5
5
|
const serverMap = {
|
|
6
6
|
[QuickConnectServerType.proxy]: undefined,
|
|
7
7
|
[QuickConnectServerType.lan]: undefined,
|
|
@@ -23,6 +23,12 @@ const getServersFromServerInfo = async (serverInfo, quickConnectServerType) => {
|
|
|
23
23
|
`http://${serverInfo.server.interface?.[0].ip}:${serverInfo.service.port}`;
|
|
24
24
|
}
|
|
25
25
|
const server = serverMap[quickConnectServerType];
|
|
26
|
+
if (lanPriority && serverMap[QuickConnectServerType.lan]) {
|
|
27
|
+
const lanServer = serverMap[QuickConnectServerType.lan];
|
|
28
|
+
if (lanServer && (await pingpang(lanServer))) {
|
|
29
|
+
return lanServer;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
26
32
|
if (!server) {
|
|
27
33
|
return Promise.reject(`${quickConnectServerType} server not found`);
|
|
28
34
|
}
|
|
@@ -34,7 +40,7 @@ const getServersFromServerInfo = async (serverInfo, quickConnectServerType) => {
|
|
|
34
40
|
return server;
|
|
35
41
|
}
|
|
36
42
|
};
|
|
37
|
-
export const getServerInfo = async (quickConnectId, quickConnectServerType) => {
|
|
43
|
+
export const getServerInfo = async (quickConnectId, quickConnectServerType, lanPriority) => {
|
|
38
44
|
const params = {
|
|
39
45
|
version: 1,
|
|
40
46
|
id: "dsm",
|
|
@@ -53,10 +59,10 @@ export const getServerInfo = async (quickConnectId, quickConnectServerType) => {
|
|
|
53
59
|
};
|
|
54
60
|
// get replay tunnel
|
|
55
61
|
const result = (await Axios.post(`https://${serverInfo.env.control_host}/Serv.php`, relayRequestParams)).data;
|
|
56
|
-
return getServersFromServerInfo(result, quickConnectServerType);
|
|
62
|
+
return getServersFromServerInfo(result, quickConnectServerType, lanPriority);
|
|
57
63
|
}
|
|
58
64
|
else {
|
|
59
|
-
return getServersFromServerInfo(serverInfo, quickConnectServerType);
|
|
65
|
+
return getServersFromServerInfo(serverInfo, quickConnectServerType, lanPriority);
|
|
60
66
|
}
|
|
61
67
|
};
|
|
62
68
|
// pingpang
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { SynologyApiResponse } from "../../types/index.js";
|
|
2
1
|
export type DownloadFileParams = {
|
|
3
2
|
path: string;
|
|
4
|
-
mode?: "download" | "open";
|
|
5
3
|
};
|
|
6
|
-
export type DownloadFileResponse =
|
|
7
|
-
export declare function
|
|
4
|
+
export type DownloadFileResponse = Buffer;
|
|
5
|
+
export declare function getDownload(params: DownloadFileParams): Promise<DownloadFileResponse>;
|
|
@@ -1,19 +1,35 @@
|
|
|
1
1
|
import { FileStationApi } from "../../types/index.js";
|
|
2
|
-
import {
|
|
3
|
-
export async function
|
|
4
|
-
const { path
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
14
|
-
const url = buildUrlWithQuery(`${this.baseUrl}${api.path}`, query);
|
|
15
|
-
return {
|
|
16
|
-
data: url,
|
|
17
|
-
success: true,
|
|
18
|
-
};
|
|
2
|
+
import { isNode } from "../../utils/index.js";
|
|
3
|
+
export async function getDownload(params) {
|
|
4
|
+
const { path } = params;
|
|
5
|
+
const res = await this.run(FileStationApi.Download, {
|
|
6
|
+
responseType: "arraybuffer",
|
|
7
|
+
params: {
|
|
8
|
+
path,
|
|
9
|
+
mode: "download",
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
return isNode ? Buffer.from(res) : res;
|
|
19
13
|
}
|
|
14
|
+
// export async function getFileOpenUrl(params: DownloadFileParams): Promise<{
|
|
15
|
+
// data: string;
|
|
16
|
+
// success: boolean;
|
|
17
|
+
// }> {
|
|
18
|
+
// if (!this.isConnecting) {
|
|
19
|
+
// await this.connect();
|
|
20
|
+
// }
|
|
21
|
+
// const { path } = params;
|
|
22
|
+
// const apiInfo = this.getApiInfoByName(FileStationApi.Download);
|
|
23
|
+
// const url = buildUrlWithQuery(`${this.baseUrl}${apiInfo.path}`, {
|
|
24
|
+
// api: FileStationApi.Download,
|
|
25
|
+
// method:"download",
|
|
26
|
+
// path,
|
|
27
|
+
// mode: "open",
|
|
28
|
+
// version: apiInfo.maxVersion,
|
|
29
|
+
// _sid: this.authInfo?.sid,
|
|
30
|
+
// });
|
|
31
|
+
// return {
|
|
32
|
+
// data: url,
|
|
33
|
+
// success: true,
|
|
34
|
+
// };
|
|
35
|
+
// }
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { SynologyApiResponse } from "../../types/index.js";
|
|
2
1
|
export type GetThumbRequest = {
|
|
3
2
|
path: string;
|
|
4
3
|
size?: "small" | "medium" | "large" | "original";
|
|
@@ -14,5 +13,5 @@ export type GetThumbRequest = {
|
|
|
14
13
|
*/
|
|
15
14
|
rotate?: 0 | 1 | 2 | 3 | 4;
|
|
16
15
|
};
|
|
17
|
-
export type GetThumbResponse =
|
|
18
|
-
export declare function
|
|
16
|
+
export type GetThumbResponse = Buffer;
|
|
17
|
+
export declare function getThumb(params: GetThumbRequest): Promise<GetThumbResponse>;
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
import { FileStationApi } from "../../types/index.js";
|
|
2
|
-
import {
|
|
3
|
-
export async function
|
|
2
|
+
import { isNode } from "../../utils/index.js";
|
|
3
|
+
export async function getThumb(params) {
|
|
4
4
|
const { path, size = "small", rotate = 0 } = params;
|
|
5
|
-
const
|
|
6
|
-
|
|
5
|
+
const res = await this.run(FileStationApi.Thumb, {
|
|
6
|
+
responseType: "arraybuffer",
|
|
7
7
|
params: {
|
|
8
8
|
path,
|
|
9
9
|
size,
|
|
10
10
|
rotate,
|
|
11
11
|
},
|
|
12
12
|
});
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
success: true,
|
|
16
|
-
data: thumbUrl,
|
|
17
|
-
};
|
|
13
|
+
return isNode ? Buffer.from(res) : res;
|
|
18
14
|
}
|
|
@@ -12,7 +12,7 @@ export async function uploadFile(params) {
|
|
|
12
12
|
}
|
|
13
13
|
const api = this.getApiInfoByName(FileStationApi.Upload);
|
|
14
14
|
const { path, file, overwrite = OverwriteEnum.OVERWRITE, create_parents = true } = params;
|
|
15
|
-
|
|
15
|
+
const formData = createFormData();
|
|
16
16
|
formData.append("method", "upload");
|
|
17
17
|
formData.append("version", String(api?.maxVersion));
|
|
18
18
|
formData.append("api", FileStationApi.Upload);
|
|
@@ -11,7 +11,7 @@ export async function uploadFile(params) {
|
|
|
11
11
|
}
|
|
12
12
|
const api = this.getApiInfoByName(FileStationApi.Upload);
|
|
13
13
|
const { path, file, overwrite = OverwriteEnum.OVERWRITE, create_parents = true } = params;
|
|
14
|
-
|
|
14
|
+
const formData = createFormData();
|
|
15
15
|
formData.append("method", "upload");
|
|
16
16
|
formData.append("version", String(api?.maxVersion));
|
|
17
17
|
formData.append("api", FileStationApi.Upload);
|
|
@@ -6,9 +6,9 @@ import { getFileList, getShareFileList, getVirtualFolderList } from "./List.js";
|
|
|
6
6
|
import { addFavorite, deleteFavorite, getFavoriteList, clearBrokenFavorite, editFavorite } from "./Favorite.js";
|
|
7
7
|
import { startSearch, stopSearch, getSearchList, cleanSearch } from "./Search.js";
|
|
8
8
|
import { createFolder } from "./CreateFolder.js";
|
|
9
|
-
import {
|
|
9
|
+
import { getDownload } from "./Download.js";
|
|
10
10
|
import { stopDeleteFile, startDeleteFile, getDeleteFileStatus } from "./Delete.js";
|
|
11
|
-
import {
|
|
11
|
+
import { getThumb } from "./Thumb.js";
|
|
12
12
|
import { startDirSizeCalc, stopDirSizeCalc, getDirSizeCalcStatus } from "./DirSize.js";
|
|
13
13
|
import { startMD5Calc, stopMD5Calc, getMD5CalcStatus } from "./MD5.js";
|
|
14
14
|
import { checkPermission } from "./CheckPermission.js";
|
|
@@ -31,11 +31,11 @@ export declare const METHODS: {
|
|
|
31
31
|
getSearchList: typeof getSearchList;
|
|
32
32
|
cleanSearch: typeof cleanSearch;
|
|
33
33
|
createFolder: typeof createFolder;
|
|
34
|
-
|
|
34
|
+
getDownload: typeof getDownload;
|
|
35
35
|
stopDeleteFile: typeof stopDeleteFile;
|
|
36
36
|
startDeleteFile: typeof startDeleteFile;
|
|
37
37
|
getDeleteFileStatus: typeof getDeleteFileStatus;
|
|
38
|
-
|
|
38
|
+
getThumb: typeof getThumb;
|
|
39
39
|
startDirSizeCalc: typeof startDirSizeCalc;
|
|
40
40
|
stopDirSizeCalc: typeof stopDirSizeCalc;
|
|
41
41
|
getDirSizeCalcStatus: typeof getDirSizeCalcStatus;
|
|
@@ -6,9 +6,9 @@ import { getFileList, getShareFileList, getVirtualFolderList } from "./List.js";
|
|
|
6
6
|
import { addFavorite, deleteFavorite, getFavoriteList, clearBrokenFavorite, editFavorite, } from "./Favorite.js";
|
|
7
7
|
import { startSearch, stopSearch, getSearchList, cleanSearch } from "./Search.js";
|
|
8
8
|
import { createFolder } from "./CreateFolder.js";
|
|
9
|
-
import {
|
|
9
|
+
import { getDownload } from "./Download.js";
|
|
10
10
|
import { stopDeleteFile, startDeleteFile, getDeleteFileStatus } from "./Delete.js";
|
|
11
|
-
import {
|
|
11
|
+
import { getThumb } from "./Thumb.js";
|
|
12
12
|
import { startDirSizeCalc, stopDirSizeCalc, getDirSizeCalcStatus } from "./DirSize.js";
|
|
13
13
|
import { startMD5Calc, stopMD5Calc, getMD5CalcStatus } from "./MD5.js";
|
|
14
14
|
import { checkPermission } from "./CheckPermission.js";
|
|
@@ -32,11 +32,12 @@ export const METHODS = {
|
|
|
32
32
|
getSearchList,
|
|
33
33
|
cleanSearch,
|
|
34
34
|
createFolder,
|
|
35
|
-
|
|
35
|
+
getDownload,
|
|
36
|
+
// getFileOpenUrl,
|
|
36
37
|
stopDeleteFile,
|
|
37
38
|
startDeleteFile,
|
|
38
39
|
getDeleteFileStatus,
|
|
39
|
-
|
|
40
|
+
getThumb,
|
|
40
41
|
startDirSizeCalc,
|
|
41
42
|
stopDirSizeCalc,
|
|
42
43
|
getDirSizeCalcStatus,
|
|
@@ -15,11 +15,11 @@ export declare const METHODS: {
|
|
|
15
15
|
getSearchList: typeof import("./Search.js").getSearchList;
|
|
16
16
|
cleanSearch: typeof import("./Search.js").cleanSearch;
|
|
17
17
|
createFolder: typeof import("./CreateFolder.js").createFolder;
|
|
18
|
-
|
|
18
|
+
getDownload: typeof import("./Download.js").getDownload;
|
|
19
19
|
stopDeleteFile: typeof import("./Delete.js").stopDeleteFile;
|
|
20
20
|
startDeleteFile: typeof import("./Delete.js").startDeleteFile;
|
|
21
21
|
getDeleteFileStatus: typeof import("./Delete.js").getDeleteFileStatus;
|
|
22
|
-
|
|
22
|
+
getThumb: typeof import("./Thumb.js").getThumb;
|
|
23
23
|
startDirSizeCalc: typeof import("./DirSize.js").startDirSizeCalc;
|
|
24
24
|
stopDirSizeCalc: typeof import("./DirSize.js").stopDirSizeCalc;
|
|
25
25
|
getDirSizeCalcStatus: typeof import("./DirSize.js").getDirSizeCalcStatus;
|
|
@@ -15,11 +15,11 @@ export declare const METHODS: {
|
|
|
15
15
|
getSearchList: typeof import("./Search.js").getSearchList;
|
|
16
16
|
cleanSearch: typeof import("./Search.js").cleanSearch;
|
|
17
17
|
createFolder: typeof import("./CreateFolder.js").createFolder;
|
|
18
|
-
|
|
18
|
+
getDownload: typeof import("./Download.js").getDownload;
|
|
19
19
|
stopDeleteFile: typeof import("./Delete.js").stopDeleteFile;
|
|
20
20
|
startDeleteFile: typeof import("./Delete.js").startDeleteFile;
|
|
21
21
|
getDeleteFileStatus: typeof import("./Delete.js").getDeleteFileStatus;
|
|
22
|
-
|
|
22
|
+
getThumb: typeof import("./Thumb.js").getThumb;
|
|
23
23
|
startDirSizeCalc: typeof import("./DirSize.js").startDirSizeCalc;
|
|
24
24
|
stopDirSizeCalc: typeof import("./DirSize.js").stopDirSizeCalc;
|
|
25
25
|
getDirSizeCalcStatus: typeof import("./DirSize.js").getDirSizeCalcStatus;
|
|
@@ -21,7 +21,8 @@ export async function getStreamUrl(params) {
|
|
|
21
21
|
allow_api: VideoStationApi.Streaming,
|
|
22
22
|
allow_methods: ["stream"],
|
|
23
23
|
});
|
|
24
|
-
const
|
|
24
|
+
const apiInfo = this.getApiInfoByName(VideoStationApi.Streaming);
|
|
25
|
+
const url = `${this.baseUrl}${apiInfo.path}/1.mp4`;
|
|
25
26
|
const query = {
|
|
26
27
|
...params,
|
|
27
28
|
api: VideoStationApi.Streaming,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fett/synology-api",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "synology api for nodejs",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"pub": "npm publish --access=public",
|
|
59
59
|
"pub:beta": "npm publish --access=public --tag=beta",
|
|
60
60
|
"test": "vitest",
|
|
61
|
+
"test:debug": "node --inspect-brk=9230 ./node_modules/vitest/vitest.mjs run --pool=forks",
|
|
61
62
|
"coverage": "vitest run --coverage"
|
|
62
63
|
},
|
|
63
64
|
"devDependencies": {
|