mcp-scraper 0.56.0 → 0.57.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/CHANGELOG.md +18 -0
- package/README.md +2 -2
- package/dist/bin/api-server.cjs +564 -156
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +2 -2
- 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 +2 -2
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.cjs +25 -2
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +4 -4
- package/dist/{chunk-NP66MZ5A.js → chunk-5XYBKE3X.js} +2 -2
- package/dist/{chunk-LUJYVNO7.js → chunk-HU4R6BP2.js} +2 -2
- package/dist/{chunk-LUJYVNO7.js.map → chunk-HU4R6BP2.js.map} +1 -1
- package/dist/chunk-QQ6ZBYZZ.js +7 -0
- package/dist/chunk-QQ6ZBYZZ.js.map +1 -0
- package/dist/{chunk-WO2SSENO.js → chunk-R6CO77BN.js} +3 -3
- package/dist/{chunk-WO2SSENO.js.map → chunk-R6CO77BN.js.map} +1 -1
- package/dist/{chunk-JEZW6N2X.js → chunk-ULAJAZQF.js} +26 -3
- package/dist/chunk-ULAJAZQF.js.map +1 -0
- package/dist/{extract-bundle-6KYTD55T.js → extract-bundle-H7JEELY7.js} +3 -3
- package/dist/{server-SETYJPYO.js → server-NBGZJX4P.js} +447 -72
- package/dist/server-NBGZJX4P.js.map +1 -0
- package/dist/{site-extract-repository-YGNYFTNE.js → site-extract-repository-CFMSWAVL.js} +3 -3
- package/dist/{worker-DTVBN3RQ.js → worker-S2WXELUC.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-245IAJ7R.js +0 -7
- package/dist/chunk-245IAJ7R.js.map +0 -1
- package/dist/chunk-JEZW6N2X.js.map +0 -1
- package/dist/server-SETYJPYO.js.map +0 -1
- /package/dist/{chunk-NP66MZ5A.js.map → chunk-5XYBKE3X.js.map} +0 -0
- /package/dist/{extract-bundle-6KYTD55T.js.map → extract-bundle-H7JEELY7.js.map} +0 -0
- /package/dist/{site-extract-repository-YGNYFTNE.js.map → site-extract-repository-CFMSWAVL.js.map} +0 -0
- /package/dist/{worker-DTVBN3RQ.js.map → worker-S2WXELUC.js.map} +0 -0
package/dist/bin/api-server.cjs
CHANGED
|
@@ -12455,8 +12455,8 @@ var init_product_contract_generated = __esm({
|
|
|
12455
12455
|
"freeSignupCredits": 0
|
|
12456
12456
|
},
|
|
12457
12457
|
"inventory": {
|
|
12458
|
-
"totalTools":
|
|
12459
|
-
"scraperTools":
|
|
12458
|
+
"totalTools": 251,
|
|
12459
|
+
"scraperTools": 150,
|
|
12460
12460
|
"memoryTools": 101
|
|
12461
12461
|
},
|
|
12462
12462
|
"concurrencyPack": {
|
|
@@ -44624,7 +44624,7 @@ var PACKAGE_VERSION;
|
|
|
44624
44624
|
var init_version = __esm({
|
|
44625
44625
|
"src/version.ts"() {
|
|
44626
44626
|
"use strict";
|
|
44627
|
-
PACKAGE_VERSION = "0.
|
|
44627
|
+
PACKAGE_VERSION = "0.57.0";
|
|
44628
44628
|
}
|
|
44629
44629
|
});
|
|
44630
44630
|
|
|
@@ -46453,7 +46453,7 @@ var init_contracts = __esm({
|
|
|
46453
46453
|
});
|
|
46454
46454
|
|
|
46455
46455
|
// src/mcp/mcp-tool-schemas.ts
|
|
46456
|
-
var import_zod43, WEBSITE_URL_OR_DOMAIN_ERROR, WebsiteUrlOrDomainSchema, HarvestPaaInputSchema, ExtractUrlBaseInputSchema, ExtractUrlInputSchema, ExtractUrlLocalInputSchema, DiffPageBaseInputSchema, DiffPageInputSchema, DiffPageLocalInputSchema, MapSiteUrlsInputSchema, MapWaybackSnapshotsInputSchema, ExtractSiteInputSchema, AuditSiteInputSchema, CheckSiteExportInputSchema, ArchiveReadInputSchema, YoutubeHarvestInputSchema, YoutubeTranscribeInputSchema, FacebookPageIntelInputSchema, FacebookAdSearchInputSchema, RedditThreadInputSchema, RedditTrendingInputSchema, VideoFrameAnalysisInputSchema, VideoFrameAnalysisStatusInputSchema, FacebookAdTranscribeInputSchema, FacebookVideoTranscribeInputSchema, GoogleAdsSearchInputSchema, GoogleAdsPageIntelInputSchema, GoogleAdsTranscribeInputSchema, InstagramProfileContentInputSchema, InstagramMediaDownloadInputSchema, MapsPlaceIntelInputSchema, TrustpilotReviewsInputSchema, G2ReviewsInputSchema, ReviewCardSchema, MapsSearchInputSchema, DirectoryWorkflowInputSchema, LocationMarketsInputSchema, CommonsSearchEntitiesInputSchema, CommonsGetEntityInputSchema, CommonsGetEntityLinksetInputSchema, CommonsFeaturedImageInputSchema, CommonsMediaInputSchema, CommonsCitationInputSchema, CommonsSourceInputSchema, CommonsRelatedLinkInputSchema, CommonsClaimInputSchema, CommonsPrepareEntityInputSchema, CommonsSubmitEntityInputSchema, CommonsValidateEntityInputSchema, CommonsGetEntityLedgerInputSchema, CommonsGetProposalInputSchema, CommonsSaveFilterInputSchema, CommonsListFiltersInputSchema, CommonsListNeedsLinksInputSchema, CommonsGenericOutputSchema, DirectoryWorkflowStatusInputSchema, LocalSourcebookSubmitInputSchema, LocalSourcebookCategorySchema, LocalSourcebookSchemaTypeInputSchema, LocalSourcebookTagCandidateObjectSchema, LocalSourcebookTagDecisionObjectSchema, LocalSourcebookIdentityObjectSchema, GetLocalSourcebookContractInputSchema, ListLocalSourcebookTagsInputSchema, ResolveLocalSourcebookTagsInputSchema, PrepareLocalSourcebookWriteInputSchema, ValidateLocalSourcebookWriteInputSchema, LocalSourcebookCaptureInputSchema, LocalSourcebookSubmissionStatusInputSchema, LocalSourcebookRefreshInputSchema, LocalSourcebookOutputSchema, ArtifactPointerOutputSchema, EditorialReadingRoomSiteSchema, EditorialReadingRoomImageSchema, EditorialReadingRoomArticleSchema, EditorialReadingRoomGuideInputSchema, EditorialReadingRoomGuideOutputSchema, CreateEditorialReadingRoomInputSchema, EditorialReadingRoomArtifactSchema, CreateEditorialReadingRoomOutputSchema, RenewEditorialReadingRoomDownloadInputSchema, RenewEditorialReadingRoomDownloadOutputSchema, CommonsPublicationSubdomainSchema, CommonsPreparePublicationInputSchema, CommonsValidatePublicationInputSchema, CommonsClaimPublicationInputSchema, CommonsPublishEditorialInputSchema, CommonsGetPublicationInputSchema, RankTrackerModeSchema, RankTrackerBlueprintInputSchema, NullableString, MapsSearchAttemptOutput, MapsSearchOutputSchema, DirectoryMapsBusinessOutput, DirectoryCsvArtifactOutput, DirectoryWorkflowOutputSchema, LocationDatasetProvenanceOutput, LocationMarketsOutputSchema, RankTrackerToolPlanOutput, RankTrackerTableOutput, RankTrackerCronJobOutput, RankTrackerBlueprintOutputSchema, OrganicResultOutput, AiOverviewOutput, EntityIdsOutput, HarvestPaaOutputSchema, SearchSerpOutputSchema, PageMediaAssetOutput, PageMediaArtifactOutput, ExtractUrlOutputSchema, DiffPageOutputSchema, ExtractSiteOutputSchema, AuditSiteOutputSchema, CheckSiteExportOutputSchema, ArchiveEntryOutputSchema, ArchiveReadOutputSchema, MapsPlaceIntelOutputSchema, TrustpilotReviewsOutputSchema, G2ReviewsOutputSchema, CreditsInfoOutputSchema, MapSiteUrlsOutputSchema, WaybackCaptureOutputSchema, MapWaybackSnapshotsOutputSchema, YoutubeHarvestOutputSchema, FacebookAdSearchOutputSchema, VideoFrameAnalysisOutputSchema, VideoFrameAnalysisStatusOutputSchema, RedditThreadOutputSchema, RedditTrendingOutputSchema, FacebookPageIntelOutputSchema, GoogleAdsSearchOutputSchema, GoogleAdsPageIntelOutputSchema, TranscriptSignalOutput, FacebookVideoTranscribeOutputSchema, TranscriptChunkOutput, InstagramBrowserOutput, InstagramPaginationOutput, InstagramProfileContentOutputSchema, InstagramMediaTrackOutput, InstagramDownloadOutput, InstagramMediaDownloadOutputSchema, YoutubeTranscribeOutputSchema, FacebookAdTranscribeOutputSchema, GoogleAdsTranscribeOutputSchema, CaptureSerpSnapshotOutputSchema, CaptureSerpPageSnapshotsOutputSchema, CreditsInfoInputSchema, WorkflowIdSchema2, WorkflowListInputSchema, WorkflowSuggestInputSchema, WorkflowRunInputSchema, WorkflowStepInputSchema, WorkflowStatusInputSchema, WorkflowArtifactReadInputSchema, WorkflowRecipeOutput, WorkflowDefinitionOutput, WorkflowArtifactOutput, WorkflowListOutputSchema, WorkflowSuggestOutputSchema, WorkflowRunOutputSchema, WorkflowStepOutputSchema, WorkflowStatusOutputSchema, WorkflowArtifactReadOutputSchema, SearchSerpInputSchema, CaptureSerpSnapshotInputSchema, ScreenshotInputSchema, CaptureSerpPageSnapshotsInputSchema, ReportArtifactReadInputSchema, ReportArtifactReadOutputSchema, ListServiceConnectionsInputSchema, ListServiceConnectionsOutputSchema, TestServiceConnectionInputSchema, TestServiceConnectionOutputSchema, ReadServiceConnectionInputSchema, ReadServiceConnectionOutputSchema, MetaAdCreativeMediaInputSchema, MetaAdCreativeMediaOutputSchema, ImportServiceConnectionToMemoryInputSchema, ImportServiceConnectionToMemoryOutputSchema, DescribeServiceConnectionToolInputSchema, DescribeServiceConnectionToolOutputSchema, ConnectedDataContinuationSchema, ExportConnectedServiceDataInputSchema, ConnectedDataArtifactSchema, ExportConnectedServiceDataOutputSchema, SearchConsoleTableColumnSchema, SearchConsoleTableFilterSchema, ExportSearchConsoleTableDataInputSchema, ExportSearchConsoleTableDataOutputSchema, RenewConnectedDataExportDownloadInputSchema, RenewConnectedDataExportDownloadOutputSchema, CallServiceConnectionActionInputSchema, CallServiceConnectionActionOutputSchema, SetScheduledActionConnectionsInputSchema, SetScheduledActionConnectionsOutputSchema, SlackSendMessageInputSchema, SlackSendMessageOutputSchema, GmailSendMessageInputSchema, GmailSendMessageOutputSchema, GmailSearchContactsInputSchema, GmailSearchContactsOutputSchema, GoogleCalendarCreateEventInputSchema, GoogleCalendarCreateEventOutputSchema, ZoomCreateMeetingInputSchema, ZoomCreateMeetingOutputSchema;
|
|
46456
|
+
var import_zod43, WEBSITE_URL_OR_DOMAIN_ERROR, WebsiteUrlOrDomainSchema, HarvestPaaInputSchema, ExtractUrlBaseInputSchema, ExtractUrlInputSchema, ExtractUrlLocalInputSchema, DiffPageBaseInputSchema, DiffPageInputSchema, DiffPageLocalInputSchema, MapSiteUrlsInputSchema, MapWaybackSnapshotsInputSchema, ExtractSiteInputSchema, AuditSiteInputSchema, CheckSiteExportInputSchema, ArchiveReadInputSchema, YoutubeHarvestInputSchema, YoutubeTranscribeInputSchema, FacebookPageIntelInputSchema, FacebookAdSearchInputSchema, RedditThreadInputSchema, RedditTrendingInputSchema, VideoFrameAnalysisInputSchema, VideoFrameAnalysisStatusInputSchema, FacebookAdTranscribeInputSchema, FacebookVideoTranscribeInputSchema, GoogleAdsSearchInputSchema, GoogleAdsPageIntelInputSchema, GoogleAdsTranscribeInputSchema, InstagramProfileContentInputSchema, InstagramMediaDownloadInputSchema, MapsPlaceIntelInputSchema, TrustpilotReviewsInputSchema, G2ReviewsInputSchema, ReviewCardSchema, MapsSearchInputSchema, DirectoryWorkflowInputSchema, LocationMarketsInputSchema, CommonsSearchEntitiesInputSchema, CommonsGetEntityInputSchema, CommonsGetEntityLinksetInputSchema, CommonsFeaturedImageInputSchema, CommonsMediaInputSchema, CommonsCitationInputSchema, CommonsSourceInputSchema, CommonsRelatedLinkInputSchema, CommonsClaimInputSchema, CommonsPrepareEntityInputSchema, CommonsSubmitEntityInputSchema, CommonsValidateEntityInputSchema, CommonsGetEntityLedgerInputSchema, CommonsHostImageInputSchema, CommonsGetProposalInputSchema, CommonsSaveFilterInputSchema, CommonsListFiltersInputSchema, CommonsListNeedsLinksInputSchema, CommonsGenericOutputSchema, DirectoryWorkflowStatusInputSchema, LocalSourcebookSubmitInputSchema, LocalSourcebookCategorySchema, LocalSourcebookSchemaTypeInputSchema, LocalSourcebookTagCandidateObjectSchema, LocalSourcebookTagDecisionObjectSchema, LocalSourcebookIdentityObjectSchema, GetLocalSourcebookContractInputSchema, ListLocalSourcebookTagsInputSchema, ResolveLocalSourcebookTagsInputSchema, PrepareLocalSourcebookWriteInputSchema, ValidateLocalSourcebookWriteInputSchema, LocalSourcebookCaptureInputSchema, LocalSourcebookSubmissionStatusInputSchema, LocalSourcebookRefreshInputSchema, LocalSourcebookOutputSchema, ArtifactPointerOutputSchema, EditorialReadingRoomSiteSchema, EditorialReadingRoomImageSchema, EditorialReadingRoomArticleSchema, EditorialReadingRoomGuideInputSchema, EditorialReadingRoomGuideOutputSchema, CreateEditorialReadingRoomInputSchema, EditorialReadingRoomArtifactSchema, CreateEditorialReadingRoomOutputSchema, RenewEditorialReadingRoomDownloadInputSchema, RenewEditorialReadingRoomDownloadOutputSchema, CommonsPublicationSubdomainSchema, CommonsPreparePublicationInputSchema, CommonsValidatePublicationInputSchema, CommonsClaimPublicationInputSchema, CommonsPublishEditorialInputSchema, CommonsGetPublicationInputSchema, RankTrackerModeSchema, RankTrackerBlueprintInputSchema, NullableString, MapsSearchAttemptOutput, MapsSearchOutputSchema, DirectoryMapsBusinessOutput, DirectoryCsvArtifactOutput, DirectoryWorkflowOutputSchema, LocationDatasetProvenanceOutput, LocationMarketsOutputSchema, RankTrackerToolPlanOutput, RankTrackerTableOutput, RankTrackerCronJobOutput, RankTrackerBlueprintOutputSchema, OrganicResultOutput, AiOverviewOutput, EntityIdsOutput, HarvestPaaOutputSchema, SearchSerpOutputSchema, PageMediaAssetOutput, PageMediaArtifactOutput, ExtractUrlOutputSchema, DiffPageOutputSchema, ExtractSiteOutputSchema, AuditSiteOutputSchema, CheckSiteExportOutputSchema, ArchiveEntryOutputSchema, ArchiveReadOutputSchema, MapsPlaceIntelOutputSchema, TrustpilotReviewsOutputSchema, G2ReviewsOutputSchema, CreditsInfoOutputSchema, MapSiteUrlsOutputSchema, WaybackCaptureOutputSchema, MapWaybackSnapshotsOutputSchema, YoutubeHarvestOutputSchema, FacebookAdSearchOutputSchema, VideoFrameAnalysisOutputSchema, VideoFrameAnalysisStatusOutputSchema, RedditThreadOutputSchema, RedditTrendingOutputSchema, FacebookPageIntelOutputSchema, GoogleAdsSearchOutputSchema, GoogleAdsPageIntelOutputSchema, TranscriptSignalOutput, FacebookVideoTranscribeOutputSchema, TranscriptChunkOutput, InstagramBrowserOutput, InstagramPaginationOutput, InstagramProfileContentOutputSchema, InstagramMediaTrackOutput, InstagramDownloadOutput, InstagramMediaDownloadOutputSchema, YoutubeTranscribeOutputSchema, FacebookAdTranscribeOutputSchema, GoogleAdsTranscribeOutputSchema, CaptureSerpSnapshotOutputSchema, CaptureSerpPageSnapshotsOutputSchema, CreditsInfoInputSchema, WorkflowIdSchema2, WorkflowListInputSchema, WorkflowSuggestInputSchema, WorkflowRunInputSchema, WorkflowStepInputSchema, WorkflowStatusInputSchema, WorkflowArtifactReadInputSchema, WorkflowRecipeOutput, WorkflowDefinitionOutput, WorkflowArtifactOutput, WorkflowListOutputSchema, WorkflowSuggestOutputSchema, WorkflowRunOutputSchema, WorkflowStepOutputSchema, WorkflowStatusOutputSchema, WorkflowArtifactReadOutputSchema, SearchSerpInputSchema, CaptureSerpSnapshotInputSchema, ScreenshotInputSchema, CaptureSerpPageSnapshotsInputSchema, ReportArtifactReadInputSchema, ReportArtifactReadOutputSchema, ListServiceConnectionsInputSchema, ListServiceConnectionsOutputSchema, TestServiceConnectionInputSchema, TestServiceConnectionOutputSchema, ReadServiceConnectionInputSchema, ReadServiceConnectionOutputSchema, MetaAdCreativeMediaInputSchema, MetaAdCreativeMediaOutputSchema, ImportServiceConnectionToMemoryInputSchema, ImportServiceConnectionToMemoryOutputSchema, DescribeServiceConnectionToolInputSchema, DescribeServiceConnectionToolOutputSchema, ConnectedDataContinuationSchema, ExportConnectedServiceDataInputSchema, ConnectedDataArtifactSchema, ExportConnectedServiceDataOutputSchema, SearchConsoleTableColumnSchema, SearchConsoleTableFilterSchema, ExportSearchConsoleTableDataInputSchema, ExportSearchConsoleTableDataOutputSchema, RenewConnectedDataExportDownloadInputSchema, RenewConnectedDataExportDownloadOutputSchema, CallServiceConnectionActionInputSchema, CallServiceConnectionActionOutputSchema, SetScheduledActionConnectionsInputSchema, SetScheduledActionConnectionsOutputSchema, SlackSendMessageInputSchema, SlackSendMessageOutputSchema, GmailSendMessageInputSchema, GmailSendMessageOutputSchema, GmailSearchContactsInputSchema, GmailSearchContactsOutputSchema, GoogleCalendarCreateEventInputSchema, GoogleCalendarCreateEventOutputSchema, ZoomCreateMeetingInputSchema, ZoomCreateMeetingOutputSchema;
|
|
46457
46457
|
var init_mcp_tool_schemas = __esm({
|
|
46458
46458
|
"src/mcp/mcp-tool-schemas.ts"() {
|
|
46459
46459
|
"use strict";
|
|
@@ -46935,6 +46935,13 @@ var init_mcp_tool_schemas = __esm({
|
|
|
46935
46935
|
CommonsGetEntityLedgerInputSchema = {
|
|
46936
46936
|
idOrSlug: import_zod43.z.string().trim().min(1).max(180).describe("Published entity id or /wiki/ slug whose contribution ledger should be read.")
|
|
46937
46937
|
};
|
|
46938
|
+
CommonsHostImageInputSchema = {
|
|
46939
|
+
sourceUrl: import_zod43.z.string().url().optional().describe("Public https image URL to download and host. The wiki never serves a third-party URL directly, so pass the original source here rather than putting it on the entity."),
|
|
46940
|
+
imageBase64: import_zod43.z.string().min(16).optional().describe("Base64 image bytes for an image you already hold. Use for images under about 3 MB; larger files should be published from a URL."),
|
|
46941
|
+
alt: import_zod43.z.string().trim().max(500).optional().describe("Alt text describing the image for readers who cannot see it."),
|
|
46942
|
+
license: import_zod43.z.string().trim().max(240).optional().describe("License or usage terms of the original image, preserved with the hosted copy."),
|
|
46943
|
+
attribution: import_zod43.z.string().trim().max(500).optional().describe("Credit line for the original photographer, publication, or archive.")
|
|
46944
|
+
};
|
|
46938
46945
|
CommonsGetProposalInputSchema = {
|
|
46939
46946
|
proposalId: import_zod43.z.string().trim().min(1).max(120).describe("Proposal id returned by commons_submit_entity, in the form commons-proposal-<uuid>.")
|
|
46940
46947
|
};
|
|
@@ -50477,6 +50484,19 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
50477
50484
|
openWorldHint: false
|
|
50478
50485
|
}
|
|
50479
50486
|
}, async (input) => executor.commonsGetEntityLedger(input));
|
|
50487
|
+
server.registerTool("commons_host_image", {
|
|
50488
|
+
title: "Host a Transparent Commons Image",
|
|
50489
|
+
description: "Download an image from a public https URL, or accept base64 bytes, and store it as a permanent Commons-hosted image. Returns the hosted URL to use on an entity. Commons never serves a third-party image URL: submitting an entity with an external image hosts it automatically, and this tool exists for hosting an image before or independently of a write. JPEG, PNG, GIF, and WebP up to 10 MB; SVG is rejected because the wiki serves images to the public web. Identical bytes are stored once and reused.",
|
|
50490
|
+
inputSchema: CommonsHostImageInputSchema,
|
|
50491
|
+
outputSchema: recordOutputSchema("commons_host_image", CommonsGenericOutputSchema),
|
|
50492
|
+
annotations: {
|
|
50493
|
+
title: "Host a Transparent Commons Image",
|
|
50494
|
+
readOnlyHint: false,
|
|
50495
|
+
destructiveHint: false,
|
|
50496
|
+
idempotentHint: true,
|
|
50497
|
+
openWorldHint: true
|
|
50498
|
+
}
|
|
50499
|
+
}, async (input) => executor.commonsHostImage(input));
|
|
50480
50500
|
server.registerTool("commons_get_proposal", {
|
|
50481
50501
|
title: "Transparent Commons Proposal Status",
|
|
50482
50502
|
description: "Read one commons_submit_entity proposal owned by the calling account. Use it when submit returned a proposal that was held for review instead of published, to see the review reason and whether it has since been applied.",
|
|
@@ -51540,6 +51560,9 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
51540
51560
|
commonsGetProposal(input) {
|
|
51541
51561
|
return this.getJson(`/commons/proposals/${encodeURIComponent(input.proposalId)}`);
|
|
51542
51562
|
}
|
|
51563
|
+
commonsHostImage(input) {
|
|
51564
|
+
return this.call("/commons/images", input);
|
|
51565
|
+
}
|
|
51543
51566
|
commonsSaveFilter(input) {
|
|
51544
51567
|
return this.call("/commons/filters", input);
|
|
51545
51568
|
}
|
|
@@ -64276,6 +64299,231 @@ var init_editorial_reading_room_routes = __esm({
|
|
|
64276
64299
|
}
|
|
64277
64300
|
});
|
|
64278
64301
|
|
|
64302
|
+
// src/api/commons-image-store.ts
|
|
64303
|
+
async function ensureCommonsImageSchema() {
|
|
64304
|
+
if (imageSchemaReady) return;
|
|
64305
|
+
await getDb().execute(`
|
|
64306
|
+
CREATE TABLE IF NOT EXISTS commons_images (
|
|
64307
|
+
id TEXT PRIMARY KEY,
|
|
64308
|
+
user_id INTEGER NOT NULL,
|
|
64309
|
+
digest TEXT NOT NULL,
|
|
64310
|
+
storage_key TEXT NOT NULL,
|
|
64311
|
+
url TEXT NOT NULL,
|
|
64312
|
+
content_type TEXT NOT NULL,
|
|
64313
|
+
bytes INTEGER NOT NULL,
|
|
64314
|
+
source_url TEXT,
|
|
64315
|
+
alt TEXT,
|
|
64316
|
+
license TEXT,
|
|
64317
|
+
attribution TEXT,
|
|
64318
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
64319
|
+
)
|
|
64320
|
+
`);
|
|
64321
|
+
await getDb().execute(`CREATE UNIQUE INDEX IF NOT EXISTS commons_images_digest ON commons_images(digest)`);
|
|
64322
|
+
imageSchemaReady = true;
|
|
64323
|
+
}
|
|
64324
|
+
function sniffImageFormat(bytes) {
|
|
64325
|
+
if (bytes.length < 12) return null;
|
|
64326
|
+
if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) return "image/jpeg";
|
|
64327
|
+
if (bytes.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) return "image/png";
|
|
64328
|
+
if (bytes.subarray(0, 6).toString("ascii") === "GIF87a" || bytes.subarray(0, 6).toString("ascii") === "GIF89a") return "image/gif";
|
|
64329
|
+
if (bytes.subarray(0, 4).toString("ascii") === "RIFF" && bytes.subarray(8, 12).toString("ascii") === "WEBP") return "image/webp";
|
|
64330
|
+
return null;
|
|
64331
|
+
}
|
|
64332
|
+
function isBlockedAddress(address) {
|
|
64333
|
+
if ((0, import_node_net2.isIP)(address) === 6) {
|
|
64334
|
+
const normalized = address.toLowerCase();
|
|
64335
|
+
return normalized === "::1" || normalized.startsWith("fc") || normalized.startsWith("fd") || normalized.startsWith("fe80");
|
|
64336
|
+
}
|
|
64337
|
+
const parts = address.split(".").map(Number);
|
|
64338
|
+
if (parts.length !== 4 || parts.some((part) => Number.isNaN(part))) return true;
|
|
64339
|
+
const [a, b] = parts;
|
|
64340
|
+
if (a === 10 || a === 127 || a === 0) return true;
|
|
64341
|
+
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
64342
|
+
if (a === 192 && b === 168) return true;
|
|
64343
|
+
if (a === 169 && b === 254) return true;
|
|
64344
|
+
if (a === 100 && b >= 64 && b <= 127) return true;
|
|
64345
|
+
return false;
|
|
64346
|
+
}
|
|
64347
|
+
async function assertPublicHttpsUrl(rawUrl) {
|
|
64348
|
+
let url;
|
|
64349
|
+
try {
|
|
64350
|
+
url = new URL(rawUrl);
|
|
64351
|
+
} catch {
|
|
64352
|
+
throw new CommonsImageError("image_url_invalid", `"${rawUrl}" is not a valid URL.`);
|
|
64353
|
+
}
|
|
64354
|
+
if (url.protocol !== "https:") {
|
|
64355
|
+
throw new CommonsImageError("image_url_not_https", "Commons image sources must be https URLs.");
|
|
64356
|
+
}
|
|
64357
|
+
const hostname = url.hostname.replace(/^\[|\]$/g, "");
|
|
64358
|
+
const addresses = (0, import_node_net2.isIP)(hostname) ? [{ address: hostname }] : await (0, import_promises15.lookup)(hostname, { all: true }).catch(() => []);
|
|
64359
|
+
if (!addresses.length) {
|
|
64360
|
+
throw new CommonsImageError("image_host_unresolvable", `Could not resolve ${url.hostname}.`);
|
|
64361
|
+
}
|
|
64362
|
+
if (addresses.some((entry) => isBlockedAddress(entry.address))) {
|
|
64363
|
+
throw new CommonsImageError("image_host_blocked", "Commons image sources cannot resolve to private or loopback addresses.");
|
|
64364
|
+
}
|
|
64365
|
+
return url;
|
|
64366
|
+
}
|
|
64367
|
+
async function downloadImage(sourceUrl) {
|
|
64368
|
+
let current = sourceUrl;
|
|
64369
|
+
for (let redirect = 0; redirect <= COMMONS_IMAGE_MAX_REDIRECTS; redirect += 1) {
|
|
64370
|
+
const url = await assertPublicHttpsUrl(current);
|
|
64371
|
+
const response = await fetch(url, { redirect: "manual", signal: AbortSignal.timeout(COMMONS_IMAGE_FETCH_TIMEOUT_MS) });
|
|
64372
|
+
if (response.status >= 300 && response.status < 400) {
|
|
64373
|
+
const location2 = response.headers.get("location");
|
|
64374
|
+
if (!location2) throw new CommonsImageError("image_redirect_invalid", "Image source redirected without a destination.");
|
|
64375
|
+
current = new URL(location2, url).toString();
|
|
64376
|
+
continue;
|
|
64377
|
+
}
|
|
64378
|
+
if (!response.ok) {
|
|
64379
|
+
throw new CommonsImageError("image_source_unavailable", `Image source returned HTTP ${response.status}.`, 422);
|
|
64380
|
+
}
|
|
64381
|
+
const declaredLength = Number(response.headers.get("content-length") ?? "0");
|
|
64382
|
+
if (declaredLength > COMMONS_IMAGE_MAX_BYTES) {
|
|
64383
|
+
throw new CommonsImageError("image_too_large", `Image exceeds the ${COMMONS_IMAGE_MAX_BYTES} byte limit.`, 413);
|
|
64384
|
+
}
|
|
64385
|
+
const bytes = Buffer.from(await response.arrayBuffer());
|
|
64386
|
+
if (bytes.length > COMMONS_IMAGE_MAX_BYTES) {
|
|
64387
|
+
throw new CommonsImageError("image_too_large", `Image exceeds the ${COMMONS_IMAGE_MAX_BYTES} byte limit.`, 413);
|
|
64388
|
+
}
|
|
64389
|
+
return bytes;
|
|
64390
|
+
}
|
|
64391
|
+
throw new CommonsImageError("image_redirect_limit", "Image source exceeded the redirect limit.");
|
|
64392
|
+
}
|
|
64393
|
+
function decodeBase64Image(value) {
|
|
64394
|
+
const payload = value.includes(",") && value.trim().startsWith("data:") ? value.slice(value.indexOf(",") + 1) : value;
|
|
64395
|
+
const bytes = Buffer.from(payload, "base64");
|
|
64396
|
+
if (!bytes.length) throw new CommonsImageError("image_base64_invalid", "imageBase64 did not decode to any bytes.");
|
|
64397
|
+
if (bytes.length > COMMONS_IMAGE_MAX_BYTES) {
|
|
64398
|
+
throw new CommonsImageError("image_too_large", `Image exceeds the ${COMMONS_IMAGE_MAX_BYTES} byte limit.`, 413);
|
|
64399
|
+
}
|
|
64400
|
+
return bytes;
|
|
64401
|
+
}
|
|
64402
|
+
function isCommonsHostedImageUrl(url) {
|
|
64403
|
+
return /^https:\/\/[^/]*(\.public\.blob\.vercel-storage\.com|blob\.vercel-storage\.com)\//i.test(url) || url.startsWith("file://");
|
|
64404
|
+
}
|
|
64405
|
+
async function hostCommonsImage(input) {
|
|
64406
|
+
if (hostOverride) return hostOverride(input);
|
|
64407
|
+
await ensureCommonsImageSchema();
|
|
64408
|
+
if (!input.sourceUrl && !input.imageBase64) {
|
|
64409
|
+
throw new CommonsImageError("image_source_missing", "Provide either sourceUrl or imageBase64.");
|
|
64410
|
+
}
|
|
64411
|
+
const bytes = input.imageBase64 ? decodeBase64Image(input.imageBase64) : await downloadImage(String(input.sourceUrl));
|
|
64412
|
+
const contentType = sniffImageFormat(bytes);
|
|
64413
|
+
if (!contentType) {
|
|
64414
|
+
throw new CommonsImageError(
|
|
64415
|
+
"image_format_unsupported",
|
|
64416
|
+
"Commons hosts JPEG, PNG, GIF, and WebP. SVG and other formats are rejected because the wiki serves them to the public web.",
|
|
64417
|
+
415
|
|
64418
|
+
);
|
|
64419
|
+
}
|
|
64420
|
+
const digest2 = (0, import_node_crypto37.createHash)("sha256").update(bytes).digest("hex");
|
|
64421
|
+
const existing = await getDb().execute({
|
|
64422
|
+
sql: "SELECT id, url, content_type, bytes, source_url FROM commons_images WHERE digest = ? LIMIT 1",
|
|
64423
|
+
args: [digest2]
|
|
64424
|
+
});
|
|
64425
|
+
const reusable = existing.rows[0];
|
|
64426
|
+
if (reusable) {
|
|
64427
|
+
return {
|
|
64428
|
+
id: String(reusable.id),
|
|
64429
|
+
url: String(reusable.url),
|
|
64430
|
+
contentType: String(reusable.content_type),
|
|
64431
|
+
bytes: Number(reusable.bytes),
|
|
64432
|
+
digest: digest2,
|
|
64433
|
+
sourceUrl: reusable.source_url ? String(reusable.source_url) : null,
|
|
64434
|
+
reused: true
|
|
64435
|
+
};
|
|
64436
|
+
}
|
|
64437
|
+
const extension = contentType.split("/")[1] === "jpeg" ? "jpg" : contentType.split("/")[1];
|
|
64438
|
+
const storageKey = `commons/images/${digest2.slice(0, 2)}/${digest2}.${extension}`;
|
|
64439
|
+
const stored = await getBlobStore().put(storageKey, bytes, contentType);
|
|
64440
|
+
const id = `TPW-IMG-${digest2.slice(0, 16).toUpperCase()}`;
|
|
64441
|
+
await getDb().execute({
|
|
64442
|
+
sql: `
|
|
64443
|
+
INSERT INTO commons_images (id, user_id, digest, storage_key, url, content_type, bytes, source_url, alt, license, attribution, created_at)
|
|
64444
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
64445
|
+
`,
|
|
64446
|
+
args: [
|
|
64447
|
+
id,
|
|
64448
|
+
input.userId,
|
|
64449
|
+
digest2,
|
|
64450
|
+
storageKey,
|
|
64451
|
+
stored.url,
|
|
64452
|
+
contentType,
|
|
64453
|
+
bytes.length,
|
|
64454
|
+
input.sourceUrl ?? null,
|
|
64455
|
+
input.alt ?? null,
|
|
64456
|
+
input.license ?? null,
|
|
64457
|
+
input.attribution ?? null,
|
|
64458
|
+
(/* @__PURE__ */ new Date()).toISOString()
|
|
64459
|
+
]
|
|
64460
|
+
});
|
|
64461
|
+
return { id, url: stored.url, contentType, bytes: bytes.length, digest: digest2, sourceUrl: input.sourceUrl ?? null, reused: false };
|
|
64462
|
+
}
|
|
64463
|
+
async function hostEntityImages(input) {
|
|
64464
|
+
const rewrite = { mediaUrls: /* @__PURE__ */ new Map(), dropped: [] };
|
|
64465
|
+
const featuredUrl = input.featuredImage?.url;
|
|
64466
|
+
if (featuredUrl && !isCommonsHostedImageUrl(featuredUrl)) {
|
|
64467
|
+
const hosted = await hostCommonsImage({
|
|
64468
|
+
userId: input.userId,
|
|
64469
|
+
sourceUrl: featuredUrl,
|
|
64470
|
+
alt: input.featuredImage?.alt,
|
|
64471
|
+
license: input.featuredImage?.license,
|
|
64472
|
+
attribution: input.featuredImage?.sourceUrl
|
|
64473
|
+
}).catch((error) => {
|
|
64474
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
64475
|
+
throw new CommonsImageError(
|
|
64476
|
+
error instanceof CommonsImageError ? error.code : "featured_image_unhostable",
|
|
64477
|
+
`The featured image could not be hosted, so this entity would publish with a link that can break: ${message}`,
|
|
64478
|
+
422
|
|
64479
|
+
);
|
|
64480
|
+
});
|
|
64481
|
+
rewrite.featuredImageUrl = hosted.url;
|
|
64482
|
+
}
|
|
64483
|
+
for (const item of input.media ?? []) {
|
|
64484
|
+
if (!item.url || isCommonsHostedImageUrl(item.url)) continue;
|
|
64485
|
+
try {
|
|
64486
|
+
const hosted = await hostCommonsImage({
|
|
64487
|
+
userId: input.userId,
|
|
64488
|
+
sourceUrl: item.url,
|
|
64489
|
+
alt: item.alt,
|
|
64490
|
+
license: item.license,
|
|
64491
|
+
attribution: item.sourceUrl
|
|
64492
|
+
});
|
|
64493
|
+
rewrite.mediaUrls.set(item.url, hosted.url);
|
|
64494
|
+
} catch (error) {
|
|
64495
|
+
rewrite.dropped.push({ url: item.url, reason: error instanceof Error ? error.message : String(error) });
|
|
64496
|
+
}
|
|
64497
|
+
}
|
|
64498
|
+
return rewrite;
|
|
64499
|
+
}
|
|
64500
|
+
var import_node_crypto37, import_promises15, import_node_net2, COMMONS_IMAGE_MAX_BYTES, COMMONS_IMAGE_MAX_REDIRECTS, COMMONS_IMAGE_FETCH_TIMEOUT_MS, CommonsImageError, imageSchemaReady, hostOverride;
|
|
64501
|
+
var init_commons_image_store = __esm({
|
|
64502
|
+
"src/api/commons-image-store.ts"() {
|
|
64503
|
+
"use strict";
|
|
64504
|
+
import_node_crypto37 = require("crypto");
|
|
64505
|
+
import_promises15 = require("dns/promises");
|
|
64506
|
+
import_node_net2 = require("net");
|
|
64507
|
+
init_blob_store();
|
|
64508
|
+
init_db();
|
|
64509
|
+
COMMONS_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
64510
|
+
COMMONS_IMAGE_MAX_REDIRECTS = 3;
|
|
64511
|
+
COMMONS_IMAGE_FETCH_TIMEOUT_MS = 2e4;
|
|
64512
|
+
CommonsImageError = class extends Error {
|
|
64513
|
+
constructor(code, message, httpStatus = 400) {
|
|
64514
|
+
super(message);
|
|
64515
|
+
this.code = code;
|
|
64516
|
+
this.httpStatus = httpStatus;
|
|
64517
|
+
this.name = "CommonsImageError";
|
|
64518
|
+
}
|
|
64519
|
+
code;
|
|
64520
|
+
httpStatus;
|
|
64521
|
+
};
|
|
64522
|
+
imageSchemaReady = false;
|
|
64523
|
+
hostOverride = null;
|
|
64524
|
+
}
|
|
64525
|
+
});
|
|
64526
|
+
|
|
64279
64527
|
// src/api/schema-presence.ts
|
|
64280
64528
|
async function loadSchemaObjects() {
|
|
64281
64529
|
const res = await getDb().execute(
|
|
@@ -64378,7 +64626,7 @@ function buildCommonsLinkset(entity, claims) {
|
|
|
64378
64626
|
context[claim.predicate] = targets;
|
|
64379
64627
|
}
|
|
64380
64628
|
const document2 = { linkset: [context] };
|
|
64381
|
-
const etag = `"${(0,
|
|
64629
|
+
const etag = `"${(0, import_node_crypto38.createHash)("sha256").update(JSON.stringify(document2)).digest("hex")}"`;
|
|
64382
64630
|
return { document: document2, etag, publicUrl, linksetUrl, profile: COMMONS_RELATIONSHIP_PROFILE };
|
|
64383
64631
|
}
|
|
64384
64632
|
function commonsLinksetDiscoveryHeader(idOrSlug) {
|
|
@@ -64446,11 +64694,11 @@ function normalizeHreflang(value) {
|
|
|
64446
64694
|
const languages = [...new Set(value.map((item) => optionalText(item, 80)).filter((item) => Boolean(item)))];
|
|
64447
64695
|
return languages.length ? languages : void 0;
|
|
64448
64696
|
}
|
|
64449
|
-
var
|
|
64697
|
+
var import_node_crypto38, COMMONS_LINKSET_MEDIA_TYPE, COMMONS_RELATIONSHIP_PROFILE, REGISTERED_RELATIONS;
|
|
64450
64698
|
var init_commons_linksets = __esm({
|
|
64451
64699
|
"src/api/commons-linksets.ts"() {
|
|
64452
64700
|
"use strict";
|
|
64453
|
-
|
|
64701
|
+
import_node_crypto38 = require("crypto");
|
|
64454
64702
|
COMMONS_LINKSET_MEDIA_TYPE = "application/linkset+json";
|
|
64455
64703
|
COMMONS_RELATIONSHIP_PROFILE = "https://mcpscraper.dev/commons/profiles/relationships/v1";
|
|
64456
64704
|
REGISTERED_RELATIONS = /* @__PURE__ */ new Set([
|
|
@@ -64781,23 +65029,99 @@ async function searchCommonsEntities(filters = {}, userId) {
|
|
|
64781
65029
|
const pattern = `%${escapeLike(term)}%`;
|
|
64782
65030
|
args.push(pattern, pattern, pattern, pattern, pattern);
|
|
64783
65031
|
}
|
|
64784
|
-
|
|
64785
|
-
|
|
65032
|
+
if (!terms.length) {
|
|
65033
|
+
args.push(limit, offset);
|
|
65034
|
+
const result = await getDb().execute({
|
|
65035
|
+
sql: `
|
|
65036
|
+
SELECT *
|
|
65037
|
+
FROM commons_entities
|
|
65038
|
+
WHERE ${clauses.join(" AND ")}
|
|
65039
|
+
ORDER BY updated_at DESC, title ASC
|
|
65040
|
+
LIMIT ? OFFSET ?
|
|
65041
|
+
`,
|
|
65042
|
+
args
|
|
65043
|
+
});
|
|
65044
|
+
const results2 = result.rows.map((row) => rowToEntity(row));
|
|
65045
|
+
await resolveRelatedLinksAgainstPublishedEntities(results2);
|
|
65046
|
+
return { results: results2, filters: mergedFilters, limit, offset };
|
|
65047
|
+
}
|
|
65048
|
+
const candidates = await getDb().execute({
|
|
64786
65049
|
sql: `
|
|
64787
|
-
SELECT
|
|
65050
|
+
SELECT id, title, tags_json, keywords_json, description, search_text, updated_at,
|
|
65051
|
+
(
|
|
65052
|
+
SELECT group_concat(
|
|
65053
|
+
coalesce(commons_claims.title, '') || ' ' ||
|
|
65054
|
+
coalesce(commons_claims.predicate, '') || ' ' ||
|
|
65055
|
+
coalesce(commons_claims.predicate_label, '') || ' ' ||
|
|
65056
|
+
coalesce(commons_claims.object_url, ''), ' ')
|
|
65057
|
+
FROM commons_claims
|
|
65058
|
+
WHERE commons_claims.subject_entity_id = commons_entities.id
|
|
65059
|
+
) AS claim_text
|
|
64788
65060
|
FROM commons_entities
|
|
64789
65061
|
WHERE ${clauses.join(" AND ")}
|
|
64790
65062
|
ORDER BY updated_at DESC, title ASC
|
|
64791
|
-
LIMIT
|
|
65063
|
+
LIMIT ${SEARCH_CANDIDATE_LIMIT}
|
|
64792
65064
|
`,
|
|
64793
65065
|
args
|
|
64794
65066
|
});
|
|
64795
|
-
|
|
64796
|
-
|
|
64797
|
-
|
|
64798
|
-
|
|
64799
|
-
|
|
64800
|
-
|
|
65067
|
+
const ranked = candidates.rows.map((row) => {
|
|
65068
|
+
const record = row;
|
|
65069
|
+
const score = relevanceScore(terms, {
|
|
65070
|
+
title: String(record.title ?? ""),
|
|
65071
|
+
description: String(record.description ?? ""),
|
|
65072
|
+
tags: parseJsonArray(record.tags_json),
|
|
65073
|
+
keywords: parseJsonArray(record.keywords_json),
|
|
65074
|
+
searchText: String(record.search_text ?? ""),
|
|
65075
|
+
claimText: String(record.claim_text ?? "")
|
|
65076
|
+
});
|
|
65077
|
+
return { id: String(record.id), updatedAt: String(record.updated_at ?? ""), title: String(record.title ?? ""), score };
|
|
65078
|
+
}).filter((candidate) => candidate.score > 0).sort((left, right) => right.score - left.score || right.updatedAt.localeCompare(left.updatedAt) || left.title.localeCompare(right.title));
|
|
65079
|
+
const pageIds = ranked.slice(offset, offset + limit).map((candidate) => candidate.id);
|
|
65080
|
+
if (!pageIds.length) return { results: [], filters: mergedFilters, limit, offset };
|
|
65081
|
+
const page = await getDb().execute({
|
|
65082
|
+
sql: `SELECT * FROM commons_entities WHERE id IN (${pageIds.map(() => "?").join(", ")})`,
|
|
65083
|
+
args: pageIds
|
|
65084
|
+
});
|
|
65085
|
+
const byId = new Map(page.rows.map((row) => {
|
|
65086
|
+
const entity = rowToEntity(row);
|
|
65087
|
+
return [entity.id, entity];
|
|
65088
|
+
}));
|
|
65089
|
+
const results = pageIds.map((id) => byId.get(id)).filter((entity) => Boolean(entity));
|
|
65090
|
+
await resolveRelatedLinksAgainstPublishedEntities(results);
|
|
65091
|
+
return { results, filters: mergedFilters, limit, offset };
|
|
65092
|
+
}
|
|
65093
|
+
function parseJsonArray(value) {
|
|
65094
|
+
try {
|
|
65095
|
+
const parsed = JSON.parse(String(value ?? "[]"));
|
|
65096
|
+
return Array.isArray(parsed) ? parsed.map((item) => String(item)) : [];
|
|
65097
|
+
} catch {
|
|
65098
|
+
return [];
|
|
65099
|
+
}
|
|
65100
|
+
}
|
|
65101
|
+
function containsWord(haystack, term) {
|
|
65102
|
+
if (!haystack || !term) return false;
|
|
65103
|
+
const pattern = new RegExp(`(^|[^a-z0-9])${term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}([^a-z0-9]|$)`, "i");
|
|
65104
|
+
return pattern.test(haystack);
|
|
65105
|
+
}
|
|
65106
|
+
function relevanceScore(terms, fields) {
|
|
65107
|
+
let score = 0;
|
|
65108
|
+
const tagText = fields.tags.join(" ");
|
|
65109
|
+
const keywordText = fields.keywords.join(" ");
|
|
65110
|
+
for (const term of terms) {
|
|
65111
|
+
const inTitle = containsWord(fields.title, term);
|
|
65112
|
+
const inTags = containsWord(tagText, term) || containsWord(keywordText, term);
|
|
65113
|
+
const inDescription = containsWord(fields.description, term);
|
|
65114
|
+
const inBody = containsWord(fields.searchText, term);
|
|
65115
|
+
const inClaims = containsWord(fields.claimText, term);
|
|
65116
|
+
if (!inTitle && !inTags && !inDescription && !inBody && !inClaims) return 0;
|
|
65117
|
+
if (inTitle) score += 100;
|
|
65118
|
+
if (inTags) score += 40;
|
|
65119
|
+
if (inDescription) score += 20;
|
|
65120
|
+
if (inClaims) score += 10;
|
|
65121
|
+
if (inBody) score += 5;
|
|
65122
|
+
}
|
|
65123
|
+
if (terms.every((term) => containsWord(fields.title, term))) score += 50;
|
|
65124
|
+
return score;
|
|
64801
65125
|
}
|
|
64802
65126
|
async function prepareCommonsEntity(input, user) {
|
|
64803
65127
|
await ensureCommonsSchema();
|
|
@@ -64944,7 +65268,10 @@ async function getCommonsEntity(idOrSlug) {
|
|
|
64944
65268
|
`,
|
|
64945
65269
|
args: [lookup2, normalizeSlug(lookup2)]
|
|
64946
65270
|
});
|
|
64947
|
-
|
|
65271
|
+
if (!result.rows[0]) return null;
|
|
65272
|
+
const entity = rowToEntity(result.rows[0]);
|
|
65273
|
+
await resolveRelatedLinksAgainstPublishedEntities([entity]);
|
|
65274
|
+
return entity;
|
|
64948
65275
|
}
|
|
64949
65276
|
async function classifyCommonsWrite(input, user) {
|
|
64950
65277
|
await ensureCommonsSchema();
|
|
@@ -64967,14 +65294,30 @@ async function submitCommonsEntity(input, user) {
|
|
|
64967
65294
|
applied: existingProposal.status === "accepted",
|
|
64968
65295
|
reviewReason: existingProposal.reviewReason,
|
|
64969
65296
|
conflictNote: null,
|
|
65297
|
+
droppedImages: [],
|
|
64970
65298
|
publicUrl: entity2?.status === "published" ? publicUrlForSlug(entity2.slug) : null
|
|
64971
65299
|
};
|
|
64972
65300
|
}
|
|
65301
|
+
const hostedImages = await hostEntityImages({
|
|
65302
|
+
userId: Number(user.id),
|
|
65303
|
+
featuredImage: normalized.featuredImage,
|
|
65304
|
+
media: normalized.media
|
|
65305
|
+
});
|
|
65306
|
+
if (hostedImages.featuredImageUrl && normalized.featuredImage) {
|
|
65307
|
+
normalized.featuredImage = { ...normalized.featuredImage, url: hostedImages.featuredImageUrl };
|
|
65308
|
+
}
|
|
65309
|
+
if (hostedImages.mediaUrls.size || hostedImages.dropped.length) {
|
|
65310
|
+
const droppedUrls = new Set(hostedImages.dropped.map((item) => item.url));
|
|
65311
|
+
normalized.media = normalized.media.filter((item) => !droppedUrls.has(item.url)).map((item) => {
|
|
65312
|
+
const hostedUrl = hostedImages.mediaUrls.get(item.url);
|
|
65313
|
+
return hostedUrl ? { ...item, url: hostedUrl } : item;
|
|
65314
|
+
});
|
|
65315
|
+
}
|
|
64973
65316
|
const existing = await findEntityBySlugOrIdAnyStatus(normalized.slug, normalized.entityId);
|
|
64974
65317
|
const existingClaims = existing && normalized.claims !== void 0 ? await getCommonsClaimsByEntityId(existing.id) : [];
|
|
64975
65318
|
const safety = evaluatePublishSafety(normalized, existing);
|
|
64976
65319
|
const shouldApply = safety.safe && normalized.reviewPolicy !== "always_review";
|
|
64977
|
-
const proposalId = `commons-proposal-${(0,
|
|
65320
|
+
const proposalId = `commons-proposal-${(0, import_node_crypto39.randomUUID)()}`;
|
|
64978
65321
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
64979
65322
|
const entityId = existing?.id ?? normalized.entityId ?? allocateEntityId();
|
|
64980
65323
|
const proposalStatus = shouldApply ? "accepted" : "pending_review";
|
|
@@ -65029,7 +65372,7 @@ async function submitCommonsEntity(input, user) {
|
|
|
65029
65372
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
65030
65373
|
`,
|
|
65031
65374
|
args: [
|
|
65032
|
-
`commons-ledger-${(0,
|
|
65375
|
+
`commons-ledger-${(0, import_node_crypto39.randomUUID)()}`,
|
|
65033
65376
|
nextEntity.id,
|
|
65034
65377
|
proposalId,
|
|
65035
65378
|
user.id,
|
|
@@ -65064,6 +65407,7 @@ async function submitCommonsEntity(input, user) {
|
|
|
65064
65407
|
applied: shouldApply,
|
|
65065
65408
|
reviewReason: safety.reason,
|
|
65066
65409
|
conflictNote: safety.conflictNote,
|
|
65410
|
+
droppedImages: hostedImages.dropped,
|
|
65067
65411
|
publicUrl: entity?.status === "published" && shouldApply ? publicUrlForSlug(entity.slug) : null
|
|
65068
65412
|
};
|
|
65069
65413
|
}
|
|
@@ -65134,7 +65478,7 @@ async function saveCommonsFilter(input, user) {
|
|
|
65134
65478
|
sql: "SELECT id FROM commons_saved_filters WHERE user_id = ? AND name = ? LIMIT 1",
|
|
65135
65479
|
args: [user.id, name]
|
|
65136
65480
|
});
|
|
65137
|
-
const id = existing.rows[0]?.id != null ? String(existing.rows[0].id) : `commons-filter-${(0,
|
|
65481
|
+
const id = existing.rows[0]?.id != null ? String(existing.rows[0].id) : `commons-filter-${(0, import_node_crypto39.randomUUID)()}`;
|
|
65138
65482
|
await getDb().execute({
|
|
65139
65483
|
sql: `
|
|
65140
65484
|
INSERT INTO commons_saved_filters (id, user_id, name, description, filter_json, created_at, updated_at)
|
|
@@ -65202,8 +65546,9 @@ async function listCommonsNeedsLinks(filters = {}) {
|
|
|
65202
65546
|
});
|
|
65203
65547
|
const concepts = /* @__PURE__ */ new Map();
|
|
65204
65548
|
const queryTerms = tokenize(cleanFilters.query);
|
|
65205
|
-
|
|
65206
|
-
|
|
65549
|
+
const scanned = result.rows.map((row) => rowToEntity(row));
|
|
65550
|
+
await resolveRelatedLinksAgainstPublishedEntities(scanned);
|
|
65551
|
+
for (const entity of scanned) {
|
|
65207
65552
|
for (const link2 of entity.articleSections.relatedLinks) {
|
|
65208
65553
|
if (!relatedLinkNeedsPage(link2)) continue;
|
|
65209
65554
|
const haystack = [link2.title, link2.summary, link2.relationship, entity.title, entity.description, entity.tags.join(" ")].filter(Boolean).join(" ").toLowerCase();
|
|
@@ -65911,7 +66256,7 @@ function commonsIndexDocuments(entity, now) {
|
|
|
65911
66256
|
return documents;
|
|
65912
66257
|
}
|
|
65913
66258
|
function commonsIndexDocumentId(entityId, documentType, documentKey) {
|
|
65914
|
-
return `commons-index-${(0,
|
|
66259
|
+
return `commons-index-${(0, import_node_crypto39.createHash)("sha256").update(`${entityId}
|
|
65915
66260
|
${documentType}
|
|
65916
66261
|
${documentKey}`).digest("hex").slice(0, 32)}`;
|
|
65917
66262
|
}
|
|
@@ -66246,6 +66591,44 @@ function sanitizeNeedsLinkFilters(filters) {
|
|
|
66246
66591
|
offset: clampNumber(filters.offset, 0, 1e4, 0)
|
|
66247
66592
|
};
|
|
66248
66593
|
}
|
|
66594
|
+
async function publishedEntityIndexFor(titles) {
|
|
66595
|
+
const index = /* @__PURE__ */ new Map();
|
|
66596
|
+
const slugKeys = uniqueStrings(titles.map((title) => normalizeNeedsLinkTitle(title))).filter(Boolean);
|
|
66597
|
+
const titleKeys = uniqueStrings(titles.map((title) => String(title || "").trim().toLowerCase())).filter(Boolean);
|
|
66598
|
+
if (!slugKeys.length && !titleKeys.length) return index;
|
|
66599
|
+
const result = await getDb().execute({
|
|
66600
|
+
sql: `
|
|
66601
|
+
SELECT id, slug, title
|
|
66602
|
+
FROM commons_entities
|
|
66603
|
+
WHERE status = 'published'
|
|
66604
|
+
AND (slug IN (${slugKeys.map(() => "?").join(", ") || "NULL"})
|
|
66605
|
+
OR lower(title) IN (${titleKeys.map(() => "?").join(", ") || "NULL"}))
|
|
66606
|
+
`,
|
|
66607
|
+
args: [...slugKeys, ...titleKeys]
|
|
66608
|
+
});
|
|
66609
|
+
for (const row of result.rows) {
|
|
66610
|
+
const record = row;
|
|
66611
|
+
const entry = { id: String(record.id), slug: String(record.slug), title: String(record.title) };
|
|
66612
|
+
index.set(entry.slug, entry);
|
|
66613
|
+
index.set(normalizeNeedsLinkTitle(entry.title), entry);
|
|
66614
|
+
}
|
|
66615
|
+
return index;
|
|
66616
|
+
}
|
|
66617
|
+
function unresolvedRelatedLinkTitles(entities) {
|
|
66618
|
+
return entities.flatMap((entity) => entity.articleSections.relatedLinks.filter((link2) => relatedLinkNeedsPage(link2)).map((link2) => link2.title));
|
|
66619
|
+
}
|
|
66620
|
+
async function resolveRelatedLinksAgainstPublishedEntities(entities) {
|
|
66621
|
+
const index = await publishedEntityIndexFor(unresolvedRelatedLinkTitles(entities));
|
|
66622
|
+
if (!index.size) return;
|
|
66623
|
+
for (const entity of entities) {
|
|
66624
|
+
entity.articleSections.relatedLinks = entity.articleSections.relatedLinks.map((link2) => {
|
|
66625
|
+
if (!relatedLinkNeedsPage(link2)) return link2;
|
|
66626
|
+
const match = index.get(normalizeNeedsLinkTitle(link2.title));
|
|
66627
|
+
if (!match || match.id === entity.id) return link2;
|
|
66628
|
+
return { ...link2, slug: match.slug, entityId: match.id, needsLink: false };
|
|
66629
|
+
});
|
|
66630
|
+
}
|
|
66631
|
+
}
|
|
66249
66632
|
function relatedLinkNeedsPage(link2) {
|
|
66250
66633
|
if (link2.needsLink === true) return true;
|
|
66251
66634
|
if (link2.entityId || link2.slug) return false;
|
|
@@ -66438,12 +66821,13 @@ function jsonLikeValue(value) {
|
|
|
66438
66821
|
function escapeLike(value) {
|
|
66439
66822
|
return value.replace(/[%_]/g, "");
|
|
66440
66823
|
}
|
|
66441
|
-
var
|
|
66824
|
+
var import_node_crypto39, COMMONS_SCHEMA_VERSION, DEFAULT_COMMONS_BASE_URL, DEFAULT_ENTITY_TYPE, COMMONS_ENTITY_PROFILES, schemaReady, COMMONS_SCHEMA_OBJECTS, SEARCH_CANDIDATE_LIMIT, CommonsRepositoryError;
|
|
66442
66825
|
var init_commons_repository = __esm({
|
|
66443
66826
|
"src/api/commons-repository.ts"() {
|
|
66444
66827
|
"use strict";
|
|
66445
|
-
|
|
66828
|
+
import_node_crypto39 = require("crypto");
|
|
66446
66829
|
init_db();
|
|
66830
|
+
init_commons_image_store();
|
|
66447
66831
|
init_schema_presence();
|
|
66448
66832
|
init_rates();
|
|
66449
66833
|
init_commons_linksets();
|
|
@@ -66621,6 +67005,7 @@ var init_commons_repository = __esm({
|
|
|
66621
67005
|
"commons_publications_updated",
|
|
66622
67006
|
"commons_publication_editions_publication_published"
|
|
66623
67007
|
];
|
|
67008
|
+
SEARCH_CANDIDATE_LIMIT = 500;
|
|
66624
67009
|
CommonsRepositoryError = class extends Error {
|
|
66625
67010
|
constructor(code, message, httpStatus = 400) {
|
|
66626
67011
|
super(message);
|
|
@@ -66723,7 +67108,7 @@ async function claimCommonsPublication(input, user) {
|
|
|
66723
67108
|
}
|
|
66724
67109
|
const existingName = await getCommonsPublicationBySubdomain(subdomain);
|
|
66725
67110
|
if (existingName) throw new CommonsPublicationError("publication_name_unavailable", "That publication name is already claimed.", 409);
|
|
66726
|
-
const id = `tcpub_${(0,
|
|
67111
|
+
const id = `tcpub_${(0, import_node_crypto40.randomUUID)()}`;
|
|
66727
67112
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
66728
67113
|
try {
|
|
66729
67114
|
await getDb().execute({
|
|
@@ -66775,7 +67160,7 @@ async function publishCommonsEditorial(input, user) {
|
|
|
66775
67160
|
const canonicalUrl = editionPublicUrl(subdomain, editionSlug);
|
|
66776
67161
|
const rendered = renderEditorialReadingRoom(editionInput);
|
|
66777
67162
|
const html = addPublicMetadata(rendered.html, canonicalUrl, publication.title);
|
|
66778
|
-
const editionId = `tced_${(0,
|
|
67163
|
+
const editionId = `tced_${(0, import_node_crypto40.randomUUID)()}`;
|
|
66779
67164
|
const revision = (latest?.revision ?? 0) + 1;
|
|
66780
67165
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
66781
67166
|
await getDb().batch([
|
|
@@ -66799,7 +67184,7 @@ async function publishCommonsEditorial(input, user) {
|
|
|
66799
67184
|
JSON.stringify(editionInput.articles),
|
|
66800
67185
|
html,
|
|
66801
67186
|
rendered.filename,
|
|
66802
|
-
(0,
|
|
67187
|
+
(0, import_node_crypto40.createHash)("sha256").update(html).digest("hex"),
|
|
66803
67188
|
rendered.articleCount,
|
|
66804
67189
|
rendered.wordCount,
|
|
66805
67190
|
Buffer.byteLength(html),
|
|
@@ -66985,11 +67370,11 @@ function addPublicMetadata(html, canonicalUrl, publicationTitle) {
|
|
|
66985
67370
|
"</head>"
|
|
66986
67371
|
].join("\n"));
|
|
66987
67372
|
}
|
|
66988
|
-
var
|
|
67373
|
+
var import_node_crypto40, PUBLICATION_ROOT_DOMAIN, RESERVED_SUBDOMAINS, CommonsPublicationError;
|
|
66989
67374
|
var init_commons_publication_repository = __esm({
|
|
66990
67375
|
"src/api/commons-publication-repository.ts"() {
|
|
66991
67376
|
"use strict";
|
|
66992
|
-
|
|
67377
|
+
import_node_crypto40 = require("crypto");
|
|
66993
67378
|
init_db();
|
|
66994
67379
|
init_commons_repository();
|
|
66995
67380
|
init_render();
|
|
@@ -67090,7 +67475,7 @@ function publicationError(c, error) {
|
|
|
67090
67475
|
function xmlEscape(value) {
|
|
67091
67476
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
67092
67477
|
}
|
|
67093
|
-
var import_hono31, import_zod52, commonsApp, auth2, SearchBodySchema, FeaturedImageSchema, MediaSchema, CitationSchema, RelatedLinkSchema, SubmitEntitySchema, PrepareEntitySchema, ValidateEntitySchema, SaveFilterSchema, NeedsLinkBodySchema, PreparePublicationSchema, ValidatePublicationSchema, ClaimPublicationSchema, PublishEditorialSchema;
|
|
67478
|
+
var import_hono31, import_zod52, commonsApp, auth2, SearchBodySchema, FeaturedImageSchema, MediaSchema, CitationSchema, RelatedLinkSchema, SubmitEntitySchema, PrepareEntitySchema, ValidateEntitySchema, SaveFilterSchema, NeedsLinkBodySchema, PreparePublicationSchema, ValidatePublicationSchema, ClaimPublicationSchema, PublishEditorialSchema, HostImageSchema;
|
|
67094
67479
|
var init_commons_routes = __esm({
|
|
67095
67480
|
"src/api/commons-routes.ts"() {
|
|
67096
67481
|
"use strict";
|
|
@@ -67098,6 +67483,7 @@ var init_commons_routes = __esm({
|
|
|
67098
67483
|
import_zod52 = require("zod");
|
|
67099
67484
|
init_api_auth();
|
|
67100
67485
|
init_commons_repository();
|
|
67486
|
+
init_commons_image_store();
|
|
67101
67487
|
init_commons_linksets();
|
|
67102
67488
|
init_listing_write_billing();
|
|
67103
67489
|
init_commons_publication_repository();
|
|
@@ -67351,6 +67737,28 @@ var init_commons_routes = __esm({
|
|
|
67351
67737
|
return publicationError(c, error);
|
|
67352
67738
|
}
|
|
67353
67739
|
});
|
|
67740
|
+
HostImageSchema = import_zod52.z.object({
|
|
67741
|
+
sourceUrl: import_zod52.z.string().url().optional(),
|
|
67742
|
+
imageBase64: import_zod52.z.string().min(16).optional(),
|
|
67743
|
+
alt: import_zod52.z.string().max(500).optional(),
|
|
67744
|
+
license: import_zod52.z.string().max(240).optional(),
|
|
67745
|
+
attribution: import_zod52.z.string().max(500).optional()
|
|
67746
|
+
}).strict().refine((body) => Boolean(body.sourceUrl || body.imageBase64), {
|
|
67747
|
+
message: "Provide either sourceUrl or imageBase64."
|
|
67748
|
+
});
|
|
67749
|
+
commonsApp.post("/images", auth2, async (c) => {
|
|
67750
|
+
const parsed = HostImageSchema.safeParse(await c.req.json().catch(() => ({})));
|
|
67751
|
+
if (!parsed.success) return validationError(c, parsed.error);
|
|
67752
|
+
try {
|
|
67753
|
+
const hosted = await hostCommonsImage({ ...parsed.data, userId: Number(c.get("user").id) });
|
|
67754
|
+
return c.json({ ok: true, data: hosted }, hosted.reused ? 200 : 201);
|
|
67755
|
+
} catch (error) {
|
|
67756
|
+
if (error instanceof CommonsImageError) {
|
|
67757
|
+
return c.json({ ok: false, error: error.code, message: error.message }, error.httpStatus);
|
|
67758
|
+
}
|
|
67759
|
+
throw error;
|
|
67760
|
+
}
|
|
67761
|
+
});
|
|
67354
67762
|
commonsApp.get("/entities", async (c) => {
|
|
67355
67763
|
const result = await searchCommonsEntities(filtersFromQuery(c.req.query()));
|
|
67356
67764
|
return c.json({ ok: true, data: result });
|
|
@@ -68152,7 +68560,7 @@ async function migrateAnalytics() {
|
|
|
68152
68560
|
}
|
|
68153
68561
|
function normalizeSlug2(value) {
|
|
68154
68562
|
const slug4 = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
68155
|
-
return slug4 || `site-${(0,
|
|
68563
|
+
return slug4 || `site-${(0, import_node_crypto41.randomBytes)(4).toString("hex")}`;
|
|
68156
68564
|
}
|
|
68157
68565
|
function normalizeObservedHostname(origin) {
|
|
68158
68566
|
if (!origin || origin === "null") return null;
|
|
@@ -68165,7 +68573,7 @@ function normalizeObservedHostname(origin) {
|
|
|
68165
68573
|
}
|
|
68166
68574
|
}
|
|
68167
68575
|
function publicPixelId() {
|
|
68168
|
-
return `px_${(0,
|
|
68576
|
+
return `px_${(0, import_node_crypto41.randomBytes)(18).toString("base64url")}`;
|
|
68169
68577
|
}
|
|
68170
68578
|
function mapRows(rows) {
|
|
68171
68579
|
return rows;
|
|
@@ -68197,7 +68605,7 @@ async function requireEditor(client2, siteId, userId) {
|
|
|
68197
68605
|
async function createAnalyticsSite(input) {
|
|
68198
68606
|
const db = getAnalyticsPool();
|
|
68199
68607
|
const client2 = await db.connect();
|
|
68200
|
-
const id = (0,
|
|
68608
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
68201
68609
|
const baseSlug = normalizeSlug2(input.slug || input.name);
|
|
68202
68610
|
try {
|
|
68203
68611
|
await client2.query("BEGIN");
|
|
@@ -68213,7 +68621,7 @@ async function createAnalyticsSite(input) {
|
|
|
68213
68621
|
} catch (error) {
|
|
68214
68622
|
const code = error.code;
|
|
68215
68623
|
if (code !== "23505" || attempt === 2) throw error;
|
|
68216
|
-
slug4 = `${baseSlug}-${(0,
|
|
68624
|
+
slug4 = `${baseSlug}-${(0, import_node_crypto41.randomBytes)(2).toString("hex")}`;
|
|
68217
68625
|
}
|
|
68218
68626
|
}
|
|
68219
68627
|
await client2.query(
|
|
@@ -68428,7 +68836,7 @@ async function createAnalyticsPixel(input) {
|
|
|
68428
68836
|
VALUES ($1, $2, $3, $4, $5)
|
|
68429
68837
|
RETURNING id, site_id, public_id, name, environment, status, created_at::text, NULL::text AS last_event_at`,
|
|
68430
68838
|
[
|
|
68431
|
-
(0,
|
|
68839
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68432
68840
|
input.siteId,
|
|
68433
68841
|
publicPixelId(),
|
|
68434
68842
|
input.name.trim(),
|
|
@@ -68505,7 +68913,7 @@ async function setAnalyticsPixelDomainState(input) {
|
|
|
68505
68913
|
SELECT $1, p.id, $4, $5 FROM analytics_pixels p WHERE p.id = $2 AND p.site_id = $3
|
|
68506
68914
|
ON CONFLICT(pixel_id, hostname) DO UPDATE SET state = EXCLUDED.state, updated_at = now()
|
|
68507
68915
|
RETURNING id`,
|
|
68508
|
-
[(0,
|
|
68916
|
+
[(0, import_node_crypto41.randomUUID)(), input.pixelId, input.siteId, hostname, input.state]
|
|
68509
68917
|
);
|
|
68510
68918
|
if (!result.rowCount)
|
|
68511
68919
|
throw new AnalyticsRepositoryError(
|
|
@@ -68555,7 +68963,7 @@ function sanitizeAnalyticsProperties(value) {
|
|
|
68555
68963
|
}
|
|
68556
68964
|
async function ingestAnalyticsEvents(input) {
|
|
68557
68965
|
const db = getAnalyticsPool();
|
|
68558
|
-
const requestId = `air_${(0,
|
|
68966
|
+
const requestId = `air_${(0, import_node_crypto41.randomUUID)()}`;
|
|
68559
68967
|
const hostname = normalizeObservedHostname(input.origin);
|
|
68560
68968
|
const pixelResult = await db.query(
|
|
68561
68969
|
`SELECT p.id, p.site_id, p.status,
|
|
@@ -68576,7 +68984,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68576
68984
|
`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, hostname, rejected_count, reason_codes)
|
|
68577
68985
|
VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)`,
|
|
68578
68986
|
[
|
|
68579
|
-
(0,
|
|
68987
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68580
68988
|
requestId,
|
|
68581
68989
|
pixel?.site_id ?? null,
|
|
68582
68990
|
pixel?.id ?? null,
|
|
@@ -68601,7 +69009,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68601
69009
|
`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, hostname, rejected_count, reason_codes)
|
|
68602
69010
|
VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)`,
|
|
68603
69011
|
[
|
|
68604
|
-
(0,
|
|
69012
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68605
69013
|
requestId,
|
|
68606
69014
|
pixel.site_id,
|
|
68607
69015
|
pixel.id,
|
|
@@ -68626,7 +69034,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68626
69034
|
`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, rejected_count, reason_codes)
|
|
68627
69035
|
VALUES ($1, $2, $3, $4, $5, $6::jsonb)`,
|
|
68628
69036
|
[
|
|
68629
|
-
(0,
|
|
69037
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68630
69038
|
requestId,
|
|
68631
69039
|
pixel.site_id,
|
|
68632
69040
|
pixel.id,
|
|
@@ -68650,7 +69058,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68650
69058
|
ON CONFLICT(pixel_id, hostname) DO UPDATE
|
|
68651
69059
|
SET last_seen_at = now(), updated_at = now()
|
|
68652
69060
|
RETURNING state`,
|
|
68653
|
-
[(0,
|
|
69061
|
+
[(0, import_node_crypto41.randomUUID)(), pixel.id, hostname]
|
|
68654
69062
|
);
|
|
68655
69063
|
if (domainResult.rows[0]?.state !== "approved") {
|
|
68656
69064
|
await db.query(
|
|
@@ -68664,7 +69072,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68664
69072
|
`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, hostname, rejected_count, reason_codes)
|
|
68665
69073
|
VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)`,
|
|
68666
69074
|
[
|
|
68667
|
-
(0,
|
|
69075
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68668
69076
|
requestId,
|
|
68669
69077
|
pixel.site_id,
|
|
68670
69078
|
pixel.id,
|
|
@@ -68714,7 +69122,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68714
69122
|
$23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33
|
|
68715
69123
|
) ON CONFLICT(site_id, event_id) DO NOTHING`,
|
|
68716
69124
|
[
|
|
68717
|
-
(0,
|
|
69125
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68718
69126
|
event2.eventId,
|
|
68719
69127
|
pixel.site_id,
|
|
68720
69128
|
pixel.id,
|
|
@@ -68772,7 +69180,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68772
69180
|
id, request_id, site_id, pixel_id, hostname, accepted_count, rejected_count, reason_codes
|
|
68773
69181
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb)`,
|
|
68774
69182
|
[
|
|
68775
|
-
(0,
|
|
69183
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68776
69184
|
requestId,
|
|
68777
69185
|
pixel.site_id,
|
|
68778
69186
|
pixel.id,
|
|
@@ -68804,7 +69212,7 @@ function normalizeGeographyCode(value, max) {
|
|
|
68804
69212
|
return normalized && /^[A-Z0-9-]+$/.test(normalized) ? normalized.slice(0, max) : null;
|
|
68805
69213
|
}
|
|
68806
69214
|
function pageFingerprint(scope, siteId, filters) {
|
|
68807
|
-
return (0,
|
|
69215
|
+
return (0, import_node_crypto41.createHash)("sha256").update(JSON.stringify({ scope, siteId, filters })).digest("base64url").slice(0, 18);
|
|
68808
69216
|
}
|
|
68809
69217
|
function decodePageOffset(cursor, fingerprint) {
|
|
68810
69218
|
if (!cursor) return 0;
|
|
@@ -68854,7 +69262,7 @@ async function createAnalyticsConversion(input) {
|
|
|
68854
69262
|
404
|
|
68855
69263
|
);
|
|
68856
69264
|
}
|
|
68857
|
-
const id = (0,
|
|
69265
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
68858
69266
|
const resolvedPerson = input.sessionId ? await db.query(
|
|
68859
69267
|
`SELECT e.person_id FROM analytics_identity_nodes n JOIN analytics_identity_edges e ON e.identity_node_id = n.id
|
|
68860
69268
|
WHERE n.site_id = $1 AND n.kind = 'session_id' AND n.value_hmac = $2 ORDER BY e.confidence DESC LIMIT 1`,
|
|
@@ -69603,7 +70011,7 @@ async function createAnalyticsCampaignLink(input) {
|
|
|
69603
70011
|
404
|
|
69604
70012
|
);
|
|
69605
70013
|
}
|
|
69606
|
-
const shortCode = (input.shortCode?.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-") || (0,
|
|
70014
|
+
const shortCode = (input.shortCode?.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-") || (0, import_node_crypto41.randomBytes)(5).toString("base64url").toLowerCase()).slice(0, 48);
|
|
69607
70015
|
try {
|
|
69608
70016
|
const result = await db.query(
|
|
69609
70017
|
`INSERT INTO analytics_campaign_links(
|
|
@@ -69612,7 +70020,7 @@ async function createAnalyticsCampaignLink(input) {
|
|
|
69612
70020
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15)
|
|
69613
70021
|
RETURNING *, 0::int AS click_count`,
|
|
69614
70022
|
[
|
|
69615
|
-
(0,
|
|
70023
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
69616
70024
|
input.siteId,
|
|
69617
70025
|
input.pixelId ?? null,
|
|
69618
70026
|
input.name.trim(),
|
|
@@ -69683,7 +70091,7 @@ async function resolveAnalyticsCampaignLink(shortCode, referrer) {
|
|
|
69683
70091
|
if (!row) return null;
|
|
69684
70092
|
await db.query(
|
|
69685
70093
|
`INSERT INTO analytics_campaign_clicks(id, link_id, referrer) VALUES ($1, $2, $3)`,
|
|
69686
|
-
[(0,
|
|
70094
|
+
[(0, import_node_crypto41.randomUUID)(), row.id, normalizeAnalyticsUrl(referrer || void 0)]
|
|
69687
70095
|
);
|
|
69688
70096
|
return buildTaggedCampaignUrl(row);
|
|
69689
70097
|
}
|
|
@@ -69701,14 +70109,14 @@ async function createAnalyticsForm(input) {
|
|
|
69701
70109
|
404
|
|
69702
70110
|
);
|
|
69703
70111
|
const baseSlug = normalizeSlug2(input.name);
|
|
69704
|
-
const slug4 = `${baseSlug}-${(0,
|
|
69705
|
-
const publicId = `form_${(0,
|
|
70112
|
+
const slug4 = `${baseSlug}-${(0, import_node_crypto41.randomBytes)(3).toString("hex")}`;
|
|
70113
|
+
const publicId = `form_${(0, import_node_crypto41.randomBytes)(18).toString("base64url")}`;
|
|
69706
70114
|
const result = await db.query(
|
|
69707
70115
|
`INSERT INTO analytics_forms(id, public_id, site_id, pixel_id, name, slug, fields, brand, submit_label, success_message, redirect_url, consent_text, status, created_by_user_id)
|
|
69708
70116
|
VALUES ($1,$2,$3,$4,$5,$6,$7::jsonb,$8::jsonb,$9,$10,$11,$12,$13,$14)
|
|
69709
70117
|
RETURNING *, 0::int AS submission_count`,
|
|
69710
70118
|
[
|
|
69711
|
-
(0,
|
|
70119
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
69712
70120
|
publicId,
|
|
69713
70121
|
input.siteId,
|
|
69714
70122
|
input.pixelId,
|
|
@@ -69753,7 +70161,7 @@ async function getPublicAnalyticsForm(publicId) {
|
|
|
69753
70161
|
return result.rows[0] ?? null;
|
|
69754
70162
|
}
|
|
69755
70163
|
async function recordAnalyticsFormSubmission(input) {
|
|
69756
|
-
const id = (0,
|
|
70164
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
69757
70165
|
await getAnalyticsPool().query(
|
|
69758
70166
|
`INSERT INTO analytics_form_submissions(id, form_id, site_id, pixel_id, visitor_id, session_id, crm_person_ref, source, medium, campaign, crm_delivery_status, click_ids)
|
|
69759
70167
|
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12::jsonb)`,
|
|
@@ -69784,7 +70192,7 @@ function sanitizeClickIds(value) {
|
|
|
69784
70192
|
return output;
|
|
69785
70193
|
}
|
|
69786
70194
|
function identityHmac(kind, value) {
|
|
69787
|
-
return (0,
|
|
70195
|
+
return (0, import_node_crypto41.createHmac)("sha256", getSessionSecret()).update(`${kind}:${value.trim().toLowerCase()}`).digest("hex");
|
|
69788
70196
|
}
|
|
69789
70197
|
async function linkAnalyticsFormIdentity(input) {
|
|
69790
70198
|
const client2 = await getAnalyticsPool().connect();
|
|
@@ -69793,7 +70201,7 @@ async function linkAnalyticsFormIdentity(input) {
|
|
|
69793
70201
|
const person = await client2.query(
|
|
69794
70202
|
`INSERT INTO analytics_people(id, site_id, crm_person_ref) VALUES ($1,$2,$3)
|
|
69795
70203
|
ON CONFLICT(site_id, crm_person_ref) DO UPDATE SET last_seen_at = now() RETURNING id`,
|
|
69796
|
-
[(0,
|
|
70204
|
+
[(0, import_node_crypto41.randomUUID)(), input.siteId, input.crmPersonRef]
|
|
69797
70205
|
);
|
|
69798
70206
|
const personId = person.rows[0].id;
|
|
69799
70207
|
const signals = [];
|
|
@@ -69840,7 +70248,7 @@ async function linkAnalyticsFormIdentity(input) {
|
|
|
69840
70248
|
`INSERT INTO analytics_identity_nodes(id, site_id, kind, value_hmac) VALUES ($1,$2,$3,$4)
|
|
69841
70249
|
ON CONFLICT(site_id, kind, value_hmac) DO UPDATE SET last_seen_at = now() RETURNING id`,
|
|
69842
70250
|
[
|
|
69843
|
-
(0,
|
|
70251
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
69844
70252
|
input.siteId,
|
|
69845
70253
|
signal.kind,
|
|
69846
70254
|
identityHmac(signal.kind, signal.value)
|
|
@@ -69851,7 +70259,7 @@ async function linkAnalyticsFormIdentity(input) {
|
|
|
69851
70259
|
VALUES ($1,$2,$3,$4,$5,$6)
|
|
69852
70260
|
ON CONFLICT(person_id, identity_node_id, evidence_kind) DO UPDATE SET last_seen_at = now(), confidence = greatest(analytics_identity_edges.confidence, EXCLUDED.confidence)`,
|
|
69853
70261
|
[
|
|
69854
|
-
(0,
|
|
70262
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
69855
70263
|
input.siteId,
|
|
69856
70264
|
personId,
|
|
69857
70265
|
node.rows[0].id,
|
|
@@ -69949,7 +70357,7 @@ async function createAnalyticsCrmImport(input) {
|
|
|
69949
70357
|
const db = getAnalyticsPool();
|
|
69950
70358
|
await requireEditor(db, input.siteId, input.userId);
|
|
69951
70359
|
const client2 = await db.connect();
|
|
69952
|
-
const id = (0,
|
|
70360
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
69953
70361
|
try {
|
|
69954
70362
|
await client2.query("BEGIN");
|
|
69955
70363
|
await client2.query(
|
|
@@ -69969,7 +70377,7 @@ async function createAnalyticsCrmImport(input) {
|
|
|
69969
70377
|
await client2.query(
|
|
69970
70378
|
`INSERT INTO analytics_crm_import_rows(id, import_id, crm_person_ref, payload_ciphertext)
|
|
69971
70379
|
VALUES ($1,$2,$3,$4) ON CONFLICT(import_id, crm_person_ref) DO NOTHING`,
|
|
69972
|
-
[(0,
|
|
70380
|
+
[(0, import_node_crypto41.randomUUID)(), id, row.crmPersonRef, row.payloadCiphertext]
|
|
69973
70381
|
);
|
|
69974
70382
|
}
|
|
69975
70383
|
await client2.query("COMMIT");
|
|
@@ -70008,7 +70416,7 @@ async function createAnalyticsActivationDestination(input) {
|
|
|
70008
70416
|
`INSERT INTO analytics_activation_destinations(id, site_id, platform, name, connection_ref, external_dataset_id, event_mapping, created_by_user_id)
|
|
70009
70417
|
VALUES ($1,$2,$3,$4,$5,$6,$7::jsonb,$8) RETURNING *`,
|
|
70010
70418
|
[
|
|
70011
|
-
(0,
|
|
70419
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
70012
70420
|
input.siteId,
|
|
70013
70421
|
input.platform,
|
|
70014
70422
|
input.name.trim(),
|
|
@@ -70060,7 +70468,7 @@ async function queueAnalyticsActivation(input) {
|
|
|
70060
70468
|
`INSERT INTO analytics_activation_jobs(id, destination_id, conversion_id, person_id, payload_ciphertext)
|
|
70061
70469
|
VALUES ($1,$2,$3,$4,$5) ON CONFLICT(destination_id, conversion_id) DO NOTHING`,
|
|
70062
70470
|
[
|
|
70063
|
-
(0,
|
|
70471
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
70064
70472
|
destination.id,
|
|
70065
70473
|
input.conversionId,
|
|
70066
70474
|
input.personId ?? null,
|
|
@@ -70072,7 +70480,7 @@ async function queueAnalyticsActivation(input) {
|
|
|
70072
70480
|
return queued;
|
|
70073
70481
|
}
|
|
70074
70482
|
async function queueAnalyticsFormDelivery(input) {
|
|
70075
|
-
const id = (0,
|
|
70483
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
70076
70484
|
await getAnalyticsPool().query(
|
|
70077
70485
|
`INSERT INTO analytics_form_delivery_jobs(id, submission_id, owner_user_id, payload_ciphertext, last_error_code)
|
|
70078
70486
|
VALUES ($1,$2,$3,$4,$5)`,
|
|
@@ -70199,7 +70607,7 @@ async function analyticsHealth(siteId, userId) {
|
|
|
70199
70607
|
}
|
|
70200
70608
|
async function refreshAnalyticsDailyRollups(input) {
|
|
70201
70609
|
const db = getAnalyticsPool();
|
|
70202
|
-
const runId = (0,
|
|
70610
|
+
const runId = (0, import_node_crypto41.randomUUID)();
|
|
70203
70611
|
await db.query(
|
|
70204
70612
|
`INSERT INTO analytics_rollup_runs(id, window_start, window_end, status) VALUES ($1, $2, $3, 'running')`,
|
|
70205
70613
|
[runId, input.start, input.end]
|
|
@@ -70396,7 +70804,7 @@ async function createAnalyticsExport(input) {
|
|
|
70396
70804
|
`Generated ${(/* @__PURE__ */ new Date()).toISOString()} from the governed ${input.report} report contract.`
|
|
70397
70805
|
].join("\n");
|
|
70398
70806
|
}
|
|
70399
|
-
const id = (0,
|
|
70807
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
70400
70808
|
const inserted = await getAnalyticsPool().query(
|
|
70401
70809
|
`INSERT INTO analytics_exports(id, site_id, requested_by_user_id, idempotency_key, report, format, filters, content)
|
|
70402
70810
|
VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8)
|
|
@@ -70429,11 +70837,11 @@ async function createAnalyticsExport(input) {
|
|
|
70429
70837
|
}
|
|
70430
70838
|
return describeArtifact(replay.rows[0]);
|
|
70431
70839
|
}
|
|
70432
|
-
var
|
|
70840
|
+
var import_node_crypto41, import_pg, AnalyticsRepositoryError, pool2, MAX_ENGAGED_MS, ENGAGED_SESSION_MS, blockedPropertyName, inferredFamilySql, ANALYTICS_CONTENT_SORTS, clickIdKeys;
|
|
70433
70841
|
var init_analytics_repository = __esm({
|
|
70434
70842
|
"src/api/analytics-repository.ts"() {
|
|
70435
70843
|
"use strict";
|
|
70436
|
-
|
|
70844
|
+
import_node_crypto41 = require("crypto");
|
|
70437
70845
|
import_pg = require("pg");
|
|
70438
70846
|
init_session();
|
|
70439
70847
|
init_analytics_attribution();
|
|
@@ -70672,8 +71080,8 @@ function dashboardCallbackUrl() {
|
|
|
70672
71080
|
}
|
|
70673
71081
|
async function createThorbitConnectUrl(userId) {
|
|
70674
71082
|
if (!bridgeConfigured()) throw new Error("Thorbit X-Ray account bridge is not configured");
|
|
70675
|
-
const state = (0,
|
|
70676
|
-
const stateHash = (0,
|
|
71083
|
+
const state = (0, import_node_crypto42.randomBytes)(32).toString("base64url");
|
|
71084
|
+
const stateHash = (0, import_node_crypto42.createHash)("sha256").update(state).digest("hex");
|
|
70677
71085
|
await getAnalyticsPool().query(
|
|
70678
71086
|
`INSERT INTO analytics_thorbit_connect_states(state_hash,user_id,expires_at)
|
|
70679
71087
|
VALUES ($1,$2,now()+interval '10 minutes')
|
|
@@ -70688,9 +71096,9 @@ async function createThorbitConnectUrl(userId) {
|
|
|
70688
71096
|
function verifyThorbitAssertion(token6) {
|
|
70689
71097
|
const [encoded, signature] = token6.split(".");
|
|
70690
71098
|
if (!encoded || !signature || !bridgeConfigured()) throw new Error("Invalid Thorbit assertion");
|
|
70691
|
-
const expected = (0,
|
|
71099
|
+
const expected = (0, import_node_crypto42.createHmac)("sha256", bridgeSecret()).update(encoded).digest();
|
|
70692
71100
|
const actual = Buffer.from(signature, "base64url");
|
|
70693
|
-
if (actual.length !== expected.length || !(0,
|
|
71101
|
+
if (actual.length !== expected.length || !(0, import_node_crypto42.timingSafeEqual)(actual, expected)) {
|
|
70694
71102
|
throw new Error("Invalid Thorbit assertion signature");
|
|
70695
71103
|
}
|
|
70696
71104
|
const parsed = AssertionSchema.safeParse(
|
|
@@ -70702,7 +71110,7 @@ function verifyThorbitAssertion(token6) {
|
|
|
70702
71110
|
return parsed.data.entitlement;
|
|
70703
71111
|
}
|
|
70704
71112
|
async function consumeThorbitConnectCallback(input) {
|
|
70705
|
-
const stateHash = (0,
|
|
71113
|
+
const stateHash = (0, import_node_crypto42.createHash)("sha256").update(input.state).digest("hex");
|
|
70706
71114
|
const client2 = await getAnalyticsPool().connect();
|
|
70707
71115
|
try {
|
|
70708
71116
|
await client2.query("BEGIN");
|
|
@@ -70742,11 +71150,11 @@ async function disconnectAnalyticsEntitlement(userId) {
|
|
|
70742
71150
|
[userId]
|
|
70743
71151
|
);
|
|
70744
71152
|
}
|
|
70745
|
-
var
|
|
71153
|
+
var import_node_crypto42, import_zod53, THORBIT_PRODUCT_URL, REFRESH_INTERVAL_MS, ELIGIBLE_GRACE_MS, TRIAL_LENGTH_MS, ThorbitEntitlementSchema, AssertionSchema;
|
|
70746
71154
|
var init_analytics_entitlement = __esm({
|
|
70747
71155
|
"src/api/analytics-entitlement.ts"() {
|
|
70748
71156
|
"use strict";
|
|
70749
|
-
|
|
71157
|
+
import_node_crypto42 = require("crypto");
|
|
70750
71158
|
import_zod53 = require("zod");
|
|
70751
71159
|
init_analytics_repository();
|
|
70752
71160
|
THORBIT_PRODUCT_URL = "https://thorbit.ai";
|
|
@@ -70886,14 +71294,14 @@ function renderPublicForm(form, placementUrl) {
|
|
|
70886
71294
|
const brand = form.brand;
|
|
70887
71295
|
return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>:root{font-family:ui-sans-serif,system-ui;color:${escapeHtml7(brand.textColor)};background:${escapeHtml7(brand.backgroundColor)}}*{box-sizing:border-box}body{margin:0;padding:18px}form{display:grid;gap:14px}label{display:grid;gap:6px;font-size:13px;font-weight:650}.check{grid-template-columns:auto 1fr;align-items:center}.check span{grid-column:2}.check input{grid-column:1;grid-row:1}input,textarea,select{width:100%;min-height:44px;padding:10px 12px;border:1px solid #ccd3df;border-radius:${brand.radius}px;background:white;color:inherit;font:inherit}textarea{min-height:110px;resize:vertical}button{min-height:46px;border:0;border-radius:${brand.radius}px;color:white;background:${escapeHtml7(brand.primaryColor)};font:inherit;font-weight:750;cursor:pointer}.consent{margin:0;color:#667085;font-size:11px;line-height:1.45}.notice{display:none;padding:12px;border-radius:${brand.radius}px;background:#edf8f2;color:#17613c}.hp{position:absolute!important;left:-9999px!important}</style></head><body><form id="mcp-form">${fields}<label class="hp">Website<input name="website" autocomplete="off" tabindex="-1"></label>${form.consent_text ? `<p class="consent">${escapeHtml7(form.consent_text)}</p>` : ""}<button>${escapeHtml7(form.submit_label)}</button><div class="notice" role="status"></div></form><script>(()=>{const form=document.querySelector('#mcp-form'),notice=form.querySelector('.notice'),q=new URLSearchParams(location.search);form.addEventListener('submit',async event=>{event.preventDefault();const button=form.querySelector('button');button.disabled=true;const raw=Object.fromEntries(new FormData(form).entries()),website=String(raw.website||''),clickIds={};delete raw.website;for(const k of ['fbclid','gclid','gbraid','wbraid','ttclid','rdt_cid','msclkid']){const v=q.get(k);if(v)clickIds[k]=v}try{const response=await fetch('/analytics/forms/${escapeHtml7(form.public_id)}/submissions',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({data:raw,website,placementUrl:${JSON.stringify(placementUrl)},visitorId:q.get('visitor')||undefined,sessionId:q.get('session')||undefined,source:q.get('source')||undefined,medium:q.get('medium')||undefined,campaign:q.get('campaign')||undefined,clickIds})});if(!response.ok)throw new Error('submit');notice.textContent=${JSON.stringify(form.success_message)};notice.style.display='block';form.reset();${form.redirect_url ? `setTimeout(()=>{top.location.href=${JSON.stringify(form.redirect_url)}},700);` : ""}}catch{notice.textContent='Your response could not be submitted. Please try again.';notice.style.display='block'}finally{button.disabled=false}})})()</script></body></html>`;
|
|
70888
71296
|
}
|
|
70889
|
-
var import_hono32, import_factory6, import_zod54,
|
|
71297
|
+
var import_hono32, import_factory6, import_zod54, import_node_crypto43, import_papaparse4, analyticsApp, auth3, entitlementGuard, ThorbitApiKeySchema, ThorbitCallbackSchema, SiteInputSchema, PixelInputSchema, PixelUpdateSchema, EventSchema, IngestionSchema, ConversionSchema, ExportSchema2, CampaignLinkSchema, FormFieldSchema, FormInputSchema, FormSubmissionSchema, CrmImportSchema, ActivationDestinationSchema, BusinessModelSchema, AdSpendSchema;
|
|
70890
71298
|
var init_analytics_routes = __esm({
|
|
70891
71299
|
"src/api/analytics-routes.ts"() {
|
|
70892
71300
|
"use strict";
|
|
70893
71301
|
import_hono32 = require("hono");
|
|
70894
71302
|
import_factory6 = require("hono/factory");
|
|
70895
71303
|
import_zod54 = require("zod");
|
|
70896
|
-
|
|
71304
|
+
import_node_crypto43 = require("crypto");
|
|
70897
71305
|
import_papaparse4 = __toESM(require("papaparse"), 1);
|
|
70898
71306
|
init_api_auth();
|
|
70899
71307
|
init_db();
|
|
@@ -71224,7 +71632,7 @@ var init_analytics_routes = __esm({
|
|
|
71224
71632
|
const lastName = typeof data.last_name === "string" ? data.last_name.trim() : "";
|
|
71225
71633
|
const fullName = [firstName, lastName].filter(Boolean).join(" ") || (typeof data.name === "string" ? data.name.trim() : "") || email || "Website lead";
|
|
71226
71634
|
const identitySeed = email || `${fullName}:${Date.now()}`;
|
|
71227
|
-
const suffix2 = (0,
|
|
71635
|
+
const suffix2 = (0, import_node_crypto43.createHash)("sha256").update(identitySeed).digest("hex").slice(0, 12);
|
|
71228
71636
|
const path6 = `Leads/person-${suffix2}`;
|
|
71229
71637
|
const { key: memoryKey, error: memoryKeyError } = await getOrCreateUserMemoryKey(user);
|
|
71230
71638
|
const existing = memoryKey ? await memoryCall("getTool", { vault: "People", path: path6 }, memoryKey) : { ok: false, error: memoryKeyError || "memory_credential_unavailable" };
|
|
@@ -71323,9 +71731,9 @@ Submitted the published form.
|
|
|
71323
71731
|
occurredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
71324
71732
|
});
|
|
71325
71733
|
const match = {
|
|
71326
|
-
...email ? { emailSha256: (0,
|
|
71734
|
+
...email ? { emailSha256: (0, import_node_crypto43.createHash)("sha256").update(email).digest("hex") } : {},
|
|
71327
71735
|
...phone ? {
|
|
71328
|
-
phoneSha256: (0,
|
|
71736
|
+
phoneSha256: (0, import_node_crypto43.createHash)("sha256").update(phone.replace(/\D/g, "")).digest("hex")
|
|
71329
71737
|
} : {}
|
|
71330
71738
|
};
|
|
71331
71739
|
const activationQueued = await queueAnalyticsActivation({
|
|
@@ -71753,7 +72161,7 @@ Submitted the published form.
|
|
|
71753
72161
|
rejectedCount += 1;
|
|
71754
72162
|
continue;
|
|
71755
72163
|
}
|
|
71756
|
-
const digest2 = (0,
|
|
72164
|
+
const digest2 = (0, import_node_crypto43.createHash)("sha256").update(
|
|
71757
72165
|
`${parsed.data.sourceSystem}:${externalId || email || phone || `${fullName}:${index}`}`
|
|
71758
72166
|
).digest("hex").slice(0, 16);
|
|
71759
72167
|
const path6 = `Leads/person-${digest2}`;
|
|
@@ -72211,13 +72619,13 @@ var init_analytics_delivery = __esm({
|
|
|
72211
72619
|
|
|
72212
72620
|
// src/api/scheduled-artifact-owner.ts
|
|
72213
72621
|
function scheduledArtifactOwnerIdForApiKey(apiKey) {
|
|
72214
|
-
return (0,
|
|
72622
|
+
return (0, import_node_crypto44.createHash)("sha256").update(apiKey).digest("hex").slice(0, 24);
|
|
72215
72623
|
}
|
|
72216
|
-
var
|
|
72624
|
+
var import_node_crypto44;
|
|
72217
72625
|
var init_scheduled_artifact_owner = __esm({
|
|
72218
72626
|
"src/api/scheduled-artifact-owner.ts"() {
|
|
72219
72627
|
"use strict";
|
|
72220
|
-
|
|
72628
|
+
import_node_crypto44 = require("crypto");
|
|
72221
72629
|
}
|
|
72222
72630
|
});
|
|
72223
72631
|
|
|
@@ -72274,7 +72682,7 @@ async function ensureScheduledRunViewLinksSchema() {
|
|
|
72274
72682
|
schemaReady2 = true;
|
|
72275
72683
|
}
|
|
72276
72684
|
function tokenHash2(token6) {
|
|
72277
|
-
return (0,
|
|
72685
|
+
return (0, import_node_crypto45.createHash)("sha256").update(token6).digest("hex");
|
|
72278
72686
|
}
|
|
72279
72687
|
function mapRow(row) {
|
|
72280
72688
|
return {
|
|
@@ -72294,9 +72702,9 @@ function mapRow(row) {
|
|
|
72294
72702
|
async function createScheduledRunViewLink(input) {
|
|
72295
72703
|
await ensureScheduledRunViewLinksSchema();
|
|
72296
72704
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
72297
|
-
const token6 = (0,
|
|
72705
|
+
const token6 = (0, import_node_crypto45.randomBytes)(32).toString("base64url");
|
|
72298
72706
|
const record = {
|
|
72299
|
-
shareId: (0,
|
|
72707
|
+
shareId: (0, import_node_crypto45.randomUUID)(),
|
|
72300
72708
|
ownerId: input.ownerId,
|
|
72301
72709
|
runId: input.runId,
|
|
72302
72710
|
artifactId: input.artifactId,
|
|
@@ -72359,11 +72767,11 @@ async function revokeScheduledRunViewLink(ownerId, runId, shareId, now = /* @__P
|
|
|
72359
72767
|
});
|
|
72360
72768
|
return result.rowsAffected > 0;
|
|
72361
72769
|
}
|
|
72362
|
-
var
|
|
72770
|
+
var import_node_crypto45, schemaReady2;
|
|
72363
72771
|
var init_scheduled_run_view_links = __esm({
|
|
72364
72772
|
"src/api/scheduled-run-view-links.ts"() {
|
|
72365
72773
|
"use strict";
|
|
72366
|
-
|
|
72774
|
+
import_node_crypto45 = require("crypto");
|
|
72367
72775
|
init_db();
|
|
72368
72776
|
schemaReady2 = false;
|
|
72369
72777
|
}
|
|
@@ -72429,15 +72837,15 @@ ${section(flags.finalCta && Boolean(finalCta), `<section class="section cta" id=
|
|
|
72429
72837
|
html,
|
|
72430
72838
|
filename: `${input.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "personal-authority"}.html`,
|
|
72431
72839
|
bytes,
|
|
72432
|
-
sha256: (0,
|
|
72840
|
+
sha256: (0, import_node_crypto46.createHash)("sha256").update(html).digest("hex"),
|
|
72433
72841
|
generatedAt: generatedAtIso
|
|
72434
72842
|
};
|
|
72435
72843
|
}
|
|
72436
|
-
var
|
|
72844
|
+
var import_node_crypto46;
|
|
72437
72845
|
var init_render2 = __esm({
|
|
72438
72846
|
"src/personal-authority/render.ts"() {
|
|
72439
72847
|
"use strict";
|
|
72440
|
-
|
|
72848
|
+
import_node_crypto46 = require("crypto");
|
|
72441
72849
|
}
|
|
72442
72850
|
});
|
|
72443
72851
|
|
|
@@ -72540,15 +72948,15 @@ ${section2(flags.finalCta && Boolean(finalCta), `<section class="section cta" id
|
|
|
72540
72948
|
html,
|
|
72541
72949
|
filename: `${input.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "personal-authority"}.html`,
|
|
72542
72950
|
bytes,
|
|
72543
|
-
sha256: (0,
|
|
72951
|
+
sha256: (0, import_node_crypto47.createHash)("sha256").update(html).digest("hex"),
|
|
72544
72952
|
generatedAt: generatedAtIso
|
|
72545
72953
|
};
|
|
72546
72954
|
}
|
|
72547
|
-
var
|
|
72955
|
+
var import_node_crypto47, FONT_STACKS;
|
|
72548
72956
|
var init_render_v2 = __esm({
|
|
72549
72957
|
"src/personal-authority/render-v2.ts"() {
|
|
72550
72958
|
"use strict";
|
|
72551
|
-
|
|
72959
|
+
import_node_crypto47 = require("crypto");
|
|
72552
72960
|
init_contracts();
|
|
72553
72961
|
FONT_STACKS = Object.freeze({
|
|
72554
72962
|
"editorial-serif": "Iowan Old Style, Baskerville, Times New Roman, serif",
|
|
@@ -72664,15 +73072,15 @@ body{overflow-x:hidden}.lead-story__body,.lead-support__item,.story-card__body{m
|
|
|
72664
73072
|
@media(max-width:620px){.desk-section__grid--panorama,.desk-section__grid--mosaic,.desk-section__grid--tiles{grid-template-columns:1fr}.story-card--panorama{display:block}.story-card--panorama h3,.story-card--mosaic-lead h3{font-size:34px}.story-card--mosaic-lead{grid-column:auto;grid-row:auto}.desk-section__grid--tiles>.story-card:nth-child(3n+2){margin-top:0}}
|
|
72665
73073
|
</style></head><body data-theme="${escapeHtml10(config.theme)}" id="top" data-scheduled-renderer="newsroom_publisher_v1">${ticker}${masthead}${navigation}<main>${leadGrid}${latest}${sections}${newsletter}${pressRoom}${trustCenter}</main>${trustFooter}</body></html>`;
|
|
72666
73074
|
const bytes = Buffer.byteLength(html);
|
|
72667
|
-
const sha2563 = (0,
|
|
73075
|
+
const sha2563 = (0, import_node_crypto48.createHash)("sha256").update(html).digest("hex");
|
|
72668
73076
|
const filename = `${brand.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "newsroom"}-news-site.html`;
|
|
72669
73077
|
return { html, filename, bytes, sha256: sha2563, generatedAt: generatedAtIso };
|
|
72670
73078
|
}
|
|
72671
|
-
var
|
|
73079
|
+
var import_node_crypto48;
|
|
72672
73080
|
var init_render3 = __esm({
|
|
72673
73081
|
"src/newsroom-publisher/render.ts"() {
|
|
72674
73082
|
"use strict";
|
|
72675
|
-
|
|
73083
|
+
import_node_crypto48 = require("crypto");
|
|
72676
73084
|
}
|
|
72677
73085
|
});
|
|
72678
73086
|
|
|
@@ -72764,7 +73172,7 @@ function renderBlogArticleV1(input, config, generatedAt) {
|
|
|
72764
73172
|
:root{--ink:#10213d;--ink2:#1c355a;--blue:#2563eb;--blue2:#1749b6;--mint:#45d5aa;--paper:#f7f5f0;--line:#dce4ef;--card:#fff;--body:#475569;--serif:Iowan Old Style,Palatino Linotype,Palatino,Georgia,serif;--sans:Inter,Avenir Next,ui-sans-serif,system-ui,sans-serif}body[data-theme="slate"]{--ink:#1e293b;--ink2:#334155;--blue:#475569;--blue2:#1e293b;--mint:#94a3b8;--paper:#f8fafc}body[data-theme="forest"]{--ink:#12352e;--ink2:#23584c;--blue:#147d64;--blue2:#0c5b48;--mint:#79d8bd;--paper:#f4f8f3}*{box-sizing:border-box}html{scroll-behavior:smooth;background:var(--paper)}body{margin:0;color:#252a33;background:var(--paper);font-family:var(--sans);line-height:1.6}a{color:inherit}button{font:inherit}button:focus-visible,a:focus-visible{outline:3px solid var(--mint);outline-offset:3px}.progress{position:fixed;z-index:50;top:0;left:0;height:4px;width:0;background:var(--mint)}.hero{position:relative;overflow:hidden;color:#fff;background:var(--ink)}.hero:after{position:absolute;right:-110px;top:-150px;width:420px;height:420px;border:1px solid #ffffff1a;border-radius:50%;content:""}.hero-inner{position:relative;z-index:1;max-width:1240px;margin:auto;padding:58px 42px 126px}.breadcrumb{display:flex;gap:8px;margin-bottom:34px;color:#dbeafecc;font-size:14px}.eyebrow{display:block;color:var(--blue);font-size:12px;font-weight:800;letter-spacing:.16em;text-transform:uppercase}.hero .eyebrow{color:var(--mint)}h1,h2,h3,p{margin-top:0}.hero h1{max-width:1000px;margin:14px 0 24px;font:700 clamp(44px,6vw,78px)/.98 var(--serif);letter-spacing:-.035em}.hero .dek{max-width:780px;color:#dbeafe;font-size:20px}.contributors{margin-top:30px;color:#eff6ff;font-size:14px}.contributors a{font-weight:800}.meta{display:flex;flex-wrap:wrap;gap:12px;margin-top:6px;color:#dbeafecc}.layout{position:relative;z-index:2;display:grid;grid-template-columns:minmax(0,760px) 290px;gap:64px;max-width:1240px;margin:-78px auto 0;padding:0 42px 80px}.main{min-width:0}.takeaways{padding:38px 44px;border-radius:24px;background:#fff;box-shadow:0 24px 70px #10213d24}.takeaways h2{margin:5px 0 20px;font:700 32px/1.1 var(--serif);color:var(--ink)}.takeaways ul{display:grid;gap:16px;margin:0;padding:0;list-style:none}.takeaways li{position:relative;padding-left:26px;color:var(--body);font-size:17px}.takeaways li:before{position:absolute;left:2px;top:.7em;width:8px;height:8px;border-radius:50%;background:var(--blue);content:""}.intro{padding:40px 0 4px}.intro p,.article-section>p{margin-bottom:22px;color:var(--body);font:400 18px/1.75 var(--sans)}.article-section{scroll-margin-top:28px;padding-top:45px}.article-section h2,.faq h2{margin:6px 0 20px;color:var(--ink);font:700 38px/1.08 var(--serif);letter-spacing:-.02em}.article-section ul{display:grid;gap:10px;margin:22px 0;padding-left:24px;color:var(--body);font-size:17px}.article-section li::marker{color:var(--blue)}.callout{margin:34px 0;padding:24px 28px;border-left:4px solid var(--blue);border-radius:0 16px 16px 0;background:#fff}.callout span{color:var(--blue);font-size:11px;font-weight:800;letter-spacing:.13em;text-transform:uppercase}.callout h3{margin:5px 0 8px;color:var(--ink);font:700 24px/1.15 var(--serif)}.callout p{margin:0;color:var(--body)}.rail{padding-top:0}.sidebar-media{overflow:hidden;margin:0 0 18px;border:1px solid #dbeafe;border-radius:16px;background:#fff}.sidebar-media img,.sidebar-media svg{display:block;width:100%;aspect-ratio:16/9;object-fit:cover}.sidebar-media figcaption{padding:10px 13px;color:#64748b;font-size:11px}.disclosure{margin-bottom:28px;border-top:1px solid #dbeafe;border-bottom:1px solid #dbeafe}.disclosure button{display:flex;width:100%;align-items:center;justify-content:space-between;gap:14px;padding:15px 0;border:0;color:#64748b;background:transparent;text-align:left;font-size:12px;cursor:pointer}.disclosure button b{color:var(--blue);font-size:18px;transition:transform .2s}.disclosure button[aria-expanded="true"] b{transform:rotate(180deg)}.disclosure p{padding:0 0 16px;margin:0;color:#64748b;font-size:12px}.toc{position:sticky;top:30px;padding:22px;border:1px solid var(--line);border-radius:16px;background:#fff;box-shadow:0 2px 5px #10213d12}.toc header{display:flex;align-items:center;justify-content:space-between}.toc header strong{color:var(--ink);font:700 21px/1 var(--serif)}.toc header button{width:34px;height:34px;border:0;border-radius:50%;color:var(--blue);background:transparent;cursor:pointer}.toc nav{display:grid;margin-top:14px}.toc nav a{display:flex;align-items:flex-start;gap:11px;padding:8px 0;color:#64748b;text-decoration:none;font-size:13px;line-height:1.35}.toc nav i{width:8px;height:8px;margin-top:5px;border:2px solid #bfdbfe;border-radius:50%}.toc nav a[aria-current="location"]{color:var(--ink);font-weight:800}.toc nav a[aria-current="location"] i{border-color:var(--blue);background:var(--blue)}.back-top{width:100%;margin-top:18px;padding:16px 0 0;border:0;border-top:1px solid var(--line);color:var(--blue);background:transparent;text-align:right;font-size:13px;font-weight:800;cursor:pointer}.faq{scroll-margin-top:28px;padding-top:64px}.faq>div{border-top:1px solid var(--line);border-bottom:1px solid var(--line)}.faq article+article{border-top:1px solid var(--line)}.faq h3{margin:0}.faq h3 button{display:flex;width:100%;align-items:center;justify-content:space-between;gap:18px;padding:19px 0;border:0;color:var(--ink);background:transparent;text-align:left;font-weight:800;cursor:pointer}.faq h3 b{color:var(--blue);font-size:22px}.faq article>p{padding:0 0 20px;margin:0;color:var(--body);font-size:16px}.author-card{margin-top:64px;padding:32px 36px;border-radius:18px;background:#fff}.article-actions{display:flex;flex-wrap:wrap;justify-content:space-between;gap:14px}.article-actions button{display:inline-flex;min-height:46px;align-items:center;justify-content:center;gap:8px;padding:8px 18px;border:2px solid var(--blue);border-radius:999px;color:var(--ink);background:#fff;font-weight:800;cursor:pointer}.article-actions button:hover{color:#fff;background:var(--blue)}.action-status{min-height:20px;margin:8px 0 0;color:var(--blue);text-align:right;font-size:13px;font-weight:700}.author-grid{display:grid;grid-template-columns:auto 1fr auto;gap:22px;align-items:center;margin-top:24px}.author-portrait{width:88px;height:88px;border-radius:50%;object-fit:cover}.author-initials{display:grid;place-items:center;color:var(--ink);background:#fecdd3;font-size:22px;font-weight:900}.author-grid span{color:#64748b;font-size:13px}.author-grid h2{margin:2px 0;color:var(--ink);font:700 27px/1 var(--serif)}.author-grid h2 a{text-decoration:none}.author-grid p{margin:8px 0;color:#64748b;font-size:14px}.author-grid nav{display:flex;flex-wrap:wrap;gap:14px}.author-grid nav a{color:#64748b;font-size:12px}.author-more{display:inline-flex;min-height:48px;align-items:center;justify-content:center;padding:10px 24px;border:2px solid var(--blue);color:var(--blue);text-align:center;text-decoration:none;font-size:13px;font-weight:800}.author-bio{margin:24px 0 0!important;padding-top:20px;border-top:1px solid var(--line);color:var(--body);font-size:16px}dialog{width:min(720px,calc(100% - 30px));max-height:calc(100dvh - 30px);padding:0;border:0;border-radius:18px;color:var(--ink);background:#fff;box-shadow:0 24px 70px #10213d38}dialog::backdrop{background:#0f172a7a;backdrop-filter:blur(2px)}dialog>div{position:relative;padding:30px}dialog h2{margin:0 50px 2px 0;font:700 30px/1.1 var(--serif)}dialog>div>p{color:#64748b}.dialog-close{position:absolute;top:13px;right:13px;width:44px;height:44px;border:0;border-radius:50%;color:var(--blue);background:transparent;font-size:29px;cursor:pointer}dialog section{border-top:1px solid var(--line)}dialog section button{display:block;width:100%;padding:17px 5px;border:0;border-bottom:1px solid var(--line);color:var(--body);background:#fff;text-align:left;line-height:1.65;cursor:pointer}.citation-status{min-height:22px;margin:14px 0 0!important;color:var(--blue)!important;font-size:13px;font-weight:800}.generated{max-width:1156px;margin:-52px auto 50px;padding:0 42px;color:#94a3b8;font-size:11px}@media(max-width:900px){.layout{display:block}.rail{display:none}.hero-inner{padding-bottom:116px}}@media(max-width:620px){.hero-inner{padding:36px 20px 104px}.hero h1{font-size:46px}.hero .dek{font-size:17px}.layout{margin-top:-70px;padding:0 16px 54px}.takeaways{padding:28px 24px}.article-section h2,.faq h2{font-size:32px}.author-card{padding:24px}.article-actions{display:grid;justify-content:start}.author-grid{grid-template-columns:1fr;gap:12px}.author-more{width:100%}dialog>div{padding:24px}.generated{padding:0 20px}}
|
|
72765
73173
|
</style></head><body data-theme="${escapeHtml11(config.theme)}" data-scheduled-renderer="blog_article_v1"><div class="progress" aria-hidden="true"></div><header class="hero"><div class="hero-inner"><nav class="breadcrumb" aria-label="Breadcrumb"><a href="${safeHref4(input.canonicalUrl)}">${escapeHtml11(input.category)}</a><span>/</span><span>Article</span></nav><span class="eyebrow">${escapeHtml11(input.eyebrow)}</span><h1>${escapeHtml11(input.title)}</h1>${input.dek ? `<p class="dek">${escapeHtml11(input.dek)}</p>` : ""}<div class="contributors">${contributorText}<div class="meta"><time datetime="${escapeHtml11(articleDate)}">Updated ${formatDate2(articleDate)}</time><span>\u2022</span><span>${input.readTimeMinutes} min read</span>${input.reviewer ? "<span>\u2022</span><strong>Expert reviewed</strong>" : ""}</div></div></div></header><main class="layout"><article class="main"><section class="takeaways"><span class="eyebrow">The short answer</span><h2>Key takeaways</h2><ul>${input.keyTakeaways.map((item) => `<li>${escapeHtml11(item)}</li>`).join("")}</ul></section><section class="intro">${input.introduction.map((paragraph) => `<p>${escapeHtml11(paragraph)}</p>`).join("")}</section>${sections}${faq}${author}</article><div class="rail">${media}${disclosure}${toc}</div></main>${config.showGeneratedAt ? `<p class="generated">Rendered ${formatDate2(generatedAtIso)} by MCP Scraper.</p>` : ""}${citationDialog}<script>(()=>{const citations=${jsonForScript(citationValues)};const canonical=${jsonForScript(input.canonicalUrl)};const title=${jsonForScript(input.title)};const progress=document.querySelector('.progress');const tocLinks=[...document.querySelectorAll('.toc nav a')];const targets=tocLinks.map(link=>document.querySelector(link.hash)).filter(Boolean);const update=()=>{const max=document.documentElement.scrollHeight-innerHeight;if(progress)progress.style.width=(max>0?scrollY/max*100:0)+'%';let active=targets[0]?.id;for(const target of targets){if(target.getBoundingClientRect().top<=innerHeight*.55)active=target.id}tocLinks.forEach(link=>link.toggleAttribute('aria-current',link.hash==='#'+active));tocLinks.forEach(link=>{if(link.hash==='#'+active)link.setAttribute('aria-current','location');else link.removeAttribute('aria-current')})};addEventListener('scroll',update,{passive:true});addEventListener('resize',update);update();document.querySelectorAll('.faq h3 button').forEach(button=>button.addEventListener('click',()=>{const panel=document.getElementById(button.getAttribute('aria-controls'));const open=button.getAttribute('aria-expanded')==='true';button.setAttribute('aria-expanded',String(!open));panel.hidden=open;button.querySelector('b').textContent=open?'+':'\u2212'}));const disclosure=document.querySelector('.disclosure button');disclosure?.addEventListener('click',()=>{const panel=document.getElementById(disclosure.getAttribute('aria-controls'));const open=disclosure.getAttribute('aria-expanded')==='true';disclosure.setAttribute('aria-expanded',String(!open));panel.hidden=open});const tocToggle=document.querySelector('.toc header button');tocToggle?.addEventListener('click',()=>{const nav=document.getElementById('toc-links');const open=tocToggle.getAttribute('aria-expanded')==='true';tocToggle.setAttribute('aria-expanded',String(!open));nav.hidden=open;tocToggle.textContent=open?'\u2304':'\u2303'});document.querySelector('.back-top')?.addEventListener('click',()=>scrollTo({top:0,behavior:'smooth'}));const copy=async text=>{try{await navigator.clipboard.writeText(text)}catch{const area=document.createElement('textarea');area.value=text;area.style.position='fixed';area.style.opacity='0';document.body.append(area);area.select();document.execCommand('copy');area.remove()}};const dialog=document.getElementById('citation-dialog');document.querySelector('[data-cite]')?.addEventListener('click',()=>dialog.showModal());document.querySelector('.dialog-close')?.addEventListener('click',()=>dialog.close());dialog?.addEventListener('click',event=>{if(event.target===dialog)dialog.close()});document.querySelectorAll('[data-citation]').forEach(button=>button.addEventListener('click',async()=>{const style=button.dataset.citation;await copy(citations[style]);document.querySelector('.citation-status').textContent=style+' citation copied to clipboard.'}));document.querySelector('[data-share]')?.addEventListener('click',async()=>{const status=document.querySelector('.action-status');if(navigator.share){try{await navigator.share({title,url:canonical});status.textContent='Sharing options opened.';return}catch(error){if(error.name==='AbortError')return}}await copy(canonical);status.textContent='Article link copied to clipboard.'})})()</script></body></html>`;
|
|
72766
73174
|
const bytes = Buffer.byteLength(html);
|
|
72767
|
-
const sha2563 = (0,
|
|
73175
|
+
const sha2563 = (0, import_node_crypto49.createHash)("sha256").update(html).digest("hex");
|
|
72768
73176
|
return {
|
|
72769
73177
|
html,
|
|
72770
73178
|
filename: "blog-article.html",
|
|
@@ -72774,11 +73182,11 @@ function renderBlogArticleV1(input, config, generatedAt) {
|
|
|
72774
73182
|
generatedAt: generatedAtIso
|
|
72775
73183
|
};
|
|
72776
73184
|
}
|
|
72777
|
-
var
|
|
73185
|
+
var import_node_crypto49;
|
|
72778
73186
|
var init_render4 = __esm({
|
|
72779
73187
|
"src/blog-article/render.ts"() {
|
|
72780
73188
|
"use strict";
|
|
72781
|
-
|
|
73189
|
+
import_node_crypto49 = require("crypto");
|
|
72782
73190
|
}
|
|
72783
73191
|
});
|
|
72784
73192
|
|
|
@@ -73109,7 +73517,7 @@ function policy5() {
|
|
|
73109
73517
|
};
|
|
73110
73518
|
}
|
|
73111
73519
|
function runStorageSegment(runId) {
|
|
73112
|
-
return /^[a-zA-Z0-9_-]{1,160}$/.test(runId) ? runId : `run-${(0,
|
|
73520
|
+
return /^[a-zA-Z0-9_-]{1,160}$/.test(runId) ? runId : `run-${(0, import_node_crypto50.createHash)("sha256").update(runId).digest("hex").slice(0, 32)}`;
|
|
73113
73521
|
}
|
|
73114
73522
|
async function createScheduledRunArtifact(args) {
|
|
73115
73523
|
if (args.rendered.bytes > SCHEDULED_RUN_ARTIFACT_MAX_BYTES) {
|
|
@@ -73150,12 +73558,12 @@ async function readScheduledRunArtifact(args) {
|
|
|
73150
73558
|
if (!window2 || window2.nextOffset !== null || window2.totalBytes > SCHEDULED_RUN_ARTIFACT_MAX_BYTES) return null;
|
|
73151
73559
|
return window2.text;
|
|
73152
73560
|
}
|
|
73153
|
-
var
|
|
73561
|
+
var import_node_crypto50, SCHEDULED_RUN_ARTIFACT_PREFIX, SCHEDULED_RUN_ARTIFACT_DOWNLOAD_TTL_MS, SCHEDULED_RUN_ARTIFACT_MAX_BYTES;
|
|
73154
73562
|
var init_scheduled_run_artifact_store = __esm({
|
|
73155
73563
|
"src/scheduled-artifacts/scheduled-run-artifact-store.ts"() {
|
|
73156
73564
|
"use strict";
|
|
73157
73565
|
init_private_artifacts();
|
|
73158
|
-
|
|
73566
|
+
import_node_crypto50 = require("crypto");
|
|
73159
73567
|
SCHEDULED_RUN_ARTIFACT_PREFIX = "scheduled-run-artifacts/";
|
|
73160
73568
|
SCHEDULED_RUN_ARTIFACT_DOWNLOAD_TTL_MS = 15 * 60 * 1e3;
|
|
73161
73569
|
SCHEDULED_RUN_ARTIFACT_MAX_BYTES = 2e6;
|
|
@@ -73373,7 +73781,7 @@ async function reconcileDiscoveredNangoConnections(identity, discovered) {
|
|
|
73373
73781
|
updated_at = excluded.updated_at
|
|
73374
73782
|
`,
|
|
73375
73783
|
args: [
|
|
73376
|
-
(0,
|
|
73784
|
+
(0, import_node_crypto51.randomUUID)(),
|
|
73377
73785
|
userId,
|
|
73378
73786
|
connection.providerConfigKey,
|
|
73379
73787
|
connection.provider,
|
|
@@ -73444,7 +73852,7 @@ async function recordServiceConnectionHealth(args) {
|
|
|
73444
73852
|
});
|
|
73445
73853
|
await getDb().execute({
|
|
73446
73854
|
sql: `INSERT INTO service_connection_health_events (id, connection_id, operational_status, failure_code, retryable, evidence_source) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
73447
|
-
args: [(0,
|
|
73855
|
+
args: [(0, import_node_crypto51.randomUUID)(), args.connectionId, args.operationalStatus, args.failureCode ?? null, args.retryable == null ? null : args.retryable ? 1 : 0, args.evidenceSource]
|
|
73448
73856
|
});
|
|
73449
73857
|
}
|
|
73450
73858
|
async function setServiceConnectionActions(identity, connectionId, enabled) {
|
|
@@ -73484,7 +73892,7 @@ async function claimServiceConnectionAction(args) {
|
|
|
73484
73892
|
if (!connection) throw new Error("service_connection_not_found");
|
|
73485
73893
|
const inserted = await getDb().execute({
|
|
73486
73894
|
sql: `INSERT OR IGNORE INTO service_connection_action_audit (id, connection_id, user_id, tool, request_id, status, request_digest) VALUES (?, ?, ?, ?, ?, 'started', ?)`,
|
|
73487
|
-
args: [(0,
|
|
73895
|
+
args: [(0, import_node_crypto51.randomUUID)(), connection.id, connection.userId, args.tool, args.requestId, args.requestDigest]
|
|
73488
73896
|
});
|
|
73489
73897
|
if (Number(inserted.rowsAffected ?? 0) === 1) return { claimed: true };
|
|
73490
73898
|
const existing = await getDb().execute({
|
|
@@ -73509,11 +73917,11 @@ async function claimServiceConnectionAction(args) {
|
|
|
73509
73917
|
...result !== void 0 ? { result } : {}
|
|
73510
73918
|
};
|
|
73511
73919
|
}
|
|
73512
|
-
var
|
|
73920
|
+
var import_node_crypto51, schemaReady3, schemaDb4;
|
|
73513
73921
|
var init_service_connections = __esm({
|
|
73514
73922
|
"src/api/service-connections.ts"() {
|
|
73515
73923
|
"use strict";
|
|
73516
|
-
|
|
73924
|
+
import_node_crypto51 = require("crypto");
|
|
73517
73925
|
init_db();
|
|
73518
73926
|
schemaReady3 = null;
|
|
73519
73927
|
schemaDb4 = null;
|
|
@@ -73527,8 +73935,8 @@ function signingSecret() {
|
|
|
73527
73935
|
return secret2;
|
|
73528
73936
|
}
|
|
73529
73937
|
function schedulerIntegrationSignature(args) {
|
|
73530
|
-
const bodyHash = (0,
|
|
73531
|
-
return (0,
|
|
73938
|
+
const bodyHash = (0, import_node_crypto52.createHash)("sha256").update(args.body).digest("hex");
|
|
73939
|
+
return (0, import_node_crypto52.createHmac)("sha256", args.secret).update(`${args.method.toUpperCase()}
|
|
73532
73940
|
${args.path}
|
|
73533
73941
|
${args.timestamp}
|
|
73534
73942
|
${args.nonce}
|
|
@@ -73575,17 +73983,17 @@ async function verifySchedulerIntegrationRequest(request, rawBody) {
|
|
|
73575
73983
|
});
|
|
73576
73984
|
const suppliedBytes = Buffer.from(signature, "hex");
|
|
73577
73985
|
const expectedBytes = Buffer.from(expected, "hex");
|
|
73578
|
-
if (suppliedBytes.length !== expectedBytes.length || !(0,
|
|
73986
|
+
if (suppliedBytes.length !== expectedBytes.length || !(0, import_node_crypto52.timingSafeEqual)(suppliedBytes, expectedBytes)) {
|
|
73579
73987
|
throw new SchedulerIntegrationAuthError("invalid_signature");
|
|
73580
73988
|
}
|
|
73581
73989
|
await claimNonce(nonce, timestampMs);
|
|
73582
73990
|
return { requestId };
|
|
73583
73991
|
}
|
|
73584
|
-
var
|
|
73992
|
+
var import_node_crypto52, MAX_CLOCK_SKEW_MS, SchedulerIntegrationAuthError;
|
|
73585
73993
|
var init_scheduler_integration_auth = __esm({
|
|
73586
73994
|
"src/api/scheduler-integration-auth.ts"() {
|
|
73587
73995
|
"use strict";
|
|
73588
|
-
|
|
73996
|
+
import_node_crypto52 = require("crypto");
|
|
73589
73997
|
init_db();
|
|
73590
73998
|
init_service_connections();
|
|
73591
73999
|
MAX_CLOCK_SKEW_MS = 5 * 60 * 1e3;
|
|
@@ -73893,7 +74301,7 @@ async function fetchMedia(rawUrl, expectedType) {
|
|
|
73893
74301
|
finalUrl: checked.parsed.href,
|
|
73894
74302
|
width: dimensions?.width ?? null,
|
|
73895
74303
|
height: dimensions?.height ?? null,
|
|
73896
|
-
sha256: (0,
|
|
74304
|
+
sha256: (0, import_node_crypto53.createHash)("sha256").update(bytes).digest("hex")
|
|
73897
74305
|
};
|
|
73898
74306
|
}
|
|
73899
74307
|
throw new Error("media_redirect_rejected");
|
|
@@ -74007,7 +74415,7 @@ async function packagePageMedia(args) {
|
|
|
74007
74415
|
files.push({ path: "summary.json", content: Buffer.from(JSON.stringify(summary, null, 2)) });
|
|
74008
74416
|
files.push({ path: "media.jsonl", content: Buffer.from(cleanAssets.map((asset) => JSON.stringify(asset)).join("\n") + "\n") });
|
|
74009
74417
|
const archive = await zipBuffer2(files);
|
|
74010
|
-
const id = (0,
|
|
74418
|
+
const id = (0, import_node_crypto53.randomBytes)(6).toString("hex");
|
|
74011
74419
|
const pointer = await createPrivateArtifact({
|
|
74012
74420
|
policy: policy6(),
|
|
74013
74421
|
ownerId: args.ownerId,
|
|
@@ -74020,11 +74428,11 @@ async function packagePageMedia(args) {
|
|
|
74020
74428
|
const localPath = token5() ? null : (0, import_node_path21.join)(process.env.MCP_SCRAPER_OUTPUT_DIR?.trim() || (0, import_node_path21.join)((0, import_node_os14.homedir)(), "Downloads", "mcp-scraper"), "blobs", pointer.artifactId);
|
|
74021
74429
|
return { media: args.media, artifact: { ...pointer, localPath } };
|
|
74022
74430
|
}
|
|
74023
|
-
var
|
|
74431
|
+
var import_node_crypto53, import_node_os14, import_node_path21, import_p_limit7, import_yazl3, PAGE_MEDIA_ARTIFACT_PREFIX, PAGE_MEDIA_ARTIFACT_TTL_MS, PAGE_MEDIA_DOWNLOAD_TTL_MS, MAX_FILE_BYTES, MAX_ARCHIVE_MEDIA_BYTES, MAX_INLINE_IMAGE_BYTES2, MAX_INLINE_TOTAL_BYTES2, DOWNLOAD_CONCURRENCY2, MAX_REDIRECTS3;
|
|
74024
74432
|
var init_page_media_artifacts = __esm({
|
|
74025
74433
|
"src/api/page-media-artifacts.ts"() {
|
|
74026
74434
|
"use strict";
|
|
74027
|
-
|
|
74435
|
+
import_node_crypto53 = require("crypto");
|
|
74028
74436
|
import_node_os14 = require("os");
|
|
74029
74437
|
import_node_path21 = require("path");
|
|
74030
74438
|
import_p_limit7 = __toESM(require("p-limit"), 1);
|
|
@@ -74118,7 +74526,7 @@ var init_site_extract_reconciliation = __esm({
|
|
|
74118
74526
|
|
|
74119
74527
|
// src/api/page-diff.ts
|
|
74120
74528
|
function sha256Hex(value) {
|
|
74121
|
-
return (0,
|
|
74529
|
+
return (0, import_node_crypto54.createHash)("sha256").update(value).digest("hex");
|
|
74122
74530
|
}
|
|
74123
74531
|
function truncateForStorage(value, maxChars = MAX_SNAPSHOT_CONTENT_CHARS) {
|
|
74124
74532
|
if (value.length <= maxChars) return { value, truncated: false };
|
|
@@ -74175,11 +74583,11 @@ function diffPageContent(oldContent, newContent) {
|
|
|
74175
74583
|
totalChangedLineCount
|
|
74176
74584
|
};
|
|
74177
74585
|
}
|
|
74178
|
-
var
|
|
74586
|
+
var import_node_crypto54, import_diff, MAX_SNAPSHOT_CONTENT_CHARS, MAX_DIFF_HUNKS, MAX_DIFF_LINES_PER_RESPONSE;
|
|
74179
74587
|
var init_page_diff = __esm({
|
|
74180
74588
|
"src/api/page-diff.ts"() {
|
|
74181
74589
|
"use strict";
|
|
74182
|
-
|
|
74590
|
+
import_node_crypto54 = require("crypto");
|
|
74183
74591
|
import_diff = require("diff");
|
|
74184
74592
|
MAX_SNAPSHOT_CONTENT_CHARS = 25e4;
|
|
74185
74593
|
MAX_DIFF_HUNKS = 200;
|
|
@@ -74253,7 +74661,7 @@ var init_scrape_vault_sink = __esm({
|
|
|
74253
74661
|
|
|
74254
74662
|
// src/api/scrape-image-sink.ts
|
|
74255
74663
|
function idempotencyKey2(userId, vault, input) {
|
|
74256
|
-
return `scrape-image-${(0,
|
|
74664
|
+
return `scrape-image-${(0, import_node_crypto55.createHash)("sha256").update(`${userId}\0${vault}\0${input.sourceKind}\0${input.sourceUrl}\0${input.imageUrl ?? ""}\0${input.imageBase64 ?? ""}`).digest("hex")}`;
|
|
74257
74665
|
}
|
|
74258
74666
|
async function persistScrapeImagesToMemory(user, inputs, vault) {
|
|
74259
74667
|
const selected = inputs.slice(0, MAX_IMAGES_PER_SCRAPE);
|
|
@@ -74295,11 +74703,11 @@ async function persistScrapeImagesToMemory(user, inputs, vault) {
|
|
|
74295
74703
|
assets
|
|
74296
74704
|
};
|
|
74297
74705
|
}
|
|
74298
|
-
var
|
|
74706
|
+
var import_node_crypto55, MAX_IMAGES_PER_SCRAPE;
|
|
74299
74707
|
var init_scrape_image_sink = __esm({
|
|
74300
74708
|
"src/api/scrape-image-sink.ts"() {
|
|
74301
74709
|
"use strict";
|
|
74302
|
-
|
|
74710
|
+
import_node_crypto55 = require("crypto");
|
|
74303
74711
|
init_memory();
|
|
74304
74712
|
MAX_IMAGES_PER_SCRAPE = 25;
|
|
74305
74713
|
}
|
|
@@ -74752,7 +75160,7 @@ function canonicalJson(value) {
|
|
|
74752
75160
|
return JSON.stringify(value);
|
|
74753
75161
|
}
|
|
74754
75162
|
function sha2562(value) {
|
|
74755
|
-
return (0,
|
|
75163
|
+
return (0, import_node_crypto56.createHash)("sha256").update(value).digest("hex");
|
|
74756
75164
|
}
|
|
74757
75165
|
function sensitiveKey(key) {
|
|
74758
75166
|
const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
@@ -74967,11 +75375,11 @@ async function importServiceConnectionToMemory(identity, input, dependencies) {
|
|
|
74967
75375
|
...!searchReady ? { warning: "The snapshot was stored, but no search chunks were indexed yet." } : {}
|
|
74968
75376
|
};
|
|
74969
75377
|
}
|
|
74970
|
-
var
|
|
75378
|
+
var import_node_crypto56, CONNECTION_MEMORY_IMPORT_MAX_ARGS_BYTES, CONNECTION_MEMORY_IMPORT_MAX_RESULT_BYTES, CONNECTION_MEMORY_IMPORT_MAX_STRING_CHARS, CONNECTION_MEMORY_IMPORT_MAX_DEPTH, ConnectionMemoryImportError;
|
|
74971
75379
|
var init_connection_memory_import = __esm({
|
|
74972
75380
|
"src/api/connection-memory-import.ts"() {
|
|
74973
75381
|
"use strict";
|
|
74974
|
-
|
|
75382
|
+
import_node_crypto56 = require("crypto");
|
|
74975
75383
|
init_slugify();
|
|
74976
75384
|
CONNECTION_MEMORY_IMPORT_MAX_ARGS_BYTES = 64 * 1024;
|
|
74977
75385
|
CONNECTION_MEMORY_IMPORT_MAX_RESULT_BYTES = 1e6;
|
|
@@ -75016,16 +75424,16 @@ async function cleanupLocal(cutoff) {
|
|
|
75016
75424
|
let deleted = 0;
|
|
75017
75425
|
let entries;
|
|
75018
75426
|
try {
|
|
75019
|
-
entries = await (0,
|
|
75427
|
+
entries = await (0, import_promises16.readdir)(dir);
|
|
75020
75428
|
} catch {
|
|
75021
75429
|
return { deleted: 0, store: "local" };
|
|
75022
75430
|
}
|
|
75023
75431
|
for (const name of entries) {
|
|
75024
75432
|
const path6 = (0, import_node_path23.join)(dir, name);
|
|
75025
75433
|
try {
|
|
75026
|
-
const s = await (0,
|
|
75434
|
+
const s = await (0, import_promises16.stat)(path6);
|
|
75027
75435
|
if (s.isFile() && s.mtimeMs < cutoff) {
|
|
75028
|
-
await (0,
|
|
75436
|
+
await (0, import_promises16.unlink)(path6);
|
|
75029
75437
|
deleted++;
|
|
75030
75438
|
}
|
|
75031
75439
|
} catch {
|
|
@@ -75042,11 +75450,11 @@ async function cleanupExpiredScrapeBlobs(maxAgeMs = SCRAPE_BLOB_TTL_MS) {
|
|
|
75042
75450
|
return { deleted: 0, store: "none" };
|
|
75043
75451
|
}
|
|
75044
75452
|
}
|
|
75045
|
-
var
|
|
75453
|
+
var import_promises16, import_node_os15, import_node_path23;
|
|
75046
75454
|
var init_scrape_blob_cleanup = __esm({
|
|
75047
75455
|
"src/api/scrape-blob-cleanup.ts"() {
|
|
75048
75456
|
"use strict";
|
|
75049
|
-
|
|
75457
|
+
import_promises16 = require("fs/promises");
|
|
75050
75458
|
import_node_os15 = require("os");
|
|
75051
75459
|
import_node_path23 = require("path");
|
|
75052
75460
|
init_scrape_vault_sink();
|
|
@@ -75189,7 +75597,7 @@ function finitePositive(value, fallback) {
|
|
|
75189
75597
|
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
75190
75598
|
}
|
|
75191
75599
|
async function collectConnectedDataExport(args) {
|
|
75192
|
-
const exportId = (0,
|
|
75600
|
+
const exportId = (0, import_node_crypto57.randomUUID)();
|
|
75193
75601
|
const now = args.now ?? Date.now;
|
|
75194
75602
|
const startedAt = now();
|
|
75195
75603
|
const budgetMs = finitePositive(CONNECTED_DATA_EXPORT_BUDGET_MS, 24e4);
|
|
@@ -75303,11 +75711,11 @@ ${lines.length ? `${lines.join("\n")}
|
|
|
75303
75711
|
untrustedContent: true
|
|
75304
75712
|
};
|
|
75305
75713
|
}
|
|
75306
|
-
var
|
|
75714
|
+
var import_node_crypto57, CONNECTED_DATA_INLINE_BUDGET_BYTES, CONNECTED_DATA_MAX_EXPORT_BYTES, CONNECTED_DATA_EXPORT_BUDGET_MS, CONNECTED_DATA_PAGE_START_HEADROOM_MS, CONNECTED_DATA_DATASETS, ConnectedDataExportValidationError;
|
|
75307
75715
|
var init_connected_data_export = __esm({
|
|
75308
75716
|
"src/api/connected-data-export.ts"() {
|
|
75309
75717
|
"use strict";
|
|
75310
|
-
|
|
75718
|
+
import_node_crypto57 = require("crypto");
|
|
75311
75719
|
CONNECTED_DATA_INLINE_BUDGET_BYTES = Number(
|
|
75312
75720
|
process.env.MCP_SCRAPER_CONNECTED_DATA_INLINE_BUDGET_BYTES ?? 5e4
|
|
75313
75721
|
);
|
|
@@ -75421,7 +75829,7 @@ async function exportSearchConsoleTableData(args) {
|
|
|
75421
75829
|
offset += rows.length;
|
|
75422
75830
|
if (stoppedForBytes || rows.length < limit || offset >= matchedRows) break;
|
|
75423
75831
|
}
|
|
75424
|
-
const exportId = (0,
|
|
75832
|
+
const exportId = (0, import_node_crypto58.randomUUID)();
|
|
75425
75833
|
const artifact = await args.writeArtifact({
|
|
75426
75834
|
ownerId: args.ownerId,
|
|
75427
75835
|
exportId,
|
|
@@ -75443,11 +75851,11 @@ async function exportSearchConsoleTableData(args) {
|
|
|
75443
75851
|
warnings
|
|
75444
75852
|
};
|
|
75445
75853
|
}
|
|
75446
|
-
var
|
|
75854
|
+
var import_node_crypto58, SEARCH_CONSOLE_TABLE_EXPORT_MAX_ROWS, SEARCH_CONSOLE_TABLE_EXPORT_PAGE_SIZE, SEARCH_CONSOLE_TABLE_EXPORT_MAX_BYTES, SEARCH_CONSOLE_TABLE_COLUMNS, SearchConsoleTableExportValidationError;
|
|
75447
75855
|
var init_search_console_table_export = __esm({
|
|
75448
75856
|
"src/api/search-console-table-export.ts"() {
|
|
75449
75857
|
"use strict";
|
|
75450
|
-
|
|
75858
|
+
import_node_crypto58 = require("crypto");
|
|
75451
75859
|
SEARCH_CONSOLE_TABLE_EXPORT_MAX_ROWS = 5e4;
|
|
75452
75860
|
SEARCH_CONSOLE_TABLE_EXPORT_PAGE_SIZE = 2e3;
|
|
75453
75861
|
SEARCH_CONSOLE_TABLE_EXPORT_MAX_BYTES = 50 * 1024 * 1024;
|
|
@@ -76626,7 +77034,7 @@ async function listNangoToolsDirect(identity, connectionId) {
|
|
|
76626
77034
|
});
|
|
76627
77035
|
const readTools = [...policies.values()].filter((policy7) => policy7.classification === "read").map((policy7) => policy7.name);
|
|
76628
77036
|
const actionTools = [...policies.values()].filter((policy7) => policy7.classification === "action").map((policy7) => policy7.name);
|
|
76629
|
-
const revision = (0,
|
|
77037
|
+
const revision = (0, import_node_crypto59.createHash)("sha256").update(JSON.stringify(tools.map((tool) => ({ name: tool.name, inputSchema: tool.inputSchema })))).digest("hex");
|
|
76630
77038
|
await updateServiceConnectionTools(connection.id, readTools, actionTools, revision);
|
|
76631
77039
|
const refreshed = await getOwnedServiceConnection(identity, connection.id);
|
|
76632
77040
|
return { connection: refreshed ?? { ...connection, readTools, actionTools, toolRevision: revision }, tools };
|
|
@@ -76653,8 +77061,8 @@ async function callNangoToolDirect(args) {
|
|
|
76653
77061
|
identity: args.identity,
|
|
76654
77062
|
ratePolicyVersion: CONNECTED_USAGE_RATE_POLICY_VERSION
|
|
76655
77063
|
});
|
|
76656
|
-
const requestId = args.requestId?.trim() || (0,
|
|
76657
|
-
const idempotencyKey3 = `main-nango:${(0,
|
|
77064
|
+
const requestId = args.requestId?.trim() || (0, import_node_crypto59.randomUUID)();
|
|
77065
|
+
const idempotencyKey3 = `main-nango:${(0, import_node_crypto59.createHash)("sha256").update(args.identity.toLowerCase()).update("\0").update(connection.id).update("\0").update(args.tool).update("\0").update(requestId).digest("hex")}`;
|
|
76658
77066
|
const startedAt = /* @__PURE__ */ new Date();
|
|
76659
77067
|
const started = performance.now();
|
|
76660
77068
|
let result;
|
|
@@ -76679,7 +77087,7 @@ async function callNangoToolDirect(args) {
|
|
|
76679
77087
|
toolName: args.tool,
|
|
76680
77088
|
operationKind: args.operationKind ?? args.classification,
|
|
76681
77089
|
outcome: providerError ? "error" : "partial",
|
|
76682
|
-
requestId: requestId.length <= 200 ? requestId : (0,
|
|
77090
|
+
requestId: requestId.length <= 200 ? requestId : (0, import_node_crypto59.createHash)("sha256").update(requestId).digest("hex"),
|
|
76683
77091
|
startedAt: startedAt.toISOString(),
|
|
76684
77092
|
completedAt: completedAt.toISOString()
|
|
76685
77093
|
}
|
|
@@ -76721,15 +77129,15 @@ async function describeNangoToolDirect(identity, connectionId, toolName) {
|
|
|
76721
77129
|
providerContractHash: MAIN_INTEGRATION_CONTRACT_HASH,
|
|
76722
77130
|
protocolVersion: null,
|
|
76723
77131
|
schemaSource: "live_tools_list",
|
|
76724
|
-
schemaHash: (0,
|
|
77132
|
+
schemaHash: (0, import_node_crypto59.createHash)("sha256").update(JSON.stringify(projected)).digest("hex"),
|
|
76725
77133
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
76726
77134
|
};
|
|
76727
77135
|
}
|
|
76728
|
-
var
|
|
77136
|
+
var import_node_crypto59, import_client13, DEFAULT_NANGO_MCP_URL, NANGO_TIMEOUT_MS, NANGO_CONNECTION_PAGE_SIZE, NANGO_CONNECTION_MAX_PAGES, MAIN_INTEGRATION_CONTRACT_VERSION, MAIN_INTEGRATION_CONTRACT_HASH, MainNangoTransportError;
|
|
76729
77137
|
var init_main_nango_transport = __esm({
|
|
76730
77138
|
"src/api/main-nango-transport.ts"() {
|
|
76731
77139
|
"use strict";
|
|
76732
|
-
|
|
77140
|
+
import_node_crypto59 = require("crypto");
|
|
76733
77141
|
import_client13 = require("@modelcontextprotocol/client");
|
|
76734
77142
|
init_service_connections();
|
|
76735
77143
|
init_connected_usage_billing();
|
|
@@ -77353,8 +77761,8 @@ async function setScheduleConnectionActionsEnabled(identity, connectionId, enabl
|
|
|
77353
77761
|
return data.connection.actionsEnabled === true;
|
|
77354
77762
|
}
|
|
77355
77763
|
async function callScheduleConnectionAction(identity, connectionId, input, tool, idempotencyKey3) {
|
|
77356
|
-
const requestId = `main-connected-action:${(0,
|
|
77357
|
-
const requestDigest = (0,
|
|
77764
|
+
const requestId = `main-connected-action:${(0, import_node_crypto60.createHash)("sha256").update(identity).update("\0").update(idempotencyKey3?.trim() || (0, import_node_crypto60.randomUUID)()).digest("hex")}`;
|
|
77765
|
+
const requestDigest = (0, import_node_crypto60.createHash)("sha256").update(connectionId).update("\0").update(tool?.trim() ?? "").update("\0").update(canonicalJson2(input)).digest("hex");
|
|
77358
77766
|
if (mainOwnsIntegrations()) {
|
|
77359
77767
|
const selectedTool = tool?.trim();
|
|
77360
77768
|
if (!selectedTool) throw new NangoControlError("An action tool is required.", 400, "invalid_request", false);
|
|
@@ -77505,7 +77913,7 @@ function canonicalJson2(value) {
|
|
|
77505
77913
|
return JSON.stringify(value);
|
|
77506
77914
|
}
|
|
77507
77915
|
function projectedToolSchemaHash(tool) {
|
|
77508
|
-
return (0,
|
|
77916
|
+
return (0, import_node_crypto60.createHash)("sha256").update(canonicalJson2(tool)).digest("hex");
|
|
77509
77917
|
}
|
|
77510
77918
|
async function describeNangoTool(identity, connectionId, tool, fresh) {
|
|
77511
77919
|
if (mainOwnsIntegrations()) {
|
|
@@ -77782,11 +78190,11 @@ async function callMainOwnedExportPage(identity, input) {
|
|
|
77782
78190
|
untrustedContent: true
|
|
77783
78191
|
};
|
|
77784
78192
|
}
|
|
77785
|
-
var
|
|
78193
|
+
var import_node_crypto60, DEFAULT_NANGO_CONTROL_URL, DISABLED_NANGO_TOOLS, CONNECTION_SYNC_REQUIRED_TOOLS, CONNECTION_SYNC_OPTIONAL_TOOLS, NangoControlError, ScheduleConnectionValidationError, SAFE_CONTROL_ERROR_CODES, FIXED_CONTROL_ERROR_MESSAGES, CONTROL_ERROR_CODE_ALIASES;
|
|
77786
78194
|
var init_nango_control = __esm({
|
|
77787
78195
|
"src/api/nango-control.ts"() {
|
|
77788
78196
|
"use strict";
|
|
77789
|
-
|
|
78197
|
+
import_node_crypto60 = require("crypto");
|
|
77790
78198
|
init_connected_data_export();
|
|
77791
78199
|
init_slack_connected_data_export();
|
|
77792
78200
|
init_main_nango_transport();
|
|
@@ -78142,7 +78550,7 @@ async function callResendRead(identity, connectionId, tool, args) {
|
|
|
78142
78550
|
return isRecord5(data) ? data.result ?? data : data;
|
|
78143
78551
|
}
|
|
78144
78552
|
async function callResendAction(identity, connectionId, tool, input, idempotencyKey3) {
|
|
78145
|
-
const requestId = `main-resend-action:${(0,
|
|
78553
|
+
const requestId = `main-resend-action:${(0, import_node_crypto61.createHash)("sha256").update(identity).update("\0").update(idempotencyKey3.trim()).digest("hex")}`;
|
|
78146
78554
|
const body = await controlRequest2("/api/internal/resend/actions/call", {
|
|
78147
78555
|
method: "POST",
|
|
78148
78556
|
headers: { "x-request-id": requestId },
|
|
@@ -78207,12 +78615,12 @@ async function callResendExportPage(identity, input) {
|
|
|
78207
78615
|
untrustedContent: true
|
|
78208
78616
|
};
|
|
78209
78617
|
}
|
|
78210
|
-
var
|
|
78618
|
+
var import_node_crypto61, DEFAULT_CONNECTION_CONTROL_URL, RESEND_PROVIDER_CONFIG_KEY, RESEND_LOGO_URL, RESEND_DOCS_URL, RESEND_ADMIN_BLOCKED_TOOLS, RESEND_CONNECTION_SYNC_REQUIRED_TOOLS, ResendControlError;
|
|
78211
78619
|
var init_resend_control = __esm({
|
|
78212
78620
|
"src/api/resend-control.ts"() {
|
|
78213
78621
|
"use strict";
|
|
78214
78622
|
init_connected_data_export();
|
|
78215
|
-
|
|
78623
|
+
import_node_crypto61 = require("crypto");
|
|
78216
78624
|
DEFAULT_CONNECTION_CONTROL_URL = "https://mcp-scraper-scheduler.vercel.app";
|
|
78217
78625
|
RESEND_PROVIDER_CONFIG_KEY = "resend";
|
|
78218
78626
|
RESEND_LOGO_URL = "https://cdn.resend.com/brand/resend-icon-black.svg";
|
|
@@ -78797,7 +79205,7 @@ function settleWithinTickBudget(label, unfinished, work, onDeadlineOrError) {
|
|
|
78797
79205
|
);
|
|
78798
79206
|
});
|
|
78799
79207
|
}
|
|
78800
|
-
var import_resend3,
|
|
79208
|
+
var import_resend3, import_node_crypto62, import_hono36, import_hono37, import_factory8, import_cookie2, import_stripe2, secureCookies2, isProduction2, sessionCookieOptions2, requireAllowedOrigin, auth4, sessionAuth, requireIntegrationsTier, requirePaidSchedulingTier, app, deploymentProfile, STRIPE_API_VERSION, SYNC_HARVEST_TIMEOUT_OVERRIDE_MS, CRON_TICK_BUDGET_MS, CRON_TICK_DRAIN_BUDGET_MS;
|
|
78801
79209
|
var init_server = __esm({
|
|
78802
79210
|
"src/api/server.ts"() {
|
|
78803
79211
|
"use strict";
|
|
@@ -78810,7 +79218,7 @@ var init_server = __esm({
|
|
|
78810
79218
|
init_og();
|
|
78811
79219
|
import_resend3 = require("resend");
|
|
78812
79220
|
init_url_utils();
|
|
78813
|
-
|
|
79221
|
+
import_node_crypto62 = require("crypto");
|
|
78814
79222
|
init_kpo_extractor();
|
|
78815
79223
|
init_screenshot();
|
|
78816
79224
|
init_media_extractor();
|
|
@@ -80360,7 +80768,7 @@ var init_server = __esm({
|
|
|
80360
80768
|
if (!harvestOk) return c.json(insufficientBalanceResponse(harvestBal, harvestCost), 402);
|
|
80361
80769
|
jobId2 = await createJob(user.id, options.query, { ...options, billingHoldMc: harvestCost }, body.callback_url);
|
|
80362
80770
|
} else {
|
|
80363
|
-
jobId2 = (0,
|
|
80771
|
+
jobId2 = (0, import_node_crypto62.randomUUID)();
|
|
80364
80772
|
const billingDebitKey = `paa-harvest:${jobId2}:hold`;
|
|
80365
80773
|
const description = `PAA harvest: ${options.query}`.slice(0, 500);
|
|
80366
80774
|
const hold = await debitMcIdempotent(
|