openship 0.3.0 → 0.4.1

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.
Files changed (82) hide show
  1. package/README.md +104 -61
  2. package/dist/bare-ITM45QBX.js +18 -0
  3. package/dist/bowser-MFQA6OS4.js +2821 -0
  4. package/dist/chunk-3U4SPZD5.js +241 -0
  5. package/dist/chunk-46YJFP4S.js +1771 -0
  6. package/dist/chunk-4CQWT2WL.js +116 -0
  7. package/dist/chunk-4FABQGQP.js +23 -0
  8. package/dist/chunk-4LEL3H2Z.js +84 -0
  9. package/dist/chunk-4MG3BVHE.js +326 -0
  10. package/dist/chunk-4VNS5WPM.js +42 -0
  11. package/dist/chunk-5N7VUGL6.js +2094 -0
  12. package/dist/chunk-5ZCKQ2MI.js +1360 -0
  13. package/dist/chunk-6ERIMTBC.js +1412 -0
  14. package/dist/chunk-7UOB5GGQ.js +132 -0
  15. package/dist/chunk-BUBSSKO6.js +1384 -0
  16. package/dist/chunk-E6W2JMMU.js +341 -0
  17. package/dist/chunk-E77LJWJK.js +1535 -0
  18. package/dist/chunk-F4DFVG6Q.js +573 -0
  19. package/dist/chunk-HFYDYK4D.js +1092 -0
  20. package/dist/chunk-JR2OCMJA.js +46 -0
  21. package/dist/chunk-JUJBBF5U.js +746 -0
  22. package/dist/chunk-JZLNHGLW.js +19145 -0
  23. package/dist/chunk-KD7VO4LG.js +2617 -0
  24. package/dist/chunk-LBFH7THC.js +435 -0
  25. package/dist/chunk-NB2VEIWG.js +129 -0
  26. package/dist/chunk-OJE6YWPQ.js +2866 -0
  27. package/dist/chunk-QKFRZNKN.js +4941 -0
  28. package/dist/chunk-QWFNE5NS.js +13354 -0
  29. package/dist/chunk-S6DSRLNE.js +121 -0
  30. package/dist/chunk-TEYJYSMT.js +409 -0
  31. package/dist/chunk-U2DPZSXA.js +112 -0
  32. package/dist/chunk-WJPCBU7Z.js +3147 -0
  33. package/dist/chunk-XIFRMKYT.js +13 -0
  34. package/dist/chunk-XVSAUO2I.js +7946 -0
  35. package/dist/chunk-Y37KHU7L.js +31 -0
  36. package/dist/chunk-YL67EWYZ.js +416 -0
  37. package/dist/chunk-ZKJOFWBJ.js +1879 -0
  38. package/dist/cloud-JMPHO3CW.js +7 -0
  39. package/dist/cloud-W5G6YXAY.js +24 -0
  40. package/dist/dist-L3MPOWCA.js +65 -0
  41. package/dist/dist-es-4C322O5D.js +22 -0
  42. package/dist/dist-es-GTAMF674.js +87 -0
  43. package/dist/dist-es-KE56MWYO.js +169 -0
  44. package/dist/dist-es-NRZIQY5B.js +484 -0
  45. package/dist/dist-es-WZCR7DHQ.js +317 -0
  46. package/dist/dist-es-XQCOTGC7.js +376 -0
  47. package/dist/dist-es-ZW3HFQUM.js +69 -0
  48. package/dist/docker-3FVJMFC3.js +12 -0
  49. package/dist/docker-edge-executor-ZIWAZWPL.js +9 -0
  50. package/dist/edge-import-W2D4L6HL.js +39 -0
  51. package/dist/event-streams-7LGDL56D.js +42 -0
  52. package/dist/executor-J7BHW5HF.js +26 -0
  53. package/dist/index.js +2450 -3484
  54. package/dist/loadSso-N273C5I7.js +577 -0
  55. package/dist/nginx-YZWKYKQU.js +16 -0
  56. package/dist/noop-RRNCIUI5.js +7 -0
  57. package/dist/openresty-lua-HAO4EUDY.js +32 -0
  58. package/dist/server/index.js +230533 -217891
  59. package/dist/server/migrations/0057_complete_prism.sql +18 -0
  60. package/dist/server/migrations/0058_add_server_is_local.sql +1 -0
  61. package/dist/server/migrations/0059_legal_fixer.sql +18 -0
  62. package/dist/server/migrations/0060_add_route_strategy_host_port.sql +3 -0
  63. package/dist/server/migrations/0061_notification_default_multi_kind.sql +3 -0
  64. package/dist/server/migrations/0062_add_incoming_webhook.sql +21 -0
  65. package/dist/server/migrations/0063_add_migration_logs.sql +1 -0
  66. package/dist/server/migrations/0064_add_migration_partial.sql +2 -0
  67. package/dist/server/migrations/0065_custom_app_template.sql +14 -0
  68. package/dist/server/migrations/0066_ensure_migration_partial_columns.sql +2 -0
  69. package/dist/server/migrations/0067_webhook_delivery.sql +28 -0
  70. package/dist/server/migrations/0068_add_migration_target_volumes.sql +1 -0
  71. package/dist/server/migrations/0069_add_project_composite_routes.sql +1 -0
  72. package/dist/server/migrations/0070_forward_git_to_server.sql +1 -0
  73. package/dist/server/migrations/meta/0057_snapshot.json +9326 -0
  74. package/dist/server/migrations/meta/0058_snapshot.json +9333 -0
  75. package/dist/server/migrations/meta/0059_snapshot.json +9495 -0
  76. package/dist/server/migrations/meta/0060_snapshot.json +9515 -0
  77. package/dist/server/migrations/meta/_journal.json +99 -1
  78. package/dist/setup-5X3WEEHA.js +14 -0
  79. package/dist/signin-DR462ERO.js +663 -0
  80. package/dist/sso-oidc-VBZLJUK5.js +830 -0
  81. package/dist/sts-EJLZ4Z77.js +1422 -0
  82. package/package.json +6 -2
@@ -0,0 +1,116 @@
1
+ // ../../packages/adapters/src/system/local-shell.ts
2
+ import { execFile } from "child_process";
3
+ import { basename } from "path";
4
+ var LOCAL_BUILD_ENV_KEYS = [
5
+ "HOME",
6
+ "PATH",
7
+ "SHELL",
8
+ "USER",
9
+ "LOGNAME",
10
+ "TMPDIR",
11
+ "TMP",
12
+ "TEMP",
13
+ "LANG",
14
+ "LC_ALL",
15
+ "LC_CTYPE",
16
+ "TERM",
17
+ "COLORTERM",
18
+ "SSH_AUTH_SOCK",
19
+ "SSH_AGENT_PID",
20
+ "GIT_SSH_COMMAND",
21
+ "GIT_ASKPASS",
22
+ "XDG_CONFIG_HOME",
23
+ "XDG_CACHE_HOME",
24
+ "XDG_DATA_HOME"
25
+ ];
26
+ function sq(value) {
27
+ return `'${value.replace(/'/g, "'\\''")}'`;
28
+ }
29
+ function logEntry(message, level = "info", rawData) {
30
+ return { timestamp: (/* @__PURE__ */ new Date()).toISOString(), message, level, ...rawData ? { rawData } : {} };
31
+ }
32
+ function getLocalShellPath() {
33
+ return process.env.SHELL?.trim() || "/bin/sh";
34
+ }
35
+ function getLocalShellArgs(command) {
36
+ const shellName = basename(getLocalShellPath());
37
+ if (shellName === "bash" || shellName === "zsh") {
38
+ return ["-lc", command];
39
+ }
40
+ return ["-c", command];
41
+ }
42
+ function getLocalExecEnv() {
43
+ return { ...process.env, DEBIAN_FRONTEND: "noninteractive", DPKG_FORCE: "confnew" };
44
+ }
45
+ async function execFileText(command, args, timeout = 5e3) {
46
+ return new Promise((resolve, reject) => {
47
+ execFile(command, args, { timeout }, (err, stdout, stderr) => {
48
+ if (err) {
49
+ reject(new Error(stderr.trim() || stdout.trim() || err.message));
50
+ return;
51
+ }
52
+ resolve(stdout.trim());
53
+ });
54
+ });
55
+ }
56
+ async function hasLocalCommand(command) {
57
+ try {
58
+ await execFileText("sh", ["-c", `command -v ${command} >/dev/null 2>&1 && echo ok`], 4e3);
59
+ return true;
60
+ } catch {
61
+ return false;
62
+ }
63
+ }
64
+ function emitBufferedLines(chunk, state, onLine) {
65
+ const text = `${state.partial}${chunk.toString()}`.replace(/\r/g, "\n");
66
+ const parts = text.split("\n");
67
+ state.partial = parts.pop() ?? "";
68
+ for (const raw of parts) {
69
+ const line = raw.trimEnd();
70
+ if (line) {
71
+ onLine(line);
72
+ }
73
+ }
74
+ }
75
+ function flushBufferedLines(state, onLine) {
76
+ const line = state.partial.trimEnd();
77
+ state.partial = "";
78
+ if (line) {
79
+ onLine(line);
80
+ }
81
+ }
82
+ function buildIsolatedLocalEnv(overrides) {
83
+ const env = { DEBIAN_FRONTEND: "noninteractive", DPKG_FORCE: "confnew" };
84
+ for (const key of LOCAL_BUILD_ENV_KEYS) {
85
+ const value = process.env[key];
86
+ if (value) {
87
+ env[key] = value;
88
+ }
89
+ }
90
+ if (overrides) {
91
+ for (const [key, value] of Object.entries(overrides)) {
92
+ if (typeof value === "string") {
93
+ env[key] = value;
94
+ }
95
+ }
96
+ }
97
+ return env;
98
+ }
99
+ function wrapLocalBuildCommand(command, envOverrides) {
100
+ const shellPath = getLocalShellPath();
101
+ const envVars = buildIsolatedLocalEnv(envOverrides);
102
+ const envAssignments = Object.entries(envVars).filter((entry) => typeof entry[1] === "string").map(([key, value]) => `${key}=${sq(value)}`).join(" ");
103
+ return `env -i ${envAssignments} ${sq(shellPath)} ${getLocalShellArgs(command).map(sq).join(" ")}`;
104
+ }
105
+
106
+ export {
107
+ sq,
108
+ logEntry,
109
+ getLocalShellPath,
110
+ getLocalShellArgs,
111
+ getLocalExecEnv,
112
+ hasLocalCommand,
113
+ emitBufferedLines,
114
+ flushBufferedLines,
115
+ wrapLocalBuildCommand
116
+ };
@@ -0,0 +1,23 @@
1
+ // ../../packages/adapters/src/infra/noop.ts
2
+ var NoopInfraProvider = class {
3
+ async registerRoute(_route) {
4
+ }
5
+ async removeRoute(_domain) {
6
+ }
7
+ async provisionCert(domain) {
8
+ return { domain, expiresAt: "", issuer: "none", verified: false };
9
+ }
10
+ async renewCert(domain) {
11
+ return { domain, expiresAt: "", issuer: "none", verified: false };
12
+ }
13
+ async verifyCert(domain) {
14
+ return { domain, expiresAt: "", issuer: "none", verified: false };
15
+ }
16
+ async installCert(domain, _cert) {
17
+ return { domain, expiresAt: "", issuer: "none", verified: false };
18
+ }
19
+ };
20
+
21
+ export {
22
+ NoopInfraProvider
23
+ };
@@ -0,0 +1,84 @@
1
+ // ../../packages/adapters/src/system/errors.ts
2
+ var SSH_AUTH_ERROR_PATTERNS = [
3
+ "All configured authentication methods failed"
4
+ ];
5
+ var RETRYABLE_CONNECTION_ERROR_PATTERNS = [
6
+ "ECONNRESET",
7
+ "ECONNREFUSED",
8
+ "ETIMEDOUT",
9
+ "EHOSTUNREACH",
10
+ "ENETUNREACH",
11
+ "Timed out",
12
+ "Not connected",
13
+ "Connection lost",
14
+ "read ECONNRESET",
15
+ "Handshake failed",
16
+ "keepalive timeout",
17
+ "SSH connection closed before ready",
18
+ // ssh2 emits "Channel open failure: open failed" / "Channel open failure: …"
19
+ // when the SSH SERVER refuses a new channel - typically because the cached
20
+ // connection has gone half-dead (peer-side LOGOUT, network blip,
21
+ // remote sshd MaxSessions). The inner SshExecutor retries `exec`/
22
+ // `streamExec` on this, but `pipeLocal`, `transferIn`, and any other
23
+ // channel-bearing op bubble it up. Listing it here lets `withExecutor`
24
+ // drop the dead connection and retry transparently - fixes the
25
+ // "first redeploy fails, second click works" pattern.
26
+ "Channel open failure",
27
+ "open failed"
28
+ ];
29
+ var SshDisconnectedError = class extends Error {
30
+ constructor(message = "SSH connection lost") {
31
+ super(message);
32
+ this.name = "SshDisconnectedError";
33
+ }
34
+ };
35
+ function isSshDisconnectedError(err) {
36
+ return err instanceof SshDisconnectedError || err instanceof Error && err.name === "SshDisconnectedError";
37
+ }
38
+ function isSshAuthError(err) {
39
+ if (!(err instanceof Error)) return false;
40
+ return SSH_AUTH_ERROR_PATTERNS.some((pattern) => err.message.includes(pattern));
41
+ }
42
+ function isRetryableRemoteConnectionError(err) {
43
+ if (isSshDisconnectedError(err)) return true;
44
+ if (!(err instanceof Error)) return false;
45
+ return RETRYABLE_CONNECTION_ERROR_PATTERNS.some(
46
+ (pattern) => err.message.includes(pattern)
47
+ );
48
+ }
49
+ function isRemoteConnectionError(err) {
50
+ return isSshAuthError(err) || isRetryableRemoteConnectionError(err);
51
+ }
52
+ function isRuntimeNotFoundError(err) {
53
+ if (!err || typeof err !== "object") return false;
54
+ const e = err;
55
+ if (e.statusCode === 404) return true;
56
+ return typeof e.message === "string" && /no such (container|image|volume|network)/i.test(e.message);
57
+ }
58
+
59
+ // ../../packages/adapters/src/system/debug.ts
60
+ function isTruthy(value) {
61
+ if (!value) return false;
62
+ return ["1", "true", "yes", "on", "debug"].includes(value.toLowerCase());
63
+ }
64
+ function isSystemDebugEnabled() {
65
+ return isTruthy(process.env.SYSTEM_DEBUG_LOGS);
66
+ }
67
+ function systemDebug(scope, message) {
68
+ if (!isSystemDebugEnabled()) return;
69
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
70
+ console.log(`[system-debug] ${timestamp} [${scope}] ${message}`);
71
+ }
72
+ function formatDuration(startMs) {
73
+ return `${Date.now() - startMs}ms`;
74
+ }
75
+
76
+ export {
77
+ SshDisconnectedError,
78
+ isSshAuthError,
79
+ isRetryableRemoteConnectionError,
80
+ isRemoteConnectionError,
81
+ isRuntimeNotFoundError,
82
+ systemDebug,
83
+ formatDuration
84
+ };
@@ -0,0 +1,326 @@
1
+ import {
2
+ isSshAuthError,
3
+ systemDebug
4
+ } from "./chunk-4LEL3H2Z.js";
5
+ import {
6
+ PACKAGE_ROOT_ONLY_EXCLUDES
7
+ } from "./chunk-JZLNHGLW.js";
8
+
9
+ // ../../packages/adapters/src/archive.ts
10
+ import { execFile } from "child_process";
11
+ import { mkdtemp, rm, stat, writeFile } from "fs/promises";
12
+ import { tmpdir } from "os";
13
+ import { join } from "path";
14
+ import { promisify } from "util";
15
+ var execFileAsync = promisify(execFile);
16
+ var ROOT_ONLY_EXCLUDES = new Set(PACKAGE_ROOT_ONLY_EXCLUDES);
17
+ var NOOP_CLEANUP = async () => {
18
+ };
19
+ function getTarCreateEnv() {
20
+ return {
21
+ ...process.env,
22
+ COPYFILE_DISABLE: "1",
23
+ COPY_EXTENDED_ATTRIBUTES_DISABLE: "1"
24
+ };
25
+ }
26
+ function tarCreateBaseArgs(localPath) {
27
+ const darwinFlags = process.platform === "darwin" ? ["--no-mac-metadata", "--no-xattrs", "--no-acls", "--no-fflags"] : [];
28
+ return [...darwinFlags, "-czf", "-", "-C", localPath];
29
+ }
30
+ async function gitTrackedFiles(localPath) {
31
+ try {
32
+ const { stdout } = await execFileAsync(
33
+ "git",
34
+ ["-C", localPath, "ls-files", "-z", "--cached", "--others", "--exclude-standard"],
35
+ { maxBuffer: 256 * 1024 * 1024 }
36
+ );
37
+ const files = stdout.split("\0").filter(Boolean);
38
+ return files.length > 0 ? files : null;
39
+ } catch {
40
+ return null;
41
+ }
42
+ }
43
+ async function existingRelativePaths(root, paths) {
44
+ if (!paths?.length) return [];
45
+ const found = [];
46
+ for (const p of paths) {
47
+ try {
48
+ await stat(join(root, p));
49
+ found.push(p);
50
+ } catch {
51
+ }
52
+ }
53
+ return found;
54
+ }
55
+ async function prepareSourceTarArgs(localPath, options) {
56
+ if (options?.includes?.length) {
57
+ return { args: getTarCreateArgs(localPath, options), cleanup: NOOP_CLEANUP };
58
+ }
59
+ const files = await gitTrackedFiles(localPath);
60
+ if (files) {
61
+ const extra = await existingRelativePaths(localPath, options?.alsoInclude);
62
+ const entries = extra.length ? [...files, ...extra] : files;
63
+ const tmpDir = await mkdtemp(join(tmpdir(), "openship-tarlist-"));
64
+ const listFile = join(tmpDir, "files.null");
65
+ await writeFile(listFile, entries.join("\0"));
66
+ const args = [...tarCreateBaseArgs(localPath), "--null", "-T", listFile];
67
+ return { args, cleanup: () => rm(tmpDir, { recursive: true, force: true }) };
68
+ }
69
+ return { args: getTarCreateArgs(localPath, options), cleanup: NOOP_CLEANUP };
70
+ }
71
+ function getTarCreateArgs(localPath, options) {
72
+ const args = tarCreateBaseArgs(localPath);
73
+ if (options?.includes?.length) {
74
+ args.push(...options.includes);
75
+ return args;
76
+ }
77
+ for (const exclude of options?.excludes ?? []) {
78
+ const pattern = ROOT_ONLY_EXCLUDES.has(exclude) ? `./${exclude}` : exclude;
79
+ args.push(`--exclude=${pattern}`);
80
+ }
81
+ args.push(".");
82
+ return args;
83
+ }
84
+
85
+ // ../../packages/adapters/src/system/ssh-client.ts
86
+ import { Client } from "ssh2";
87
+
88
+ // ../../packages/adapters/src/system/ssh-support.ts
89
+ import { execFile as execFile2 } from "child_process";
90
+ import { access } from "fs/promises";
91
+ import { homedir } from "os";
92
+ import { join as join2 } from "path";
93
+ function formatSshTarget(config) {
94
+ return `${config.username ?? "root"}@${config.host}:${config.port ?? 22}`;
95
+ }
96
+ function describeSshAuthFailure(config, originalMessage) {
97
+ const target = formatSshTarget(config);
98
+ if (config.password) {
99
+ return `SSH password authentication failed for ${target}. Check the username/password, or verify that the server allows password login. (${originalMessage})`;
100
+ }
101
+ if (config.privateKey || config.sshAgent) {
102
+ return `SSH key authentication failed for ${target}. Check the username, private key, passphrase, or whether the server accepts this key. (${originalMessage})`;
103
+ }
104
+ return `SSH authentication failed for ${target}. (${originalMessage})`;
105
+ }
106
+ function execFileText(command, args, timeout = 5e3) {
107
+ return new Promise((resolve, reject) => {
108
+ execFile2(command, args, { timeout }, (err, stdout, stderr) => {
109
+ if (err) {
110
+ reject(new Error(stderr.trim() || stdout.trim() || err.message));
111
+ return;
112
+ }
113
+ resolve(stdout.trim());
114
+ });
115
+ });
116
+ }
117
+ function parseKnownHostsEntries(text) {
118
+ const entries = /* @__PURE__ */ new Set();
119
+ for (const line of text.split("\n")) {
120
+ const trimmed = line.trim();
121
+ if (!trimmed || trimmed.startsWith("#")) continue;
122
+ const parts = trimmed.split(/\s+/);
123
+ if (parts.length >= 3) {
124
+ entries.add(`${parts[1]} ${parts[2]}`);
125
+ }
126
+ }
127
+ return entries;
128
+ }
129
+ async function reconcileKnownHosts(config) {
130
+ const knownHostsPath = join2(homedir(), ".ssh", "known_hosts");
131
+ try {
132
+ await access(knownHostsPath);
133
+ } catch {
134
+ return;
135
+ }
136
+ const port = config.port ?? 22;
137
+ const hostPatterns = port === 22 ? [config.host] : [config.host, `[${config.host}]:${port}`];
138
+ const knownEntries = /* @__PURE__ */ new Set();
139
+ for (const pattern of hostPatterns) {
140
+ try {
141
+ const output = await execFileText(
142
+ "ssh-keygen",
143
+ ["-F", pattern, "-f", knownHostsPath],
144
+ 4e3
145
+ );
146
+ for (const entry of parseKnownHostsEntries(output)) {
147
+ knownEntries.add(entry);
148
+ }
149
+ } catch {
150
+ }
151
+ }
152
+ if (knownEntries.size === 0) return;
153
+ let scanned;
154
+ try {
155
+ scanned = await execFileText(
156
+ "ssh-keyscan",
157
+ ["-p", String(port), "-T", "5", config.host],
158
+ 7e3
159
+ );
160
+ } catch {
161
+ return;
162
+ }
163
+ const scannedEntries = parseKnownHostsEntries(scanned);
164
+ if (scannedEntries.size === 0) return;
165
+ for (const entry of knownEntries) {
166
+ if (scannedEntries.has(entry)) {
167
+ return;
168
+ }
169
+ }
170
+ for (const pattern of hostPatterns) {
171
+ try {
172
+ await execFileText(
173
+ "ssh-keygen",
174
+ ["-R", pattern, "-f", knownHostsPath],
175
+ 4e3
176
+ );
177
+ systemDebug(
178
+ "ssh-known-hosts",
179
+ `removed stale known_hosts entry for ${pattern}`
180
+ );
181
+ } catch {
182
+ }
183
+ }
184
+ }
185
+
186
+ // ../../packages/adapters/src/system/ssh-client.ts
187
+ function toHostVerifier(config) {
188
+ if (!config.hostVerifier) {
189
+ return void 0;
190
+ }
191
+ return (key) => config.hostVerifier(Buffer.isBuffer(key) ? key : Buffer.from(key));
192
+ }
193
+ function toConnectConfig(config) {
194
+ return {
195
+ host: config.host,
196
+ port: config.port ?? 22,
197
+ username: config.username ?? "root",
198
+ hostVerifier: toHostVerifier(config),
199
+ password: config.password,
200
+ privateKey: config.privateKey,
201
+ passphrase: config.privateKeyPassphrase,
202
+ agent: config.sshAgent,
203
+ tryKeyboard: false,
204
+ keepaliveInterval: 15e3,
205
+ // 10 (~150s) rather than 3 (45s): a small server pegged by a heavy
206
+ // `docker build` / `bun install` can briefly starve sshd of keepalive
207
+ // replies, and 45s was dropping the SSH channel mid-build (build failed with
208
+ // a bare "exited with code 1"). Still detects a truly-dead link within ~2.5m.
209
+ keepaliveCountMax: 10
210
+ };
211
+ }
212
+ async function connectSshClient(config) {
213
+ await reconcileKnownHosts(config);
214
+ const client = new Client();
215
+ return new Promise((resolve, reject) => {
216
+ let settled = false;
217
+ client.on("ready", () => {
218
+ if (settled) return;
219
+ settled = true;
220
+ resolve(client);
221
+ });
222
+ client.on("error", (err) => {
223
+ if (settled) return;
224
+ settled = true;
225
+ if (isSshAuthError(err)) {
226
+ reject(new Error(describeSshAuthFailure(config, err.message)));
227
+ return;
228
+ }
229
+ reject(err);
230
+ });
231
+ client.on("close", () => {
232
+ if (settled) return;
233
+ settled = true;
234
+ reject(new Error("SSH connection closed before ready"));
235
+ });
236
+ client.connect(toConnectConfig(config));
237
+ });
238
+ }
239
+ async function openSftp(client) {
240
+ return new Promise((resolve, reject) => {
241
+ client.sftp((err, sftp) => {
242
+ if (err) reject(err);
243
+ else resolve(sftp);
244
+ });
245
+ });
246
+ }
247
+ async function openSshUnixSocket(client, socketPath) {
248
+ return new Promise((resolve, reject) => {
249
+ if (!client.openssh_forwardOutStreamLocal) {
250
+ reject(new Error("SSH server/client does not support OpenSSH streamlocal socket forwarding."));
251
+ return;
252
+ }
253
+ client.openssh_forwardOutStreamLocal(socketPath, (err, stream) => {
254
+ if (err) {
255
+ reject(err);
256
+ return;
257
+ }
258
+ resolve(stream);
259
+ });
260
+ });
261
+ }
262
+ async function openSshExecChannel(client, command) {
263
+ return new Promise((resolve, reject) => {
264
+ client.exec(command, (err, stream) => {
265
+ if (err) {
266
+ reject(err);
267
+ return;
268
+ }
269
+ resolve(stream);
270
+ });
271
+ });
272
+ }
273
+ async function execSshCommand(client, command, timeout = 1e4) {
274
+ return new Promise((resolve, reject) => {
275
+ let stdout = "";
276
+ let stderr = "";
277
+ let stream;
278
+ let timedOut = false;
279
+ const timer = setTimeout(() => {
280
+ timedOut = true;
281
+ if (stream) {
282
+ try {
283
+ stream.close();
284
+ } catch {
285
+ }
286
+ }
287
+ reject(new Error(`SSH command timed out after ${timeout}ms: ${command}`));
288
+ }, timeout);
289
+ client.exec(command, (err, execStream) => {
290
+ if (err) {
291
+ clearTimeout(timer);
292
+ reject(err);
293
+ return;
294
+ }
295
+ stream = execStream;
296
+ if (timedOut) {
297
+ try {
298
+ stream.close();
299
+ } catch {
300
+ }
301
+ return;
302
+ }
303
+ stream.on("data", (chunk) => {
304
+ stdout += chunk.toString();
305
+ });
306
+ stream.stderr.on("data", (chunk) => {
307
+ stderr += chunk.toString();
308
+ });
309
+ stream.on("close", (code) => {
310
+ clearTimeout(timer);
311
+ resolve({ stdout: stdout.trim(), stderr: stderr.trim(), code: code ?? 1 });
312
+ });
313
+ });
314
+ });
315
+ }
316
+
317
+ export {
318
+ getTarCreateEnv,
319
+ prepareSourceTarArgs,
320
+ reconcileKnownHosts,
321
+ connectSshClient,
322
+ openSftp,
323
+ openSshUnixSocket,
324
+ openSshExecChannel,
325
+ execSshCommand
326
+ };
@@ -0,0 +1,42 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
14
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
+ };
16
+ var __export = (target, all) => {
17
+ for (var name in all)
18
+ __defProp(target, name, { get: all[name], enumerable: true });
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") {
22
+ for (let key of __getOwnPropNames(from))
23
+ if (!__hasOwnProp.call(to, key) && key !== except)
24
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
+ // If the importer is in node compatibility mode or this is not an ESM
30
+ // file that has been converted to a CommonJS file using a Babel-
31
+ // compatible transform (i.e. "__esModule" has not been set), then set
32
+ // "default" to the CommonJS "module.exports" for node compatibility.
33
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
+ mod
35
+ ));
36
+
37
+ export {
38
+ __require,
39
+ __commonJS,
40
+ __export,
41
+ __toESM
42
+ };