mcp-scraper 0.43.4 → 0.43.5
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/README.md +1 -1
- package/dist/bin/api-server.cjs +79 -25
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +1 -1
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +4 -4
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +3 -3
- package/dist/{chunk-FCFQ634B.js → chunk-5X7CJEK3.js} +25 -8
- package/dist/chunk-5X7CJEK3.js.map +1 -0
- package/dist/chunk-H4RPUFRR.js +7 -0
- package/dist/chunk-H4RPUFRR.js.map +1 -0
- package/dist/{chunk-ZBQ6EXZW.js → chunk-OVD4E4AP.js} +2 -2
- package/dist/{chunk-6TAQ2MXK.js → chunk-RJMOOII7.js} +2 -2
- package/dist/{chunk-SXLQZKWC.js → chunk-RSGUS5V6.js} +3 -3
- package/dist/{chunk-ZDVQARDQ.js → chunk-T5AFM4G5.js} +2 -2
- package/dist/{chunk-QOWBJ4YY.js → chunk-WT2UHDSE.js} +2 -2
- package/dist/{chunk-GUI33Q27.js → chunk-WWIJ2NID.js} +2 -2
- package/dist/{db-C5ELI55I.js → db-4ABEYNDM.js} +4 -2
- package/dist/{extract-bundle-IOM45SFL.js → extract-bundle-ITPFWRNI.js} +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/{location-data-repository-SHEOIBTL.js → location-data-repository-HDNCU4Z4.js} +3 -3
- package/dist/{server-K76DL4S7.js → server-BTDXZA5U.js} +68 -31
- package/dist/{server-K76DL4S7.js.map → server-BTDXZA5U.js.map} +1 -1
- package/dist/{site-extract-repository-XNI4ZK2M.js → site-extract-repository-CKCJDP7N.js} +3 -3
- package/dist/{worker-OB6WSWOD.js → worker-73AYU4IK.js} +5 -5
- package/package.json +2 -1
- package/dist/chunk-FCFQ634B.js.map +0 -1
- package/dist/chunk-XQIVXIAL.js +0 -7
- package/dist/chunk-XQIVXIAL.js.map +0 -1
- /package/dist/{chunk-ZBQ6EXZW.js.map → chunk-OVD4E4AP.js.map} +0 -0
- /package/dist/{chunk-6TAQ2MXK.js.map → chunk-RJMOOII7.js.map} +0 -0
- /package/dist/{chunk-SXLQZKWC.js.map → chunk-RSGUS5V6.js.map} +0 -0
- /package/dist/{chunk-ZDVQARDQ.js.map → chunk-T5AFM4G5.js.map} +0 -0
- /package/dist/{chunk-QOWBJ4YY.js.map → chunk-WT2UHDSE.js.map} +0 -0
- /package/dist/{chunk-GUI33Q27.js.map → chunk-WWIJ2NID.js.map} +0 -0
- /package/dist/{db-C5ELI55I.js.map → db-4ABEYNDM.js.map} +0 -0
- /package/dist/{extract-bundle-IOM45SFL.js.map → extract-bundle-ITPFWRNI.js.map} +0 -0
- /package/dist/{location-data-repository-SHEOIBTL.js.map → location-data-repository-HDNCU4Z4.js.map} +0 -0
- /package/dist/{site-extract-repository-XNI4ZK2M.js.map → site-extract-repository-CKCJDP7N.js.map} +0 -0
- /package/dist/{worker-OB6WSWOD.js.map → worker-73AYU4IK.js.map} +0 -0
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ Build the branded one-click bundle:
|
|
|
90
90
|
npm run build:mcpb
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.43.
|
|
93
|
+
The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.43.5`, SHA-256 `2c70cc4490f44d78f6803ab2e2b2e2fcdde72949532be053192744815bebe2aa`). Install it by opening or dragging it into Claude Desktop. Claude displays the `MCP Scraper` install card, icon, and API-key configuration field from the bundle manifest.
|
|
94
94
|
|
|
95
95
|
The MCPB install exposes every tool — web-intelligence plus all `browser_*` tools — through the one `mcp-scraper` server.
|
|
96
96
|
|
package/dist/bin/api-server.cjs
CHANGED
|
@@ -3671,6 +3671,7 @@ __export(db_exports, {
|
|
|
3671
3671
|
CORE_SCHEMA_VERSION: () => CORE_SCHEMA_VERSION,
|
|
3672
3672
|
CREDIT_LOTS_EPOCH: () => CREDIT_LOTS_EPOCH,
|
|
3673
3673
|
CREDIT_LOT_TTL: () => CREDIT_LOT_TTL,
|
|
3674
|
+
SITE_EXTRACT_COUNTER_REPAIR_VERSION: () => SITE_EXTRACT_COUNTER_REPAIR_VERSION,
|
|
3674
3675
|
SiteAuditJobRowSchema: () => SiteAuditJobRowSchema,
|
|
3675
3676
|
SiteAuditPhaseLogRowSchema: () => SiteAuditPhaseLogRowSchema,
|
|
3676
3677
|
advanceWorkflowRunStep: () => advanceWorkflowRunStep,
|
|
@@ -3808,7 +3809,7 @@ async function hasCurrentCoreSchema(db) {
|
|
|
3808
3809
|
const result = await db.execute(`SELECT ${checks.join(" AND ")} AS ready`);
|
|
3809
3810
|
return Number(result.rows[0]?.ready ?? 0) === 1;
|
|
3810
3811
|
}
|
|
3811
|
-
async function
|
|
3812
|
+
async function runSiteExtractCounterRepair(db) {
|
|
3812
3813
|
await db.execute(`
|
|
3813
3814
|
UPDATE site_extract_jobs SET
|
|
3814
3815
|
attempted_urls = done_urls,
|
|
@@ -3848,6 +3849,18 @@ async function runIdempotentCoreDataBackfills(db) {
|
|
|
3848
3849
|
AND failed_urls = 0
|
|
3849
3850
|
`);
|
|
3850
3851
|
}
|
|
3852
|
+
async function runPendingDataRepairs(db) {
|
|
3853
|
+
const applied = await db.execute({
|
|
3854
|
+
sql: "SELECT 1 AS applied FROM schema_migrations WHERE version = ? LIMIT 1",
|
|
3855
|
+
args: [SITE_EXTRACT_COUNTER_REPAIR_VERSION]
|
|
3856
|
+
});
|
|
3857
|
+
if (applied.rows.length > 0) return;
|
|
3858
|
+
await runSiteExtractCounterRepair(db);
|
|
3859
|
+
await db.execute({
|
|
3860
|
+
sql: "INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",
|
|
3861
|
+
args: [SITE_EXTRACT_COUNTER_REPAIR_VERSION]
|
|
3862
|
+
});
|
|
3863
|
+
}
|
|
3851
3864
|
function getDb() {
|
|
3852
3865
|
if (!_db) _db = (0, import_http.createClient)({ url: DB_URL, authToken: DB_TOKEN });
|
|
3853
3866
|
return _db;
|
|
@@ -3855,7 +3868,7 @@ function getDb() {
|
|
|
3855
3868
|
function setDbForTesting(client2) {
|
|
3856
3869
|
_db = client2;
|
|
3857
3870
|
}
|
|
3858
|
-
async function migrate() {
|
|
3871
|
+
async function migrate(options = {}) {
|
|
3859
3872
|
const db = getDb();
|
|
3860
3873
|
let applied;
|
|
3861
3874
|
try {
|
|
@@ -3874,12 +3887,15 @@ async function migrate() {
|
|
|
3874
3887
|
`);
|
|
3875
3888
|
applied = { rows: [] };
|
|
3876
3889
|
}
|
|
3877
|
-
if (applied.rows.length > 0
|
|
3878
|
-
|
|
3879
|
-
|
|
3890
|
+
if (applied.rows.length > 0) {
|
|
3891
|
+
if (!options.verifyCurrentSchema) return;
|
|
3892
|
+
if (await hasCurrentCoreSchema(db)) {
|
|
3893
|
+
if (options.runDataRepairs) await runPendingDataRepairs(db);
|
|
3894
|
+
return;
|
|
3895
|
+
}
|
|
3880
3896
|
}
|
|
3881
3897
|
if (await hasCurrentCoreSchema(db)) {
|
|
3882
|
-
await
|
|
3898
|
+
await runPendingDataRepairs(db);
|
|
3883
3899
|
await db.execute({
|
|
3884
3900
|
sql: "INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",
|
|
3885
3901
|
args: [CORE_SCHEMA_VERSION]
|
|
@@ -4692,7 +4708,7 @@ async function migrate() {
|
|
|
4692
4708
|
if (!await hasCurrentCoreSchema(db)) {
|
|
4693
4709
|
throw new Error("core schema migration finished without all required tables, indexes, and columns");
|
|
4694
4710
|
}
|
|
4695
|
-
await
|
|
4711
|
+
await runPendingDataRepairs(db);
|
|
4696
4712
|
await db.execute({
|
|
4697
4713
|
sql: "INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)",
|
|
4698
4714
|
args: [CORE_SCHEMA_VERSION]
|
|
@@ -6666,7 +6682,7 @@ async function listActiveUserIds() {
|
|
|
6666
6682
|
const res = await getDb().execute("SELECT id FROM users WHERE active = 1");
|
|
6667
6683
|
return res.rows.map((r) => Number(r.id));
|
|
6668
6684
|
}
|
|
6669
|
-
var import_http, import_node_crypto, import_zod, DB_URL, DB_TOKEN, _db, _rateLimitSchemaReady, CORE_SCHEMA_VERSION, CORE_SCHEMA_TABLES, CORE_SCHEMA_INDEXES, CORE_SCHEMA_TRIGGERS, CORE_SCHEMA_COLUMNS, REQUEST_EVENT_RESULT_MAX_BYTES, CREDIT_LOT_TTL, SiteAuditJobRowSchema, SiteAuditPhaseLogRowSchema;
|
|
6685
|
+
var import_http, import_node_crypto, import_zod, DB_URL, DB_TOKEN, _db, _rateLimitSchemaReady, CORE_SCHEMA_VERSION, SITE_EXTRACT_COUNTER_REPAIR_VERSION, CORE_SCHEMA_TABLES, CORE_SCHEMA_INDEXES, CORE_SCHEMA_TRIGGERS, CORE_SCHEMA_COLUMNS, REQUEST_EVENT_RESULT_MAX_BYTES, CREDIT_LOT_TTL, SiteAuditJobRowSchema, SiteAuditPhaseLogRowSchema;
|
|
6670
6686
|
var init_db = __esm({
|
|
6671
6687
|
"src/api/db.ts"() {
|
|
6672
6688
|
"use strict";
|
|
@@ -6680,6 +6696,7 @@ var init_db = __esm({
|
|
|
6680
6696
|
_db = null;
|
|
6681
6697
|
_rateLimitSchemaReady = false;
|
|
6682
6698
|
CORE_SCHEMA_VERSION = "2026-07-30.1";
|
|
6699
|
+
SITE_EXTRACT_COUNTER_REPAIR_VERSION = "data-2026-07-28-site-extract-counters.1";
|
|
6683
6700
|
CORE_SCHEMA_TABLES = [
|
|
6684
6701
|
"admin_credit_adjustment_events",
|
|
6685
6702
|
"admin_credit_adjustments",
|
|
@@ -39517,7 +39534,7 @@ var PACKAGE_VERSION;
|
|
|
39517
39534
|
var init_version = __esm({
|
|
39518
39535
|
"src/version.ts"() {
|
|
39519
39536
|
"use strict";
|
|
39520
|
-
PACKAGE_VERSION = "0.43.
|
|
39537
|
+
PACKAGE_VERSION = "0.43.5";
|
|
39521
39538
|
}
|
|
39522
39539
|
});
|
|
39523
39540
|
|
|
@@ -52096,6 +52113,22 @@ function isScraperResource(resource) {
|
|
|
52096
52113
|
if (!resource) return false;
|
|
52097
52114
|
return resource.replace(/\/$/, "") === SCRAPER_RESOURCE();
|
|
52098
52115
|
}
|
|
52116
|
+
async function withOAuthDatabaseDeadline(stage, operation, timeoutMs = OAUTH_DATABASE_TIMEOUT_MS) {
|
|
52117
|
+
const startedAt = Date.now();
|
|
52118
|
+
let timeout;
|
|
52119
|
+
try {
|
|
52120
|
+
const value = await Promise.race([
|
|
52121
|
+
operation,
|
|
52122
|
+
new Promise((_, reject) => {
|
|
52123
|
+
timeout = setTimeout(() => reject(new OAuthDatabaseUnavailableError(stage)), timeoutMs);
|
|
52124
|
+
})
|
|
52125
|
+
]);
|
|
52126
|
+
console.log("[oauth-db] stage=%s status=ok duration_ms=%d", stage, Date.now() - startedAt);
|
|
52127
|
+
return value;
|
|
52128
|
+
} finally {
|
|
52129
|
+
if (timeout) clearTimeout(timeout);
|
|
52130
|
+
}
|
|
52131
|
+
}
|
|
52099
52132
|
async function getKeys() {
|
|
52100
52133
|
if (cachedKeys) return cachedKeys;
|
|
52101
52134
|
const raw = process.env.OAUTH_SIGNING_KEY;
|
|
@@ -52149,7 +52182,7 @@ async function sessionUser(token4) {
|
|
|
52149
52182
|
if (!token4) return null;
|
|
52150
52183
|
const userId = verifySession(token4);
|
|
52151
52184
|
if (!userId) return null;
|
|
52152
|
-
const user = await getUserById(userId);
|
|
52185
|
+
const user = await withOAuthDatabaseDeadline("session-user", getUserById(userId));
|
|
52153
52186
|
return user ?? null;
|
|
52154
52187
|
}
|
|
52155
52188
|
function escapeHtml2(value) {
|
|
@@ -52274,7 +52307,7 @@ function parseAuthParams(get) {
|
|
|
52274
52307
|
async function validateAuthRequest(p) {
|
|
52275
52308
|
if (p.response_type !== "code") return { ok: false, status: 400, message: "response_type must be code" };
|
|
52276
52309
|
if (!p.client_id) return { ok: false, status: 400, message: "client_id is required" };
|
|
52277
|
-
const client2 = await getClient(p.client_id);
|
|
52310
|
+
const client2 = await withOAuthDatabaseDeadline("get-client", getClient(p.client_id));
|
|
52278
52311
|
if (!client2) return { ok: false, status: 400, message: "unknown client_id" };
|
|
52279
52312
|
if (!p.redirect_uri || !client2.redirect_uris.includes(p.redirect_uri)) return { ok: false, status: 400, message: "redirect_uri does not match the registered set" };
|
|
52280
52313
|
if (!isAllowedRedirect(p.redirect_uri)) return { ok: false, status: 400, message: "redirect_uri host not allowed" };
|
|
@@ -52293,7 +52326,7 @@ async function mintAccessToken(identity, scope, plan, audience) {
|
|
|
52293
52326
|
function tokenErrorResponse(c, error, description, status) {
|
|
52294
52327
|
return c.json({ error, error_description: description }, status);
|
|
52295
52328
|
}
|
|
52296
|
-
var import_hono23, import_cookie, import_node_crypto28, import_jose2, ISSUER, RESOURCE, SCRAPER_RESOURCE, MEMORY_SCOPES, SCRAPER_SCOPES, SUPPORTED_SCOPES, ACCESS_TTL_SECONDS, REFRESH_TTL_SECONDS, CODE_TTL_SECONDS, ROTATION_GRACE_SECONDS, secureCookies, sessionCookieOptions, cachedKeys, oauthApp;
|
|
52329
|
+
var import_hono23, import_cookie, import_node_crypto28, import_jose2, ISSUER, RESOURCE, SCRAPER_RESOURCE, MEMORY_SCOPES, SCRAPER_SCOPES, SUPPORTED_SCOPES, ACCESS_TTL_SECONDS, REFRESH_TTL_SECONDS, CODE_TTL_SECONDS, ROTATION_GRACE_SECONDS, OAUTH_DATABASE_TIMEOUT_MS, OAuthDatabaseUnavailableError, secureCookies, sessionCookieOptions, cachedKeys, oauthApp;
|
|
52297
52330
|
var init_oauth_routes = __esm({
|
|
52298
52331
|
"src/api/oauth-routes.ts"() {
|
|
52299
52332
|
"use strict";
|
|
@@ -52315,6 +52348,15 @@ var init_oauth_routes = __esm({
|
|
|
52315
52348
|
REFRESH_TTL_SECONDS = 60 * 60 * 24 * 30;
|
|
52316
52349
|
CODE_TTL_SECONDS = 60;
|
|
52317
52350
|
ROTATION_GRACE_SECONDS = 120;
|
|
52351
|
+
OAUTH_DATABASE_TIMEOUT_MS = 5e3;
|
|
52352
|
+
OAuthDatabaseUnavailableError = class extends Error {
|
|
52353
|
+
stage;
|
|
52354
|
+
constructor(stage) {
|
|
52355
|
+
super("The authorization service database is temporarily unavailable.");
|
|
52356
|
+
this.name = "OAuthDatabaseUnavailableError";
|
|
52357
|
+
this.stage = stage;
|
|
52358
|
+
}
|
|
52359
|
+
};
|
|
52318
52360
|
secureCookies = process.env.NODE_ENV === "production" || process.env.VERCEL === "1";
|
|
52319
52361
|
sessionCookieOptions = {
|
|
52320
52362
|
httpOnly: true,
|
|
@@ -52325,6 +52367,18 @@ var init_oauth_routes = __esm({
|
|
|
52325
52367
|
};
|
|
52326
52368
|
cachedKeys = null;
|
|
52327
52369
|
oauthApp = new import_hono23.Hono();
|
|
52370
|
+
oauthApp.onError((error, c) => {
|
|
52371
|
+
if (error instanceof OAuthDatabaseUnavailableError) {
|
|
52372
|
+
console.error("[oauth-db] stage=%s status=timeout timeout_ms=%d", error.stage, OAUTH_DATABASE_TIMEOUT_MS);
|
|
52373
|
+
c.header("Retry-After", "5");
|
|
52374
|
+
return c.json({
|
|
52375
|
+
error: "temporarily_unavailable",
|
|
52376
|
+
error_description: "Authorization is temporarily unavailable. Please retry shortly."
|
|
52377
|
+
}, 503);
|
|
52378
|
+
}
|
|
52379
|
+
console.error("[oauth] unhandled error:", error);
|
|
52380
|
+
return c.json({ error: "server_error", error_description: "Authorization could not be completed." }, 500);
|
|
52381
|
+
});
|
|
52328
52382
|
oauthApp.use("*", async (c, next) => {
|
|
52329
52383
|
c.header("Access-Control-Allow-Origin", "*");
|
|
52330
52384
|
c.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
@@ -52386,7 +52440,7 @@ var init_oauth_routes = __esm({
|
|
|
52386
52440
|
}
|
|
52387
52441
|
const clientName = typeof body.client_name === "string" ? body.client_name : null;
|
|
52388
52442
|
const clientId = `client_${(0, import_node_crypto28.randomBytes)(16).toString("hex")}`;
|
|
52389
|
-
await registerClient(clientId, redirectUris, clientName);
|
|
52443
|
+
await withOAuthDatabaseDeadline("register-client", registerClient(clientId, redirectUris, clientName));
|
|
52390
52444
|
console.log("[oauth-dcr] register OK client_id=%s redirect_uris=%s", clientId, JSON.stringify(redirectUris));
|
|
52391
52445
|
return c.json({
|
|
52392
52446
|
client_id: clientId,
|
|
@@ -52424,7 +52478,7 @@ var init_oauth_routes = __esm({
|
|
|
52424
52478
|
if (action === "login") {
|
|
52425
52479
|
const email = (get("email") ?? "").trim().toLowerCase();
|
|
52426
52480
|
const password = get("password") ?? "";
|
|
52427
|
-
const user2 = email ? await getUserByEmail(email) : void 0;
|
|
52481
|
+
const user2 = email ? await withOAuthDatabaseDeadline("login-user", getUserByEmail(email)) : void 0;
|
|
52428
52482
|
const okPw = !!(user2 && user2.password_hash && verifyPassword(password, user2.password_hash));
|
|
52429
52483
|
console.log("[oauth-dcr] LOGIN email=%s found=%s hasHash=%s pwLen=%d ok=%s", email, !!user2, !!(user2 && user2.password_hash), password.length, okPw);
|
|
52430
52484
|
if (!okPw) {
|
|
@@ -52440,7 +52494,7 @@ var init_oauth_routes = __esm({
|
|
|
52440
52494
|
const scope = negotiateScope(p.scope, user, p.resource);
|
|
52441
52495
|
const code = `code_${(0, import_node_crypto28.randomBytes)(32).toString("base64url")}`;
|
|
52442
52496
|
const expiresAt = new Date(Date.now() + CODE_TTL_SECONDS * 1e3).toISOString();
|
|
52443
|
-
await putCode({
|
|
52497
|
+
await withOAuthDatabaseDeadline("put-authorization-code", putCode({
|
|
52444
52498
|
code,
|
|
52445
52499
|
client_id: p.client_id,
|
|
52446
52500
|
redirect_uri: p.redirect_uri,
|
|
@@ -52449,7 +52503,7 @@ var init_oauth_routes = __esm({
|
|
|
52449
52503
|
scope,
|
|
52450
52504
|
resource: p.resource || RESOURCE(),
|
|
52451
52505
|
expires_at: expiresAt
|
|
52452
|
-
});
|
|
52506
|
+
}));
|
|
52453
52507
|
const u = new URL(p.redirect_uri);
|
|
52454
52508
|
u.searchParams.set("code", code);
|
|
52455
52509
|
if (p.state) u.searchParams.set("state", p.state);
|
|
@@ -52467,18 +52521,18 @@ var init_oauth_routes = __esm({
|
|
|
52467
52521
|
const clientId = get("client_id") ?? "";
|
|
52468
52522
|
const redirectUri = get("redirect_uri") ?? "";
|
|
52469
52523
|
const verifier = get("code_verifier") ?? "";
|
|
52470
|
-
const record = await consumeCode(code);
|
|
52524
|
+
const record = await withOAuthDatabaseDeadline("consume-authorization-code", consumeCode(code));
|
|
52471
52525
|
if (!record) return tokenErrorResponse(c, "invalid_grant", "Authorization code is invalid or already used", 400);
|
|
52472
52526
|
if (new Date(record.expires_at).getTime() < Date.now()) return tokenErrorResponse(c, "invalid_grant", "Authorization code has expired", 400);
|
|
52473
52527
|
if (record.client_id !== clientId) return tokenErrorResponse(c, "invalid_grant", "client_id mismatch", 400);
|
|
52474
52528
|
if (record.redirect_uri !== redirectUri) return tokenErrorResponse(c, "invalid_grant", "redirect_uri mismatch", 400);
|
|
52475
52529
|
if (!pkceMatches(verifier, record.code_challenge)) return tokenErrorResponse(c, "invalid_grant", "PKCE verification failed", 400);
|
|
52476
|
-
const user = await getUserByEmail(record.identity);
|
|
52530
|
+
const user = await withOAuthDatabaseDeadline("token-user", getUserByEmail(record.identity));
|
|
52477
52531
|
const plan = user ? resolvePlan(user) : "free";
|
|
52478
52532
|
const audience = record.resource ?? RESOURCE();
|
|
52479
52533
|
const accessToken = await mintAccessToken(record.identity, record.scope, plan, audience);
|
|
52480
52534
|
const refreshToken = `rt_${(0, import_node_crypto28.randomBytes)(40).toString("base64url")}`;
|
|
52481
|
-
await putRefresh({
|
|
52535
|
+
await withOAuthDatabaseDeadline("put-refresh-token", putRefresh({
|
|
52482
52536
|
refresh_token: refreshToken,
|
|
52483
52537
|
client_id: clientId,
|
|
52484
52538
|
identity: record.identity,
|
|
@@ -52486,15 +52540,15 @@ var init_oauth_routes = __esm({
|
|
|
52486
52540
|
resource: audience,
|
|
52487
52541
|
expires_at: new Date(Date.now() + REFRESH_TTL_SECONDS * 1e3).toISOString(),
|
|
52488
52542
|
revoked: 0
|
|
52489
|
-
});
|
|
52543
|
+
}));
|
|
52490
52544
|
return c.json({ access_token: accessToken, token_type: "Bearer", expires_in: ACCESS_TTL_SECONDS, refresh_token: refreshToken, scope: record.scope });
|
|
52491
52545
|
}
|
|
52492
52546
|
if (grantType === "refresh_token") {
|
|
52493
52547
|
const refreshToken = get("refresh_token") ?? "";
|
|
52494
52548
|
const clientId = get("client_id") ?? "";
|
|
52495
|
-
const record = await getRefresh(refreshToken);
|
|
52549
|
+
const record = await withOAuthDatabaseDeadline("get-refresh-token", getRefresh(refreshToken));
|
|
52496
52550
|
if (record && record.revoked && record.replaced_by && record.rotated_at && Date.now() - new Date(record.rotated_at).getTime() < ROTATION_GRACE_SECONDS * 1e3 && (!clientId || record.client_id === clientId)) {
|
|
52497
|
-
const graceUser = await getUserByEmail(record.identity);
|
|
52551
|
+
const graceUser = await withOAuthDatabaseDeadline("refresh-grace-user", getUserByEmail(record.identity));
|
|
52498
52552
|
const gracePlan = graceUser ? resolvePlan(graceUser) : "free";
|
|
52499
52553
|
const graceAudience = record.resource ?? RESOURCE();
|
|
52500
52554
|
const graceAccess = await mintAccessToken(record.identity, record.scope, gracePlan, graceAudience);
|
|
@@ -52503,12 +52557,12 @@ var init_oauth_routes = __esm({
|
|
|
52503
52557
|
if (!record || record.revoked) return tokenErrorResponse(c, "invalid_grant", "Refresh token is invalid or revoked", 400);
|
|
52504
52558
|
if (new Date(record.expires_at).getTime() < Date.now()) return tokenErrorResponse(c, "invalid_grant", "Refresh token has expired", 400);
|
|
52505
52559
|
if (clientId && record.client_id !== clientId) return tokenErrorResponse(c, "invalid_grant", "client_id mismatch", 400);
|
|
52506
|
-
const user = await getUserByEmail(record.identity);
|
|
52560
|
+
const user = await withOAuthDatabaseDeadline("refresh-user", getUserByEmail(record.identity));
|
|
52507
52561
|
const plan = user ? resolvePlan(user) : "free";
|
|
52508
52562
|
const audience = record.resource ?? RESOURCE();
|
|
52509
52563
|
const accessToken = await mintAccessToken(record.identity, record.scope, plan, audience);
|
|
52510
52564
|
const nextRefresh = `rt_${(0, import_node_crypto28.randomBytes)(40).toString("base64url")}`;
|
|
52511
|
-
await rotateRefresh(refreshToken, {
|
|
52565
|
+
await withOAuthDatabaseDeadline("rotate-refresh-token", rotateRefresh(refreshToken, {
|
|
52512
52566
|
refresh_token: nextRefresh,
|
|
52513
52567
|
client_id: record.client_id,
|
|
52514
52568
|
identity: record.identity,
|
|
@@ -52516,7 +52570,7 @@ var init_oauth_routes = __esm({
|
|
|
52516
52570
|
resource: audience,
|
|
52517
52571
|
expires_at: new Date(Date.now() + REFRESH_TTL_SECONDS * 1e3).toISOString(),
|
|
52518
52572
|
revoked: 0
|
|
52519
|
-
});
|
|
52573
|
+
}));
|
|
52520
52574
|
return c.json({ access_token: accessToken, token_type: "Bearer", expires_in: ACCESS_TTL_SECONDS, refresh_token: nextRefresh, scope: record.scope });
|
|
52521
52575
|
}
|
|
52522
52576
|
return tokenErrorResponse(c, "unsupported_grant_type", "grant_type must be authorization_code or refresh_token", 400);
|