dsh-zen-remote 2.2.9 → 2.3.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 (149) hide show
  1. package/README.md +2 -2
  2. package/README.zh-CN.md +2 -2
  3. package/docs/interface.md +1 -1
  4. package/docs/remote-access.md +20 -0
  5. package/lan-gate.mjs +11 -1
  6. package/lib/adapters/dsh-better-sidebar/index.js +6 -2
  7. package/lib/adapters/dsh-better-sidebar/index.js.map +1 -1
  8. package/lib/adapters/dsh-better-sidebar/methods.js +3 -0
  9. package/lib/adapters/dsh-better-sidebar/methods.js.map +1 -1
  10. package/lib/admin-routes.js +33 -2
  11. package/lib/admin-routes.js.map +1 -1
  12. package/lib/client.js +3289 -6
  13. package/lib/config.js +70 -0
  14. package/lib/config.js.map +1 -1
  15. package/lib/index.js +232 -2
  16. package/lib/index.js.map +1 -1
  17. package/lib/intercept.js +43 -3
  18. package/lib/intercept.js.map +1 -1
  19. package/lib/lan-gate-server.cjs +29 -3
  20. package/lib/merge-streams.js +42 -12
  21. package/lib/merge-streams.js.map +1 -1
  22. package/lib/types/adapters/dsh-better-sidebar/index.d.ts +1 -1
  23. package/lib/types/adapters/dsh-better-sidebar/index.d.ts.map +1 -1
  24. package/lib/types/adapters/dsh-better-sidebar/methods.d.ts.map +1 -1
  25. package/lib/types/admin-routes.d.ts +13 -0
  26. package/lib/types/admin-routes.d.ts.map +1 -1
  27. package/lib/types/client/index.d.ts.map +1 -1
  28. package/lib/types/client/locales.d.ts +204 -1
  29. package/lib/types/client/locales.d.ts.map +1 -1
  30. package/lib/types/client/wizard/GatewayWizard.d.ts +29 -0
  31. package/lib/types/client/wizard/GatewayWizard.d.ts.map +1 -0
  32. package/lib/types/client/wizard/WizardCard.d.ts +30 -0
  33. package/lib/types/client/wizard/WizardCard.d.ts.map +1 -0
  34. package/lib/types/client/wizard/cards/MigrateCard.d.ts +15 -0
  35. package/lib/types/client/wizard/cards/MigrateCard.d.ts.map +1 -0
  36. package/lib/types/client/wizard/cards/PortForwardCard.d.ts +15 -0
  37. package/lib/types/client/wizard/cards/PortForwardCard.d.ts.map +1 -0
  38. package/lib/types/client/wizard/cards/ProxyCard.d.ts +19 -0
  39. package/lib/types/client/wizard/cards/ProxyCard.d.ts.map +1 -0
  40. package/lib/types/client/wizard/cards/TokenCard.d.ts +20 -0
  41. package/lib/types/client/wizard/cards/TokenCard.d.ts.map +1 -0
  42. package/lib/types/client/wizard/register-wizard.d.ts +51 -0
  43. package/lib/types/client/wizard/register-wizard.d.ts.map +1 -0
  44. package/lib/types/client/wizard/wizard-css.d.ts +10 -0
  45. package/lib/types/client/wizard/wizard-css.d.ts.map +1 -0
  46. package/lib/types/client-data/qr.d.ts +20 -0
  47. package/lib/types/client-data/qr.d.ts.map +1 -0
  48. package/lib/types/client-data/settings-form.d.ts +7 -2
  49. package/lib/types/client-data/settings-form.d.ts.map +1 -1
  50. package/lib/types/client-data/wizard.d.ts +247 -0
  51. package/lib/types/client-data/wizard.d.ts.map +1 -0
  52. package/lib/types/config.d.ts +27 -0
  53. package/lib/types/config.d.ts.map +1 -1
  54. package/lib/types/index.d.ts.map +1 -1
  55. package/lib/types/intercept.d.ts.map +1 -1
  56. package/lib/types/merge-streams.d.ts.map +1 -1
  57. package/lib/types/wizard/binary-io.d.ts +111 -0
  58. package/lib/types/wizard/binary-io.d.ts.map +1 -0
  59. package/lib/types/wizard/binary.d.ts +118 -0
  60. package/lib/types/wizard/binary.d.ts.map +1 -0
  61. package/lib/types/wizard/caddy-process.d.ts +101 -0
  62. package/lib/types/wizard/caddy-process.d.ts.map +1 -0
  63. package/lib/types/wizard/caddy.d.ts +53 -0
  64. package/lib/types/wizard/caddy.d.ts.map +1 -0
  65. package/lib/types/wizard/cloudflare.d.ts +112 -0
  66. package/lib/types/wizard/cloudflare.d.ts.map +1 -0
  67. package/lib/types/wizard/cloudflared.d.ts +71 -0
  68. package/lib/types/wizard/cloudflared.d.ts.map +1 -0
  69. package/lib/types/wizard/probe.d.ts +66 -0
  70. package/lib/types/wizard/probe.d.ts.map +1 -0
  71. package/lib/types/wizard/proxy-snippets.d.ts +60 -0
  72. package/lib/types/wizard/proxy-snippets.d.ts.map +1 -0
  73. package/lib/types/wizard/routes.d.ts +152 -0
  74. package/lib/types/wizard/routes.d.ts.map +1 -0
  75. package/lib/types/wizard/source-detect.d.ts +53 -0
  76. package/lib/types/wizard/source-detect.d.ts.map +1 -0
  77. package/lib/types/wizard/status.d.ts +115 -0
  78. package/lib/types/wizard/status.d.ts.map +1 -0
  79. package/lib/types/wizard/token-store.d.ts +27 -0
  80. package/lib/types/wizard/token-store.d.ts.map +1 -0
  81. package/lib/types/wizard/tunnel-orchestrator.d.ts +90 -0
  82. package/lib/types/wizard/tunnel-orchestrator.d.ts.map +1 -0
  83. package/lib/types/wizard/verify.d.ts +97 -0
  84. package/lib/types/wizard/verify.d.ts.map +1 -0
  85. package/lib/wizard/binary-io.js +386 -0
  86. package/lib/wizard/binary-io.js.map +1 -0
  87. package/lib/wizard/binary.js +138 -0
  88. package/lib/wizard/binary.js.map +1 -0
  89. package/lib/wizard/caddy-process.js +162 -0
  90. package/lib/wizard/caddy-process.js.map +1 -0
  91. package/lib/wizard/caddy.js +80 -0
  92. package/lib/wizard/caddy.js.map +1 -0
  93. package/lib/wizard/cloudflare.js +334 -0
  94. package/lib/wizard/cloudflare.js.map +1 -0
  95. package/lib/wizard/cloudflared.js +158 -0
  96. package/lib/wizard/cloudflared.js.map +1 -0
  97. package/lib/wizard/probe.js +118 -0
  98. package/lib/wizard/probe.js.map +1 -0
  99. package/lib/wizard/proxy-snippets.js +112 -0
  100. package/lib/wizard/proxy-snippets.js.map +1 -0
  101. package/lib/wizard/routes.js +462 -0
  102. package/lib/wizard/routes.js.map +1 -0
  103. package/lib/wizard/source-detect.js +77 -0
  104. package/lib/wizard/source-detect.js.map +1 -0
  105. package/lib/wizard/status.js +94 -0
  106. package/lib/wizard/status.js.map +1 -0
  107. package/lib/wizard/token-store.js +71 -0
  108. package/lib/wizard/token-store.js.map +1 -0
  109. package/lib/wizard/tunnel-orchestrator.js +155 -0
  110. package/lib/wizard/tunnel-orchestrator.js.map +1 -0
  111. package/lib/wizard/verify.js +171 -0
  112. package/lib/wizard/verify.js.map +1 -0
  113. package/package.json +37 -37
  114. package/scripts/check-settings-form.mjs +5 -4
  115. package/scripts/check-wizard-ui.mjs +690 -0
  116. package/src/adapters/dsh-better-sidebar/index.ts +6 -2
  117. package/src/adapters/dsh-better-sidebar/methods.ts +3 -0
  118. package/src/admin-routes.ts +44 -2
  119. package/src/client/index.tsx +9 -0
  120. package/src/client/locales.ts +410 -2
  121. package/src/client/wizard/GatewayWizard.tsx +2220 -0
  122. package/src/client/wizard/WizardCard.tsx +81 -0
  123. package/src/client/wizard/cards/MigrateCard.tsx +42 -0
  124. package/src/client/wizard/cards/PortForwardCard.tsx +37 -0
  125. package/src/client/wizard/cards/ProxyCard.tsx +56 -0
  126. package/src/client/wizard/cards/TokenCard.tsx +81 -0
  127. package/src/client/wizard/register-wizard.ts +99 -0
  128. package/src/client/wizard/wizard-css.ts +948 -0
  129. package/src/client-data/qr.ts +284 -0
  130. package/src/client-data/settings-form.ts +12 -3
  131. package/src/client-data/wizard.ts +432 -0
  132. package/src/config.ts +87 -0
  133. package/src/index.ts +227 -2
  134. package/src/intercept.ts +43 -3
  135. package/src/merge-streams.ts +41 -12
  136. package/src/wizard/binary-io.ts +449 -0
  137. package/src/wizard/binary.ts +177 -0
  138. package/src/wizard/caddy-process.ts +228 -0
  139. package/src/wizard/caddy.ts +97 -0
  140. package/src/wizard/cloudflare.ts +413 -0
  141. package/src/wizard/cloudflared.ts +196 -0
  142. package/src/wizard/probe.ts +161 -0
  143. package/src/wizard/proxy-snippets.ts +128 -0
  144. package/src/wizard/routes.ts +537 -0
  145. package/src/wizard/source-detect.ts +87 -0
  146. package/src/wizard/status.ts +180 -0
  147. package/src/wizard/token-store.ts +73 -0
  148. package/src/wizard/tunnel-orchestrator.ts +197 -0
  149. package/src/wizard/verify.ts +236 -0
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Final-verification orchestration (GW-9): the wizard's last mile, where
3
+ * 「完成」 means a real phone really paired through the real public URL —
4
+ * never a green light from internal checks alone (设计: 不做已联通的假绿灯).
5
+ *
6
+ * The flow, spread over two entry points the UI drives:
7
+ *
8
+ * start({ publicUrl }): runtime ready? → walk the public URL
9
+ * (GW-8's probe; BOTH the pairing page and the admin-403 shape must be
10
+ * right) → snapshot the gateway's device ids (the baseline) → mint a WEB
11
+ * pairing code → remember the session IN MEMORY and answer with the
12
+ * code, the URL and the expiry. The code never touches the row config,
13
+ * and minting it restarts nothing — trustedProxies changes are what
14
+ * restart the gateway, and any such change invalidates the session
15
+ * instead (the config fingerprint below).
16
+ *
17
+ * check(): re-read the gateway status. A device id the baseline did not
18
+ * have is a freshly paired phone; the gateway's lastWebClaim record must
19
+ * name THAT device with secure === true (the proxy passed
20
+ * X-Forwarded-Proto: https through, so the issued cookie carries the
21
+ * Secure flag). All green → pass. The claim recorded an insecure cookie →
22
+ * cookie-insecure. Past the code's expiry → code-expired. Anything else →
23
+ * pending, keep polling.
24
+ *
25
+ * The session binds to a CONFIG FINGERPRINT (ingressMode, domain,
26
+ * httpsPort, publicUrl, the gateway's ACTUAL port, host, trustedProxies):
27
+ * any of those moving between start and check answers stale and discards
28
+ * the session, because the verification proved a URL that no longer exists.
29
+ * The session is deliberately memory-only — a row reload (which a
30
+ * trustedProxies change causes) builds a fresh manager and the session is
31
+ * gone, exactly the same verdict the fingerprint would have produced.
32
+ */
33
+ import type { ZenRemoteConfig } from '../config.js';
34
+ import { type HostPathOutcome } from './probe.js';
35
+ export interface VerificationManagerOptions {
36
+ /** Loopback base of the gateway child, `http://127.0.0.1:<port>`. */
37
+ gatewayBase: string;
38
+ /** Fresh resolved config values per call (volatile discipline). */
39
+ getValues: () => ZenRemoteConfig;
40
+ /** The hostPath probe; injectable for tests (defaults to GW-8's real one). */
41
+ probe?: (publicUrl: string) => Promise<HostPathOutcome>;
42
+ /** Whether the ingress processes are alive (Caddy / cloudflared). The
43
+ * wiring supplies this once the process managers are mounted; absent
44
+ * means "checked elsewhere" and only the gateway is probed. */
45
+ runtimeReady?: () => boolean | Promise<boolean>;
46
+ fetchImpl?: typeof fetch;
47
+ /** Per-gateway-call ceiling. Default 5000 ms. */
48
+ timeoutMs?: number;
49
+ /** Clock (tests drive expiry). */
50
+ now?: () => number;
51
+ }
52
+ export type VerificationStartResult = {
53
+ ok: true;
54
+ pairingCode: string;
55
+ publicUrl: string;
56
+ expiresAt: number;
57
+ } | {
58
+ ok: false;
59
+ reason: 'no-public-url' | 'bad-public-url' | 'runtime-not-ready' | 'gateway-unreachable' | 'probe-failed' | 'pair-refused';
60
+ /** The probe's classifications for `probe-failed`; the gateway's status
61
+ * code for `pair-refused`; the normalize failure reason for
62
+ * `bad-public-url`. */
63
+ detail?: unknown;
64
+ };
65
+ export type VerificationCheckResult = {
66
+ result: 'not-started';
67
+ } | {
68
+ result: 'stale';
69
+ } | {
70
+ result: 'code-expired';
71
+ } | {
72
+ result: 'pending';
73
+ } | {
74
+ result: 'cookie-insecure';
75
+ deviceId: string;
76
+ } | {
77
+ result: 'pass';
78
+ deviceId: string;
79
+ at: number;
80
+ };
81
+ /**
82
+ * The config fingerprint a session binds to: any drift between start and
83
+ * check means the verified URL is no longer the deployed URL.
84
+ */
85
+ export declare function verificationFingerprint(values: ZenRemoteConfig, gatewayPort: number | null): string;
86
+ export interface VerificationManager {
87
+ start(input: {
88
+ publicUrl: unknown;
89
+ probeOnly?: boolean;
90
+ }): Promise<VerificationStartResult>;
91
+ check(): Promise<VerificationCheckResult>;
92
+ /** Whether a verification session is open (the route surfaces it for the
93
+ * UI's 「待外部验证」 state). */
94
+ hasSession(): boolean;
95
+ }
96
+ export declare function createVerificationManager(options: VerificationManagerOptions): VerificationManager;
97
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/wizard/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEnD,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAA;AAEhE,MAAM,WAAW,0BAA0B;IACzC,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,SAAS,EAAE,MAAM,eAAe,CAAA;IAChC,8EAA8E;IAC9E,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,CAAC,CAAA;IACvD;;mEAE+D;IAC/D,YAAY,CAAC,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC/C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED,MAAM,MAAM,uBAAuB,GAC/B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACvE;IACA,EAAE,EAAE,KAAK,CAAA;IACT,MAAM,EAAE,eAAe,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,cAAc,GAAG,cAAc,CAAA;IAC1H;;2BAEuB;IACvB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAEH,MAAM,MAAM,uBAAuB,GAC/B;IAAE,MAAM,EAAE,aAAa,CAAA;CAAE,GACzB;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GACnB;IAAE,MAAM,EAAE,cAAc,CAAA;CAAE,GAC1B;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAA;AASpD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAUnG;AAWD,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAA;IAC3F,KAAK,IAAI,OAAO,CAAC,uBAAuB,CAAC,CAAA;IACzC;8BAC0B;IAC1B,UAAU,IAAI,OAAO,CAAA;CACtB;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,0BAA0B,GAAG,mBAAmB,CAyHlG"}
@@ -0,0 +1,386 @@
1
+ /**
2
+ * Ingress binary I/O (GW-2, revised by GW-fix-1/H1): download, unpack,
3
+ * install and cache-probe for the two wizard-managed binaries. The
4
+ * arithmetic lives in binary.ts; this file is the only one allowed to touch
5
+ * the filesystem or the network for it.
6
+ *
7
+ * House rules the tasks pin down:
8
+ *
9
+ * - No shell, no `child_process` at all. Downloads ride `fetch`, the
10
+ * body streams straight to a `.part` file, and the install is a POSIX
11
+ * rename — a crash mid-download can never leave a half binary at the
12
+ * install path.
13
+ * - The archive wrapper comes from binary.ts's METADATA (`options.archive`,
14
+ * what binaryUrls() models per platform), never from sniffing the URL:
15
+ * the Caddy build API's URL is a query string whose ending says nothing
16
+ * about the tar.gz / zip payload it answers with (GW-fix-1/H1).
17
+ * - Windows' Caddy asset is a zip and there is no zip reader here yet:
18
+ * refused up front with the typed `windows-zip-unsupported` code, the
19
+ * manual-install link stays the fallback (GW-fix-1/H1 item 3).
20
+ * - After unpacking (or for a bare download), a unix image must carry an
21
+ * ELF or Mach-O magic; anything else is refused as `bad-binary-image`
22
+ * and leaves nothing on disk (GW-fix-1/H1 item 4). Windows keeps no
23
+ * magic check — PE inspection is not this module's job.
24
+ * - The darwin cloudflared asset is a `.tgz`; it is unpacked with
25
+ * `zlib.gunzipSync` plus a minimal ustar reader (the archive carries a
26
+ * single entry — no PAX/GNU long-name handling needed, but those
27
+ * header types are skipped correctly if an upstream rebuild adds one).
28
+ * - Installed images get 0755; `ensureBinary` is idempotent (an existing
29
+ * executable short-circuits before any network traffic).
30
+ *
31
+ * `fetch` is injectable so the tests drive real downloads against a local
32
+ * mock server without touching the network.
33
+ */
34
+ import { accessSync, chmodSync, closeSync, constants as fsConstants, createWriteStream, mkdirSync, openSync, readFileSync, readSync, renameSync, rmSync, statSync, writeFileSync, } from 'node:fs';
35
+ import { Readable, Transform } from 'node:stream';
36
+ import { pipeline } from 'node:stream/promises';
37
+ import { gunzipSync } from 'node:zlib';
38
+ import { MANUAL_INSTALL_LINKS, binaryDownloadCandidates, binaryInstallPath, binDir, binaryUrls, currentPlatform, } from './binary.js';
39
+ /** Generous ceiling on one download; a mirror gone wrong must not be able
40
+ * to fill the disk. Both real binaries sit far below 200 MB. */
41
+ const MAX_DOWNLOAD_BYTES = 512 * 1024 * 1024;
42
+ /** Connection / response-headers timeout before a mirror is skipped. */
43
+ const CONNECT_TIMEOUT_MS = 10_000;
44
+ /** Maximum idle gap between body chunks before a stalled mirror is aborted. */
45
+ const STALL_TIMEOUT_MS = 15_000;
46
+ /** ELF: `\x7fELF`. */
47
+ const ELF_MAGIC = Buffer.from([0x7f, 0x45, 0x4c, 0x46]);
48
+ /** Mach-O 32 big-endian, Mach-O 64 big-endian, Mach-O 64 little-endian —
49
+ * the three shapes Apple toolchains emit for this codebase's targets. */
50
+ const MACH_O_MAGICS = [
51
+ Buffer.from([0xfe, 0xed, 0xfa, 0xce]),
52
+ Buffer.from([0xfe, 0xed, 0xfa, 0xcf]),
53
+ Buffer.from([0xcf, 0xfa, 0xed, 0xfe]),
54
+ ];
55
+ /** Whether the first bytes of an image look like an executable this module
56
+ * is willing to install on a unix host (GW-fix-1/H1 item 4). */
57
+ function looksLikeUnixImage(head) {
58
+ return ELF_MAGIC.equals(head) || MACH_O_MAGICS.some((magic) => magic.equals(head));
59
+ }
60
+ /** The first four bytes of a file (fewer when the file is shorter). */
61
+ function headBytes(path) {
62
+ const head = Buffer.alloc(4);
63
+ const fd = openSync(path, 'r');
64
+ try {
65
+ return head.subarray(0, readSync(fd, head, 0, 4, 0));
66
+ }
67
+ finally {
68
+ closeSync(fd);
69
+ }
70
+ }
71
+ /**
72
+ * One failed or refused download/install. `code` is the wire-stable marker
73
+ * the UI classifies on — `'download-failed'` for transport/shaping
74
+ * failures, `'windows-zip-unsupported'` for the zip refusal, and
75
+ * `'bad-binary-image'` when the payload did not carry an executable
76
+ * image's magic. `installUrl` is the official manual-install page the
77
+ * failure card links to. Fields are assigned in the constructor body rather
78
+ * than declared as parameter properties (the check scripts import modules
79
+ * through Node's strip-only type stripping, which rejects that syntax).
80
+ */
81
+ export class BinaryDownloadError extends Error {
82
+ code;
83
+ tool;
84
+ url;
85
+ status;
86
+ installUrl;
87
+ constructor(tool, url, status, message, options) {
88
+ super(message, options);
89
+ this.name = 'BinaryDownloadError';
90
+ this.code = options?.code ?? 'download-failed';
91
+ this.tool = tool;
92
+ this.url = url;
93
+ this.status = status;
94
+ this.installUrl = MANUAL_INSTALL_LINKS[tool];
95
+ }
96
+ }
97
+ /** Whether `path` exists and is executable (the "already installed" test). */
98
+ function isExecutableFile(path) {
99
+ try {
100
+ if (!statSync(path).isFile())
101
+ return false;
102
+ accessSync(path, fsConstants.X_OK);
103
+ return true;
104
+ }
105
+ catch {
106
+ return false;
107
+ }
108
+ }
109
+ /**
110
+ * The installed binary's absolute path, or undefined when it is not (yet)
111
+ * on disk in executable shape — the read-only probe; see binary.ts's
112
+ * `binaryInstallPath` for the pure arithmetic.
113
+ */
114
+ export function binaryPath(dshHome, tool, platform = currentPlatform()) {
115
+ const path = binaryInstallPath(dshHome, tool, platform);
116
+ return isExecutableFile(path) ? path : undefined;
117
+ }
118
+ /** Write one fetched response body to `partPath` under the size cap and
119
+ * per-chunk stall timeout so a throttled or hung mirror fails over quickly. */
120
+ async function streamToFile(tool, url, body, partPath, onProgress) {
121
+ let received = 0;
122
+ let stallTimer;
123
+ const counter = new Transform({
124
+ transform(chunk, _encoding, done) {
125
+ received += chunk.length;
126
+ if (received > MAX_DOWNLOAD_BYTES) {
127
+ done(new BinaryDownloadError(tool, url, null, `the download of ${tool} exceeds the ${MAX_DOWNLOAD_BYTES}-byte cap`));
128
+ return;
129
+ }
130
+ if (stallTimer !== undefined)
131
+ clearTimeout(stallTimer);
132
+ stallTimer = setTimeout(() => {
133
+ counter.destroy(new BinaryDownloadError(tool, url, null, `the download of ${tool} stalled after ${received} bytes`));
134
+ }, STALL_TIMEOUT_MS);
135
+ if (typeof stallTimer.unref === 'function')
136
+ stallTimer.unref();
137
+ onProgress?.(received, null);
138
+ done(null, chunk);
139
+ },
140
+ });
141
+ stallTimer = setTimeout(() => {
142
+ counter.destroy(new BinaryDownloadError(tool, url, null, `the download of ${tool} stalled before first byte`));
143
+ }, STALL_TIMEOUT_MS);
144
+ if (typeof stallTimer.unref === 'function')
145
+ stallTimer.unref();
146
+ try {
147
+ await pipeline(Readable.fromWeb(body), counter, createWriteStream(partPath, { mode: 0o644 }));
148
+ }
149
+ catch (error) {
150
+ rmSync(partPath, { force: true });
151
+ throw error;
152
+ }
153
+ finally {
154
+ if (stallTimer !== undefined)
155
+ clearTimeout(stallTimer);
156
+ }
157
+ }
158
+ /** Size bytes of a ustar header's octal size field, 0 when unparsable. */
159
+ function tarEntrySize(header) {
160
+ const raw = header.subarray(124, 136).toString('ascii').replace(/[\0 ]+$/g, '').trim();
161
+ const size = parseInt(raw === '' ? '0' : raw, 8);
162
+ return Number.isFinite(size) && size > 0 ? size : 0;
163
+ }
164
+ /**
165
+ * The first regular-file payload of a ustar archive as one buffer slice.
166
+ * The cloudflared `.tgz` carries exactly one (`cloudflared`); anything else
167
+ * (PAX/GNU metadata, directories) is skipped by advancing over its data
168
+ * blocks, so a future archive layout change degrades to "not found" instead
169
+ * of corrupt bytes.
170
+ */
171
+ function firstTarFileEntry(archive) {
172
+ let offset = 0;
173
+ while (offset + 512 <= archive.length) {
174
+ const header = archive.subarray(offset, offset + 512);
175
+ if (header.every((byte) => byte === 0))
176
+ return undefined;
177
+ const size = tarEntrySize(header);
178
+ const typeflag = String.fromCharCode(header[156] ?? 0x20);
179
+ const dataStart = offset + 512;
180
+ if ((typeflag === '0' || typeflag === '\0') && size > 0 && dataStart + size <= archive.length) {
181
+ return archive.subarray(dataStart, dataStart + size);
182
+ }
183
+ offset = dataStart + Math.ceil(size / 512) * 512;
184
+ }
185
+ return undefined;
186
+ }
187
+ function chmodExec(path) {
188
+ try {
189
+ chmodSync(path, 0o755);
190
+ }
191
+ catch {
192
+ // Windows: no executable bit — the extension does that job.
193
+ }
194
+ }
195
+ /** Install `bytes` at `installPath`: `.part` sibling, chmod, atomic rename. */
196
+ function installBytes(bytes, installPath) {
197
+ const partPath = `${installPath}.part`;
198
+ try {
199
+ writeFileSync(partPath, bytes, { mode: 0o644 });
200
+ chmodExec(partPath);
201
+ renameSync(partPath, installPath);
202
+ }
203
+ catch (error) {
204
+ rmSync(partPath, { force: true });
205
+ throw error;
206
+ }
207
+ }
208
+ /** The unix image-magic gate (GW-fix-1/H1 item 4): a payload that does not
209
+ * open with an ELF or Mach-O magic is refused, nothing lands on disk. */
210
+ function assertUnixImageMagic(tool, url, status, head) {
211
+ if (looksLikeUnixImage(head))
212
+ return;
213
+ throw new BinaryDownloadError(tool, url, status, `the downloaded ${tool} does not carry an ELF or Mach-O image magic`, { code: 'bad-binary-image' });
214
+ }
215
+ /**
216
+ * Download one binary from an explicit URL and install it. The archive
217
+ * wrapper is the CALLER'S metadata (`options.archive`) — `ensureBinary`
218
+ * feeds it from binaryUrls(); tests pin it per fixture. `platform` only
219
+ * matters for the install name and the magic-check gate; it defaults to
220
+ * this process's.
221
+ * @returns the absolute install path.
222
+ */
223
+ export async function downloadBinary(dshHome, tool, url, options = {}) {
224
+ const platform = options.platform ?? currentPlatform();
225
+ const archive = options.archive ?? 'none';
226
+ const installPath = binaryInstallPath(dshHome, tool, platform);
227
+ if (archive === 'zip') {
228
+ // Refused BEFORE any network traffic: there is no zip reader in this
229
+ // codebase yet (GW-fix-1/H1 item 3), and half-supporting the format
230
+ // would only install a zip's bytes as an image.
231
+ throw new BinaryDownloadError(tool, url, null, `the ${tool} asset for Windows ships as a zip, which cannot be unpacked here yet`, { code: 'windows-zip-unsupported' });
232
+ }
233
+ const fetchImpl = options.fetchImpl ?? fetch;
234
+ let response;
235
+ try {
236
+ response = await fetchImpl(url, {
237
+ redirect: 'follow',
238
+ signal: AbortSignal.timeout(CONNECT_TIMEOUT_MS),
239
+ });
240
+ }
241
+ catch (cause) {
242
+ throw new BinaryDownloadError(tool, url, null, `the download of ${tool} failed before an answer arrived`, { cause });
243
+ }
244
+ if (!response.ok || response.body === null) {
245
+ throw new BinaryDownloadError(tool, url, response.status, `the download of ${tool} answered ${response.status}`);
246
+ }
247
+ mkdirSync(binDir(dshHome), { recursive: true });
248
+ const declared = Number(response.headers.get('content-length'));
249
+ const total = Number.isFinite(declared) && declared > 0 ? declared : null;
250
+ const onProgress = options.onProgress
251
+ ? (received) => options.onProgress?.(received, total)
252
+ : undefined;
253
+ if (archive === 'tgz') {
254
+ // Archive (or auto-detected bare binary if an upstream endpoint serves a
255
+ // raw ELF/Mach-O image despite tgz metadata): land the bytes in a sibling,
256
+ // then either install directly when the payload already starts with a
257
+ // unix image magic or gunzip + extract the tar entry.
258
+ const tgzPath = `${installPath}.download.tgz`;
259
+ try {
260
+ await streamToFile(tool, url, response.body, tgzPath, onProgress);
261
+ const rawBytes = readFileSync(tgzPath);
262
+ const gzipMagic = rawBytes.length >= 2 && rawBytes[0] === 0x1f && rawBytes[1] === 0x8b;
263
+ const entry = (!gzipMagic && platform.os !== 'windows' && looksLikeUnixImage(rawBytes.subarray(0, 4)))
264
+ ? rawBytes
265
+ : firstTarFileEntry(gunzipSync(rawBytes));
266
+ if (entry === undefined) {
267
+ throw new BinaryDownloadError(tool, url, response.status, `the ${tool} archive carried no binary entry`);
268
+ }
269
+ if (platform.os !== 'windows')
270
+ assertUnixImageMagic(tool, url, response.status, entry.subarray(0, 4));
271
+ installBytes(entry, installPath);
272
+ }
273
+ catch (error) {
274
+ if (error instanceof BinaryDownloadError)
275
+ throw error;
276
+ throw new BinaryDownloadError(tool, url, response.status, `the ${tool} archive could not be unpacked`, { cause: error });
277
+ }
278
+ finally {
279
+ rmSync(tgzPath, { force: true });
280
+ }
281
+ return installPath;
282
+ }
283
+ // Bare executable: stream to the .part, gate the magic, then rename.
284
+ const partPath = `${installPath}.part`;
285
+ try {
286
+ await streamToFile(tool, url, response.body, partPath, onProgress);
287
+ if (platform.os !== 'windows')
288
+ assertUnixImageMagic(tool, url, response.status, headBytes(partPath));
289
+ chmodExec(partPath);
290
+ renameSync(partPath, installPath);
291
+ }
292
+ catch (error) {
293
+ rmSync(partPath, { force: true });
294
+ if (error instanceof BinaryDownloadError)
295
+ throw error;
296
+ throw new BinaryDownloadError(tool, url, response.status, `the download of ${tool} could not be written to disk`, { cause: error });
297
+ }
298
+ return installPath;
299
+ }
300
+ /** Cached mainland-China network detection so repeated downloads do not
301
+ * re-probe within the same process. */
302
+ let cachedCnNetwork;
303
+ /**
304
+ * Detect whether the current host is in mainland China:
305
+ * 1. Fast local check: system timezone is `Asia/Shanghai`, `Asia/Chongqing`,
306
+ * `Asia/Harbin`, or `Asia/Urumqi`, or `LANG`/`LC_ALL` carries `zh_CN`.
307
+ * 2. Quick 1.5s probe to Cloudflare's `/cdn-cgi/trace` (`loc=CN`), or if
308
+ * direct `github.com` HEAD fails/times out within 2s.
309
+ */
310
+ export async function detectCnNetwork(fetchImpl = fetch) {
311
+ if (cachedCnNetwork !== undefined)
312
+ return cachedCnNetwork;
313
+ try {
314
+ const tz = Intl.DateTimeFormat().resolvedOptions().timeZone ?? '';
315
+ if (/^Asia\/(Shanghai|Chongqing|Harbin|Urumqi)$/i.test(tz)) {
316
+ cachedCnNetwork = true;
317
+ return true;
318
+ }
319
+ }
320
+ catch { /* ignore */ }
321
+ const envLang = `${process.env.LANG ?? ''} ${process.env.LC_ALL ?? ''}`;
322
+ if (/zh_CN/i.test(envLang)) {
323
+ cachedCnNetwork = true;
324
+ return true;
325
+ }
326
+ try {
327
+ const trace = await fetchImpl('https://www.cloudflare.com/cdn-cgi/trace', {
328
+ signal: AbortSignal.timeout(1500),
329
+ });
330
+ if (trace.ok) {
331
+ const text = await trace.text();
332
+ if (/\bloc=CN\b/i.test(text)) {
333
+ cachedCnNetwork = true;
334
+ return true;
335
+ }
336
+ cachedCnNetwork = false;
337
+ return false;
338
+ }
339
+ }
340
+ catch {
341
+ // ignore trace timeout
342
+ }
343
+ cachedCnNetwork = false;
344
+ return false;
345
+ }
346
+ /**
347
+ * The idempotent front door: an already-installed executable short-circuits
348
+ * (no network), anything else downloads from the official distribution
349
+ * point for the tool, archive shape included.
350
+ *
351
+ * When using the default `fetch` transport, automatically detects mainland
352
+ * China network environments and tries prebuilt GitHub Release mirrors
353
+ * (`gh-proxy.com` / `ghfast.top`) + direct GitHub Release before falling back
354
+ * to `caddyserver.com/api/download`. When a custom `fetchImpl` is injected
355
+ * (unit tests), calls the canonical `binaryUrls(platform)` endpoint directly.
356
+ * @returns the absolute install path and whether THIS call downloaded.
357
+ */
358
+ export async function ensureBinary(dshHome, tool, options = {}) {
359
+ const platform = options.platform ?? currentPlatform();
360
+ const existing = binaryPath(dshHome, tool, platform);
361
+ if (existing !== undefined)
362
+ return { path: existing, downloaded: false };
363
+ if (options.fetchImpl !== undefined) {
364
+ const urls = binaryUrls(platform);
365
+ const [url, archive] = tool === 'caddy' ? [urls.caddy, urls.caddyArchive] : [urls.cloudflared, urls.cloudflaredArchive];
366
+ const path = await downloadBinary(dshHome, tool, url, { ...options, archive });
367
+ return { path, downloaded: true };
368
+ }
369
+ const preferCnMirror = await detectCnNetwork();
370
+ const candidates = binaryDownloadCandidates(tool, platform, preferCnMirror);
371
+ let lastError;
372
+ for (const candidate of candidates) {
373
+ try {
374
+ const path = await downloadBinary(dshHome, tool, candidate.url, {
375
+ ...options,
376
+ archive: candidate.archive,
377
+ });
378
+ return { path, downloaded: true };
379
+ }
380
+ catch (error) {
381
+ lastError = error;
382
+ }
383
+ }
384
+ throw lastError;
385
+ }
386
+ //# sourceMappingURL=binary-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary-io.js","sourceRoot":"","sources":["../../src/wizard/binary-io.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Ingress binary arithmetic (GW-2): platform mapping, download-URL
3
+ * construction and install-path computation for the two binaries the
4
+ * gateway wizard manages — Caddy (custom build with the Cloudflare DNS
5
+ * module, for DNS-01 certificates) and cloudflared (the tunnel client).
6
+ *
7
+ * Pure by contract: URL strings, path strings and platform facts only —
8
+ * every touch of the filesystem or the network lives in binary-io.ts, and
9
+ * the routes layer reads both. `node:path`/`node:os` here are arithmetic,
10
+ * not I/O: the same discipline as virtual-id.ts's zero-dependency rule,
11
+ * relaxed one notch because path building is this module's whole job.
12
+ *
13
+ * Platform coverage mirrors what both upstream distribution points actually
14
+ * ship: darwin/linux/windows × amd64/arm64. macOS arm64's cloudflared asset
15
+ * is a `.tgz` (the only archive shape in the set) — binary-io unpacks it.
16
+ */
17
+ import { join } from 'node:path';
18
+ import { homedir } from 'node:os';
19
+ /** This process's platform, mapped into the download points' naming. */
20
+ export function currentPlatform() {
21
+ if (process.platform === 'win32')
22
+ return { os: 'windows', arch: 'amd64' };
23
+ const arch = process.arch === 'arm64' ? 'arm64' : 'amd64';
24
+ if (process.platform === 'darwin')
25
+ return { os: 'darwin', arch };
26
+ return { os: 'linux', arch };
27
+ }
28
+ /** Caddy's custom-build API, pinned to the Cloudflare DNS module the
29
+ * DNS-01 challenge needs (plain Caddy cannot write the TXT record). */
30
+ export function caddyDownloadUrl(platform) {
31
+ return `https://caddyserver.com/api/download?os=${platform.os}&arch=${platform.arch}&p=github.com/caddy-dns/cloudflare`;
32
+ }
33
+ /**
34
+ * The Caddy asset the build API answers with, PLUS its archive shape —
35
+ * `caddyserver.com/api/download` returns a bare Mach-O/ELF binary on unix
36
+ * (`Content-Disposition: attachment; filename="caddy_<os>_<arch>_custom"`,
37
+ * `Content-Type: application/octet-stream`) and a bare `.exe` on Windows.
38
+ */
39
+ export function caddyDownload(platform) {
40
+ return { url: caddyDownloadUrl(platform), archive: platform.os === 'windows' ? 'exe' : 'none' };
41
+ }
42
+ /** cloudflared's GitHub Releases asset for one platform, plus the archive
43
+ * shape the I/O half must unwrap (darwin assets are `.tgz`, windows ships
44
+ * a bare `.exe`, linux a bare binary). */
45
+ export function cloudflaredDownload(platform) {
46
+ const base = 'https://github.com/cloudflare/cloudflared/releases/latest/download/';
47
+ if (platform.os === 'darwin')
48
+ return { url: `${base}cloudflared-darwin-${platform.arch}.tgz`, archive: 'tgz' };
49
+ if (platform.os === 'windows')
50
+ return { url: `${base}cloudflared-windows-amd64.exe`, archive: 'exe' };
51
+ return { url: `${base}cloudflared-linux-${platform.arch}`, archive: 'none' };
52
+ }
53
+ /** Both download URLs for one platform WITH their archive shapes, defaults
54
+ * to the running process's. The archive metadata — not a URL suffix — is
55
+ * what tells the I/O half how to unpack. */
56
+ export function binaryUrls(platform = currentPlatform()) {
57
+ const caddy = caddyDownload(platform);
58
+ const cloudflared = cloudflaredDownload(platform);
59
+ return { caddy: caddy.url, caddyArchive: caddy.archive, cloudflared: cloudflared.url, cloudflaredArchive: cloudflared.archive };
60
+ }
61
+ /** Official manual-install pages, surfaced by the UI when a download fails. */
62
+ export const MANUAL_INSTALL_LINKS = {
63
+ caddy: 'https://caddyserver.com/download',
64
+ cloudflared: 'https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/',
65
+ };
66
+ /** Everything ingress lives under this one directory of DSH_HOME. */
67
+ export const INGRESS_DIR_NAME = 'zen-remote-ingress';
68
+ /** `<DSH_HOME>` as the rest of the plugin resolves it (config.ts's convention). */
69
+ export function dshHomeDefault(env = process.env) {
70
+ return env.DSH_HOME ?? join(homedir(), '.dsh');
71
+ }
72
+ /** `<DSH_HOME>/zen-remote-ingress` — Caddyfile, data dir and bin/ sit here. */
73
+ export function ingressDir(dshHome) {
74
+ return join(dshHome, INGRESS_DIR_NAME);
75
+ }
76
+ /** `<DSH_HOME>/zen-remote-ingress/bin` — both binaries install here. */
77
+ export function binDir(dshHome) {
78
+ return join(ingressDir(dshHome), 'bin');
79
+ }
80
+ /** `<DSH_HOME>/zen-remote-ingress/Caddyfile` — generated, validated, then
81
+ * handed to `caddy run --config`. */
82
+ export function caddyfilePath(dshHome) {
83
+ return join(ingressDir(dshHome), 'Caddyfile');
84
+ }
85
+ /** `<DSH_HOME>/zen-remote-ingress/caddy-data` — certificates and the ACME
86
+ * account live here, kept out of the default Caddy home. */
87
+ export function caddyDataDir(dshHome) {
88
+ return join(ingressDir(dshHome), 'caddy-data');
89
+ }
90
+ /** The installed file name. Windows cannot spawn an extension-less image,
91
+ * so the `.exe` suffix is part of the install name there. */
92
+ export function binaryFileName(tool, platform = currentPlatform()) {
93
+ if (platform.os === 'windows')
94
+ return tool === 'caddy' ? 'caddy.exe' : 'cloudflared.exe';
95
+ return tool;
96
+ }
97
+ /** The absolute install path for one binary (where downloadBinary puts it). */
98
+ export function binaryInstallPath(dshHome, tool, platform = currentPlatform()) {
99
+ return join(binDir(dshHome), binaryFileName(tool, platform));
100
+ }
101
+ /** Prebuilt Caddy + `github.com/caddy-dns/cloudflare` release assets hosted
102
+ * on this repository's `caddy-cloudflare` GitHub Release (built by
103
+ * `.github/workflows/caddy-assets.yml`). Unlike `caddyserver.com/api/download`
104
+ * — which compiles on the fly and throttles downloads to ~13 KB/s — these
105
+ * static GitHub Release assets download in seconds and work with mainland
106
+ * China GitHub acceleration mirrors (`gh-proxy.com` / `ghfast.top`). */
107
+ export function caddyPrebuiltDownload(platform) {
108
+ const base = 'https://github.com/KyoMio/dsh-zen-remote/releases/download/caddy-cloudflare/';
109
+ if (platform.os === 'windows')
110
+ return { url: `${base}caddy-windows-amd64.exe`, archive: 'exe' };
111
+ return { url: `${base}caddy-${platform.os}-${platform.arch}.tgz`, archive: 'tgz' };
112
+ }
113
+ /** Mainland China GitHub release acceleration mirrors, tried first when the
114
+ * host environment is detected as mainland China (or tried as fallbacks if
115
+ * direct GitHub times out). */
116
+ export const GITHUB_MIRROR_PREFIXES = [
117
+ 'https://gh-proxy.com/',
118
+ 'https://ghfast.top/',
119
+ ];
120
+ /** Ordered candidate downloads for one binary and platform:
121
+ * - When `preferCnMirror` is true, GitHub Release URLs through mainland
122
+ * mirrors come first, followed by direct GitHub Release URL, and finally
123
+ * (for Caddy) the upstream `caddyserver.com/api/download` fallback.
124
+ * - When `preferCnMirror` is false, direct GitHub Release comes first, then
125
+ * mainland mirrors, then the upstream build API fallback. */
126
+ export function binaryDownloadCandidates(tool, platform = currentPlatform(), preferCnMirror = false) {
127
+ const primary = tool === 'caddy' ? caddyPrebuiltDownload(platform) : cloudflaredDownload(platform);
128
+ const mirrored = GITHUB_MIRROR_PREFIXES.map((prefix) => ({
129
+ url: `${prefix}${primary.url}`,
130
+ archive: primary.archive,
131
+ }));
132
+ const ordered = preferCnMirror ? [...mirrored, primary] : [primary, ...mirrored];
133
+ if (tool === 'caddy') {
134
+ ordered.push(caddyDownload(platform));
135
+ }
136
+ return ordered;
137
+ }
138
+ //# sourceMappingURL=binary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary.js","sourceRoot":"","sources":["../../src/wizard/binary.ts"],"names":[],"mappings":"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"}