dsh-mobile 0.8.5 → 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -1
- package/CONTRIBUTORS.md +10 -4
- package/README.en.md +3 -2
- package/README.md +3 -2
- package/apps/mobile/README.md +2 -0
- package/apps/mobile/README.zh-CN.md +2 -0
- package/docs/CLIENT_MODULES.en.md +1 -1
- package/docs/CLIENT_MODULES.md +1 -1
- package/docs/README.md +1 -1
- package/docs/WEB_PUSH.en.md +20 -4
- package/docs/WEB_PUSH.md +20 -4
- package/lib/cli.js +104 -9
- package/lib/cli.js.map +1 -1
- package/lib/client.js +207 -14
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +40 -1
- package/lib/index.mjs +373 -31
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/packages/question-fixes/package.json +1 -1
package/lib/index.mjs
CHANGED
|
@@ -1210,6 +1210,39 @@ function parseGatewayConfig(raw) {
|
|
|
1210
1210
|
});
|
|
1211
1211
|
}
|
|
1212
1212
|
// src/exec-file.ts
|
|
1213
|
+
/**
|
|
1214
|
+
* Longest stream text attached to a failed subprocess result.
|
|
1215
|
+
*
|
|
1216
|
+
* The text exists for diagnostics only: a caller decides which part is safe to
|
|
1217
|
+
* show. It is bounded here so a chatty child cannot turn one failure into an
|
|
1218
|
+
* unbounded buffer in every future consumer of that rejection.
|
|
1219
|
+
*/
|
|
1220
|
+
const MAX_SUBPROCESS_ERROR_STREAM_CHARS = 8192;
|
|
1221
|
+
function boundedStream(value) {
|
|
1222
|
+
if (typeof value !== "string" || value === "") return void 0;
|
|
1223
|
+
return value.length <= 8192 ? value : value.slice(0, MAX_SUBPROCESS_ERROR_STREAM_CHARS);
|
|
1224
|
+
}
|
|
1225
|
+
/**
|
|
1226
|
+
* Attach the captured streams to a subprocess failure, best effort.
|
|
1227
|
+
*
|
|
1228
|
+
* `execFile` reports a non-zero exit as an Error whose only text is the command
|
|
1229
|
+
* line with stderr merged into `message`; the raw stream strings are handed to
|
|
1230
|
+
* the callback and otherwise discarded, so a caller cannot read them from the
|
|
1231
|
+
* rejection. They are copied onto it when it accepts properties. A frozen,
|
|
1232
|
+
* exotic or primitive rejection value must keep `message` as its diagnostic
|
|
1233
|
+
* rather than turn one failure into a different error, so every write is
|
|
1234
|
+
* guarded and an existing property is never overwritten.
|
|
1235
|
+
*/
|
|
1236
|
+
function attachCapturedStreams(error, stdout, stderr) {
|
|
1237
|
+
if (typeof error !== "object" || error === null) return;
|
|
1238
|
+
const target = error;
|
|
1239
|
+
try {
|
|
1240
|
+
const capturedStderr = boundedStream(stderr);
|
|
1241
|
+
const capturedStdout = boundedStream(stdout);
|
|
1242
|
+
if (target.stderr === void 0 && capturedStderr !== void 0) target.stderr = capturedStderr;
|
|
1243
|
+
if (target.stdout === void 0 && capturedStdout !== void 0) target.stdout = capturedStdout;
|
|
1244
|
+
} catch {}
|
|
1245
|
+
}
|
|
1213
1246
|
/** Capture both output streams even when a desktop host wraps execFile without Node's promisify metadata. */
|
|
1214
1247
|
function execFileText(file, args, options = {}) {
|
|
1215
1248
|
return new Promise((resolve, reject) => {
|
|
@@ -1219,6 +1252,7 @@ function execFileText(file, args, options = {}) {
|
|
|
1219
1252
|
encoding: "utf8"
|
|
1220
1253
|
}, (error, stdout, stderr) => {
|
|
1221
1254
|
if (error !== null) {
|
|
1255
|
+
attachCapturedStreams(error, stdout, stderr);
|
|
1222
1256
|
reject(error);
|
|
1223
1257
|
return;
|
|
1224
1258
|
}
|
|
@@ -5703,6 +5737,7 @@ const MOBILE_PUSH_PREFERENCES_PATH = `${AUTH_PREFIX}/push/preferences`;
|
|
|
5703
5737
|
const MOBILE_PUSH_DISABLE_PATH = `${AUTH_PREFIX}/push/disable`;
|
|
5704
5738
|
const MOBILE_PUSH_TEST_PATH = `${AUTH_PREFIX}/push/test`;
|
|
5705
5739
|
const MOBILE_PUSH_RESOLVE_PATH = `${AUTH_PREFIX}/push/resolve`;
|
|
5740
|
+
const BACKGROUND_EVENT_PATH = `${AUTH_PREFIX}/background-events`;
|
|
5706
5741
|
const MOBILE_PUSH_PREFERENCE_KEYS = [
|
|
5707
5742
|
"question",
|
|
5708
5743
|
"plan",
|
|
@@ -6448,6 +6483,12 @@ function sanitizeRequestHeaders(request, upstream) {
|
|
|
6448
6483
|
const value = request.headers[name];
|
|
6449
6484
|
if (value !== void 0) headers[name] = value;
|
|
6450
6485
|
}
|
|
6486
|
+
for (const name of Object.keys(request.headers)) {
|
|
6487
|
+
const lower = name.toLowerCase();
|
|
6488
|
+
if (!lower.startsWith("x-dsh-") || lower.startsWith("x-dsh-mobile-") || lower === "x-dsh-auth-token") continue;
|
|
6489
|
+
const value = request.headers[name];
|
|
6490
|
+
if (value !== void 0) headers[name] = Array.isArray(value) ? value[0] : value;
|
|
6491
|
+
}
|
|
6451
6492
|
return headers;
|
|
6452
6493
|
}
|
|
6453
6494
|
const BLOCKED_RESPONSE_HEADERS = /* @__PURE__ */ new Set([
|
|
@@ -7601,6 +7642,7 @@ var MobileAccessGateway = class {
|
|
|
7601
7642
|
const computerImage = request.method === "GET" && target.decodedPathname === `/mobile-access/computer-image`;
|
|
7602
7643
|
const workspaceDirectories = (request.method === "GET" || request.method === "POST") && target.decodedPathname === `/mobile-access/workspace-directories`;
|
|
7603
7644
|
const clientModules = target.decodedPathname === `${AUTH_PREFIX}/client-modules`;
|
|
7645
|
+
const backgroundEvents = target.decodedPathname === BACKGROUND_EVENT_PATH;
|
|
7604
7646
|
const mobilePushRoute = [
|
|
7605
7647
|
MOBILE_PUSH_CONFIG_PATH,
|
|
7606
7648
|
MOBILE_PUSH_SUBSCRIPTION_PATH,
|
|
@@ -7634,7 +7676,7 @@ var MobileAccessGateway = class {
|
|
|
7634
7676
|
fallback: void 0,
|
|
7635
7677
|
digest: requestedCompatRevision
|
|
7636
7678
|
} : void 0;
|
|
7637
|
-
if (customAsset === void 0 && requestedMobileBootBatch === void 0 && !computerImages && !computerImage && !workspaceDirectories && !clientModules && !mobilePushRoute && extensionTarget(target.decodedPathname) === void 0 && (target.decodedPathname === "/mobile-access" || target.decodedPathname.startsWith(`/mobile-access/`))) throw new HttpError(404, "not_found");
|
|
7679
|
+
if (customAsset === void 0 && requestedMobileBootBatch === void 0 && !computerImages && !computerImage && !workspaceDirectories && !clientModules && !backgroundEvents && !mobilePushRoute && extensionTarget(target.decodedPathname) === void 0 && (target.decodedPathname === "/mobile-access" || target.decodedPathname.startsWith(`/mobile-access/`))) throw new HttpError(404, "not_found");
|
|
7638
7680
|
if (![
|
|
7639
7681
|
"GET",
|
|
7640
7682
|
"HEAD",
|
|
@@ -7675,6 +7717,11 @@ var MobileAccessGateway = class {
|
|
|
7675
7717
|
await this.handleMobilePushRequest(target, request, response, authorization);
|
|
7676
7718
|
return;
|
|
7677
7719
|
}
|
|
7720
|
+
if (backgroundEvents) {
|
|
7721
|
+
if (request.method !== "GET" || target.search !== "") throw new HttpError(request.method === "GET" ? 400 : 405, request.method === "GET" ? "bad_request" : "method_not_allowed");
|
|
7722
|
+
this.openBackgroundEventStream(request, response, authorization);
|
|
7723
|
+
return;
|
|
7724
|
+
}
|
|
7678
7725
|
if (clientModules) {
|
|
7679
7726
|
if (target.search !== "") throw new HttpError(400, "bad_request");
|
|
7680
7727
|
if (request.method !== "GET" && request.method !== "POST") throw new HttpError(405, "method_not_allowed");
|
|
@@ -9415,6 +9462,54 @@ var MobileAccessGateway = class {
|
|
|
9415
9462
|
request.once("aborted", close);
|
|
9416
9463
|
response.once("close", close);
|
|
9417
9464
|
}
|
|
9465
|
+
/**
|
|
9466
|
+
* Native background notifications need only Host task and revocation events.
|
|
9467
|
+
* They use the paired session cookie but no mobile document view, because the
|
|
9468
|
+
* App has no live WebView while this stream is serving a suspended page.
|
|
9469
|
+
*/
|
|
9470
|
+
openBackgroundEventStream(request, response, authorization) {
|
|
9471
|
+
const operation = this.allocateRequest(authorization, response, {});
|
|
9472
|
+
let closed = false;
|
|
9473
|
+
let heartbeat;
|
|
9474
|
+
const close = () => {
|
|
9475
|
+
if (closed) return;
|
|
9476
|
+
closed = true;
|
|
9477
|
+
if (heartbeat !== void 0) clearInterval(heartbeat);
|
|
9478
|
+
this.taskEventListeners.delete(sendTask);
|
|
9479
|
+
const deviceListeners = this.deviceEventListeners.get(authorization.deviceId);
|
|
9480
|
+
deviceListeners?.delete(sendDevice);
|
|
9481
|
+
if (deviceListeners?.size === 0) this.deviceEventListeners.delete(authorization.deviceId);
|
|
9482
|
+
request.removeListener("aborted", close);
|
|
9483
|
+
response.removeListener("close", close);
|
|
9484
|
+
operation.release();
|
|
9485
|
+
};
|
|
9486
|
+
const sendTask = (payload) => {
|
|
9487
|
+
if (closed || response.destroyed || response.writableEnded) return;
|
|
9488
|
+
response.write(`event: task-notify\ndata: ${payload}\n\n`);
|
|
9489
|
+
};
|
|
9490
|
+
const sendDevice = (payload) => {
|
|
9491
|
+
if (closed || response.destroyed || response.writableEnded) return;
|
|
9492
|
+
response.write(`event: device-revoked\ndata: ${payload}\n\n`);
|
|
9493
|
+
};
|
|
9494
|
+
setSecurityHeaders(response, this.tlsEnabled);
|
|
9495
|
+
response.writeHead(200, {
|
|
9496
|
+
"Content-Type": "text/event-stream; charset=utf-8",
|
|
9497
|
+
"Cache-Control": "no-store",
|
|
9498
|
+
Connection: "keep-alive",
|
|
9499
|
+
"X-Accel-Buffering": "no"
|
|
9500
|
+
});
|
|
9501
|
+
response.write("retry: 2000\n: ready\n\n");
|
|
9502
|
+
this.taskEventListeners.add(sendTask);
|
|
9503
|
+
const deviceListeners = this.deviceEventListeners.get(authorization.deviceId) ?? /* @__PURE__ */ new Set();
|
|
9504
|
+
deviceListeners.add(sendDevice);
|
|
9505
|
+
this.deviceEventListeners.set(authorization.deviceId, deviceListeners);
|
|
9506
|
+
heartbeat = setInterval(() => {
|
|
9507
|
+
if (!closed && !response.destroyed && !response.writableEnded) response.write(": heartbeat\n\n");
|
|
9508
|
+
}, EXTENSION_EVENT_HEARTBEAT_MS);
|
|
9509
|
+
heartbeat.unref();
|
|
9510
|
+
request.once("aborted", close);
|
|
9511
|
+
response.once("close", close);
|
|
9512
|
+
}
|
|
9418
9513
|
async readUpgradeResponse(upstream, expectedAccept) {
|
|
9419
9514
|
return new Promise((resolve, reject) => {
|
|
9420
9515
|
let buffer = Buffer.alloc(0);
|
|
@@ -9903,6 +9998,26 @@ var MemoryDeviceStore = class {
|
|
|
9903
9998
|
return structuredClone(this.snapshot);
|
|
9904
9999
|
}
|
|
9905
10000
|
};
|
|
10001
|
+
// src/mobile-push/service.ts
|
|
10002
|
+
/**
|
|
10003
|
+
* Small Cordis service exposed to trusted Host plugins. The provider owns the
|
|
10004
|
+
* runtime lifetime and all recipient, category, session, and expiry checks.
|
|
10005
|
+
*/
|
|
10006
|
+
var MobilePushService = class extends Service {
|
|
10007
|
+
send;
|
|
10008
|
+
constructor(ctx, send) {
|
|
10009
|
+
super(ctx, "mobilePush");
|
|
10010
|
+
this.send = send;
|
|
10011
|
+
}
|
|
10012
|
+
/**
|
|
10013
|
+
* Queue a notification for enabled web-push recipients.
|
|
10014
|
+
* @param input - Session, text, optional category and optional expiry.
|
|
10015
|
+
* @returns The number of newly queued recipient deliveries and the applied expiry.
|
|
10016
|
+
*/
|
|
10017
|
+
async notify(input) {
|
|
10018
|
+
return await this.send(input);
|
|
10019
|
+
}
|
|
10020
|
+
};
|
|
9906
10021
|
// src/managed-files.ts
|
|
9907
10022
|
/** Refuse link-shaped ancestors inside an owned state root before accessing a child. */
|
|
9908
10023
|
async function assertManagedParents(root, target, prefix) {
|
|
@@ -15961,6 +16076,79 @@ var IrohIdentityProbeError = class extends Error {
|
|
|
15961
16076
|
function publicStatus$2(status) {
|
|
15962
16077
|
return Object.freeze({ ...status });
|
|
15963
16078
|
}
|
|
16079
|
+
function diagnosticText(value, dataDir) {
|
|
16080
|
+
const text = value.toString("utf8").replaceAll(dataDir, "<data-dir>").trim().replace(/\s+/gu, " ");
|
|
16081
|
+
return text === "" ? void 0 : text.slice(0, IDENTITY_DIAGNOSTIC_MAX_BYTES);
|
|
16082
|
+
}
|
|
16083
|
+
/** The wrapper `tls-prepare` prints when it discards the underlying native cause. */
|
|
16084
|
+
const HOST_TLS_PREPARATION_FAILURE = "Error: host TLS preparation failed";
|
|
16085
|
+
/**
|
|
16086
|
+
* Whether the wrapper is the only explanation stderr carries.
|
|
16087
|
+
*
|
|
16088
|
+
* Compare lines, never the whole buffer: the probe collapses whitespace for
|
|
16089
|
+
* reporting, and a preceding warning or a CRLF terminator must not hide the
|
|
16090
|
+
* fact that no cause chain was printed. A `Caused by:` section means the
|
|
16091
|
+
* native explanation already reached us, so the extra host run cannot add
|
|
16092
|
+
* anything the caller does not already have.
|
|
16093
|
+
*/
|
|
16094
|
+
function isBareHostTlsPreparationFailure(value, dataDir) {
|
|
16095
|
+
const lines = value.toString("utf8").replaceAll(dataDir, "<data-dir>").split(/\r?\n/gu).map((line) => line.trim()).filter((line) => line !== "");
|
|
16096
|
+
return lines.includes(HOST_TLS_PREPARATION_FAILURE) && !lines.some((line) => /^Caused by:/u.test(line));
|
|
16097
|
+
}
|
|
16098
|
+
/**
|
|
16099
|
+
* Ask the host entry point for the cause chain when `tls-prepare` reports only
|
|
16100
|
+
* its top-level wrapper. The command is local-only and bounded; it never
|
|
16101
|
+
* downloads a component or enables relay/discovery.
|
|
16102
|
+
*/
|
|
16103
|
+
async function hostIdentityDiagnostic(executable, dataDir, launch, onSpawn) {
|
|
16104
|
+
const args = [
|
|
16105
|
+
"--lang",
|
|
16106
|
+
"en",
|
|
16107
|
+
"host",
|
|
16108
|
+
"--data-dir",
|
|
16109
|
+
dataDir,
|
|
16110
|
+
"--local-only"
|
|
16111
|
+
];
|
|
16112
|
+
const child = launch === void 0 ? spawn(executable, args, {
|
|
16113
|
+
stdio: [
|
|
16114
|
+
"pipe",
|
|
16115
|
+
"pipe",
|
|
16116
|
+
"pipe"
|
|
16117
|
+
],
|
|
16118
|
+
windowsHide: true
|
|
16119
|
+
}) : launch(executable, args);
|
|
16120
|
+
onSpawn?.(child);
|
|
16121
|
+
let stderrOutput = Buffer.alloc(0);
|
|
16122
|
+
let settled = false;
|
|
16123
|
+
let deadline;
|
|
16124
|
+
return await new Promise((resolve) => {
|
|
16125
|
+
const finish = (value) => {
|
|
16126
|
+
if (settled) return;
|
|
16127
|
+
settled = true;
|
|
16128
|
+
if (deadline !== void 0) clearTimeout(deadline);
|
|
16129
|
+
resolve(value);
|
|
16130
|
+
};
|
|
16131
|
+
deadline = setTimeout(() => {
|
|
16132
|
+
terminateRemoteProcess(child).then(() => {
|
|
16133
|
+
finish(diagnosticText(stderrOutput, dataDir));
|
|
16134
|
+
}, () => {
|
|
16135
|
+
finish(diagnosticText(stderrOutput, dataDir));
|
|
16136
|
+
});
|
|
16137
|
+
}, 5e3);
|
|
16138
|
+
deadline.unref?.();
|
|
16139
|
+
child.stderr?.on("data", (chunk) => {
|
|
16140
|
+
const remaining = IDENTITY_DIAGNOSTIC_MAX_BYTES - stderrOutput.length;
|
|
16141
|
+
if (remaining > 0) stderrOutput = Buffer.concat([stderrOutput, chunk.subarray(0, remaining)]);
|
|
16142
|
+
});
|
|
16143
|
+
child.once("error", () => {
|
|
16144
|
+
finish(diagnosticText(stderrOutput, dataDir));
|
|
16145
|
+
});
|
|
16146
|
+
child.once("close", () => {
|
|
16147
|
+
finish(diagnosticText(stderrOutput, dataDir));
|
|
16148
|
+
});
|
|
16149
|
+
child.stdin?.end();
|
|
16150
|
+
});
|
|
16151
|
+
}
|
|
15964
16152
|
/**
|
|
15965
16153
|
* Prepare the sidecar's private identity/TLS state and resolve its endpoint.
|
|
15966
16154
|
*
|
|
@@ -16030,6 +16218,15 @@ async function defaultResolveIdentity(executable, dataDir, options = {}) {
|
|
|
16030
16218
|
if (settled) return;
|
|
16031
16219
|
settled = true;
|
|
16032
16220
|
const probeDiagnostic = diagnostic();
|
|
16221
|
+
if (code !== 0 && probeDiagnostic !== void 0 && isBareHostTlsPreparationFailure(stderrOutput, dataDir)) {
|
|
16222
|
+
hostIdentityDiagnostic(executable, dataDir, options.launch, options.onSpawn).then((detail) => {
|
|
16223
|
+
const resolvedDiagnostic = detail ?? probeDiagnostic;
|
|
16224
|
+
reject(new IrohIdentityProbeError(/private (?:Windows )?data directory is not secure|private path ACL grants/iu.test(resolvedDiagnostic) ? "iroh_data_directory_insecure" : "iroh_identity_invalid", resolvedDiagnostic));
|
|
16225
|
+
}, () => {
|
|
16226
|
+
reject(new IrohIdentityProbeError("iroh_identity_invalid", probeDiagnostic));
|
|
16227
|
+
});
|
|
16228
|
+
return;
|
|
16229
|
+
}
|
|
16033
16230
|
if (code !== 0 && probeDiagnostic !== void 0 && /private (?:Windows )?data directory is not secure|private path ACL grants/iu.test(probeDiagnostic)) {
|
|
16034
16231
|
reject(new IrohIdentityProbeError("iroh_data_directory_insecure", probeDiagnostic));
|
|
16035
16232
|
return;
|
|
@@ -16939,23 +17136,36 @@ function remoteSuffix(origin) {
|
|
|
16939
17136
|
return "地址格式无效";
|
|
16940
17137
|
}
|
|
16941
17138
|
}
|
|
17139
|
+
/**
|
|
17140
|
+
* Read-only PowerShell that reports whether both managed LAN rules are usable.
|
|
17141
|
+
*
|
|
17142
|
+
* The verdict mirrors `windowsFirewallSetupScript`'s post-condition: enabled,
|
|
17143
|
+
* inbound, allow, and `Profile` exactly `Any`. A Domain/Private-scoped rule is
|
|
17144
|
+
* active only on those networks, so reporting it as ready would tell a user on
|
|
17145
|
+
* a Public network that nothing needs fixing. The script only reads: it never
|
|
17146
|
+
* enables, creates or deletes a rule, and the caller keeps its 3s budget.
|
|
17147
|
+
* @param port - managed LAN listener port the rules must cover.
|
|
17148
|
+
*/
|
|
17149
|
+
function windowsFirewallProbeScript(port) {
|
|
17150
|
+
return [
|
|
17151
|
+
"$specs = @(@{ Name = 'DSH Mobile HTTPS'; Protocol = 'TCP' }, @{ Name = 'DSH Mobile Discovery'; Protocol = 'UDP' })",
|
|
17152
|
+
"$ready = $true",
|
|
17153
|
+
"$specs | ForEach-Object {",
|
|
17154
|
+
" $spec = $_",
|
|
17155
|
+
" $rule = Get-NetFirewallRule -DisplayName $spec.Name -ErrorAction SilentlyContinue | Where-Object { $_.Enabled -eq 'True' -and $_.Direction -eq 'Inbound' -and $_.Action -eq 'Allow' -and $_.Profile -eq 'Any' } | Select-Object -First 1",
|
|
17156
|
+
" if ($null -eq $rule) { $ready = $false; return }",
|
|
17157
|
+
" $filters = @($rule | Get-NetFirewallPortFilter -ErrorAction SilentlyContinue)",
|
|
17158
|
+
` $matching = @($filters | Where-Object { $_.Protocol -eq $spec.Protocol -and ($_.LocalPort -eq 'Any' -or $_.LocalPort -eq '${String(port)}') })`,
|
|
17159
|
+
" if ($matching.Count -eq 0) { $ready = $false }",
|
|
17160
|
+
"}",
|
|
17161
|
+
"if ($ready) { 'ready' } else { 'missing' }"
|
|
17162
|
+
].join("; ");
|
|
17163
|
+
}
|
|
16942
17164
|
function defaultFirewallProbe(platform = process.platform) {
|
|
16943
17165
|
return async (port) => {
|
|
16944
17166
|
if (platform !== "win32") return { state: "not-applicable" };
|
|
16945
17167
|
if (port === void 0) return { state: "unknown" };
|
|
16946
|
-
const script =
|
|
16947
|
-
"$specs = @(@{ Name = 'DSH Mobile HTTPS'; Protocol = 'TCP' }, @{ Name = 'DSH Mobile Discovery'; Protocol = 'UDP' })",
|
|
16948
|
-
"$ready = $true",
|
|
16949
|
-
"$specs | ForEach-Object {",
|
|
16950
|
-
" $spec = $_",
|
|
16951
|
-
" $rule = Get-NetFirewallRule -DisplayName $spec.Name -ErrorAction SilentlyContinue | Where-Object { $_.Enabled -eq 'True' -and $_.Direction -eq 'Inbound' -and $_.Action -eq 'Allow' } | Select-Object -First 1",
|
|
16952
|
-
" if ($null -eq $rule) { $ready = $false; return }",
|
|
16953
|
-
" $filters = @($rule | Get-NetFirewallPortFilter -ErrorAction SilentlyContinue)",
|
|
16954
|
-
` $matching = @($filters | Where-Object { $_.Protocol -eq $spec.Protocol -and ($_.LocalPort -eq 'Any' -or $_.LocalPort -eq '${String(port)}') })`,
|
|
16955
|
-
" if ($matching.Count -eq 0) { $ready = $false }",
|
|
16956
|
-
"}",
|
|
16957
|
-
"if ($ready) { 'ready' } else { 'missing' }"
|
|
16958
|
-
].join("; ");
|
|
17168
|
+
const script = windowsFirewallProbeScript(port);
|
|
16959
17169
|
try {
|
|
16960
17170
|
return { state: (await execFileText("powershell.exe", [
|
|
16961
17171
|
"-NoProfile",
|
|
@@ -22109,7 +22319,8 @@ function validSource(value) {
|
|
|
22109
22319
|
"lifetime",
|
|
22110
22320
|
"turn",
|
|
22111
22321
|
"callId",
|
|
22112
|
-
"goal"
|
|
22322
|
+
"goal",
|
|
22323
|
+
"custom"
|
|
22113
22324
|
])) return false;
|
|
22114
22325
|
return [
|
|
22115
22326
|
value.sourceId,
|
|
@@ -22126,7 +22337,7 @@ function validSource(value) {
|
|
|
22126
22337
|
"live",
|
|
22127
22338
|
"projected",
|
|
22128
22339
|
"committed"
|
|
22129
|
-
].includes(String(value.lifetime)) && (value.turn === void 0 || Number.isSafeInteger(value.turn)) && (value.callId === void 0 || typeof value.callId === "string") && (value.goal === void 0 || object(value.goal) && only(value.goal, ["id", "revision"]) && typeof value.goal.id === "string" && Number.isSafeInteger(value.goal.revision));
|
|
22340
|
+
].includes(String(value.lifetime)) && (value.turn === void 0 || Number.isSafeInteger(value.turn)) && (value.callId === void 0 || typeof value.callId === "string") && (value.goal === void 0 || object(value.goal) && only(value.goal, ["id", "revision"]) && typeof value.goal.id === "string" && Number.isSafeInteger(value.goal.revision)) && (value.custom === void 0 || object(value.custom) && only(value.custom, ["title", "body"]) && typeof value.custom.title === "string" && value.custom.title.length > 0 && value.custom.title.length <= 80 && !/[\u0000-\u001f\u007f]/u.test(value.custom.title) && typeof value.custom.body === "string" && value.custom.body.length > 0 && value.custom.body.length <= 200 && !/[\u0000-\u001f\u007f]/u.test(value.custom.body));
|
|
22130
22341
|
}
|
|
22131
22342
|
function scopedCounts(rows, scope, maximum = 1024) {
|
|
22132
22343
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -22742,10 +22953,11 @@ function validateNavigate(navigate, category) {
|
|
|
22742
22953
|
if (typeof navigate !== "string" || !/^\/\?mobile-push=[A-Za-z0-9_-]{1,256}$/u.test(navigate)) throw new TypeError("push_navigation_invalid");
|
|
22743
22954
|
}
|
|
22744
22955
|
/** Build Apple's declarative Web Push schema with generic, locale-owned text. */
|
|
22745
|
-
function buildDeclarativePayload(category, locale, navigate, tag) {
|
|
22956
|
+
function buildDeclarativePayload(category, locale, navigate, tag, custom) {
|
|
22746
22957
|
validateNavigate(navigate, category);
|
|
22747
22958
|
if (!(locale in messages) || !(category in messages[locale]) || typeof tag !== "string" || !/^[A-Za-z0-9._:-]{1,128}$/u.test(tag)) throw new TypeError("push_payload_invalid");
|
|
22748
|
-
|
|
22959
|
+
if (custom !== void 0 && (typeof custom.title !== "string" || custom.title.length === 0 || custom.title.length > 80 || typeof custom.body !== "string" || custom.body.length === 0 || custom.body.length > 200)) throw new TypeError("push_payload_invalid");
|
|
22960
|
+
const [title, body] = custom === void 0 ? messages[locale][category] : [custom.title, custom.body];
|
|
22749
22961
|
const payload = JSON.stringify({
|
|
22750
22962
|
web_push: 8030,
|
|
22751
22963
|
notification: {
|
|
@@ -23085,6 +23297,12 @@ function sameKey(a, b) {
|
|
|
23085
23297
|
function isPreferenceEnabled(preferences, category) {
|
|
23086
23298
|
return preferences[category] === true;
|
|
23087
23299
|
}
|
|
23300
|
+
function notificationText(value, maximum, label) {
|
|
23301
|
+
if (typeof value !== "string") throw new TypeError(`push_${label}_invalid`);
|
|
23302
|
+
const text = value.trim().replace(/[\u0000-\u001f\u007f]+/gu, " ");
|
|
23303
|
+
if (text.length === 0 || text.length > maximum) throw new TypeError(`push_${label}_invalid`);
|
|
23304
|
+
return text;
|
|
23305
|
+
}
|
|
23088
23306
|
function pendingHas(snapshot, intent) {
|
|
23089
23307
|
return snapshot.pending.some((item) => item.id === intent.id && sameKey(item.key, intent.key));
|
|
23090
23308
|
}
|
|
@@ -23198,6 +23416,51 @@ var PushDelivery = class {
|
|
|
23198
23416
|
this.#kick();
|
|
23199
23417
|
});
|
|
23200
23418
|
}
|
|
23419
|
+
/**
|
|
23420
|
+
* Queue trusted Host-plugin text for every enabled web-push recipient that
|
|
23421
|
+
* opted into the selected notification category. The source keeps its own
|
|
23422
|
+
* short expiry; a restart may still retry it only inside that window.
|
|
23423
|
+
*/
|
|
23424
|
+
async notifyCustom(input) {
|
|
23425
|
+
if (!this.#started || this.#closed || !this.#admitting) throw new Error("push_unavailable");
|
|
23426
|
+
const sessionId = typeof input.sessionId === "string" ? input.sessionId.trim() : "";
|
|
23427
|
+
if (sessionId === "" || sessionId.length > 4096) throw new TypeError("push_session_id_invalid");
|
|
23428
|
+
const title = notificationText(input.title, 80, "title");
|
|
23429
|
+
const body = notificationText(input.body, 200, "body");
|
|
23430
|
+
const category = input.category ?? "response";
|
|
23431
|
+
if (![
|
|
23432
|
+
"question",
|
|
23433
|
+
"plan",
|
|
23434
|
+
"approval",
|
|
23435
|
+
"response",
|
|
23436
|
+
"goal",
|
|
23437
|
+
"failure"
|
|
23438
|
+
].includes(category)) throw new TypeError("push_category_invalid");
|
|
23439
|
+
const now = this.#now();
|
|
23440
|
+
const maximumExpiry = now + OUTCOME_TTL_MS;
|
|
23441
|
+
if (input.expiresAt !== void 0 && (!Number.isSafeInteger(input.expiresAt) || input.expiresAt <= now)) throw new TypeError("push_expiry_invalid");
|
|
23442
|
+
const expiresAt = Math.min(input.expiresAt ?? maximumExpiry, maximumExpiry);
|
|
23443
|
+
if (!await this.#host.sessionExists(sessionId)) throw new Error("push_session_unavailable");
|
|
23444
|
+
const source = {
|
|
23445
|
+
sourceId: `custom:${randomUUID()}`,
|
|
23446
|
+
sessionId,
|
|
23447
|
+
targetSessionId: sessionId,
|
|
23448
|
+
category,
|
|
23449
|
+
createdAt: now,
|
|
23450
|
+
expiresAt,
|
|
23451
|
+
lifetime: "committed",
|
|
23452
|
+
custom: {
|
|
23453
|
+
title,
|
|
23454
|
+
body
|
|
23455
|
+
}
|
|
23456
|
+
};
|
|
23457
|
+
const queued = await this.#admit(source);
|
|
23458
|
+
this.#kick();
|
|
23459
|
+
return {
|
|
23460
|
+
queued,
|
|
23461
|
+
expiresAt
|
|
23462
|
+
};
|
|
23463
|
+
}
|
|
23201
23464
|
async resolve(owner, reference) {
|
|
23202
23465
|
if (this.#closed || !reference) return void 0;
|
|
23203
23466
|
let snapshot;
|
|
@@ -23237,14 +23500,15 @@ var PushDelivery = class {
|
|
|
23237
23500
|
this.#origins.clear();
|
|
23238
23501
|
}
|
|
23239
23502
|
async #admit(source) {
|
|
23240
|
-
if (!this.#admitting || source.expiresAt <= this.#now()) return;
|
|
23503
|
+
if (!this.#admitting || source.expiresAt <= this.#now()) return 0;
|
|
23241
23504
|
let eligible = false;
|
|
23242
23505
|
try {
|
|
23243
|
-
eligible = this.#host.available && await this.#host.eligible(source);
|
|
23506
|
+
eligible = source.custom === void 0 ? this.#host.available && await this.#host.eligible(source) : this.#host.available && await this.#host.sessionExists(source.sessionId);
|
|
23244
23507
|
} catch {
|
|
23245
23508
|
eligible = false;
|
|
23246
23509
|
}
|
|
23247
|
-
if (!eligible || source.expiresAt <= this.#now()) return;
|
|
23510
|
+
if (!eligible || source.expiresAt <= this.#now()) return 0;
|
|
23511
|
+
let queued = 0;
|
|
23248
23512
|
for (const origin of this.#origins.values()) {
|
|
23249
23513
|
if (!origin.active || this.#closed) continue;
|
|
23250
23514
|
const devices = await this.#readAuthorized(origin);
|
|
@@ -23253,7 +23517,7 @@ var PushDelivery = class {
|
|
|
23253
23517
|
try {
|
|
23254
23518
|
snapshot = this.#registry.snapshot();
|
|
23255
23519
|
} catch {
|
|
23256
|
-
return;
|
|
23520
|
+
return queued;
|
|
23257
23521
|
}
|
|
23258
23522
|
const registrations = snapshot.registrations.filter((reg) => reg.scopeId === origin.scopeId && reg.origin === origin.origin && devices.has(reg.deviceId) && reg.enabled && reg.health === "ready" && isPreferenceEnabled(reg.preferences, source.category) && snapshot.keys?.fingerprint === reg.keyFingerprint);
|
|
23259
23523
|
if (registrations.length === 0) continue;
|
|
@@ -23282,6 +23546,7 @@ var PushDelivery = class {
|
|
|
23282
23546
|
attempts: 0,
|
|
23283
23547
|
nextAttemptAt: this.#now()
|
|
23284
23548
|
});
|
|
23549
|
+
queued += 1;
|
|
23285
23550
|
}
|
|
23286
23551
|
return {
|
|
23287
23552
|
...clean,
|
|
@@ -23290,6 +23555,7 @@ var PushDelivery = class {
|
|
|
23290
23555
|
});
|
|
23291
23556
|
}
|
|
23292
23557
|
this.#kick();
|
|
23558
|
+
return queued;
|
|
23293
23559
|
}
|
|
23294
23560
|
async #reconcileKnownScopes() {
|
|
23295
23561
|
let snapshot;
|
|
@@ -23474,7 +23740,7 @@ var PushDelivery = class {
|
|
|
23474
23740
|
await this.#removeIntent(intent);
|
|
23475
23741
|
return;
|
|
23476
23742
|
}
|
|
23477
|
-
const payload = buildDeclarativePayload(intent.source.category, registration.locale, `/?mobile-push=${reference}`, intent.source.sourceId.replace(/[^A-Za-z0-9._:-]/gu, "_").slice(0, 128) || "push");
|
|
23743
|
+
const payload = buildDeclarativePayload(intent.source.category, registration.locale, `/?mobile-push=${reference}`, intent.source.sourceId.replace(/[^A-Za-z0-9._:-]/gu, "_").slice(0, 128) || "push", intent.source.custom);
|
|
23478
23744
|
let result;
|
|
23479
23745
|
try {
|
|
23480
23746
|
result = await this.#sender.send({
|
|
@@ -23584,6 +23850,11 @@ var PushDelivery = class {
|
|
|
23584
23850
|
/** Maps the Host tri-state for durable-work decisions; boolean eligible() would collapse transient uncertainty into denial. */
|
|
23585
23851
|
async #sourceGuard(source) {
|
|
23586
23852
|
if (!this.#host.available) return "unverifiable";
|
|
23853
|
+
if (source.custom !== void 0) try {
|
|
23854
|
+
return await this.#host.sessionExists(source.sessionId) ? "allowed" : "denied";
|
|
23855
|
+
} catch {
|
|
23856
|
+
return "unverifiable";
|
|
23857
|
+
}
|
|
23587
23858
|
let result;
|
|
23588
23859
|
try {
|
|
23589
23860
|
result = await this.#host.reconcile(source);
|
|
@@ -23937,6 +24208,10 @@ var PushGatewayCoordinator = class {
|
|
|
23937
24208
|
installationId
|
|
23938
24209
|
});
|
|
23939
24210
|
}
|
|
24211
|
+
async notifyCustom(input) {
|
|
24212
|
+
if (!this.host.available) throw new Error("push_unavailable");
|
|
24213
|
+
return await this.delivery.notifyCustom(input);
|
|
24214
|
+
}
|
|
23940
24215
|
async resolve(owner, reference) {
|
|
23941
24216
|
if (!this.host.available || !await this.authorize(owner, true)) return void 0;
|
|
23942
24217
|
return this.delivery.resolve(owner, reference);
|
|
@@ -24059,16 +24334,71 @@ const MAX_MANAGED_PORT = 65535;
|
|
|
24059
24334
|
function assertManagedPort(port, name) {
|
|
24060
24335
|
if (!Number.isSafeInteger(port) || port < MIN_MANAGED_PORT || port > MAX_MANAGED_PORT) throw new Error(`${name} must be from ${String(MIN_MANAGED_PORT)} through ${String(MAX_MANAGED_PORT)}`);
|
|
24061
24336
|
}
|
|
24062
|
-
|
|
24337
|
+
/** Longest failure detail carried in the thrown message. */
|
|
24338
|
+
const MAX_FAILURE_DETAIL_CHARS = 512;
|
|
24339
|
+
/**
|
|
24340
|
+
* Strip the elevated invocation and filesystem locations from PowerShell text.
|
|
24341
|
+
*
|
|
24342
|
+
* The launcher's stderr quotes the command it ran, including the base64
|
|
24343
|
+
* `-EncodedCommand` payload, and the elevated script quotes its own scratch
|
|
24344
|
+
* path. Neither helps an operator, and both can push the one useful line past
|
|
24345
|
+
* the length bound, so they are replaced before the detail is bounded.
|
|
24346
|
+
*/
|
|
24347
|
+
function redactPowerShellDetail(value) {
|
|
24348
|
+
return value.replace(/EncodedCommand\s+\S+/giu, "EncodedCommand <redacted>").replace(/\b[A-Za-z0-9+/]{64,}={0,2}\b/gu, "<redacted>").replace(/(?<![A-Za-z])[A-Za-z]:[\\/][^\s'"]*/gu, "<path>");
|
|
24349
|
+
}
|
|
24350
|
+
/** Bounded, redacted detail for a failed elevated Windows operation. */
|
|
24351
|
+
function powerShellFailureDetail(error, innerError = "") {
|
|
24063
24352
|
if (!(error instanceof Error)) return "unknown failure";
|
|
24064
|
-
const code = "code" in error && typeof error.code === "string" ? ` (${error.code})` : "";
|
|
24065
|
-
const
|
|
24066
|
-
return `${code}${
|
|
24353
|
+
const code = "code" in error && (typeof error.code === "string" || typeof error.code === "number") ? ` (${String(error.code)})` : "";
|
|
24354
|
+
const detail = redactPowerShellDetail(innerError.trim() === "" && "stderr" in error && typeof error.stderr === "string" ? error.stderr : innerError).trim().replace(/\s+/gu, " ").slice(0, MAX_FAILURE_DETAIL_CHARS);
|
|
24355
|
+
return `${code}${detail === "" ? "" : `: ${detail}`}`;
|
|
24356
|
+
}
|
|
24357
|
+
/** Default sink for a scratch directory that could not be removed. */
|
|
24358
|
+
function warnFirewallCleanupFailure(detail) {
|
|
24359
|
+
process.emitWarning(`Windows firewall temporary cleanup failed (${detail})`, { code: "DSH_MOBILE_FIREWALL_CLEANUP_FAILED" });
|
|
24360
|
+
}
|
|
24361
|
+
/**
|
|
24362
|
+
* Remove the elevated helper's scratch directory without touching the run's outcome.
|
|
24363
|
+
*
|
|
24364
|
+
* The directory is created before elevation and removed in a `finally`, so a
|
|
24365
|
+
* cleanup failure must not replace the firewall error that explains the
|
|
24366
|
+
* failure, and must not fail a run that already succeeded. It stays observable
|
|
24367
|
+
* instead: the removal error's code is reported to the warning sink, whose own
|
|
24368
|
+
* failure is ignored for the same reason.
|
|
24369
|
+
* @param directory - scratch path created for this run.
|
|
24370
|
+
* @param options - injectable removal and warning sink for tests.
|
|
24371
|
+
*/
|
|
24372
|
+
async function discardFirewallScratch(directory, options = {}) {
|
|
24373
|
+
const remove = options.remove ?? ((path) => rm(path, {
|
|
24374
|
+
recursive: true,
|
|
24375
|
+
force: true
|
|
24376
|
+
}));
|
|
24377
|
+
try {
|
|
24378
|
+
await remove(directory);
|
|
24379
|
+
} catch (error) {
|
|
24380
|
+
const code = error !== null && typeof error === "object" && "code" in error && typeof error.code === "string" ? error.code : "unknown";
|
|
24381
|
+
const warn = options.warn ?? warnFirewallCleanupFailure;
|
|
24382
|
+
try {
|
|
24383
|
+
warn(code);
|
|
24384
|
+
} catch {}
|
|
24385
|
+
}
|
|
24067
24386
|
}
|
|
24068
24387
|
async function runElevatedPowerShell(script) {
|
|
24388
|
+
const temporary = await mkdtemp(join(tmpdir(), "dsh-mobile-firewall-"));
|
|
24389
|
+
const errorFile = join(temporary, "error.log");
|
|
24390
|
+
const wrapped = [
|
|
24391
|
+
`$__dshMobileErrorFile = '${errorFile.replaceAll("'", "''")}'`,
|
|
24392
|
+
"try {",
|
|
24393
|
+
script,
|
|
24394
|
+
"} catch {",
|
|
24395
|
+
" try { [IO.File]::WriteAllText($__dshMobileErrorFile, ($_ | Out-String)) } catch {}",
|
|
24396
|
+
" throw",
|
|
24397
|
+
"}"
|
|
24398
|
+
].join("\n");
|
|
24069
24399
|
const launch = [
|
|
24070
24400
|
"$ErrorActionPreference = 'Stop'; $process = Start-Process -FilePath 'powershell.exe' -Verb RunAs -WindowStyle Hidden -Wait -PassThru",
|
|
24071
|
-
` -ArgumentList @('-NoProfile','-NonInteractive','-EncodedCommand','${Buffer.from(
|
|
24401
|
+
` -ArgumentList @('-NoProfile','-NonInteractive','-EncodedCommand','${Buffer.from(wrapped, "utf16le").toString("base64")}')`,
|
|
24072
24402
|
"; exit $process.ExitCode"
|
|
24073
24403
|
].join(" ");
|
|
24074
24404
|
try {
|
|
@@ -24079,7 +24409,13 @@ async function runElevatedPowerShell(script) {
|
|
|
24079
24409
|
launch
|
|
24080
24410
|
], { windowsHide: true });
|
|
24081
24411
|
} catch (error) {
|
|
24082
|
-
|
|
24412
|
+
let innerError = "";
|
|
24413
|
+
try {
|
|
24414
|
+
innerError = (await readFile(errorFile, "utf8")).replace(/^\uFEFF/u, "");
|
|
24415
|
+
} catch {}
|
|
24416
|
+
throw new Error(`Windows firewall operation failed${powerShellFailureDetail(error, innerError)}`, { cause: error });
|
|
24417
|
+
} finally {
|
|
24418
|
+
await discardFirewallScratch(temporary);
|
|
24083
24419
|
}
|
|
24084
24420
|
}
|
|
24085
24421
|
function firewallRuleScript(name, protocol, port) {
|
|
@@ -24094,7 +24430,7 @@ function firewallRuleScript(name, protocol, port) {
|
|
|
24094
24430
|
" $rule | Get-NetFirewallAddressFilter | Set-NetFirewallAddressFilter -RemoteAddress LocalSubnet",
|
|
24095
24431
|
" }",
|
|
24096
24432
|
"}",
|
|
24097
|
-
`$verified = @(Get-NetFirewallRule -DisplayName '${name}' -Enabled True -Direction Inbound -Action Allow -Profile Any
|
|
24433
|
+
`$verified = @(Get-NetFirewallRule -DisplayName '${name}' -ErrorAction Stop | Where-Object { $_.Enabled -eq 'True' -and $_.Direction -eq 'Inbound' -and $_.Action -eq 'Allow' -and $_.Profile -eq 'Any' })`,
|
|
24098
24434
|
`$matchingPort = @($verified | Get-NetFirewallPortFilter | Where-Object { $_.Protocol -eq '${protocol}' -and $_.LocalPort -contains '${String(port)}' })`,
|
|
24099
24435
|
`$matchingAddress = @($verified | Get-NetFirewallAddressFilter | Where-Object { $_.RemoteAddress -contains 'LocalSubnet' })`,
|
|
24100
24436
|
`if ($verified.Count -eq 0 -or $matchingPort.Count -eq 0 -or $matchingAddress.Count -eq 0) { throw "DSH Mobile firewall rule '${name}' is not active with the expected scope" }`
|
|
@@ -24590,6 +24926,7 @@ async function apply(ctx, config) {
|
|
|
24590
24926
|
if (service === void 0) throw new Error("push_unavailable");
|
|
24591
24927
|
return service;
|
|
24592
24928
|
};
|
|
24929
|
+
new MobilePushService(ctx, async (input) => (await requiredPushGatewayService()).notifyCustom(input));
|
|
24593
24930
|
const queueDeviceInvalidations = (scopeId, deviceIds) => {
|
|
24594
24931
|
let queued = pendingDeviceInvalidations.get(scopeId);
|
|
24595
24932
|
if (queued === void 0) pendingDeviceInvalidations.set(scopeId, queued = /* @__PURE__ */ new Set());
|
|
@@ -24664,6 +25001,11 @@ async function apply(ctx, config) {
|
|
|
24664
25001
|
async test(owner, installationId) {
|
|
24665
25002
|
await (await requiredPushGatewayService()).test(owner, installationId);
|
|
24666
25003
|
},
|
|
25004
|
+
async notifyCustom(input) {
|
|
25005
|
+
const service = await requiredPushGatewayService();
|
|
25006
|
+
if (service.notifyCustom === void 0) throw new Error("push_unavailable");
|
|
25007
|
+
return await service.notifyCustom(input);
|
|
25008
|
+
},
|
|
24667
25009
|
async resolve(owner, reference) {
|
|
24668
25010
|
return (await requiredPushGatewayService()).resolve(owner, reference);
|
|
24669
25011
|
}
|
|
@@ -25999,6 +26341,6 @@ async function apply(ctx, config) {
|
|
|
25999
26341
|
};
|
|
26000
26342
|
}, "dsh-mobile: independent LAN and selectable remote providers with /mobile command");
|
|
26001
26343
|
}
|
|
26002
|
-
export { AUTH_PREFIX, AccessController, AccessError, BlockedUpgradePathLog, BoundedRateLimiter, CERT_EXPIRING_DAYS, CLOUDFLARED_COMPONENT_RELEASE, CLOUDFLARED_COMPONENT_RELEASES, CPOLAR_COMPONENT_RELEASE, CPOLAR_COMPONENT_RELEASES, CSRF_COOKIE, CSRF_HEADER, ClientModuleConflictError, ClientModulePreferenceStore, CloudflaredComponentManager, CloudflaredController, CloudflaredTunnelStore, Config, CpolarComponentManager, DEFAULT_IROH_LOCAL_PORT, DEFAULT_ORIGIN_LISTEN_PORT, FRP_VHOST_HTTP_PORT as DEFAULT_VHOST_HTTP_PORT, FRP_VHOST_HTTP_PORT, DEVICE_COOKIE, EXTENSION_LIMITS, FRP_ATTACH_DISCOVERY_PATH, FRP_ATTACH_LOCAL_DECLARATION, FRP_ATTACH_SELF_SIGNED_DECLARATION, FRP_ATTACH_VPS_DECLARATION, FRP_CADDY_IMPORT_LINE, FRP_CADDY_SNIPPET_MARKER, FRP_CADDY_SNIPPET_PATH, FRP_COMPONENT_RELEASES, FRP_DEFAULT_PROXY_NAME, FRP_DEFAULT_PUBLIC_PORT, FRP_RESERVED_PORTS, FrpComponentManager, FrpConfigStore, FrpController, IROH_COMPONENT_RELEASES, IROH_LEAF_RENEW_BEFORE_DAYS, IROH_LEAF_VALIDITY_DAYS, IROH_VERSION, IrohComponentManager, IrohController, JsonDeviceStore, JsonMobileAccessControlStore, JsonRemoteProviderStore, LOCAL_ADMIN_PREFIX, MAX_BLOCKED_UPGRADE_PATHS, MAX_EXTRA_WEBSOCKET_PATHS, MAX_PAIRING_DESCRIPTOR_BYTES, MAX_PAIRING_LIFETIME_MS, MAX_WEBSOCKET_PATH_LENGTH, MemoryDeviceStore, MobileAccessGateway, MobileAccessGatewayController, MobileAccessService, MobileExtensionError, OriginConfigStore, OriginController, PAIRING_DESCRIPTOR_LOCAL_PORT, PAIRING_DESCRIPTOR_TYPE, PAIRING_DESCRIPTOR_VERSION, REMOTE_PROVIDERS, RequestTrustPolicy, SESSION_COOKIE, TASK_EVENT_DEBOUNCE_MS, TaskEventHub, WS_PATHS, WebSocketPathStore, addressAllowed, apply, assertExtensionId, configuredRemoteProvider, createCaddySite, createFrpAttachPlan, createFrpAttachTemplate, createFrpAttachTemplateParts, createFrpServerTemplate, createFrpcToml, createMobileAccessService, createRestrictedFrpServerTemplate, decodePairingDescriptor, encodePairingDescriptor, ensureFrpIngressCertificate, ensureIrohTls, evaluateCertificateLifetime, frpAttachVpsParts, frpIngressPaths, frpIngressSelfCheck, frpProxyName, inject, irohGatewayConfig, irohHostname, irohOrigin, irohTlsPaths, isCloudflaredRegistration, isFrpSelfSignedIngress, isGloballyRoutableIpv4, isLoopbackAddress, issueServerCertificate, mergeSavedCloudflaredTunnelSettings, mergeSavedFrpSettings, mergeSavedFrpTarget, name, normalizeWebSocketPaths, originGatewayConfig, parseAuthority, parseCidr, parseCloudflaredOrigin, parseCloudflaredTunnelSettings, parseControlFile, parseDeviceSnapshot, parseExtensionManifest, parseFrpSettings, parseGatewayConfig, parseMobileAccessControlState, parseOriginSettings, parseRemoteProviderState, probeOriginCertificate, readCertificateRenewal, resolveAuthority, resolveFrpEntryTls, resolveFrpMode, resolveFrpPublicPort, resolveFrpVhostHttpPort, resolveHostExecution, rewriteMobileIndex, validateAttachSettings, validateCloudflaredTunnelHostname, validateCloudflaredTunnelPort, validateCloudflaredTunnelToken, validateFrpEntryTls, validateFrpMode, validateFrpProxyName, validateFrpPublicOrigin, validateFrpPublicPort, validateFrpServerAddress, validateFrpServerPort, validateFrpToken, validateFrpVhostHttpPort, validateIrohOrigin, validateOriginAllowedCidrs, validateOriginListenHost, validateOriginListenPort, validateOriginPublicOrigin, validatePairingDescriptor, validateWebSocketPath, watchTaskCompletions };
|
|
26344
|
+
export { AUTH_PREFIX, AccessController, AccessError, BlockedUpgradePathLog, BoundedRateLimiter, CERT_EXPIRING_DAYS, CLOUDFLARED_COMPONENT_RELEASE, CLOUDFLARED_COMPONENT_RELEASES, CPOLAR_COMPONENT_RELEASE, CPOLAR_COMPONENT_RELEASES, CSRF_COOKIE, CSRF_HEADER, ClientModuleConflictError, ClientModulePreferenceStore, CloudflaredComponentManager, CloudflaredController, CloudflaredTunnelStore, Config, CpolarComponentManager, DEFAULT_IROH_LOCAL_PORT, DEFAULT_ORIGIN_LISTEN_PORT, FRP_VHOST_HTTP_PORT as DEFAULT_VHOST_HTTP_PORT, FRP_VHOST_HTTP_PORT, DEVICE_COOKIE, EXTENSION_LIMITS, FRP_ATTACH_DISCOVERY_PATH, FRP_ATTACH_LOCAL_DECLARATION, FRP_ATTACH_SELF_SIGNED_DECLARATION, FRP_ATTACH_VPS_DECLARATION, FRP_CADDY_IMPORT_LINE, FRP_CADDY_SNIPPET_MARKER, FRP_CADDY_SNIPPET_PATH, FRP_COMPONENT_RELEASES, FRP_DEFAULT_PROXY_NAME, FRP_DEFAULT_PUBLIC_PORT, FRP_RESERVED_PORTS, FrpComponentManager, FrpConfigStore, FrpController, IROH_COMPONENT_RELEASES, IROH_LEAF_RENEW_BEFORE_DAYS, IROH_LEAF_VALIDITY_DAYS, IROH_VERSION, IrohComponentManager, IrohController, JsonDeviceStore, JsonMobileAccessControlStore, JsonRemoteProviderStore, LOCAL_ADMIN_PREFIX, MAX_BLOCKED_UPGRADE_PATHS, MAX_EXTRA_WEBSOCKET_PATHS, MAX_PAIRING_DESCRIPTOR_BYTES, MAX_PAIRING_LIFETIME_MS, MAX_WEBSOCKET_PATH_LENGTH, MemoryDeviceStore, MobileAccessGateway, MobileAccessGatewayController, MobileAccessService, MobileExtensionError, MobilePushService, OriginConfigStore, OriginController, PAIRING_DESCRIPTOR_LOCAL_PORT, PAIRING_DESCRIPTOR_TYPE, PAIRING_DESCRIPTOR_VERSION, REMOTE_PROVIDERS, RequestTrustPolicy, SESSION_COOKIE, TASK_EVENT_DEBOUNCE_MS, TaskEventHub, WS_PATHS, WebSocketPathStore, addressAllowed, apply, assertExtensionId, configuredRemoteProvider, createCaddySite, createFrpAttachPlan, createFrpAttachTemplate, createFrpAttachTemplateParts, createFrpServerTemplate, createFrpcToml, createMobileAccessService, createRestrictedFrpServerTemplate, decodePairingDescriptor, encodePairingDescriptor, ensureFrpIngressCertificate, ensureIrohTls, evaluateCertificateLifetime, frpAttachVpsParts, frpIngressPaths, frpIngressSelfCheck, frpProxyName, inject, irohGatewayConfig, irohHostname, irohOrigin, irohTlsPaths, isCloudflaredRegistration, isFrpSelfSignedIngress, isGloballyRoutableIpv4, isLoopbackAddress, issueServerCertificate, mergeSavedCloudflaredTunnelSettings, mergeSavedFrpSettings, mergeSavedFrpTarget, name, normalizeWebSocketPaths, originGatewayConfig, parseAuthority, parseCidr, parseCloudflaredOrigin, parseCloudflaredTunnelSettings, parseControlFile, parseDeviceSnapshot, parseExtensionManifest, parseFrpSettings, parseGatewayConfig, parseMobileAccessControlState, parseOriginSettings, parseRemoteProviderState, probeOriginCertificate, readCertificateRenewal, resolveAuthority, resolveFrpEntryTls, resolveFrpMode, resolveFrpPublicPort, resolveFrpVhostHttpPort, resolveHostExecution, rewriteMobileIndex, validateAttachSettings, validateCloudflaredTunnelHostname, validateCloudflaredTunnelPort, validateCloudflaredTunnelToken, validateFrpEntryTls, validateFrpMode, validateFrpProxyName, validateFrpPublicOrigin, validateFrpPublicPort, validateFrpServerAddress, validateFrpServerPort, validateFrpToken, validateFrpVhostHttpPort, validateIrohOrigin, validateOriginAllowedCidrs, validateOriginListenHost, validateOriginListenPort, validateOriginPublicOrigin, validatePairingDescriptor, validateWebSocketPath, watchTaskCompletions };
|
|
26003
26345
|
|
|
26004
26346
|
//# sourceMappingURL=index.mjs.map
|