mcp-scraper 0.56.0 → 0.57.1
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 +28 -0
- package/README.md +2 -2
- package/dist/bin/api-server.cjs +576 -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-JEZW6N2X.js → chunk-2KL4MSZP.js} +26 -3
- package/dist/chunk-2KL4MSZP.js.map +1 -0
- 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-WO2SSENO.js → chunk-R6CO77BN.js} +3 -3
- package/dist/{chunk-WO2SSENO.js.map → chunk-R6CO77BN.js.map} +1 -1
- package/dist/chunk-VTBJVKBE.js +7 -0
- package/dist/chunk-VTBJVKBE.js.map +1 -0
- package/dist/{extract-bundle-6KYTD55T.js → extract-bundle-H7JEELY7.js} +3 -3
- package/dist/{server-SETYJPYO.js → server-DSCKFM7K.js} +459 -72
- package/dist/server-DSCKFM7K.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.1";
|
|
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,243 @@ 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 commonsImageBlobStore() {
|
|
64403
|
+
const token6 = process.env.COMMONS_IMAGE_READ_WRITE_TOKEN?.trim() || process.env.COMMONS_IMAGE_BLOB_READ_WRITE_TOKEN?.trim() || process.env.BLOB_READ_WRITE_TOKEN?.trim();
|
|
64404
|
+
return token6 ? new VercelBlobStore(token6) : getBlobStore();
|
|
64405
|
+
}
|
|
64406
|
+
function isCommonsHostedImageUrl(url) {
|
|
64407
|
+
return /^https:\/\/[^/]*(\.public\.blob\.vercel-storage\.com|blob\.vercel-storage\.com)\//i.test(url);
|
|
64408
|
+
}
|
|
64409
|
+
async function hostCommonsImage(input) {
|
|
64410
|
+
if (hostOverride) return hostOverride(input);
|
|
64411
|
+
await ensureCommonsImageSchema();
|
|
64412
|
+
if (!input.sourceUrl && !input.imageBase64) {
|
|
64413
|
+
throw new CommonsImageError("image_source_missing", "Provide either sourceUrl or imageBase64.");
|
|
64414
|
+
}
|
|
64415
|
+
const bytes = input.imageBase64 ? decodeBase64Image(input.imageBase64) : await downloadImage(String(input.sourceUrl));
|
|
64416
|
+
const contentType = sniffImageFormat(bytes);
|
|
64417
|
+
if (!contentType) {
|
|
64418
|
+
throw new CommonsImageError(
|
|
64419
|
+
"image_format_unsupported",
|
|
64420
|
+
"Commons hosts JPEG, PNG, GIF, and WebP. SVG and other formats are rejected because the wiki serves them to the public web.",
|
|
64421
|
+
415
|
|
64422
|
+
);
|
|
64423
|
+
}
|
|
64424
|
+
const digest2 = (0, import_node_crypto37.createHash)("sha256").update(bytes).digest("hex");
|
|
64425
|
+
const existing = await getDb().execute({
|
|
64426
|
+
sql: "SELECT id, url, content_type, bytes, source_url FROM commons_images WHERE digest = ? LIMIT 1",
|
|
64427
|
+
args: [digest2]
|
|
64428
|
+
});
|
|
64429
|
+
const reusable = existing.rows[0];
|
|
64430
|
+
if (reusable) {
|
|
64431
|
+
return {
|
|
64432
|
+
id: String(reusable.id),
|
|
64433
|
+
url: String(reusable.url),
|
|
64434
|
+
contentType: String(reusable.content_type),
|
|
64435
|
+
bytes: Number(reusable.bytes),
|
|
64436
|
+
digest: digest2,
|
|
64437
|
+
sourceUrl: reusable.source_url ? String(reusable.source_url) : null,
|
|
64438
|
+
reused: true
|
|
64439
|
+
};
|
|
64440
|
+
}
|
|
64441
|
+
const extension = contentType.split("/")[1] === "jpeg" ? "jpg" : contentType.split("/")[1];
|
|
64442
|
+
const storageKey = `commons/images/${digest2.slice(0, 2)}/${digest2}.${extension}`;
|
|
64443
|
+
const store = commonsImageBlobStore();
|
|
64444
|
+
if (store.kind !== "vercel-blob") {
|
|
64445
|
+
throw new CommonsImageError(
|
|
64446
|
+
"image_storage_unconfigured",
|
|
64447
|
+
"Commons image hosting needs a Vercel Blob token. Refusing to write a local file path into a public wiki entity.",
|
|
64448
|
+
422
|
|
64449
|
+
);
|
|
64450
|
+
}
|
|
64451
|
+
const stored = await store.put(storageKey, bytes, contentType);
|
|
64452
|
+
const id = `TPW-IMG-${digest2.slice(0, 16).toUpperCase()}`;
|
|
64453
|
+
await getDb().execute({
|
|
64454
|
+
sql: `
|
|
64455
|
+
INSERT INTO commons_images (id, user_id, digest, storage_key, url, content_type, bytes, source_url, alt, license, attribution, created_at)
|
|
64456
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
64457
|
+
`,
|
|
64458
|
+
args: [
|
|
64459
|
+
id,
|
|
64460
|
+
input.userId,
|
|
64461
|
+
digest2,
|
|
64462
|
+
storageKey,
|
|
64463
|
+
stored.url,
|
|
64464
|
+
contentType,
|
|
64465
|
+
bytes.length,
|
|
64466
|
+
input.sourceUrl ?? null,
|
|
64467
|
+
input.alt ?? null,
|
|
64468
|
+
input.license ?? null,
|
|
64469
|
+
input.attribution ?? null,
|
|
64470
|
+
(/* @__PURE__ */ new Date()).toISOString()
|
|
64471
|
+
]
|
|
64472
|
+
});
|
|
64473
|
+
return { id, url: stored.url, contentType, bytes: bytes.length, digest: digest2, sourceUrl: input.sourceUrl ?? null, reused: false };
|
|
64474
|
+
}
|
|
64475
|
+
async function hostEntityImages(input) {
|
|
64476
|
+
const rewrite = { mediaUrls: /* @__PURE__ */ new Map(), dropped: [] };
|
|
64477
|
+
const featuredUrl = input.featuredImage?.url;
|
|
64478
|
+
if (featuredUrl && !isCommonsHostedImageUrl(featuredUrl)) {
|
|
64479
|
+
const hosted = await hostCommonsImage({
|
|
64480
|
+
userId: input.userId,
|
|
64481
|
+
sourceUrl: featuredUrl,
|
|
64482
|
+
alt: input.featuredImage?.alt,
|
|
64483
|
+
license: input.featuredImage?.license,
|
|
64484
|
+
attribution: input.featuredImage?.sourceUrl
|
|
64485
|
+
}).catch((error) => {
|
|
64486
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
64487
|
+
throw new CommonsImageError(
|
|
64488
|
+
error instanceof CommonsImageError ? error.code : "featured_image_unhostable",
|
|
64489
|
+
`The featured image could not be hosted, so this entity would publish with a link that can break: ${message}`,
|
|
64490
|
+
422
|
|
64491
|
+
);
|
|
64492
|
+
});
|
|
64493
|
+
rewrite.featuredImageUrl = hosted.url;
|
|
64494
|
+
}
|
|
64495
|
+
for (const item of input.media ?? []) {
|
|
64496
|
+
if (!item.url || isCommonsHostedImageUrl(item.url)) continue;
|
|
64497
|
+
try {
|
|
64498
|
+
const hosted = await hostCommonsImage({
|
|
64499
|
+
userId: input.userId,
|
|
64500
|
+
sourceUrl: item.url,
|
|
64501
|
+
alt: item.alt,
|
|
64502
|
+
license: item.license,
|
|
64503
|
+
attribution: item.sourceUrl
|
|
64504
|
+
});
|
|
64505
|
+
rewrite.mediaUrls.set(item.url, hosted.url);
|
|
64506
|
+
} catch (error) {
|
|
64507
|
+
rewrite.dropped.push({ url: item.url, reason: error instanceof Error ? error.message : String(error) });
|
|
64508
|
+
}
|
|
64509
|
+
}
|
|
64510
|
+
return rewrite;
|
|
64511
|
+
}
|
|
64512
|
+
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;
|
|
64513
|
+
var init_commons_image_store = __esm({
|
|
64514
|
+
"src/api/commons-image-store.ts"() {
|
|
64515
|
+
"use strict";
|
|
64516
|
+
import_node_crypto37 = require("crypto");
|
|
64517
|
+
import_promises15 = require("dns/promises");
|
|
64518
|
+
import_node_net2 = require("net");
|
|
64519
|
+
init_blob_store();
|
|
64520
|
+
init_db();
|
|
64521
|
+
COMMONS_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
64522
|
+
COMMONS_IMAGE_MAX_REDIRECTS = 3;
|
|
64523
|
+
COMMONS_IMAGE_FETCH_TIMEOUT_MS = 2e4;
|
|
64524
|
+
CommonsImageError = class extends Error {
|
|
64525
|
+
constructor(code, message, httpStatus = 400) {
|
|
64526
|
+
super(message);
|
|
64527
|
+
this.code = code;
|
|
64528
|
+
this.httpStatus = httpStatus;
|
|
64529
|
+
this.name = "CommonsImageError";
|
|
64530
|
+
}
|
|
64531
|
+
code;
|
|
64532
|
+
httpStatus;
|
|
64533
|
+
};
|
|
64534
|
+
imageSchemaReady = false;
|
|
64535
|
+
hostOverride = null;
|
|
64536
|
+
}
|
|
64537
|
+
});
|
|
64538
|
+
|
|
64279
64539
|
// src/api/schema-presence.ts
|
|
64280
64540
|
async function loadSchemaObjects() {
|
|
64281
64541
|
const res = await getDb().execute(
|
|
@@ -64378,7 +64638,7 @@ function buildCommonsLinkset(entity, claims) {
|
|
|
64378
64638
|
context[claim.predicate] = targets;
|
|
64379
64639
|
}
|
|
64380
64640
|
const document2 = { linkset: [context] };
|
|
64381
|
-
const etag = `"${(0,
|
|
64641
|
+
const etag = `"${(0, import_node_crypto38.createHash)("sha256").update(JSON.stringify(document2)).digest("hex")}"`;
|
|
64382
64642
|
return { document: document2, etag, publicUrl, linksetUrl, profile: COMMONS_RELATIONSHIP_PROFILE };
|
|
64383
64643
|
}
|
|
64384
64644
|
function commonsLinksetDiscoveryHeader(idOrSlug) {
|
|
@@ -64446,11 +64706,11 @@ function normalizeHreflang(value) {
|
|
|
64446
64706
|
const languages = [...new Set(value.map((item) => optionalText(item, 80)).filter((item) => Boolean(item)))];
|
|
64447
64707
|
return languages.length ? languages : void 0;
|
|
64448
64708
|
}
|
|
64449
|
-
var
|
|
64709
|
+
var import_node_crypto38, COMMONS_LINKSET_MEDIA_TYPE, COMMONS_RELATIONSHIP_PROFILE, REGISTERED_RELATIONS;
|
|
64450
64710
|
var init_commons_linksets = __esm({
|
|
64451
64711
|
"src/api/commons-linksets.ts"() {
|
|
64452
64712
|
"use strict";
|
|
64453
|
-
|
|
64713
|
+
import_node_crypto38 = require("crypto");
|
|
64454
64714
|
COMMONS_LINKSET_MEDIA_TYPE = "application/linkset+json";
|
|
64455
64715
|
COMMONS_RELATIONSHIP_PROFILE = "https://mcpscraper.dev/commons/profiles/relationships/v1";
|
|
64456
64716
|
REGISTERED_RELATIONS = /* @__PURE__ */ new Set([
|
|
@@ -64781,23 +65041,99 @@ async function searchCommonsEntities(filters = {}, userId) {
|
|
|
64781
65041
|
const pattern = `%${escapeLike(term)}%`;
|
|
64782
65042
|
args.push(pattern, pattern, pattern, pattern, pattern);
|
|
64783
65043
|
}
|
|
64784
|
-
|
|
64785
|
-
|
|
65044
|
+
if (!terms.length) {
|
|
65045
|
+
args.push(limit, offset);
|
|
65046
|
+
const result = await getDb().execute({
|
|
65047
|
+
sql: `
|
|
65048
|
+
SELECT *
|
|
65049
|
+
FROM commons_entities
|
|
65050
|
+
WHERE ${clauses.join(" AND ")}
|
|
65051
|
+
ORDER BY updated_at DESC, title ASC
|
|
65052
|
+
LIMIT ? OFFSET ?
|
|
65053
|
+
`,
|
|
65054
|
+
args
|
|
65055
|
+
});
|
|
65056
|
+
const results2 = result.rows.map((row) => rowToEntity(row));
|
|
65057
|
+
await resolveRelatedLinksAgainstPublishedEntities(results2);
|
|
65058
|
+
return { results: results2, filters: mergedFilters, limit, offset };
|
|
65059
|
+
}
|
|
65060
|
+
const candidates = await getDb().execute({
|
|
64786
65061
|
sql: `
|
|
64787
|
-
SELECT
|
|
65062
|
+
SELECT id, title, tags_json, keywords_json, description, search_text, updated_at,
|
|
65063
|
+
(
|
|
65064
|
+
SELECT group_concat(
|
|
65065
|
+
coalesce(commons_claims.title, '') || ' ' ||
|
|
65066
|
+
coalesce(commons_claims.predicate, '') || ' ' ||
|
|
65067
|
+
coalesce(commons_claims.predicate_label, '') || ' ' ||
|
|
65068
|
+
coalesce(commons_claims.object_url, ''), ' ')
|
|
65069
|
+
FROM commons_claims
|
|
65070
|
+
WHERE commons_claims.subject_entity_id = commons_entities.id
|
|
65071
|
+
) AS claim_text
|
|
64788
65072
|
FROM commons_entities
|
|
64789
65073
|
WHERE ${clauses.join(" AND ")}
|
|
64790
65074
|
ORDER BY updated_at DESC, title ASC
|
|
64791
|
-
LIMIT
|
|
65075
|
+
LIMIT ${SEARCH_CANDIDATE_LIMIT}
|
|
64792
65076
|
`,
|
|
64793
65077
|
args
|
|
64794
65078
|
});
|
|
64795
|
-
|
|
64796
|
-
|
|
64797
|
-
|
|
64798
|
-
|
|
64799
|
-
|
|
64800
|
-
|
|
65079
|
+
const ranked = candidates.rows.map((row) => {
|
|
65080
|
+
const record = row;
|
|
65081
|
+
const score = relevanceScore(terms, {
|
|
65082
|
+
title: String(record.title ?? ""),
|
|
65083
|
+
description: String(record.description ?? ""),
|
|
65084
|
+
tags: parseJsonArray(record.tags_json),
|
|
65085
|
+
keywords: parseJsonArray(record.keywords_json),
|
|
65086
|
+
searchText: String(record.search_text ?? ""),
|
|
65087
|
+
claimText: String(record.claim_text ?? "")
|
|
65088
|
+
});
|
|
65089
|
+
return { id: String(record.id), updatedAt: String(record.updated_at ?? ""), title: String(record.title ?? ""), score };
|
|
65090
|
+
}).filter((candidate) => candidate.score > 0).sort((left, right) => right.score - left.score || right.updatedAt.localeCompare(left.updatedAt) || left.title.localeCompare(right.title));
|
|
65091
|
+
const pageIds = ranked.slice(offset, offset + limit).map((candidate) => candidate.id);
|
|
65092
|
+
if (!pageIds.length) return { results: [], filters: mergedFilters, limit, offset };
|
|
65093
|
+
const page = await getDb().execute({
|
|
65094
|
+
sql: `SELECT * FROM commons_entities WHERE id IN (${pageIds.map(() => "?").join(", ")})`,
|
|
65095
|
+
args: pageIds
|
|
65096
|
+
});
|
|
65097
|
+
const byId = new Map(page.rows.map((row) => {
|
|
65098
|
+
const entity = rowToEntity(row);
|
|
65099
|
+
return [entity.id, entity];
|
|
65100
|
+
}));
|
|
65101
|
+
const results = pageIds.map((id) => byId.get(id)).filter((entity) => Boolean(entity));
|
|
65102
|
+
await resolveRelatedLinksAgainstPublishedEntities(results);
|
|
65103
|
+
return { results, filters: mergedFilters, limit, offset };
|
|
65104
|
+
}
|
|
65105
|
+
function parseJsonArray(value) {
|
|
65106
|
+
try {
|
|
65107
|
+
const parsed = JSON.parse(String(value ?? "[]"));
|
|
65108
|
+
return Array.isArray(parsed) ? parsed.map((item) => String(item)) : [];
|
|
65109
|
+
} catch {
|
|
65110
|
+
return [];
|
|
65111
|
+
}
|
|
65112
|
+
}
|
|
65113
|
+
function containsWord(haystack, term) {
|
|
65114
|
+
if (!haystack || !term) return false;
|
|
65115
|
+
const pattern = new RegExp(`(^|[^a-z0-9])${term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}([^a-z0-9]|$)`, "i");
|
|
65116
|
+
return pattern.test(haystack);
|
|
65117
|
+
}
|
|
65118
|
+
function relevanceScore(terms, fields) {
|
|
65119
|
+
let score = 0;
|
|
65120
|
+
const tagText = fields.tags.join(" ");
|
|
65121
|
+
const keywordText = fields.keywords.join(" ");
|
|
65122
|
+
for (const term of terms) {
|
|
65123
|
+
const inTitle = containsWord(fields.title, term);
|
|
65124
|
+
const inTags = containsWord(tagText, term) || containsWord(keywordText, term);
|
|
65125
|
+
const inDescription = containsWord(fields.description, term);
|
|
65126
|
+
const inBody = containsWord(fields.searchText, term);
|
|
65127
|
+
const inClaims = containsWord(fields.claimText, term);
|
|
65128
|
+
if (!inTitle && !inTags && !inDescription && !inBody && !inClaims) return 0;
|
|
65129
|
+
if (inTitle) score += 100;
|
|
65130
|
+
if (inTags) score += 40;
|
|
65131
|
+
if (inDescription) score += 20;
|
|
65132
|
+
if (inClaims) score += 10;
|
|
65133
|
+
if (inBody) score += 5;
|
|
65134
|
+
}
|
|
65135
|
+
if (terms.every((term) => containsWord(fields.title, term))) score += 50;
|
|
65136
|
+
return score;
|
|
64801
65137
|
}
|
|
64802
65138
|
async function prepareCommonsEntity(input, user) {
|
|
64803
65139
|
await ensureCommonsSchema();
|
|
@@ -64944,7 +65280,10 @@ async function getCommonsEntity(idOrSlug) {
|
|
|
64944
65280
|
`,
|
|
64945
65281
|
args: [lookup2, normalizeSlug(lookup2)]
|
|
64946
65282
|
});
|
|
64947
|
-
|
|
65283
|
+
if (!result.rows[0]) return null;
|
|
65284
|
+
const entity = rowToEntity(result.rows[0]);
|
|
65285
|
+
await resolveRelatedLinksAgainstPublishedEntities([entity]);
|
|
65286
|
+
return entity;
|
|
64948
65287
|
}
|
|
64949
65288
|
async function classifyCommonsWrite(input, user) {
|
|
64950
65289
|
await ensureCommonsSchema();
|
|
@@ -64967,14 +65306,30 @@ async function submitCommonsEntity(input, user) {
|
|
|
64967
65306
|
applied: existingProposal.status === "accepted",
|
|
64968
65307
|
reviewReason: existingProposal.reviewReason,
|
|
64969
65308
|
conflictNote: null,
|
|
65309
|
+
droppedImages: [],
|
|
64970
65310
|
publicUrl: entity2?.status === "published" ? publicUrlForSlug(entity2.slug) : null
|
|
64971
65311
|
};
|
|
64972
65312
|
}
|
|
65313
|
+
const hostedImages = await hostEntityImages({
|
|
65314
|
+
userId: Number(user.id),
|
|
65315
|
+
featuredImage: normalized.featuredImage,
|
|
65316
|
+
media: normalized.media
|
|
65317
|
+
});
|
|
65318
|
+
if (hostedImages.featuredImageUrl && normalized.featuredImage) {
|
|
65319
|
+
normalized.featuredImage = { ...normalized.featuredImage, url: hostedImages.featuredImageUrl };
|
|
65320
|
+
}
|
|
65321
|
+
if (hostedImages.mediaUrls.size || hostedImages.dropped.length) {
|
|
65322
|
+
const droppedUrls = new Set(hostedImages.dropped.map((item) => item.url));
|
|
65323
|
+
normalized.media = normalized.media.filter((item) => !droppedUrls.has(item.url)).map((item) => {
|
|
65324
|
+
const hostedUrl = hostedImages.mediaUrls.get(item.url);
|
|
65325
|
+
return hostedUrl ? { ...item, url: hostedUrl } : item;
|
|
65326
|
+
});
|
|
65327
|
+
}
|
|
64973
65328
|
const existing = await findEntityBySlugOrIdAnyStatus(normalized.slug, normalized.entityId);
|
|
64974
65329
|
const existingClaims = existing && normalized.claims !== void 0 ? await getCommonsClaimsByEntityId(existing.id) : [];
|
|
64975
65330
|
const safety = evaluatePublishSafety(normalized, existing);
|
|
64976
65331
|
const shouldApply = safety.safe && normalized.reviewPolicy !== "always_review";
|
|
64977
|
-
const proposalId = `commons-proposal-${(0,
|
|
65332
|
+
const proposalId = `commons-proposal-${(0, import_node_crypto39.randomUUID)()}`;
|
|
64978
65333
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
64979
65334
|
const entityId = existing?.id ?? normalized.entityId ?? allocateEntityId();
|
|
64980
65335
|
const proposalStatus = shouldApply ? "accepted" : "pending_review";
|
|
@@ -65029,7 +65384,7 @@ async function submitCommonsEntity(input, user) {
|
|
|
65029
65384
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
65030
65385
|
`,
|
|
65031
65386
|
args: [
|
|
65032
|
-
`commons-ledger-${(0,
|
|
65387
|
+
`commons-ledger-${(0, import_node_crypto39.randomUUID)()}`,
|
|
65033
65388
|
nextEntity.id,
|
|
65034
65389
|
proposalId,
|
|
65035
65390
|
user.id,
|
|
@@ -65064,6 +65419,7 @@ async function submitCommonsEntity(input, user) {
|
|
|
65064
65419
|
applied: shouldApply,
|
|
65065
65420
|
reviewReason: safety.reason,
|
|
65066
65421
|
conflictNote: safety.conflictNote,
|
|
65422
|
+
droppedImages: hostedImages.dropped,
|
|
65067
65423
|
publicUrl: entity?.status === "published" && shouldApply ? publicUrlForSlug(entity.slug) : null
|
|
65068
65424
|
};
|
|
65069
65425
|
}
|
|
@@ -65134,7 +65490,7 @@ async function saveCommonsFilter(input, user) {
|
|
|
65134
65490
|
sql: "SELECT id FROM commons_saved_filters WHERE user_id = ? AND name = ? LIMIT 1",
|
|
65135
65491
|
args: [user.id, name]
|
|
65136
65492
|
});
|
|
65137
|
-
const id = existing.rows[0]?.id != null ? String(existing.rows[0].id) : `commons-filter-${(0,
|
|
65493
|
+
const id = existing.rows[0]?.id != null ? String(existing.rows[0].id) : `commons-filter-${(0, import_node_crypto39.randomUUID)()}`;
|
|
65138
65494
|
await getDb().execute({
|
|
65139
65495
|
sql: `
|
|
65140
65496
|
INSERT INTO commons_saved_filters (id, user_id, name, description, filter_json, created_at, updated_at)
|
|
@@ -65202,8 +65558,9 @@ async function listCommonsNeedsLinks(filters = {}) {
|
|
|
65202
65558
|
});
|
|
65203
65559
|
const concepts = /* @__PURE__ */ new Map();
|
|
65204
65560
|
const queryTerms = tokenize(cleanFilters.query);
|
|
65205
|
-
|
|
65206
|
-
|
|
65561
|
+
const scanned = result.rows.map((row) => rowToEntity(row));
|
|
65562
|
+
await resolveRelatedLinksAgainstPublishedEntities(scanned);
|
|
65563
|
+
for (const entity of scanned) {
|
|
65207
65564
|
for (const link2 of entity.articleSections.relatedLinks) {
|
|
65208
65565
|
if (!relatedLinkNeedsPage(link2)) continue;
|
|
65209
65566
|
const haystack = [link2.title, link2.summary, link2.relationship, entity.title, entity.description, entity.tags.join(" ")].filter(Boolean).join(" ").toLowerCase();
|
|
@@ -65911,7 +66268,7 @@ function commonsIndexDocuments(entity, now) {
|
|
|
65911
66268
|
return documents;
|
|
65912
66269
|
}
|
|
65913
66270
|
function commonsIndexDocumentId(entityId, documentType, documentKey) {
|
|
65914
|
-
return `commons-index-${(0,
|
|
66271
|
+
return `commons-index-${(0, import_node_crypto39.createHash)("sha256").update(`${entityId}
|
|
65915
66272
|
${documentType}
|
|
65916
66273
|
${documentKey}`).digest("hex").slice(0, 32)}`;
|
|
65917
66274
|
}
|
|
@@ -66246,6 +66603,44 @@ function sanitizeNeedsLinkFilters(filters) {
|
|
|
66246
66603
|
offset: clampNumber(filters.offset, 0, 1e4, 0)
|
|
66247
66604
|
};
|
|
66248
66605
|
}
|
|
66606
|
+
async function publishedEntityIndexFor(titles) {
|
|
66607
|
+
const index = /* @__PURE__ */ new Map();
|
|
66608
|
+
const slugKeys = uniqueStrings(titles.map((title) => normalizeNeedsLinkTitle(title))).filter(Boolean);
|
|
66609
|
+
const titleKeys = uniqueStrings(titles.map((title) => String(title || "").trim().toLowerCase())).filter(Boolean);
|
|
66610
|
+
if (!slugKeys.length && !titleKeys.length) return index;
|
|
66611
|
+
const result = await getDb().execute({
|
|
66612
|
+
sql: `
|
|
66613
|
+
SELECT id, slug, title
|
|
66614
|
+
FROM commons_entities
|
|
66615
|
+
WHERE status = 'published'
|
|
66616
|
+
AND (slug IN (${slugKeys.map(() => "?").join(", ") || "NULL"})
|
|
66617
|
+
OR lower(title) IN (${titleKeys.map(() => "?").join(", ") || "NULL"}))
|
|
66618
|
+
`,
|
|
66619
|
+
args: [...slugKeys, ...titleKeys]
|
|
66620
|
+
});
|
|
66621
|
+
for (const row of result.rows) {
|
|
66622
|
+
const record = row;
|
|
66623
|
+
const entry = { id: String(record.id), slug: String(record.slug), title: String(record.title) };
|
|
66624
|
+
index.set(entry.slug, entry);
|
|
66625
|
+
index.set(normalizeNeedsLinkTitle(entry.title), entry);
|
|
66626
|
+
}
|
|
66627
|
+
return index;
|
|
66628
|
+
}
|
|
66629
|
+
function unresolvedRelatedLinkTitles(entities) {
|
|
66630
|
+
return entities.flatMap((entity) => entity.articleSections.relatedLinks.filter((link2) => relatedLinkNeedsPage(link2)).map((link2) => link2.title));
|
|
66631
|
+
}
|
|
66632
|
+
async function resolveRelatedLinksAgainstPublishedEntities(entities) {
|
|
66633
|
+
const index = await publishedEntityIndexFor(unresolvedRelatedLinkTitles(entities));
|
|
66634
|
+
if (!index.size) return;
|
|
66635
|
+
for (const entity of entities) {
|
|
66636
|
+
entity.articleSections.relatedLinks = entity.articleSections.relatedLinks.map((link2) => {
|
|
66637
|
+
if (!relatedLinkNeedsPage(link2)) return link2;
|
|
66638
|
+
const match = index.get(normalizeNeedsLinkTitle(link2.title));
|
|
66639
|
+
if (!match || match.id === entity.id) return link2;
|
|
66640
|
+
return { ...link2, slug: match.slug, entityId: match.id, needsLink: false };
|
|
66641
|
+
});
|
|
66642
|
+
}
|
|
66643
|
+
}
|
|
66249
66644
|
function relatedLinkNeedsPage(link2) {
|
|
66250
66645
|
if (link2.needsLink === true) return true;
|
|
66251
66646
|
if (link2.entityId || link2.slug) return false;
|
|
@@ -66438,12 +66833,13 @@ function jsonLikeValue(value) {
|
|
|
66438
66833
|
function escapeLike(value) {
|
|
66439
66834
|
return value.replace(/[%_]/g, "");
|
|
66440
66835
|
}
|
|
66441
|
-
var
|
|
66836
|
+
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
66837
|
var init_commons_repository = __esm({
|
|
66443
66838
|
"src/api/commons-repository.ts"() {
|
|
66444
66839
|
"use strict";
|
|
66445
|
-
|
|
66840
|
+
import_node_crypto39 = require("crypto");
|
|
66446
66841
|
init_db();
|
|
66842
|
+
init_commons_image_store();
|
|
66447
66843
|
init_schema_presence();
|
|
66448
66844
|
init_rates();
|
|
66449
66845
|
init_commons_linksets();
|
|
@@ -66621,6 +67017,7 @@ var init_commons_repository = __esm({
|
|
|
66621
67017
|
"commons_publications_updated",
|
|
66622
67018
|
"commons_publication_editions_publication_published"
|
|
66623
67019
|
];
|
|
67020
|
+
SEARCH_CANDIDATE_LIMIT = 500;
|
|
66624
67021
|
CommonsRepositoryError = class extends Error {
|
|
66625
67022
|
constructor(code, message, httpStatus = 400) {
|
|
66626
67023
|
super(message);
|
|
@@ -66723,7 +67120,7 @@ async function claimCommonsPublication(input, user) {
|
|
|
66723
67120
|
}
|
|
66724
67121
|
const existingName = await getCommonsPublicationBySubdomain(subdomain);
|
|
66725
67122
|
if (existingName) throw new CommonsPublicationError("publication_name_unavailable", "That publication name is already claimed.", 409);
|
|
66726
|
-
const id = `tcpub_${(0,
|
|
67123
|
+
const id = `tcpub_${(0, import_node_crypto40.randomUUID)()}`;
|
|
66727
67124
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
66728
67125
|
try {
|
|
66729
67126
|
await getDb().execute({
|
|
@@ -66775,7 +67172,7 @@ async function publishCommonsEditorial(input, user) {
|
|
|
66775
67172
|
const canonicalUrl = editionPublicUrl(subdomain, editionSlug);
|
|
66776
67173
|
const rendered = renderEditorialReadingRoom(editionInput);
|
|
66777
67174
|
const html = addPublicMetadata(rendered.html, canonicalUrl, publication.title);
|
|
66778
|
-
const editionId = `tced_${(0,
|
|
67175
|
+
const editionId = `tced_${(0, import_node_crypto40.randomUUID)()}`;
|
|
66779
67176
|
const revision = (latest?.revision ?? 0) + 1;
|
|
66780
67177
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
66781
67178
|
await getDb().batch([
|
|
@@ -66799,7 +67196,7 @@ async function publishCommonsEditorial(input, user) {
|
|
|
66799
67196
|
JSON.stringify(editionInput.articles),
|
|
66800
67197
|
html,
|
|
66801
67198
|
rendered.filename,
|
|
66802
|
-
(0,
|
|
67199
|
+
(0, import_node_crypto40.createHash)("sha256").update(html).digest("hex"),
|
|
66803
67200
|
rendered.articleCount,
|
|
66804
67201
|
rendered.wordCount,
|
|
66805
67202
|
Buffer.byteLength(html),
|
|
@@ -66985,11 +67382,11 @@ function addPublicMetadata(html, canonicalUrl, publicationTitle) {
|
|
|
66985
67382
|
"</head>"
|
|
66986
67383
|
].join("\n"));
|
|
66987
67384
|
}
|
|
66988
|
-
var
|
|
67385
|
+
var import_node_crypto40, PUBLICATION_ROOT_DOMAIN, RESERVED_SUBDOMAINS, CommonsPublicationError;
|
|
66989
67386
|
var init_commons_publication_repository = __esm({
|
|
66990
67387
|
"src/api/commons-publication-repository.ts"() {
|
|
66991
67388
|
"use strict";
|
|
66992
|
-
|
|
67389
|
+
import_node_crypto40 = require("crypto");
|
|
66993
67390
|
init_db();
|
|
66994
67391
|
init_commons_repository();
|
|
66995
67392
|
init_render();
|
|
@@ -67090,7 +67487,7 @@ function publicationError(c, error) {
|
|
|
67090
67487
|
function xmlEscape(value) {
|
|
67091
67488
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
67092
67489
|
}
|
|
67093
|
-
var import_hono31, import_zod52, commonsApp, auth2, SearchBodySchema, FeaturedImageSchema, MediaSchema, CitationSchema, RelatedLinkSchema, SubmitEntitySchema, PrepareEntitySchema, ValidateEntitySchema, SaveFilterSchema, NeedsLinkBodySchema, PreparePublicationSchema, ValidatePublicationSchema, ClaimPublicationSchema, PublishEditorialSchema;
|
|
67490
|
+
var import_hono31, import_zod52, commonsApp, auth2, SearchBodySchema, FeaturedImageSchema, MediaSchema, CitationSchema, RelatedLinkSchema, SubmitEntitySchema, PrepareEntitySchema, ValidateEntitySchema, SaveFilterSchema, NeedsLinkBodySchema, PreparePublicationSchema, ValidatePublicationSchema, ClaimPublicationSchema, PublishEditorialSchema, HostImageSchema;
|
|
67094
67491
|
var init_commons_routes = __esm({
|
|
67095
67492
|
"src/api/commons-routes.ts"() {
|
|
67096
67493
|
"use strict";
|
|
@@ -67098,6 +67495,7 @@ var init_commons_routes = __esm({
|
|
|
67098
67495
|
import_zod52 = require("zod");
|
|
67099
67496
|
init_api_auth();
|
|
67100
67497
|
init_commons_repository();
|
|
67498
|
+
init_commons_image_store();
|
|
67101
67499
|
init_commons_linksets();
|
|
67102
67500
|
init_listing_write_billing();
|
|
67103
67501
|
init_commons_publication_repository();
|
|
@@ -67351,6 +67749,28 @@ var init_commons_routes = __esm({
|
|
|
67351
67749
|
return publicationError(c, error);
|
|
67352
67750
|
}
|
|
67353
67751
|
});
|
|
67752
|
+
HostImageSchema = import_zod52.z.object({
|
|
67753
|
+
sourceUrl: import_zod52.z.string().url().optional(),
|
|
67754
|
+
imageBase64: import_zod52.z.string().min(16).optional(),
|
|
67755
|
+
alt: import_zod52.z.string().max(500).optional(),
|
|
67756
|
+
license: import_zod52.z.string().max(240).optional(),
|
|
67757
|
+
attribution: import_zod52.z.string().max(500).optional()
|
|
67758
|
+
}).strict().refine((body) => Boolean(body.sourceUrl || body.imageBase64), {
|
|
67759
|
+
message: "Provide either sourceUrl or imageBase64."
|
|
67760
|
+
});
|
|
67761
|
+
commonsApp.post("/images", auth2, async (c) => {
|
|
67762
|
+
const parsed = HostImageSchema.safeParse(await c.req.json().catch(() => ({})));
|
|
67763
|
+
if (!parsed.success) return validationError(c, parsed.error);
|
|
67764
|
+
try {
|
|
67765
|
+
const hosted = await hostCommonsImage({ ...parsed.data, userId: Number(c.get("user").id) });
|
|
67766
|
+
return c.json({ ok: true, data: hosted }, hosted.reused ? 200 : 201);
|
|
67767
|
+
} catch (error) {
|
|
67768
|
+
if (error instanceof CommonsImageError) {
|
|
67769
|
+
return c.json({ ok: false, error: error.code, message: error.message }, error.httpStatus);
|
|
67770
|
+
}
|
|
67771
|
+
throw error;
|
|
67772
|
+
}
|
|
67773
|
+
});
|
|
67354
67774
|
commonsApp.get("/entities", async (c) => {
|
|
67355
67775
|
const result = await searchCommonsEntities(filtersFromQuery(c.req.query()));
|
|
67356
67776
|
return c.json({ ok: true, data: result });
|
|
@@ -68152,7 +68572,7 @@ async function migrateAnalytics() {
|
|
|
68152
68572
|
}
|
|
68153
68573
|
function normalizeSlug2(value) {
|
|
68154
68574
|
const slug4 = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
68155
|
-
return slug4 || `site-${(0,
|
|
68575
|
+
return slug4 || `site-${(0, import_node_crypto41.randomBytes)(4).toString("hex")}`;
|
|
68156
68576
|
}
|
|
68157
68577
|
function normalizeObservedHostname(origin) {
|
|
68158
68578
|
if (!origin || origin === "null") return null;
|
|
@@ -68165,7 +68585,7 @@ function normalizeObservedHostname(origin) {
|
|
|
68165
68585
|
}
|
|
68166
68586
|
}
|
|
68167
68587
|
function publicPixelId() {
|
|
68168
|
-
return `px_${(0,
|
|
68588
|
+
return `px_${(0, import_node_crypto41.randomBytes)(18).toString("base64url")}`;
|
|
68169
68589
|
}
|
|
68170
68590
|
function mapRows(rows) {
|
|
68171
68591
|
return rows;
|
|
@@ -68197,7 +68617,7 @@ async function requireEditor(client2, siteId, userId) {
|
|
|
68197
68617
|
async function createAnalyticsSite(input) {
|
|
68198
68618
|
const db = getAnalyticsPool();
|
|
68199
68619
|
const client2 = await db.connect();
|
|
68200
|
-
const id = (0,
|
|
68620
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
68201
68621
|
const baseSlug = normalizeSlug2(input.slug || input.name);
|
|
68202
68622
|
try {
|
|
68203
68623
|
await client2.query("BEGIN");
|
|
@@ -68213,7 +68633,7 @@ async function createAnalyticsSite(input) {
|
|
|
68213
68633
|
} catch (error) {
|
|
68214
68634
|
const code = error.code;
|
|
68215
68635
|
if (code !== "23505" || attempt === 2) throw error;
|
|
68216
|
-
slug4 = `${baseSlug}-${(0,
|
|
68636
|
+
slug4 = `${baseSlug}-${(0, import_node_crypto41.randomBytes)(2).toString("hex")}`;
|
|
68217
68637
|
}
|
|
68218
68638
|
}
|
|
68219
68639
|
await client2.query(
|
|
@@ -68428,7 +68848,7 @@ async function createAnalyticsPixel(input) {
|
|
|
68428
68848
|
VALUES ($1, $2, $3, $4, $5)
|
|
68429
68849
|
RETURNING id, site_id, public_id, name, environment, status, created_at::text, NULL::text AS last_event_at`,
|
|
68430
68850
|
[
|
|
68431
|
-
(0,
|
|
68851
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68432
68852
|
input.siteId,
|
|
68433
68853
|
publicPixelId(),
|
|
68434
68854
|
input.name.trim(),
|
|
@@ -68505,7 +68925,7 @@ async function setAnalyticsPixelDomainState(input) {
|
|
|
68505
68925
|
SELECT $1, p.id, $4, $5 FROM analytics_pixels p WHERE p.id = $2 AND p.site_id = $3
|
|
68506
68926
|
ON CONFLICT(pixel_id, hostname) DO UPDATE SET state = EXCLUDED.state, updated_at = now()
|
|
68507
68927
|
RETURNING id`,
|
|
68508
|
-
[(0,
|
|
68928
|
+
[(0, import_node_crypto41.randomUUID)(), input.pixelId, input.siteId, hostname, input.state]
|
|
68509
68929
|
);
|
|
68510
68930
|
if (!result.rowCount)
|
|
68511
68931
|
throw new AnalyticsRepositoryError(
|
|
@@ -68555,7 +68975,7 @@ function sanitizeAnalyticsProperties(value) {
|
|
|
68555
68975
|
}
|
|
68556
68976
|
async function ingestAnalyticsEvents(input) {
|
|
68557
68977
|
const db = getAnalyticsPool();
|
|
68558
|
-
const requestId = `air_${(0,
|
|
68978
|
+
const requestId = `air_${(0, import_node_crypto41.randomUUID)()}`;
|
|
68559
68979
|
const hostname = normalizeObservedHostname(input.origin);
|
|
68560
68980
|
const pixelResult = await db.query(
|
|
68561
68981
|
`SELECT p.id, p.site_id, p.status,
|
|
@@ -68576,7 +68996,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68576
68996
|
`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, hostname, rejected_count, reason_codes)
|
|
68577
68997
|
VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)`,
|
|
68578
68998
|
[
|
|
68579
|
-
(0,
|
|
68999
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68580
69000
|
requestId,
|
|
68581
69001
|
pixel?.site_id ?? null,
|
|
68582
69002
|
pixel?.id ?? null,
|
|
@@ -68601,7 +69021,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68601
69021
|
`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, hostname, rejected_count, reason_codes)
|
|
68602
69022
|
VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)`,
|
|
68603
69023
|
[
|
|
68604
|
-
(0,
|
|
69024
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68605
69025
|
requestId,
|
|
68606
69026
|
pixel.site_id,
|
|
68607
69027
|
pixel.id,
|
|
@@ -68626,7 +69046,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68626
69046
|
`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, rejected_count, reason_codes)
|
|
68627
69047
|
VALUES ($1, $2, $3, $4, $5, $6::jsonb)`,
|
|
68628
69048
|
[
|
|
68629
|
-
(0,
|
|
69049
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68630
69050
|
requestId,
|
|
68631
69051
|
pixel.site_id,
|
|
68632
69052
|
pixel.id,
|
|
@@ -68650,7 +69070,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68650
69070
|
ON CONFLICT(pixel_id, hostname) DO UPDATE
|
|
68651
69071
|
SET last_seen_at = now(), updated_at = now()
|
|
68652
69072
|
RETURNING state`,
|
|
68653
|
-
[(0,
|
|
69073
|
+
[(0, import_node_crypto41.randomUUID)(), pixel.id, hostname]
|
|
68654
69074
|
);
|
|
68655
69075
|
if (domainResult.rows[0]?.state !== "approved") {
|
|
68656
69076
|
await db.query(
|
|
@@ -68664,7 +69084,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68664
69084
|
`INSERT INTO analytics_ingestion_receipts(id, request_id, site_id, pixel_id, hostname, rejected_count, reason_codes)
|
|
68665
69085
|
VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb)`,
|
|
68666
69086
|
[
|
|
68667
|
-
(0,
|
|
69087
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68668
69088
|
requestId,
|
|
68669
69089
|
pixel.site_id,
|
|
68670
69090
|
pixel.id,
|
|
@@ -68714,7 +69134,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68714
69134
|
$23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33
|
|
68715
69135
|
) ON CONFLICT(site_id, event_id) DO NOTHING`,
|
|
68716
69136
|
[
|
|
68717
|
-
(0,
|
|
69137
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68718
69138
|
event2.eventId,
|
|
68719
69139
|
pixel.site_id,
|
|
68720
69140
|
pixel.id,
|
|
@@ -68772,7 +69192,7 @@ async function ingestAnalyticsEvents(input) {
|
|
|
68772
69192
|
id, request_id, site_id, pixel_id, hostname, accepted_count, rejected_count, reason_codes
|
|
68773
69193
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb)`,
|
|
68774
69194
|
[
|
|
68775
|
-
(0,
|
|
69195
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
68776
69196
|
requestId,
|
|
68777
69197
|
pixel.site_id,
|
|
68778
69198
|
pixel.id,
|
|
@@ -68804,7 +69224,7 @@ function normalizeGeographyCode(value, max) {
|
|
|
68804
69224
|
return normalized && /^[A-Z0-9-]+$/.test(normalized) ? normalized.slice(0, max) : null;
|
|
68805
69225
|
}
|
|
68806
69226
|
function pageFingerprint(scope, siteId, filters) {
|
|
68807
|
-
return (0,
|
|
69227
|
+
return (0, import_node_crypto41.createHash)("sha256").update(JSON.stringify({ scope, siteId, filters })).digest("base64url").slice(0, 18);
|
|
68808
69228
|
}
|
|
68809
69229
|
function decodePageOffset(cursor, fingerprint) {
|
|
68810
69230
|
if (!cursor) return 0;
|
|
@@ -68854,7 +69274,7 @@ async function createAnalyticsConversion(input) {
|
|
|
68854
69274
|
404
|
|
68855
69275
|
);
|
|
68856
69276
|
}
|
|
68857
|
-
const id = (0,
|
|
69277
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
68858
69278
|
const resolvedPerson = input.sessionId ? await db.query(
|
|
68859
69279
|
`SELECT e.person_id FROM analytics_identity_nodes n JOIN analytics_identity_edges e ON e.identity_node_id = n.id
|
|
68860
69280
|
WHERE n.site_id = $1 AND n.kind = 'session_id' AND n.value_hmac = $2 ORDER BY e.confidence DESC LIMIT 1`,
|
|
@@ -69603,7 +70023,7 @@ async function createAnalyticsCampaignLink(input) {
|
|
|
69603
70023
|
404
|
|
69604
70024
|
);
|
|
69605
70025
|
}
|
|
69606
|
-
const shortCode = (input.shortCode?.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-") || (0,
|
|
70026
|
+
const shortCode = (input.shortCode?.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-") || (0, import_node_crypto41.randomBytes)(5).toString("base64url").toLowerCase()).slice(0, 48);
|
|
69607
70027
|
try {
|
|
69608
70028
|
const result = await db.query(
|
|
69609
70029
|
`INSERT INTO analytics_campaign_links(
|
|
@@ -69612,7 +70032,7 @@ async function createAnalyticsCampaignLink(input) {
|
|
|
69612
70032
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15)
|
|
69613
70033
|
RETURNING *, 0::int AS click_count`,
|
|
69614
70034
|
[
|
|
69615
|
-
(0,
|
|
70035
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
69616
70036
|
input.siteId,
|
|
69617
70037
|
input.pixelId ?? null,
|
|
69618
70038
|
input.name.trim(),
|
|
@@ -69683,7 +70103,7 @@ async function resolveAnalyticsCampaignLink(shortCode, referrer) {
|
|
|
69683
70103
|
if (!row) return null;
|
|
69684
70104
|
await db.query(
|
|
69685
70105
|
`INSERT INTO analytics_campaign_clicks(id, link_id, referrer) VALUES ($1, $2, $3)`,
|
|
69686
|
-
[(0,
|
|
70106
|
+
[(0, import_node_crypto41.randomUUID)(), row.id, normalizeAnalyticsUrl(referrer || void 0)]
|
|
69687
70107
|
);
|
|
69688
70108
|
return buildTaggedCampaignUrl(row);
|
|
69689
70109
|
}
|
|
@@ -69701,14 +70121,14 @@ async function createAnalyticsForm(input) {
|
|
|
69701
70121
|
404
|
|
69702
70122
|
);
|
|
69703
70123
|
const baseSlug = normalizeSlug2(input.name);
|
|
69704
|
-
const slug4 = `${baseSlug}-${(0,
|
|
69705
|
-
const publicId = `form_${(0,
|
|
70124
|
+
const slug4 = `${baseSlug}-${(0, import_node_crypto41.randomBytes)(3).toString("hex")}`;
|
|
70125
|
+
const publicId = `form_${(0, import_node_crypto41.randomBytes)(18).toString("base64url")}`;
|
|
69706
70126
|
const result = await db.query(
|
|
69707
70127
|
`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
70128
|
VALUES ($1,$2,$3,$4,$5,$6,$7::jsonb,$8::jsonb,$9,$10,$11,$12,$13,$14)
|
|
69709
70129
|
RETURNING *, 0::int AS submission_count`,
|
|
69710
70130
|
[
|
|
69711
|
-
(0,
|
|
70131
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
69712
70132
|
publicId,
|
|
69713
70133
|
input.siteId,
|
|
69714
70134
|
input.pixelId,
|
|
@@ -69753,7 +70173,7 @@ async function getPublicAnalyticsForm(publicId) {
|
|
|
69753
70173
|
return result.rows[0] ?? null;
|
|
69754
70174
|
}
|
|
69755
70175
|
async function recordAnalyticsFormSubmission(input) {
|
|
69756
|
-
const id = (0,
|
|
70176
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
69757
70177
|
await getAnalyticsPool().query(
|
|
69758
70178
|
`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
70179
|
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12::jsonb)`,
|
|
@@ -69784,7 +70204,7 @@ function sanitizeClickIds(value) {
|
|
|
69784
70204
|
return output;
|
|
69785
70205
|
}
|
|
69786
70206
|
function identityHmac(kind, value) {
|
|
69787
|
-
return (0,
|
|
70207
|
+
return (0, import_node_crypto41.createHmac)("sha256", getSessionSecret()).update(`${kind}:${value.trim().toLowerCase()}`).digest("hex");
|
|
69788
70208
|
}
|
|
69789
70209
|
async function linkAnalyticsFormIdentity(input) {
|
|
69790
70210
|
const client2 = await getAnalyticsPool().connect();
|
|
@@ -69793,7 +70213,7 @@ async function linkAnalyticsFormIdentity(input) {
|
|
|
69793
70213
|
const person = await client2.query(
|
|
69794
70214
|
`INSERT INTO analytics_people(id, site_id, crm_person_ref) VALUES ($1,$2,$3)
|
|
69795
70215
|
ON CONFLICT(site_id, crm_person_ref) DO UPDATE SET last_seen_at = now() RETURNING id`,
|
|
69796
|
-
[(0,
|
|
70216
|
+
[(0, import_node_crypto41.randomUUID)(), input.siteId, input.crmPersonRef]
|
|
69797
70217
|
);
|
|
69798
70218
|
const personId = person.rows[0].id;
|
|
69799
70219
|
const signals = [];
|
|
@@ -69840,7 +70260,7 @@ async function linkAnalyticsFormIdentity(input) {
|
|
|
69840
70260
|
`INSERT INTO analytics_identity_nodes(id, site_id, kind, value_hmac) VALUES ($1,$2,$3,$4)
|
|
69841
70261
|
ON CONFLICT(site_id, kind, value_hmac) DO UPDATE SET last_seen_at = now() RETURNING id`,
|
|
69842
70262
|
[
|
|
69843
|
-
(0,
|
|
70263
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
69844
70264
|
input.siteId,
|
|
69845
70265
|
signal.kind,
|
|
69846
70266
|
identityHmac(signal.kind, signal.value)
|
|
@@ -69851,7 +70271,7 @@ async function linkAnalyticsFormIdentity(input) {
|
|
|
69851
70271
|
VALUES ($1,$2,$3,$4,$5,$6)
|
|
69852
70272
|
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
70273
|
[
|
|
69854
|
-
(0,
|
|
70274
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
69855
70275
|
input.siteId,
|
|
69856
70276
|
personId,
|
|
69857
70277
|
node.rows[0].id,
|
|
@@ -69949,7 +70369,7 @@ async function createAnalyticsCrmImport(input) {
|
|
|
69949
70369
|
const db = getAnalyticsPool();
|
|
69950
70370
|
await requireEditor(db, input.siteId, input.userId);
|
|
69951
70371
|
const client2 = await db.connect();
|
|
69952
|
-
const id = (0,
|
|
70372
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
69953
70373
|
try {
|
|
69954
70374
|
await client2.query("BEGIN");
|
|
69955
70375
|
await client2.query(
|
|
@@ -69969,7 +70389,7 @@ async function createAnalyticsCrmImport(input) {
|
|
|
69969
70389
|
await client2.query(
|
|
69970
70390
|
`INSERT INTO analytics_crm_import_rows(id, import_id, crm_person_ref, payload_ciphertext)
|
|
69971
70391
|
VALUES ($1,$2,$3,$4) ON CONFLICT(import_id, crm_person_ref) DO NOTHING`,
|
|
69972
|
-
[(0,
|
|
70392
|
+
[(0, import_node_crypto41.randomUUID)(), id, row.crmPersonRef, row.payloadCiphertext]
|
|
69973
70393
|
);
|
|
69974
70394
|
}
|
|
69975
70395
|
await client2.query("COMMIT");
|
|
@@ -70008,7 +70428,7 @@ async function createAnalyticsActivationDestination(input) {
|
|
|
70008
70428
|
`INSERT INTO analytics_activation_destinations(id, site_id, platform, name, connection_ref, external_dataset_id, event_mapping, created_by_user_id)
|
|
70009
70429
|
VALUES ($1,$2,$3,$4,$5,$6,$7::jsonb,$8) RETURNING *`,
|
|
70010
70430
|
[
|
|
70011
|
-
(0,
|
|
70431
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
70012
70432
|
input.siteId,
|
|
70013
70433
|
input.platform,
|
|
70014
70434
|
input.name.trim(),
|
|
@@ -70060,7 +70480,7 @@ async function queueAnalyticsActivation(input) {
|
|
|
70060
70480
|
`INSERT INTO analytics_activation_jobs(id, destination_id, conversion_id, person_id, payload_ciphertext)
|
|
70061
70481
|
VALUES ($1,$2,$3,$4,$5) ON CONFLICT(destination_id, conversion_id) DO NOTHING`,
|
|
70062
70482
|
[
|
|
70063
|
-
(0,
|
|
70483
|
+
(0, import_node_crypto41.randomUUID)(),
|
|
70064
70484
|
destination.id,
|
|
70065
70485
|
input.conversionId,
|
|
70066
70486
|
input.personId ?? null,
|
|
@@ -70072,7 +70492,7 @@ async function queueAnalyticsActivation(input) {
|
|
|
70072
70492
|
return queued;
|
|
70073
70493
|
}
|
|
70074
70494
|
async function queueAnalyticsFormDelivery(input) {
|
|
70075
|
-
const id = (0,
|
|
70495
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
70076
70496
|
await getAnalyticsPool().query(
|
|
70077
70497
|
`INSERT INTO analytics_form_delivery_jobs(id, submission_id, owner_user_id, payload_ciphertext, last_error_code)
|
|
70078
70498
|
VALUES ($1,$2,$3,$4,$5)`,
|
|
@@ -70199,7 +70619,7 @@ async function analyticsHealth(siteId, userId) {
|
|
|
70199
70619
|
}
|
|
70200
70620
|
async function refreshAnalyticsDailyRollups(input) {
|
|
70201
70621
|
const db = getAnalyticsPool();
|
|
70202
|
-
const runId = (0,
|
|
70622
|
+
const runId = (0, import_node_crypto41.randomUUID)();
|
|
70203
70623
|
await db.query(
|
|
70204
70624
|
`INSERT INTO analytics_rollup_runs(id, window_start, window_end, status) VALUES ($1, $2, $3, 'running')`,
|
|
70205
70625
|
[runId, input.start, input.end]
|
|
@@ -70396,7 +70816,7 @@ async function createAnalyticsExport(input) {
|
|
|
70396
70816
|
`Generated ${(/* @__PURE__ */ new Date()).toISOString()} from the governed ${input.report} report contract.`
|
|
70397
70817
|
].join("\n");
|
|
70398
70818
|
}
|
|
70399
|
-
const id = (0,
|
|
70819
|
+
const id = (0, import_node_crypto41.randomUUID)();
|
|
70400
70820
|
const inserted = await getAnalyticsPool().query(
|
|
70401
70821
|
`INSERT INTO analytics_exports(id, site_id, requested_by_user_id, idempotency_key, report, format, filters, content)
|
|
70402
70822
|
VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8)
|
|
@@ -70429,11 +70849,11 @@ async function createAnalyticsExport(input) {
|
|
|
70429
70849
|
}
|
|
70430
70850
|
return describeArtifact(replay.rows[0]);
|
|
70431
70851
|
}
|
|
70432
|
-
var
|
|
70852
|
+
var import_node_crypto41, import_pg, AnalyticsRepositoryError, pool2, MAX_ENGAGED_MS, ENGAGED_SESSION_MS, blockedPropertyName, inferredFamilySql, ANALYTICS_CONTENT_SORTS, clickIdKeys;
|
|
70433
70853
|
var init_analytics_repository = __esm({
|
|
70434
70854
|
"src/api/analytics-repository.ts"() {
|
|
70435
70855
|
"use strict";
|
|
70436
|
-
|
|
70856
|
+
import_node_crypto41 = require("crypto");
|
|
70437
70857
|
import_pg = require("pg");
|
|
70438
70858
|
init_session();
|
|
70439
70859
|
init_analytics_attribution();
|
|
@@ -70672,8 +71092,8 @@ function dashboardCallbackUrl() {
|
|
|
70672
71092
|
}
|
|
70673
71093
|
async function createThorbitConnectUrl(userId) {
|
|
70674
71094
|
if (!bridgeConfigured()) throw new Error("Thorbit X-Ray account bridge is not configured");
|
|
70675
|
-
const state = (0,
|
|
70676
|
-
const stateHash = (0,
|
|
71095
|
+
const state = (0, import_node_crypto42.randomBytes)(32).toString("base64url");
|
|
71096
|
+
const stateHash = (0, import_node_crypto42.createHash)("sha256").update(state).digest("hex");
|
|
70677
71097
|
await getAnalyticsPool().query(
|
|
70678
71098
|
`INSERT INTO analytics_thorbit_connect_states(state_hash,user_id,expires_at)
|
|
70679
71099
|
VALUES ($1,$2,now()+interval '10 minutes')
|
|
@@ -70688,9 +71108,9 @@ async function createThorbitConnectUrl(userId) {
|
|
|
70688
71108
|
function verifyThorbitAssertion(token6) {
|
|
70689
71109
|
const [encoded, signature] = token6.split(".");
|
|
70690
71110
|
if (!encoded || !signature || !bridgeConfigured()) throw new Error("Invalid Thorbit assertion");
|
|
70691
|
-
const expected = (0,
|
|
71111
|
+
const expected = (0, import_node_crypto42.createHmac)("sha256", bridgeSecret()).update(encoded).digest();
|
|
70692
71112
|
const actual = Buffer.from(signature, "base64url");
|
|
70693
|
-
if (actual.length !== expected.length || !(0,
|
|
71113
|
+
if (actual.length !== expected.length || !(0, import_node_crypto42.timingSafeEqual)(actual, expected)) {
|
|
70694
71114
|
throw new Error("Invalid Thorbit assertion signature");
|
|
70695
71115
|
}
|
|
70696
71116
|
const parsed = AssertionSchema.safeParse(
|
|
@@ -70702,7 +71122,7 @@ function verifyThorbitAssertion(token6) {
|
|
|
70702
71122
|
return parsed.data.entitlement;
|
|
70703
71123
|
}
|
|
70704
71124
|
async function consumeThorbitConnectCallback(input) {
|
|
70705
|
-
const stateHash = (0,
|
|
71125
|
+
const stateHash = (0, import_node_crypto42.createHash)("sha256").update(input.state).digest("hex");
|
|
70706
71126
|
const client2 = await getAnalyticsPool().connect();
|
|
70707
71127
|
try {
|
|
70708
71128
|
await client2.query("BEGIN");
|
|
@@ -70742,11 +71162,11 @@ async function disconnectAnalyticsEntitlement(userId) {
|
|
|
70742
71162
|
[userId]
|
|
70743
71163
|
);
|
|
70744
71164
|
}
|
|
70745
|
-
var
|
|
71165
|
+
var import_node_crypto42, import_zod53, THORBIT_PRODUCT_URL, REFRESH_INTERVAL_MS, ELIGIBLE_GRACE_MS, TRIAL_LENGTH_MS, ThorbitEntitlementSchema, AssertionSchema;
|
|
70746
71166
|
var init_analytics_entitlement = __esm({
|
|
70747
71167
|
"src/api/analytics-entitlement.ts"() {
|
|
70748
71168
|
"use strict";
|
|
70749
|
-
|
|
71169
|
+
import_node_crypto42 = require("crypto");
|
|
70750
71170
|
import_zod53 = require("zod");
|
|
70751
71171
|
init_analytics_repository();
|
|
70752
71172
|
THORBIT_PRODUCT_URL = "https://thorbit.ai";
|
|
@@ -70886,14 +71306,14 @@ function renderPublicForm(form, placementUrl) {
|
|
|
70886
71306
|
const brand = form.brand;
|
|
70887
71307
|
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
71308
|
}
|
|
70889
|
-
var import_hono32, import_factory6, import_zod54,
|
|
71309
|
+
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
71310
|
var init_analytics_routes = __esm({
|
|
70891
71311
|
"src/api/analytics-routes.ts"() {
|
|
70892
71312
|
"use strict";
|
|
70893
71313
|
import_hono32 = require("hono");
|
|
70894
71314
|
import_factory6 = require("hono/factory");
|
|
70895
71315
|
import_zod54 = require("zod");
|
|
70896
|
-
|
|
71316
|
+
import_node_crypto43 = require("crypto");
|
|
70897
71317
|
import_papaparse4 = __toESM(require("papaparse"), 1);
|
|
70898
71318
|
init_api_auth();
|
|
70899
71319
|
init_db();
|
|
@@ -71224,7 +71644,7 @@ var init_analytics_routes = __esm({
|
|
|
71224
71644
|
const lastName = typeof data.last_name === "string" ? data.last_name.trim() : "";
|
|
71225
71645
|
const fullName = [firstName, lastName].filter(Boolean).join(" ") || (typeof data.name === "string" ? data.name.trim() : "") || email || "Website lead";
|
|
71226
71646
|
const identitySeed = email || `${fullName}:${Date.now()}`;
|
|
71227
|
-
const suffix2 = (0,
|
|
71647
|
+
const suffix2 = (0, import_node_crypto43.createHash)("sha256").update(identitySeed).digest("hex").slice(0, 12);
|
|
71228
71648
|
const path6 = `Leads/person-${suffix2}`;
|
|
71229
71649
|
const { key: memoryKey, error: memoryKeyError } = await getOrCreateUserMemoryKey(user);
|
|
71230
71650
|
const existing = memoryKey ? await memoryCall("getTool", { vault: "People", path: path6 }, memoryKey) : { ok: false, error: memoryKeyError || "memory_credential_unavailable" };
|
|
@@ -71323,9 +71743,9 @@ Submitted the published form.
|
|
|
71323
71743
|
occurredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
71324
71744
|
});
|
|
71325
71745
|
const match = {
|
|
71326
|
-
...email ? { emailSha256: (0,
|
|
71746
|
+
...email ? { emailSha256: (0, import_node_crypto43.createHash)("sha256").update(email).digest("hex") } : {},
|
|
71327
71747
|
...phone ? {
|
|
71328
|
-
phoneSha256: (0,
|
|
71748
|
+
phoneSha256: (0, import_node_crypto43.createHash)("sha256").update(phone.replace(/\D/g, "")).digest("hex")
|
|
71329
71749
|
} : {}
|
|
71330
71750
|
};
|
|
71331
71751
|
const activationQueued = await queueAnalyticsActivation({
|
|
@@ -71753,7 +72173,7 @@ Submitted the published form.
|
|
|
71753
72173
|
rejectedCount += 1;
|
|
71754
72174
|
continue;
|
|
71755
72175
|
}
|
|
71756
|
-
const digest2 = (0,
|
|
72176
|
+
const digest2 = (0, import_node_crypto43.createHash)("sha256").update(
|
|
71757
72177
|
`${parsed.data.sourceSystem}:${externalId || email || phone || `${fullName}:${index}`}`
|
|
71758
72178
|
).digest("hex").slice(0, 16);
|
|
71759
72179
|
const path6 = `Leads/person-${digest2}`;
|
|
@@ -72211,13 +72631,13 @@ var init_analytics_delivery = __esm({
|
|
|
72211
72631
|
|
|
72212
72632
|
// src/api/scheduled-artifact-owner.ts
|
|
72213
72633
|
function scheduledArtifactOwnerIdForApiKey(apiKey) {
|
|
72214
|
-
return (0,
|
|
72634
|
+
return (0, import_node_crypto44.createHash)("sha256").update(apiKey).digest("hex").slice(0, 24);
|
|
72215
72635
|
}
|
|
72216
|
-
var
|
|
72636
|
+
var import_node_crypto44;
|
|
72217
72637
|
var init_scheduled_artifact_owner = __esm({
|
|
72218
72638
|
"src/api/scheduled-artifact-owner.ts"() {
|
|
72219
72639
|
"use strict";
|
|
72220
|
-
|
|
72640
|
+
import_node_crypto44 = require("crypto");
|
|
72221
72641
|
}
|
|
72222
72642
|
});
|
|
72223
72643
|
|
|
@@ -72274,7 +72694,7 @@ async function ensureScheduledRunViewLinksSchema() {
|
|
|
72274
72694
|
schemaReady2 = true;
|
|
72275
72695
|
}
|
|
72276
72696
|
function tokenHash2(token6) {
|
|
72277
|
-
return (0,
|
|
72697
|
+
return (0, import_node_crypto45.createHash)("sha256").update(token6).digest("hex");
|
|
72278
72698
|
}
|
|
72279
72699
|
function mapRow(row) {
|
|
72280
72700
|
return {
|
|
@@ -72294,9 +72714,9 @@ function mapRow(row) {
|
|
|
72294
72714
|
async function createScheduledRunViewLink(input) {
|
|
72295
72715
|
await ensureScheduledRunViewLinksSchema();
|
|
72296
72716
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
72297
|
-
const token6 = (0,
|
|
72717
|
+
const token6 = (0, import_node_crypto45.randomBytes)(32).toString("base64url");
|
|
72298
72718
|
const record = {
|
|
72299
|
-
shareId: (0,
|
|
72719
|
+
shareId: (0, import_node_crypto45.randomUUID)(),
|
|
72300
72720
|
ownerId: input.ownerId,
|
|
72301
72721
|
runId: input.runId,
|
|
72302
72722
|
artifactId: input.artifactId,
|
|
@@ -72359,11 +72779,11 @@ async function revokeScheduledRunViewLink(ownerId, runId, shareId, now = /* @__P
|
|
|
72359
72779
|
});
|
|
72360
72780
|
return result.rowsAffected > 0;
|
|
72361
72781
|
}
|
|
72362
|
-
var
|
|
72782
|
+
var import_node_crypto45, schemaReady2;
|
|
72363
72783
|
var init_scheduled_run_view_links = __esm({
|
|
72364
72784
|
"src/api/scheduled-run-view-links.ts"() {
|
|
72365
72785
|
"use strict";
|
|
72366
|
-
|
|
72786
|
+
import_node_crypto45 = require("crypto");
|
|
72367
72787
|
init_db();
|
|
72368
72788
|
schemaReady2 = false;
|
|
72369
72789
|
}
|
|
@@ -72429,15 +72849,15 @@ ${section(flags.finalCta && Boolean(finalCta), `<section class="section cta" id=
|
|
|
72429
72849
|
html,
|
|
72430
72850
|
filename: `${input.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "personal-authority"}.html`,
|
|
72431
72851
|
bytes,
|
|
72432
|
-
sha256: (0,
|
|
72852
|
+
sha256: (0, import_node_crypto46.createHash)("sha256").update(html).digest("hex"),
|
|
72433
72853
|
generatedAt: generatedAtIso
|
|
72434
72854
|
};
|
|
72435
72855
|
}
|
|
72436
|
-
var
|
|
72856
|
+
var import_node_crypto46;
|
|
72437
72857
|
var init_render2 = __esm({
|
|
72438
72858
|
"src/personal-authority/render.ts"() {
|
|
72439
72859
|
"use strict";
|
|
72440
|
-
|
|
72860
|
+
import_node_crypto46 = require("crypto");
|
|
72441
72861
|
}
|
|
72442
72862
|
});
|
|
72443
72863
|
|
|
@@ -72540,15 +72960,15 @@ ${section2(flags.finalCta && Boolean(finalCta), `<section class="section cta" id
|
|
|
72540
72960
|
html,
|
|
72541
72961
|
filename: `${input.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "personal-authority"}.html`,
|
|
72542
72962
|
bytes,
|
|
72543
|
-
sha256: (0,
|
|
72963
|
+
sha256: (0, import_node_crypto47.createHash)("sha256").update(html).digest("hex"),
|
|
72544
72964
|
generatedAt: generatedAtIso
|
|
72545
72965
|
};
|
|
72546
72966
|
}
|
|
72547
|
-
var
|
|
72967
|
+
var import_node_crypto47, FONT_STACKS;
|
|
72548
72968
|
var init_render_v2 = __esm({
|
|
72549
72969
|
"src/personal-authority/render-v2.ts"() {
|
|
72550
72970
|
"use strict";
|
|
72551
|
-
|
|
72971
|
+
import_node_crypto47 = require("crypto");
|
|
72552
72972
|
init_contracts();
|
|
72553
72973
|
FONT_STACKS = Object.freeze({
|
|
72554
72974
|
"editorial-serif": "Iowan Old Style, Baskerville, Times New Roman, serif",
|
|
@@ -72664,15 +73084,15 @@ body{overflow-x:hidden}.lead-story__body,.lead-support__item,.story-card__body{m
|
|
|
72664
73084
|
@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
73085
|
</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
73086
|
const bytes = Buffer.byteLength(html);
|
|
72667
|
-
const sha2563 = (0,
|
|
73087
|
+
const sha2563 = (0, import_node_crypto48.createHash)("sha256").update(html).digest("hex");
|
|
72668
73088
|
const filename = `${brand.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "newsroom"}-news-site.html`;
|
|
72669
73089
|
return { html, filename, bytes, sha256: sha2563, generatedAt: generatedAtIso };
|
|
72670
73090
|
}
|
|
72671
|
-
var
|
|
73091
|
+
var import_node_crypto48;
|
|
72672
73092
|
var init_render3 = __esm({
|
|
72673
73093
|
"src/newsroom-publisher/render.ts"() {
|
|
72674
73094
|
"use strict";
|
|
72675
|
-
|
|
73095
|
+
import_node_crypto48 = require("crypto");
|
|
72676
73096
|
}
|
|
72677
73097
|
});
|
|
72678
73098
|
|
|
@@ -72764,7 +73184,7 @@ function renderBlogArticleV1(input, config, generatedAt) {
|
|
|
72764
73184
|
: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
73185
|
</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
73186
|
const bytes = Buffer.byteLength(html);
|
|
72767
|
-
const sha2563 = (0,
|
|
73187
|
+
const sha2563 = (0, import_node_crypto49.createHash)("sha256").update(html).digest("hex");
|
|
72768
73188
|
return {
|
|
72769
73189
|
html,
|
|
72770
73190
|
filename: "blog-article.html",
|
|
@@ -72774,11 +73194,11 @@ function renderBlogArticleV1(input, config, generatedAt) {
|
|
|
72774
73194
|
generatedAt: generatedAtIso
|
|
72775
73195
|
};
|
|
72776
73196
|
}
|
|
72777
|
-
var
|
|
73197
|
+
var import_node_crypto49;
|
|
72778
73198
|
var init_render4 = __esm({
|
|
72779
73199
|
"src/blog-article/render.ts"() {
|
|
72780
73200
|
"use strict";
|
|
72781
|
-
|
|
73201
|
+
import_node_crypto49 = require("crypto");
|
|
72782
73202
|
}
|
|
72783
73203
|
});
|
|
72784
73204
|
|
|
@@ -73109,7 +73529,7 @@ function policy5() {
|
|
|
73109
73529
|
};
|
|
73110
73530
|
}
|
|
73111
73531
|
function runStorageSegment(runId) {
|
|
73112
|
-
return /^[a-zA-Z0-9_-]{1,160}$/.test(runId) ? runId : `run-${(0,
|
|
73532
|
+
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
73533
|
}
|
|
73114
73534
|
async function createScheduledRunArtifact(args) {
|
|
73115
73535
|
if (args.rendered.bytes > SCHEDULED_RUN_ARTIFACT_MAX_BYTES) {
|
|
@@ -73150,12 +73570,12 @@ async function readScheduledRunArtifact(args) {
|
|
|
73150
73570
|
if (!window2 || window2.nextOffset !== null || window2.totalBytes > SCHEDULED_RUN_ARTIFACT_MAX_BYTES) return null;
|
|
73151
73571
|
return window2.text;
|
|
73152
73572
|
}
|
|
73153
|
-
var
|
|
73573
|
+
var import_node_crypto50, SCHEDULED_RUN_ARTIFACT_PREFIX, SCHEDULED_RUN_ARTIFACT_DOWNLOAD_TTL_MS, SCHEDULED_RUN_ARTIFACT_MAX_BYTES;
|
|
73154
73574
|
var init_scheduled_run_artifact_store = __esm({
|
|
73155
73575
|
"src/scheduled-artifacts/scheduled-run-artifact-store.ts"() {
|
|
73156
73576
|
"use strict";
|
|
73157
73577
|
init_private_artifacts();
|
|
73158
|
-
|
|
73578
|
+
import_node_crypto50 = require("crypto");
|
|
73159
73579
|
SCHEDULED_RUN_ARTIFACT_PREFIX = "scheduled-run-artifacts/";
|
|
73160
73580
|
SCHEDULED_RUN_ARTIFACT_DOWNLOAD_TTL_MS = 15 * 60 * 1e3;
|
|
73161
73581
|
SCHEDULED_RUN_ARTIFACT_MAX_BYTES = 2e6;
|
|
@@ -73373,7 +73793,7 @@ async function reconcileDiscoveredNangoConnections(identity, discovered) {
|
|
|
73373
73793
|
updated_at = excluded.updated_at
|
|
73374
73794
|
`,
|
|
73375
73795
|
args: [
|
|
73376
|
-
(0,
|
|
73796
|
+
(0, import_node_crypto51.randomUUID)(),
|
|
73377
73797
|
userId,
|
|
73378
73798
|
connection.providerConfigKey,
|
|
73379
73799
|
connection.provider,
|
|
@@ -73444,7 +73864,7 @@ async function recordServiceConnectionHealth(args) {
|
|
|
73444
73864
|
});
|
|
73445
73865
|
await getDb().execute({
|
|
73446
73866
|
sql: `INSERT INTO service_connection_health_events (id, connection_id, operational_status, failure_code, retryable, evidence_source) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
73447
|
-
args: [(0,
|
|
73867
|
+
args: [(0, import_node_crypto51.randomUUID)(), args.connectionId, args.operationalStatus, args.failureCode ?? null, args.retryable == null ? null : args.retryable ? 1 : 0, args.evidenceSource]
|
|
73448
73868
|
});
|
|
73449
73869
|
}
|
|
73450
73870
|
async function setServiceConnectionActions(identity, connectionId, enabled) {
|
|
@@ -73484,7 +73904,7 @@ async function claimServiceConnectionAction(args) {
|
|
|
73484
73904
|
if (!connection) throw new Error("service_connection_not_found");
|
|
73485
73905
|
const inserted = await getDb().execute({
|
|
73486
73906
|
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,
|
|
73907
|
+
args: [(0, import_node_crypto51.randomUUID)(), connection.id, connection.userId, args.tool, args.requestId, args.requestDigest]
|
|
73488
73908
|
});
|
|
73489
73909
|
if (Number(inserted.rowsAffected ?? 0) === 1) return { claimed: true };
|
|
73490
73910
|
const existing = await getDb().execute({
|
|
@@ -73509,11 +73929,11 @@ async function claimServiceConnectionAction(args) {
|
|
|
73509
73929
|
...result !== void 0 ? { result } : {}
|
|
73510
73930
|
};
|
|
73511
73931
|
}
|
|
73512
|
-
var
|
|
73932
|
+
var import_node_crypto51, schemaReady3, schemaDb4;
|
|
73513
73933
|
var init_service_connections = __esm({
|
|
73514
73934
|
"src/api/service-connections.ts"() {
|
|
73515
73935
|
"use strict";
|
|
73516
|
-
|
|
73936
|
+
import_node_crypto51 = require("crypto");
|
|
73517
73937
|
init_db();
|
|
73518
73938
|
schemaReady3 = null;
|
|
73519
73939
|
schemaDb4 = null;
|
|
@@ -73527,8 +73947,8 @@ function signingSecret() {
|
|
|
73527
73947
|
return secret2;
|
|
73528
73948
|
}
|
|
73529
73949
|
function schedulerIntegrationSignature(args) {
|
|
73530
|
-
const bodyHash = (0,
|
|
73531
|
-
return (0,
|
|
73950
|
+
const bodyHash = (0, import_node_crypto52.createHash)("sha256").update(args.body).digest("hex");
|
|
73951
|
+
return (0, import_node_crypto52.createHmac)("sha256", args.secret).update(`${args.method.toUpperCase()}
|
|
73532
73952
|
${args.path}
|
|
73533
73953
|
${args.timestamp}
|
|
73534
73954
|
${args.nonce}
|
|
@@ -73575,17 +73995,17 @@ async function verifySchedulerIntegrationRequest(request, rawBody) {
|
|
|
73575
73995
|
});
|
|
73576
73996
|
const suppliedBytes = Buffer.from(signature, "hex");
|
|
73577
73997
|
const expectedBytes = Buffer.from(expected, "hex");
|
|
73578
|
-
if (suppliedBytes.length !== expectedBytes.length || !(0,
|
|
73998
|
+
if (suppliedBytes.length !== expectedBytes.length || !(0, import_node_crypto52.timingSafeEqual)(suppliedBytes, expectedBytes)) {
|
|
73579
73999
|
throw new SchedulerIntegrationAuthError("invalid_signature");
|
|
73580
74000
|
}
|
|
73581
74001
|
await claimNonce(nonce, timestampMs);
|
|
73582
74002
|
return { requestId };
|
|
73583
74003
|
}
|
|
73584
|
-
var
|
|
74004
|
+
var import_node_crypto52, MAX_CLOCK_SKEW_MS, SchedulerIntegrationAuthError;
|
|
73585
74005
|
var init_scheduler_integration_auth = __esm({
|
|
73586
74006
|
"src/api/scheduler-integration-auth.ts"() {
|
|
73587
74007
|
"use strict";
|
|
73588
|
-
|
|
74008
|
+
import_node_crypto52 = require("crypto");
|
|
73589
74009
|
init_db();
|
|
73590
74010
|
init_service_connections();
|
|
73591
74011
|
MAX_CLOCK_SKEW_MS = 5 * 60 * 1e3;
|
|
@@ -73893,7 +74313,7 @@ async function fetchMedia(rawUrl, expectedType) {
|
|
|
73893
74313
|
finalUrl: checked.parsed.href,
|
|
73894
74314
|
width: dimensions?.width ?? null,
|
|
73895
74315
|
height: dimensions?.height ?? null,
|
|
73896
|
-
sha256: (0,
|
|
74316
|
+
sha256: (0, import_node_crypto53.createHash)("sha256").update(bytes).digest("hex")
|
|
73897
74317
|
};
|
|
73898
74318
|
}
|
|
73899
74319
|
throw new Error("media_redirect_rejected");
|
|
@@ -74007,7 +74427,7 @@ async function packagePageMedia(args) {
|
|
|
74007
74427
|
files.push({ path: "summary.json", content: Buffer.from(JSON.stringify(summary, null, 2)) });
|
|
74008
74428
|
files.push({ path: "media.jsonl", content: Buffer.from(cleanAssets.map((asset) => JSON.stringify(asset)).join("\n") + "\n") });
|
|
74009
74429
|
const archive = await zipBuffer2(files);
|
|
74010
|
-
const id = (0,
|
|
74430
|
+
const id = (0, import_node_crypto53.randomBytes)(6).toString("hex");
|
|
74011
74431
|
const pointer = await createPrivateArtifact({
|
|
74012
74432
|
policy: policy6(),
|
|
74013
74433
|
ownerId: args.ownerId,
|
|
@@ -74020,11 +74440,11 @@ async function packagePageMedia(args) {
|
|
|
74020
74440
|
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
74441
|
return { media: args.media, artifact: { ...pointer, localPath } };
|
|
74022
74442
|
}
|
|
74023
|
-
var
|
|
74443
|
+
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
74444
|
var init_page_media_artifacts = __esm({
|
|
74025
74445
|
"src/api/page-media-artifacts.ts"() {
|
|
74026
74446
|
"use strict";
|
|
74027
|
-
|
|
74447
|
+
import_node_crypto53 = require("crypto");
|
|
74028
74448
|
import_node_os14 = require("os");
|
|
74029
74449
|
import_node_path21 = require("path");
|
|
74030
74450
|
import_p_limit7 = __toESM(require("p-limit"), 1);
|
|
@@ -74118,7 +74538,7 @@ var init_site_extract_reconciliation = __esm({
|
|
|
74118
74538
|
|
|
74119
74539
|
// src/api/page-diff.ts
|
|
74120
74540
|
function sha256Hex(value) {
|
|
74121
|
-
return (0,
|
|
74541
|
+
return (0, import_node_crypto54.createHash)("sha256").update(value).digest("hex");
|
|
74122
74542
|
}
|
|
74123
74543
|
function truncateForStorage(value, maxChars = MAX_SNAPSHOT_CONTENT_CHARS) {
|
|
74124
74544
|
if (value.length <= maxChars) return { value, truncated: false };
|
|
@@ -74175,11 +74595,11 @@ function diffPageContent(oldContent, newContent) {
|
|
|
74175
74595
|
totalChangedLineCount
|
|
74176
74596
|
};
|
|
74177
74597
|
}
|
|
74178
|
-
var
|
|
74598
|
+
var import_node_crypto54, import_diff, MAX_SNAPSHOT_CONTENT_CHARS, MAX_DIFF_HUNKS, MAX_DIFF_LINES_PER_RESPONSE;
|
|
74179
74599
|
var init_page_diff = __esm({
|
|
74180
74600
|
"src/api/page-diff.ts"() {
|
|
74181
74601
|
"use strict";
|
|
74182
|
-
|
|
74602
|
+
import_node_crypto54 = require("crypto");
|
|
74183
74603
|
import_diff = require("diff");
|
|
74184
74604
|
MAX_SNAPSHOT_CONTENT_CHARS = 25e4;
|
|
74185
74605
|
MAX_DIFF_HUNKS = 200;
|
|
@@ -74253,7 +74673,7 @@ var init_scrape_vault_sink = __esm({
|
|
|
74253
74673
|
|
|
74254
74674
|
// src/api/scrape-image-sink.ts
|
|
74255
74675
|
function idempotencyKey2(userId, vault, input) {
|
|
74256
|
-
return `scrape-image-${(0,
|
|
74676
|
+
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
74677
|
}
|
|
74258
74678
|
async function persistScrapeImagesToMemory(user, inputs, vault) {
|
|
74259
74679
|
const selected = inputs.slice(0, MAX_IMAGES_PER_SCRAPE);
|
|
@@ -74295,11 +74715,11 @@ async function persistScrapeImagesToMemory(user, inputs, vault) {
|
|
|
74295
74715
|
assets
|
|
74296
74716
|
};
|
|
74297
74717
|
}
|
|
74298
|
-
var
|
|
74718
|
+
var import_node_crypto55, MAX_IMAGES_PER_SCRAPE;
|
|
74299
74719
|
var init_scrape_image_sink = __esm({
|
|
74300
74720
|
"src/api/scrape-image-sink.ts"() {
|
|
74301
74721
|
"use strict";
|
|
74302
|
-
|
|
74722
|
+
import_node_crypto55 = require("crypto");
|
|
74303
74723
|
init_memory();
|
|
74304
74724
|
MAX_IMAGES_PER_SCRAPE = 25;
|
|
74305
74725
|
}
|
|
@@ -74752,7 +75172,7 @@ function canonicalJson(value) {
|
|
|
74752
75172
|
return JSON.stringify(value);
|
|
74753
75173
|
}
|
|
74754
75174
|
function sha2562(value) {
|
|
74755
|
-
return (0,
|
|
75175
|
+
return (0, import_node_crypto56.createHash)("sha256").update(value).digest("hex");
|
|
74756
75176
|
}
|
|
74757
75177
|
function sensitiveKey(key) {
|
|
74758
75178
|
const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
@@ -74967,11 +75387,11 @@ async function importServiceConnectionToMemory(identity, input, dependencies) {
|
|
|
74967
75387
|
...!searchReady ? { warning: "The snapshot was stored, but no search chunks were indexed yet." } : {}
|
|
74968
75388
|
};
|
|
74969
75389
|
}
|
|
74970
|
-
var
|
|
75390
|
+
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
75391
|
var init_connection_memory_import = __esm({
|
|
74972
75392
|
"src/api/connection-memory-import.ts"() {
|
|
74973
75393
|
"use strict";
|
|
74974
|
-
|
|
75394
|
+
import_node_crypto56 = require("crypto");
|
|
74975
75395
|
init_slugify();
|
|
74976
75396
|
CONNECTION_MEMORY_IMPORT_MAX_ARGS_BYTES = 64 * 1024;
|
|
74977
75397
|
CONNECTION_MEMORY_IMPORT_MAX_RESULT_BYTES = 1e6;
|
|
@@ -75016,16 +75436,16 @@ async function cleanupLocal(cutoff) {
|
|
|
75016
75436
|
let deleted = 0;
|
|
75017
75437
|
let entries;
|
|
75018
75438
|
try {
|
|
75019
|
-
entries = await (0,
|
|
75439
|
+
entries = await (0, import_promises16.readdir)(dir);
|
|
75020
75440
|
} catch {
|
|
75021
75441
|
return { deleted: 0, store: "local" };
|
|
75022
75442
|
}
|
|
75023
75443
|
for (const name of entries) {
|
|
75024
75444
|
const path6 = (0, import_node_path23.join)(dir, name);
|
|
75025
75445
|
try {
|
|
75026
|
-
const s = await (0,
|
|
75446
|
+
const s = await (0, import_promises16.stat)(path6);
|
|
75027
75447
|
if (s.isFile() && s.mtimeMs < cutoff) {
|
|
75028
|
-
await (0,
|
|
75448
|
+
await (0, import_promises16.unlink)(path6);
|
|
75029
75449
|
deleted++;
|
|
75030
75450
|
}
|
|
75031
75451
|
} catch {
|
|
@@ -75042,11 +75462,11 @@ async function cleanupExpiredScrapeBlobs(maxAgeMs = SCRAPE_BLOB_TTL_MS) {
|
|
|
75042
75462
|
return { deleted: 0, store: "none" };
|
|
75043
75463
|
}
|
|
75044
75464
|
}
|
|
75045
|
-
var
|
|
75465
|
+
var import_promises16, import_node_os15, import_node_path23;
|
|
75046
75466
|
var init_scrape_blob_cleanup = __esm({
|
|
75047
75467
|
"src/api/scrape-blob-cleanup.ts"() {
|
|
75048
75468
|
"use strict";
|
|
75049
|
-
|
|
75469
|
+
import_promises16 = require("fs/promises");
|
|
75050
75470
|
import_node_os15 = require("os");
|
|
75051
75471
|
import_node_path23 = require("path");
|
|
75052
75472
|
init_scrape_vault_sink();
|
|
@@ -75189,7 +75609,7 @@ function finitePositive(value, fallback) {
|
|
|
75189
75609
|
return Number.isFinite(value) && value > 0 ? value : fallback;
|
|
75190
75610
|
}
|
|
75191
75611
|
async function collectConnectedDataExport(args) {
|
|
75192
|
-
const exportId = (0,
|
|
75612
|
+
const exportId = (0, import_node_crypto57.randomUUID)();
|
|
75193
75613
|
const now = args.now ?? Date.now;
|
|
75194
75614
|
const startedAt = now();
|
|
75195
75615
|
const budgetMs = finitePositive(CONNECTED_DATA_EXPORT_BUDGET_MS, 24e4);
|
|
@@ -75303,11 +75723,11 @@ ${lines.length ? `${lines.join("\n")}
|
|
|
75303
75723
|
untrustedContent: true
|
|
75304
75724
|
};
|
|
75305
75725
|
}
|
|
75306
|
-
var
|
|
75726
|
+
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
75727
|
var init_connected_data_export = __esm({
|
|
75308
75728
|
"src/api/connected-data-export.ts"() {
|
|
75309
75729
|
"use strict";
|
|
75310
|
-
|
|
75730
|
+
import_node_crypto57 = require("crypto");
|
|
75311
75731
|
CONNECTED_DATA_INLINE_BUDGET_BYTES = Number(
|
|
75312
75732
|
process.env.MCP_SCRAPER_CONNECTED_DATA_INLINE_BUDGET_BYTES ?? 5e4
|
|
75313
75733
|
);
|
|
@@ -75421,7 +75841,7 @@ async function exportSearchConsoleTableData(args) {
|
|
|
75421
75841
|
offset += rows.length;
|
|
75422
75842
|
if (stoppedForBytes || rows.length < limit || offset >= matchedRows) break;
|
|
75423
75843
|
}
|
|
75424
|
-
const exportId = (0,
|
|
75844
|
+
const exportId = (0, import_node_crypto58.randomUUID)();
|
|
75425
75845
|
const artifact = await args.writeArtifact({
|
|
75426
75846
|
ownerId: args.ownerId,
|
|
75427
75847
|
exportId,
|
|
@@ -75443,11 +75863,11 @@ async function exportSearchConsoleTableData(args) {
|
|
|
75443
75863
|
warnings
|
|
75444
75864
|
};
|
|
75445
75865
|
}
|
|
75446
|
-
var
|
|
75866
|
+
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
75867
|
var init_search_console_table_export = __esm({
|
|
75448
75868
|
"src/api/search-console-table-export.ts"() {
|
|
75449
75869
|
"use strict";
|
|
75450
|
-
|
|
75870
|
+
import_node_crypto58 = require("crypto");
|
|
75451
75871
|
SEARCH_CONSOLE_TABLE_EXPORT_MAX_ROWS = 5e4;
|
|
75452
75872
|
SEARCH_CONSOLE_TABLE_EXPORT_PAGE_SIZE = 2e3;
|
|
75453
75873
|
SEARCH_CONSOLE_TABLE_EXPORT_MAX_BYTES = 50 * 1024 * 1024;
|
|
@@ -76626,7 +77046,7 @@ async function listNangoToolsDirect(identity, connectionId) {
|
|
|
76626
77046
|
});
|
|
76627
77047
|
const readTools = [...policies.values()].filter((policy7) => policy7.classification === "read").map((policy7) => policy7.name);
|
|
76628
77048
|
const actionTools = [...policies.values()].filter((policy7) => policy7.classification === "action").map((policy7) => policy7.name);
|
|
76629
|
-
const revision = (0,
|
|
77049
|
+
const revision = (0, import_node_crypto59.createHash)("sha256").update(JSON.stringify(tools.map((tool) => ({ name: tool.name, inputSchema: tool.inputSchema })))).digest("hex");
|
|
76630
77050
|
await updateServiceConnectionTools(connection.id, readTools, actionTools, revision);
|
|
76631
77051
|
const refreshed = await getOwnedServiceConnection(identity, connection.id);
|
|
76632
77052
|
return { connection: refreshed ?? { ...connection, readTools, actionTools, toolRevision: revision }, tools };
|
|
@@ -76653,8 +77073,8 @@ async function callNangoToolDirect(args) {
|
|
|
76653
77073
|
identity: args.identity,
|
|
76654
77074
|
ratePolicyVersion: CONNECTED_USAGE_RATE_POLICY_VERSION
|
|
76655
77075
|
});
|
|
76656
|
-
const requestId = args.requestId?.trim() || (0,
|
|
76657
|
-
const idempotencyKey3 = `main-nango:${(0,
|
|
77076
|
+
const requestId = args.requestId?.trim() || (0, import_node_crypto59.randomUUID)();
|
|
77077
|
+
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
77078
|
const startedAt = /* @__PURE__ */ new Date();
|
|
76659
77079
|
const started = performance.now();
|
|
76660
77080
|
let result;
|
|
@@ -76679,7 +77099,7 @@ async function callNangoToolDirect(args) {
|
|
|
76679
77099
|
toolName: args.tool,
|
|
76680
77100
|
operationKind: args.operationKind ?? args.classification,
|
|
76681
77101
|
outcome: providerError ? "error" : "partial",
|
|
76682
|
-
requestId: requestId.length <= 200 ? requestId : (0,
|
|
77102
|
+
requestId: requestId.length <= 200 ? requestId : (0, import_node_crypto59.createHash)("sha256").update(requestId).digest("hex"),
|
|
76683
77103
|
startedAt: startedAt.toISOString(),
|
|
76684
77104
|
completedAt: completedAt.toISOString()
|
|
76685
77105
|
}
|
|
@@ -76721,15 +77141,15 @@ async function describeNangoToolDirect(identity, connectionId, toolName) {
|
|
|
76721
77141
|
providerContractHash: MAIN_INTEGRATION_CONTRACT_HASH,
|
|
76722
77142
|
protocolVersion: null,
|
|
76723
77143
|
schemaSource: "live_tools_list",
|
|
76724
|
-
schemaHash: (0,
|
|
77144
|
+
schemaHash: (0, import_node_crypto59.createHash)("sha256").update(JSON.stringify(projected)).digest("hex"),
|
|
76725
77145
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
76726
77146
|
};
|
|
76727
77147
|
}
|
|
76728
|
-
var
|
|
77148
|
+
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
77149
|
var init_main_nango_transport = __esm({
|
|
76730
77150
|
"src/api/main-nango-transport.ts"() {
|
|
76731
77151
|
"use strict";
|
|
76732
|
-
|
|
77152
|
+
import_node_crypto59 = require("crypto");
|
|
76733
77153
|
import_client13 = require("@modelcontextprotocol/client");
|
|
76734
77154
|
init_service_connections();
|
|
76735
77155
|
init_connected_usage_billing();
|
|
@@ -77353,8 +77773,8 @@ async function setScheduleConnectionActionsEnabled(identity, connectionId, enabl
|
|
|
77353
77773
|
return data.connection.actionsEnabled === true;
|
|
77354
77774
|
}
|
|
77355
77775
|
async function callScheduleConnectionAction(identity, connectionId, input, tool, idempotencyKey3) {
|
|
77356
|
-
const requestId = `main-connected-action:${(0,
|
|
77357
|
-
const requestDigest = (0,
|
|
77776
|
+
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")}`;
|
|
77777
|
+
const requestDigest = (0, import_node_crypto60.createHash)("sha256").update(connectionId).update("\0").update(tool?.trim() ?? "").update("\0").update(canonicalJson2(input)).digest("hex");
|
|
77358
77778
|
if (mainOwnsIntegrations()) {
|
|
77359
77779
|
const selectedTool = tool?.trim();
|
|
77360
77780
|
if (!selectedTool) throw new NangoControlError("An action tool is required.", 400, "invalid_request", false);
|
|
@@ -77505,7 +77925,7 @@ function canonicalJson2(value) {
|
|
|
77505
77925
|
return JSON.stringify(value);
|
|
77506
77926
|
}
|
|
77507
77927
|
function projectedToolSchemaHash(tool) {
|
|
77508
|
-
return (0,
|
|
77928
|
+
return (0, import_node_crypto60.createHash)("sha256").update(canonicalJson2(tool)).digest("hex");
|
|
77509
77929
|
}
|
|
77510
77930
|
async function describeNangoTool(identity, connectionId, tool, fresh) {
|
|
77511
77931
|
if (mainOwnsIntegrations()) {
|
|
@@ -77782,11 +78202,11 @@ async function callMainOwnedExportPage(identity, input) {
|
|
|
77782
78202
|
untrustedContent: true
|
|
77783
78203
|
};
|
|
77784
78204
|
}
|
|
77785
|
-
var
|
|
78205
|
+
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
78206
|
var init_nango_control = __esm({
|
|
77787
78207
|
"src/api/nango-control.ts"() {
|
|
77788
78208
|
"use strict";
|
|
77789
|
-
|
|
78209
|
+
import_node_crypto60 = require("crypto");
|
|
77790
78210
|
init_connected_data_export();
|
|
77791
78211
|
init_slack_connected_data_export();
|
|
77792
78212
|
init_main_nango_transport();
|
|
@@ -78142,7 +78562,7 @@ async function callResendRead(identity, connectionId, tool, args) {
|
|
|
78142
78562
|
return isRecord5(data) ? data.result ?? data : data;
|
|
78143
78563
|
}
|
|
78144
78564
|
async function callResendAction(identity, connectionId, tool, input, idempotencyKey3) {
|
|
78145
|
-
const requestId = `main-resend-action:${(0,
|
|
78565
|
+
const requestId = `main-resend-action:${(0, import_node_crypto61.createHash)("sha256").update(identity).update("\0").update(idempotencyKey3.trim()).digest("hex")}`;
|
|
78146
78566
|
const body = await controlRequest2("/api/internal/resend/actions/call", {
|
|
78147
78567
|
method: "POST",
|
|
78148
78568
|
headers: { "x-request-id": requestId },
|
|
@@ -78207,12 +78627,12 @@ async function callResendExportPage(identity, input) {
|
|
|
78207
78627
|
untrustedContent: true
|
|
78208
78628
|
};
|
|
78209
78629
|
}
|
|
78210
|
-
var
|
|
78630
|
+
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
78631
|
var init_resend_control = __esm({
|
|
78212
78632
|
"src/api/resend-control.ts"() {
|
|
78213
78633
|
"use strict";
|
|
78214
78634
|
init_connected_data_export();
|
|
78215
|
-
|
|
78635
|
+
import_node_crypto61 = require("crypto");
|
|
78216
78636
|
DEFAULT_CONNECTION_CONTROL_URL = "https://mcp-scraper-scheduler.vercel.app";
|
|
78217
78637
|
RESEND_PROVIDER_CONFIG_KEY = "resend";
|
|
78218
78638
|
RESEND_LOGO_URL = "https://cdn.resend.com/brand/resend-icon-black.svg";
|
|
@@ -78797,7 +79217,7 @@ function settleWithinTickBudget(label, unfinished, work, onDeadlineOrError) {
|
|
|
78797
79217
|
);
|
|
78798
79218
|
});
|
|
78799
79219
|
}
|
|
78800
|
-
var import_resend3,
|
|
79220
|
+
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
79221
|
var init_server = __esm({
|
|
78802
79222
|
"src/api/server.ts"() {
|
|
78803
79223
|
"use strict";
|
|
@@ -78810,7 +79230,7 @@ var init_server = __esm({
|
|
|
78810
79230
|
init_og();
|
|
78811
79231
|
import_resend3 = require("resend");
|
|
78812
79232
|
init_url_utils();
|
|
78813
|
-
|
|
79233
|
+
import_node_crypto62 = require("crypto");
|
|
78814
79234
|
init_kpo_extractor();
|
|
78815
79235
|
init_screenshot();
|
|
78816
79236
|
init_media_extractor();
|
|
@@ -80360,7 +80780,7 @@ var init_server = __esm({
|
|
|
80360
80780
|
if (!harvestOk) return c.json(insufficientBalanceResponse(harvestBal, harvestCost), 402);
|
|
80361
80781
|
jobId2 = await createJob(user.id, options.query, { ...options, billingHoldMc: harvestCost }, body.callback_url);
|
|
80362
80782
|
} else {
|
|
80363
|
-
jobId2 = (0,
|
|
80783
|
+
jobId2 = (0, import_node_crypto62.randomUUID)();
|
|
80364
80784
|
const billingDebitKey = `paa-harvest:${jobId2}:hold`;
|
|
80365
80785
|
const description = `PAA harvest: ${options.query}`.slice(0, 500);
|
|
80366
80786
|
const hold = await debitMcIdempotent(
|