@dnax/core 0.46.3 → 0.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/media/SyncAdapter.ts +5 -2
- package/lib/media/sftp.ts +88 -105
- package/package.json +2 -2
package/lib/media/SyncAdapter.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Cfg } from "../../config";
|
|
2
|
-
import { FilesystemSftpAdapter } from "
|
|
2
|
+
import { FilesystemSftpAdapter } from "./sftp";
|
|
3
|
+
//
|
|
3
4
|
async function syncAdapterFileSystem() {
|
|
4
5
|
const mediaCollections = Cfg.collections?.filter(
|
|
5
6
|
(col) => col.type == "media" && col?.media?.enabled
|
|
@@ -8,12 +9,14 @@ async function syncAdapterFileSystem() {
|
|
|
8
9
|
mediaCollections?.map((col) => {
|
|
9
10
|
if (col?.media?.filesystemAdapter) {
|
|
10
11
|
let currentAdapter = col?.media?.filesystemAdapter;
|
|
12
|
+
|
|
11
13
|
// for sftp
|
|
12
14
|
if (currentAdapter?.type == "sftp") {
|
|
13
15
|
let setAdapter = col?.media?.filesystemAdapter as InstanceType<
|
|
14
16
|
typeof FilesystemSftpAdapter
|
|
15
17
|
>;
|
|
16
|
-
|
|
18
|
+
//console.log("setAdapter", setAdapter);
|
|
19
|
+
setAdapter.syncCollectionMedia(col);
|
|
17
20
|
}
|
|
18
21
|
}
|
|
19
22
|
});
|
package/lib/media/sftp.ts
CHANGED
|
@@ -1,130 +1,113 @@
|
|
|
1
|
-
|
|
2
|
-
type
|
|
1
|
+
import { Client } from "ssh2";
|
|
2
|
+
import type { SFTPWrapper } from "ssh2";
|
|
3
|
+
import { consola } from "consola";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import chokidar from "chokidar";
|
|
6
|
+
import fs from "fs-extra";
|
|
7
|
+
import type { Collection } from "../../types";
|
|
8
|
+
const BASE_DIR = "/uploads/";
|
|
9
|
+
type ConfigType = {
|
|
3
10
|
host: string;
|
|
4
11
|
port?: number;
|
|
5
12
|
username: string;
|
|
6
13
|
password: string;
|
|
7
14
|
remoteDir: string;
|
|
15
|
+
path?: string;
|
|
8
16
|
ignorePatterns?: string[];
|
|
9
|
-
|
|
17
|
+
//privateKeyPath?: string;
|
|
10
18
|
};
|
|
11
|
-
import Client from "ssh2-sftp-client";
|
|
12
|
-
import chokidar from "chokidar";
|
|
13
|
-
import fs from "fs-extra";
|
|
14
|
-
import path from "path";
|
|
15
|
-
import { cleanDoubleSlashes } from "ufo";
|
|
16
|
-
import type { Collection } from "../../types";
|
|
17
|
-
|
|
18
19
|
class FilesystemSftpAdapter {
|
|
19
|
-
|
|
20
|
-
type: "sftp"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
conn: Client;
|
|
21
|
+
type: "sftp";
|
|
22
|
+
config: ConfigType;
|
|
23
|
+
constructor(
|
|
24
|
+
config = {
|
|
25
|
+
port: 22,
|
|
26
|
+
} as ConfigType
|
|
27
|
+
) {
|
|
24
28
|
this.config = config;
|
|
25
|
-
this.config.port = config?.port || 22;
|
|
26
|
-
this.#sftp = new Client();
|
|
27
29
|
this.type = "sftp";
|
|
30
|
+
this.conn = new Client({
|
|
31
|
+
//captureRejections: true,
|
|
32
|
+
});
|
|
28
33
|
return this;
|
|
29
34
|
}
|
|
30
35
|
|
|
31
|
-
async
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
...this.config,
|
|
35
|
-
})
|
|
36
|
+
async syncCollectionMedia(col: Collection) {
|
|
37
|
+
if (!this.config?.remoteDir) this.config.remoteDir = "/home/" + col?.slug;
|
|
38
|
+
await this.connect()
|
|
36
39
|
.then((e) => {
|
|
37
|
-
|
|
40
|
+
let visibility = col?.media?.visibility || "public";
|
|
41
|
+
|
|
42
|
+
let dirToWatch = path.join(
|
|
43
|
+
process.cwd(),
|
|
44
|
+
BASE_DIR,
|
|
45
|
+
col?.slug,
|
|
46
|
+
visibility
|
|
47
|
+
);
|
|
48
|
+
dirToWatch = path.resolve(dirToWatch);
|
|
49
|
+
const watcher = chokidar.watch(dirToWatch, {
|
|
50
|
+
persistent: true,
|
|
51
|
+
ignoreInitial: true,
|
|
52
|
+
ignored: this.config.ignorePatterns || [],
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
watcher.on("all", (event, filePath) => {
|
|
56
|
+
if (event == "change" || event == "add") {
|
|
57
|
+
//consola.info(`SFTP: ${event} ${filePath}`);
|
|
58
|
+
let remotePath = path.join(
|
|
59
|
+
this.config.remoteDir,
|
|
60
|
+
path.basename(filePath)
|
|
61
|
+
);
|
|
62
|
+
this.put(filePath, remotePath);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
38
65
|
})
|
|
39
66
|
.catch((err) => {
|
|
40
|
-
|
|
67
|
+
consola.error(`SFTP: Failed to connect ${this.config.host}`.red);
|
|
41
68
|
});
|
|
42
|
-
//.finally(() => {});
|
|
43
69
|
}
|
|
44
70
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (fs.existsSync(p)) {
|
|
58
|
-
let stats = fs.statSync(p);
|
|
59
|
-
if (stats.isFile()) {
|
|
60
|
-
await this.#sftp.mkdir(remoteDir, true).catch();
|
|
61
|
-
// Téléverser le fichier
|
|
62
|
-
let alreadyExists = await this.#sftp.exists(remotePathDest);
|
|
63
|
-
if (!alreadyExists) {
|
|
64
|
-
await this.#sftp.put(p, remotePathDest, {}).catch((err) => {
|
|
65
|
-
console.error("Fichier televerser", err?.message);
|
|
71
|
+
connect(): Promise<{ sftp: SFTPWrapper; conn: Client }> {
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
this.conn
|
|
74
|
+
.on("ready", () => {
|
|
75
|
+
this.conn.sftp((err, sftp) => {
|
|
76
|
+
if (err) {
|
|
77
|
+
this.conn.end();
|
|
78
|
+
return reject(err?.message);
|
|
79
|
+
}
|
|
80
|
+
resolve({
|
|
81
|
+
sftp: sftp,
|
|
82
|
+
conn: this.conn,
|
|
66
83
|
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
} catch (err: any) {
|
|
74
|
-
console.error(err?.message);
|
|
75
|
-
}
|
|
84
|
+
});
|
|
85
|
+
})
|
|
86
|
+
.on("error", (err) => reject(err?.message))
|
|
87
|
+
.connect(this.config);
|
|
88
|
+
});
|
|
76
89
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async init(col: Collection) {
|
|
99
|
-
let buildPath = "/uploads/";
|
|
100
|
-
if (!col?.media?.visibility && col?.media?.enabled) {
|
|
101
|
-
col.media.visibility = "public";
|
|
102
|
-
}
|
|
103
|
-
buildPath += col?.slug + "/" + col?.media?.visibility;
|
|
104
|
-
let watchLocalDir = path.resolve(process.cwd() + "/" + buildPath);
|
|
105
|
-
|
|
106
|
-
await this.connect()
|
|
107
|
-
.then(async (ops) => {
|
|
108
|
-
let remoteDir = this.config.remoteDir + buildPath;
|
|
109
|
-
|
|
110
|
-
let remoteDirExisis = await this.#sftp.exists(remoteDir);
|
|
111
|
-
|
|
112
|
-
//console.log("remoteDirExisis", remoteDir, remoteDirExisis);
|
|
113
|
-
|
|
114
|
-
if (!remoteDirExisis) {
|
|
115
|
-
await this.#sftp.mkdir(remoteDir, true).catch((err) => {});
|
|
116
|
-
// console.log("Watch", watchLocalDir);
|
|
117
|
-
|
|
118
|
-
setTimeout(() => {
|
|
119
|
-
this.watchDir(watchLocalDir);
|
|
120
|
-
}, 1000);
|
|
121
|
-
} else {
|
|
122
|
-
this.watchDir(watchLocalDir);
|
|
90
|
+
async put(localPath: string, remotePath: string) {
|
|
91
|
+
let { sftp, conn } = await this.connect();
|
|
92
|
+
return new Promise(async (resolve, reject) => {
|
|
93
|
+
sftp.fastPut(
|
|
94
|
+
localPath,
|
|
95
|
+
remotePath,
|
|
96
|
+
{
|
|
97
|
+
mode: 0o777,
|
|
98
|
+
},
|
|
99
|
+
(err) => {
|
|
100
|
+
conn.end();
|
|
101
|
+
if (err) {
|
|
102
|
+
console.log("Error exist");
|
|
103
|
+
}
|
|
104
|
+
if (err) {
|
|
105
|
+
reject(err?.message);
|
|
106
|
+
}
|
|
107
|
+
resolve(true);
|
|
123
108
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
console.error(err?.message);
|
|
127
|
-
});
|
|
109
|
+
);
|
|
110
|
+
});
|
|
128
111
|
}
|
|
129
112
|
}
|
|
130
113
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dnax/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.0",
|
|
4
4
|
"module": "index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"rfc6902": "^5.1.2",
|
|
55
55
|
"sharp": "^0.33.5",
|
|
56
56
|
"signaldb": "^0.24.5",
|
|
57
|
-
"ssh2
|
|
57
|
+
"ssh2": "^1.16.0",
|
|
58
58
|
"ufo": "^1.5.4",
|
|
59
59
|
"urlencode": "^2.0.0",
|
|
60
60
|
"uuid": "^11.1.0"
|