openship 0.5.0 → 0.6.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 (104) hide show
  1. package/README.md +26 -1
  2. package/dist/bare-IWS2QHJ3.js +23 -0
  3. package/dist/{bowser-O3AEA6AN.js → bowser-HNOTPGJO.js} +2 -2
  4. package/dist/{chunk-5MZ624VX.js → chunk-2GWYYHOR.js} +1 -1
  5. package/dist/{chunk-BS2AXYZX.js → chunk-2NZSUXOB.js} +647 -214
  6. package/dist/chunk-3FYIXVX5.js +8051 -0
  7. package/dist/{chunk-ILFETZOM.js → chunk-3LDWWY7U.js} +21 -1
  8. package/dist/{chunk-W73X43R7.js → chunk-3NQQXMDR.js} +3 -3
  9. package/dist/{chunk-NNPEG6HM.js → chunk-3NZICQHF.js} +2 -2
  10. package/dist/{chunk-OWED2GRM.js → chunk-42WQABXM.js} +2 -2
  11. package/dist/{chunk-TYVME3XD.js → chunk-6FH4AXVY.js} +20 -3
  12. package/dist/{chunk-ZCOQJCZO.js → chunk-6ODUBKUB.js} +3 -3
  13. package/dist/{chunk-DYPH4HCI.js → chunk-AO252K7Z.js} +1 -1
  14. package/dist/{chunk-IXCHURVK.js → chunk-DOD2BXHQ.js} +4 -4
  15. package/dist/{chunk-VWPEKOH6.js → chunk-DRK3MEDS.js} +3 -3
  16. package/dist/{chunk-V7BZMGOT.js → chunk-EMXI4UCU.js} +5 -5
  17. package/dist/{chunk-RB35YN3J.js → chunk-EW6KB2J7.js} +391 -63
  18. package/dist/chunk-I3DPMTSF.js +29 -0
  19. package/dist/{chunk-NXFIRK2Z.js → chunk-IOT5ZX23.js} +573 -459
  20. package/dist/{chunk-KZOBYJUW.js → chunk-IW2UKBVF.js} +3 -3
  21. package/dist/{chunk-YWMODKWL.js → chunk-IXM5245F.js} +165 -13
  22. package/dist/{chunk-KNTJ7PSF.js → chunk-JIMUYEKN.js} +4 -4
  23. package/dist/{chunk-O6ZZF52V.js → chunk-ONKEYSMY.js} +2 -2
  24. package/dist/{chunk-UMQP7SYT.js → chunk-OTLSJYAC.js} +1316 -53
  25. package/dist/{chunk-EI575GHN.js → chunk-PDW4L3NV.js} +3 -3
  26. package/dist/{chunk-KI2EY3WB.js → chunk-PXKCZB2I.js} +1 -1
  27. package/dist/{chunk-6APIPIJY.js → chunk-QWHBRY2K.js} +5 -5
  28. package/dist/{chunk-JLKKYUZA.js → chunk-RRJJGVKE.js} +7 -7
  29. package/dist/{chunk-6B5YCFFV.js → chunk-RVER2EOO.js} +5 -5
  30. package/dist/{chunk-Q2CIRAOK.js → chunk-RXQBD4ZY.js} +1 -1
  31. package/dist/{chunk-6LKHXB6T.js → chunk-TWJCLD4W.js} +48 -13
  32. package/dist/{chunk-K2RPVGPN.js → chunk-UC7YIEHT.js} +36 -17
  33. package/dist/{chunk-I6PSTQIR.js → chunk-VDDMADOF.js} +3 -3
  34. package/dist/{chunk-6PIYRG5I.js → chunk-VZ2ZHPS2.js} +52 -42
  35. package/dist/{chunk-AVIB7CT7.js → chunk-WNWQBB7F.js} +2 -2
  36. package/dist/{chunk-FRNAR33O.js → chunk-XZYFZ6A5.js} +3 -3
  37. package/dist/chunk-YIPMDGG6.js +703 -0
  38. package/dist/{chunk-RPHRPFEH.js → chunk-ZCFVHA25.js} +1 -1
  39. package/dist/{chunk-FPRHYBY2.js → chunk-ZFJXPCQP.js} +1 -1
  40. package/dist/{chunk-JYGD5WSN.js → chunk-ZWLDLTJP.js} +1 -1
  41. package/dist/{cloud-7QYOGF7F.js → cloud-KRTZ2IL5.js} +3 -3
  42. package/dist/cloud-M2YLWEXO.js +31 -0
  43. package/dist/{detect-BAJMY6KM.js → detect-ALF4GXRX.js} +7 -8
  44. package/dist/{dist-IQJ6H6UZ.js → dist-BM6NPWIH.js} +3 -3
  45. package/dist/{dist-es-X3B5QYKB.js → dist-es-2YRDXMUU.js} +6 -6
  46. package/dist/{dist-es-OSNJBLXB.js → dist-es-CCVZEFRZ.js} +5 -5
  47. package/dist/{dist-es-VNKHQVIB.js → dist-es-IOH6G4GM.js} +4 -4
  48. package/dist/{dist-es-RYHIPOTN.js → dist-es-JGBPABJI.js} +14 -14
  49. package/dist/{dist-es-JSTDUS7Q.js → dist-es-KWSMDPIP.js} +6 -6
  50. package/dist/{dist-es-5DY7K32L.js → dist-es-UYDDOVZ3.js} +6 -6
  51. package/dist/{dist-es-WV4AMOII.js → dist-es-XUOR4NQN.js} +8 -8
  52. package/dist/docker-QECQJ5P4.js +32 -0
  53. package/dist/docker-edge-executor-62N64MGS.js +17 -0
  54. package/dist/edge-import-SAYTRJLO.js +48 -0
  55. package/dist/ensure-container-edge-CFSCPGZK.js +32 -0
  56. package/dist/{event-streams-EHRAKL75.js → event-streams-TR4GAC53.js} +4 -4
  57. package/dist/{executor-LOYMPU67.js → executor-PT6UEJ5M.js} +8 -8
  58. package/dist/index.js +1228 -463
  59. package/dist/{loadSso-46FQRIZS.js → loadSso-UGF4JMRK.js} +10 -10
  60. package/dist/{local-executor-V7U5VOZW.js → local-executor-WOFZD72X.js} +4 -4
  61. package/dist/nginx-YOEEFBTE.js +31 -0
  62. package/dist/node-entry.js +4 -0
  63. package/dist/{noop-FMMFG2EZ.js → noop-NJ72F46T.js} +3 -3
  64. package/dist/openresty-lua-WGBO2M3Z.js +81 -0
  65. package/dist/server/index.js +23276 -8015
  66. package/dist/server/lua/geo_country.lua +34 -8
  67. package/dist/server/lua/maxminddb.lua +403 -0
  68. package/dist/server/lua/mgmt_api.lua +431 -68
  69. package/dist/server/lua/pipe_stream.lua +52 -39
  70. package/dist/server/lua/site_logger.lua +236 -30
  71. package/dist/server/migrations/0082_edge_target_verification.sql +39 -0
  72. package/dist/server/migrations/0083_service_incident.sql +84 -0
  73. package/dist/server/migrations/0084_analytics_daily_rollup.sql +72 -0
  74. package/dist/server/migrations/0085_resource_usage.sql +68 -0
  75. package/dist/server/migrations/0086_remote_infra_updates.sql +41 -0
  76. package/dist/server/migrations/0087_server_container_version_columns.sql +17 -0
  77. package/dist/server/migrations/0088_audit_source_and_settings.sql +27 -0
  78. package/dist/server/migrations/0089_auto_scan_infra.sql +7 -0
  79. package/dist/server/migrations/0090_project_collect_paths.sql +18 -0
  80. package/dist/server/migrations/0091_project_server_id.sql +26 -0
  81. package/dist/server/migrations/0092_project_internal_alias.sql +13 -0
  82. package/dist/server/migrations/0093_service_incident_org_index.sql +13 -0
  83. package/dist/server/migrations/0094_backup_restore_meta.sql +15 -0
  84. package/dist/server/migrations/0095_backup_restore_cancel.sql +19 -0
  85. package/dist/server/migrations/0096_backup_policy_retention_defaults.sql +20 -0
  86. package/dist/server/migrations/0097_update_status_upstream_only.sql +35 -0
  87. package/dist/server/migrations/meta/_journal.json +112 -0
  88. package/dist/setup-M2ZDGH3O.js +21 -0
  89. package/dist/{signin-ITOPKKUB.js → signin-3M3UPB6K.js} +10 -10
  90. package/dist/{sso-oidc-NON2PD7Y.js → sso-oidc-3VDIYOEJ.js} +10 -10
  91. package/dist/{sts-HHFFSAY2.js → sts-B3WIYLXR.js} +9 -9
  92. package/package.json +6 -3
  93. package/dist/bare-VRGE5MXH.js +0 -23
  94. package/dist/chunk-CUJXGK7R.js +0 -3167
  95. package/dist/chunk-EAAGSQXN.js +0 -377
  96. package/dist/cloud-3M2WZ624.js +0 -30
  97. package/dist/docker-2NGBRJFJ.js +0 -18
  98. package/dist/docker-edge-executor-5I4M5QT7.js +0 -13
  99. package/dist/edge-import-RIWNEIXQ.js +0 -47
  100. package/dist/ensure-container-edge-3NSYKHRX.js +0 -31
  101. package/dist/nginx-QE4DOM5J.js +0 -24
  102. package/dist/openresty-lua-BTAKECCF.js +0 -42
  103. package/dist/server/lua/pipe_log.lua +0 -71
  104. package/dist/setup-KELALK7H.js +0 -20
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  collectBody
7
- } from "./chunk-W73X43R7.js";
7
+ } from "./chunk-3NQQXMDR.js";
8
8
  import {
9
9
  toUtf8
10
- } from "./chunk-JYGD5WSN.js";
10
+ } from "./chunk-ZWLDLTJP.js";
11
11
 
12
12
  // ../../node_modules/@aws-sdk/core/dist-es/submodules/protocols/common.js
13
13
  var collectBodyString = (streamBody, context) => collectBody(streamBody, context).then((body) => (context?.utf8Encoder ?? toUtf8)(body));
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  var __create = Object.create;
@@ -1,22 +1,22 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  SerdeContextConfig,
7
7
  SignatureV4,
8
8
  UnionSerde
9
- } from "./chunk-IXCHURVK.js";
9
+ } from "./chunk-DOD2BXHQ.js";
10
10
  import {
11
11
  getValueFromTextNode
12
- } from "./chunk-VWPEKOH6.js";
12
+ } from "./chunk-DRK3MEDS.js";
13
13
  import {
14
14
  FromStringShapeDeserializer,
15
15
  NormalizedSchema
16
- } from "./chunk-W73X43R7.js";
16
+ } from "./chunk-3NQQXMDR.js";
17
17
  import {
18
18
  toUtf8
19
- } from "./chunk-JYGD5WSN.js";
19
+ } from "./chunk-ZWLDLTJP.js";
20
20
 
21
21
  // ../../node_modules/@smithy/signature-v4/dist-es/signature-v4a-container.js
22
22
  var signatureV4aContainer = {
@@ -1,32 +1,32 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  checkGit,
7
7
  installGit
8
- } from "./chunk-NXFIRK2Z.js";
8
+ } from "./chunk-IOT5ZX23.js";
9
9
  import {
10
10
  createDockerBuildContext,
11
11
  normalizeDockerRelativePath,
12
12
  resolveDockerfileCandidates
13
- } from "./chunk-V7BZMGOT.js";
13
+ } from "./chunk-EMXI4UCU.js";
14
14
  import {
15
15
  prepareStackOutput,
16
16
  resolveProjectDir,
17
17
  resolveStaticOutputPath,
18
18
  runLocalBuild
19
- } from "./chunk-KNTJ7PSF.js";
19
+ } from "./chunk-JIMUYEKN.js";
20
20
  import {
21
21
  BuildLogger,
22
22
  injectGitToken,
23
23
  runBuildPipeline,
24
24
  sq,
25
25
  transferLocalDirectory
26
- } from "./chunk-I6PSTQIR.js";
26
+ } from "./chunk-VDDMADOF.js";
27
27
  import {
28
28
  isRuntimeNotFoundError
29
- } from "./chunk-RPHRPFEH.js";
29
+ } from "./chunk-ZCFVHA25.js";
30
30
  import {
31
31
  STACKS,
32
32
  SYSTEM,
@@ -36,7 +36,7 @@ import {
36
36
  packageManagerEnsureCommand,
37
37
  safeErrorMessage,
38
38
  shellSplitWords
39
- } from "./chunk-UMQP7SYT.js";
39
+ } from "./chunk-OTLSJYAC.js";
40
40
 
41
41
  // ../../packages/adapters/src/runtime/cloud.ts
42
42
  import { readFile } from "fs/promises";
@@ -1,22 +1,22 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  collectBodyString
7
- } from "./chunk-EI575GHN.js";
7
+ } from "./chunk-PDW4L3NV.js";
8
8
  import {
9
9
  ProtocolLib,
10
10
  SerdeContextConfig,
11
11
  UnionSerde
12
- } from "./chunk-IXCHURVK.js";
12
+ } from "./chunk-DOD2BXHQ.js";
13
13
  import {
14
14
  HttpBindingProtocol,
15
15
  HttpInterceptingShapeDeserializer,
16
16
  HttpInterceptingShapeSerializer,
17
17
  NormalizedSchema,
18
18
  determineTimestampFormat
19
- } from "./chunk-W73X43R7.js";
19
+ } from "./chunk-3NQQXMDR.js";
20
20
  import {
21
21
  LazyJsonString,
22
22
  NumericValue,
@@ -27,7 +27,7 @@ import {
27
27
  parseRfc3339DateTimeWithOffset,
28
28
  parseRfc7231DateTime,
29
29
  toBase64
30
- } from "./chunk-JYGD5WSN.js";
30
+ } from "./chunk-ZWLDLTJP.js";
31
31
 
32
32
  // ../../node_modules/@aws-sdk/core/dist-es/submodules/protocols/json/jsonReviver.js
33
33
  function jsonReviver(key, value, context) {
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
 
@@ -1,28 +1,26 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  LocalExecutor
7
- } from "./chunk-TYVME3XD.js";
7
+ } from "./chunk-6FH4AXVY.js";
8
+ import {
9
+ explainEdgeDown,
10
+ isEdgeDownFailure
11
+ } from "./chunk-I3DPMTSF.js";
12
+ import {
13
+ edgeFailureReason
14
+ } from "./chunk-VZ2ZHPS2.js";
8
15
  import {
9
16
  logEntry,
10
17
  sq
11
- } from "./chunk-FPRHYBY2.js";
18
+ } from "./chunk-ZFJXPCQP.js";
12
19
 
13
20
  // ../../packages/adapters/src/system/docker-edge-executor.ts
14
21
  import Dockerode from "dockerode";
15
22
  import { PassThrough } from "stream";
16
23
  var DEFAULT_SOCKET = "/var/run/docker.sock";
17
- function explainEdgeExecError(err, containerName) {
18
- const msg = err?.message ?? String(err);
19
- if (/is not running|not running|409/i.test(msg)) {
20
- return new Error(
21
- `edge container "${containerName}" is not running yet (still starting, or stopped) \u2014 wait for it to be up (docker start ${containerName}) and retry.`
22
- );
23
- }
24
- return err instanceof Error ? err : new Error(msg);
25
- }
26
24
  var WRITE_CHUNK = 6e4;
27
25
  var DockerEdgeExecutor = class {
28
26
  docker;
@@ -36,6 +34,34 @@ var DockerEdgeExecutor = class {
36
34
  this.docker = opts.docker ?? new Dockerode({ socketPath: opts.socketPath ?? DEFAULT_SOCKET });
37
35
  this.fileMode = opts.fileMode ?? "mounted";
38
36
  }
37
+ /**
38
+ * Why the edge refused (or couldn't answer) a command, in one operator-facing
39
+ * line — the dockerode counterpart of `edgeContainerExecutor`'s host-shell probe.
40
+ *
41
+ * Reads the state and the log through the daemon API rather than a shell, which is
42
+ * the whole reason `edgeFailureReason` is a pure parser: the two transports agree
43
+ * on what counts as the cause without sharing a channel. Best-effort — a probe
44
+ * that fails must not replace the real failure with an error about diagnosing it.
45
+ *
46
+ * The condition this exists for used to be reported as `(HTTP code 409) … container
47
+ * <64-hex-id> is not running`: the RESOLVED id, no name, no cause. During `openship
48
+ * up` migration that surfaced as six identical 409s against the edge's own id while
49
+ * it was still starting, and from the cert flow it surfaced as a container the
50
+ * operator had no reason to think was involved at all.
51
+ */
52
+ async explainDown(err) {
53
+ const message = err?.message ?? String(err);
54
+ const container = this.docker.getContainer(this.containerName);
55
+ const status = await container.inspect().then((info) => info.State?.Status ?? null).catch(() => null);
56
+ const logs = await container.logs({ stdout: true, stderr: true, tail: 40, follow: false }).then((out) => Buffer.isBuffer(out) ? out.toString("utf8") : String(out)).catch(() => null);
57
+ const explanation = explainEdgeDown({
58
+ container: this.containerName,
59
+ status,
60
+ reason: logs ? edgeFailureReason(logs) : null
61
+ });
62
+ return new Error(`${explanation}
63
+ ${message}`);
64
+ }
39
65
  /** Run one command inside the edge container, capturing stdout/stderr + exit. */
40
66
  async run(command) {
41
67
  const container = this.docker.getContainer(this.containerName);
@@ -50,7 +76,9 @@ var DockerEdgeExecutor = class {
50
76
  });
51
77
  stream = await exec.start({ stdin: false });
52
78
  } catch (err) {
53
- throw explainEdgeExecError(err, this.containerName);
79
+ const message = err?.message ?? String(err);
80
+ if (isEdgeDownFailure(message) || /\b409\b/.test(message)) throw await this.explainDown(err);
81
+ throw err instanceof Error ? err : new Error(message);
54
82
  }
55
83
  const outStream = new PassThrough();
56
84
  const errStream = new PassThrough();
@@ -76,6 +104,7 @@ var DockerEdgeExecutor = class {
76
104
  const { code, stdout, stderr } = await this.run(command);
77
105
  if (code !== 0) {
78
106
  const detail = [stderr.trim(), stdout.trim()].filter(Boolean).join("\n");
107
+ if (isEdgeDownFailure(detail)) throw await this.explainDown(new Error(detail));
79
108
  throw new Error(
80
109
  detail || `command exited ${code} in edge container ${this.containerName}`
81
110
  );
@@ -86,6 +115,12 @@ var DockerEdgeExecutor = class {
86
115
  const { code, stdout, stderr } = await this.run(command);
87
116
  const output = [stdout, stderr].filter(Boolean).join("");
88
117
  if (output) onLog(logEntry(output, code === 0 ? "info" : "error"));
118
+ if (code !== 0 && isEdgeDownFailure(output)) {
119
+ const explanation = (await this.explainDown(new Error(output))).message.split("\n")[0];
120
+ onLog(logEntry(explanation, "error"));
121
+ return { code, output: `${explanation}
122
+ ${output}` };
123
+ }
89
124
  return { code, output };
90
125
  }
91
126
  // ── File ops ─────────────────────────────────────────────────────────────
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  import {
@@ -9,25 +9,25 @@ import {
9
9
  openSshUnixSocket,
10
10
  prepareSourceTarArgs,
11
11
  reconcileKnownHosts
12
- } from "./chunk-ZCOQJCZO.js";
12
+ } from "./chunk-6ODUBKUB.js";
13
13
  import {
14
14
  SshDisconnectedError
15
- } from "./chunk-RPHRPFEH.js";
15
+ } from "./chunk-ZCFVHA25.js";
16
16
  import {
17
17
  LocalExecutor
18
- } from "./chunk-TYVME3XD.js";
18
+ } from "./chunk-6FH4AXVY.js";
19
19
  import {
20
20
  emitBufferedLines,
21
21
  flushBufferedLines,
22
22
  hasLocalCommand,
23
23
  logEntry,
24
24
  sq
25
- } from "./chunk-FPRHYBY2.js";
25
+ } from "./chunk-ZFJXPCQP.js";
26
26
  import {
27
27
  TRANSFER_EXCLUDES,
28
28
  formatBytes,
29
29
  safeErrorMessage
30
- } from "./chunk-UMQP7SYT.js";
30
+ } from "./chunk-OTLSJYAC.js";
31
31
 
32
32
  // ../../packages/adapters/src/system/executor.ts
33
33
  import { existsSync, readFileSync } from "fs";
@@ -36,7 +36,7 @@ import { existsSync, readFileSync } from "fs";
36
36
  import { createReadStream } from "fs";
37
37
  import { mkdtemp as mkdtemp2, rm as fsRm2, stat } from "fs/promises";
38
38
  import { tmpdir as tmpdir2 } from "os";
39
- import { dirname, join as join2 } from "path";
39
+ import { join as join2, posix } from "path";
40
40
 
41
41
  // ../../packages/adapters/src/system/remote-transfer.ts
42
42
  import { spawn } from "child_process";
@@ -211,6 +211,7 @@ async function uploadFileWithRsync(localFile, remoteFile, deps, onLog, opts) {
211
211
  }
212
212
 
213
213
  // ../../packages/adapters/src/system/ssh-executor.ts
214
+ var remoteDirname = posix.dirname;
214
215
  function clampWindow(value, fallback, min, max) {
215
216
  if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
216
217
  return Math.max(min, Math.min(max, Math.floor(value)));
@@ -425,30 +426,47 @@ var SshExecutor = class _SshExecutor {
425
426
  });
426
427
  });
427
428
  }
428
- streamExec(command, onLog) {
429
- return this._streamExec(command, onLog).catch((err) => {
429
+ streamExec(command, onLog, opts) {
430
+ return this._streamExec(command, onLog, opts).catch((err) => {
430
431
  if (_SshExecutor.isChannelError(err)) {
431
432
  this.recoverFromChannelError();
432
- return this._streamExec(command, onLog);
433
+ return this._streamExec(command, onLog, opts);
433
434
  }
434
435
  throw err;
435
436
  });
436
437
  }
437
- async _streamExec(command, onLog) {
438
+ async _streamExec(command, onLog, opts) {
438
439
  const client = await this.connect();
440
+ const signal = opts?.signal;
439
441
  return new Promise((resolve, reject) => {
440
442
  let settled = false;
443
+ const chunks = [];
441
444
  const abort = (err) => finish(() => reject(err));
442
445
  const finish = (act) => {
443
446
  if (settled) return;
444
447
  settled = true;
445
448
  this.inflight.delete(abort);
449
+ signal?.removeEventListener("abort", onSignalAbort);
446
450
  act();
447
451
  };
448
452
  this.inflight.add(abort);
453
+ let channel = null;
454
+ const onSignalAbort = () => {
455
+ finish(() => resolve({ code: 0, output: chunks.join("") }));
456
+ try {
457
+ channel?.close();
458
+ } catch {
459
+ }
460
+ };
461
+ if (signal?.aborted) {
462
+ finish(() => resolve({ code: 0, output: "" }));
463
+ return;
464
+ }
449
465
  client.exec(_SshExecutor.ENV_PREFIX + command, (err, stream) => {
450
466
  if (err) return finish(() => reject(err));
451
- const chunks = [];
467
+ channel = stream;
468
+ if (signal?.aborted) return onSignalAbort();
469
+ signal?.addEventListener("abort", onSignalAbort, { once: true });
452
470
  const onChunk = (data, level) => {
453
471
  const text = data.toString();
454
472
  if (!text) return;
@@ -479,7 +497,7 @@ var SshExecutor = class _SshExecutor {
479
497
  });
480
498
  }
481
499
  async writeFile(path, content) {
482
- const dir = dirname(path);
500
+ const dir = remoteDirname(path);
483
501
  try {
484
502
  await this.exec(`mkdir -p ${sq(dir)}`);
485
503
  } catch {
@@ -794,7 +812,7 @@ var SshExecutor = class _SshExecutor {
794
812
  onLog?.(logEntry("Packing source into a single archive..."));
795
813
  await packLocalArchive(tarArgs, localArchive);
796
814
  const totalBytes = (await stat(localArchive)).size;
797
- await this.exec(`mkdir -p ${sq(dirname(remoteArchive))}`);
815
+ await this.exec(`mkdir -p ${sq(remoteDirname(remoteArchive))}`);
798
816
  const rsync = await canUseRemoteRsync(deps);
799
817
  if (rsync.ok) {
800
818
  onLog?.(logEntry(`Uploading ${formatBytes(totalBytes)} archive via rsync (resumable)...`));
@@ -920,7 +938,7 @@ import { once } from "events";
920
938
  import { mkdtemp as mkdtemp3, rm as fsRm3, stat as stat2, unlink } from "fs/promises";
921
939
  import { connect as netConnect } from "net";
922
940
  import { tmpdir as tmpdir3 } from "os";
923
- import { dirname as dirname2, join as join3 } from "path";
941
+ import { join as join3, posix as posix2 } from "path";
924
942
  import { Duplex } from "stream";
925
943
  import { promisify as promisify2 } from "util";
926
944
  import { randomBytes as randomBytes2 } from "crypto";
@@ -1028,6 +1046,7 @@ async function openSystemSshReverseTunnel(opts) {
1028
1046
 
1029
1047
  // ../../packages/adapters/src/system/system-ssh-executor.ts
1030
1048
  var execFileAsync2 = promisify2(execFile2);
1049
+ var remoteDirname2 = posix2.dirname;
1031
1050
  function clampWindow2(value, fallback, min, max) {
1032
1051
  if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
1033
1052
  return Math.max(min, Math.min(max, Math.floor(value)));
@@ -1219,7 +1238,7 @@ var SystemSshExecutor = class _SystemSshExecutor {
1219
1238
  });
1220
1239
  }
1221
1240
  async writeFile(path, content) {
1222
- const remoteCommand = `mkdir -p ${sq(dirname2(path))} && cat > ${sq(path)}`;
1241
+ const remoteCommand = `mkdir -p ${sq(remoteDirname2(path))} && cat > ${sq(path)}`;
1223
1242
  const res = await this.runSsh(remoteCommand, { input: content });
1224
1243
  if (res.code !== 0) {
1225
1244
  throw new Error(res.stderr.trim() || `Failed to write ${path} (exit ${res.code})`);
@@ -1290,7 +1309,7 @@ var SystemSshExecutor = class _SystemSshExecutor {
1290
1309
  onLog?.(logEntry("Packing source into a single archive..."));
1291
1310
  await packLocalArchive(tarArgs, localArchive);
1292
1311
  const totalBytes = (await stat2(localArchive)).size;
1293
- await this.exec(`mkdir -p ${sq(dirname2(remoteArchive))}`);
1312
+ await this.exec(`mkdir -p ${sq(remoteDirname2(remoteArchive))}`);
1294
1313
  const rsync = await canUseRemoteRsync(deps);
1295
1314
  if (rsync.ok) {
1296
1315
  onLog?.(logEntry(`Uploading ${formatBytes(totalBytes)} archive via rsync (resumable)...`));
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  getTarCreateEnv,
7
7
  prepareSourceTarArgs
8
- } from "./chunk-ZCOQJCZO.js";
8
+ } from "./chunk-6ODUBKUB.js";
9
9
  import {
10
10
  TRANSFER_EXCLUDES,
11
11
  packageManagerEnsureCommand,
12
12
  safeErrorMessage
13
- } from "./chunk-UMQP7SYT.js";
13
+ } from "./chunk-OTLSJYAC.js";
14
14
 
15
15
  // ../../packages/adapters/src/runtime/git-clone.ts
16
16
  function sq(value) {
@@ -1,17 +1,15 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  describeProcess,
7
- probeListeningPort
8
- } from "./chunk-ILFETZOM.js";
9
- import {
10
- OPENRESTY_LUA_DIR
11
- } from "./chunk-EAAGSQXN.js";
7
+ probeListeningPort,
8
+ waitForPortFree
9
+ } from "./chunk-3LDWWY7U.js";
12
10
  import {
13
11
  AppError
14
- } from "./chunk-UMQP7SYT.js";
12
+ } from "./chunk-OTLSJYAC.js";
15
13
 
16
14
  // ../../packages/adapters/src/system/proxy/detect.ts
17
15
  var EDGE_PORTS = [80, 443];
@@ -105,19 +103,16 @@ async function sanitizeEdgeVhosts(executor, sitesDir, onLog) {
105
103
  }
106
104
  }
107
105
  }
108
- async function edgeIsBroken(executor) {
106
+ async function edgeIsBroken(executor, container = EDGE_CONTAINER_NAME) {
109
107
  const status = await tryExec(
110
108
  executor,
111
- `docker inspect -f '{{.State.Status}}' ${sq(EDGE_CONTAINER_NAME)} 2>/dev/null`
109
+ `docker inspect -f '{{.State.Status}}' ${sq(container)} 2>/dev/null`
112
110
  );
113
111
  const state = (status ?? "").trim();
114
112
  return state === "restarting" || state === "exited" || state === "dead";
115
113
  }
116
- async function edgeCrashReason(executor) {
117
- const logs = await tryExec(
118
- executor,
119
- `docker logs --tail 40 ${sq(EDGE_CONTAINER_NAME)} 2>&1`
120
- );
114
+ async function edgeCrashReason(executor, container = EDGE_CONTAINER_NAME) {
115
+ const logs = await tryExec(executor, `docker logs --tail 40 ${sq(container)} 2>&1`);
121
116
  return logs ? edgeFailureReason(logs) : null;
122
117
  }
123
118
  function edgeFailureReason(containerLog) {
@@ -152,6 +147,22 @@ async function resolveOurEdgeContainer(executor, opts) {
152
147
  });
153
148
  return resolved;
154
149
  }
150
+ async function detectEdgeContainer(executor) {
151
+ const out = await tryExec(
152
+ executor,
153
+ `docker ps -a --format '{{.Names}} {{.Image}} {{.State}}' 2>/dev/null`
154
+ );
155
+ if (out === null) return null;
156
+ const absent = { name: null, running: false, image: null, exists: false };
157
+ for (const line of out.split("\n").map((l) => l.trim()).filter(Boolean)) {
158
+ const [name, image, state] = line.split(" ");
159
+ if (!name) continue;
160
+ if (name === EDGE_CONTAINER_NAME || isOurEdgeContainer(name, image)) {
161
+ return { name, image: image || null, running: state === "running", exists: true };
162
+ }
163
+ }
164
+ return absent;
165
+ }
155
166
  async function probeOurEdgeContainer(executor) {
156
167
  const byName = await tryExec(
157
168
  executor,
@@ -166,13 +177,6 @@ async function probeOurEdgeContainer(executor) {
166
177
  }
167
178
  return null;
168
179
  }
169
- async function ourLuaOnHost(executor) {
170
- const lua = await tryExec(
171
- executor,
172
- `test -f ${OPENRESTY_LUA_DIR}/site_logger.lua && echo ok`
173
- );
174
- return Boolean(lua && lua.includes("ok"));
175
- }
176
180
  async function detectDockerOnPort(executor, port) {
177
181
  const out = await tryExec(
178
182
  executor,
@@ -184,15 +188,6 @@ async function detectDockerOnPort(executor, port) {
184
188
  if (!name) return null;
185
189
  return { name, image: image ?? "" };
186
190
  }
187
- async function listenerIsOurOpenResty(executor, listener) {
188
- if (!listener) return false;
189
- if (/openresty/i.test(`${listener.rawCommand ?? ""} ${listener.command ?? ""}`)) return true;
190
- if (listener.pid) {
191
- const exe = await tryExec(executor, `readlink -f /proc/${listener.pid}/exe 2>/dev/null || true`);
192
- if (exe && /openresty/i.test(exe)) return true;
193
- }
194
- return false;
195
- }
196
191
  var WORKER_RE = /\b(?:nginx|openresty)\s*:\s*worker process/i;
197
192
  var MASTER_RE = /\b(?:nginx|openresty)\s*:\s*master process/i;
198
193
  async function resolveProxyMaster(executor, listener) {
@@ -224,7 +219,7 @@ async function probeEdgePort(executor, port, ours) {
224
219
  ].filter(Boolean).join(" ")
225
220
  );
226
221
  const foreignDockerProxy = Boolean(docker) && !isOurEdgeContainer(docker?.name, docker?.image);
227
- const managedByOpenship = isOurEdgeContainer(docker?.name, docker?.image) || ours.containerRunning && !foreignDockerProxy || !docker && ours.luaOnHost && await listenerIsOurOpenResty(executor, listener);
222
+ const managedByOpenship = isOurEdgeContainer(docker?.name, docker?.image) || ours.containerRunning && !foreignDockerProxy;
228
223
  return {
229
224
  port,
230
225
  pid: listener?.pid ?? void 0,
@@ -239,18 +234,18 @@ async function probeEdgePort(executor, port, ours) {
239
234
  };
240
235
  }
241
236
  async function probeEdge(executor) {
242
- const containerRunning = await ourEdgeContainerRunning(executor);
243
- const luaOnHost = await ourLuaOnHost(executor);
244
- const all = [];
237
+ const container = await resolveOurEdgeContainer(executor);
238
+ const containerRunning = Boolean(container) && !await edgeIsBroken(executor, container);
239
+ const occupants = [];
245
240
  for (const port of EDGE_PORTS) {
246
- const occ = await probeEdgePort(executor, port, { containerRunning, luaOnHost });
247
- if (occ) all.push(occ);
241
+ const occ = await probeEdgePort(executor, port, { containerRunning });
242
+ if (occ) occupants.push(occ);
248
243
  }
249
- const foreign = all.filter((o) => !o.managedByOpenship);
244
+ const foreign = occupants.filter((o) => !o.managedByOpenship);
250
245
  let classification;
251
- if (all.length === 0) classification = "free";
246
+ if (occupants.length === 0) classification = "free";
252
247
  else if (foreign.length === 0) classification = "ours";
253
- else if (foreign.every((o) => o.proxy && o.proxy !== "openresty")) classification = "known";
248
+ else if (foreign.every((o) => o.proxy)) classification = "known";
254
249
  else classification = "unknown";
255
250
  return {
256
251
  classification,
@@ -277,7 +272,7 @@ function stopTargetsForStatus(status) {
277
272
  }
278
273
  return out;
279
274
  }
280
- async function freeEdgeTargets(executor, targets, onLog) {
275
+ async function freeEdgeTargets(executor, targets, onLog, opts = {}) {
281
276
  for (const t of targets) {
282
277
  const where = t.port ? ` (port ${t.port})` : "";
283
278
  if (t.container) {
@@ -297,7 +292,22 @@ async function freeEdgeTargets(executor, targets, onLog) {
297
292
  await tryExec(executor, `kill -9 ${t.pid} 2>/dev/null || true`);
298
293
  }
299
294
  }
300
- await new Promise((r) => setTimeout(r, 1e3));
295
+ const named = [...new Set(targets.map((t) => t.port).filter((p) => typeof p === "number"))];
296
+ const stillBound = [];
297
+ for (const port of named.length ? named : [...EDGE_PORTS]) {
298
+ const { free, checked } = await waitForPortFree(executor, port, {
299
+ ...opts.timeoutMs === void 0 ? {} : { timeoutMs: opts.timeoutMs }
300
+ });
301
+ if (!checked) {
302
+ onLog(`Couldn't confirm port ${port} was released (socket table unreadable) \u2014 continuing.`, "warn");
303
+ continue;
304
+ }
305
+ if (!free) {
306
+ stillBound.push(port);
307
+ onLog(`Port ${port} is STILL bound after stopping its owner.`, "error");
308
+ }
309
+ }
310
+ return { freed: stillBound.length === 0, stillBound };
301
311
  }
302
312
 
303
313
  export {
@@ -314,7 +324,7 @@ export {
314
324
  ourEdgeContainerRunning,
315
325
  invalidateEdgeContainer,
316
326
  resolveOurEdgeContainer,
317
- ourLuaOnHost,
327
+ detectEdgeContainer,
318
328
  probeEdge,
319
329
  stopTargetsForStatus,
320
330
  freeEdgeTargets
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  __commonJS,
7
7
  __require,
8
8
  __toESM
9
- } from "./chunk-KI2EY3WB.js";
9
+ } from "./chunk-PXKCZB2I.js";
10
10
 
11
11
  // ../../node_modules/ws/lib/constants.js
12
12
  var require_constants = __commonJS({
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env sh
2
- ":" //# ; exec "$(command -v bun || command -v node)" "$0" "$@"
2
+ ":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
3
3
  import { createRequire as __ospCreateRequire } from "node:module";
4
4
  const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  setCredentialFeature
7
- } from "./chunk-VWPEKOH6.js";
7
+ } from "./chunk-DRK3MEDS.js";
8
8
  import {
9
9
  CredentialsProviderError
10
- } from "./chunk-W73X43R7.js";
10
+ } from "./chunk-3NQQXMDR.js";
11
11
 
12
12
  // ../../node_modules/@aws-sdk/credential-provider-env/dist-es/fromEnv.js
13
13
  var ENV_KEY = "AWS_ACCESS_KEY_ID";