@farm.js/core 0.1.0-beta.97 → 0.1.0-beta.99
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/dist/after.cjs.map +1 -0
- package/dist/agent-runtime.cjs +7 -3
- package/dist/agent-runtime.cjs.map +1 -0
- package/dist/agent-runtime.d.mts +2 -2
- package/dist/agent-runtime.d.ts +2 -2
- package/dist/agent-runtime.mjs +2 -1
- package/dist/agent-runtime.mjs.map +1 -1
- package/dist/api/route-manager.cjs.map +1 -0
- package/dist/api/route-manager.d.mts +2 -2
- package/dist/api/route-manager.d.ts +2 -2
- package/dist/api/runtime.cjs.map +1 -0
- package/dist/api.cjs +26 -1
- package/dist/api.cjs.map +1 -0
- package/dist/api.d.mts +3 -3
- package/dist/api.d.ts +3 -3
- package/dist/api.mjs +2 -2
- package/dist/{app-CIOx3LvY.d.ts → app-CGjrKNoN.d.ts} +4 -4
- package/dist/{app-DBd6437H.d.mts → app-DOcLs_iq.d.mts} +4 -4
- package/dist/app-markdown.cjs +21 -0
- package/dist/app-markdown.cjs.map +1 -0
- package/dist/app-markdown.d.mts +19 -4
- package/dist/app-markdown.d.ts +19 -4
- package/dist/app-markdown.mjs +7 -1
- package/dist/cache.cjs.map +1 -0
- package/dist/{chunk-VMCHLH3Y.mjs → chunk-26BCDVJS.mjs} +19 -1
- package/dist/chunk-26BCDVJS.mjs.map +1 -0
- package/dist/{chunk-FP5Q67FO.mjs → chunk-2HYYZCCI.mjs} +308 -19
- package/dist/chunk-2HYYZCCI.mjs.map +1 -0
- package/dist/{chunk-WKDAA6V2.mjs → chunk-3BTAMIQE.mjs} +100 -41
- package/dist/chunk-3BTAMIQE.mjs.map +1 -0
- package/dist/{chunk-WD2EBM3I.mjs → chunk-3CQJV3NC.mjs} +2 -2
- package/dist/{chunk-I3OOUWO5.mjs → chunk-3GDRV7SG.mjs} +2 -2
- package/dist/{chunk-YIBV77KZ.mjs → chunk-4WLAVHCY.mjs} +2 -2
- package/dist/{chunk-KDP5ZSWP.mjs → chunk-7PS5NKOM.mjs} +26 -11
- package/dist/chunk-7PS5NKOM.mjs.map +1 -0
- package/dist/{chunk-X4SFHKFH.mjs → chunk-BU65A3LZ.mjs} +10 -6
- package/dist/chunk-BU65A3LZ.mjs.map +1 -0
- package/dist/{chunk-WMJGA32P.mjs → chunk-BXVOHG6B.mjs} +27 -2
- package/dist/{chunk-WMJGA32P.mjs.map → chunk-BXVOHG6B.mjs.map} +1 -1
- package/dist/{chunk-BZAIS65C.mjs → chunk-DIHNOVZZ.mjs} +40 -13
- package/dist/chunk-DIHNOVZZ.mjs.map +1 -0
- package/dist/{chunk-ISSFLGJ5.mjs → chunk-FDWECN3W.mjs} +8 -4
- package/dist/chunk-FDWECN3W.mjs.map +1 -0
- package/dist/chunk-FDWXXTWR.mjs +114 -0
- package/dist/chunk-FDWXXTWR.mjs.map +1 -0
- package/dist/{chunk-FSIXEIOB.mjs → chunk-L7FSTPGS.mjs} +2 -2
- package/dist/{chunk-J3MPQ4MQ.mjs → chunk-LG4XB6RN.mjs} +2 -2
- package/dist/{chunk-J3MPQ4MQ.mjs.map → chunk-LG4XB6RN.mjs.map} +1 -1
- package/dist/{chunk-AAC66ILR.mjs → chunk-LXXG3K2Y.mjs} +61 -2
- package/dist/chunk-LXXG3K2Y.mjs.map +1 -0
- package/dist/{chunk-GJ7W6LNK.mjs → chunk-N5RK4LK6.mjs} +3 -3
- package/dist/{chunk-D7F7YZ7L.mjs → chunk-NCVFPT67.mjs} +100 -40
- package/dist/{chunk-D7F7YZ7L.mjs.map → chunk-NCVFPT67.mjs.map} +1 -1
- package/dist/{chunk-UMUWR5XA.mjs → chunk-PURU7FXR.mjs} +2 -2
- package/dist/{chunk-2SKCXYLB.mjs → chunk-QQCCBMTH.mjs} +60 -6
- package/dist/chunk-QQCCBMTH.mjs.map +1 -0
- package/dist/chunk-RKUPOYQV.mjs +28 -0
- package/dist/chunk-RKUPOYQV.mjs.map +1 -0
- package/dist/{chunk-52BR7LTX.mjs → chunk-STSPSJUI.mjs} +3 -3
- package/dist/{chunk-EPDIF432.mjs → chunk-UOGX6UNO.mjs} +37 -17
- package/dist/chunk-UOGX6UNO.mjs.map +1 -0
- package/dist/{chunk-IZBX2TEU.mjs → chunk-VQG3QWWK.mjs} +2 -2
- package/dist/{chunk-35NPLKQJ.mjs → chunk-XWM2C267.mjs} +21 -105
- package/dist/chunk-XWM2C267.mjs.map +1 -0
- package/dist/{chunk-7ZVN3YZI.mjs → chunk-Z5ARESQG.mjs} +43 -1
- package/dist/chunk-Z5ARESQG.mjs.map +1 -0
- package/dist/client/lifecycle.cjs.map +1 -0
- package/dist/client/lifecycle.mjs +2 -2
- package/dist/{client-plugins-B6-07YmP.d.mts → client-plugins-BqtHoJ9C.d.mts} +91 -3
- package/dist/{client-plugins-By6MVUX-.d.ts → client-plugins-DYprkCKN.d.ts} +91 -3
- package/dist/client-plugins.cjs +1 -1
- package/dist/client-plugins.cjs.map +1 -0
- package/dist/client-plugins.d.mts +2 -2
- package/dist/client-plugins.d.ts +2 -2
- package/dist/client-plugins.mjs +2 -2
- package/dist/client.cjs +61 -16
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.mts +5 -5
- package/dist/client.d.ts +5 -5
- package/dist/client.mjs +7 -7
- package/dist/config.cjs.map +1 -0
- package/dist/config.d.mts +2 -2
- package/dist/config.d.ts +2 -2
- package/dist/cron.cjs +48 -12
- package/dist/cron.cjs.map +1 -0
- package/dist/cron.mjs +2 -1
- package/dist/deferred.cjs.map +1 -0
- package/dist/deployment.cjs.map +1 -0
- package/dist/{devtools-XWZX6CCL.mjs → devtools-24N3U5IG.mjs} +9 -7
- package/dist/{devtools-XWZX6CCL.mjs.map → devtools-24N3U5IG.mjs.map} +1 -1
- package/dist/docs.cjs +7 -3
- package/dist/docs.cjs.map +1 -0
- package/dist/docs.mjs +9 -7
- package/dist/env-types.cjs.map +1 -0
- package/dist/env.cjs.map +1 -0
- package/dist/environment/vite.cjs.map +1 -0
- package/dist/environment.cjs.map +1 -0
- package/dist/font.cjs.map +1 -0
- package/dist/headers.cjs.map +1 -0
- package/dist/i18n/client.cjs.map +1 -0
- package/dist/i18n/index.cjs.map +1 -0
- package/dist/i18n/server.cjs.map +1 -0
- package/dist/image/server.cjs +99 -40
- package/dist/image/server.cjs.map +1 -0
- package/dist/image/server.d.mts +6 -0
- package/dist/image/server.d.ts +6 -0
- package/dist/image/server.mjs +1 -1
- package/dist/image/sharp.cjs +1 -0
- package/dist/image/sharp.cjs.map +1 -0
- package/dist/image/sharp.d.mts +1 -1
- package/dist/image/sharp.d.ts +1 -1
- package/dist/image/sharp.mjs +1 -1
- package/dist/image/sharp.mjs.map +1 -1
- package/dist/image.cjs.map +1 -0
- package/dist/index.cjs +943 -231
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.mjs +38 -24
- package/dist/index.mjs.map +1 -1
- package/dist/instrumentation.cjs.map +1 -0
- package/dist/{integration-orm-LLW6WZNK.mjs → integration-orm-G5BPBT5X.mjs} +3 -3
- package/dist/integrations.cjs +168 -5
- package/dist/integrations.cjs.map +1 -0
- package/dist/integrations.d.mts +2 -2
- package/dist/integrations.d.ts +2 -2
- package/dist/integrations.mjs +10 -3
- package/dist/internal/build-runtime.cjs +745 -139
- package/dist/internal/build-runtime.cjs.map +1 -0
- package/dist/internal/build-runtime.d.mts +4 -4
- package/dist/internal/build-runtime.d.ts +4 -4
- package/dist/internal/build-runtime.mjs +16 -14
- package/dist/internal/client-runtime.cjs +7 -2
- package/dist/internal/client-runtime.cjs.map +1 -0
- package/dist/internal/client-runtime.mjs +8 -3
- package/dist/internal/client-runtime.mjs.map +1 -1
- package/dist/internal/config-runtime.cjs +59 -42
- package/dist/internal/config-runtime.cjs.map +1 -0
- package/dist/internal/config-runtime.d.mts +3 -3
- package/dist/internal/config-runtime.d.ts +3 -3
- package/dist/internal/config-runtime.mjs +8 -6
- package/dist/internal/isolated-boundary.cjs.map +1 -0
- package/dist/internal/metadata-image-runtime.cjs.map +1 -0
- package/dist/internal/product-telemetry-runtime.cjs +52 -5
- package/dist/internal/product-telemetry-runtime.cjs.map +1 -0
- package/dist/internal/product-telemetry-runtime.d.mts +12 -1
- package/dist/internal/product-telemetry-runtime.d.ts +12 -1
- package/dist/internal/product-telemetry-runtime.mjs +50 -5
- package/dist/internal/product-telemetry-runtime.mjs.map +1 -1
- package/dist/internal/production-node-env.cjs.map +1 -0
- package/dist/internal/production-runtime.cjs +56 -10
- package/dist/internal/production-runtime.cjs.map +1 -0
- package/dist/internal/production-runtime.d.mts +8 -8
- package/dist/internal/production-runtime.d.ts +8 -8
- package/dist/internal/production-runtime.mjs +2 -2
- package/dist/markdown.cjs.map +1 -0
- package/dist/{metadata-route-8_V3UonT.d.ts → metadata-route-D2be_0kC.d.ts} +17 -2
- package/dist/{metadata-route-CWP_HjGU.d.mts → metadata-route-Dw5CrDIZ.d.mts} +17 -2
- package/dist/middleware.cjs.map +1 -0
- package/dist/middleware.d.mts +4 -4
- package/dist/middleware.d.ts +4 -4
- package/dist/navigation.cjs.map +1 -0
- package/dist/{nitro-EGRNOB5P.mjs → nitro-YJEP3FWM.mjs} +4 -3
- package/dist/{nitro-EGRNOB5P.mjs.map → nitro-YJEP3FWM.mjs.map} +1 -1
- package/dist/observability.cjs.map +1 -0
- package/dist/plugin.cjs +599 -104
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.mts +2 -2
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.mjs +13 -11
- package/dist/{production-runtime-CdmzsDax.d.ts → production-runtime-CTqpD1C8.d.ts} +2 -2
- package/dist/{production-runtime-BGRH1dKG.d.mts → production-runtime-HNqNZd4D.d.mts} +2 -2
- package/dist/query/client.cjs.map +1 -0
- package/dist/query/index.cjs.map +1 -0
- package/dist/query/parsers.cjs.map +1 -0
- package/dist/query/server.cjs.map +1 -0
- package/dist/{render-plan-DLxJYAA5.d.mts → render-plan-COscpW-i.d.mts} +1 -1
- package/dist/{render-plan-0GeHiGVZ.d.ts → render-plan-Z4kSxaT_.d.ts} +1 -1
- package/dist/renderer/react/client.cjs.map +1 -0
- package/dist/renderer/react/server.cjs.map +1 -0
- package/dist/renderer/react/vite.cjs.map +1 -0
- package/dist/renderer-client.cjs +26 -1
- package/dist/renderer-client.cjs.map +1 -0
- package/dist/renderer-client.d.mts +4 -4
- package/dist/renderer-client.d.ts +4 -4
- package/dist/renderer-client.mjs +2 -2
- package/dist/renderer.cjs.map +1 -0
- package/dist/{request-BstWbZ6O.d.ts → request-BEDb2jE9.d.ts} +1 -1
- package/dist/{request-BCNXSXLh.d.mts → request-CbIAqJY9.d.mts} +1 -1
- package/dist/request.cjs.map +1 -0
- package/dist/request.d.mts +3 -3
- package/dist/request.d.ts +3 -3
- package/dist/router.cjs.map +1 -0
- package/dist/routes.cjs.map +1 -0
- package/dist/routes.d.mts +2 -2
- package/dist/routes.d.ts +2 -2
- package/dist/server-action-security.cjs +117 -104
- package/dist/server-action-security.cjs.map +1 -0
- package/dist/server-action-security.mjs +2 -1
- package/dist/server-fn-client.cjs.map +1 -0
- package/dist/server-fn.cjs.map +1 -0
- package/dist/server-fn.mjs +3 -2
- package/dist/server-plugins.cjs.map +1 -0
- package/dist/server-plugins.d.mts +3 -3
- package/dist/server-plugins.d.ts +3 -3
- package/dist/server-query-client.cjs +26 -1
- package/dist/server-query-client.cjs.map +1 -0
- package/dist/server-query-client.mjs +3 -3
- package/dist/server-query.cjs.map +1 -0
- package/dist/server-query.mjs +4 -3
- package/dist/server.cjs +686 -170
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.mts +8 -8
- package/dist/server.d.ts +8 -8
- package/dist/server.mjs +16 -14
- package/dist/server.mjs.map +1 -1
- package/dist/{spa-router-COgu4txb.d.ts → spa-router-CjeQites.d.ts} +1 -1
- package/dist/{spa-router-BeyAVSc6.d.mts → spa-router-FJbNou1a.d.mts} +1 -1
- package/dist/storage.cjs +7 -3
- package/dist/storage.cjs.map +1 -0
- package/dist/storage.mjs +1 -1
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.mts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.mjs +2 -1
- package/dist/testing.mjs.map +1 -1
- package/dist/theme/client.cjs.map +1 -0
- package/dist/theme/index.cjs.map +1 -0
- package/dist/theme/runtime.cjs.map +1 -0
- package/dist/theme/server.cjs.map +1 -0
- package/dist/{utils-DL2VwDQl.d.mts → utils-BiMJv9Ys.d.mts} +1 -1
- package/dist/{utils-DkU2c_1B.d.ts → utils-BpnKRFv9.d.ts} +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -0
- package/dist/version.mjs +1 -1
- package/dist/vite.cjs +599 -104
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.mts +2 -2
- package/dist/vite.d.ts +2 -2
- package/dist/vite.mjs +13 -11
- package/dist/{workflows-ChyK_oTu.d.mts → workflows-BantWytQ.d.mts} +7 -0
- package/dist/{workflows-ChyK_oTu.d.ts → workflows-BantWytQ.d.ts} +7 -0
- package/dist/workflows.cjs +73 -5
- package/dist/workflows.cjs.map +1 -0
- package/dist/workflows.d.mts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/dist/workflows.mjs +2 -1
- package/package.json +17 -17
- package/dist/chunk-2SKCXYLB.mjs.map +0 -1
- package/dist/chunk-35NPLKQJ.mjs.map +0 -1
- package/dist/chunk-7ZVN3YZI.mjs.map +0 -1
- package/dist/chunk-AAC66ILR.mjs.map +0 -1
- package/dist/chunk-BZAIS65C.mjs.map +0 -1
- package/dist/chunk-EPDIF432.mjs.map +0 -1
- package/dist/chunk-FP5Q67FO.mjs.map +0 -1
- package/dist/chunk-ISSFLGJ5.mjs.map +0 -1
- package/dist/chunk-KDP5ZSWP.mjs.map +0 -1
- package/dist/chunk-VMCHLH3Y.mjs.map +0 -1
- package/dist/chunk-WKDAA6V2.mjs.map +0 -1
- package/dist/chunk-X4SFHKFH.mjs.map +0 -1
- /package/dist/{chunk-WD2EBM3I.mjs.map → chunk-3CQJV3NC.mjs.map} +0 -0
- /package/dist/{chunk-I3OOUWO5.mjs.map → chunk-3GDRV7SG.mjs.map} +0 -0
- /package/dist/{chunk-YIBV77KZ.mjs.map → chunk-4WLAVHCY.mjs.map} +0 -0
- /package/dist/{chunk-FSIXEIOB.mjs.map → chunk-L7FSTPGS.mjs.map} +0 -0
- /package/dist/{chunk-GJ7W6LNK.mjs.map → chunk-N5RK4LK6.mjs.map} +0 -0
- /package/dist/{chunk-UMUWR5XA.mjs.map → chunk-PURU7FXR.mjs.map} +0 -0
- /package/dist/{chunk-52BR7LTX.mjs.map → chunk-STSPSJUI.mjs.map} +0 -0
- /package/dist/{chunk-IZBX2TEU.mjs.map → chunk-VQG3QWWK.mjs.map} +0 -0
- /package/dist/{integration-orm-LLW6WZNK.mjs.map → integration-orm-G5BPBT5X.mjs.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/product-telemetry.ts"],"sourcesContent":["import { FARM_VERSION } from \"./version\";\n\nexport const FARM_PRODUCTION_SITE_TELEMETRY_SCHEMA_VERSION = 1 as const;\nexport const FARM_PRODUCTION_SITE_TELEMETRY_EVENT_TYPE = \"production_site_active\" as const;\nexport const FARM_PRODUCTION_SITE_TELEMETRY_PACKAGE_NAME = \"@farm.js/core\" as const;\n\nconst DEFAULT_SITE_TELEMETRY_ENDPOINT = \"https://farmjs.dev/api/telemetry/v1/sites\";\nconst REQUEST_TIMEOUT_MS = 3_000;\nconst REPORT_INTERVAL_MS = 24 * 60 * 60 * 1_000;\nconst RETRY_INTERVAL_MS = 5 * 60 * 1_000;\nconst MAX_ORIGINS_PER_INSTANCE = 32;\nconst SAFE_DETAIL_PATTERN = /^[0-9A-Za-z._-]{1,64}$/;\n\nexport interface FarmProductionSiteTelemetryPayload {\n schemaVersion: typeof FARM_PRODUCTION_SITE_TELEMETRY_SCHEMA_VERSION;\n eventType: typeof FARM_PRODUCTION_SITE_TELEMETRY_EVENT_TYPE;\n siteUrl: string;\n packageName: typeof FARM_PRODUCTION_SITE_TELEMETRY_PACKAGE_NAME;\n packageVersion: string;\n renderer: string;\n deployTarget: string;\n}\n\ninterface FarmProductionSiteReporterOptions {\n renderer: string;\n deployTarget?: string;\n endpoint?: string;\n fetch?: typeof fetch;\n now?: () => number;\n reportIntervalMs?: number;\n retryIntervalMs?: number;\n}\n\ninterface OriginReportState {\n pending?: Promise<void>;\n nextReportAt: number;\n}\n\nexport interface FarmProductionSiteReporter {\n report(requestUrl: string | URL, waitUntil?: (promise: Promise<unknown>) => void): void;\n}\n\n/**\n * Reduce an automatically observed request URL to a public HTTPS origin.\n * Request paths, query strings, hashes, and credentials are never returned.\n */\nexport function detectFarmProductionSiteOrigin(value: string | URL): string | undefined {\n try {\n const url = value instanceof URL ? value : new URL(value);\n return normalizeFarmProductionSiteOrigin(url.origin);\n } catch {\n return undefined;\n }\n}\n\n/** Normalize and validate the origin-only value accepted by the ingestion service. */\nexport function normalizeFarmProductionSiteOrigin(value: string): string | undefined {\n const candidate = value.trim();\n if (!candidate || candidate.length > 2_048) return undefined;\n\n try {\n const url = new URL(candidate);\n const hostname = url.hostname.toLowerCase();\n const isIpv4 = /^\\d{1,3}(?:\\.\\d{1,3}){3}$/.test(hostname);\n const isIpv6 = hostname.startsWith(\"[\") && hostname.endsWith(\"]\");\n const isLocal =\n hostname === \"localhost\" || hostname.endsWith(\".localhost\") || hostname.endsWith(\".local\");\n const isSingleLabel = !hostname.includes(\".\");\n\n if (\n url.protocol !== \"https:\" ||\n url.username ||\n url.password ||\n url.search ||\n url.hash ||\n url.pathname !== \"/\" ||\n isIpv4 ||\n isIpv6 ||\n isLocal ||\n isSingleLabel ||\n hostname.endsWith(\".\")\n ) {\n return undefined;\n }\n\n return url.origin;\n } catch {\n return undefined;\n }\n}\n\nexport function createFarmProductionSiteReporter(\n options: FarmProductionSiteReporterOptions,\n): FarmProductionSiteReporter {\n const now = options.now ?? Date.now;\n const reportIntervalMs = options.reportIntervalMs ?? REPORT_INTERVAL_MS;\n const retryIntervalMs = options.retryIntervalMs ?? RETRY_INTERVAL_MS;\n const send = options.fetch ?? globalThis.fetch;\n const reportStates = new Map<string, OriginReportState>();\n\n return {\n report(requestUrl, waitUntil) {\n if (productionTelemetryDisabled()) return;\n if (!isProductionDeploymentEnvironment()) {\n debug(\"production-site check-in skipped outside a production deployment\");\n return;\n }\n\n const siteUrl = detectFarmProductionSiteOrigin(requestUrl);\n if (!siteUrl) return;\n\n let state = reportStates.get(siteUrl);\n if (!state) {\n if (reportStates.size >= MAX_ORIGINS_PER_INSTANCE) return;\n state = { nextReportAt: 0 };\n reportStates.set(siteUrl, state);\n }\n\n const attemptedAt = now();\n if (state.pending || attemptedAt < state.nextReportAt) return;\n\n state.nextReportAt = attemptedAt + reportIntervalMs;\n const payload: FarmProductionSiteTelemetryPayload = {\n schemaVersion: FARM_PRODUCTION_SITE_TELEMETRY_SCHEMA_VERSION,\n eventType: FARM_PRODUCTION_SITE_TELEMETRY_EVENT_TYPE,\n siteUrl,\n packageName: FARM_PRODUCTION_SITE_TELEMETRY_PACKAGE_NAME,\n packageVersion: sanitizeDetail(FARM_VERSION, \"unknown\"),\n renderer: sanitizeDetail(options.renderer, \"custom\"),\n deployTarget: sanitizeDetail(options.deployTarget, \"custom\"),\n };\n state.pending = deliver(send, resolveSiteTelemetryEndpoint(options.endpoint), payload)\n .then((delivered) => {\n if (!delivered) state.nextReportAt = now() + retryIntervalMs;\n })\n .catch(() => {\n state.nextReportAt = now() + retryIntervalMs;\n })\n .finally(() => {\n state.pending = undefined;\n });\n\n if (waitUntil) {\n try {\n waitUntil(state.pending);\n } catch {\n // Delivery remains best-effort if a platform rejects background work.\n }\n } else {\n void state.pending;\n }\n },\n };\n}\n\nasync function deliver(\n send: typeof fetch,\n endpoint: string | undefined,\n payload: FarmProductionSiteTelemetryPayload,\n): Promise<boolean> {\n if (!endpoint) {\n debug(\"invalid or insecure production-site telemetry endpoint; check-in skipped\");\n return false;\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n timeout.unref?.();\n try {\n const response = await send(endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n if (!response.ok) {\n debug(`production-site check-in rejected with HTTP ${response.status}`);\n return false;\n }\n try {\n const result = (await response.json()) as { stored?: unknown };\n if (result && result.stored === false) {\n debug(\"production-site check-in was accepted but not stored\");\n return false;\n }\n } catch {\n // A successful empty response is also a valid acknowledgement.\n }\n return true;\n } catch {\n debug(\"production-site check-in failed\");\n return false;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction resolveSiteTelemetryEndpoint(explicit?: string): string | undefined {\n const candidate = explicit || process.env.FARM_TELEMETRY_SITE_ENDPOINT;\n if (!candidate) return DEFAULT_SITE_TELEMETRY_ENDPOINT;\n\n try {\n const url = new URL(candidate);\n const hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, \"\");\n const isLocal = [\"localhost\", \"127.0.0.1\", \"::1\"].includes(hostname);\n if (url.protocol === \"https:\" || (url.protocol === \"http:\" && isLocal)) {\n return url.toString();\n }\n } catch {\n // Invalid explicit overrides fail closed below.\n }\n return undefined;\n}\n\nfunction productionTelemetryDisabled(): boolean {\n if (process.env.DO_NOT_TRACK !== undefined && !isFalse(process.env.DO_NOT_TRACK)) return true;\n if (isTrue(process.env.FARM_TELEMETRY_DISABLED)) return true;\n return isFalse(process.env.FARM_TELEMETRY);\n}\n\n/**\n * Vercel exposes the deployment environment at build and runtime. Only its\n * production environment represents a production site; preview, development,\n * and custom targets must not create dashboard entries. Other deployment\n * providers remain eligible when no Vercel environment metadata is present.\n */\nfunction isProductionDeploymentEnvironment(): boolean {\n const environment = normalizeEnvironment(process.env.VERCEL_ENV);\n const targetEnvironment = normalizeEnvironment(process.env.VERCEL_TARGET_ENV);\n\n if (!environment && !targetEnvironment) return true;\n if (environment && environment !== \"production\") return false;\n if (targetEnvironment && targetEnvironment !== \"production\") return false;\n return true;\n}\n\nfunction normalizeEnvironment(value: string | undefined): string | undefined {\n const normalized = value?.trim().toLowerCase();\n return normalized || undefined;\n}\n\nfunction sanitizeDetail(value: string | undefined, fallback: string): string {\n return value && SAFE_DETAIL_PATTERN.test(value) ? value : fallback;\n}\n\nfunction isTrue(value: string | undefined): boolean {\n return value !== undefined && [\"1\", \"true\", \"yes\", \"on\"].includes(value.toLowerCase());\n}\n\nfunction isFalse(value: string | undefined): boolean {\n return value !== undefined && [\"0\", \"false\", \"no\", \"off\"].includes(value.toLowerCase());\n}\n\nfunction debug(message: string): void {\n if (!isTrue(process.env.FARM_TELEMETRY_DEBUG)) return;\n process.stderr.write(`[farm.telemetry] ${message}\\n`);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/product-telemetry.ts"],"sourcesContent":["import { FARM_VERSION } from \"./version\";\n\nexport const FARM_PRODUCTION_SITE_TELEMETRY_SCHEMA_VERSION = 1 as const;\nexport const FARM_PRODUCTION_SITE_TELEMETRY_EVENT_TYPE = \"production_site_active\" as const;\nexport const FARM_PRODUCTION_SITE_TELEMETRY_PACKAGE_NAME = \"@farm.js/core\" as const;\nexport const FARM_PRODUCTION_SITE_ATTESTATION_PATH = \"/.well-known/farm-telemetry\" as const;\nexport const FARM_PRODUCTION_SITE_ATTESTATION_EVENT_TYPE = \"production_site_attestation\" as const;\n\nconst DEFAULT_SITE_TELEMETRY_ENDPOINT = \"https://farmjs.dev/api/telemetry/v1/sites\";\nconst REQUEST_TIMEOUT_MS = 3_000;\nconst REPORT_INTERVAL_MS = 24 * 60 * 60 * 1_000;\nconst RETRY_INTERVAL_MS = 5 * 60 * 1_000;\nconst MAX_ORIGINS_PER_INSTANCE = 32;\nconst SAFE_DETAIL_PATTERN = /^[0-9A-Za-z._-]{1,64}$/;\n\nexport interface FarmProductionSiteTelemetryPayload {\n schemaVersion: typeof FARM_PRODUCTION_SITE_TELEMETRY_SCHEMA_VERSION;\n eventType: typeof FARM_PRODUCTION_SITE_TELEMETRY_EVENT_TYPE;\n siteUrl: string;\n packageName: typeof FARM_PRODUCTION_SITE_TELEMETRY_PACKAGE_NAME;\n packageVersion: string;\n renderer: string;\n deployTarget: string;\n}\n\nexport interface FarmProductionSiteAttestation {\n schemaVersion: typeof FARM_PRODUCTION_SITE_TELEMETRY_SCHEMA_VERSION;\n eventType: typeof FARM_PRODUCTION_SITE_ATTESTATION_EVENT_TYPE;\n packageName: typeof FARM_PRODUCTION_SITE_TELEMETRY_PACKAGE_NAME;\n packageVersion: string;\n renderer: string;\n deployTarget: string;\n}\n\ninterface FarmProductionSiteReporterOptions {\n renderer: string;\n deployTarget?: string;\n endpoint?: string;\n fetch?: typeof fetch;\n now?: () => number;\n reportIntervalMs?: number;\n retryIntervalMs?: number;\n}\n\ninterface OriginReportState {\n pending?: Promise<void>;\n nextReportAt: number;\n}\n\nexport interface FarmProductionSiteReporter {\n handleAttestation(request: Request): Response | null;\n report(requestUrl: string | URL, waitUntil?: (promise: Promise<unknown>) => void): void;\n}\n\n/**\n * Reduce an automatically observed request URL to a public HTTPS origin.\n * Request paths, query strings, hashes, and credentials are never returned.\n */\nexport function detectFarmProductionSiteOrigin(value: string | URL): string | undefined {\n try {\n const url = value instanceof URL ? value : new URL(value);\n return normalizeFarmProductionSiteOrigin(url.origin);\n } catch {\n return undefined;\n }\n}\n\n/** Normalize and validate the origin-only value accepted by the ingestion service. */\nexport function normalizeFarmProductionSiteOrigin(value: string): string | undefined {\n const candidate = value.trim();\n if (!candidate || candidate.length > 2_048) return undefined;\n\n try {\n const url = new URL(candidate);\n const hostname = url.hostname.toLowerCase();\n const isIpv4 = /^\\d{1,3}(?:\\.\\d{1,3}){3}$/.test(hostname);\n const isIpv6 = hostname.startsWith(\"[\") && hostname.endsWith(\"]\");\n const isLocal =\n hostname === \"localhost\" || hostname.endsWith(\".localhost\") || hostname.endsWith(\".local\");\n const isSingleLabel = !hostname.includes(\".\");\n\n if (\n url.protocol !== \"https:\" ||\n url.username ||\n url.password ||\n url.search ||\n url.hash ||\n url.pathname !== \"/\" ||\n isIpv4 ||\n isIpv6 ||\n isLocal ||\n isSingleLabel ||\n hostname.endsWith(\".\")\n ) {\n return undefined;\n }\n\n return url.origin;\n } catch {\n return undefined;\n }\n}\n\nexport function createFarmProductionSiteReporter(\n options: FarmProductionSiteReporterOptions,\n): FarmProductionSiteReporter {\n const now = options.now ?? Date.now;\n const reportIntervalMs = options.reportIntervalMs ?? REPORT_INTERVAL_MS;\n const retryIntervalMs = options.retryIntervalMs ?? RETRY_INTERVAL_MS;\n const send = options.fetch ?? globalThis.fetch;\n const reportStates = new Map<string, OriginReportState>();\n const attestation: FarmProductionSiteAttestation = {\n schemaVersion: FARM_PRODUCTION_SITE_TELEMETRY_SCHEMA_VERSION,\n eventType: FARM_PRODUCTION_SITE_ATTESTATION_EVENT_TYPE,\n packageName: FARM_PRODUCTION_SITE_TELEMETRY_PACKAGE_NAME,\n packageVersion: sanitizeDetail(FARM_VERSION, \"unknown\"),\n renderer: sanitizeDetail(options.renderer, \"custom\"),\n deployTarget: sanitizeDetail(options.deployTarget, \"custom\"),\n };\n\n return {\n handleAttestation(request) {\n if (productionTelemetryDisabled()) return null;\n\n let pathname: string;\n try {\n pathname = new URL(request.url).pathname;\n } catch {\n return null;\n }\n if (pathname !== FARM_PRODUCTION_SITE_ATTESTATION_PATH) return null;\n\n if (request.method !== \"GET\" && request.method !== \"HEAD\") {\n return new Response(\"Method Not Allowed\", {\n status: 405,\n headers: {\n allow: \"GET, HEAD\",\n \"cache-control\": \"no-store\",\n \"content-type\": \"text/plain; charset=utf-8\",\n \"x-content-type-options\": \"nosniff\",\n },\n });\n }\n\n return new Response(request.method === \"HEAD\" ? null : JSON.stringify(attestation), {\n status: 200,\n headers: {\n \"cache-control\": \"no-store\",\n \"content-type\": \"application/json; charset=utf-8\",\n \"x-content-type-options\": \"nosniff\",\n },\n });\n },\n report(requestUrl, waitUntil) {\n if (productionTelemetryDisabled()) return;\n if (!isProductionDeploymentEnvironment()) {\n debug(\"production-site check-in skipped outside a production deployment\");\n return;\n }\n\n const siteUrl = detectFarmProductionSiteOrigin(requestUrl);\n if (!siteUrl) return;\n\n let state = reportStates.get(siteUrl);\n if (!state) {\n if (reportStates.size >= MAX_ORIGINS_PER_INSTANCE) return;\n state = { nextReportAt: 0 };\n reportStates.set(siteUrl, state);\n }\n\n const attemptedAt = now();\n if (state.pending || attemptedAt < state.nextReportAt) return;\n\n state.nextReportAt = attemptedAt + reportIntervalMs;\n const payload: FarmProductionSiteTelemetryPayload = {\n schemaVersion: FARM_PRODUCTION_SITE_TELEMETRY_SCHEMA_VERSION,\n eventType: FARM_PRODUCTION_SITE_TELEMETRY_EVENT_TYPE,\n siteUrl,\n packageName: FARM_PRODUCTION_SITE_TELEMETRY_PACKAGE_NAME,\n packageVersion: attestation.packageVersion,\n renderer: attestation.renderer,\n deployTarget: attestation.deployTarget,\n };\n state.pending = deliver(send, resolveSiteTelemetryEndpoint(options.endpoint), payload)\n .then((delivered) => {\n if (!delivered) state.nextReportAt = now() + retryIntervalMs;\n })\n .catch(() => {\n state.nextReportAt = now() + retryIntervalMs;\n })\n .finally(() => {\n state.pending = undefined;\n });\n\n if (waitUntil) {\n try {\n waitUntil(state.pending);\n } catch {\n // Delivery remains best-effort if a platform rejects background work.\n }\n } else {\n void state.pending;\n }\n },\n };\n}\n\nasync function deliver(\n send: typeof fetch,\n endpoint: string | undefined,\n payload: FarmProductionSiteTelemetryPayload,\n): Promise<boolean> {\n if (!endpoint) {\n debug(\"invalid or insecure production-site telemetry endpoint; check-in skipped\");\n return false;\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n timeout.unref?.();\n try {\n const response = await send(endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n if (!response.ok) {\n debug(`production-site check-in rejected with HTTP ${response.status}`);\n return false;\n }\n try {\n const result = (await response.json()) as { stored?: unknown };\n if (result && result.stored === false) {\n debug(\"production-site check-in was accepted but not stored\");\n return false;\n }\n } catch {\n // A successful empty response is also a valid acknowledgement.\n }\n return true;\n } catch {\n debug(\"production-site check-in failed\");\n return false;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction resolveSiteTelemetryEndpoint(explicit?: string): string | undefined {\n const candidate = explicit || process.env.FARM_TELEMETRY_SITE_ENDPOINT;\n if (!candidate) return DEFAULT_SITE_TELEMETRY_ENDPOINT;\n\n try {\n const url = new URL(candidate);\n const hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, \"\");\n const isLocal = [\"localhost\", \"127.0.0.1\", \"::1\"].includes(hostname);\n if (url.protocol === \"https:\" || (url.protocol === \"http:\" && isLocal)) {\n return url.toString();\n }\n } catch {\n // Invalid explicit overrides fail closed below.\n }\n return undefined;\n}\n\nfunction productionTelemetryDisabled(): boolean {\n if (process.env.DO_NOT_TRACK !== undefined && !isFalse(process.env.DO_NOT_TRACK)) return true;\n if (isTrue(process.env.FARM_TELEMETRY_DISABLED)) return true;\n return isFalse(process.env.FARM_TELEMETRY);\n}\n\n/**\n * Only a provider's production environment represents a production site;\n * preview, branch, and development deployments must not create dashboard\n * entries. Each provider exposes this differently, so every signal we can read\n * is checked. A deployment whose provider exposes no environment metadata stays\n * eligible, so self-hosted sites continue to report.\n *\n * Cloudflare Pages is deliberately absent: it exposes `CF_PAGES_BRANCH` for both\n * production and preview deployments and no environment flag that distinguishes\n * them, so there is nothing here that could be read without guessing.\n */\nfunction isProductionDeploymentEnvironment(): boolean {\n // Vercel exposes the deployment environment at build and runtime.\n const environment = normalizeEnvironment(process.env.VERCEL_ENV);\n const targetEnvironment = normalizeEnvironment(process.env.VERCEL_TARGET_ENV);\n if (environment && environment !== \"production\") return false;\n if (targetEnvironment && targetEnvironment !== \"production\") return false;\n\n // Netlify: CONTEXT is production | deploy-preview | branch-deploy | dev.\n // CONTEXT is a generic name, so it is only trusted when NETLIFY marks the\n // build as Netlify's.\n if (isTrue(process.env.NETLIFY)) {\n const context = normalizeEnvironment(process.env.CONTEXT);\n if (context && context !== \"production\") return false;\n }\n\n // Render marks pull-request preview services.\n if (isTrue(process.env.IS_PULL_REQUEST)) return false;\n\n return true;\n}\n\nfunction normalizeEnvironment(value: string | undefined): string | undefined {\n const normalized = value?.trim().toLowerCase();\n return normalized || undefined;\n}\n\nfunction sanitizeDetail(value: string | undefined, fallback: string): string {\n return value && SAFE_DETAIL_PATTERN.test(value) ? value : fallback;\n}\n\nfunction isTrue(value: string | undefined): boolean {\n return value !== undefined && [\"1\", \"true\", \"yes\", \"on\"].includes(value.toLowerCase());\n}\n\nfunction isFalse(value: string | undefined): boolean {\n return value !== undefined && [\"0\", \"false\", \"no\", \"off\"].includes(value.toLowerCase());\n}\n\nfunction debug(message: string): void {\n if (!isTrue(process.env.FARM_TELEMETRY_DEBUG)) return;\n process.stderr.write(`[farm.telemetry] ${message}\\n`);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/build/production-node-env.ts"],"sourcesContent":["const productionNodeEnvStateKey = Symbol.for(\"@farm.js/core/production-node-env-state\");\n\ninterface ProductionNodeEnvState {\n depth: number;\n original: string | undefined;\n}\n\nfunction getProductionNodeEnvState(): ProductionNodeEnvState | undefined {\n return Reflect.get(globalThis, productionNodeEnvStateKey) as ProductionNodeEnvState | undefined;\n}\n\n/**\n * Keep overlapping production operations on the production condition.\n *\n * The state lives on `globalThis` so independently loaded CJS/ESM copies of\n * Farm share one refcount. The first entrant captures the caller's value and\n * only the last operation to settle restores it.\n *\n * @internal\n */\nexport async function withProductionNodeEnv<T>(operation: () => T | PromiseLike<T>): Promise<T> {\n let state = getProductionNodeEnvState();\n\n if (state) {\n state.depth += 1;\n } else {\n state = {\n depth: 1,\n original: process.env.NODE_ENV,\n };\n Reflect.set(globalThis, productionNodeEnvStateKey, state);\n }\n\n process.env.NODE_ENV = \"production\";\n\n try {\n return await operation();\n } finally {\n state.depth -= 1;\n\n if (state.depth > 0) {\n // A nested operation may have changed NODE_ENV. Keep the remaining\n // production scopes pinned until the final scope settles.\n process.env.NODE_ENV = \"production\";\n } else {\n Reflect.deleteProperty(globalThis, productionNodeEnvStateKey);\n if (state.original === undefined) {\n delete process.env.NODE_ENV;\n } else {\n process.env.NODE_ENV = state.original;\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAM,4BAA4B,uBAAO,IAAI,yCAAyC;AAOtF,SAAS,4BAAgE;AACvE,SAAO,QAAQ,IAAI,YAAY,yBAAyB;AAC1D;AAFS;AAaT,eAAsB,sBAAyB,WAAiD;AAC9F,MAAI,QAAQ,0BAA0B;AAEtC,MAAI,OAAO;AACT,UAAM,SAAS;AAAA,EACjB,OAAO;AACL,YAAQ;AAAA,MACN,OAAO;AAAA,MACP,UAAU,QAAQ,IAAI;AAAA,IACxB;AACA,YAAQ,IAAI,YAAY,2BAA2B,KAAK;AAAA,EAC1D;AAEA,UAAQ,IAAI,WAAW;AAEvB,MAAI;AACF,WAAO,MAAM,UAAU;AAAA,EACzB,UAAE;AACA,UAAM,SAAS;AAEf,QAAI,MAAM,QAAQ,GAAG;AAGnB,cAAQ,IAAI,WAAW;AAAA,IACzB,OAAO;AACL,cAAQ,eAAe,YAAY,yBAAyB;AAC5D,UAAI,MAAM,aAAa,QAAW;AAChC,eAAO,QAAQ,IAAI;AAAA,MACrB,OAAO;AACL,gBAAQ,IAAI,WAAW,MAAM;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACF;AAjCsB;","names":[]}
|
|
@@ -2417,6 +2417,40 @@ function capitalize(value) {
|
|
|
2417
2417
|
}
|
|
2418
2418
|
__name(capitalize, "capitalize");
|
|
2419
2419
|
|
|
2420
|
+
// src/agent-config.ts
|
|
2421
|
+
function pruneUndefined(object) {
|
|
2422
|
+
const result = {};
|
|
2423
|
+
for (const [key, value] of Object.entries(object)) {
|
|
2424
|
+
if (value !== void 0 && value !== null && value !== "") result[key] = value;
|
|
2425
|
+
}
|
|
2426
|
+
return result;
|
|
2427
|
+
}
|
|
2428
|
+
__name(pruneUndefined, "pruneUndefined");
|
|
2429
|
+
function serializeJsonLd(value) {
|
|
2430
|
+
return JSON.stringify(value).replace(/</g, "\\u003c");
|
|
2431
|
+
}
|
|
2432
|
+
__name(serializeJsonLd, "serializeJsonLd");
|
|
2433
|
+
function renderFarmAgentJsonLd(config, context2) {
|
|
2434
|
+
const base = pruneUndefined({
|
|
2435
|
+
name: config.name ?? context2.siteName ?? context2.title,
|
|
2436
|
+
url: config.url ?? context2.metadataBase,
|
|
2437
|
+
description: config.description ?? context2.description,
|
|
2438
|
+
logo: config.logo,
|
|
2439
|
+
sameAs: config.sameAs && config.sameAs.length > 0 ? config.sameAs : void 0
|
|
2440
|
+
});
|
|
2441
|
+
const object = {
|
|
2442
|
+
"@context": "https://schema.org",
|
|
2443
|
+
"@type": config.type || "Organization",
|
|
2444
|
+
...base,
|
|
2445
|
+
...config.properties || {}
|
|
2446
|
+
};
|
|
2447
|
+
if (Object.keys(object).length <= 2 && !config.properties) {
|
|
2448
|
+
return "";
|
|
2449
|
+
}
|
|
2450
|
+
return `<script type="application/ld+json">${serializeJsonLd(object)}</script>`;
|
|
2451
|
+
}
|
|
2452
|
+
__name(renderFarmAgentJsonLd, "renderFarmAgentJsonLd");
|
|
2453
|
+
|
|
2420
2454
|
// src/metadata.ts
|
|
2421
2455
|
function mergeMetadata(base, next) {
|
|
2422
2456
|
if (!base) return next ? { ...next } : {};
|
|
@@ -2480,7 +2514,7 @@ function addMetadataImageReference(metadata, reference) {
|
|
|
2480
2514
|
};
|
|
2481
2515
|
}
|
|
2482
2516
|
__name(addMetadataImageReference, "addMetadataImageReference");
|
|
2483
|
-
function renderMetadataHead(metadata) {
|
|
2517
|
+
function renderMetadataHead(metadata, options = {}) {
|
|
2484
2518
|
const resolvedMetadata = metadata || {};
|
|
2485
2519
|
const metadataBase = resolveMetadataBase(resolvedMetadata);
|
|
2486
2520
|
const explicitTitle = resolveMetadataTitle(resolvedMetadata.title);
|
|
@@ -2501,14 +2535,16 @@ function renderMetadataHead(metadata) {
|
|
|
2501
2535
|
appendMetaName(tags, "publisher", resolvedMetadata.publisher);
|
|
2502
2536
|
appendMetaName(tags, "robots", normalizeRobots(resolvedMetadata.robots));
|
|
2503
2537
|
const alternates = resolvedMetadata.alternates;
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2538
|
+
const explicitCanonical = isRecord(alternates) ? alternates.canonical : void 0;
|
|
2539
|
+
const canonicalHref = explicitCanonical != null ? resolveMetadataUrl(explicitCanonical, metadataBase) : options.pathname ? resolveMetadataUrl(options.pathname, metadataBase) : void 0;
|
|
2540
|
+
if (canonicalHref) {
|
|
2541
|
+
appendLink(tags, "canonical", canonicalHref);
|
|
2542
|
+
}
|
|
2543
|
+
if (isRecord(alternates) && isRecord(alternates.languages)) {
|
|
2544
|
+
for (const [language, href] of Object.entries(alternates.languages)) {
|
|
2545
|
+
appendLink(tags, "alternate", resolveMetadataUrl(href, metadataBase), {
|
|
2546
|
+
hreflang: language
|
|
2547
|
+
});
|
|
2512
2548
|
}
|
|
2513
2549
|
}
|
|
2514
2550
|
const hasFavicon = appendIcons(tags, resolvedMetadata.icons, metadataBase);
|
|
@@ -2521,6 +2557,16 @@ function renderMetadataHead(metadata) {
|
|
|
2521
2557
|
}
|
|
2522
2558
|
appendOpenGraph(tags, resolvedMetadata.openGraph, metadataBase);
|
|
2523
2559
|
appendTwitter(tags, resolvedMetadata.twitter, metadataBase);
|
|
2560
|
+
if (options.jsonLd) {
|
|
2561
|
+
const jsonLdConfig = options.jsonLd === true ? {} : options.jsonLd;
|
|
2562
|
+
const jsonLdScript = renderFarmAgentJsonLd(jsonLdConfig, {
|
|
2563
|
+
metadataBase,
|
|
2564
|
+
siteName: isRecord(resolvedMetadata.openGraph) ? normalizeContent(resolvedMetadata.openGraph.siteName) : void 0,
|
|
2565
|
+
title: explicitTitle,
|
|
2566
|
+
description: normalizeContent(resolvedMetadata.description)
|
|
2567
|
+
});
|
|
2568
|
+
if (jsonLdScript) tags.push(jsonLdScript);
|
|
2569
|
+
}
|
|
2524
2570
|
return {
|
|
2525
2571
|
title: escapeText(title),
|
|
2526
2572
|
tags: tags.length > 0 ? `
|
|
@@ -2546,7 +2592,7 @@ function appendOpenGraph(tags, openGraph, metadataBase) {
|
|
|
2546
2592
|
appendMetaProperty(tags, "og:description", openGraph.description);
|
|
2547
2593
|
appendMetaProperty(tags, "og:url", resolveMetadataUrl(openGraph.url, metadataBase));
|
|
2548
2594
|
appendMetaProperty(tags, "og:site_name", openGraph.siteName);
|
|
2549
|
-
appendMetaProperty(tags, "og:type", openGraph.type);
|
|
2595
|
+
appendMetaProperty(tags, "og:type", openGraph.type ?? "website");
|
|
2550
2596
|
appendMetaProperty(tags, "og:locale", openGraph.locale);
|
|
2551
2597
|
const images = normalizeMetadataImages(
|
|
2552
2598
|
openGraph.images ?? openGraph.image,
|