This commit is contained in:
@@ -72,9 +72,50 @@ const normalize = (value) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract tokens via better-sqlite3 (bundled dependency).
|
||||||
|
* This is the preferred strategy — no external CLI required.
|
||||||
|
*/
|
||||||
|
function extractTokensViaBetterSqlite(dbPath) {
|
||||||
|
// Dynamic require so the route stays importable even if native bindings fail
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
|
const Database = require("better-sqlite3");
|
||||||
|
const db = new Database(dbPath, { readonly: true, fileMustExist: true });
|
||||||
|
|
||||||
|
const query = (key) => {
|
||||||
|
const row = db.prepare("SELECT value FROM itemTable WHERE key=? LIMIT 1").get(key);
|
||||||
|
return row?.value || null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const normalize = (value) => {
|
||||||
|
if (typeof value !== "string") return value;
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(value);
|
||||||
|
return typeof parsed === "string" ? parsed : value;
|
||||||
|
} catch {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let accessToken = null;
|
||||||
|
for (const key of ACCESS_TOKEN_KEYS) {
|
||||||
|
const raw = query(key);
|
||||||
|
if (raw) { accessToken = normalize(raw); break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
let machineId = null;
|
||||||
|
for (const key of MACHINE_ID_KEYS) {
|
||||||
|
const raw = query(key);
|
||||||
|
if (raw) { machineId = normalize(raw); break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
db.close();
|
||||||
|
return { accessToken, machineId };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract tokens via sqlite3 CLI.
|
* Extract tokens via sqlite3 CLI.
|
||||||
* Keeps the route build-safe by avoiding optional sql.js bundling.
|
* Fallback when better-sqlite3 native bindings are unavailable.
|
||||||
*/
|
*/
|
||||||
async function extractTokensViaCLI(dbPath) {
|
async function extractTokensViaCLI(dbPath) {
|
||||||
const normalize = (raw) => {
|
const normalize = (raw) => {
|
||||||
@@ -131,7 +172,7 @@ async function extractTokensViaCLI(dbPath) {
|
|||||||
/**
|
/**
|
||||||
* GET /api/oauth/cursor/auto-import
|
* GET /api/oauth/cursor/auto-import
|
||||||
* Auto-detect and extract Cursor tokens from local SQLite database.
|
* Auto-detect and extract Cursor tokens from local SQLite database.
|
||||||
* Strategy: sqlite3 CLI → manual fallback
|
* Strategy: better-sqlite3 → sqlite3 CLI → manual fallback
|
||||||
*/
|
*/
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
try {
|
try {
|
||||||
@@ -177,7 +218,21 @@ export async function GET() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strategy 1: sqlite3 CLI
|
// Strategy 1: better-sqlite3 (bundled — no external tools required)
|
||||||
|
try {
|
||||||
|
const tokens = extractTokensViaBetterSqlite(dbPath);
|
||||||
|
if (tokens.accessToken && tokens.machineId) {
|
||||||
|
return NextResponse.json({
|
||||||
|
found: true,
|
||||||
|
accessToken: tokens.accessToken,
|
||||||
|
machineId: tokens.machineId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Native bindings unavailable — try CLI fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strategy 2: sqlite3 CLI
|
||||||
try {
|
try {
|
||||||
const tokens = await extractTokensViaCLI(dbPath);
|
const tokens = await extractTokensViaCLI(dbPath);
|
||||||
if (tokens.accessToken && tokens.machineId) {
|
if (tokens.accessToken && tokens.machineId) {
|
||||||
@@ -188,10 +243,10 @@ export async function GET() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// sqlite3 CLI not available
|
// sqlite3 CLI not available either
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strategy 2: ask user to paste manually
|
// Strategy 3: ask user to paste manually
|
||||||
return NextResponse.json({ found: false, windowsManual: true, dbPath });
|
return NextResponse.json({ found: false, windowsManual: true, dbPath });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Cursor auto-import error:", error);
|
console.log("Cursor auto-import error:", error);
|
||||||
|
|||||||
@@ -131,11 +131,8 @@ export default function CursorAuthModal({ isOpen, onSuccess, onClose }) {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-amber-700 dark:text-amber-300">
|
<p className="text-xs text-amber-700 dark:text-amber-300">
|
||||||
Run this command in your terminal, then click <strong>Retry</strong>:
|
Make sure Cursor IDE has been opened at least once, then click <strong>Retry</strong>. If the problem persists, paste your tokens manually below.
|
||||||
</p>
|
</p>
|
||||||
<pre className="text-xs bg-black/10 dark:bg-white/10 rounded p-2 font-mono select-all">
|
|
||||||
npm i better-sqlite3 -g
|
|
||||||
</pre>
|
|
||||||
<Button onClick={runAutoDetect} variant="outline" fullWidth>
|
<Button onClick={runAutoDetect} variant="outline" fullWidth>
|
||||||
Retry
|
Retry
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user