ramm 0.0.28 → 0.0.29

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/dist/ramm.js CHANGED
@@ -2,18 +2,18 @@
2
2
  // src/base/base.ts
3
3
  var {spawn } = globalThis.Bun;
4
4
 
5
- // src/debug.ts
6
- var debugInternal = (func, command) => {
7
- console.info(`>>>${func}<<< ${command}`);
5
+ // src/print.ts
6
+ var printInternal = (left, right) => {
7
+ console.info(`\x1B[32m${left}:\x1B[0m \x1B[38;5;85m${right}\x1B[0m`);
8
8
  };
9
- var debugCommand = (command) => {
10
- debugInternal(">>>\x1B[32mCommand\x1B[0m<<<", `\x1B[38;5;85m${command}\x1B[0m`);
9
+ var printCommand = (command) => {
10
+ printInternal("Command", command);
11
11
  };
12
- var debugApiCall = (command) => {
13
- debugInternal(">>>\x1B[32mapi command\x1B[0m<<<", `\x1B[38;5;85m${command}\x1B[0m`);
12
+ var printFunction = (func) => {
13
+ printInternal("Function", func);
14
14
  };
15
- var debugBlock = (text) => {
16
- debugInternal("\x1B[34mBlock\x1B[0m", `\x1B[38;5;81m${text}\x1B[0m`);
15
+ var printBlock = (name) => {
16
+ console.info(`\x1B[34mBlock:\x1B[0m \x1B[38;5;81m${name}\x1B[0m`);
17
17
  };
18
18
 
19
19
  // src/context.ts
@@ -43,32 +43,36 @@ class Context {
43
43
  }
44
44
 
45
45
  // src/base/tee.ts
46
- var tee = async (read) => {
46
+ var tee = async (read, write, prefix) => {
47
47
  const reader = read.getReader();
48
+ let leftover = "";
48
49
  let output = "";
50
+ const decoder = new TextDecoder("utf-8");
49
51
  while (true) {
50
- const { value, done: doneReading } = await reader.read();
51
- if (doneReading) {
52
+ const { value, done } = await reader.read();
53
+ if (done) {
54
+ if (leftover)
55
+ write(prefix + leftover + `
56
+ `);
52
57
  return output;
53
58
  }
54
- const decoder = new TextDecoder("utf-8");
55
- output += decoder.decode(value);
56
- process.stdout.write(value);
57
- }
58
- };
59
- var teeErr = async (read) => {
60
- const reader = read.getReader();
61
- let output = "";
62
- while (true) {
63
- const { value, done: doneReading } = await reader.read();
64
- if (doneReading) {
65
- return output;
59
+ const decodedOutput = decoder.decode(value, { stream: true });
60
+ output += decodedOutput;
61
+ const lines = (leftover + decodedOutput).split(`
62
+ `);
63
+ leftover = lines.pop() ?? "";
64
+ for (const line of lines) {
65
+ write(prefix + line + `
66
+ `);
66
67
  }
67
- const decoder = new TextDecoder("utf-8");
68
- output += decoder.decode(value);
69
- process.stderr.write(value);
70
68
  }
71
69
  };
70
+ var teeStdout = (read, prefix) => {
71
+ return tee(read, (text) => process.stdout.write(text), prefix);
72
+ };
73
+ var teeStderr = (read, prefix) => {
74
+ return tee(read, (text) => process.stderr.write(text), prefix);
75
+ };
72
76
 
73
77
  // src/base/base.ts
74
78
  var defaultContext = new Context({
@@ -77,29 +81,36 @@ var defaultContext = new Context({
77
81
  userspace: false,
78
82
  sudo: false
79
83
  });
80
- var execCommandMayError = async (command) => {
81
- debugCommand(command);
82
- const result = spawn(["bash", "-c", command], {
84
+ var execCommandRaw = async (command, { store = {}, signal, env, cwd, prefix = "" } = {}) => {
85
+ const spawnResult = spawn(["bash", "-c", command], {
83
86
  stdin: "inherit",
84
87
  stdout: "pipe",
85
- stderr: "pipe"
88
+ stderr: "pipe",
89
+ signal,
90
+ cwd,
91
+ env
86
92
  });
87
- const [output, outputErr] = await Promise.all([
88
- tee(result.stdout),
89
- teeErr(result.stderr)
93
+ store.spawnResult = spawnResult;
94
+ const [stdout, stderr] = await Promise.all([
95
+ teeStdout(spawnResult.stdout, prefix),
96
+ teeStderr(spawnResult.stderr, prefix)
90
97
  ]);
91
- await result.exited;
98
+ await spawnResult.exited;
92
99
  return {
93
- outputErr,
94
- output,
95
- spawnResult: result
100
+ stderr,
101
+ stdout,
102
+ spawnResult
96
103
  };
97
104
  };
98
- var execCommand = async (command) => {
99
- const result = await execCommandMayError(command);
105
+ var execCommandMayError = async (command, props) => {
106
+ printCommand(command);
107
+ return execCommandRaw(command, props);
108
+ };
109
+ var execCommand = async (command, props) => {
110
+ const result = await execCommandMayError(command, props);
100
111
  if (result.spawnResult.exitCode !== 0) {
101
- console.error(">>>Error<<<");
102
- console.error("command:", command);
112
+ console.error(`Error exit code:" ${result.spawnResult.exitCode}`);
113
+ console.error(`Command: ${command}`);
103
114
  throw new Error(command);
104
115
  }
105
116
  return result;
@@ -148,6 +159,7 @@ var stopSystemdService = async (constext, name) => {
148
159
  await execCommand(formatUserspace(constext, `systemctl stop ${name}`));
149
160
  };
150
161
  var restartSystemdService = async (name, constext = defaultContext) => {
162
+ printFunction(`restartSystemdService ${name}`);
151
163
  await execCommand(formatUserspace(constext, `systemctl restart ${name}`));
152
164
  };
153
165
  var checkSystemdService = async (context, serviceName) => {
@@ -155,6 +167,7 @@ var checkSystemdService = async (context, serviceName) => {
155
167
  return spawnResult.exitCode === 0;
156
168
  };
157
169
  var createSystemdService = async (context, serviceName, pathToServiceFile) => {
170
+ printFunction(`createSystemdService ${serviceName}`);
158
171
  const pathToSeviceTarget = getSystemdPathToService(context, serviceName);
159
172
  await execCommand(`cp -v ${pathToServiceFile} ${pathToSeviceTarget}`);
160
173
  await execCommand(formatUserspace(context, "systemctl daemon-reload"));
@@ -172,10 +185,10 @@ var installPodman = async () => {
172
185
  var createNetwork = async () => {
173
186
  const netwroks = await execCommand("podman network inspect $(podman network ls -q) -f '{{.NetworkInterface}}'");
174
187
  const podmanNetworks = await execCommand("podman network ls");
175
- if (podmanNetworks.output.includes("ramm")) {
188
+ if (podmanNetworks.stdout.includes("ramm")) {
176
189
  return;
177
190
  }
178
- if (netwroks.output.includes("podman_ramm")) {
191
+ if (netwroks.stdout.includes("podman_ramm")) {
179
192
  return;
180
193
  }
181
194
  await execCommand("podman network create --interface-name=podman_ramm ramm");
@@ -206,7 +219,7 @@ var runPodmanContainerService = async (name, command, context = defaultContext)
206
219
  };
207
220
  var addNftPodmanRule = async () => {
208
221
  const podmanNetworksResult = await execCommand("podman network inspect $(podman network ls -q) -f '{{.NetworkInterface}}'");
209
- const podmanNetworks = podmanNetworksResult.output.trim().split(`
222
+ const podmanNetworks = podmanNetworksResult.stdout.trim().split(`
210
223
  `);
211
224
  await execCommand(`nft add set inet ramm podman_interfaces '{ type ifname; flags dynamic; elements = { ${podmanNetworks.join(", ")} }; }'`);
212
225
  await execCommand("nft insert rule inet ramm prerouting iifname @podman_interfaces accept");
@@ -284,7 +297,6 @@ var normalizeFileContent = (str) => {
284
297
  };
285
298
  var createDir = async (str) => {
286
299
  const dirname = str.split("/").slice(0, -1).join("/");
287
- debugApiCall(`exists(${dirname})`);
288
300
  const exist = await exists(dirname);
289
301
  if (exist) {
290
302
  return;
@@ -293,11 +305,9 @@ var createDir = async (str) => {
293
305
  };
294
306
  var checkStrInFile = async (filePath, str) => {
295
307
  const file2 = Bun.file(filePath);
296
- debugApiCall(`file(${filePath}).exists())`);
297
308
  if (!await file2.exists()) {
298
309
  return false;
299
310
  }
300
- debugApiCall(`file(${filePath}).text()`);
301
311
  const fileText = await file2.text();
302
312
  if (fileText.includes(str)) {
303
313
  return true;
@@ -307,7 +317,6 @@ var checkStrInFile = async (filePath, str) => {
307
317
  var createFileIfNeed = async (rawFilePath) => {
308
318
  const filePath = normalizePath(rawFilePath);
309
319
  await createDir(filePath);
310
- debugApiCall(`file(${filePath}).exists())`);
311
320
  if (!await file(filePath).exists()) {
312
321
  await execCommand(`touch ${filePath}`);
313
322
  }
@@ -318,24 +327,20 @@ var writeIfNew = async (rawFilePath, str) => {
318
327
  if (await checkStrInFile(filePath, str)) {
319
328
  return;
320
329
  }
321
- debugApiCall(`appendFile(${filePath})`);
322
330
  await appendFile(filePath, normalizeFileContent(str));
323
331
  };
324
332
  var writeFile = async (pathToFile, str) => {
325
333
  const normalizedPath = normalizePath(pathToFile);
326
334
  await createFileIfNeed(normalizedPath);
327
- debugApiCall(`write(${normalizedPath})`);
328
335
  await write(normalizedPath, str);
329
336
  };
330
337
  var writeIfNewCompletely = async (pathToFile, str) => {
331
338
  const normalizedPath = normalizePath(pathToFile);
332
339
  await createFileIfNeed(normalizedPath);
333
- debugApiCall(`file(${normalizedPath}).text()`);
334
340
  const fileText = await file(normalizedPath).text();
335
341
  if (fileText === str) {
336
342
  return;
337
343
  }
338
- debugApiCall(`write(${normalizedPath})`);
339
344
  await write(normalizedPath, str);
340
345
  };
341
346
  // src/ssh.ts
@@ -348,29 +353,27 @@ var addKeyToHostConfig = async (pathToHost, address, pathToKey) => {
348
353
  await writeIfNew(pathToHost, text);
349
354
  };
350
355
  var getServerFingerprintBySsh = async (context) => {
351
- const { output } = await execBySsh('ssh-keyscan -t ed25519 localhost | grep -v "^#"', context);
352
- return output.replace("localhost", context.domain);
356
+ const { stdout } = await execBySsh('ssh-keyscan -t ed25519 localhost | grep -v "^#"', context);
357
+ return stdout.replace("localhost", context.domain);
353
358
  };
354
359
  async function createSshKey(pathToKey, comment) {
360
+ printFunction(createSshKey.name);
355
361
  const name = pathToKey.split("/").at(-1);
356
362
  const pathToKeyPub = `${pathToKey}.pub`;
357
363
  const pathToDir = pathToKey.split("/").slice(0, -1).join("/");
358
364
  const pathToKeyFile = file2(pathToKey);
359
365
  const pathToKeyPubFile = file2(pathToKeyPub);
360
- debugApiCall(`file(${pathToKey}).exist()`);
361
- debugApiCall(`file(${pathToKeyPub}).exist()`);
362
366
  if (await pathToKeyFile.exists() && await pathToKeyPubFile.exists()) {
363
367
  return await pathToKeyPubFile.text();
364
368
  }
365
369
  await execCommand(`mkdir -p ${pathToDir}`);
366
370
  await execCommand(`ssh-keygen -t ed25519 -f ${pathToKey} -N "" -C "${comment || name}"`);
367
371
  await execCommand(`chmod 600 ${pathToKey}`);
368
- debugApiCall(`file(${pathToKeyPub}).text()`);
369
372
  const pubKey = await Bun.file(pathToKeyPub).text();
370
373
  return pubKey;
371
374
  }
372
375
  var addSshKeyToAuthorized = async (pubKey, context) => {
373
- const { output: keys } = await execBySsh("cat .ssh/authorized_keys", context);
376
+ const { stdout: keys } = await execBySsh("cat .ssh/authorized_keys", context);
374
377
  if (keys.includes(pubKey)) {
375
378
  return;
376
379
  }
@@ -400,7 +403,7 @@ var createCron = async ({
400
403
  const pathToFileNorm = normalizePath(pathToFile);
401
404
  const constructedLine = `${time} ${pathToFileNorm}`;
402
405
  const tempFile = `/tmp/ramm_cron}`;
403
- const { output: cronConfig } = await execCommandMayError("crontab -l");
406
+ const { stdout: cronConfig } = await execCommandMayError("crontab -l");
404
407
  let newCronConfig = cronConfig;
405
408
  if (cronConfig.includes(constructedLine)) {
406
409
  return;
@@ -438,14 +441,14 @@ var buildAndRunOverSsh = async ({
438
441
  };
439
442
  var pathToJson = "/tmp/ramm_json";
440
443
  var passVarsClient = async (data, context) => {
444
+ printFunction("passVarsClient");
441
445
  const json = JSON.stringify(data);
442
- debugApiCall(`writeFile(${pathToJson})`);
443
446
  await writeFile(pathToJson, json);
444
447
  await copyFilesBySsh(pathToJson, pathToJson, context);
445
448
  await execCommand(`rm -rf ${pathToJson}`);
446
449
  };
447
450
  var passVarsServer = async () => {
448
- debugApiCall(`file(${pathToJson}).json`);
451
+ printFunction("passVarsServer");
449
452
  const jsonData = await file3(pathToJson).json();
450
453
  await execCommand(`rm -rf ${pathToJson}`);
451
454
  return jsonData;
@@ -459,6 +462,7 @@ export {
459
462
  runPodmanContainerService,
460
463
  runPodmanContainer,
461
464
  restartSystemdService,
465
+ printBlock,
462
466
  passVarsServer,
463
467
  passVarsClient,
464
468
  normalizePath,
@@ -470,7 +474,6 @@ export {
470
474
  getServerFingerprintBySsh,
471
475
  execCommandMayError as execCommand,
472
476
  execBySsh,
473
- debugBlock,
474
477
  createCron,
475
478
  createAndAddSshKey,
476
479
  copyFilesBySsh,
@@ -1,18 +1,35 @@
1
+ import { type Subprocess } from "bun";
1
2
  import { Context } from "../context.ts";
2
3
  export declare const defaultContext: Context;
3
- export declare const execCommandMayError: (command: string) => Promise<{
4
- outputErr: string;
5
- output: string;
6
- spawnResult: import("bun").Subprocess<"inherit", "pipe", "pipe">;
4
+ export type ExecCommandStore = {
5
+ spawnResult?: Subprocess<"inherit", "pipe", "pipe">;
6
+ };
7
+ type ExecProps = {
8
+ store?: ExecCommandStore;
9
+ env?: Record<string, string>;
10
+ cwd?: string;
11
+ prefix?: string;
12
+ signal?: AbortSignal;
13
+ } | void;
14
+ export declare const execCommandRaw: (command: string, { store, signal, env, cwd, prefix }?: ExecProps) => Promise<{
15
+ stderr: string;
16
+ stdout: string;
17
+ spawnResult: Subprocess<"inherit", "pipe", "pipe">;
7
18
  }>;
8
- export declare const execCommand: (command: string) => Promise<{
9
- outputErr: string;
10
- output: string;
11
- spawnResult: import("bun").Subprocess<"inherit", "pipe", "pipe">;
19
+ export declare const execCommandMayError: (command: string, props: ExecProps) => Promise<{
20
+ stderr: string;
21
+ stdout: string;
22
+ spawnResult: Subprocess<"inherit", "pipe", "pipe">;
23
+ }>;
24
+ export declare const execCommand: (command: string, props: ExecProps) => Promise<{
25
+ stderr: string;
26
+ stdout: string;
27
+ spawnResult: Subprocess<"inherit", "pipe", "pipe">;
12
28
  }>;
13
29
  export declare const copyFilesBySsh: (from: string, to: string, context: Context) => Promise<void>;
14
30
  export declare const execBySsh: (command: string, context: Context) => Promise<{
15
- outputErr: string;
16
- output: string;
17
- spawnResult: import("bun").Subprocess<"inherit", "pipe", "pipe">;
31
+ stderr: string;
32
+ stdout: string;
33
+ spawnResult: Subprocess<"inherit", "pipe", "pipe">;
18
34
  }>;
35
+ export {};
@@ -1,3 +1,2 @@
1
- export declare const tee: (read: ReadableStream) => Promise<string>;
2
- export declare const teeErr: (read: ReadableStream) => Promise<string>;
3
- export declare const readStreamToStr: (read: ReadableStream) => Promise<string>;
1
+ export declare const teeStdout: (read: ReadableStream, prefix: string) => Promise<string>;
2
+ export declare const teeStderr: (read: ReadableStream, prefix: string) => Promise<string>;
@@ -2,8 +2,8 @@ import type { Context } from "./context.ts";
2
2
  export declare const installPodman: () => Promise<void>;
3
3
  export declare const getCreateCommand: (name: string) => Promise<string>;
4
4
  export declare const loginPodman: (address: string, login: string, password: string) => Promise<{
5
- outputErr: string;
6
- output: string;
5
+ stderr: string;
6
+ stdout: string;
7
7
  spawnResult: import("bun").Subprocess<"inherit", "pipe", "pipe">;
8
8
  }>;
9
9
  export declare const runPodmanContainer: (name: string, command: string) => Promise<void>;
@@ -0,0 +1,3 @@
1
+ export declare const printCommand: (command: string) => void;
2
+ export declare const printFunction: (func: string) => void;
3
+ export declare const printBlock: (name: string) => void;
@@ -5,7 +5,7 @@ export { installPodman, runPodmanContainer, loginPodman } from "./podman.ts";
5
5
  export { runPodmanContainerService, addNftPodmanRule } from "./podman.ts";
6
6
  export { restartSystemdService } from "./systemd.ts";
7
7
  export { installSystemPackage } from "./packages.ts";
8
- export { debugBlock } from "./debug.ts";
8
+ export { printBlock } from "./print.ts";
9
9
  export { setupNftable } from "./nft.ts";
10
10
  export { writeIfNew, writeFile, writeIfNewCompletely as writeFileIfNotMatch, normalizeFileContent, } from "./files.ts";
11
11
  export { createAndAddSshKey, getServerFingerprintBySsh, addKeyToHostConfig, setupSshKey, } from "./ssh.ts";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ramm",
3
3
  "type": "module",
4
- "version": "0.0.28",
4
+ "version": "0.0.29",
5
5
  "scripts": {
6
6
  "build": "bun build ./src/ramm.ts --target bun --outdir ./dist && cp ./src/bun.sh ./dist/bun.sh",
7
7
  "types": "tsc --project tsconfig.types.json"