ramm 0.0.62 → 0.0.64

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/bun.sh ADDED
@@ -0,0 +1,23 @@
1
+ #!/bin/bash
2
+
3
+ if ! command -v unzip &> /dev/null; then
4
+ . /etc/os-release
5
+
6
+ if [[ "$ID_LIKE" == *"rhel"* ]]; then
7
+ sudo dnf install -y unzip
8
+ fi
9
+
10
+ if [[ "$ID" == "ubuntu" ]]; then
11
+ sudo apt update
12
+ sudo apt install -y unzip
13
+ fi
14
+ fi
15
+
16
+ if ! command -v bun &> /dev/null; then
17
+ echo "Installing bun..."
18
+
19
+ curl -fsSL https://bun.sh/install | bash
20
+ ln -s "$HOME/.bun/bin/bun" /usr/local/bin/bun
21
+ else
22
+ echo "Already installed bun."
23
+ fi
package/dist/ramm.js ADDED
@@ -0,0 +1,617 @@
1
+ // @bun
2
+ // src/base/base.ts
3
+ var {spawn } = globalThis.Bun;
4
+
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
+ };
9
+ var printCommand = (command) => {
10
+ printInternal("Command", command);
11
+ };
12
+ var printFunction = (func) => {
13
+ printInternal("Function", func);
14
+ };
15
+ var printBlock = (name) => {
16
+ console.info(`\x1B[34mBlock:\x1B[0m \x1B[38;5;81m${name}\x1B[0m`);
17
+ };
18
+
19
+ // src/context.ts
20
+ class Context {
21
+ user;
22
+ domain;
23
+ userspace = false;
24
+ sudo = false;
25
+ sshKey;
26
+ params = {};
27
+ constructor({
28
+ user,
29
+ address,
30
+ userspace = false,
31
+ sudo = false,
32
+ sshKey
33
+ }) {
34
+ this.user = user;
35
+ this.domain = address;
36
+ this.sudo = sudo;
37
+ this.userspace = userspace;
38
+ this.sshKey = sshKey;
39
+ }
40
+ getAddress() {
41
+ return `${this.user}@${this.domain}`;
42
+ }
43
+ }
44
+
45
+ // src/base/tee.ts
46
+ var tee = async (read, write, prefix) => {
47
+ const reader = read.getReader();
48
+ let leftover = "";
49
+ let output = "";
50
+ const decoder = new TextDecoder("utf-8");
51
+ while (true) {
52
+ const { value, done } = await reader.read();
53
+ if (done) {
54
+ if (leftover)
55
+ write(prefix + leftover + `
56
+ `);
57
+ return output;
58
+ }
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
+ `);
67
+ }
68
+ }
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
+ };
76
+
77
+ // src/base/base.ts
78
+ var defaultContext = new Context({
79
+ user: "root",
80
+ address: "0.0.0.0",
81
+ userspace: false,
82
+ sudo: false
83
+ });
84
+ var execCommandRaw = async (command, { store = {}, signal, env, cwd, prefix = "" } = {}, ctx) => {
85
+ const finalCommand = ctx?.sudo ? `sudo ${command}` : command;
86
+ const spawnResult = spawn(["bash", "-c", finalCommand], {
87
+ stdin: "inherit",
88
+ stdout: "pipe",
89
+ stderr: "pipe",
90
+ signal,
91
+ cwd,
92
+ env
93
+ });
94
+ store.spawnResult = spawnResult;
95
+ const [stdout, stderr] = await Promise.all([
96
+ teeStdout(spawnResult.stdout, prefix),
97
+ teeStderr(spawnResult.stderr, prefix)
98
+ ]);
99
+ await spawnResult.exited;
100
+ return {
101
+ stderr,
102
+ stdout,
103
+ spawnResult
104
+ };
105
+ };
106
+ var execCommandMayError = async (command, props, context) => {
107
+ printCommand(command);
108
+ return execCommandRaw(command, props, context);
109
+ };
110
+ var execCommand = async (command, props, context) => {
111
+ const callSiteError = new Error(command);
112
+ const result = await execCommandMayError(command, props, context);
113
+ if (result.spawnResult.exitCode !== 0) {
114
+ console.error(`<${command}> exitCode: ${result.spawnResult.exitCode}`);
115
+ callSiteError.stack = callSiteError.stack?.split(`
116
+ `).slice(1).join(`
117
+ `);
118
+ throw callSiteError;
119
+ }
120
+ return result;
121
+ };
122
+ var copyFilesOverSsh = async (from, to, context) => {
123
+ const sshKeyPart = context.sshKey ? ` -e "ssh -i ${context.sshKey}"` : "";
124
+ await execCommand(`rsync -avz${sshKeyPart} ${from} ${context.getAddress()}:${to}`);
125
+ };
126
+ var execCommandOverSsh = async (command, context) => {
127
+ const sshKeyPart = context.sshKey ? ` -i ${context.sshKey}` : "";
128
+ const escapedCommand = command.replace(/'/g, "'\\''");
129
+ return await execCommand(`ssh${sshKeyPart} ${context.getAddress()} '${escapedCommand}'`);
130
+ };
131
+ // src/init.ts
132
+ var installBunOverSsh = async (context) => {
133
+ const bunPath = new URL(import.meta.resolve("./bun.sh")).pathname;
134
+ await copyFilesOverSsh(bunPath, "./bun.sh", context);
135
+ await execCommandOverSsh("./bun.sh", context);
136
+ };
137
+ // src/packages.ts
138
+ var dnfOs = ["rocky", "fedora", "alma"];
139
+ var aptOs = ["ubuntu"];
140
+ var getManagerByOs = (osName) => {
141
+ if (aptOs.includes(osName)) {
142
+ return "apt";
143
+ } else if (dnfOs.includes(osName)) {
144
+ return "dnf";
145
+ } else {
146
+ throw new Error(`Unsupported OS: ${osName}`);
147
+ }
148
+ };
149
+ var getManagerConfig = (manager, packageConfig) => {
150
+ if (packageConfig.managers && manager in packageConfig.managers) {
151
+ const managerEnt = packageConfig.managers[manager];
152
+ return managerEnt;
153
+ }
154
+ return {
155
+ name: packageConfig.name,
156
+ command: packageConfig.command
157
+ };
158
+ };
159
+ var getInstallCommand = (manager, config) => {
160
+ if (manager === "apt") {
161
+ return `apt install -y ${config.name}`;
162
+ } else if (manager === "dnf") {
163
+ return `dnf install -y ${config.name}`;
164
+ } else {
165
+ throw new Error("Unknow manager");
166
+ }
167
+ };
168
+ var packages = {
169
+ nftables: {
170
+ name: "nftables",
171
+ command: "nft"
172
+ },
173
+ podman: {
174
+ name: "podman",
175
+ command: "podman"
176
+ }
177
+ };
178
+ var installSystemPackage = async (packageEnt, context) => {
179
+ const finalPackageEnt = typeof packageEnt === "string" ? packages[packageEnt] : packageEnt;
180
+ if (!finalPackageEnt) {
181
+ const errorMessage = `No package ent for: ${packageEnt}`;
182
+ throw new Error(errorMessage);
183
+ }
184
+ const { stdout: osRaw } = await execCommand("cat /etc/os-release | grep ^ID= | cut -d'=' -f2", {}, context);
185
+ const osName = osRaw.trim().replace(/"/g, "");
186
+ const manager = getManagerByOs(osName);
187
+ const managerConfig = getManagerConfig(manager, finalPackageEnt);
188
+ const checkResult = await execCommandMayError(`command -v ${managerConfig.command}`, {}, context);
189
+ if (checkResult.spawnResult.exitCode === 0) {
190
+ return;
191
+ }
192
+ const installCommand = getInstallCommand(manager, managerConfig);
193
+ await execCommand(installCommand, {}, context);
194
+ };
195
+
196
+ // src/files.ts
197
+ import { appendFile, exists } from "fs/promises";
198
+ var {file, write } = globalThis.Bun;
199
+
200
+ // src/path.ts
201
+ import { homedir } from "os";
202
+ import { join } from "path";
203
+ function normalizePath(rawFilePath) {
204
+ let finalFilePath = rawFilePath.trim();
205
+ if (finalFilePath.startsWith("~/")) {
206
+ finalFilePath = join(homedir(), finalFilePath.slice(2));
207
+ }
208
+ return finalFilePath;
209
+ }
210
+
211
+ // src/files.ts
212
+ var normalizeFileContent = (str) => {
213
+ if (str === "") {
214
+ return str;
215
+ }
216
+ if (str.at(-1) !== `
217
+ `) {
218
+ return str + `
219
+ `;
220
+ }
221
+ return str;
222
+ };
223
+ var createDir = async (str, context = defaultContext) => {
224
+ const dirname = str.split("/").slice(0, -1).join("/");
225
+ const exist = await exists(dirname);
226
+ if (exist) {
227
+ return;
228
+ }
229
+ await execCommand(`mkdir -p ${dirname}`, {}, context);
230
+ };
231
+ var checkStrInFile = async (filePath, str) => {
232
+ const file2 = Bun.file(filePath);
233
+ if (!await file2.exists()) {
234
+ return false;
235
+ }
236
+ const fileText = await file2.text();
237
+ if (fileText.includes(str)) {
238
+ return true;
239
+ }
240
+ return false;
241
+ };
242
+ var createFileIfNeed = async (rawFilePath, context = defaultContext) => {
243
+ const filePath = normalizePath(rawFilePath);
244
+ await createDir(filePath, context);
245
+ if (!await file(filePath).exists()) {
246
+ await execCommand(`touch ${filePath}`, {}, context);
247
+ }
248
+ };
249
+ var writeFileStrUniq = async (rawFilePath, str, context = defaultContext) => {
250
+ const filePath = normalizePath(rawFilePath);
251
+ await createFileIfNeed(filePath, context);
252
+ if (await checkStrInFile(filePath, str)) {
253
+ return;
254
+ }
255
+ await appendFile(filePath, normalizeFileContent(str));
256
+ };
257
+ var writeFile = async (pathToFile, str, context = defaultContext) => {
258
+ const normalizedPath = normalizePath(pathToFile);
259
+ await createFileIfNeed(normalizedPath, context);
260
+ const fileText = await file(normalizedPath).text();
261
+ if (fileText === str) {
262
+ return;
263
+ }
264
+ await write(normalizedPath, str);
265
+ };
266
+
267
+ // src/systemd.ts
268
+ var systemctlWordLangth = "systemctl ".length;
269
+ var formatUserspace = (command, context = defaultContext) => {
270
+ const userPart = context.userspace ? " --user " : "";
271
+ return "systemctl" + userPart + " " + command.slice(systemctlWordLangth);
272
+ };
273
+ var reloadSystemd = async (context = defaultContext) => {
274
+ await execCommand(formatUserspace("systemctl daemon-reload", context));
275
+ };
276
+ var startSystemdUnit = async (unitName, context = defaultContext) => {
277
+ await execCommand(formatUserspace(`systemctl start ${unitName}`, context));
278
+ };
279
+ var enableSystemdUnit = async (unitName, context = defaultContext) => {
280
+ await execCommand(formatUserspace(`systemctl enable ${unitName}`, context));
281
+ };
282
+ var restartSystemdUnit = async (name, context = defaultContext) => {
283
+ await execCommand(formatUserspace(`systemctl restart ${name}`, context));
284
+ };
285
+ var stopSystemdUnit = async (name, context = defaultContext) => {
286
+ await execCommand(formatUserspace(`systemctl stop ${name}`, context));
287
+ };
288
+ var checkSystemdUnit = async (serviceName, context = defaultContext) => {
289
+ const { spawnResult } = await execCommandMayError(formatUserspace(`systemctl is-active ${serviceName}`, context));
290
+ return spawnResult.exitCode === 0;
291
+ };
292
+ var createSystemdUnit = async (unitName, content, context = defaultContext) => {
293
+ const pathToSeviceTarget = getSystemdPathToUnit(unitName, context);
294
+ await writeFile(pathToSeviceTarget, content);
295
+ await reloadSystemd(context);
296
+ };
297
+ var getSystemdPathToUnit = (serviceName, context = defaultContext) => {
298
+ if (context.userspace) {
299
+ return `~/.config/systemd/user/${serviceName}`;
300
+ }
301
+ return `/etc/systemd/system/${serviceName}`;
302
+ };
303
+ var createSystemdService = async (serviceName, content, context = defaultContext) => {
304
+ await createSystemdUnit(serviceName, content, context);
305
+ await enableSystemdUnit(serviceName, context);
306
+ await startSystemdUnit(serviceName, context);
307
+ };
308
+
309
+ // src/nft.ts
310
+ var createNftTable = ({
311
+ allowedIpV4,
312
+ allowedPorts = []
313
+ }) => {
314
+ const nftTable = `table inet ramm {
315
+ set allowed_ipv4 {
316
+ type ipv4_addr
317
+ flags dynamic
318
+ elements = { ${allowedIpV4.join(`
319
+ `)} }
320
+ }
321
+
322
+ chain local_chain_base {
323
+ iif "lo" accept
324
+ ct state established,related accept
325
+ ip saddr @allowed_ipv4 tcp dport 22 accept
326
+ tcp dport 22 ct state new limit rate over 700/minute burst 5 packets drop
327
+ tcp dport 22 accept
328
+ ${allowedPorts.map((port) => {
329
+ return `tcp dport ${port} accept`;
330
+ }).join(`
331
+ `)}
332
+ }
333
+
334
+ chain local_chain {
335
+ jump local_chain_base
336
+ drop
337
+ }
338
+
339
+ chain prerouting {
340
+ type filter hook prerouting priority mangle; policy accept;
341
+ fib daddr type local jump local_chain
342
+ }
343
+ }
344
+ `;
345
+ return nftTable;
346
+ };
347
+ var setupNftable = async ({
348
+ allowedIpV4,
349
+ allowedPorts,
350
+ context = defaultContext
351
+ }) => {
352
+ await installSystemPackage("nftables", context);
353
+ const listTable = await execCommandMayError("nft list table inet ramm", {}, context);
354
+ if (listTable.spawnResult.exitCode === 0) {
355
+ await execCommand("nft delete table inet ramm", {}, context);
356
+ }
357
+ const nftTable = createNftTable({ allowedIpV4, allowedPorts });
358
+ await execCommand(`nft -f - <<EOF
359
+ ${nftTable}
360
+ EOF`, {}, context);
361
+ await safeNftTable(context);
362
+ };
363
+ var safeNftTable = async (context = defaultContext) => {
364
+ await execCommand("nft list ruleset > /etc/nftables.conf", {}, context);
365
+ await execCommand("systemctl enable nftables", {}, context);
366
+ };
367
+
368
+ // src/podman.ts
369
+ var installPodman = async (context = defaultContext) => {
370
+ const check = await execCommandMayError("command -v podman", {}, context);
371
+ if (check.spawnResult.exitCode !== 0) {
372
+ await installSystemPackage("podman", context);
373
+ }
374
+ await createNetwork(context);
375
+ };
376
+ var createNetwork = async (context = defaultContext) => {
377
+ const netwroks = await execCommand("podman network inspect $(podman network ls -q) -f '{{.NetworkInterface}}'", {}, context);
378
+ const podmanNetworks = await execCommand("podman network ls", {}, context);
379
+ if (podmanNetworks.stdout.includes("ramm")) {
380
+ return;
381
+ }
382
+ if (netwroks.stdout.includes("podman_ramm")) {
383
+ return;
384
+ }
385
+ await execCommand("podman network create --interface-name=podman_ramm ramm", {}, context);
386
+ };
387
+ var getCreateCommand = async (name, context = defaultContext) => {
388
+ const result = await execCommandMayError(`podman inspect --format '{{.Config.CreateCommand}}' ${name}`, {}, context);
389
+ const text = result.stdout.trim();
390
+ if (text.startsWith("[") && text.endsWith("]")) {
391
+ return text.slice(1, -1);
392
+ }
393
+ return text;
394
+ };
395
+ var loginPodman = async (address, login, password, context = defaultContext) => {
396
+ return await execCommand(`echo "${password}" | podman login --username "${login}" --password-stdin ${address}`, {}, context);
397
+ };
398
+ var createPodmanCommand = ({
399
+ name,
400
+ replace = true,
401
+ background = true,
402
+ networks = ["ramm"],
403
+ envs = [],
404
+ volumes = [],
405
+ command
406
+ }) => {
407
+ const values = [];
408
+ values.push("podman", "run");
409
+ if (name) {
410
+ values.push(`--name ${name}`);
411
+ }
412
+ if (replace) {
413
+ values.push("--replace");
414
+ }
415
+ if (background) {
416
+ values.push("-d");
417
+ }
418
+ for (const network of networks) {
419
+ values.push(`--network ${network}`);
420
+ }
421
+ for (const env of envs) {
422
+ values.push(`-e ${env.name}=${env.value}`);
423
+ }
424
+ for (const volume of volumes) {
425
+ values.push(`-v ${volume.from}:${volume.to}`);
426
+ }
427
+ values.push(command);
428
+ const str = values.join(" ");
429
+ return str;
430
+ };
431
+ var runPodmanContainer = async (name, command, context = defaultContext) => {
432
+ if (await getCreateCommand(name, context) !== command) {
433
+ await execCommand(`podman rm -f ${name}`, {}, context);
434
+ await execCommand(command, {}, context);
435
+ return;
436
+ }
437
+ console.info("Podman container is already running");
438
+ };
439
+ var runPodmanContainerService = async (name, command, context = defaultContext) => {
440
+ const serviceName = `${name}.service`;
441
+ const filepath = getSystemdPathToUnit(serviceName);
442
+ if (await checkSystemdUnit(serviceName, context)) {
443
+ await stopSystemdUnit(serviceName, context);
444
+ }
445
+ await runPodmanContainer(name, command, context);
446
+ await execCommand(`podman generate systemd --name --new ${name} > ${filepath}`, {}, context);
447
+ await reloadSystemd(context);
448
+ await startSystemdUnit(serviceName, context);
449
+ await enableSystemdUnit(serviceName, context);
450
+ };
451
+ var addNftPodmanRule = async (context = defaultContext) => {
452
+ const podmanNetworksResult = await execCommand("podman network inspect $(podman network ls -q) -f '{{.NetworkInterface}}'", {}, context);
453
+ const podmanNetworks = podmanNetworksResult.stdout.trim().split(`
454
+ `);
455
+ await execCommand(`nft add set inet ramm podman_interfaces '{ type ifname; flags dynamic; elements = { ${podmanNetworks.join(", ")} }; }'`, {}, context);
456
+ await execCommand("nft insert rule inet ramm prerouting iifname @podman_interfaces accept", {}, context);
457
+ await safeNftTable(context);
458
+ };
459
+ // src/ssh.ts
460
+ var {file: file2 } = globalThis.Bun;
461
+ var addKeyToHostConfig = async (pathToHost, address, pathToKey, context = defaultContext) => {
462
+ const text = `Host ${address}
463
+ IdentityFile ${pathToKey}
464
+ `;
465
+ await writeFileStrUniq(pathToHost, text, context);
466
+ };
467
+ var getServerFingerprint = async (context) => {
468
+ const { stdout } = await execCommandOverSsh('ssh-keyscan -t ed25519 localhost | grep -v "^#"', context);
469
+ return stdout.replace("localhost", context.domain);
470
+ };
471
+ var saveSshFingerptint = async (filePath, context) => {
472
+ const normalizedPath = normalizePath(filePath);
473
+ const fingerprint = await getServerFingerprint(context);
474
+ await writeFile(normalizedPath, fingerprint, context);
475
+ };
476
+ async function createSshKey(filePath, comment, context = defaultContext) {
477
+ printFunction(`${createSshKey.name} ${filePath}`);
478
+ const normalizedPathToKey = normalizePath(filePath);
479
+ const name = normalizedPathToKey.split("/").at(-1);
480
+ const pathToKeyPub = `${normalizedPathToKey}.pub`;
481
+ const pathToDir = normalizedPathToKey.split("/").slice(0, -1).join("/");
482
+ const pathToKeyFile = file2(normalizedPathToKey);
483
+ const pathToKeyPubFile = file2(pathToKeyPub);
484
+ if (await pathToKeyFile.exists() && await pathToKeyPubFile.exists()) {
485
+ return await pathToKeyPubFile.text();
486
+ }
487
+ await execCommand(`mkdir -p ${pathToDir}`, {}, context);
488
+ await execCommand(`ssh-keygen -t ed25519 -f ${normalizedPathToKey} -N "" -C "${comment || name}"`, {}, context);
489
+ await execCommand(`chmod 600 ${normalizedPathToKey}`, {}, context);
490
+ const pubKey = await Bun.file(pathToKeyPub).text();
491
+ return pubKey;
492
+ }
493
+ var addSshKeyToAuthorizedOverSsh = async (pubKey, context) => {
494
+ printFunction(`${addSshKeyToAuthorizedOverSsh.name} ${pubKey}`);
495
+ const { stdout: keys } = await execCommandOverSsh("cat .ssh/authorized_keys", context);
496
+ if (keys.includes(pubKey)) {
497
+ return;
498
+ }
499
+ await execCommandOverSsh(`echo "${pubKey}" >> .ssh/authorized_keys`, context);
500
+ };
501
+ var createAndAddSshKey = async (filePath, comment, context) => {
502
+ const normalizedPath = normalizePath(filePath);
503
+ const pubKey = await createSshKey(normalizedPath, comment, context);
504
+ console.log(`Key is: ${pubKey}`);
505
+ await addSshKeyToAuthorizedOverSsh(pubKey, context);
506
+ };
507
+ var addSshKeyToUse = async ({
508
+ key,
509
+ fingerprint,
510
+ filePath,
511
+ server,
512
+ context = defaultContext
513
+ }) => {
514
+ printFunction(`${addSshKeyToUse.name} ${filePath}`);
515
+ const normalizedFilePath = normalizePath(filePath);
516
+ await writeFile(normalizedFilePath, key, context);
517
+ await execCommand(`chmod 0600 ${normalizedFilePath}`, {}, context);
518
+ await writeFileStrUniq("~/.ssh/known_hosts", fingerprint, context);
519
+ await addKeyToHostConfig("~/.ssh/config", server, normalizedFilePath, context);
520
+ };
521
+ // src/cron.ts
522
+ var createCron = async ({
523
+ time,
524
+ pathToFile,
525
+ context = defaultContext
526
+ }) => {
527
+ const pathToFileNorm = normalizePath(pathToFile);
528
+ const constructedLine = `${time} ${pathToFileNorm}`;
529
+ const tempFile = `/tmp/ramm_cron`;
530
+ const { stdout: cronConfig } = await execCommandMayError("crontab -l", {}, context);
531
+ if (cronConfig.includes(constructedLine)) {
532
+ return;
533
+ }
534
+ let baseCronConfig = cronConfig;
535
+ if (cronConfig.includes(pathToFileNorm)) {
536
+ baseCronConfig = cronConfig.split(`
537
+ `).filter((str) => !str.includes(pathToFileNorm)).join(`
538
+ `);
539
+ }
540
+ const newCronConfig = normalizeFileContent(normalizeFileContent(baseCronConfig) + constructedLine);
541
+ await writeFile(tempFile, newCronConfig, context);
542
+ await execCommandMayError(`cat ${tempFile}`, {}, context);
543
+ await execCommandMayError(`crontab ${tempFile}`, {}, context);
544
+ await execCommandMayError(`rm ${tempFile}`, {}, context);
545
+ };
546
+ // src/build.ts
547
+ var {build, file: file3 } = globalThis.Bun;
548
+ var buildAndRunOverSsh = async ({
549
+ entrypoint,
550
+ context
551
+ }) => {
552
+ const normalizedEntrypoint = normalizePath(entrypoint);
553
+ const distName = `ramm_dist`;
554
+ const distDir = `/tmp/${distName}`;
555
+ const outputs = await build({
556
+ outdir: distDir,
557
+ entrypoints: [normalizedEntrypoint],
558
+ target: "bun"
559
+ });
560
+ const pathToDistFile = outputs.outputs[0]?.path;
561
+ const relativePathToFile = pathToDistFile.slice(distDir.length + 1);
562
+ await copyFilesOverSsh(`${distDir}/`, distDir, context);
563
+ await execCommandOverSsh(`bun run ${distDir}/${relativePathToFile}`, context);
564
+ await execCommand(`rm -rf ${distDir}`, {}, context);
565
+ };
566
+ var pathToJson = "/tmp/ramm_json";
567
+ var passVarsClient = async (data, context) => {
568
+ printFunction("passVarsClient");
569
+ const json = JSON.stringify(data);
570
+ await writeFile(pathToJson, json, context);
571
+ await copyFilesOverSsh(pathToJson, pathToJson, context);
572
+ await execCommand(`rm -rf ${pathToJson}`, {}, context);
573
+ };
574
+ var passVarsServer = async (context = defaultContext) => {
575
+ printFunction("passVarsServer");
576
+ const jsonData = await file3(pathToJson).json();
577
+ await execCommand(`rm -rf ${pathToJson}`, {}, context);
578
+ return jsonData;
579
+ };
580
+ export {
581
+ writeFileStrUniq,
582
+ writeFile,
583
+ startSystemdUnit,
584
+ setupNftable,
585
+ saveSshFingerptint,
586
+ runPodmanContainerService,
587
+ runPodmanContainer,
588
+ restartSystemdUnit,
589
+ reloadSystemd,
590
+ printBlock,
591
+ passVarsServer,
592
+ passVarsClient,
593
+ normalizePath,
594
+ normalizeFileContent,
595
+ loginPodman,
596
+ installSystemPackage,
597
+ installPodman,
598
+ installBunOverSsh,
599
+ getSystemdPathToUnit,
600
+ getServerFingerprint,
601
+ execCommandRaw,
602
+ execCommandOverSsh,
603
+ execCommandMayError,
604
+ execCommand,
605
+ enableSystemdUnit,
606
+ createSystemdUnit,
607
+ createSystemdService,
608
+ createPodmanCommand,
609
+ createCron,
610
+ createAndAddSshKey,
611
+ copyFilesOverSsh,
612
+ buildAndRunOverSsh,
613
+ addSshKeyToUse,
614
+ addNftPodmanRule,
615
+ addKeyToHostConfig,
616
+ Context
617
+ };
@@ -0,0 +1,35 @@
1
+ import { type Subprocess } from "bun";
2
+ import { Context } from "../context.ts";
3
+ export declare const defaultContext: Context;
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, ctx?: Context) => Promise<{
15
+ stderr: string;
16
+ stdout: string;
17
+ spawnResult: Subprocess<"inherit", "pipe", "pipe">;
18
+ }>;
19
+ export declare const execCommandMayError: (command: string, props: ExecProps, context?: Context) => Promise<{
20
+ stderr: string;
21
+ stdout: string;
22
+ spawnResult: Subprocess<"inherit", "pipe", "pipe">;
23
+ }>;
24
+ export declare const execCommand: (command: string, props: ExecProps, context?: Context) => Promise<{
25
+ stderr: string;
26
+ stdout: string;
27
+ spawnResult: Subprocess<"inherit", "pipe", "pipe">;
28
+ }>;
29
+ export declare const copyFilesOverSsh: (from: string, to: string, context: Context) => Promise<void>;
30
+ export declare const execCommandOverSsh: (command: string, context: Context) => Promise<{
31
+ stderr: string;
32
+ stdout: string;
33
+ spawnResult: Subprocess<"inherit", "pipe", "pipe">;
34
+ }>;
35
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare const teeStdout: (read: ReadableStream, prefix: string) => Promise<string>;
2
+ export declare const teeStderr: (read: ReadableStream, prefix: string) => Promise<string>;
@@ -0,0 +1,7 @@
1
+ import type { Context } from "./context.ts";
2
+ export declare const buildAndRunOverSsh: ({ entrypoint, context, }: {
3
+ entrypoint: string;
4
+ context: Context;
5
+ }) => Promise<void>;
6
+ export declare const passVarsClient: (data: Record<string, any>, context: Context) => Promise<void>;
7
+ export declare const passVarsServer: (context?: Context) => Promise<any>;
@@ -0,0 +1,16 @@
1
+ export declare class Context {
2
+ user: string;
3
+ domain: string;
4
+ userspace: boolean;
5
+ sudo: boolean;
6
+ sshKey?: string;
7
+ params: Record<string, string>;
8
+ constructor({ user, address, userspace, sudo, sshKey, }: {
9
+ user: string;
10
+ address: string;
11
+ userspace?: boolean;
12
+ sudo?: boolean;
13
+ sshKey?: string;
14
+ });
15
+ getAddress(): string;
16
+ }
@@ -0,0 +1,6 @@
1
+ import type { Context } from "./context.ts";
2
+ export declare const createCron: ({ time, pathToFile, context, }: {
3
+ time: string;
4
+ pathToFile: string;
5
+ context?: Context;
6
+ }) => Promise<void>;
@@ -0,0 +1,4 @@
1
+ import type { Context } from "./context.ts";
2
+ export declare const normalizeFileContent: (str: string) => string;
3
+ export declare const writeFileStrUniq: (rawFilePath: string, str: string, context?: Context) => Promise<void>;
4
+ export declare const writeFile: (pathToFile: string, str: string, context?: Context) => Promise<void>;
@@ -0,0 +1,2 @@
1
+ import type { Context } from "./context.ts";
2
+ export declare const installBunOverSsh: (context: Context) => Promise<void>;
@@ -0,0 +1,8 @@
1
+ import type { Context } from "./context.ts";
2
+ export declare const localNftChainName = "local_chain";
3
+ export declare const setupNftable: ({ allowedIpV4, allowedPorts, context, }: {
4
+ allowedIpV4: string[];
5
+ allowedPorts: string[];
6
+ context?: Context;
7
+ }) => Promise<void>;
8
+ export declare const safeNftTable: (context?: Context) => Promise<void>;
@@ -0,0 +1,13 @@
1
+ import type { Context } from "./context.ts";
2
+ type Manager = "dnf" | "apt";
3
+ type PackageConfig = {
4
+ name: string;
5
+ command: string;
6
+ managers?: Record<Manager, ManagerConfig>;
7
+ };
8
+ type ManagerConfig = {
9
+ name: string;
10
+ command: string;
11
+ };
12
+ export declare const installSystemPackage: (packageEnt: string | PackageConfig, context?: Context) => Promise<void>;
13
+ export {};
@@ -0,0 +1 @@
1
+ export declare function normalizePath(rawFilePath: string): string;
@@ -0,0 +1,25 @@
1
+ import type { Context } from "./context.ts";
2
+ export declare const installPodman: (context?: Context) => Promise<void>;
3
+ export declare const loginPodman: (address: string, login: string, password: string, context?: Context) => Promise<{
4
+ stderr: string;
5
+ stdout: string;
6
+ spawnResult: import("bun").Subprocess<"inherit", "pipe", "pipe">;
7
+ }>;
8
+ export declare const createPodmanCommand: ({ name, replace, background, networks, envs, volumes, command, }: {
9
+ name?: string;
10
+ replace?: boolean;
11
+ background?: boolean;
12
+ networks?: string[];
13
+ envs?: {
14
+ name: string;
15
+ value: string;
16
+ }[];
17
+ volumes?: {
18
+ from: string;
19
+ to: string;
20
+ }[];
21
+ command: string;
22
+ }) => string;
23
+ export declare const runPodmanContainer: (name: string, command: string, context?: Context) => Promise<void>;
24
+ export declare const runPodmanContainerService: (name: string, command: string, context?: Context) => Promise<void>;
25
+ export declare const addNftPodmanRule: (context?: Context) => 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;
@@ -0,0 +1,13 @@
1
+ export { execCommandOverSsh, execCommand, execCommandMayError, copyFilesOverSsh, execCommandRaw, } from "./base/base.ts";
2
+ export { Context } from "./context.ts";
3
+ export { installBunOverSsh } from "./init.ts";
4
+ export { installPodman, runPodmanContainer, loginPodman, runPodmanContainerService, addNftPodmanRule, createPodmanCommand, } from "./podman.ts";
5
+ export { startSystemdUnit, enableSystemdUnit, restartSystemdUnit, createSystemdService, getSystemdPathToUnit, createSystemdUnit, reloadSystemd, } from "./systemd.ts";
6
+ export { installSystemPackage } from "./packages.ts";
7
+ export { printBlock } from "./print.ts";
8
+ export { setupNftable } from "./nft.ts";
9
+ export { writeFileStrUniq, writeFile, normalizeFileContent, } from "./files.ts";
10
+ export { createAndAddSshKey, getServerFingerprint, addKeyToHostConfig, addSshKeyToUse, saveSshFingerptint, } from "./ssh.ts";
11
+ export { normalizePath } from "./path.ts";
12
+ export { createCron } from "./cron.ts";
13
+ export { buildAndRunOverSsh, passVarsClient, passVarsServer } from "./build.ts";
@@ -0,0 +1,12 @@
1
+ import type { Context } from "./context.ts";
2
+ export declare const addKeyToHostConfig: (pathToHost: string, address: string, pathToKey: string, context?: Context) => Promise<void>;
3
+ export declare const getServerFingerprint: (context: Context) => Promise<string>;
4
+ export declare const saveSshFingerptint: (filePath: string, context: Context) => Promise<void>;
5
+ export declare const createAndAddSshKey: (filePath: string, comment: string, context: Context) => Promise<void>;
6
+ export declare const addSshKeyToUse: ({ key, fingerprint, filePath, server, context, }: {
7
+ key: string;
8
+ fingerprint: string;
9
+ filePath: string;
10
+ server: string;
11
+ context?: Context;
12
+ }) => Promise<void>;
@@ -0,0 +1,10 @@
1
+ import { Context } from "./context.ts";
2
+ export declare const reloadSystemd: (context?: Context) => Promise<void>;
3
+ export declare const startSystemdUnit: (unitName: string, context?: Context) => Promise<void>;
4
+ export declare const enableSystemdUnit: (unitName: string, context?: Context) => Promise<void>;
5
+ export declare const restartSystemdUnit: (name: string, context?: Context) => Promise<void>;
6
+ export declare const stopSystemdUnit: (name: string, context?: Context) => Promise<void>;
7
+ export declare const checkSystemdUnit: (serviceName: string, context?: Context) => Promise<boolean>;
8
+ export declare const createSystemdUnit: (unitName: string, content: string, context?: Context) => Promise<void>;
9
+ export declare const getSystemdPathToUnit: (serviceName: string, context?: Context) => string;
10
+ export declare const createSystemdService: (serviceName: string, content: string, context?: Context) => Promise<void>;
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "ramm",
3
3
  "type": "module",
4
- "version": "0.0.62",
4
+ "version": "0.0.64",
5
5
  "scripts": {
6
- "build": "bun build ./src/ramm.ts --target bun --outdir ./dist && cp ./src/bun.sh ./dist/bun.sh",
7
- "types": "tsc --project tsconfig.types.json"
6
+ "build": "bun run build:js && bun run build:types",
7
+ "build:js": "bun build ./src/ramm.ts --target bun --outdir ./dist && cp ./src/bun.sh ./dist/bun.sh",
8
+ "build:types": "tsc --project tsconfig.types.json"
8
9
  },
9
10
  "main": "dist/ramm.js",
10
11
  "types": "dist/types/ramm.d.ts",