@bprotsyk/aso-core 2.0.32 → 2.0.34

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.
@@ -29,7 +29,9 @@ export declare class ServerUtil {
29
29
  setupCertbot(): Promise<boolean>;
30
30
  setupSSL(email: string, host: string): Promise<void>;
31
31
  refresh(): Promise<boolean>;
32
- uploadDirectoryToSftp(localDir: string, remoteDir: string, sftpConfig: ISFTP): Promise<void>;
32
+ uploadDirectoryToSftp(localDir: string, remoteDir: string, sftpConfig: any): Promise<void>;
33
33
  generateNginxConfig(domain: string, rootPath: string): Promise<string>;
34
+ extractUploadedZip(name: string, file: any): Promise<void>;
35
+ ensureDirectoryExistsViaSSH(sshConfig: ISFTP, remoteDir: string): Promise<void>;
34
36
  }
35
37
  export {};
@@ -4,11 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ServerUtil = exports.PORT = exports.HOST = exports.PASSWORD = exports.IP = void 0;
7
+ const node_ssh_1 = require("node-ssh");
7
8
  const child_process_1 = __importDefault(require("child_process"));
8
9
  const ssh2_sftp_client_1 = __importDefault(require("ssh2-sftp-client"));
9
10
  const fs_1 = __importDefault(require("fs"));
10
11
  const mustache_1 = __importDefault(require("mustache"));
11
12
  const path_1 = __importDefault(require("path"));
13
+ const unzipper_1 = __importDefault(require("unzipper"));
12
14
  const { promisify } = require("util");
13
15
  const execPromise = promisify(child_process_1.default.exec);
14
16
  exports.IP = "185.123.53.227";
@@ -170,18 +172,22 @@ class ServerUtil {
170
172
  try {
171
173
  await sftp.connect(sftpConfig);
172
174
  const items = fs_1.default.readdirSync(localDir, { withFileTypes: true });
173
- // Перебираємо кожен елемент (файл чи папку)
174
175
  for (const item of items) {
175
176
  const localPath = path_1.default.join(localDir, item.name);
176
177
  const remotePath = `${remoteDir}/${item.name}`;
177
178
  if (item.isDirectory()) {
178
- // Якщо це директорія, створюємо її на сервері
179
- await sftp.mkdir(remotePath, true);
180
- // Рекурсивно передаємо вміст цієї директорії
179
+ // Створення підкаталогу на віддаленому сервері
180
+ await sftp.mkdir(remotePath, true).catch(async (err) => {
181
+ if (err.code !== 4) { // Ігноруємо помилку "Directory already exists"
182
+ console.error(`Помилка під час створення папки: ${remotePath}`, err);
183
+ throw err;
184
+ }
185
+ });
186
+ // Рекурсивне копіювання вмісту директорії
181
187
  await this.uploadDirectoryToSftp(localPath, remotePath, sftpConfig);
182
188
  }
183
189
  else {
184
- // Якщо це файл, передаємо його на сервер
190
+ // Завантаження файлу на віддалений сервер
185
191
  await sftp.put(localPath, remotePath);
186
192
  console.log(`Передано файл: ${localPath} -> ${remotePath}`);
187
193
  }
@@ -192,15 +198,68 @@ class ServerUtil {
192
198
  console.error('Помилка під час передавання файлів через SFTP:', err);
193
199
  }
194
200
  finally {
195
- // Закриваємо підключення до SFTP
196
201
  await sftp.end();
197
202
  }
198
203
  }
199
204
  async generateNginxConfig(domain, rootPath) {
200
- const templatePath = path_1.default.join(__dirname, '..', 'templates', 'nginx-template.conf');
205
+ const templatePath = path_1.default.join(__dirname, "..", "templates", "nginx-template.conf");
201
206
  const template = fs_1.default.readFileSync(templatePath, "utf8");
202
207
  const config = mustache_1.default.render(template, { domain, rootPath });
203
208
  return config;
204
209
  }
210
+ async extractUploadedZip(name, file) {
211
+ const zipFilePath = file.path;
212
+ const outputDir = path_1.default.join(__dirname, '..', 'uploads', name);
213
+ console.log('Looking for ZIP file at:', zipFilePath);
214
+ console.log('Extracting to:', outputDir);
215
+ ensureDirectoryExistence(outputDir);
216
+ if (!fs_1.default.existsSync(zipFilePath)) {
217
+ console.error('Error: File not found:', zipFilePath);
218
+ return;
219
+ }
220
+ try {
221
+ await new Promise((resolve, reject) => {
222
+ fs_1.default.createReadStream(zipFilePath)
223
+ .pipe(unzipper_1.default.Parse())
224
+ .on('entry', (entry) => {
225
+ // Видаляємо перший сегмент шляху, щоб уникнути кореневої директорії
226
+ const entryPath = path_1.default.join(outputDir, ...entry.path.split('/').slice(1));
227
+ if (entry.type === 'Directory') {
228
+ ensureDirectoryExistence(entryPath);
229
+ }
230
+ else {
231
+ ensureDirectoryExistence(path_1.default.dirname(entryPath));
232
+ entry.pipe(fs_1.default.createWriteStream(entryPath));
233
+ }
234
+ })
235
+ .on('close', resolve)
236
+ .on('error', reject);
237
+ });
238
+ console.log('File successfully extracted.');
239
+ }
240
+ catch (err) {
241
+ console.error('Error extracting file:', err);
242
+ }
243
+ }
244
+ async ensureDirectoryExistsViaSSH(sshConfig, remoteDir) {
245
+ const ssh = new node_ssh_1.NodeSSH();
246
+ try {
247
+ await ssh.connect(sshConfig);
248
+ // Перевірка, чи існує директорія, і створення її, якщо вона не існує
249
+ const command = `if [ ! -d "${remoteDir}" ]; then mkdir -p "${remoteDir}"; fi`;
250
+ await ssh.execCommand(command);
251
+ console.log(`Перевірено або створено папку: ${remoteDir}`);
252
+ }
253
+ catch (err) {
254
+ console.error('Помилка під час перевірки або створення папки через SSH:', err);
255
+ throw err;
256
+ }
257
+ finally {
258
+ ssh.dispose();
259
+ }
260
+ }
205
261
  }
206
262
  exports.ServerUtil = ServerUtil;
263
+ function ensureDirectoryExistence(outputDir) {
264
+ throw new Error("Function not implemented.");
265
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bprotsyk/aso-core",
3
- "version": "2.0.32",
3
+ "version": "2.0.34",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "scripts": {
@@ -37,7 +37,8 @@
37
37
  "replace-in-file": "^7.0.1",
38
38
  "sleep-promise": "^9.1.0",
39
39
  "ssh2-sftp-client": "^11.0.0",
40
- "styled-components": "^5.3.9"
40
+ "styled-components": "^5.3.9",
41
+ "unzipper": "^0.12.3"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@types/mustache": "^4.2.5",
@@ -45,6 +46,7 @@
45
46
  "@types/react": "^18.2.14",
46
47
  "@types/react-dom": "^18.3.0",
47
48
  "@types/ssh2-sftp-client": "^9.0.4",
49
+ "@types/unzipper": "^0.10.10",
48
50
  "copyfiles": "^2.4.1",
49
51
  "typedoc": "^0.23.28",
50
52
  "typescript": "^4.9.5"
@@ -4,6 +4,8 @@ import Client from "ssh2-sftp-client";
4
4
  import fs from "fs";
5
5
  import mustache from "mustache";
6
6
  import path from "path";
7
+ import unzipper from 'unzipper';
8
+
7
9
  const { promisify } = require("util");
8
10
  const execPromise = promisify(ChildProcess.exec);
9
11
 
@@ -14,17 +16,17 @@ export let PORT = 56777;
14
16
 
15
17
  interface FileObject {
16
18
  name: string;
17
- content: string; // Це буде Base64 закодовані дані
19
+ content: string; // Це буде Base64 закодовані дані
18
20
  }
19
21
 
20
- interface ISFTP{
21
- host:string ,
22
- port: number,
23
- username: string,
24
- password: string;
22
+ interface ISFTP {
23
+ host: string;
24
+ port: number;
25
+ username: string;
26
+ password: string;
25
27
  }
26
28
 
27
- export class ServerUtil {
29
+ export class ServerUtil {
28
30
  DOMAIN_HOME = "/etc/nginx/sites-enabled";
29
31
 
30
32
  ssh?: NodeSSH;
@@ -156,7 +158,7 @@ export class ServerUtil {
156
158
  return true;
157
159
  }
158
160
 
159
- // checking if the ssl certificate exists
161
+ // checking if the ssl certificate exists
160
162
  async domainNginxCertsExist(host: string): Promise<boolean> {
161
163
  try {
162
164
  let result = await this.exec(`ls /etc/letsencrypt/live/${host}`);
@@ -204,34 +206,35 @@ export class ServerUtil {
204
206
 
205
207
  return true;
206
208
  }
207
-
208
-
209
209
 
210
210
  async uploadDirectoryToSftp(
211
211
  localDir: string,
212
212
  remoteDir: string,
213
- sftpConfig: ISFTP
213
+ sftpConfig: any
214
214
  ) {
215
215
  const sftp = new Client();
216
216
 
217
217
  try {
218
218
  await sftp.connect(sftpConfig);
219
-
220
219
  const items = fs.readdirSync(localDir, { withFileTypes: true });
221
220
 
222
- // Перебираємо кожен елемент (файл чи папку)
223
221
  for (const item of items) {
224
222
  const localPath = path.join(localDir, item.name);
225
223
  const remotePath = `${remoteDir}/${item.name}`;
226
224
 
227
225
  if (item.isDirectory()) {
228
- // Якщо це директорія, створюємо її на сервері
229
- await sftp.mkdir(remotePath, true);
226
+ // Створення підкаталогу на віддаленому сервері
227
+ await sftp.mkdir(remotePath, true).catch(async (err) => {
228
+ if (err.code !== 4) { // Ігноруємо помилку "Directory already exists"
229
+ console.error(`Помилка під час створення папки: ${remotePath}`, err);
230
+ throw err;
231
+ }
232
+ });
230
233
 
231
- // Рекурсивно передаємо вміст цієї директорії
234
+ // Рекурсивне копіювання вмісту директорії
232
235
  await this.uploadDirectoryToSftp(localPath, remotePath, sftpConfig);
233
236
  } else {
234
- // Якщо це файл, передаємо його на сервер
237
+ // Завантаження файлу на віддалений сервер
235
238
  await sftp.put(localPath, remotePath);
236
239
  console.log(`Передано файл: ${localPath} -> ${remotePath}`);
237
240
  }
@@ -241,21 +244,87 @@ export class ServerUtil {
241
244
  } catch (err) {
242
245
  console.error('Помилка під час передавання файлів через SFTP:', err);
243
246
  } finally {
244
- // Закриваємо підключення до SFTP
245
247
  await sftp.end();
246
248
  }
247
249
  }
248
-
249
250
 
250
251
  async generateNginxConfig(domain: string, rootPath: string): Promise<string> {
251
- const templatePath = path.join(__dirname, '..', 'templates', 'nginx-template.conf');
252
+ const templatePath = path.join(
253
+ __dirname,
254
+ "..",
255
+ "templates",
256
+ "nginx-template.conf"
257
+ );
252
258
  const template = fs.readFileSync(templatePath, "utf8");
253
259
  const config = mustache.render(template, { domain, rootPath });
254
260
  return config;
255
261
  }
256
- }
257
-
258
-
259
262
 
260
263
 
264
+ async extractUploadedZip(name:string, file:any) {
265
+ const zipFilePath = file.path;
266
+ const outputDir = path.join(__dirname, '..', 'uploads', name);
267
+
268
+ console.log('Looking for ZIP file at:', zipFilePath);
269
+ console.log('Extracting to:', outputDir);
270
+
271
+ ensureDirectoryExistence(outputDir);
272
+
273
+ if (!fs.existsSync(zipFilePath)) {
274
+ console.error('Error: File not found:', zipFilePath);
275
+ return;
276
+ }
277
+
278
+ try {
279
+ await new Promise((resolve, reject) => {
280
+ fs.createReadStream(zipFilePath)
281
+ .pipe(unzipper.Parse())
282
+ .on('entry', (entry) => {
283
+ // Видаляємо перший сегмент шляху, щоб уникнути кореневої директорії
284
+ const entryPath = path.join(
285
+ outputDir,
286
+ ...entry.path.split('/').slice(1)
287
+ );
288
+
289
+ if (entry.type === 'Directory') {
290
+ ensureDirectoryExistence(entryPath);
291
+ } else {
292
+ ensureDirectoryExistence(path.dirname(entryPath));
293
+ entry.pipe(fs.createWriteStream(entryPath));
294
+ }
295
+ })
296
+ .on('close', resolve)
297
+ .on('error', reject);
298
+ });
299
+
300
+ console.log('File successfully extracted.');
301
+ } catch (err) {
302
+ console.error('Error extracting file:', err);
303
+ }
304
+ }
305
+
306
+ async ensureDirectoryExistsViaSSH(sshConfig:ISFTP, remoteDir:string) {
307
+ const ssh = new NodeSSH();
308
+
309
+ try {
310
+ await ssh.connect(sshConfig);
311
+
312
+ // Перевірка, чи існує директорія, і створення її, якщо вона не існує
313
+ const command = `if [ ! -d "${remoteDir}" ]; then mkdir -p "${remoteDir}"; fi`;
314
+ await ssh.execCommand(command);
315
+ console.log(`Перевірено або створено папку: ${remoteDir}`);
316
+ } catch (err) {
317
+ console.error(
318
+ 'Помилка під час перевірки або створення папки через SSH:',
319
+ err
320
+ );
321
+ throw err;
322
+ } finally {
323
+ ssh.dispose();
324
+ }
325
+ }
326
+ }
327
+ function ensureDirectoryExistence(outputDir: string) {
328
+ throw new Error("Function not implemented.");
329
+ }
261
330