mcp-scraper 0.36.0 → 0.37.0
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 +766 -168
- 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 +52 -8
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +5 -5
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +3 -3
- package/dist/chunk-3LWYPAU5.js +7 -0
- package/dist/chunk-3LWYPAU5.js.map +1 -0
- package/dist/{chunk-IFYER7O4.js → chunk-CSCD2HNS.js} +132 -2
- package/dist/chunk-CSCD2HNS.js.map +1 -0
- package/dist/{chunk-D7LM5QZN.js → chunk-FSAXLDB3.js} +2 -2
- package/dist/{chunk-5RULXBJ7.js → chunk-JK2FRDAP.js} +55 -11
- package/dist/{chunk-5RULXBJ7.js.map → chunk-JK2FRDAP.js.map} +1 -1
- package/dist/{chunk-ANCGXUQJ.js → chunk-LOPKN3YL.js} +2 -2
- package/dist/{chunk-E5UEELA7.js → chunk-MA5JBAUZ.js} +2 -2
- package/dist/{chunk-AN3VQARU.js → chunk-PUJFYJXB.js} +2 -2
- package/dist/{chunk-4ZIJ3BKZ.js → chunk-PWPUKR5U.js} +4 -2
- package/dist/{chunk-4ZIJ3BKZ.js.map → chunk-PWPUKR5U.js.map} +1 -1
- package/dist/{chunk-O2MCWFXQ.js → chunk-Q35WZJJK.js} +3 -3
- package/dist/{db-N6MPVMEF.js → db-N3YECFWR.js} +6 -2
- package/dist/{extract-bundle-M4SDJG3V.js → extract-bundle-346R6MXD.js} +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/{location-data-repository-Z4NQOU5Y.js → location-data-repository-O2VII3ON.js} +3 -3
- package/dist/{server-ZIGAFKOL.js → server-QKDDEBVQ.js} +500 -99
- package/dist/server-QKDDEBVQ.js.map +1 -0
- package/dist/{site-extract-repository-PGQZNW6V.js → site-extract-repository-I3VM6WXN.js} +4 -4
- package/dist/{worker-EBB6CTGW.js → worker-TTFXPPDK.js} +6 -6
- package/docs/mcp-tool-manifest.generated.json +182 -6
- package/package.json +2 -2
- package/dist/chunk-4HO66323.js +0 -7
- package/dist/chunk-4HO66323.js.map +0 -1
- package/dist/chunk-IFYER7O4.js.map +0 -1
- package/dist/server-ZIGAFKOL.js.map +0 -1
- /package/dist/{chunk-D7LM5QZN.js.map → chunk-FSAXLDB3.js.map} +0 -0
- /package/dist/{chunk-ANCGXUQJ.js.map → chunk-LOPKN3YL.js.map} +0 -0
- /package/dist/{chunk-E5UEELA7.js.map → chunk-MA5JBAUZ.js.map} +0 -0
- /package/dist/{chunk-AN3VQARU.js.map → chunk-PUJFYJXB.js.map} +0 -0
- /package/dist/{chunk-O2MCWFXQ.js.map → chunk-Q35WZJJK.js.map} +0 -0
- /package/dist/{db-N6MPVMEF.js.map → db-N3YECFWR.js.map} +0 -0
- /package/dist/{extract-bundle-M4SDJG3V.js.map → extract-bundle-346R6MXD.js.map} +0 -0
- /package/dist/{location-data-repository-Z4NQOU5Y.js.map → location-data-repository-O2VII3ON.js.map} +0 -0
- /package/dist/{site-extract-repository-PGQZNW6V.js.map → site-extract-repository-I3VM6WXN.js.map} +0 -0
- /package/dist/{worker-EBB6CTGW.js.map → worker-TTFXPPDK.js.map} +0 -0
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
importHostedCensusPlacesCsv,
|
|
10
10
|
importHostedZipGroupsCsv,
|
|
11
11
|
listActiveHostedLocationDatasets
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-PUJFYJXB.js";
|
|
13
13
|
import {
|
|
14
14
|
classifyHarvestProblem,
|
|
15
15
|
createHarvestAttemptRecorder,
|
|
16
16
|
harvestProblemResponse,
|
|
17
17
|
serializeHarvestProblem
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-FSAXLDB3.js";
|
|
19
19
|
import {
|
|
20
20
|
BACKUP_LAST_RESORT_ATTEMPTS,
|
|
21
21
|
BrowserDriver,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
resolveBackupKernelProxyId,
|
|
30
30
|
resolveKernelProxyId,
|
|
31
31
|
serpArrivalUrl
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-LOPKN3YL.js";
|
|
33
33
|
import {
|
|
34
34
|
HttpMcpToolExecutor,
|
|
35
35
|
WIZPER_LANGUAGES,
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
sanitizeAttempts,
|
|
57
57
|
sanitizeHarvestResult,
|
|
58
58
|
transcribeMediaUrl
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-JK2FRDAP.js";
|
|
60
60
|
import {
|
|
61
61
|
auditImageUrls,
|
|
62
62
|
auditImages,
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
recordKernelSession,
|
|
75
75
|
recordVendorUsage,
|
|
76
76
|
runWithCostContext
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-MA5JBAUZ.js";
|
|
78
78
|
import {
|
|
79
79
|
listWorkflowDefinitions,
|
|
80
80
|
runWorkflow,
|
|
@@ -101,7 +101,7 @@ import {
|
|
|
101
101
|
RawMapsOverviewSchema,
|
|
102
102
|
RawMapsReviewStatsSchema
|
|
103
103
|
} from "./chunk-CB5C3BPB.js";
|
|
104
|
-
import "./chunk-
|
|
104
|
+
import "./chunk-3LWYPAU5.js";
|
|
105
105
|
import {
|
|
106
106
|
abandonExtractSettlement,
|
|
107
107
|
countSuccessfulPages,
|
|
@@ -124,7 +124,7 @@ import {
|
|
|
124
124
|
setExtractJobTotal,
|
|
125
125
|
settleExtractJob,
|
|
126
126
|
terminalExtractJobStatus
|
|
127
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-Q35WZJJK.js";
|
|
128
128
|
import {
|
|
129
129
|
BROWSER_OPEN_MIN_BALANCE_MC,
|
|
130
130
|
CONCURRENCY_PRICE_ID,
|
|
@@ -169,7 +169,7 @@ import {
|
|
|
169
169
|
tierBillingInterval,
|
|
170
170
|
tierCreditsPerInterval,
|
|
171
171
|
vendorCostUsdToMc
|
|
172
|
-
} from "./chunk-
|
|
172
|
+
} from "./chunk-PWPUKR5U.js";
|
|
173
173
|
import {
|
|
174
174
|
CaptchaError,
|
|
175
175
|
ExtractionError,
|
|
@@ -195,6 +195,7 @@ import {
|
|
|
195
195
|
createWorkflowRun,
|
|
196
196
|
createWorkflowSchedule,
|
|
197
197
|
creditMc,
|
|
198
|
+
creditMcIdempotent,
|
|
198
199
|
deactivateUser,
|
|
199
200
|
debitMc,
|
|
200
201
|
debitMcIdempotent,
|
|
@@ -264,7 +265,7 @@ import {
|
|
|
264
265
|
softDeleteInboxMessage,
|
|
265
266
|
upsertPageSnapshot,
|
|
266
267
|
verifyPassword
|
|
267
|
-
} from "./chunk-
|
|
268
|
+
} from "./chunk-CSCD2HNS.js";
|
|
268
269
|
|
|
269
270
|
// src/blog/registry.ts
|
|
270
271
|
var posts = [
|
|
@@ -6186,7 +6187,7 @@ async function extractSite(opts) {
|
|
|
6186
6187
|
}
|
|
6187
6188
|
|
|
6188
6189
|
// src/api/server.ts
|
|
6189
|
-
import { Hono as
|
|
6190
|
+
import { Hono as Hono28 } from "hono";
|
|
6190
6191
|
import { serve as serveInngest } from "inngest/hono";
|
|
6191
6192
|
|
|
6192
6193
|
// src/inngest/client.ts
|
|
@@ -8594,7 +8595,7 @@ var siteExtractFn = inngest.createFunction(
|
|
|
8594
8595
|
});
|
|
8595
8596
|
}) : null;
|
|
8596
8597
|
const finalized = await step.run("finalize", async () => {
|
|
8597
|
-
const { assembleExtractArtifacts } = await import("./extract-bundle-
|
|
8598
|
+
const { assembleExtractArtifacts } = await import("./extract-bundle-346R6MXD.js");
|
|
8598
8599
|
const current = await getExtractJob(jobId2);
|
|
8599
8600
|
if (!current) throw new Error("extract job disappeared before finalization");
|
|
8600
8601
|
const stored = await assembleExtractArtifacts(current, { branding, imageAudit });
|
|
@@ -9507,7 +9508,7 @@ async function resolveUsZipsPath(requestedPath) {
|
|
|
9507
9508
|
async function loadZipGroups(stateAbbr, requestedPath, warnings, sourceMode) {
|
|
9508
9509
|
const mode = resolvedLocationDataMode({ zipSource: sourceMode });
|
|
9509
9510
|
if (mode === "hosted") {
|
|
9510
|
-
const { getHostedZipGroups } = await import("./location-data-repository-
|
|
9511
|
+
const { getHostedZipGroups } = await import("./location-data-repository-O2VII3ON.js");
|
|
9511
9512
|
const hosted = await getHostedZipGroups(stateAbbr);
|
|
9512
9513
|
if (!hosted.dataset) {
|
|
9513
9514
|
throw new DirectoryLocationError(
|
|
@@ -9570,7 +9571,7 @@ async function resolveDirectoryMarkets(options, config = {}) {
|
|
|
9570
9571
|
const sourceUrl = censusStateUrl(state.fips);
|
|
9571
9572
|
const warnings = [];
|
|
9572
9573
|
if (resolvedLocationDataMode(config) === "hosted") {
|
|
9573
|
-
const { queryHostedLocationMarkets } = await import("./location-data-repository-
|
|
9574
|
+
const { queryHostedLocationMarkets } = await import("./location-data-repository-O2VII3ON.js");
|
|
9574
9575
|
const hosted = await queryHostedLocationMarkets({
|
|
9575
9576
|
state: state.abbr,
|
|
9576
9577
|
minPopulation: options.minPopulation,
|
|
@@ -15960,8 +15961,409 @@ googleAdsApp.post("/transcribe", createApiKeyAuth(), async (c) => {
|
|
|
15960
15961
|
}
|
|
15961
15962
|
});
|
|
15962
15963
|
|
|
15963
|
-
// src/api/
|
|
15964
|
+
// src/api/admin-auth.ts
|
|
15965
|
+
import { createMiddleware as createMiddleware3 } from "hono/factory";
|
|
15966
|
+
var adminAuth = createMiddleware3(async (c, next) => {
|
|
15967
|
+
const configured = process.env.ADMIN_KEY?.trim();
|
|
15968
|
+
const key = c.req.header("x-admin-key")?.trim();
|
|
15969
|
+
if (!configured) return c.json({ error: "Admin access disabled" }, 503);
|
|
15970
|
+
if (!key || key !== configured) return c.json({ error: "Unauthorized" }, 401);
|
|
15971
|
+
return next();
|
|
15972
|
+
});
|
|
15973
|
+
|
|
15974
|
+
// src/api/admin-credit-routes.ts
|
|
15964
15975
|
import { Hono as Hono9 } from "hono";
|
|
15976
|
+
|
|
15977
|
+
// src/api/admin-credits.ts
|
|
15978
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
15979
|
+
var MIN_ADJUSTMENT_CREDITS = 1;
|
|
15980
|
+
var LARGE_ADJUSTMENT_CREDITS = 1e5;
|
|
15981
|
+
var MAX_ADJUSTMENT_CREDITS = 1e7;
|
|
15982
|
+
var MIN_REASON_LENGTH = 3;
|
|
15983
|
+
var MAX_REASON_LENGTH = 500;
|
|
15984
|
+
var MAX_ACTOR_LENGTH = 120;
|
|
15985
|
+
var AdminCreditError = class extends Error {
|
|
15986
|
+
constructor(status, message, detail) {
|
|
15987
|
+
super(message);
|
|
15988
|
+
this.status = status;
|
|
15989
|
+
this.detail = detail;
|
|
15990
|
+
this.name = "AdminCreditError";
|
|
15991
|
+
}
|
|
15992
|
+
status;
|
|
15993
|
+
detail;
|
|
15994
|
+
};
|
|
15995
|
+
function toCredits(mc) {
|
|
15996
|
+
return mc / MC_PER_CREDIT;
|
|
15997
|
+
}
|
|
15998
|
+
function creditsToMc(credits) {
|
|
15999
|
+
return Math.round(credits * MC_PER_CREDIT);
|
|
16000
|
+
}
|
|
16001
|
+
function validateCredits(credits, confirmLarge) {
|
|
16002
|
+
if (typeof credits !== "number" || !Number.isFinite(credits) || !Number.isInteger(credits)) {
|
|
16003
|
+
throw new AdminCreditError(400, "credits must be a whole number");
|
|
16004
|
+
}
|
|
16005
|
+
if (credits < MIN_ADJUSTMENT_CREDITS) {
|
|
16006
|
+
throw new AdminCreditError(400, `credits must be at least ${MIN_ADJUSTMENT_CREDITS}`);
|
|
16007
|
+
}
|
|
16008
|
+
if (credits > MAX_ADJUSTMENT_CREDITS) {
|
|
16009
|
+
throw new AdminCreditError(400, `credits exceeds the hard ceiling of ${MAX_ADJUSTMENT_CREDITS.toLocaleString()}`);
|
|
16010
|
+
}
|
|
16011
|
+
if (credits > LARGE_ADJUSTMENT_CREDITS && !confirmLarge) {
|
|
16012
|
+
throw new AdminCreditError(422, `adjustments over ${LARGE_ADJUSTMENT_CREDITS.toLocaleString()} credits require confirmLarge: true`, {
|
|
16013
|
+
credits,
|
|
16014
|
+
threshold: LARGE_ADJUSTMENT_CREDITS
|
|
16015
|
+
});
|
|
16016
|
+
}
|
|
16017
|
+
return credits;
|
|
16018
|
+
}
|
|
16019
|
+
function validateReason(reason) {
|
|
16020
|
+
const trimmed = typeof reason === "string" ? reason.trim() : "";
|
|
16021
|
+
if (trimmed.length < MIN_REASON_LENGTH) {
|
|
16022
|
+
throw new AdminCreditError(400, `reason must be at least ${MIN_REASON_LENGTH} characters`);
|
|
16023
|
+
}
|
|
16024
|
+
if (trimmed.length > MAX_REASON_LENGTH) {
|
|
16025
|
+
throw new AdminCreditError(400, `reason must be at most ${MAX_REASON_LENGTH} characters`);
|
|
16026
|
+
}
|
|
16027
|
+
return trimmed;
|
|
16028
|
+
}
|
|
16029
|
+
function validateActor(actor) {
|
|
16030
|
+
const trimmed = typeof actor === "string" ? actor.trim() : "";
|
|
16031
|
+
if (!trimmed) throw new AdminCreditError(400, "actor is required so the adjustment records who made it");
|
|
16032
|
+
if (trimmed.length > MAX_ACTOR_LENGTH) {
|
|
16033
|
+
throw new AdminCreditError(400, `actor must be at most ${MAX_ACTOR_LENGTH} characters`);
|
|
16034
|
+
}
|
|
16035
|
+
return trimmed;
|
|
16036
|
+
}
|
|
16037
|
+
function validateDirection(direction) {
|
|
16038
|
+
if (direction !== "grant" && direction !== "revoke") {
|
|
16039
|
+
throw new AdminCreditError(400, "direction must be either 'grant' or 'revoke'");
|
|
16040
|
+
}
|
|
16041
|
+
return direction;
|
|
16042
|
+
}
|
|
16043
|
+
async function resolveUser2(target) {
|
|
16044
|
+
const email = target.email?.trim().toLowerCase();
|
|
16045
|
+
if (!email && target.userId == null) {
|
|
16046
|
+
throw new AdminCreditError(400, "Provide either email or userId");
|
|
16047
|
+
}
|
|
16048
|
+
const user = email ? await getUserByEmail(email) : await getUserById(target.userId);
|
|
16049
|
+
if (user) return user;
|
|
16050
|
+
const probe = await getDb().execute(
|
|
16051
|
+
email ? { sql: "SELECT active FROM users WHERE email = ? LIMIT 1", args: [email] } : { sql: "SELECT active FROM users WHERE id = ? LIMIT 1", args: [target.userId] }
|
|
16052
|
+
);
|
|
16053
|
+
if (probe.rows.length > 0) {
|
|
16054
|
+
throw new AdminCreditError(409, "Account is deactivated; reactivate it before adjusting credits");
|
|
16055
|
+
}
|
|
16056
|
+
throw new AdminCreditError(404, "No account found for that email or id");
|
|
16057
|
+
}
|
|
16058
|
+
async function moveCredits(userId, direction, mc, reason, key) {
|
|
16059
|
+
if (direction === "grant") {
|
|
16060
|
+
const res2 = await creditMcIdempotent(userId, mc, LedgerOperation.ADMIN_GRANT, reason, key);
|
|
16061
|
+
if (!res2.ok) throw new AdminCreditError(409, "Grant could not be applied");
|
|
16062
|
+
return;
|
|
16063
|
+
}
|
|
16064
|
+
const res = await debitMcIdempotent(userId, mc, LedgerOperation.ADMIN_REVOKE, reason, key);
|
|
16065
|
+
if (!res.ok) {
|
|
16066
|
+
const balance = await reconcileBalanceMc(userId);
|
|
16067
|
+
throw new AdminCreditError(409, "Account does not have enough credits for this revoke", {
|
|
16068
|
+
requested_credits: toCredits(mc),
|
|
16069
|
+
available_credits: toCredits(balance)
|
|
16070
|
+
});
|
|
16071
|
+
}
|
|
16072
|
+
}
|
|
16073
|
+
function flip(direction) {
|
|
16074
|
+
return direction === "grant" ? "revoke" : "grant";
|
|
16075
|
+
}
|
|
16076
|
+
async function loadAdjustment(reference) {
|
|
16077
|
+
const db = getDb();
|
|
16078
|
+
const res = await db.execute({
|
|
16079
|
+
sql: `SELECT a.reference, a.user_id, a.direction, a.amount_mc, a.reason, a.actor, a.status, a.created_at, a.updated_at, u.email
|
|
16080
|
+
FROM admin_credit_adjustments a JOIN users u ON u.id = a.user_id
|
|
16081
|
+
WHERE a.reference = ? LIMIT 1`,
|
|
16082
|
+
args: [reference]
|
|
16083
|
+
});
|
|
16084
|
+
const row = res.rows[0];
|
|
16085
|
+
if (!row) throw new AdminCreditError(404, `No adjustment found with reference ${reference}`);
|
|
16086
|
+
const events = await db.execute({
|
|
16087
|
+
sql: `SELECT seq, kind, from_amount_mc, to_amount_mc, from_reason, to_reason, moved_mc, actor, created_at
|
|
16088
|
+
FROM admin_credit_adjustment_events WHERE reference = ? ORDER BY seq ASC`,
|
|
16089
|
+
args: [reference]
|
|
16090
|
+
});
|
|
16091
|
+
return {
|
|
16092
|
+
reference: String(row.reference),
|
|
16093
|
+
user_id: Number(row.user_id),
|
|
16094
|
+
user_email: String(row.email),
|
|
16095
|
+
direction: String(row.direction),
|
|
16096
|
+
credits: toCredits(Number(row.amount_mc)),
|
|
16097
|
+
amount_mc: Number(row.amount_mc),
|
|
16098
|
+
reason: String(row.reason),
|
|
16099
|
+
actor: String(row.actor),
|
|
16100
|
+
status: String(row.status),
|
|
16101
|
+
created_at: String(row.created_at),
|
|
16102
|
+
updated_at: row.updated_at == null ? null : String(row.updated_at),
|
|
16103
|
+
history: events.rows.map((e) => ({
|
|
16104
|
+
seq: Number(e.seq),
|
|
16105
|
+
kind: String(e.kind),
|
|
16106
|
+
from_credits: e.from_amount_mc == null ? null : toCredits(Number(e.from_amount_mc)),
|
|
16107
|
+
to_credits: e.to_amount_mc == null ? null : toCredits(Number(e.to_amount_mc)),
|
|
16108
|
+
from_reason: e.from_reason == null ? null : String(e.from_reason),
|
|
16109
|
+
to_reason: e.to_reason == null ? null : String(e.to_reason),
|
|
16110
|
+
moved_credits: toCredits(Number(e.moved_mc ?? 0)),
|
|
16111
|
+
actor: String(e.actor),
|
|
16112
|
+
created_at: String(e.created_at)
|
|
16113
|
+
}))
|
|
16114
|
+
};
|
|
16115
|
+
}
|
|
16116
|
+
async function nextSeq(reference) {
|
|
16117
|
+
const res = await getDb().execute({
|
|
16118
|
+
sql: "SELECT COALESCE(MAX(seq), 0) AS max_seq FROM admin_credit_adjustment_events WHERE reference = ?",
|
|
16119
|
+
args: [reference]
|
|
16120
|
+
});
|
|
16121
|
+
return Number(res.rows[0]?.max_seq ?? 0) + 1;
|
|
16122
|
+
}
|
|
16123
|
+
async function applyAdjustment(input) {
|
|
16124
|
+
const direction = validateDirection(input.direction);
|
|
16125
|
+
const credits = validateCredits(input.credits, input.confirmLarge === true);
|
|
16126
|
+
const reason = validateReason(input.reason);
|
|
16127
|
+
const actor = validateActor(input.actor);
|
|
16128
|
+
const reference = input.reference?.trim() || `adj_${randomUUID5()}`;
|
|
16129
|
+
if (reference.length > 120) throw new AdminCreditError(400, "reference must be at most 120 characters");
|
|
16130
|
+
const db = getDb();
|
|
16131
|
+
const existing = await db.execute({
|
|
16132
|
+
sql: "SELECT reference, user_id, direction, amount_mc FROM admin_credit_adjustments WHERE reference = ? LIMIT 1",
|
|
16133
|
+
args: [reference]
|
|
16134
|
+
});
|
|
16135
|
+
if (existing.rows.length > 0) {
|
|
16136
|
+
const prior = existing.rows[0];
|
|
16137
|
+
if (String(prior.direction) !== direction || Number(prior.amount_mc) !== creditsToMc(credits)) {
|
|
16138
|
+
throw new AdminCreditError(409, "reference already exists with different values; use the edit endpoint to change it");
|
|
16139
|
+
}
|
|
16140
|
+
return loadAdjustment(reference);
|
|
16141
|
+
}
|
|
16142
|
+
const user = await resolveUser2({ email: input.email, userId: input.userId });
|
|
16143
|
+
const mc = creditsToMc(credits);
|
|
16144
|
+
await moveCredits(user.id, direction, mc, reason, `${reference}:1`);
|
|
16145
|
+
await db.batch([
|
|
16146
|
+
{
|
|
16147
|
+
sql: `INSERT OR IGNORE INTO admin_credit_adjustments (reference, user_id, direction, amount_mc, reason, actor, status)
|
|
16148
|
+
VALUES (?, ?, ?, ?, ?, ?, 'applied')`,
|
|
16149
|
+
args: [reference, user.id, direction, mc, reason, actor]
|
|
16150
|
+
},
|
|
16151
|
+
{
|
|
16152
|
+
sql: `INSERT OR IGNORE INTO admin_credit_adjustment_events (reference, seq, kind, from_amount_mc, to_amount_mc, from_reason, to_reason, moved_mc, actor)
|
|
16153
|
+
VALUES (?, 1, 'created', NULL, ?, NULL, ?, ?, ?)`,
|
|
16154
|
+
args: [reference, mc, reason, mc, actor]
|
|
16155
|
+
}
|
|
16156
|
+
], "write");
|
|
16157
|
+
return loadAdjustment(reference);
|
|
16158
|
+
}
|
|
16159
|
+
async function editAdjustment(input) {
|
|
16160
|
+
const actor = validateActor(input.actor);
|
|
16161
|
+
const current = await loadAdjustment(input.reference);
|
|
16162
|
+
if (current.status === "reversed") {
|
|
16163
|
+
throw new AdminCreditError(409, "This adjustment was reversed and can no longer be edited");
|
|
16164
|
+
}
|
|
16165
|
+
if (input.credits === void 0 && input.reason === void 0) {
|
|
16166
|
+
throw new AdminCreditError(400, "Provide credits, reason, or both");
|
|
16167
|
+
}
|
|
16168
|
+
const db = getDb();
|
|
16169
|
+
if (input.reason !== void 0) {
|
|
16170
|
+
const reason = validateReason(input.reason);
|
|
16171
|
+
if (reason !== current.reason) {
|
|
16172
|
+
const seq = await nextSeq(current.reference);
|
|
16173
|
+
await db.batch([
|
|
16174
|
+
{
|
|
16175
|
+
sql: "UPDATE admin_credit_adjustments SET reason = ?, updated_at = datetime('now') WHERE reference = ?",
|
|
16176
|
+
args: [reason, current.reference]
|
|
16177
|
+
},
|
|
16178
|
+
{
|
|
16179
|
+
sql: `INSERT INTO admin_credit_adjustment_events (reference, seq, kind, from_reason, to_reason, moved_mc, actor)
|
|
16180
|
+
VALUES (?, ?, 'reason_edited', ?, ?, 0, ?)`,
|
|
16181
|
+
args: [current.reference, seq, current.reason, reason, actor]
|
|
16182
|
+
}
|
|
16183
|
+
], "write");
|
|
16184
|
+
}
|
|
16185
|
+
}
|
|
16186
|
+
if (input.credits !== void 0) {
|
|
16187
|
+
const credits = validateCredits(input.credits, input.confirmLarge === true);
|
|
16188
|
+
const targetMc = creditsToMc(credits);
|
|
16189
|
+
if (targetMc !== current.amount_mc) {
|
|
16190
|
+
const deltaMc = targetMc - current.amount_mc;
|
|
16191
|
+
const moveDirection = deltaMc > 0 ? current.direction : flip(current.direction);
|
|
16192
|
+
const moveMc = Math.abs(deltaMc);
|
|
16193
|
+
const seq = await nextSeq(current.reference);
|
|
16194
|
+
const reason = input.reason !== void 0 ? validateReason(input.reason) : current.reason;
|
|
16195
|
+
await moveCredits(current.user_id, moveDirection, moveMc, `edit ${current.reference}: ${reason}`, `${current.reference}:${seq}`);
|
|
16196
|
+
await db.batch([
|
|
16197
|
+
{
|
|
16198
|
+
sql: "UPDATE admin_credit_adjustments SET amount_mc = ?, updated_at = datetime('now') WHERE reference = ?",
|
|
16199
|
+
args: [targetMc, current.reference]
|
|
16200
|
+
},
|
|
16201
|
+
{
|
|
16202
|
+
sql: `INSERT INTO admin_credit_adjustment_events (reference, seq, kind, from_amount_mc, to_amount_mc, moved_mc, actor)
|
|
16203
|
+
VALUES (?, ?, 'amount_edited', ?, ?, ?, ?)`,
|
|
16204
|
+
args: [current.reference, seq, current.amount_mc, targetMc, moveMc, actor]
|
|
16205
|
+
}
|
|
16206
|
+
], "write");
|
|
16207
|
+
}
|
|
16208
|
+
}
|
|
16209
|
+
return loadAdjustment(input.reference);
|
|
16210
|
+
}
|
|
16211
|
+
async function reverseAdjustment(reference, actor) {
|
|
16212
|
+
const validActor = validateActor(actor);
|
|
16213
|
+
const current = await loadAdjustment(reference);
|
|
16214
|
+
if (current.status === "reversed") return current;
|
|
16215
|
+
const seq = await nextSeq(reference);
|
|
16216
|
+
if (current.amount_mc > 0) {
|
|
16217
|
+
await moveCredits(current.user_id, flip(current.direction), current.amount_mc, `reverse ${reference}: ${current.reason}`, `${reference}:${seq}`);
|
|
16218
|
+
}
|
|
16219
|
+
await getDb().batch([
|
|
16220
|
+
{
|
|
16221
|
+
sql: "UPDATE admin_credit_adjustments SET status = 'reversed', updated_at = datetime('now') WHERE reference = ?",
|
|
16222
|
+
args: [reference]
|
|
16223
|
+
},
|
|
16224
|
+
{
|
|
16225
|
+
sql: `INSERT INTO admin_credit_adjustment_events (reference, seq, kind, from_amount_mc, to_amount_mc, moved_mc, actor)
|
|
16226
|
+
VALUES (?, ?, 'reversed', ?, 0, ?, ?)`,
|
|
16227
|
+
args: [reference, seq, current.amount_mc, current.amount_mc, validActor]
|
|
16228
|
+
}
|
|
16229
|
+
], "write");
|
|
16230
|
+
return loadAdjustment(reference);
|
|
16231
|
+
}
|
|
16232
|
+
async function lookupAccount(target, limit = 20) {
|
|
16233
|
+
const user = await resolveUser2(target);
|
|
16234
|
+
const db = getDb();
|
|
16235
|
+
const balanceMc = await reconcileBalanceMc(user.id, user.balance_mc);
|
|
16236
|
+
const lots = await db.execute({
|
|
16237
|
+
sql: `SELECT COUNT(*) AS n, COALESCE(SUM(remaining_mc), 0) AS mc, MIN(expires_at) AS next_expiry
|
|
16238
|
+
FROM credit_lots
|
|
16239
|
+
WHERE user_id = ? AND remaining_mc > 0 AND (never_expires = 1 OR expires_at > datetime('now'))`,
|
|
16240
|
+
args: [user.id]
|
|
16241
|
+
});
|
|
16242
|
+
const refs = await db.execute({
|
|
16243
|
+
sql: "SELECT reference FROM admin_credit_adjustments WHERE user_id = ? ORDER BY created_at DESC, rowid DESC LIMIT ?",
|
|
16244
|
+
args: [user.id, limit]
|
|
16245
|
+
});
|
|
16246
|
+
const adjustments = await Promise.all(refs.rows.map((r) => loadAdjustment(String(r.reference))));
|
|
16247
|
+
const ledger = await db.execute({
|
|
16248
|
+
sql: "SELECT created_at, operation, amount_mc, description FROM ledger WHERE user_id = ? ORDER BY id DESC LIMIT ?",
|
|
16249
|
+
args: [user.id, limit]
|
|
16250
|
+
});
|
|
16251
|
+
return {
|
|
16252
|
+
user: {
|
|
16253
|
+
id: user.id,
|
|
16254
|
+
email: user.email,
|
|
16255
|
+
active: Boolean(user.active),
|
|
16256
|
+
balance_credits: toCredits(balanceMc),
|
|
16257
|
+
balance_mc: balanceMc
|
|
16258
|
+
},
|
|
16259
|
+
lots: {
|
|
16260
|
+
active_lots: Number(lots.rows[0]?.n ?? 0),
|
|
16261
|
+
active_credits: toCredits(Number(lots.rows[0]?.mc ?? 0)),
|
|
16262
|
+
next_expiry: lots.rows[0]?.next_expiry == null ? null : String(lots.rows[0].next_expiry)
|
|
16263
|
+
},
|
|
16264
|
+
adjustments,
|
|
16265
|
+
recent_ledger: ledger.rows.map((r) => ({
|
|
16266
|
+
created_at: String(r.created_at),
|
|
16267
|
+
operation: String(r.operation),
|
|
16268
|
+
credits: toCredits(Number(r.amount_mc)),
|
|
16269
|
+
description: r.description == null ? null : String(r.description)
|
|
16270
|
+
}))
|
|
16271
|
+
};
|
|
16272
|
+
}
|
|
16273
|
+
|
|
16274
|
+
// src/api/admin-credit-routes.ts
|
|
16275
|
+
var adminCreditsApp = new Hono9();
|
|
16276
|
+
adminCreditsApp.use("*", adminAuth);
|
|
16277
|
+
function fail(c, err) {
|
|
16278
|
+
if (err instanceof AdminCreditError) {
|
|
16279
|
+
return c.json({ error: err.message, ...err.detail ?? {} }, err.status);
|
|
16280
|
+
}
|
|
16281
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16282
|
+
if (message.includes("conflicts with another")) {
|
|
16283
|
+
return c.json({ error: "A concurrent adjustment used the same key; re-read the account and retry" }, 409);
|
|
16284
|
+
}
|
|
16285
|
+
console.error("[admin/credits] unexpected failure:", message);
|
|
16286
|
+
return c.json({ error: "Adjustment failed" }, 500);
|
|
16287
|
+
}
|
|
16288
|
+
async function readBody(c) {
|
|
16289
|
+
try {
|
|
16290
|
+
const parsed = await c.req.json();
|
|
16291
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
16292
|
+
} catch {
|
|
16293
|
+
return {};
|
|
16294
|
+
}
|
|
16295
|
+
}
|
|
16296
|
+
function targetFrom(query) {
|
|
16297
|
+
const email = query.email?.trim();
|
|
16298
|
+
const idRaw = query.userId?.trim();
|
|
16299
|
+
const userId = idRaw ? Number(idRaw) : void 0;
|
|
16300
|
+
if (userId !== void 0 && !Number.isInteger(userId)) {
|
|
16301
|
+
throw new AdminCreditError(400, "userId must be an integer");
|
|
16302
|
+
}
|
|
16303
|
+
return { email: email || void 0, userId };
|
|
16304
|
+
}
|
|
16305
|
+
adminCreditsApp.post("/adjust", async (c) => {
|
|
16306
|
+
try {
|
|
16307
|
+
const body = await readBody(c);
|
|
16308
|
+
const record = await applyAdjustment({
|
|
16309
|
+
email: typeof body.email === "string" ? body.email : void 0,
|
|
16310
|
+
userId: typeof body.userId === "number" ? body.userId : void 0,
|
|
16311
|
+
direction: body.direction,
|
|
16312
|
+
credits: body.credits,
|
|
16313
|
+
reason: body.reason,
|
|
16314
|
+
actor: body.actor,
|
|
16315
|
+
reference: typeof body.reference === "string" ? body.reference : void 0,
|
|
16316
|
+
confirmLarge: body.confirmLarge === true
|
|
16317
|
+
});
|
|
16318
|
+
return c.json({ ok: true, adjustment: record });
|
|
16319
|
+
} catch (err) {
|
|
16320
|
+
return fail(c, err);
|
|
16321
|
+
}
|
|
16322
|
+
});
|
|
16323
|
+
adminCreditsApp.post("/adjustments/:reference/edit", async (c) => {
|
|
16324
|
+
try {
|
|
16325
|
+
const body = await readBody(c);
|
|
16326
|
+
const record = await editAdjustment({
|
|
16327
|
+
reference: c.req.param("reference"),
|
|
16328
|
+
credits: typeof body.credits === "number" ? body.credits : void 0,
|
|
16329
|
+
reason: typeof body.reason === "string" ? body.reason : void 0,
|
|
16330
|
+
actor: body.actor,
|
|
16331
|
+
confirmLarge: body.confirmLarge === true
|
|
16332
|
+
});
|
|
16333
|
+
return c.json({ ok: true, adjustment: record });
|
|
16334
|
+
} catch (err) {
|
|
16335
|
+
return fail(c, err);
|
|
16336
|
+
}
|
|
16337
|
+
});
|
|
16338
|
+
adminCreditsApp.post("/adjustments/:reference/reverse", async (c) => {
|
|
16339
|
+
try {
|
|
16340
|
+
const body = await readBody(c);
|
|
16341
|
+
const record = await reverseAdjustment(c.req.param("reference"), body.actor);
|
|
16342
|
+
return c.json({ ok: true, adjustment: record });
|
|
16343
|
+
} catch (err) {
|
|
16344
|
+
return fail(c, err);
|
|
16345
|
+
}
|
|
16346
|
+
});
|
|
16347
|
+
adminCreditsApp.get("/adjustments/:reference", async (c) => {
|
|
16348
|
+
try {
|
|
16349
|
+
return c.json({ ok: true, adjustment: await loadAdjustment(c.req.param("reference")) });
|
|
16350
|
+
} catch (err) {
|
|
16351
|
+
return fail(c, err);
|
|
16352
|
+
}
|
|
16353
|
+
});
|
|
16354
|
+
adminCreditsApp.get("/lookup", async (c) => {
|
|
16355
|
+
try {
|
|
16356
|
+
const target = targetFrom(c.req.query());
|
|
16357
|
+
const limitRaw = c.req.query("limit");
|
|
16358
|
+
const limit = limitRaw ? Math.min(Math.max(Number(limitRaw), 1), 100) : 20;
|
|
16359
|
+
return c.json({ ok: true, ...await lookupAccount(target, limit) });
|
|
16360
|
+
} catch (err) {
|
|
16361
|
+
return fail(c, err);
|
|
16362
|
+
}
|
|
16363
|
+
});
|
|
16364
|
+
|
|
16365
|
+
// src/api/instagram-routes.ts
|
|
16366
|
+
import { Hono as Hono10 } from "hono";
|
|
15965
16367
|
import { z as z19 } from "zod";
|
|
15966
16368
|
import { mkdtempSync, readFileSync as readFileSync2, rmSync, writeFileSync } from "fs";
|
|
15967
16369
|
import { tmpdir } from "os";
|
|
@@ -16349,7 +16751,7 @@ var InstagramMediaDownloadBodySchema = z19.object({
|
|
|
16349
16751
|
includeTranscript: z19.boolean().default(false),
|
|
16350
16752
|
mux: z19.boolean().default(true)
|
|
16351
16753
|
});
|
|
16352
|
-
var instagramApp = new
|
|
16754
|
+
var instagramApp = new Hono10();
|
|
16353
16755
|
function invalidRequest3(message) {
|
|
16354
16756
|
return { error_code: "invalid_request", message };
|
|
16355
16757
|
}
|
|
@@ -16629,7 +17031,7 @@ instagramApp.post("/media-download", createApiKeyAuth(), async (c) => {
|
|
|
16629
17031
|
});
|
|
16630
17032
|
|
|
16631
17033
|
// src/api/reddit-routes.ts
|
|
16632
|
-
import { Hono as
|
|
17034
|
+
import { Hono as Hono11 } from "hono";
|
|
16633
17035
|
import { z as z20 } from "zod";
|
|
16634
17036
|
|
|
16635
17037
|
// src/api/reddit-trending.ts
|
|
@@ -16875,7 +17277,7 @@ async function scrapeOldRedditWithRetries(url, script, accept) {
|
|
|
16875
17277
|
}
|
|
16876
17278
|
return null;
|
|
16877
17279
|
}
|
|
16878
|
-
var redditApp = new
|
|
17280
|
+
var redditApp = new Hono11();
|
|
16879
17281
|
redditApp.post("/thread", createApiKeyAuth(), async (c) => {
|
|
16880
17282
|
const raw = await c.req.json().catch(() => ({}));
|
|
16881
17283
|
const parsed = RedditThreadBodySchema.safeParse(raw);
|
|
@@ -17076,9 +17478,9 @@ redditApp.post("/trending", createApiKeyAuth(), async (c) => {
|
|
|
17076
17478
|
});
|
|
17077
17479
|
|
|
17078
17480
|
// src/api/video-routes.ts
|
|
17079
|
-
import { Hono as
|
|
17481
|
+
import { Hono as Hono12 } from "hono";
|
|
17080
17482
|
import { z as z21 } from "zod";
|
|
17081
|
-
var videoApp = new
|
|
17483
|
+
var videoApp = new Hono12();
|
|
17082
17484
|
var AnalyzeBodySchema = z21.object({
|
|
17083
17485
|
sourceUrl: z21.string().trim().url("sourceUrl must be a direct video file URL"),
|
|
17084
17486
|
intervalS: z21.number().min(1).max(30).optional(),
|
|
@@ -17188,7 +17590,7 @@ videoApp.post("/status", createApiKeyAuth(), async (c) => {
|
|
|
17188
17590
|
});
|
|
17189
17591
|
|
|
17190
17592
|
// src/api/maps-routes.ts
|
|
17191
|
-
import { Hono as
|
|
17593
|
+
import { Hono as Hono13 } from "hono";
|
|
17192
17594
|
|
|
17193
17595
|
// src/extractor/MapsNavigator.ts
|
|
17194
17596
|
var BUSINESS_PANEL_REDIRECT_BASE = "https://serp-redirector.vercel.app";
|
|
@@ -17805,7 +18207,7 @@ function mapsErrorResponse(c, err, errorCode) {
|
|
|
17805
18207
|
retryable
|
|
17806
18208
|
}, retryable ? 503 : 500);
|
|
17807
18209
|
}
|
|
17808
|
-
var mapsApp = new
|
|
18210
|
+
var mapsApp = new Hono13();
|
|
17809
18211
|
mapsApp.post("/search", createApiKeyAuth(), async (c) => {
|
|
17810
18212
|
const user = c.get("user");
|
|
17811
18213
|
const body = await c.req.json().catch(() => ({}));
|
|
@@ -17944,7 +18346,7 @@ mapsApp.post("/place", createApiKeyAuth(), async (c) => {
|
|
|
17944
18346
|
});
|
|
17945
18347
|
|
|
17946
18348
|
// src/api/trustpilot-routes.ts
|
|
17947
|
-
import { Hono as
|
|
18349
|
+
import { Hono as Hono14 } from "hono";
|
|
17948
18350
|
import { z as z23 } from "zod";
|
|
17949
18351
|
var TrustpilotReviewsBodySchema = z23.object({
|
|
17950
18352
|
domain: z23.string().trim().min(1, "domain is required"),
|
|
@@ -18013,7 +18415,7 @@ async function extractReviewCards(page) {
|
|
|
18013
18415
|
});
|
|
18014
18416
|
});
|
|
18015
18417
|
}
|
|
18016
|
-
var trustpilotApp = new
|
|
18418
|
+
var trustpilotApp = new Hono14();
|
|
18017
18419
|
trustpilotApp.post("/reviews", createApiKeyAuth(), async (c) => {
|
|
18018
18420
|
const raw = await c.req.json().catch(() => ({}));
|
|
18019
18421
|
const parsed = TrustpilotReviewsBodySchema.safeParse(raw);
|
|
@@ -18094,7 +18496,7 @@ trustpilotApp.post("/reviews", createApiKeyAuth(), async (c) => {
|
|
|
18094
18496
|
});
|
|
18095
18497
|
|
|
18096
18498
|
// src/api/g2-routes.ts
|
|
18097
|
-
import { Hono as
|
|
18499
|
+
import { Hono as Hono15 } from "hono";
|
|
18098
18500
|
import { z as z24 } from "zod";
|
|
18099
18501
|
var G2ReviewsBodySchema = z24.object({
|
|
18100
18502
|
product: z24.string().trim().min(1, "product is required"),
|
|
@@ -18203,7 +18605,7 @@ async function extractG2ReviewCards(page) {
|
|
|
18203
18605
|
});
|
|
18204
18606
|
});
|
|
18205
18607
|
}
|
|
18206
|
-
var g2App = new
|
|
18608
|
+
var g2App = new Hono15();
|
|
18207
18609
|
g2App.post("/reviews", createApiKeyAuth(), async (c) => {
|
|
18208
18610
|
const raw = await c.req.json().catch(() => ({}));
|
|
18209
18611
|
const parsed = G2ReviewsBodySchema.safeParse(raw);
|
|
@@ -18304,17 +18706,17 @@ g2App.post("/reviews", createApiKeyAuth(), async (c) => {
|
|
|
18304
18706
|
});
|
|
18305
18707
|
|
|
18306
18708
|
// src/api/directory-routes.ts
|
|
18307
|
-
import { createHash as createHash4, randomUUID as
|
|
18308
|
-
import { Hono as
|
|
18709
|
+
import { createHash as createHash4, randomUUID as randomUUID7 } from "crypto";
|
|
18710
|
+
import { Hono as Hono16 } from "hono";
|
|
18309
18711
|
|
|
18310
18712
|
// src/api/directory-workflow-dispatch.ts
|
|
18311
|
-
import { randomUUID as
|
|
18713
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
18312
18714
|
function retryDelaySeconds(attempts) {
|
|
18313
18715
|
return Math.min(60 * 60, Math.max(15, 15 * 2 ** Math.min(8, Math.max(0, attempts - 1))));
|
|
18314
18716
|
}
|
|
18315
18717
|
async function dispatchPendingDirectoryWorkflows(limit = 25) {
|
|
18316
18718
|
const rows = await claimDirectoryWorkflowOutbox({
|
|
18317
|
-
workerId: `directory-dispatch-${process.pid}-${
|
|
18719
|
+
workerId: `directory-dispatch-${process.pid}-${randomUUID6().slice(0, 8)}`,
|
|
18318
18720
|
limit
|
|
18319
18721
|
});
|
|
18320
18722
|
const result = { claimed: rows.length, dispatched: 0, failed: 0 };
|
|
@@ -18338,7 +18740,7 @@ async function dispatchPendingDirectoryWorkflows(limit = 25) {
|
|
|
18338
18740
|
}
|
|
18339
18741
|
|
|
18340
18742
|
// src/api/directory-routes.ts
|
|
18341
|
-
var directoryApp = new
|
|
18743
|
+
var directoryApp = new Hono16();
|
|
18342
18744
|
function safeOptions(options) {
|
|
18343
18745
|
const { kernelApiKey: _kernelApiKey, ...safe } = options;
|
|
18344
18746
|
return safe;
|
|
@@ -18353,14 +18755,14 @@ function idempotencyKey(raw) {
|
|
|
18353
18755
|
if (trimmed.length > 500) return { ok: false, message: "Idempotency-Key must be 500 characters or fewer." };
|
|
18354
18756
|
return { ok: true, key: trimmed };
|
|
18355
18757
|
}
|
|
18356
|
-
return { ok: true, key: `directory-${
|
|
18758
|
+
return { ok: true, key: `directory-${randomUUID7()}` };
|
|
18357
18759
|
}
|
|
18358
18760
|
function debitKeyFor(userId, responseKey) {
|
|
18359
18761
|
const digest = createHash4("sha256").update(String(userId)).update("\0").update(responseKey).digest("hex");
|
|
18360
18762
|
return `directory-workflow:${userId}:${digest}`;
|
|
18361
18763
|
}
|
|
18362
18764
|
function jobId() {
|
|
18363
|
-
return `dir_${
|
|
18765
|
+
return `dir_${randomUUID7().replace(/-/g, "")}`;
|
|
18364
18766
|
}
|
|
18365
18767
|
function publicStatus(job, result) {
|
|
18366
18768
|
if (job.status === "failed") return "failed";
|
|
@@ -18664,7 +19066,7 @@ directoryApp.get("/jobs/:id", createApiKeyAuth(), async (c) => {
|
|
|
18664
19066
|
});
|
|
18665
19067
|
|
|
18666
19068
|
// src/api/location-data-routes.ts
|
|
18667
|
-
import { Hono as
|
|
19069
|
+
import { Hono as Hono17 } from "hono";
|
|
18668
19070
|
import { z as z25 } from "zod";
|
|
18669
19071
|
var LOCATION_IMPORT_MAX_BYTES = 64 * 1024 * 1024;
|
|
18670
19072
|
var LOCATION_IMPORT_TIMEOUT_MS = 6e4;
|
|
@@ -18684,7 +19086,7 @@ var importSchema = z25.object({
|
|
|
18684
19086
|
sourceUrl: z25.string().url().max(2e3).optional()
|
|
18685
19087
|
});
|
|
18686
19088
|
var censusSyncSchema = z25.object({ state: z25.string().trim().min(2).max(40) });
|
|
18687
|
-
var locationDataApp = new
|
|
19089
|
+
var locationDataApp = new Hono17();
|
|
18688
19090
|
function locationAdminAuthorized(header) {
|
|
18689
19091
|
const expected = process.env.MCP_SCRAPER_LOCATION_ADMIN_KEY?.trim();
|
|
18690
19092
|
return Boolean(expected && header?.trim() === expected);
|
|
@@ -18952,9 +19354,9 @@ async function reconcileDirectoryWorkflowSettlements(limit = 25) {
|
|
|
18952
19354
|
// src/api/workflow-routes.ts
|
|
18953
19355
|
import { createHmac as createHmac3 } from "crypto";
|
|
18954
19356
|
import { readFile as readFile2 } from "fs/promises";
|
|
18955
|
-
import { Hono as
|
|
19357
|
+
import { Hono as Hono18 } from "hono";
|
|
18956
19358
|
import { z as z26 } from "zod";
|
|
18957
|
-
var workflowApp = new
|
|
19359
|
+
var workflowApp = new Hono18();
|
|
18958
19360
|
var WorkflowInputSchema = z26.record(z26.unknown()).default({});
|
|
18959
19361
|
var WorkflowIdSchema = z26.string().min(1);
|
|
18960
19362
|
var CadenceSchema = z26.enum(["daily", "weekly", "monthly"]);
|
|
@@ -19484,8 +19886,8 @@ workflowApp.post("/cron/dispatch", async (c) => {
|
|
|
19484
19886
|
});
|
|
19485
19887
|
|
|
19486
19888
|
// src/api/serp-intelligence-routes.ts
|
|
19487
|
-
import { Hono as
|
|
19488
|
-
import { createHash as createHash6, randomUUID as
|
|
19889
|
+
import { Hono as Hono19 } from "hono";
|
|
19890
|
+
import { createHash as createHash6, randomUUID as randomUUID8 } from "crypto";
|
|
19489
19891
|
|
|
19490
19892
|
// src/serp-intelligence/page-snapshot-extractor.ts
|
|
19491
19893
|
import { createHash as createHash5 } from "crypto";
|
|
@@ -20217,7 +20619,7 @@ var SERP_INTELLIGENCE_RATE_WINDOW_SECONDS = 60;
|
|
|
20217
20619
|
var POST_CAPTURE_ROUTE_LABEL = "POST /capture";
|
|
20218
20620
|
var POST_PAGE_SNAPSHOTS_ROUTE_LABEL = "POST /page-snapshots";
|
|
20219
20621
|
var SERP_CAPTURE_BILLING_SOURCE = "serp_intelligence_capture";
|
|
20220
|
-
var serpIntelligenceApp = new
|
|
20622
|
+
var serpIntelligenceApp = new Hono19();
|
|
20221
20623
|
serpIntelligenceApp.use("*", createApiKeyAuth());
|
|
20222
20624
|
function structuredError(input) {
|
|
20223
20625
|
return {
|
|
@@ -20270,7 +20672,7 @@ async function logRequestEventBestEffort(input) {
|
|
|
20270
20672
|
}
|
|
20271
20673
|
}
|
|
20272
20674
|
function captureBillingKeys(userId, suppliedKey, body) {
|
|
20273
|
-
const responseKey = suppliedKey?.trim() ||
|
|
20675
|
+
const responseKey = suppliedKey?.trim() || randomUUID8();
|
|
20274
20676
|
const requestFingerprint2 = createHash6("sha256").update(JSON.stringify(body)).digest("hex");
|
|
20275
20677
|
const keyDigest = createHash6("sha256").update(String(userId)).update("\0").update(responseKey).digest("hex");
|
|
20276
20678
|
return {
|
|
@@ -20493,7 +20895,7 @@ serpIntelligenceApp.post("/page-snapshots", async (c) => {
|
|
|
20493
20895
|
});
|
|
20494
20896
|
|
|
20495
20897
|
// src/mcp/mcp-routes.ts
|
|
20496
|
-
import { Hono as
|
|
20898
|
+
import { Hono as Hono20 } from "hono";
|
|
20497
20899
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
20498
20900
|
|
|
20499
20901
|
// src/mcp/memory-mcp-tool-executor.ts
|
|
@@ -20787,6 +21189,7 @@ import { addVaultTool } from "mcpscraper-memory-tools/tools/vaults/add-vault";
|
|
|
20787
21189
|
import { deleteVaultTool } from "mcpscraper-memory-tools/tools/vaults/delete-vault";
|
|
20788
21190
|
import { memoryCaptureTool } from "mcpscraper-memory-tools/tools/capture/memory-capture";
|
|
20789
21191
|
import { upsertTagTool } from "mcpscraper-memory-tools/tools/tags/upsert-tag";
|
|
21192
|
+
import { mergeTagsTool } from "mcpscraper-memory-tools/tools/tags/merge-tags";
|
|
20790
21193
|
var registered2 = false;
|
|
20791
21194
|
function registerWriteCutovers() {
|
|
20792
21195
|
if (registered2) return;
|
|
@@ -20935,6 +21338,10 @@ function registerWriteCutovers() {
|
|
|
20935
21338
|
const result = await upsertTagTool.execute({ ...input, apiKey }, {});
|
|
20936
21339
|
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
20937
21340
|
});
|
|
21341
|
+
registerCutover("mergeTagsTool", async (input, apiKey) => {
|
|
21342
|
+
const result = await mergeTagsTool.execute({ ...input, apiKey }, {});
|
|
21343
|
+
return { content: [{ type: "text", text: JSON.stringify(result ?? {}) }], structuredContent: result ?? {}, isError: false };
|
|
21344
|
+
});
|
|
20938
21345
|
}
|
|
20939
21346
|
|
|
20940
21347
|
// src/mcp/memory-cutover/billing.ts
|
|
@@ -21144,7 +21551,7 @@ async function requireMcpCallerKey(c) {
|
|
|
21144
21551
|
if (!user) return mcpAuthError();
|
|
21145
21552
|
return { key: callerKey, user };
|
|
21146
21553
|
}
|
|
21147
|
-
var mcpApp = new
|
|
21554
|
+
var mcpApp = new Hono20();
|
|
21148
21555
|
mcpApp.all("/", async (c) => {
|
|
21149
21556
|
try {
|
|
21150
21557
|
const keyOrError = await requireMcpCallerKey(c);
|
|
@@ -21170,11 +21577,11 @@ mcpApp.all("/", async (c) => {
|
|
|
21170
21577
|
});
|
|
21171
21578
|
|
|
21172
21579
|
// src/api/browser-agent-routes.ts
|
|
21173
|
-
import { randomUUID as
|
|
21174
|
-
import { Hono as
|
|
21580
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
21581
|
+
import { Hono as Hono21 } from "hono";
|
|
21175
21582
|
|
|
21176
21583
|
// src/api/browser-agent-db.ts
|
|
21177
|
-
import { randomUUID as
|
|
21584
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
21178
21585
|
var _ready = false;
|
|
21179
21586
|
var _migrationPromise = null;
|
|
21180
21587
|
async function migrateBrowserAgent() {
|
|
@@ -21305,7 +21712,7 @@ async function runBrowserAgentMigration() {
|
|
|
21305
21712
|
}
|
|
21306
21713
|
async function createExtensionRow(input) {
|
|
21307
21714
|
const db = getDb();
|
|
21308
|
-
const id = `bext_${
|
|
21715
|
+
const id = `bext_${randomUUID9().replace(/-/g, "").slice(0, 20)}`;
|
|
21309
21716
|
await db.execute({
|
|
21310
21717
|
sql: `INSERT INTO browser_agent_extensions (id, user_id, name, backend_id, backend_name, source, source_url, size_bytes)
|
|
21311
21718
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
@@ -21340,7 +21747,7 @@ async function deleteExtensionRow(userId, name) {
|
|
|
21340
21747
|
}
|
|
21341
21748
|
async function createAuthConnectionRow(input) {
|
|
21342
21749
|
const db = getDb();
|
|
21343
|
-
const connectionId = `authc_${
|
|
21750
|
+
const connectionId = `authc_${randomUUID9().replace(/-/g, "").slice(0, 20)}`;
|
|
21344
21751
|
await db.execute({
|
|
21345
21752
|
sql: `INSERT INTO browser_auth_connections (connection_id, domain, profile, account_email, note, status, browser_agent_session_id)
|
|
21346
21753
|
VALUES (?, ?, ?, ?, ?, 'NEEDS_AUTH', ?)`,
|
|
@@ -21425,7 +21832,7 @@ async function deleteProfileLabel(userId, profile) {
|
|
|
21425
21832
|
}
|
|
21426
21833
|
async function createSessionRow(input) {
|
|
21427
21834
|
const db = getDb();
|
|
21428
|
-
const id = `bas_${
|
|
21835
|
+
const id = `bas_${randomUUID9().replace(/-/g, "").slice(0, 20)}`;
|
|
21429
21836
|
await db.execute({
|
|
21430
21837
|
sql: `INSERT INTO browser_agent_sessions (id, runtime_session_id, live_view_url, cdp_ws_url, status, label, user_id, concurrency_lock_id, last_action_at)
|
|
21431
21838
|
VALUES (?, ?, ?, ?, 'open', ?, ?, ?, datetime('now'))`,
|
|
@@ -21494,7 +21901,7 @@ async function recordAction(input) {
|
|
|
21494
21901
|
sql: `INSERT INTO browser_agent_actions (id, session_id, type, params_json, ok, error)
|
|
21495
21902
|
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
21496
21903
|
args: [
|
|
21497
|
-
`baa_${
|
|
21904
|
+
`baa_${randomUUID9().replace(/-/g, "").slice(0, 20)}`,
|
|
21498
21905
|
input.sessionId,
|
|
21499
21906
|
input.type,
|
|
21500
21907
|
input.params == null ? null : JSON.stringify(input.params),
|
|
@@ -22724,7 +23131,7 @@ async function loadOpenSession(id, userId) {
|
|
|
22724
23131
|
return row;
|
|
22725
23132
|
}
|
|
22726
23133
|
function buildBrowserAgentRoutes() {
|
|
22727
|
-
const app2 = new
|
|
23134
|
+
const app2 = new Hono21();
|
|
22728
23135
|
app2.use("*", async (c, next) => {
|
|
22729
23136
|
await migrateBrowserAgent();
|
|
22730
23137
|
return next();
|
|
@@ -23225,7 +23632,7 @@ function buildBrowserAgentRoutes() {
|
|
|
23225
23632
|
}
|
|
23226
23633
|
const existing = await getExtensionRow(user.id, name);
|
|
23227
23634
|
if (existing) return c.json({ error: `an extension named "${name}" already exists \u2014 delete it first or pick another name` }, 409);
|
|
23228
|
-
const backendName = `u${user.id}_${
|
|
23635
|
+
const backendName = `u${user.id}_${randomUUID10().replace(/-/g, "")}`;
|
|
23229
23636
|
try {
|
|
23230
23637
|
const imported = await importExtensionFromStore(storeUrl, backendName);
|
|
23231
23638
|
const row = await createExtensionRow({
|
|
@@ -23557,7 +23964,7 @@ if (state.key) { refreshSessions(); if (state.current) selectSession(state.curre
|
|
|
23557
23964
|
|
|
23558
23965
|
// src/api/stripe-routes.ts
|
|
23559
23966
|
import Stripe from "stripe";
|
|
23560
|
-
import { Hono as
|
|
23967
|
+
import { Hono as Hono22 } from "hono";
|
|
23561
23968
|
var stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: "2026-02-25.clover" });
|
|
23562
23969
|
async function cancelStandaloneMemorySub(memSubId, baseSubId) {
|
|
23563
23970
|
if (!memSubId || memSubId === baseSubId) return;
|
|
@@ -23572,7 +23979,7 @@ async function cancelStandaloneMemorySub(memSubId, baseSubId) {
|
|
|
23572
23979
|
console.error("[stripe] could not wind down standalone memory subscription", memSubId, err instanceof Error ? err.message : err);
|
|
23573
23980
|
}
|
|
23574
23981
|
}
|
|
23575
|
-
var stripeApp = new
|
|
23982
|
+
var stripeApp = new Hono22();
|
|
23576
23983
|
stripeApp.post("/webhooks", async (c) => {
|
|
23577
23984
|
const sig = c.req.header("stripe-signature");
|
|
23578
23985
|
const body = await c.req.text();
|
|
@@ -23598,7 +24005,7 @@ stripeApp.post("/webhooks", async (c) => {
|
|
|
23598
24005
|
const tierPriceId = liveBasePlanPriceId ?? invoice.lines.data.map(linePriceId).find((id) => id && id in SUBSCRIPTION_TIERS);
|
|
23599
24006
|
const tier = tierPriceId ? SUBSCRIPTION_TIERS[tierPriceId] : void 0;
|
|
23600
24007
|
if (tier) {
|
|
23601
|
-
const user = await
|
|
24008
|
+
const user = await resolveUser3(invoice.customer, invoice.customer_email ?? void 0);
|
|
23602
24009
|
if (user && invoice.id && !await ledgerExistsForStripePI(invoice.id)) {
|
|
23603
24010
|
await creditMc(user.id, tier.credits_mc, LedgerOperation.SUBSCRIPTION, `${tier.label} subscription credits`, invoice.id, { neverExpires: tier.credits_never_expire });
|
|
23604
24011
|
await setSubscriptionTier(user.id, tier.tier, tier.concurrency, subId ?? user.subscription_id);
|
|
@@ -23618,7 +24025,7 @@ stripeApp.post("/webhooks", async (c) => {
|
|
|
23618
24025
|
const priceId = findBasePlanItem(sub)?.price?.id ?? sub.items.data[0]?.price?.id;
|
|
23619
24026
|
if (priceId && priceId in MEMORY_PLANS) {
|
|
23620
24027
|
const mem = MEMORY_PLANS[priceId];
|
|
23621
|
-
const user2 = await
|
|
24028
|
+
const user2 = await resolveUser3(sub.customer, sub.customer_email);
|
|
23622
24029
|
if (user2) {
|
|
23623
24030
|
const live = sub.status === "active" || sub.status === "trialing";
|
|
23624
24031
|
const newMemoryPlan = live ? mem.plan : "free";
|
|
@@ -23688,7 +24095,7 @@ function linePriceId(line) {
|
|
|
23688
24095
|
const l = line;
|
|
23689
24096
|
return l?.price?.id ?? l?.pricing?.price_details?.price ?? l?.plan?.id;
|
|
23690
24097
|
}
|
|
23691
|
-
async function
|
|
24098
|
+
async function resolveUser3(customerId, emailFallback) {
|
|
23692
24099
|
let user = await getUserByStripeCustomerId(customerId);
|
|
23693
24100
|
if (user) return user;
|
|
23694
24101
|
if (!emailFallback) return void 0;
|
|
@@ -23698,9 +24105,9 @@ async function resolveUser2(customerId, emailFallback) {
|
|
|
23698
24105
|
}
|
|
23699
24106
|
|
|
23700
24107
|
// src/api/oauth-routes.ts
|
|
23701
|
-
import { Hono as
|
|
24108
|
+
import { Hono as Hono23 } from "hono";
|
|
23702
24109
|
import { getCookie, setCookie } from "hono/cookie";
|
|
23703
|
-
import { createHash as createHash7, randomBytes as randomBytes2, randomUUID as
|
|
24110
|
+
import { createHash as createHash7, randomBytes as randomBytes2, randomUUID as randomUUID11 } from "crypto";
|
|
23704
24111
|
import { importPKCS8, exportJWK, SignJWT } from "jose";
|
|
23705
24112
|
var ISSUER = "https://mcpscraper.dev";
|
|
23706
24113
|
var RESOURCE = () => process.env.MCP_MEMORY_RESOURCE_URL ?? "https://memory.mcpscraper.dev/mcp";
|
|
@@ -23867,7 +24274,7 @@ function redirectWithError(redirectUri, state, error) {
|
|
|
23867
24274
|
if (state) u.searchParams.set("state", state);
|
|
23868
24275
|
return new Response(null, { status: 302, headers: { Location: u.toString() } });
|
|
23869
24276
|
}
|
|
23870
|
-
var oauthApp = new
|
|
24277
|
+
var oauthApp = new Hono23();
|
|
23871
24278
|
oauthApp.use("*", async (c, next) => {
|
|
23872
24279
|
c.header("Access-Control-Allow-Origin", "*");
|
|
23873
24280
|
c.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
@@ -24048,7 +24455,7 @@ function pkceMatches(verifier, challenge) {
|
|
|
24048
24455
|
}
|
|
24049
24456
|
async function mintAccessToken(identity, scope, plan, audience) {
|
|
24050
24457
|
const { privateKey, kid } = await getKeys();
|
|
24051
|
-
return new SignJWT({ scope, plan }).setProtectedHeader({ alg: "RS256", kid }).setIssuer(ISSUER).setSubject(identity).setAudience(audience).setIssuedAt().setJti(
|
|
24458
|
+
return new SignJWT({ scope, plan }).setProtectedHeader({ alg: "RS256", kid }).setIssuer(ISSUER).setSubject(identity).setAudience(audience).setIssuedAt().setJti(randomUUID11()).setExpirationTime(`${ACCESS_TTL_SECONDS}s`).sign(privateKey);
|
|
24052
24459
|
}
|
|
24053
24460
|
function tokenErrorResponse(c, error, description, status) {
|
|
24054
24461
|
return c.json({ error, error_description: description }, status);
|
|
@@ -24121,8 +24528,8 @@ oauthApp.post("/oauth/token", async (c) => {
|
|
|
24121
24528
|
});
|
|
24122
24529
|
|
|
24123
24530
|
// src/api/chat-routes.ts
|
|
24124
|
-
import { Hono as
|
|
24125
|
-
var chatApp = new
|
|
24531
|
+
import { Hono as Hono24 } from "hono";
|
|
24532
|
+
var chatApp = new Hono24();
|
|
24126
24533
|
function tokenOk(token) {
|
|
24127
24534
|
return !!token && token.startsWith("mk_") && token.length > 10;
|
|
24128
24535
|
}
|
|
@@ -24792,7 +25199,7 @@ loadChannels();
|
|
|
24792
25199
|
}
|
|
24793
25200
|
|
|
24794
25201
|
// src/api/vault-routes.ts
|
|
24795
|
-
import { Hono as
|
|
25202
|
+
import { Hono as Hono25 } from "hono";
|
|
24796
25203
|
var VAULTS = ["People", "Organizations", "Deals", "Projects", "Tasks", "Communications", "Calendar"];
|
|
24797
25204
|
var PROJECT_TYPES = ["codebase", "personal", "work", "client"];
|
|
24798
25205
|
var PROJECT_KIND_BY_TYPE = {
|
|
@@ -24811,7 +25218,7 @@ var PROJECT_TYPE_BY_KIND = {
|
|
|
24811
25218
|
var MAX_VAULT_RECORDS = 200;
|
|
24812
25219
|
var MAX_MEMORY_READ_CONCURRENCY = 4;
|
|
24813
25220
|
var MAX_MEMORY_READ_ATTEMPTS = 3;
|
|
24814
|
-
var vaultApp = new
|
|
25221
|
+
var vaultApp = new Hono25();
|
|
24815
25222
|
function validToken(token) {
|
|
24816
25223
|
return !!token && token.startsWith("mk_") && token.length > 20 && token.length < 256;
|
|
24817
25224
|
}
|
|
@@ -25160,8 +25567,8 @@ vaultApp.post("/api/activity", async (c) => {
|
|
|
25160
25567
|
});
|
|
25161
25568
|
|
|
25162
25569
|
// src/api/schedule-routes.ts
|
|
25163
|
-
import { Hono as
|
|
25164
|
-
var scheduleApp = new
|
|
25570
|
+
import { Hono as Hono26 } from "hono";
|
|
25571
|
+
var scheduleApp = new Hono26();
|
|
25165
25572
|
function tokenOk2(token) {
|
|
25166
25573
|
return !!token && token.startsWith("mk_") && token.length > 10;
|
|
25167
25574
|
}
|
|
@@ -25492,7 +25899,7 @@ loadActions();
|
|
|
25492
25899
|
}
|
|
25493
25900
|
|
|
25494
25901
|
// src/api/resend-inbound-routes.ts
|
|
25495
|
-
import { Hono as
|
|
25902
|
+
import { Hono as Hono27 } from "hono";
|
|
25496
25903
|
import { Resend } from "resend";
|
|
25497
25904
|
|
|
25498
25905
|
// src/api/resend-support-thread.ts
|
|
@@ -26123,7 +26530,7 @@ async function relayOperatorReply(resend, email, customerEmail, threadAddress, n
|
|
|
26123
26530
|
if (sent.error) throw new Error(`support reply relay failed: ${sent.error.message}`);
|
|
26124
26531
|
return sent.data.id;
|
|
26125
26532
|
}
|
|
26126
|
-
var resendInboundApp = new
|
|
26533
|
+
var resendInboundApp = new Hono27();
|
|
26127
26534
|
resendInboundApp.post("/webhooks", async (c) => {
|
|
26128
26535
|
const apiKey = process.env.RESEND_API_KEY?.trim();
|
|
26129
26536
|
const webhookSecret = process.env.RESEND_WEBHOOK_SECRET?.trim();
|
|
@@ -26279,7 +26686,7 @@ function startSiteAuditWorker() {
|
|
|
26279
26686
|
}
|
|
26280
26687
|
|
|
26281
26688
|
// src/api/server.ts
|
|
26282
|
-
import { createMiddleware as
|
|
26689
|
+
import { createMiddleware as createMiddleware4 } from "hono/factory";
|
|
26283
26690
|
import { getCookie as getCookie2, setCookie as setCookie2, deleteCookie } from "hono/cookie";
|
|
26284
26691
|
import Stripe2 from "stripe";
|
|
26285
26692
|
|
|
@@ -26771,7 +27178,7 @@ async function cleanupExpiredScrapeBlobs(maxAgeMs = SCRAPE_BLOB_TTL_MS) {
|
|
|
26771
27178
|
}
|
|
26772
27179
|
|
|
26773
27180
|
// src/api/connected-data-export.ts
|
|
26774
|
-
import { randomUUID as
|
|
27181
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
26775
27182
|
var CONNECTED_DATA_INLINE_BUDGET_BYTES = Number(
|
|
26776
27183
|
process.env.MCP_SCRAPER_CONNECTED_DATA_INLINE_BUDGET_BYTES ?? 5e4
|
|
26777
27184
|
);
|
|
@@ -26897,7 +27304,7 @@ function finitePositive(value, fallback) {
|
|
|
26897
27304
|
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
26898
27305
|
}
|
|
26899
27306
|
async function collectConnectedDataExport(args) {
|
|
26900
|
-
const exportId =
|
|
27307
|
+
const exportId = randomUUID12();
|
|
26901
27308
|
const now = args.now ?? Date.now;
|
|
26902
27309
|
const startedAt = now();
|
|
26903
27310
|
const budgetMs = finitePositive(CONNECTED_DATA_EXPORT_BUDGET_MS, 24e4);
|
|
@@ -27009,7 +27416,7 @@ ${lines.length ? `${lines.join("\n")}
|
|
|
27009
27416
|
}
|
|
27010
27417
|
|
|
27011
27418
|
// src/api/search-console-table-export.ts
|
|
27012
|
-
import { randomUUID as
|
|
27419
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
27013
27420
|
var SEARCH_CONSOLE_TABLE_EXPORT_MAX_ROWS = 5e4;
|
|
27014
27421
|
var SEARCH_CONSOLE_TABLE_EXPORT_PAGE_SIZE = 2e3;
|
|
27015
27422
|
var SEARCH_CONSOLE_TABLE_EXPORT_MAX_BYTES = 50 * 1024 * 1024;
|
|
@@ -27109,7 +27516,7 @@ async function exportSearchConsoleTableData(args) {
|
|
|
27109
27516
|
offset += rows.length;
|
|
27110
27517
|
if (stoppedForBytes || rows.length < limit || offset >= matchedRows) break;
|
|
27111
27518
|
}
|
|
27112
|
-
const exportId =
|
|
27519
|
+
const exportId = randomUUID13();
|
|
27113
27520
|
const artifact = await args.writeArtifact({
|
|
27114
27521
|
ownerId: args.ownerId,
|
|
27115
27522
|
exportId,
|
|
@@ -27344,15 +27751,15 @@ async function dbUsage(identity, plan) {
|
|
|
27344
27751
|
}
|
|
27345
27752
|
|
|
27346
27753
|
// src/api/nango-control.ts
|
|
27347
|
-
import { createHash as createHash12, randomUUID as
|
|
27754
|
+
import { createHash as createHash12, randomUUID as randomUUID16 } from "crypto";
|
|
27348
27755
|
|
|
27349
27756
|
// src/api/main-nango-transport.ts
|
|
27350
|
-
import { createHash as createHash11, randomUUID as
|
|
27757
|
+
import { createHash as createHash11, randomUUID as randomUUID15 } from "crypto";
|
|
27351
27758
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
27352
27759
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
27353
27760
|
|
|
27354
27761
|
// src/api/service-connections.ts
|
|
27355
|
-
import { randomUUID as
|
|
27762
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
27356
27763
|
var schemaReady2 = null;
|
|
27357
27764
|
var schemaDb2 = null;
|
|
27358
27765
|
function ensureServiceConnectionsSchema() {
|
|
@@ -27486,7 +27893,7 @@ async function reconcileDiscoveredNangoConnections(identity, discovered) {
|
|
|
27486
27893
|
updated_at = excluded.updated_at
|
|
27487
27894
|
`,
|
|
27488
27895
|
args: [
|
|
27489
|
-
|
|
27896
|
+
randomUUID14(),
|
|
27490
27897
|
userId,
|
|
27491
27898
|
connection.providerConfigKey,
|
|
27492
27899
|
connection.provider,
|
|
@@ -27557,7 +27964,7 @@ async function recordServiceConnectionHealth(args) {
|
|
|
27557
27964
|
});
|
|
27558
27965
|
await getDb().execute({
|
|
27559
27966
|
sql: `INSERT INTO service_connection_health_events (id, connection_id, operational_status, failure_code, retryable, evidence_source) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
27560
|
-
args: [
|
|
27967
|
+
args: [randomUUID14(), args.connectionId, args.operationalStatus, args.failureCode ?? null, args.retryable == null ? null : args.retryable ? 1 : 0, args.evidenceSource]
|
|
27561
27968
|
});
|
|
27562
27969
|
}
|
|
27563
27970
|
async function setServiceConnectionActions(identity, connectionId, enabled) {
|
|
@@ -27597,7 +28004,7 @@ async function claimServiceConnectionAction(args) {
|
|
|
27597
28004
|
if (!connection) throw new Error("service_connection_not_found");
|
|
27598
28005
|
const inserted = await getDb().execute({
|
|
27599
28006
|
sql: `INSERT OR IGNORE INTO service_connection_action_audit (id, connection_id, user_id, tool, request_id, status) VALUES (?, ?, ?, ?, ?, 'started')`,
|
|
27600
|
-
args: [
|
|
28007
|
+
args: [randomUUID14(), connection.id, connection.userId, args.tool, args.requestId]
|
|
27601
28008
|
});
|
|
27602
28009
|
if (Number(inserted.rowsAffected ?? 0) === 1) return { claimed: true };
|
|
27603
28010
|
const existing = await getDb().execute({
|
|
@@ -27959,7 +28366,7 @@ async function callNangoToolDirect(args) {
|
|
|
27959
28366
|
identity: args.identity,
|
|
27960
28367
|
ratePolicyVersion: CONNECTED_USAGE_RATE_POLICY_VERSION
|
|
27961
28368
|
});
|
|
27962
|
-
const requestId = args.requestId?.trim() ||
|
|
28369
|
+
const requestId = args.requestId?.trim() || randomUUID15();
|
|
27963
28370
|
const idempotencyKey2 = `main-nango:${createHash11("sha256").update(args.identity.toLowerCase()).update("\0").update(connection.id).update("\0").update(args.tool).update("\0").update(requestId).digest("hex")}`;
|
|
27964
28371
|
const startedAt = /* @__PURE__ */ new Date();
|
|
27965
28372
|
const started = performance.now();
|
|
@@ -28746,7 +29153,7 @@ async function setScheduleConnectionActionsEnabled(identity, connectionId, enabl
|
|
|
28746
29153
|
return data.connection.actionsEnabled === true;
|
|
28747
29154
|
}
|
|
28748
29155
|
async function callScheduleConnectionAction(identity, connectionId, input, tool, idempotencyKey2) {
|
|
28749
|
-
const requestId = `main-connected-action:${createHash12("sha256").update(identity).update("\0").update(idempotencyKey2?.trim() ||
|
|
29156
|
+
const requestId = `main-connected-action:${createHash12("sha256").update(identity).update("\0").update(idempotencyKey2?.trim() || randomUUID16()).digest("hex")}`;
|
|
28750
29157
|
if (mainOwnsIntegrations()) {
|
|
28751
29158
|
const selectedTool = tool?.trim();
|
|
28752
29159
|
if (!selectedTool) throw new NangoControlError("An action tool is required.", 400, "invalid_request", false);
|
|
@@ -29587,13 +29994,13 @@ async function enforceRateLimit(c, scope, key, limit, windowSeconds) {
|
|
|
29587
29994
|
{ "Retry-After": String(result.resetSeconds) }
|
|
29588
29995
|
);
|
|
29589
29996
|
}
|
|
29590
|
-
var requireAllowedOrigin =
|
|
29997
|
+
var requireAllowedOrigin = createMiddleware4(async (c, next) => {
|
|
29591
29998
|
const origin = c.req.header("origin");
|
|
29592
29999
|
if (!origin) return next();
|
|
29593
30000
|
if (!configuredOrigins().has(origin)) return c.json({ error: "Origin not allowed" }, 403);
|
|
29594
30001
|
return next();
|
|
29595
30002
|
});
|
|
29596
|
-
var auth2 =
|
|
30003
|
+
var auth2 = createMiddleware4(async (c, next) => {
|
|
29597
30004
|
const key = c.req.header("x-api-key");
|
|
29598
30005
|
if (!key) return c.json({ error: "Missing API key" }, 401);
|
|
29599
30006
|
const user = await getUserByApiKey(key);
|
|
@@ -29603,14 +30010,7 @@ var auth2 = createMiddleware3(async (c, next) => {
|
|
|
29603
30010
|
c.set("user", { ...refreshed, balance_mc: balanceMc });
|
|
29604
30011
|
return next();
|
|
29605
30012
|
});
|
|
29606
|
-
var
|
|
29607
|
-
const configured = process.env.ADMIN_KEY?.trim();
|
|
29608
|
-
const key = c.req.header("x-admin-key")?.trim();
|
|
29609
|
-
if (!configured) return c.json({ error: "Admin access disabled" }, 503);
|
|
29610
|
-
if (!key || key !== configured) return c.json({ error: "Unauthorized" }, 401);
|
|
29611
|
-
return next();
|
|
29612
|
-
});
|
|
29613
|
-
var sessionAuth = createMiddleware3(async (c, next) => {
|
|
30013
|
+
var sessionAuth = createMiddleware4(async (c, next) => {
|
|
29614
30014
|
const token = getCookie2(c, "session");
|
|
29615
30015
|
if (!token) return c.json({ error: "Not authenticated" }, 401);
|
|
29616
30016
|
const userId = verifySession(token);
|
|
@@ -29622,7 +30022,7 @@ var sessionAuth = createMiddleware3(async (c, next) => {
|
|
|
29622
30022
|
c.set("sessionUser", { ...refreshed, balance_mc: balanceMc });
|
|
29623
30023
|
return next();
|
|
29624
30024
|
});
|
|
29625
|
-
var requireIntegrationsTier =
|
|
30025
|
+
var requireIntegrationsTier = createMiddleware4(async (c, next) => {
|
|
29626
30026
|
const user = c.get("user");
|
|
29627
30027
|
if (!user.subscription_tier) {
|
|
29628
30028
|
return c.json({
|
|
@@ -29633,12 +30033,12 @@ var requireIntegrationsTier = createMiddleware3(async (c, next) => {
|
|
|
29633
30033
|
}
|
|
29634
30034
|
return next();
|
|
29635
30035
|
});
|
|
29636
|
-
var requirePaidSchedulingTier =
|
|
30036
|
+
var requirePaidSchedulingTier = createMiddleware4(async (c, next) => {
|
|
29637
30037
|
const user = c.get("user");
|
|
29638
30038
|
if (!hasPaidSchedulingAccess(user)) return c.json(paidPlanRequiredPayload(), 403);
|
|
29639
30039
|
return next();
|
|
29640
30040
|
});
|
|
29641
|
-
var app = new
|
|
30041
|
+
var app = new Hono28();
|
|
29642
30042
|
var STRIPE_API_VERSION = "2026-02-25.clover";
|
|
29643
30043
|
function requireStripeSecret() {
|
|
29644
30044
|
const secret2 = process.env.STRIPE_SECRET_KEY?.trim();
|
|
@@ -32283,7 +32683,7 @@ app.get("/cron/tick", async (c) => {
|
|
|
32283
32683
|
if (!process.env.CRON_SECRET || secret2 !== `Bearer ${process.env.CRON_SECRET}`) {
|
|
32284
32684
|
return c.json({ error: "Unauthorized" }, 401);
|
|
32285
32685
|
}
|
|
32286
|
-
const { drainQueue } = await import("./worker-
|
|
32686
|
+
const { drainQueue } = await import("./worker-TTFXPPDK.js");
|
|
32287
32687
|
const budget = { maxJobs: 10, deadlineMs: Date.now() + 28e4 };
|
|
32288
32688
|
const workflowDispatchResult = await dispatchDueWorkflowSchedules(`${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`);
|
|
32289
32689
|
const [results, sweepResult, reapResult, expiredResult, blobCleanup, connectedDataArtifactCleanup, connectedAccountBilling, directoryWorkflowDispatch, directoryWorkflowReconciliation, directoryArtifactCleanup, siteExtractArtifactCleanup, siteExtractRedispatch, siteExtractReconciliation] = await Promise.all([
|
|
@@ -32332,8 +32732,8 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
|
|
|
32332
32732
|
finishExtractJob: finishExtractJob2,
|
|
32333
32733
|
terminalExtractJobStatus: terminalExtractJobStatus2,
|
|
32334
32734
|
extractJobLimitInfo: extractJobLimitInfo2
|
|
32335
|
-
} = await import("./site-extract-repository-
|
|
32336
|
-
const { assembleExtractArtifacts } = await import("./extract-bundle-
|
|
32735
|
+
} = await import("./site-extract-repository-I3VM6WXN.js");
|
|
32736
|
+
const { assembleExtractArtifacts } = await import("./extract-bundle-346R6MXD.js");
|
|
32337
32737
|
const existing = await getExtractJob2(jobId2);
|
|
32338
32738
|
if (!existing) return c.json({ error: "job not found" }, 404);
|
|
32339
32739
|
if (existing.status !== "failed") {
|
|
@@ -32360,7 +32760,7 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
|
|
|
32360
32760
|
if (!updated) return c.json({ error: "job state changed during re-finalization" }, 409);
|
|
32361
32761
|
let settlement = "already_settled_or_refunded";
|
|
32362
32762
|
if (job.billedMc == null && job.userId != null) {
|
|
32363
|
-
const { settleExtractJob: settleExtractJob3, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-
|
|
32763
|
+
const { settleExtractJob: settleExtractJob3, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-I3VM6WXN.js");
|
|
32364
32764
|
const heldMc = Number(job.options.heldMc ?? 0);
|
|
32365
32765
|
const successful = await countSuccessfulPages2(jobId2);
|
|
32366
32766
|
const usedMc = Math.min(successful * MC_COSTS.page_scrape, heldMc);
|
|
@@ -32376,6 +32776,7 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
|
|
|
32376
32776
|
return c.json({ ok: true, jobId: jobId2, artifacts: stored.length, settlement, bundleUrl: bundle?.url ?? null, bundleBytes: bundle?.bytes ?? null });
|
|
32377
32777
|
});
|
|
32378
32778
|
app.on(["GET", "POST", "PUT"], "/api/inngest", serveInngest({ client: inngest, functions: [siteAuditFn, siteExtractFn, directoryWorkflowFn] }));
|
|
32779
|
+
app.route("/admin/credits", adminCreditsApp);
|
|
32379
32780
|
app.route("/api/internal/site-architecture-auditor", siteAuditApp);
|
|
32380
32781
|
app.route("/api/internal/memory", internalMemoryApp);
|
|
32381
32782
|
app.route("/api/internal/billing", internalBillingApp);
|
|
@@ -32530,4 +32931,4 @@ app.get("/blog/:slug/", (c) => {
|
|
|
32530
32931
|
export {
|
|
32531
32932
|
app
|
|
32532
32933
|
};
|
|
32533
|
-
//# sourceMappingURL=server-
|
|
32934
|
+
//# sourceMappingURL=server-QKDDEBVQ.js.map
|