mirror of
https://github.com/aipoch/open-science.git
synced 2026-10-02 10:24:47 +08:00
* feat(branding): unify product name while preserving existing data locations * chore(ci): retain the existing protected impact configuration * refactor(branding): classify native path modules with existing CI rules * fix(storage): preserve location recovery across brand upgrades * fix(branding): align certificate subjects and repository labels (#10) * fix(brand): preserve data ownership and retry native upgrades * fix(storage): preserve confirmed data locations during brand upgrade * feat(security): select credential identity with silent probes (#11) * fix(branding): guard location ownership and repair CI regressions * fix(branding): preserve coexisting application installations * fix(ci): isolate installed sandbox and native dialog regressions * fix(cli): preserve explicit bindings and signing identities * fix(compat): preserve Linux credentials and legacy RIS names * fix(ci): register brand compatibility ownership and consumers (#12) * fix(startup): log detailed bootstrap failures * fix(credentials): select macOS identities sequentially with guarded access * refactor(storage): remove profile initialization records * fix(storage): preserve legacy roots and save onboarding choices * docs(brand): keep compatibility policies outside repository
52 lines
1.6 KiB
JavaScript
52 lines
1.6 KiB
JavaScript
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
|
|
import { readFile } from 'node:fs/promises'
|
|
import { join } from 'node:path'
|
|
|
|
const STATE_FILE = 'web-service.json'
|
|
const TOKEN_FILE = 'web-token'
|
|
const READY_URL_PATTERN =
|
|
/Open-Science Web:\s+(http:\/\/127\.0\.0\.1:\d+\/(?:\?token=[A-Za-z0-9_-]+)?)/
|
|
|
|
const parsePackagedAppEndpoint = (output) => {
|
|
const match = output.match(READY_URL_PATTERN)
|
|
if (!match) return undefined
|
|
const url = new URL(match[1])
|
|
const token = url.searchParams.get('token')
|
|
return {
|
|
endpoint: url.origin,
|
|
...(token ? { auth: `token=${encodeURIComponent(token)}` } : {})
|
|
}
|
|
}
|
|
|
|
const authenticatePackagedAppEndpoint = async (
|
|
output,
|
|
configRoots = [],
|
|
{ readText = readFile, joinPath = join } = {}
|
|
) => {
|
|
const service = parsePackagedAppEndpoint(output)
|
|
if (!service || service.auth) return service
|
|
|
|
const port = Number(new URL(service.endpoint).port)
|
|
const roots = [...new Set(configRoots.filter((root) => typeof root === 'string' && root))]
|
|
|
|
for (const root of roots) {
|
|
try {
|
|
const state = JSON.parse(await readText(joinPath(root, STATE_FILE), 'utf8'))
|
|
if (state.port !== port) continue
|
|
const token = (await readText(joinPath(root, TOKEN_FILE), 'utf8')).trim()
|
|
if (token.length < 32) continue
|
|
return {
|
|
...service,
|
|
auth: `token=${encodeURIComponent(token)}`
|
|
}
|
|
} catch {
|
|
// State and token files are published independently; retry while the service is starting.
|
|
}
|
|
}
|
|
|
|
return undefined
|
|
}
|
|
|
|
export { authenticatePackagedAppEndpoint, parsePackagedAppEndpoint }
|