#!/usr/bin/env node
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { createRequire } from "node:module";
import { fileURLToPath, pathToFileURL } from "node:url";
import {
DISPLAY_CHROME_PATH,
DISPLAY_META_PATH,
DISPLAY_RUNTIME_HOME,
DISPLAY_PROFILE_DIR,
DISPLAY_STATE_PATH,
ensureDir,
ensureParentDir,
ensureRuntimeTree,
resolveChromePath,
resolveMetaWritePath,
resolveProfileDir,
resolveRuntimeHome,
resolveStateWritePath,
} from "./lib/runtime-paths.mjs";
import { parseArgs } from "./lib/cli-shared.mjs";
import { extractClientBin } from "./lib/auth-shared.mjs";
const DEFAULT_URL =
"https://salesintelligence-dv.oracle.com/ui/dv/ui/project.jsp?pageid=visualAnalyzer&reportmode=presentation&reportpath=%2F%40Catalog%2Fshared%2FTeam%20Sharing%20Area%2FLAD%2FLAD%20Sales%20Operations%2FLAD%20Production%2FLAD%20Knowledge%20One%20View";
const scriptsDir = path.dirname(fileURLToPath(import.meta.url));
const skillHome = path.resolve(scriptsDir, "..");
const skillsHome = path.resolve(skillHome, "..");
function usage() {
return `Refresh Oracle Sales Intelligence auth by opening Chrome.
This is an optional development and troubleshooting helper. Daily use should prefer scripts/refresh-auth-direct.mjs.
Usage:
node scripts/refresh-auth-state.mjs [options]
Options:
--runtime-home
Override workspace runtime root (default: ${DISPLAY_RUNTIME_HOME})
--state-path Override auth-state.json output path (default: ${DISPLAY_STATE_PATH})
--meta-path Override session-meta.json output path (default: ${DISPLAY_META_PATH})
--profile-dir Override Chrome profile directory (default: ${DISPLAY_PROFILE_DIR})
--chrome-path Override Chrome executable path (default: ${DISPLAY_CHROME_PATH})
--url Target Oracle DV workbook URL
--timeout-ms Wait time for authenticated Oracle DV page (default: 600000)
--help Show this help
`;
}
async function pathExists(targetPath) {
try {
await fs.access(targetPath);
return true;
} catch {
return false;
}
}
function uniquePaths(values) {
const seen = new Set();
const result = [];
for (const value of values.filter(Boolean)) {
const resolved = path.resolve(value);
if (seen.has(resolved)) continue;
seen.add(resolved);
result.push(resolved);
}
return result;
}
function bundledRuntimePackageCandidates(packageName) {
const execDir = path.dirname(process.execPath || "");
const envNodeModules = [
process.env.CODEX_NODE_MODULES,
process.env.CODEX_BUNDLED_NODE_MODULES,
process.env.NODE_PATH,
].filter(Boolean);
const packageJsonCandidates = [];
for (const nodeModulesPath of envNodeModules) {
for (const basePath of String(nodeModulesPath).split(path.delimiter)) {
if (!basePath) continue;
packageJsonCandidates.push(path.join(basePath, packageName, "package.json"));
}
}
if (process.env.CODEX_PRIMARY_RUNTIME_HOME) {
packageJsonCandidates.push(
path.join(
process.env.CODEX_PRIMARY_RUNTIME_HOME,
"dependencies",
"node",
"node_modules",
packageName,
"package.json",
),
);
}
packageJsonCandidates.push(
path.join(execDir, "node_modules", packageName, "package.json"),
path.join(execDir, "..", "node_modules", packageName, "package.json"),
path.join(execDir, "..", "..", "node_modules", packageName, "package.json"),
path.join(
os.homedir(),
".cache",
"codex-runtimes",
"codex-primary-runtime",
"dependencies",
"node",
"node_modules",
packageName,
"package.json",
),
);
return uniquePaths(packageJsonCandidates);
}
async function loadPlaywright() {
const packageNames = ["playwright", "playwright-core"];
for (const packageName of packageNames) {
try {
return {
runtime: await import(packageName),
sourceLabel: `local-module:${packageName}`,
};
} catch {}
}
const sharedSkillPackageJson = path.join(skillsHome, "playwright", "package.json");
if (await pathExists(sharedSkillPackageJson)) {
const requireFromSharedSkill = createRequire(sharedSkillPackageJson);
for (const packageName of packageNames) {
try {
return {
runtime: requireFromSharedSkill(packageName),
sourceLabel: `shared-skill:${packageName}`,
};
} catch {}
}
}
for (const packageName of packageNames) {
for (const packageJsonPath of bundledRuntimePackageCandidates(packageName)) {
if (!(await pathExists(packageJsonPath))) continue;
try {
const requireFromBundledRuntime = createRequire(packageJsonPath);
return {
runtime: requireFromBundledRuntime(packageName),
sourceLabel: `bundled-runtime:${packageJsonPath}`,
};
} catch {}
}
}
throw new Error(
[
"Could not load Playwright for the browser auth helper.",
"Tried local module resolution, ~/.codex/skills/playwright, and bundled Codex runtime locations.",
"Install a shared Playwright runtime under ~/.codex/skills/playwright or run this helper from a Codex environment with bundled node_modules.",
].join(" "),
);
}
async function ensureChromeExecutable(chromePath) {
try {
await fs.access(chromePath);
} catch {
throw new Error(
`Could not find a Chrome executable at ${chromePath}. Pass --chrome-path or set ORACLE_SI_CHROME_PATH to a valid Chrome installation.`
);
}
}
export async function main(argv = process.argv.slice(2)) {
const args = parseArgs(argv);
if (args.help === "true") {
console.log(usage());
return;
}
const runtimeHome = resolveRuntimeHome(args["runtime-home"]);
await ensureRuntimeTree(runtimeHome);
const statePath = resolveStateWritePath({ explicitPath: args["state-path"], runtimeHome });
const metaPath = resolveMetaWritePath({ explicitPath: args["meta-path"], runtimeHome });
const profileDir = resolveProfileDir({ explicitPath: args["profile-dir"], runtimeHome });
const chromePath = resolveChromePath(args["chrome-path"]);
const targetUrl = args.url || process.env.ORACLE_SI_TARGET_URL || DEFAULT_URL;
const timeoutMs = Number(args["timeout-ms"] || 10 * 60 * 1000);
await ensureChromeExecutable(chromePath);
const { runtime: playwrightRuntime, sourceLabel } = await loadPlaywright();
const { chromium } = playwrightRuntime;
await ensureParentDir(statePath);
await ensureParentDir(metaPath);
await ensureDir(profileDir);
console.log(`Opening Chrome profile at ${profileDir}`);
console.log(`Using browser automation runtime: ${sourceLabel}`);
console.log("Complete Oracle login in the opened window if prompted.");
const context = await chromium.launchPersistentContext(profileDir, {
executablePath: chromePath,
headless: false,
ignoreHTTPSErrors: true,
viewport: { width: 1600, height: 900 },
});
let headerMeta = null;
const requestListener = (request) => {
if (headerMeta) return;
if (!request.url().includes("/ui/dv/ui/api/")) return;
const headers = request.headers();
const csrfToken = headers["x-csrf-token"] || null;
const clientBin = headers["x-bitech-clientbin"] || null;
if (!csrfToken || !clientBin) return;
headerMeta = {
xCsrfToken: csrfToken,
xBitechClientbin: clientBin,
referer: headers.referer || targetUrl,
targetUrl,
capturedAt: new Date().toISOString(),
};
};
context.on("request", requestListener);
try {
const page = context.pages()[0] ?? (await context.newPage());
await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 120000 });
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
await page.waitForTimeout(2000);
const url = page.url();
const title = await page.title().catch(() => "");
console.log(`Waiting for Oracle Analytics session: ${url}`);
const authenticated =
url.startsWith("https://salesintelligence-dv.oracle.com/") &&
!url.includes("signon.oracle.com") &&
!url.includes("signon-int.oracle.com") &&
/Oracle Analytics|LAD Knowledge One View/i.test(title || url);
if (!authenticated) continue;
const html = await page.content();
const fallbackClientBin = extractClientBin(html);
if (!headerMeta) {
await page.reload({ waitUntil: "domcontentloaded" }).catch(() => {});
await page.waitForTimeout(4000);
}
if (!headerMeta?.xBitechClientbin && fallbackClientBin) {
headerMeta = {
...(headerMeta || {}),
xCsrfToken: headerMeta?.xCsrfToken || null,
xBitechClientbin: fallbackClientBin,
referer: headerMeta?.referer || targetUrl,
targetUrl,
capturedAt: new Date().toISOString(),
};
}
if (!headerMeta?.xCsrfToken || !headerMeta?.xBitechClientbin) {
continue;
}
const state = await context.storageState();
await fs.writeFile(statePath, `${JSON.stringify(state, null, 2)}\n`, "utf8");
await fs.writeFile(metaPath, `${JSON.stringify(headerMeta, null, 2)}\n`, "utf8");
console.log(`Saved auth state to ${statePath}`);
console.log(`Saved session metadata to ${metaPath}`);
return;
}
throw new Error(`Timed out waiting for an authenticated Oracle DV page after ${timeoutMs}ms.`);
} finally {
context.off("request", requestListener);
await context.close().catch(() => {});
}
}
const entryUrl = process.argv[1] ? pathToFileURL(path.resolve(process.argv[1])).href : null;
if (import.meta.url === entryUrl) {
main().catch((error) => {
console.error(error.message);
process.exitCode = 1;
});
}