ramm 0.0.27 → 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");
@@ -247,10 +260,7 @@ var createNftTable = ({ allowedIpV4 }) => {
247
260
  var setupNftable = async ({
248
261
  allowedIpV4
249
262
  }) => {
250
- const listTable = await execCommand("nft list table inet ramm");
251
- if (listTable.spawnResult.exitCode === 0) {
252
- await execCommand("nft delete table inet ramm");
253
- }
263
+ await execCommand("nft flush ruleset");
254
264
  const nftTable = createNftTable({ allowedIpV4 });
255
265
  await execCommand(`nft -f - <<EOF
256
266
  ${nftTable}
@@ -287,7 +297,6 @@ var normalizeFileContent = (str) => {
287
297
  };
288
298
  var createDir = async (str) => {
289
299
  const dirname = str.split("/").slice(0, -1).join("/");
290
- debugApiCall(`exists(${dirname})`);
291
300
  const exist = await exists(dirname);
292
301
  if (exist) {
293
302
  return;
@@ -296,11 +305,9 @@ var createDir = async (str) => {
296
305
  };
297
306
  var checkStrInFile = async (filePath, str) => {
298
307
  const file2 = Bun.file(filePath);
299
- debugApiCall(`file(${filePath}).exists())`);
300
308
  if (!await file2.exists()) {
301
309
  return false;
302
310
  }
303
- debugApiCall(`file(${filePath}).text()`);
304
311
  const fileText = await file2.text();
305
312
  if (fileText.includes(str)) {
306
313
  return true;
@@ -310,7 +317,6 @@ var checkStrInFile = async (filePath, str) => {
310
317
  var createFileIfNeed = async (rawFilePath) => {
311
318
  const filePath = normalizePath(rawFilePath);
312
319
  await createDir(filePath);
313
- debugApiCall(`file(${filePath}).exists())`);
314
320
  if (!await file(filePath).exists()) {
315
321
  await execCommand(`touch ${filePath}`);
316
322
  }
@@ -321,24 +327,20 @@ var writeIfNew = async (rawFilePath, str) => {
321
327
  if (await checkStrInFile(filePath, str)) {
322
328
  return;
323
329
  }
324
- debugApiCall(`appendFile(${filePath})`);
325
330
  await appendFile(filePath, normalizeFileContent(str));
326
331
  };
327
332
  var writeFile = async (pathToFile, str) => {
328
333
  const normalizedPath = normalizePath(pathToFile);
329
334
  await createFileIfNeed(normalizedPath);
330
- debugApiCall(`write(${normalizedPath})`);
331
335
  await write(normalizedPath, str);
332
336
  };
333
337
  var writeIfNewCompletely = async (pathToFile, str) => {
334
338
  const normalizedPath = normalizePath(pathToFile);
335
339
  await createFileIfNeed(normalizedPath);
336
- debugApiCall(`file(${normalizedPath}).text()`);
337
340
  const fileText = await file(normalizedPath).text();
338
341
  if (fileText === str) {
339
342
  return;
340
343
  }
341
- debugApiCall(`write(${normalizedPath})`);
342
344
  await write(normalizedPath, str);
343
345
  };
344
346
  // src/ssh.ts
@@ -351,29 +353,27 @@ var addKeyToHostConfig = async (pathToHost, address, pathToKey) => {
351
353
  await writeIfNew(pathToHost, text);
352
354
  };
353
355
  var getServerFingerprintBySsh = async (context) => {
354
- const { output } = await execBySsh('ssh-keyscan -t ed25519 localhost | grep -v "^#"', context);
355
- 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);
356
358
  };
357
359
  async function createSshKey(pathToKey, comment) {
360
+ printFunction(createSshKey.name);
358
361
  const name = pathToKey.split("/").at(-1);
359
362
  const pathToKeyPub = `${pathToKey}.pub`;
360
363
  const pathToDir = pathToKey.split("/").slice(0, -1).join("/");
361
364
  const pathToKeyFile = file2(pathToKey);
362
365
  const pathToKeyPubFile = file2(pathToKeyPub);
363
- debugApiCall(`file(${pathToKey}).exist()`);
364
- debugApiCall(`file(${pathToKeyPub}).exist()`);
365
366
  if (await pathToKeyFile.exists() && await pathToKeyPubFile.exists()) {
366
367
  return await pathToKeyPubFile.text();
367
368
  }
368
369
  await execCommand(`mkdir -p ${pathToDir}`);
369
370
  await execCommand(`ssh-keygen -t ed25519 -f ${pathToKey} -N "" -C "${comment || name}"`);
370
371
  await execCommand(`chmod 600 ${pathToKey}`);
371
- debugApiCall(`file(${pathToKeyPub}).text()`);
372
372
  const pubKey = await Bun.file(pathToKeyPub).text();
373
373
  return pubKey;
374
374
  }
375
375
  var addSshKeyToAuthorized = async (pubKey, context) => {
376
- const { output: keys } = await execBySsh("cat .ssh/authorized_keys", context);
376
+ const { stdout: keys } = await execBySsh("cat .ssh/authorized_keys", context);
377
377
  if (keys.includes(pubKey)) {
378
378
  return;
379
379
  }
@@ -403,7 +403,7 @@ var createCron = async ({
403
403
  const pathToFileNorm = normalizePath(pathToFile);
404
404
  const constructedLine = `${time} ${pathToFileNorm}`;
405
405
  const tempFile = `/tmp/ramm_cron}`;
406
- const { output: cronConfig } = await execCommandMayError("crontab -l");
406
+ const { stdout: cronConfig } = await execCommandMayError("crontab -l");
407
407
  let newCronConfig = cronConfig;
408
408
  if (cronConfig.includes(constructedLine)) {
409
409
  return;
@@ -441,14 +441,14 @@ var buildAndRunOverSsh = async ({
441
441
  };
442
442
  var pathToJson = "/tmp/ramm_json";
443
443
  var passVarsClient = async (data, context) => {
444
+ printFunction("passVarsClient");
444
445
  const json = JSON.stringify(data);
445
- debugApiCall(`writeFile(${pathToJson})`);
446
446
  await writeFile(pathToJson, json);
447
447
  await copyFilesBySsh(pathToJson, pathToJson, context);
448
448
  await execCommand(`rm -rf ${pathToJson}`);
449
449
  };
450
450
  var passVarsServer = async () => {
451
- debugApiCall(`file(${pathToJson}).json`);
451
+ printFunction("passVarsServer");
452
452
  const jsonData = await file3(pathToJson).json();
453
453
  await execCommand(`rm -rf ${pathToJson}`);
454
454
  return jsonData;
@@ -462,6 +462,7 @@ export {
462
462
  runPodmanContainerService,
463
463
  runPodmanContainer,
464
464
  restartSystemdService,
465
+ printBlock,
465
466
  passVarsServer,
466
467
  passVarsClient,
467
468
  normalizePath,
@@ -473,7 +474,6 @@ export {
473
474
  getServerFingerprintBySsh,
474
475
  execCommandMayError as execCommand,
475
476
  execBySsh,
476
- debugBlock,
477
477
  createCron,
478
478
  createAndAddSshKey,
479
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.27",
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"