fix(store): use string prefix + URLSearchParams for connection URL parsing
The URL constructor parses non-standard protocols (multica://) differently across engines — Chromium may return empty hostname while Node.js returns "connect". Replace new URL() with simple startsWith check and URLSearchParams to ensure consistent behavior in both web and Electron environments. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
ff80cf0732
commit
b6d7626239
1 changed files with 43 additions and 3 deletions
|
|
@ -22,10 +22,50 @@ function isConnectionInfo(obj: unknown): obj is ConnectionInfo {
|
|||
)
|
||||
}
|
||||
|
||||
// Parse multica://connect?gateway=...&hub=...&agent=...&token=...&exp=... URL format
|
||||
// Uses string prefix + URLSearchParams to avoid cross-engine URL hostname differences
|
||||
function parseConnectionUrl(input: string): ConnectionInfo | null {
|
||||
const prefix = "multica://connect?"
|
||||
if (!input.startsWith(prefix)) return null
|
||||
try {
|
||||
const params = new URLSearchParams(input.slice(prefix.length))
|
||||
const gateway = params.get("gateway")
|
||||
const hubId = params.get("hub")
|
||||
const agentId = params.get("agent")
|
||||
const token = params.get("token")
|
||||
const exp = params.get("exp")
|
||||
if (!gateway || !hubId || !agentId || !token || !exp) return null
|
||||
return {
|
||||
type: "multica-connect",
|
||||
gateway,
|
||||
hubId,
|
||||
agentId,
|
||||
token,
|
||||
expires: Number(exp),
|
||||
}
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function isExpired(expires: number): boolean {
|
||||
// Desktop generates expires as millisecond timestamp (Date.now() + seconds * 1000)
|
||||
return Date.now() > expires
|
||||
}
|
||||
|
||||
export function parseConnectionCode(input: string): ConnectionInfo {
|
||||
const trimmed = input.trim()
|
||||
|
||||
// Try JSON first
|
||||
// Try multica:// URL format first (desktop "Copy Link" output)
|
||||
const fromUrl = parseConnectionUrl(trimmed)
|
||||
if (fromUrl) {
|
||||
if (isExpired(fromUrl.expires)) {
|
||||
throw new Error("Connection code has expired")
|
||||
}
|
||||
return fromUrl
|
||||
}
|
||||
|
||||
// Try JSON (QR code scan output)
|
||||
let parsed: unknown
|
||||
try {
|
||||
parsed = JSON.parse(trimmed)
|
||||
|
|
@ -42,7 +82,7 @@ export function parseConnectionCode(input: string): ConnectionInfo {
|
|||
throw new Error("Invalid connection code format")
|
||||
}
|
||||
|
||||
if (Date.now() > parsed.expires * 1000) {
|
||||
if (isExpired(parsed.expires)) {
|
||||
throw new Error("Connection code has expired")
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +100,7 @@ export function loadConnection(): ConnectionInfo | null {
|
|||
try {
|
||||
const info = JSON.parse(raw)
|
||||
if (!isConnectionInfo(info)) return null
|
||||
if (Date.now() > info.expires * 1000) {
|
||||
if (isExpired(info.expires)) {
|
||||
localStorage.removeItem(STORAGE_KEY)
|
||||
return null
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue