camstack 1.2.105 → 1.2.107
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js
CHANGED
|
@@ -38,7 +38,7 @@ async function runServe(args) {
|
|
|
38
38
|
...typeof values.data === "string" ? { data: values.data } : {}
|
|
39
39
|
};
|
|
40
40
|
Object.assign(process.env, buildServeEnv(opts));
|
|
41
|
-
await import("./launcher-
|
|
41
|
+
await import("./launcher-HX7B54EQ.js");
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// src/commands/agent.ts
|
|
@@ -83,7 +83,7 @@ async function runAgent(args) {
|
|
|
83
83
|
...typeof values.port === "string" ? { port: values.port } : {}
|
|
84
84
|
};
|
|
85
85
|
Object.assign(process.env, buildAgentEnv(opts));
|
|
86
|
-
await import("./launcher-
|
|
86
|
+
await import("./launcher-HX7B54EQ.js");
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// src/commands/setup.ts
|
|
@@ -65727,21 +65727,46 @@ var require_device_manager_addon = __commonJS({
|
|
|
65727
65727
|
device
|
|
65728
65728
|
};
|
|
65729
65729
|
}
|
|
65730
|
+
function persistedOnlineFallback(input) {
|
|
65731
|
+
if (!input.registryPresent) return false;
|
|
65732
|
+
if (input.parentDeviceId !== null) return true;
|
|
65733
|
+
return Object.keys(input.config ?? {}).length > 0;
|
|
65734
|
+
}
|
|
65730
65735
|
function extractCallerAddonId(input) {
|
|
65731
65736
|
const raw = Reflect.get(input, "callerAddonId");
|
|
65732
65737
|
return typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
65733
65738
|
}
|
|
65734
65739
|
async function listPersistedByAddon(pctx, input) {
|
|
65735
65740
|
const { addonId } = input;
|
|
65736
|
-
|
|
65737
|
-
|
|
65738
|
-
|
|
65739
|
-
|
|
65740
|
-
|
|
65741
|
-
|
|
65742
|
-
|
|
65743
|
-
|
|
65744
|
-
|
|
65741
|
+
const rows = await pctx.metaStore.rows.listByAddon(addonId);
|
|
65742
|
+
const saved = [];
|
|
65743
|
+
for (const row of rows) {
|
|
65744
|
+
const m = row.meta;
|
|
65745
|
+
if (!row.registered) {
|
|
65746
|
+
const reserved = await pctx.settings.readDeviceStore(m.id);
|
|
65747
|
+
if (Object.keys(reserved ?? {}).length === 0) {
|
|
65748
|
+
pctx.host.ctx.logger.warn("Skipping an unregistered device reservation with no configuration \u2014 not a device, not restored", {
|
|
65749
|
+
tags: { deviceId: m.id },
|
|
65750
|
+
meta: {
|
|
65751
|
+
addonId,
|
|
65752
|
+
stableId: m.stableId,
|
|
65753
|
+
type: m.type
|
|
65754
|
+
}
|
|
65755
|
+
});
|
|
65756
|
+
continue;
|
|
65757
|
+
}
|
|
65758
|
+
}
|
|
65759
|
+
saved.push({
|
|
65760
|
+
id: m.id,
|
|
65761
|
+
stableId: m.stableId,
|
|
65762
|
+
type: m.type,
|
|
65763
|
+
name: m.name,
|
|
65764
|
+
location: m.location ?? null,
|
|
65765
|
+
disabled: m.disabled ?? false,
|
|
65766
|
+
parentDeviceId: m.parentDeviceId
|
|
65767
|
+
});
|
|
65768
|
+
}
|
|
65769
|
+
return saved;
|
|
65745
65770
|
}
|
|
65746
65771
|
async function readDeviceConfigs(pctx, deviceIds) {
|
|
65747
65772
|
if (deviceIds.length === 0) return /* @__PURE__ */ new Map();
|
|
@@ -65811,7 +65836,11 @@ var require_device_manager_addon = __commonJS({
|
|
|
65811
65836
|
disabled: m.disabled ?? false,
|
|
65812
65837
|
parentDeviceId: m.parentDeviceId ?? null,
|
|
65813
65838
|
role: toDeviceRole(m.role),
|
|
65814
|
-
online: pctx.host.resolveDeviceOnline(m.id,
|
|
65839
|
+
online: pctx.host.resolveDeviceOnline(m.id, persistedOnlineFallback({
|
|
65840
|
+
registryPresent: pctx.registry !== null,
|
|
65841
|
+
parentDeviceId: m.parentDeviceId ?? null,
|
|
65842
|
+
config: persistedConfig
|
|
65843
|
+
})),
|
|
65815
65844
|
probed: pctx.host.resolveDeviceProbed(m.id),
|
|
65816
65845
|
features: persistedFeatures(m.features),
|
|
65817
65846
|
isCamera: persistedIsCamera(persistedType),
|
|
@@ -65856,7 +65885,11 @@ var require_device_manager_addon = __commonJS({
|
|
|
65856
65885
|
disabled: m.disabled ?? false,
|
|
65857
65886
|
parentDeviceId: m.parentDeviceId,
|
|
65858
65887
|
role: toDeviceRole(m.role),
|
|
65859
|
-
online: pctx.host.resolveDeviceOnline(deviceId,
|
|
65888
|
+
online: pctx.host.resolveDeviceOnline(deviceId, persistedOnlineFallback({
|
|
65889
|
+
registryPresent: true,
|
|
65890
|
+
parentDeviceId: m.parentDeviceId ?? null,
|
|
65891
|
+
config: persistedConfig
|
|
65892
|
+
})),
|
|
65860
65893
|
probed: pctx.host.resolveDeviceProbed(deviceId),
|
|
65861
65894
|
features: persistedFeatures(m.features),
|
|
65862
65895
|
isCamera: persistedIsCamera(m.type),
|
|
@@ -66172,7 +66205,7 @@ var require_device_manager_addon = __commonJS({
|
|
|
66172
66205
|
async function adoptDevice(pctx, input) {
|
|
66173
66206
|
const dp = await pctx.host.requireDeviceProvider(input.addonId);
|
|
66174
66207
|
if (!await dp.supportsDiscovery({})) throw new Error(`Addon "${input.addonId}" does not support device adoption`);
|
|
66175
|
-
const summary = await dp.adoptDiscoveredDevice({ candidate: input.candidate });
|
|
66208
|
+
const summary = await pctx.removalFence.runUnfenced(() => dp.adoptDiscoveredDevice({ candidate: input.candidate }));
|
|
66176
66209
|
if (input.integrationId !== void 0) try {
|
|
66177
66210
|
await pctx.stampIntegrationId(summary.id, input.integrationId);
|
|
66178
66211
|
} catch (err) {
|
|
@@ -66194,10 +66227,10 @@ var require_device_manager_addon = __commonJS({
|
|
|
66194
66227
|
async function createDevice(pctx, input) {
|
|
66195
66228
|
const dp = await pctx.host.requireDeviceProvider(input.addonId);
|
|
66196
66229
|
if (!await dp.supportsManualCreation({})) throw new Error(`Addon "${input.addonId}" does not support manual device creation`);
|
|
66197
|
-
const summary = await dp.createDevice({
|
|
66230
|
+
const summary = await pctx.removalFence.runUnfenced(() => dp.createDevice({
|
|
66198
66231
|
type: input.type,
|
|
66199
66232
|
config: input.config
|
|
66200
|
-
});
|
|
66233
|
+
}));
|
|
66201
66234
|
if (input.integrationId !== void 0) try {
|
|
66202
66235
|
await pctx.stampIntegrationId(summary.id, input.integrationId);
|
|
66203
66236
|
} catch (err) {
|
|
@@ -67487,6 +67520,17 @@ var require_device_manager_addon = __commonJS({
|
|
|
67487
67520
|
return await pctx.metaStore.withMetaWriteLock(async () => {
|
|
67488
67521
|
const existing = await pctx.metaStore.rows.findByStableId(addonId, stableId);
|
|
67489
67522
|
if (existing) return { id: existing.meta.id };
|
|
67523
|
+
const fenced = pctx.removalFence.isPairFenced(addonId, stableId);
|
|
67524
|
+
if (fenced) {
|
|
67525
|
+
pctx.host.ctx.logger.warn("allocateDeviceId refused \u2014 this device was just removed, NOT re-created", {
|
|
67526
|
+
tags: { deviceId: fenced.deviceId },
|
|
67527
|
+
meta: {
|
|
67528
|
+
addonId,
|
|
67529
|
+
stableId
|
|
67530
|
+
}
|
|
67531
|
+
});
|
|
67532
|
+
throw new Error(`[device-manager] allocateDeviceId: device ${fenced.deviceId} (${addonId}/${stableId}) was removed \u2014 refusing to re-create it`);
|
|
67533
|
+
}
|
|
67490
67534
|
const id = await pctx.metaStore.allocateNextDeviceId();
|
|
67491
67535
|
await pctx.metaStore.rows.upsert({
|
|
67492
67536
|
addonId,
|
|
@@ -67615,6 +67659,16 @@ var require_device_manager_addon = __commonJS({
|
|
|
67615
67659
|
async function registerDevice(pctx, input) {
|
|
67616
67660
|
const { addonId, stableId, id, type, name, parentDeviceId, features, config } = input;
|
|
67617
67661
|
const featuresArr = Array.isArray(features) ? [...features] : [];
|
|
67662
|
+
if (pctx.removalFence.isIdFenced(id) ?? pctx.removalFence.isPairFenced(addonId, stableId)) {
|
|
67663
|
+
pctx.host.ctx.logger.warn("registerDevice refused \u2014 this device was removed, NOT resurrected", {
|
|
67664
|
+
tags: { deviceId: id },
|
|
67665
|
+
meta: {
|
|
67666
|
+
addonId,
|
|
67667
|
+
stableId
|
|
67668
|
+
}
|
|
67669
|
+
});
|
|
67670
|
+
throw new Error(`[device-manager] registerDevice: device ${id} (${addonId}/${stableId}) was removed \u2014 refusing to resurrect it`);
|
|
67671
|
+
}
|
|
67618
67672
|
const { isFirstRegistration, exportFingerprint, fingerprintChanged, inheritedLocation, inheritedDescendantIds, inheritFailed } = await pctx.metaStore.withMetaWriteLock(async () => {
|
|
67619
67673
|
const existingRow = await pctx.metaStore.rows.get(id);
|
|
67620
67674
|
const existingMeta = existingRow?.meta;
|
|
@@ -67755,6 +67809,11 @@ var require_device_manager_addon = __commonJS({
|
|
|
67755
67809
|
const deviceName = persistedMeta.name;
|
|
67756
67810
|
await pctx.metaStore.withMetaWriteLock(async () => {
|
|
67757
67811
|
await pctx.metaStore.rows.remove(deviceId);
|
|
67812
|
+
pctx.removalFence.record({
|
|
67813
|
+
deviceId,
|
|
67814
|
+
addonId,
|
|
67815
|
+
stableId
|
|
67816
|
+
});
|
|
67758
67817
|
});
|
|
67759
67818
|
await pctx.settings.clearDeviceStore(deviceId);
|
|
67760
67819
|
await pctx.settings.clearDeviceRuntimeState(deviceId);
|
|
@@ -69681,7 +69740,7 @@ var require_device_manager_addon = __commonJS({
|
|
|
69681
69740
|
function createMigrationGuard(now = Date.now) {
|
|
69682
69741
|
const inFlight = /* @__PURE__ */ new Set();
|
|
69683
69742
|
const completed = /* @__PURE__ */ new Map();
|
|
69684
|
-
const
|
|
69743
|
+
const pairKey2 = (sourceId, targetId) => `${sourceId}->${targetId}`;
|
|
69685
69744
|
return {
|
|
69686
69745
|
begin(sourceId, targetId) {
|
|
69687
69746
|
for (const id of [sourceId, targetId]) if (inFlight.has(id)) throw new Error(`[device-manager] migrateDevice: a migration involving device ${id} is already in flight \u2014 this call was refused, not queued. The running migration's report stands; re-read the device rows before retrying.`);
|
|
@@ -69693,13 +69752,13 @@ var require_device_manager_addon = __commonJS({
|
|
|
69693
69752
|
inFlight.delete(targetId);
|
|
69694
69753
|
},
|
|
69695
69754
|
recordCompleted(record) {
|
|
69696
|
-
completed.set(
|
|
69755
|
+
completed.set(pairKey2(record.sourceId, record.targetId), {
|
|
69697
69756
|
...record,
|
|
69698
69757
|
completedAt: now()
|
|
69699
69758
|
});
|
|
69700
69759
|
},
|
|
69701
69760
|
matchReplay(sourceId, targetId, atSource, atTarget) {
|
|
69702
|
-
const key =
|
|
69761
|
+
const key = pairKey2(sourceId, targetId);
|
|
69703
69762
|
const record = completed.get(key);
|
|
69704
69763
|
if (record === void 0) return null;
|
|
69705
69764
|
if (now() - record.completedAt > 9e5) {
|
|
@@ -69711,6 +69770,56 @@ var require_device_manager_addon = __commonJS({
|
|
|
69711
69770
|
}
|
|
69712
69771
|
};
|
|
69713
69772
|
}
|
|
69773
|
+
function pairKey(addonId, stableId) {
|
|
69774
|
+
return `${addonId}\0${stableId}`;
|
|
69775
|
+
}
|
|
69776
|
+
function createRemovalFence(options = {}) {
|
|
69777
|
+
const ttlMs = options.ttlMs ?? 3e5;
|
|
69778
|
+
const now = options.now ?? (() => Date.now());
|
|
69779
|
+
const byId = /* @__PURE__ */ new Map();
|
|
69780
|
+
const byPair = /* @__PURE__ */ new Map();
|
|
69781
|
+
let suspensions = 0;
|
|
69782
|
+
const fresh = (entry) => {
|
|
69783
|
+
if (entry === void 0) return null;
|
|
69784
|
+
if (suspensions > 0) return null;
|
|
69785
|
+
if (now() - entry.removedAt >= ttlMs) {
|
|
69786
|
+
byId.delete(entry.deviceId);
|
|
69787
|
+
byPair.delete(pairKey(entry.addonId, entry.stableId));
|
|
69788
|
+
return null;
|
|
69789
|
+
}
|
|
69790
|
+
return entry;
|
|
69791
|
+
};
|
|
69792
|
+
return {
|
|
69793
|
+
record(entry) {
|
|
69794
|
+
const full = {
|
|
69795
|
+
...entry,
|
|
69796
|
+
removedAt: now()
|
|
69797
|
+
};
|
|
69798
|
+
byId.set(full.deviceId, full);
|
|
69799
|
+
byPair.set(pairKey(full.addonId, full.stableId), full);
|
|
69800
|
+
},
|
|
69801
|
+
isIdFenced(deviceId) {
|
|
69802
|
+
return fresh(byId.get(deviceId));
|
|
69803
|
+
},
|
|
69804
|
+
isPairFenced(addonId, stableId) {
|
|
69805
|
+
return fresh(byPair.get(pairKey(addonId, stableId)));
|
|
69806
|
+
},
|
|
69807
|
+
lift(addonId, stableId) {
|
|
69808
|
+
const entry = byPair.get(pairKey(addonId, stableId));
|
|
69809
|
+
if (entry === void 0) return;
|
|
69810
|
+
byPair.delete(pairKey(addonId, stableId));
|
|
69811
|
+
byId.delete(entry.deviceId);
|
|
69812
|
+
},
|
|
69813
|
+
async runUnfenced(fn) {
|
|
69814
|
+
suspensions += 1;
|
|
69815
|
+
try {
|
|
69816
|
+
return await fn();
|
|
69817
|
+
} finally {
|
|
69818
|
+
suspensions -= 1;
|
|
69819
|
+
}
|
|
69820
|
+
}
|
|
69821
|
+
};
|
|
69822
|
+
}
|
|
69714
69823
|
var DeviceManagerAddon = class extends require_dist10.BaseAddon {
|
|
69715
69824
|
constructor() {
|
|
69716
69825
|
super({});
|
|
@@ -69951,6 +70060,7 @@ var require_device_manager_addon = __commonJS({
|
|
|
69951
70060
|
registry,
|
|
69952
70061
|
bindingsDeps: this.bindingsDeps,
|
|
69953
70062
|
migrationGuard: createMigrationGuard(),
|
|
70063
|
+
removalFence: createRemovalFence(),
|
|
69954
70064
|
requireDeviceOps,
|
|
69955
70065
|
stampIntegrationId: stampIntegrationId$1,
|
|
69956
70066
|
get provider() {
|
|
@@ -241146,6 +241256,53 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
241146
241256
|
const ids = [...this._permanentRestoreFailures.keys()].join(", ");
|
|
241147
241257
|
return `${this._permanentRestoreFailures.size} device(s) permanently failed restore (deviceIds: ${ids}) \u2014 restart the ${this.providerName} provider to retry`;
|
|
241148
241258
|
}
|
|
241259
|
+
/**
|
|
241260
|
+
* A top-level persisted row with NO configuration is a leftover, not a
|
|
241261
|
+
* device — quarantine it instead of dialling it.
|
|
241262
|
+
*
|
|
241263
|
+
* Device 614 was deleted, resurrected as a config-less shell by a write
|
|
241264
|
+
* already in flight (D376), and then dialled at every single boot: eight
|
|
241265
|
+
* `Failed to restore device — bounded retry scheduled` lines in one day,
|
|
241266
|
+
* each one the same Zod refusal on `host` and `password`. The bound was
|
|
241267
|
+
* real, but it is a bound PER PROCESS, and the runner restarts — so nothing
|
|
241268
|
+
* about the row ever stopped costing attempts and log lines.
|
|
241269
|
+
*
|
|
241270
|
+
* No retry can add a configuration that is not there. The row is reported
|
|
241271
|
+
* once, with its `deviceId`, and set aside.
|
|
241272
|
+
*
|
|
241273
|
+
* Top-level only: an accessory child legitimately carries an empty blob (it
|
|
241274
|
+
* lives off its parent), and a hub-adopted child with an emptied blob is
|
|
241275
|
+
* repaired by `healSavedConfig` from its parent instead. Providers that
|
|
241276
|
+
* genuinely create configuration-free top-level devices turn this off.
|
|
241277
|
+
*/
|
|
241278
|
+
quarantineConfiglessTopLevelRestores = true;
|
|
241279
|
+
isUnrestorableShell(saved) {
|
|
241280
|
+
if (!this.quarantineConfiglessTopLevelRestores) return false;
|
|
241281
|
+
if (saved.parentDeviceId !== null) return false;
|
|
241282
|
+
const config = saved.config;
|
|
241283
|
+
if (config === void 0) return false;
|
|
241284
|
+
return Object.keys(config).length === 0;
|
|
241285
|
+
}
|
|
241286
|
+
quarantineShell(saved) {
|
|
241287
|
+
this._permanentRestoreFailures.set(saved.id, {
|
|
241288
|
+
deviceId: saved.id,
|
|
241289
|
+
stableId: saved.stableId,
|
|
241290
|
+
type: saved.type,
|
|
241291
|
+
attempts: 0,
|
|
241292
|
+
lastError: "persisted row has no configuration",
|
|
241293
|
+
failedAt: Date.now()
|
|
241294
|
+
});
|
|
241295
|
+
this.ctx.logger.error("Persisted device row has NO configuration \u2014 quarantined: not restored, not retried. Remove it (deviceManager.removeDevice) or re-add the device.", {
|
|
241296
|
+
tags: {
|
|
241297
|
+
deviceId: saved.id,
|
|
241298
|
+
stableId: saved.stableId
|
|
241299
|
+
},
|
|
241300
|
+
meta: {
|
|
241301
|
+
type: saved.type,
|
|
241302
|
+
provider: this.providerName
|
|
241303
|
+
}
|
|
241304
|
+
});
|
|
241305
|
+
}
|
|
241149
241306
|
cancelRestoreRetries() {
|
|
241150
241307
|
this._restoreRetryScheduler?.cancel();
|
|
241151
241308
|
this._restoreRetryScheduler = null;
|
|
@@ -241331,6 +241488,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
241331
241488
|
});
|
|
241332
241489
|
return;
|
|
241333
241490
|
}
|
|
241491
|
+
if (this.isUnrestorableShell(saved)) {
|
|
241492
|
+
this.quarantineShell(saved);
|
|
241493
|
+
return;
|
|
241494
|
+
}
|
|
241334
241495
|
try {
|
|
241335
241496
|
await attemptRestore(saved);
|
|
241336
241497
|
} catch (err) {
|
|
@@ -412781,8 +412942,8 @@ var require_session_cookie = __commonJS({
|
|
|
412781
412942
|
function shouldRedirectToLogin(method, accept) {
|
|
412782
412943
|
return method === "GET" && typeof accept === "string" && accept.includes("text/html");
|
|
412783
412944
|
}
|
|
412784
|
-
function loginRedirectUrl(originalUrl) {
|
|
412785
|
-
return
|
|
412945
|
+
function loginRedirectUrl(originalUrl, mountPrefix = null) {
|
|
412946
|
+
return `${mountPrefix ?? ""}/login?next=${encodeURIComponent(originalUrl)}`;
|
|
412786
412947
|
}
|
|
412787
412948
|
function isEmbedRedirectTarget(next) {
|
|
412788
412949
|
if (!next.startsWith("/addon/stream-broker/embed/"))
|
|
@@ -413959,6 +414120,97 @@ var require_spa_static = __commonJS({
|
|
|
413959
414120
|
}
|
|
413960
414121
|
});
|
|
413961
414122
|
|
|
414123
|
+
// ../../server/backend/dist/api/static/spa-mount.js
|
|
414124
|
+
var require_spa_mount = __commonJS({
|
|
414125
|
+
"../../server/backend/dist/api/static/spa-mount.js"(exports) {
|
|
414126
|
+
"use strict";
|
|
414127
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
414128
|
+
if (k2 === void 0) k2 = k;
|
|
414129
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
414130
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
414131
|
+
desc = { enumerable: true, get: function() {
|
|
414132
|
+
return m[k];
|
|
414133
|
+
} };
|
|
414134
|
+
}
|
|
414135
|
+
Object.defineProperty(o, k2, desc);
|
|
414136
|
+
}) : (function(o, m, k, k2) {
|
|
414137
|
+
if (k2 === void 0) k2 = k;
|
|
414138
|
+
o[k2] = m[k];
|
|
414139
|
+
}));
|
|
414140
|
+
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
414141
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
414142
|
+
}) : function(o, v) {
|
|
414143
|
+
o["default"] = v;
|
|
414144
|
+
});
|
|
414145
|
+
var __importStar = exports && exports.__importStar || /* @__PURE__ */ (function() {
|
|
414146
|
+
var ownKeys = function(o) {
|
|
414147
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
414148
|
+
var ar = [];
|
|
414149
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
414150
|
+
return ar;
|
|
414151
|
+
};
|
|
414152
|
+
return ownKeys(o);
|
|
414153
|
+
};
|
|
414154
|
+
return function(mod) {
|
|
414155
|
+
if (mod && mod.__esModule) return mod;
|
|
414156
|
+
var result = {};
|
|
414157
|
+
if (mod != null) {
|
|
414158
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
414159
|
+
}
|
|
414160
|
+
__setModuleDefault(result, mod);
|
|
414161
|
+
return result;
|
|
414162
|
+
};
|
|
414163
|
+
})();
|
|
414164
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
414165
|
+
exports.FORWARDED_PREFIX_HEADER = void 0;
|
|
414166
|
+
exports.parseForwardedPrefix = parseForwardedPrefix;
|
|
414167
|
+
exports.injectSpaMount = injectSpaMount;
|
|
414168
|
+
exports.sendSpaShell = sendSpaShell;
|
|
414169
|
+
var fs = __importStar(__require("fs/promises"));
|
|
414170
|
+
var spa_static_1 = require_spa_static();
|
|
414171
|
+
exports.FORWARDED_PREFIX_HEADER = "x-forwarded-prefix";
|
|
414172
|
+
var FORWARDED_PREFIX_VARY = "X-Forwarded-Prefix";
|
|
414173
|
+
var MOUNT_META_NAME = "camstack-mount";
|
|
414174
|
+
var PREFIX_RE = /^\/[A-Za-z0-9_\-.]+(?:\/[A-Za-z0-9_\-.]+)*$/;
|
|
414175
|
+
var MAX_PREFIX_LENGTH = 512;
|
|
414176
|
+
function parseForwardedPrefix(value) {
|
|
414177
|
+
if (typeof value !== "string")
|
|
414178
|
+
return null;
|
|
414179
|
+
if (value.length === 0 || value.length > MAX_PREFIX_LENGTH)
|
|
414180
|
+
return null;
|
|
414181
|
+
const trimmed = value.endsWith("/") ? value.slice(0, -1) : value;
|
|
414182
|
+
if (trimmed === "")
|
|
414183
|
+
return null;
|
|
414184
|
+
if (!PREFIX_RE.test(trimmed))
|
|
414185
|
+
return null;
|
|
414186
|
+
if (trimmed.split("/").some((segment) => segment === ".." || segment === "."))
|
|
414187
|
+
return null;
|
|
414188
|
+
return trimmed;
|
|
414189
|
+
}
|
|
414190
|
+
function injectSpaMount(html, prefix) {
|
|
414191
|
+
const match = /<head(?:\s[^>]*)?>/i.exec(html);
|
|
414192
|
+
if (match === null)
|
|
414193
|
+
return html;
|
|
414194
|
+
const mount = `${prefix}/`;
|
|
414195
|
+
const injected = `<base href="${mount}"><meta name="${MOUNT_META_NAME}" content="${mount}">`;
|
|
414196
|
+
const at = match.index + match[0].length;
|
|
414197
|
+
return `${html.slice(0, at)}${injected}${html.slice(at)}`;
|
|
414198
|
+
}
|
|
414199
|
+
async function sendSpaShell(reply, indexPath, headers) {
|
|
414200
|
+
reply.header("cache-control", (0, spa_static_1.spaShellCacheControl)());
|
|
414201
|
+
reply.header("vary", FORWARDED_PREFIX_VARY);
|
|
414202
|
+
let html;
|
|
414203
|
+
try {
|
|
414204
|
+
html = await fs.readFile(indexPath, "utf8");
|
|
414205
|
+
} catch {
|
|
414206
|
+
return reply.status(503).send({ error: "Admin UI shell unavailable" });
|
|
414207
|
+
}
|
|
414208
|
+
const prefix = parseForwardedPrefix(headers[exports.FORWARDED_PREFIX_HEADER]);
|
|
414209
|
+
return reply.type("text/html").send(prefix === null ? html : injectSpaMount(html, prefix));
|
|
414210
|
+
}
|
|
414211
|
+
}
|
|
414212
|
+
});
|
|
414213
|
+
|
|
413962
414214
|
// ../../server/backend/dist/boot/integration-id-backfill.js
|
|
413963
414215
|
var require_integration_id_backfill = __commonJS({
|
|
413964
414216
|
"../../server/backend/dist/boot/integration-id-backfill.js"(exports) {
|
|
@@ -429580,6 +429832,7 @@ var require_main4 = __commonJS({
|
|
|
429580
429832
|
var sse_no_compression_js_1 = require_sse_no_compression();
|
|
429581
429833
|
var precompressed_asset_js_1 = require_precompressed_asset();
|
|
429582
429834
|
var spa_static_1 = require_spa_static();
|
|
429835
|
+
var spa_mount_1 = require_spa_mount();
|
|
429583
429836
|
var cap_providers_1 = require_cap_providers();
|
|
429584
429837
|
var logging_settings_1 = require_logging_settings();
|
|
429585
429838
|
var request_census_settings_1 = require_request_census_settings();
|
|
@@ -430207,7 +430460,7 @@ var require_main4 = __commonJS({
|
|
|
430207
430460
|
return reply.status(404).send({ error: "Not found" });
|
|
430208
430461
|
}
|
|
430209
430462
|
if (method === "GET" && spaIndexHtml) {
|
|
430210
|
-
return
|
|
430463
|
+
return (0, spa_mount_1.sendSpaShell)(reply, spaIndexHtml, request.headers);
|
|
430211
430464
|
}
|
|
430212
430465
|
return reply.status(404).send({ error: "Not found" });
|
|
430213
430466
|
}
|
|
@@ -430217,7 +430470,7 @@ var require_main4 = __commonJS({
|
|
|
430217
430470
|
if (!authHeader && !cookieToken) {
|
|
430218
430471
|
if ((0, session_cookie_js_1.shouldRedirectToLogin)(request.method, request.headers.accept)) {
|
|
430219
430472
|
const qs = request.url.includes("?") ? request.url.slice(request.url.indexOf("?")) : "";
|
|
430220
|
-
return reply.redirect((0, session_cookie_js_1.loginRedirectUrl)(fullPath + qs));
|
|
430473
|
+
return reply.redirect((0, session_cookie_js_1.loginRedirectUrl)(fullPath + qs, (0, spa_mount_1.parseForwardedPrefix)(request.headers["x-forwarded-prefix"])));
|
|
430221
430474
|
}
|
|
430222
430475
|
return reply.status(401).send({ error: "Unauthorized" });
|
|
430223
430476
|
}
|
|
@@ -430419,7 +430672,7 @@ var require_main4 = __commonJS({
|
|
|
430419
430672
|
return reply.status(503).send({ error: "Admin UI is starting" });
|
|
430420
430673
|
}
|
|
430421
430674
|
const pathOnly = url.split("?")[0] ?? url;
|
|
430422
|
-
if (/\.[a-zA-Z0-9]+$/.test(pathOnly)) {
|
|
430675
|
+
if (pathOnly !== "/index.html" && /\.[a-zA-Z0-9]+$/.test(pathOnly)) {
|
|
430423
430676
|
const rel = pathOnly.replace(/^\/+/, "");
|
|
430424
430677
|
const abs = path.join(staticDir, rel);
|
|
430425
430678
|
if ((abs === staticDir || abs.startsWith(staticDir + path.sep)) && fs.existsSync(abs)) {
|
|
@@ -430428,8 +430681,7 @@ var require_main4 = __commonJS({
|
|
|
430428
430681
|
}
|
|
430429
430682
|
return reply.callNotFound();
|
|
430430
430683
|
}
|
|
430431
|
-
|
|
430432
|
-
return reply.type("text/html").send(fs.createReadStream(indexPath));
|
|
430684
|
+
return (0, spa_mount_1.sendSpaShell)(reply, indexPath, request.headers);
|
|
430433
430685
|
});
|
|
430434
430686
|
const resolveAdminUi = async () => {
|
|
430435
430687
|
try {
|