@sonordev/site-kit 6.3.6 → 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-manifest.json +8 -2
- package/dist/{AnalyticsProvider-XDVJTAPN.mjs → AnalyticsProvider-4K5T7OQ7.mjs} +6 -6
- package/dist/{AnalyticsProvider-XDVJTAPN.mjs.map → AnalyticsProvider-4K5T7OQ7.mjs.map} +1 -1
- package/dist/{AnalyticsProvider-L3GWK5PO.js → AnalyticsProvider-QXZN5O6D.js} +10 -10
- package/dist/{AnalyticsProvider-L3GWK5PO.js.map → AnalyticsProvider-QXZN5O6D.js.map} +1 -1
- package/dist/{ArticleViewTracker-7AJJTGFY.mjs → ArticleViewTracker-BUG2TOHS.mjs} +5 -5
- package/dist/{ArticleViewTracker-7AJJTGFY.mjs.map → ArticleViewTracker-BUG2TOHS.mjs.map} +1 -1
- package/dist/{ArticleViewTracker-YMGW6ZXB.js → ArticleViewTracker-FFMHR7AY.js} +6 -6
- package/dist/{ArticleViewTracker-YMGW6ZXB.js.map → ArticleViewTracker-FFMHR7AY.js.map} +1 -1
- package/dist/{ChatWidget-MR64ZLOG.mjs → ChatWidget-CRQPBDEF.mjs} +7 -7
- package/dist/{ChatWidget-MR64ZLOG.mjs.map → ChatWidget-CRQPBDEF.mjs.map} +1 -1
- package/dist/{ChatWidget-IAYEXLNX.js → ChatWidget-XFYLVXAX.js} +10 -10
- package/dist/{ChatWidget-IAYEXLNX.js.map → ChatWidget-XFYLVXAX.js.map} +1 -1
- package/dist/EngageWidget-S234YAT2.js +21 -0
- package/dist/{EngageWidget-BF7DH4GO.js.map → EngageWidget-S234YAT2.js.map} +1 -1
- package/dist/EngageWidget-SQU4T7CI.mjs +12 -0
- package/dist/{EngageWidget-RANSIKC3.mjs.map → EngageWidget-SQU4T7CI.mjs.map} +1 -1
- package/dist/{FileField-7ZNQ5BID.mjs → FileField-HNEBEBLB.mjs} +5 -5
- package/dist/{FileField-7ZNQ5BID.mjs.map → FileField-HNEBEBLB.mjs.map} +1 -1
- package/dist/{FileField-VRKATE4G.js → FileField-XG4EYAZW.js} +6 -6
- package/dist/{FileField-VRKATE4G.js.map → FileField-XG4EYAZW.js.map} +1 -1
- package/dist/{FormSpotlight-VQJ2QWIU.js → FormSpotlight-IODREOPN.js} +9 -9
- package/dist/{FormSpotlight-VQJ2QWIU.js.map → FormSpotlight-IODREOPN.js.map} +1 -1
- package/dist/{FormSpotlight-QNH7XGYS.mjs → FormSpotlight-VKD774PZ.mjs} +3 -3
- package/dist/{FormSpotlight-QNH7XGYS.mjs.map → FormSpotlight-VKD774PZ.mjs.map} +1 -1
- package/dist/{FormStage-3JIN6X6O.js → FormStage-37KKZQH4.js} +9 -9
- package/dist/{FormStage-3JIN6X6O.js.map → FormStage-37KKZQH4.js.map} +1 -1
- package/dist/{FormStage-XB4JNFCH.mjs → FormStage-PRZNRYNC.mjs} +3 -3
- package/dist/{FormStage-XB4JNFCH.mjs.map → FormStage-PRZNRYNC.mjs.map} +1 -1
- package/dist/ManagedForm-4PZOCKCV.mjs +16 -0
- package/dist/{ManagedForm-E6F4FLVY.mjs.map → ManagedForm-4PZOCKCV.mjs.map} +1 -1
- package/dist/ManagedForm-JCMEE626.js +25 -0
- package/dist/{ManagedForm-Q5UFMUBE.js.map → ManagedForm-JCMEE626.js.map} +1 -1
- package/dist/{ManagedNewsletterForm-UTNOJ5T4.js → ManagedNewsletterForm-CTC33B2U.js} +7 -7
- package/dist/{ManagedNewsletterForm-UTNOJ5T4.js.map → ManagedNewsletterForm-CTC33B2U.js.map} +1 -1
- package/dist/{ManagedNewsletterForm-OEEC3GVY.mjs → ManagedNewsletterForm-KMZG24OE.mjs} +6 -6
- package/dist/{ManagedNewsletterForm-OEEC3GVY.mjs.map → ManagedNewsletterForm-KMZG24OE.mjs.map} +1 -1
- package/dist/{SignalCore-4AUWHMYK.js → SignalCore-YHT7WPXV.js} +11 -11
- package/dist/{SignalCore-4AUWHMYK.js.map → SignalCore-YHT7WPXV.js.map} +1 -1
- package/dist/{SignalCore-PWN5X6FF.mjs → SignalCore-YIPKKIUG.mjs} +5 -5
- package/dist/{SignalCore-PWN5X6FF.mjs.map → SignalCore-YIPKKIUG.mjs.map} +1 -1
- package/dist/SitemapSync-GN4OXIM2.js +18 -0
- package/dist/{SitemapSync-DHJ25PSH.js.map → SitemapSync-GN4OXIM2.js.map} +1 -1
- package/dist/SitemapSync-NG763CGN.mjs +9 -0
- package/dist/{SitemapSync-ZA2MNM63.mjs.map → SitemapSync-NG763CGN.mjs.map} +1 -1
- package/dist/analytics/index.js +9 -9
- package/dist/analytics/index.mjs +4 -4
- package/dist/articles/AuthorPage.d.ts +1 -1
- package/dist/articles/AuthorPage.d.ts.map +1 -1
- package/dist/articles/author-schema.d.ts +59 -13
- package/dist/articles/author-schema.d.ts.map +1 -1
- package/dist/articles/index.js +24 -23
- package/dist/articles/index.js.map +1 -1
- package/dist/articles/index.mjs +12 -11
- package/dist/articles/index.mjs.map +1 -1
- package/dist/articles/routes.d.ts +9 -0
- package/dist/articles/routes.d.ts.map +1 -1
- package/dist/articles/server-core.d.ts +5 -2
- package/dist/articles/server-core.d.ts.map +1 -1
- package/dist/articles/server-ui.js +45 -45
- package/dist/articles/server-ui.mjs +8 -8
- package/dist/articles/server.d.ts +5 -2
- package/dist/articles/server.d.ts.map +1 -1
- package/dist/articles/server.js +72 -56
- package/dist/articles/server.mjs +3 -3
- package/dist/articles/types.d.ts +17 -0
- package/dist/articles/types.d.ts.map +1 -1
- package/dist/{chunk-PQICWWQW.mjs → chunk-24LFAQEG.mjs} +5 -5
- package/dist/{chunk-PQICWWQW.mjs.map → chunk-24LFAQEG.mjs.map} +1 -1
- package/dist/chunk-3AOKYAZ2.js +135 -0
- package/dist/chunk-3AOKYAZ2.js.map +1 -0
- package/dist/{chunk-UJIKP35G.mjs → chunk-4C3INRHE.mjs} +4 -4
- package/dist/{chunk-UJIKP35G.mjs.map → chunk-4C3INRHE.mjs.map} +1 -1
- package/dist/{chunk-ZR43XFUM.js → chunk-55J2KE7D.js} +3 -3
- package/dist/chunk-55J2KE7D.js.map +1 -0
- package/dist/{chunk-B2NO5QVY.mjs → chunk-5BARLEAI.mjs} +3 -3
- package/dist/{chunk-B2NO5QVY.mjs.map → chunk-5BARLEAI.mjs.map} +1 -1
- package/dist/{chunk-BJKA3XRS.mjs → chunk-5T3J24K4.mjs} +4 -4
- package/dist/{chunk-BJKA3XRS.mjs.map → chunk-5T3J24K4.mjs.map} +1 -1
- package/dist/{chunk-3J5L5DIK.js → chunk-5W4S7XQD.js} +3 -3
- package/dist/{chunk-3J5L5DIK.js.map → chunk-5W4S7XQD.js.map} +1 -1
- package/dist/{chunk-6DCAMW62.mjs → chunk-6C47333H.mjs} +3 -3
- package/dist/chunk-6C47333H.mjs.map +1 -0
- package/dist/{chunk-YKZ3EVAQ.mjs → chunk-6QPKC6XP.mjs} +3 -3
- package/dist/{chunk-YKZ3EVAQ.mjs.map → chunk-6QPKC6XP.mjs.map} +1 -1
- package/dist/{chunk-JOYMIGR2.mjs → chunk-7K6L33BX.mjs} +22 -22
- package/dist/{chunk-JS75ORH7.js → chunk-ATPQ6264.js} +24 -24
- package/dist/{chunk-5J4FKRGH.mjs → chunk-BI7DH42Z.mjs} +4 -4
- package/dist/{chunk-5J4FKRGH.mjs.map → chunk-BI7DH42Z.mjs.map} +1 -1
- package/dist/{chunk-J4C3JAJF.js → chunk-C7J4XLBN.js} +15 -15
- package/dist/{chunk-J4C3JAJF.js.map → chunk-C7J4XLBN.js.map} +1 -1
- package/dist/{chunk-LWCAZDY2.js → chunk-CDRQYJUT.js} +4 -4
- package/dist/{chunk-LWCAZDY2.js.map → chunk-CDRQYJUT.js.map} +1 -1
- package/dist/chunk-CIB3RHNZ.js +8 -0
- package/dist/{chunk-6SBRD5KT.js.map → chunk-CIB3RHNZ.js.map} +1 -1
- package/dist/{chunk-FRUBUQOH.js → chunk-CUZ3I6CO.js} +5 -5
- package/dist/{chunk-FRUBUQOH.js.map → chunk-CUZ3I6CO.js.map} +1 -1
- package/dist/{chunk-PMWF5CRL.js → chunk-EWDWLY74.js} +11 -11
- package/dist/{chunk-PMWF5CRL.js.map → chunk-EWDWLY74.js.map} +1 -1
- package/dist/{chunk-OLVCGOXZ.js → chunk-F2GECCK7.js} +12 -12
- package/dist/{chunk-OLVCGOXZ.js.map → chunk-F2GECCK7.js.map} +1 -1
- package/dist/chunk-GFSQMK35.mjs +127 -0
- package/dist/chunk-GFSQMK35.mjs.map +1 -0
- package/dist/{chunk-2MEMK5XC.js → chunk-GGGX54ZE.js} +14 -14
- package/dist/{chunk-2MEMK5XC.js.map → chunk-GGGX54ZE.js.map} +1 -1
- package/dist/{chunk-6MOGGEY3.mjs → chunk-GSU6VTCZ.mjs} +3 -3
- package/dist/{chunk-6MOGGEY3.mjs.map → chunk-GSU6VTCZ.mjs.map} +1 -1
- package/dist/{chunk-3POB4JKR.js → chunk-GXSSFQ5D.js} +15 -15
- package/dist/{chunk-3POB4JKR.js.map → chunk-GXSSFQ5D.js.map} +1 -1
- package/dist/{chunk-BJ4T65OK.mjs → chunk-H4TSADY3.mjs} +3 -3
- package/dist/{chunk-BJ4T65OK.mjs.map → chunk-H4TSADY3.mjs.map} +1 -1
- package/dist/{chunk-2UZULHI4.js → chunk-HSLPN3QK.js} +7 -7
- package/dist/{chunk-2UZULHI4.js.map → chunk-HSLPN3QK.js.map} +1 -1
- package/dist/{chunk-EB33U2WT.js → chunk-HTCNRTN6.js} +129 -69
- package/dist/chunk-HTCNRTN6.js.map +1 -0
- package/dist/{chunk-3Q3Y6OQE.mjs → chunk-JXRGIE3V.mjs} +4 -4
- package/dist/{chunk-3Q3Y6OQE.mjs.map → chunk-JXRGIE3V.mjs.map} +1 -1
- package/dist/chunk-K3PVUXKB.mjs +6 -0
- package/dist/{chunk-3V6DIQI7.mjs.map → chunk-K3PVUXKB.mjs.map} +1 -1
- package/dist/{chunk-KMONA7CT.mjs → chunk-KOPFFKG2.mjs} +3 -3
- package/dist/{chunk-KMONA7CT.mjs.map → chunk-KOPFFKG2.mjs.map} +1 -1
- package/dist/{chunk-UAOQVHZW.js → chunk-KZBDH5A3.js} +4 -4
- package/dist/{chunk-UAOQVHZW.js.map → chunk-KZBDH5A3.js.map} +1 -1
- package/dist/{chunk-SB4CJX2X.mjs → chunk-LPDXS2B2.mjs} +3 -3
- package/dist/{chunk-SB4CJX2X.mjs.map → chunk-LPDXS2B2.mjs.map} +1 -1
- package/dist/{chunk-6I5O5CTL.mjs → chunk-M3JCHPK3.mjs} +127 -67
- package/dist/chunk-M3JCHPK3.mjs.map +1 -0
- package/dist/{chunk-LFF32POH.mjs → chunk-M62L2N5A.mjs} +3 -3
- package/dist/{chunk-LFF32POH.mjs.map → chunk-M62L2N5A.mjs.map} +1 -1
- package/dist/{chunk-G3L26XQ7.js → chunk-OIPG3EGM.js} +5 -5
- package/dist/{chunk-G3L26XQ7.js.map → chunk-OIPG3EGM.js.map} +1 -1
- package/dist/{chunk-X3MY4PL7.mjs → chunk-QAQTDHHT.mjs} +10 -14
- package/dist/chunk-QAQTDHHT.mjs.map +1 -0
- package/dist/{chunk-KB7SIIVY.mjs → chunk-QOKMH2TD.mjs} +3 -3
- package/dist/{chunk-KB7SIIVY.mjs.map → chunk-QOKMH2TD.mjs.map} +1 -1
- package/dist/{chunk-HXHRS3PX.mjs → chunk-RCB6HEHM.mjs} +3 -3
- package/dist/{chunk-HXHRS3PX.mjs.map → chunk-RCB6HEHM.mjs.map} +1 -1
- package/dist/{chunk-NNZDWY3L.mjs → chunk-RH4XEXTK.mjs} +3 -3
- package/dist/{chunk-NAA5J2JM.js → chunk-RQROZLH3.js} +47 -51
- package/dist/chunk-RQROZLH3.js.map +1 -0
- package/dist/{chunk-VGBUC2JP.js → chunk-S5QKNXLQ.js} +10 -10
- package/dist/{chunk-VGBUC2JP.js.map → chunk-S5QKNXLQ.js.map} +1 -1
- package/dist/{chunk-5DZVQW35.mjs → chunk-SBTA6B6Y.mjs} +4 -4
- package/dist/{chunk-5DZVQW35.mjs.map → chunk-SBTA6B6Y.mjs.map} +1 -1
- package/dist/{chunk-5YA6SI4Z.mjs → chunk-TIFVAASU.mjs} +2 -2
- package/dist/{chunk-R26FAQWF.mjs → chunk-TPDDSEL3.mjs} +3 -3
- package/dist/{chunk-R26FAQWF.mjs.map → chunk-TPDDSEL3.mjs.map} +1 -1
- package/dist/{chunk-X5J3PYZJ.js → chunk-U4CYO4NG.js} +5 -5
- package/dist/{chunk-X5J3PYZJ.js.map → chunk-U4CYO4NG.js.map} +1 -1
- package/dist/{chunk-TE3YNZVH.js → chunk-U5NFIHLY.js} +4 -4
- package/dist/{chunk-TE3YNZVH.js.map → chunk-U5NFIHLY.js.map} +1 -1
- package/dist/{chunk-L6BQIDSZ.mjs → chunk-USQPRLSG.mjs} +8 -8
- package/dist/{chunk-L6BQIDSZ.mjs.map → chunk-USQPRLSG.mjs.map} +1 -1
- package/dist/{chunk-5XDOBM5S.js → chunk-VDEQVXNV.js} +3 -3
- package/dist/{chunk-5XDOBM5S.js.map → chunk-VDEQVXNV.js.map} +1 -1
- package/dist/{chunk-SAOUAIRS.js → chunk-VMNPLCZB.js} +14 -14
- package/dist/{chunk-SAOUAIRS.js.map → chunk-VMNPLCZB.js.map} +1 -1
- package/dist/{chunk-ANYCUTS5.js → chunk-W7IAG5YD.js} +3 -3
- package/dist/{chunk-ANYCUTS5.js.map → chunk-W7IAG5YD.js.map} +1 -1
- package/dist/{chunk-K6ZQVDP4.mjs → chunk-WIWHM47B.mjs} +3 -3
- package/dist/{chunk-K6ZQVDP4.mjs.map → chunk-WIWHM47B.mjs.map} +1 -1
- package/dist/{chunk-I7AZC5ZQ.js → chunk-XXSSUCJB.js} +2 -2
- package/dist/{chunk-7NFSSPGM.js → chunk-XZHR4E2D.js} +8 -8
- package/dist/{chunk-7NFSSPGM.js.map → chunk-XZHR4E2D.js.map} +1 -1
- package/dist/{chunk-E7EV2AHT.js → chunk-YACU35MY.js} +9 -9
- package/dist/{chunk-E7EV2AHT.js.map → chunk-YACU35MY.js.map} +1 -1
- package/dist/chunk-YMZNEDFP.js +39 -0
- package/dist/chunk-YMZNEDFP.js.map +1 -0
- package/dist/{chunk-CXYGKK4U.mjs → chunk-YRKWJCML.mjs} +3 -3
- package/dist/{chunk-CXYGKK4U.mjs.map → chunk-YRKWJCML.mjs.map} +1 -1
- package/dist/chunk-Z2URIOKG.mjs +36 -0
- package/dist/chunk-Z2URIOKG.mjs.map +1 -0
- package/dist/{chunk-W46QIVBM.mjs → chunk-ZEBOOUBP.mjs} +3 -3
- package/dist/{chunk-W46QIVBM.mjs.map → chunk-ZEBOOUBP.mjs.map} +1 -1
- package/dist/{chunk-SNXJXPB6.js → chunk-ZOBUA65N.js} +6 -6
- package/dist/{chunk-SNXJXPB6.js.map → chunk-ZOBUA65N.js.map} +1 -1
- package/dist/{chunk-NN2YE5WT.js → chunk-ZUQSVCMD.js} +3 -3
- package/dist/cli/index.js +211 -211
- package/dist/cli/index.mjs +151 -151
- package/dist/client/index.js +4 -4
- package/dist/client/index.mjs +3 -3
- package/dist/commerce/index.js +57 -57
- package/dist/commerce/index.mjs +5 -5
- package/dist/engage/DesignRenderer.d.ts.map +1 -1
- package/dist/engage/EngageWidget.d.ts.map +1 -1
- package/dist/engage/element-rules.d.ts +39 -0
- package/dist/engage/element-rules.d.ts.map +1 -0
- package/dist/engage/index.js +9 -9
- package/dist/engage/index.mjs +6 -6
- package/dist/fleet/index.js +8 -8
- package/dist/fleet/index.mjs +4 -4
- package/dist/forms/index.js +13 -13
- package/dist/forms/index.mjs +7 -7
- package/dist/forms/server.js +2 -2
- package/dist/forms/server.mjs +1 -1
- package/dist/images/index.js +11 -11
- package/dist/images/index.mjs +4 -4
- package/dist/index.js +63 -63
- package/dist/index.mjs +9 -9
- package/dist/layout/client.js +8 -8
- package/dist/layout/client.mjs +7 -7
- package/dist/layout/index.js +10 -10
- package/dist/layout/index.mjs +8 -8
- package/dist/{lib-6HOOMENJ.js → lib-6GWWPDJR.js} +7 -7
- package/dist/lib-BD4KKQBI.mjs +4 -0
- package/dist/{lib-R7IQ4ZHE.mjs → lib-N5PD6JNJ.mjs} +2 -2
- package/dist/{lib-BGAWCSUH.js → lib-WFB5RLEQ.js} +8 -8
- package/dist/llms/index.d.ts +2 -0
- package/dist/llms/index.d.ts.map +1 -1
- package/dist/llms/index.js +129 -14
- package/dist/llms/index.js.map +1 -1
- package/dist/llms/index.mjs +115 -5
- package/dist/llms/index.mjs.map +1 -1
- package/dist/llms/revalidate.d.ts +3 -0
- package/dist/llms/revalidate.d.ts.map +1 -1
- package/dist/llms/seo-revalidate.d.ts +105 -0
- package/dist/llms/seo-revalidate.d.ts.map +1 -0
- package/dist/maps/index.js +5 -5
- package/dist/maps/index.mjs +3 -3
- package/dist/mcp/transport.d.ts +166 -0
- package/dist/mcp/transport.d.ts.map +1 -0
- package/dist/mcp/transport.js +137 -0
- package/dist/mcp/transport.js.map +1 -0
- package/dist/mcp/transport.mjs +123 -0
- package/dist/mcp/transport.mjs.map +1 -0
- package/dist/search/index.js +4 -4
- package/dist/search/index.mjs +3 -3
- package/dist/seo/client.js +5 -5
- package/dist/seo/client.mjs +4 -4
- package/dist/seo/index.js +5 -5
- package/dist/seo/index.mjs +4 -4
- package/dist/seo/register-sitemap-cli.js +3 -3
- package/dist/seo/register-sitemap-cli.mjs +2 -2
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +2 -2
- package/dist/shared/build-entries.d.ts +7 -0
- package/dist/shared/build-entries.d.ts.map +1 -1
- package/dist/shared/request-guards.d.ts +27 -0
- package/dist/shared/request-guards.d.ts.map +1 -0
- package/dist/shared/version.d.ts +1 -1
- package/dist/signal/index.js +11 -11
- package/dist/signal/index.mjs +2 -2
- package/dist/sitemap/index.js +3 -3
- package/dist/sitemap/index.mjs +2 -2
- package/dist/sync/index.js +17 -17
- package/dist/sync/index.mjs +4 -4
- package/dist/{web-vitals.attribution-7LKLZ5GR.mjs → web-vitals.attribution-CHXXWO72.mjs} +3 -3
- package/dist/web-vitals.attribution-CHXXWO72.mjs.map +1 -0
- package/dist/{web-vitals.attribution-ONVYQNRB.js → web-vitals.attribution-SQVZNHN3.js} +3 -3
- package/dist/web-vitals.attribution-SQVZNHN3.js.map +1 -0
- package/dist/{writeLLMsTxt-LYYC3ZSN.mjs → writeLLMsTxt-IYJILIU3.mjs} +3 -3
- package/dist/{writeLLMsTxt-XHLHJ5XY.js → writeLLMsTxt-SQG4B63X.js} +4 -4
- package/package.json +6 -1
- package/dist/EngageWidget-BF7DH4GO.js +0 -21
- package/dist/EngageWidget-RANSIKC3.mjs +0 -12
- package/dist/ManagedForm-E6F4FLVY.mjs +0 -16
- package/dist/ManagedForm-Q5UFMUBE.js +0 -25
- package/dist/SitemapSync-DHJ25PSH.js +0 -18
- package/dist/SitemapSync-ZA2MNM63.mjs +0 -9
- package/dist/chunk-3V6DIQI7.mjs +0 -6
- package/dist/chunk-6DCAMW62.mjs.map +0 -1
- package/dist/chunk-6I5O5CTL.mjs.map +0 -1
- package/dist/chunk-6SBRD5KT.js +0 -8
- package/dist/chunk-EB33U2WT.js.map +0 -1
- package/dist/chunk-NAA5J2JM.js.map +0 -1
- package/dist/chunk-X3MY4PL7.mjs.map +0 -1
- package/dist/chunk-YRCR7WY3.js +0 -65
- package/dist/chunk-YRCR7WY3.js.map +0 -1
- package/dist/chunk-ZL35JCDA.mjs +0 -61
- package/dist/chunk-ZL35JCDA.mjs.map +0 -1
- package/dist/chunk-ZR43XFUM.js.map +0 -1
- package/dist/lib-RSDMEKDQ.mjs +0 -4
- package/dist/web-vitals.attribution-7LKLZ5GR.mjs.map +0 -1
- package/dist/web-vitals.attribution-ONVYQNRB.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/mcp/transport.ts"],"names":["createHmac","timingSafeEqual","readCappedBody"],"mappings":"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","file":"transport.js","sourcesContent":["/**\n * @sonordev/site-kit/mcp/transport — the rate-limited public MCP relay\n *\n * Netlify rate-limits a native function (declarative `config.rateLimit`), never\n * a Next.js route handler. So a public MCP endpoint on Netlify takes this path:\n *\n * agent ─► /api/mcp netlify/functions/mcp.mjs, rate-limited\n * │ createNetlifyMcpRelay: signs the request\n * │ (HMAC-SHA256 of MCP_TRANSPORT_SECRET over a label)\n * ▼\n * https://<deploy-id>--<site>.netlify.app/api/mcp-internal\n * │ createMcpInternalRoute: 403 unless signed,\n * ▼ then dispatches to the /api/mcp handlers\n * app/api/mcp/route.ts protectMcpHandlers(createMcpHandler(...))\n *\n * In production the function owns /api/mcp, and the Next route behind it\n * refuses unsigned calls too, so no request reaches a tool without passing\n * the rate limit. The relay targets the deploy permalink, so a request is\n * answered by the same immutable deploy that received it, and the base URL\n * comes from the platform (`context`), never from a client header.\n *\n * Single source of truth for the relay. It replaced per-site copies in\n * upforge-nextjs and wirsch-law-nextjs (`lib/mcp/transport-auth.ts`, the\n * `protect()` wrapper, the `/api/mcp-internal` relay and the function body);\n * don't fork it back into a site.\n *\n * Node only (`crypto`), and deliberately not re-exported from the\n * `@sonordev/site-kit/mcp` barrel so that barrel stays runtime-neutral.\n * Nothing here imports `server-only`: the Netlify function runs in plain Node,\n * where `server-only` throws on import.\n *\n * Setup: `MCP_TRANSPORT_SECRET` (`openssl rand -hex 32`) in every deploy\n * context, Functions scope. See the module README for the three files.\n */\n\nimport { createHmac, timingSafeEqual } from 'crypto'\nimport { readCappedBody } from '../shared/request-guards'\n\n// ============================================\n// Constants\n// ============================================\n\n/** Env var holding the relay's HMAC key. */\nexport const MCP_TRANSPORT_SECRET_ENV = 'MCP_TRANSPORT_SECRET'\n\n/** Default request header carrying the signature (and the response marker). */\nexport const DEFAULT_MCP_TRANSPORT_HEADER = 'x-site-mcp-transport'\n\n/** Default HMAC message. Changing it invalidates every signature at once. */\nexport const DEFAULT_MCP_TRANSPORT_LABEL = 'site-mcp-transport-v1'\n\n/** Path of the signed Next route the function relays to. */\nexport const MCP_INTERNAL_PATH = '/api/mcp-internal'\n\n/** Value of the marker header on every relayed response. Release checks assert it. */\nexport const MCP_RELAY_MARKER = 'netlify-rate-limited-v1'\n\n/** Largest POST body the relay forwards (tool arguments), in bytes. */\nexport const MCP_RELAY_MAX_BODY_BYTES = 64 * 1024\n\n/** Upstream timeout. Under Netlify's 60 s synchronous function limit, so the 502 is ours. */\nexport const MCP_RELAY_TIMEOUT_MS = 55_000\n\n/** Methods the MCP wire uses. Anything else gets a 405. */\nexport const MCP_RELAY_METHODS = ['GET', 'POST', 'OPTIONS', 'DELETE'] as const\n\n// ============================================\n// Types\n// ============================================\n\nexport interface McpTransportOptions {\n /**\n * Request header that carries the signature. The relay also stamps it on\n * responses with {@link MCP_RELAY_MARKER}. Must match between the function\n * and the Next routes. Default {@link DEFAULT_MCP_TRANSPORT_HEADER}.\n */\n header?: string\n /**\n * HMAC message. Must match between the function and the Next routes.\n * Default {@link DEFAULT_MCP_TRANSPORT_LABEL}.\n */\n label?: string\n /**\n * The HMAC key, or a getter for it. Default: `MCP_TRANSPORT_SECRET`, read on\n * every request (`Netlify.env` when present, else `process.env`).\n */\n secret?: string | (() => string | undefined)\n}\n\nexport type McpRouteHandler = (request: Request) => Response | Promise<Response>\n\n/** The four method handlers an MCP route exports (what `createMcpHandler` returns). */\nexport interface McpRouteHandlerSet {\n GET: McpRouteHandler\n POST: McpRouteHandler\n DELETE: McpRouteHandler\n OPTIONS: McpRouteHandler\n}\n\nexport interface ProtectMcpHandlersOptions extends McpTransportOptions {\n /**\n * Refuse unsigned requests. Default: `NODE_ENV === 'production'`, read per\n * request, so `next dev` still answers a local MCP client directly.\n */\n enforce?: boolean | (() => boolean)\n}\n\nexport interface NetlifyMcpRelayOptions extends McpTransportOptions {\n /** The signed Next route, on the same deploy. Default {@link MCP_INTERNAL_PATH}. */\n internalPath?: string\n /** Error text for the 502 when the upstream fails or times out. */\n timeoutMessage?: string\n}\n\n/** The parts of Netlify's function `context` the relay reads. */\nexport interface NetlifyRelayContext {\n deploy?: { id?: string }\n site?: { name?: string; url?: string }\n}\n\ninterface ResolvedTransport {\n header: string\n label: string\n secret: McpTransportOptions['secret']\n}\n\n// ============================================\n// Signing\n// ============================================\n\nfunction resolveTransport(options: McpTransportOptions = {}): ResolvedTransport {\n const header = (options.header ?? DEFAULT_MCP_TRANSPORT_HEADER).toLowerCase()\n const label = options.label ?? DEFAULT_MCP_TRANSPORT_LABEL\n if (!/^[a-z0-9-]+$/.test(header)) {\n throw new TypeError(`@sonordev/site-kit/mcp/transport: invalid header name ${JSON.stringify(options.header)}`)\n }\n if (!label) throw new TypeError('@sonordev/site-kit/mcp/transport: label must not be empty')\n return { header, label, secret: options.secret }\n}\n\nfunction readSecret(secret: McpTransportOptions['secret']): string | undefined {\n if (typeof secret === 'function') return secret()\n if (secret !== undefined) return secret\n const netlify = (globalThis as { Netlify?: { env?: { get(name: string): string | undefined } } }).Netlify\n return netlify?.env?.get(MCP_TRANSPORT_SECRET_ENV) || process.env[MCP_TRANSPORT_SECRET_ENV]\n}\n\n/** The signature a relayed request carries: hex HMAC-SHA256 of `label` under `secret`. */\nexport function signMcpTransport(secret: string, label: string = DEFAULT_MCP_TRANSPORT_LABEL): string {\n return createHmac('sha256', secret).update(label).digest('hex')\n}\n\nfunction verify(request: Request, transport: ResolvedTransport): boolean {\n const key = readSecret(transport.secret)\n const supplied = request.headers.get(transport.header) || ''\n if (!key || !/^[a-f0-9]{64}$/.test(supplied)) return false\n const expected = createHmac('sha256', key).update(transport.label).digest()\n return timingSafeEqual(expected, Buffer.from(supplied, 'hex'))\n}\n\n/**\n * True when the request came through the rate-limited relay: its transport\n * header holds the HMAC of `label` under `MCP_TRANSPORT_SECRET`, compared in\n * constant time. False when the secret is unset.\n */\nexport function hasMcpTransportAuthorization(request: Request, options: McpTransportOptions = {}): boolean {\n return verify(request, resolveTransport(options))\n}\n\n// ============================================\n// Next.js routes\n// ============================================\n\nfunction isEnforced(enforce: ProtectMcpHandlersOptions['enforce']): boolean {\n if (typeof enforce === 'function') return enforce()\n if (enforce !== undefined) return enforce\n return process.env.NODE_ENV === 'production'\n}\n\n/**\n * Wrap the `/api/mcp` handlers so, in production, they answer only relayed\n * (signed) requests. The public path is the function's; this closes the Next\n * handler behind it so nothing can skip the rate limit.\n *\n * @example\n * ```ts\n * // app/api/mcp/route.ts\n * export const { POST, GET, DELETE, OPTIONS } = protectMcpHandlers(\n * createMcpHandler({ server: mcpServer, baseUrl: SITE_URL, allowedOrigins: '*' }),\n * )\n * ```\n */\nexport function protectMcpHandlers(\n handlers: McpRouteHandlerSet,\n options: ProtectMcpHandlersOptions = {},\n): McpRouteHandlerSet {\n const transport = resolveTransport(options)\n const protect =\n (handler: McpRouteHandler): McpRouteHandler =>\n (request) => {\n if (isEnforced(options.enforce) && !verify(request, transport)) {\n return Response.json({ error: 'Use the public MCP endpoint' }, { status: 403 })\n }\n return handler(request)\n }\n return {\n GET: protect(handlers.GET),\n POST: protect(handlers.POST),\n DELETE: protect(handlers.DELETE),\n OPTIONS: protect(handlers.OPTIONS),\n }\n}\n\n/**\n * Handlers for `/api/mcp-internal`, the relay's target. 403 without a valid\n * signature in every environment, then dispatch by method to the `/api/mcp`\n * handlers.\n *\n * @example\n * ```ts\n * // app/api/mcp-internal/route.ts\n * import * as mcp from '../mcp/route'\n * export const { POST, GET, DELETE, OPTIONS } = createMcpInternalRoute(mcp)\n * ```\n */\nexport function createMcpInternalRoute(\n handlers: McpRouteHandlerSet,\n options: McpTransportOptions = {},\n): McpRouteHandlerSet {\n const transport = resolveTransport(options)\n const relay: McpRouteHandler = (request) => {\n if (!verify(request, transport)) return Response.json({ error: 'Forbidden' }, { status: 403 })\n switch (request.method) {\n case 'GET':\n return handlers.GET(request)\n case 'POST':\n return handlers.POST(request)\n case 'DELETE':\n return handlers.DELETE(request)\n case 'OPTIONS':\n return handlers.OPTIONS(request)\n default:\n return new Response(null, { status: 405 })\n }\n }\n return { GET: relay, POST: relay, DELETE: relay, OPTIONS: relay }\n}\n\n// ============================================\n// Netlify function\n// ============================================\n\n/**\n * The default export for `netlify/functions/mcp.mjs`. Signs the request and\n * relays it to {@link MCP_INTERNAL_PATH} on the same deploy.\n *\n * - 503 when `MCP_TRANSPORT_SECRET` is unset; 405 for methods MCP doesn't use.\n * - Strips `host` and `content-length`, overwrites any client-sent transport\n * header with the real signature.\n * - POST bodies over 64 KB get a 413 and are never forwarded.\n * - `redirect: 'error'` and a 55 s timeout; any upstream failure is a 502.\n * - Responses drop the encoding/length headers fetch already undid, and gain\n * `Cache-Control: no-store` plus the transport header set to\n * {@link MCP_RELAY_MARKER}.\n *\n * The function file must still declare its own literal `config`: Netlify\n * reads `path` and `rateLimit` statically from that file, so they can't come\n * from an import.\n *\n * @example\n * ```js\n * // netlify/functions/mcp.mjs\n * import { createNetlifyMcpRelay } from '@sonordev/site-kit/mcp/transport'\n *\n * export default createNetlifyMcpRelay()\n *\n * export const config = {\n * path: '/api/mcp',\n * rateLimit: { windowSize: 60, windowLimit: 60, aggregateBy: ['ip', 'domain'] },\n * }\n * ```\n */\nexport function createNetlifyMcpRelay(\n options: NetlifyMcpRelayOptions = {},\n): (request: Request, context: NetlifyRelayContext) => Promise<Response> {\n const transport = resolveTransport(options)\n const internalPath = options.internalPath ?? MCP_INTERNAL_PATH\n const timeoutMessage = options.timeoutMessage ?? 'MCP request timed out. Try again.'\n const unavailable = () => Response.json({ error: 'MCP is temporarily unavailable' }, { status: 503 })\n\n return async function relayMcp(request, context) {\n const key = readSecret(transport.secret)\n if (!key) return unavailable()\n if (!(MCP_RELAY_METHODS as readonly string[]).includes(request.method)) return new Response(null, { status: 405 })\n\n // context is platform-provided, never a client-controlled forwarding URL.\n // The deploy permalink keeps the relay on the deploy that took the call.\n const base =\n context?.deploy?.id && context.site?.name\n ? `https://${context.deploy.id}--${context.site.name}.netlify.app`\n : context?.site?.url\n if (!base) return unavailable()\n const target = new URL(internalPath, base)\n\n const headers = new Headers(request.headers)\n headers.delete('host')\n headers.delete('content-length')\n // set, not append: overwrite anything a client sent under this name.\n headers.set(transport.header, signMcpTransport(key, transport.label))\n\n let body: Uint8Array<ArrayBuffer> | undefined\n if (request.method === 'POST') {\n const bytes = await readCappedBody(request, MCP_RELAY_MAX_BODY_BYTES)\n if (!bytes) return Response.json({ error: 'Tool arguments are too large' }, { status: 413 })\n body = bytes\n }\n\n try {\n const response = await fetch(target, {\n method: request.method,\n headers,\n body,\n redirect: 'error',\n signal: AbortSignal.timeout(MCP_RELAY_TIMEOUT_MS),\n })\n const outgoing = new Headers(response.headers)\n // fetch decodes the upstream body; its compression/length headers no longer apply.\n for (const name of ['content-encoding', 'content-length', 'transfer-encoding']) outgoing.delete(name)\n outgoing.set('Cache-Control', 'no-store')\n outgoing.set(transport.header, MCP_RELAY_MARKER)\n return new Response(response.body, { status: response.status, headers: outgoing })\n } catch {\n return Response.json({ error: timeoutMessage }, { status: 502 })\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { readCappedBody } from '../chunk-Z2URIOKG.mjs';
|
|
2
|
+
import '../chunk-BEXTDHO4.mjs';
|
|
3
|
+
import { createHmac, timingSafeEqual } from 'crypto';
|
|
4
|
+
|
|
5
|
+
var MCP_TRANSPORT_SECRET_ENV = "MCP_TRANSPORT_SECRET";
|
|
6
|
+
var DEFAULT_MCP_TRANSPORT_HEADER = "x-site-mcp-transport";
|
|
7
|
+
var DEFAULT_MCP_TRANSPORT_LABEL = "site-mcp-transport-v1";
|
|
8
|
+
var MCP_INTERNAL_PATH = "/api/mcp-internal";
|
|
9
|
+
var MCP_RELAY_MARKER = "netlify-rate-limited-v1";
|
|
10
|
+
var MCP_RELAY_MAX_BODY_BYTES = 64 * 1024;
|
|
11
|
+
var MCP_RELAY_TIMEOUT_MS = 55e3;
|
|
12
|
+
var MCP_RELAY_METHODS = ["GET", "POST", "OPTIONS", "DELETE"];
|
|
13
|
+
function resolveTransport(options = {}) {
|
|
14
|
+
const header = (options.header ?? DEFAULT_MCP_TRANSPORT_HEADER).toLowerCase();
|
|
15
|
+
const label = options.label ?? DEFAULT_MCP_TRANSPORT_LABEL;
|
|
16
|
+
if (!/^[a-z0-9-]+$/.test(header)) {
|
|
17
|
+
throw new TypeError(`@sonordev/site-kit/mcp/transport: invalid header name ${JSON.stringify(options.header)}`);
|
|
18
|
+
}
|
|
19
|
+
if (!label) throw new TypeError("@sonordev/site-kit/mcp/transport: label must not be empty");
|
|
20
|
+
return { header, label, secret: options.secret };
|
|
21
|
+
}
|
|
22
|
+
function readSecret(secret) {
|
|
23
|
+
if (typeof secret === "function") return secret();
|
|
24
|
+
if (secret !== void 0) return secret;
|
|
25
|
+
const netlify = globalThis.Netlify;
|
|
26
|
+
return netlify?.env?.get(MCP_TRANSPORT_SECRET_ENV) || process.env[MCP_TRANSPORT_SECRET_ENV];
|
|
27
|
+
}
|
|
28
|
+
function signMcpTransport(secret, label = DEFAULT_MCP_TRANSPORT_LABEL) {
|
|
29
|
+
return createHmac("sha256", secret).update(label).digest("hex");
|
|
30
|
+
}
|
|
31
|
+
function verify(request, transport) {
|
|
32
|
+
const key = readSecret(transport.secret);
|
|
33
|
+
const supplied = request.headers.get(transport.header) || "";
|
|
34
|
+
if (!key || !/^[a-f0-9]{64}$/.test(supplied)) return false;
|
|
35
|
+
const expected = createHmac("sha256", key).update(transport.label).digest();
|
|
36
|
+
return timingSafeEqual(expected, Buffer.from(supplied, "hex"));
|
|
37
|
+
}
|
|
38
|
+
function hasMcpTransportAuthorization(request, options = {}) {
|
|
39
|
+
return verify(request, resolveTransport(options));
|
|
40
|
+
}
|
|
41
|
+
function isEnforced(enforce) {
|
|
42
|
+
if (typeof enforce === "function") return enforce();
|
|
43
|
+
if (enforce !== void 0) return enforce;
|
|
44
|
+
return process.env.NODE_ENV === "production";
|
|
45
|
+
}
|
|
46
|
+
function protectMcpHandlers(handlers, options = {}) {
|
|
47
|
+
const transport = resolveTransport(options);
|
|
48
|
+
const protect = (handler) => (request) => {
|
|
49
|
+
if (isEnforced(options.enforce) && !verify(request, transport)) {
|
|
50
|
+
return Response.json({ error: "Use the public MCP endpoint" }, { status: 403 });
|
|
51
|
+
}
|
|
52
|
+
return handler(request);
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
GET: protect(handlers.GET),
|
|
56
|
+
POST: protect(handlers.POST),
|
|
57
|
+
DELETE: protect(handlers.DELETE),
|
|
58
|
+
OPTIONS: protect(handlers.OPTIONS)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function createMcpInternalRoute(handlers, options = {}) {
|
|
62
|
+
const transport = resolveTransport(options);
|
|
63
|
+
const relay = (request) => {
|
|
64
|
+
if (!verify(request, transport)) return Response.json({ error: "Forbidden" }, { status: 403 });
|
|
65
|
+
switch (request.method) {
|
|
66
|
+
case "GET":
|
|
67
|
+
return handlers.GET(request);
|
|
68
|
+
case "POST":
|
|
69
|
+
return handlers.POST(request);
|
|
70
|
+
case "DELETE":
|
|
71
|
+
return handlers.DELETE(request);
|
|
72
|
+
case "OPTIONS":
|
|
73
|
+
return handlers.OPTIONS(request);
|
|
74
|
+
default:
|
|
75
|
+
return new Response(null, { status: 405 });
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
return { GET: relay, POST: relay, DELETE: relay, OPTIONS: relay };
|
|
79
|
+
}
|
|
80
|
+
function createNetlifyMcpRelay(options = {}) {
|
|
81
|
+
const transport = resolveTransport(options);
|
|
82
|
+
const internalPath = options.internalPath ?? MCP_INTERNAL_PATH;
|
|
83
|
+
const timeoutMessage = options.timeoutMessage ?? "MCP request timed out. Try again.";
|
|
84
|
+
const unavailable = () => Response.json({ error: "MCP is temporarily unavailable" }, { status: 503 });
|
|
85
|
+
return async function relayMcp(request, context) {
|
|
86
|
+
const key = readSecret(transport.secret);
|
|
87
|
+
if (!key) return unavailable();
|
|
88
|
+
if (!MCP_RELAY_METHODS.includes(request.method)) return new Response(null, { status: 405 });
|
|
89
|
+
const base = context?.deploy?.id && context.site?.name ? `https://${context.deploy.id}--${context.site.name}.netlify.app` : context?.site?.url;
|
|
90
|
+
if (!base) return unavailable();
|
|
91
|
+
const target = new URL(internalPath, base);
|
|
92
|
+
const headers = new Headers(request.headers);
|
|
93
|
+
headers.delete("host");
|
|
94
|
+
headers.delete("content-length");
|
|
95
|
+
headers.set(transport.header, signMcpTransport(key, transport.label));
|
|
96
|
+
let body;
|
|
97
|
+
if (request.method === "POST") {
|
|
98
|
+
const bytes = await readCappedBody(request, MCP_RELAY_MAX_BODY_BYTES);
|
|
99
|
+
if (!bytes) return Response.json({ error: "Tool arguments are too large" }, { status: 413 });
|
|
100
|
+
body = bytes;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const response = await fetch(target, {
|
|
104
|
+
method: request.method,
|
|
105
|
+
headers,
|
|
106
|
+
body,
|
|
107
|
+
redirect: "error",
|
|
108
|
+
signal: AbortSignal.timeout(MCP_RELAY_TIMEOUT_MS)
|
|
109
|
+
});
|
|
110
|
+
const outgoing = new Headers(response.headers);
|
|
111
|
+
for (const name of ["content-encoding", "content-length", "transfer-encoding"]) outgoing.delete(name);
|
|
112
|
+
outgoing.set("Cache-Control", "no-store");
|
|
113
|
+
outgoing.set(transport.header, MCP_RELAY_MARKER);
|
|
114
|
+
return new Response(response.body, { status: response.status, headers: outgoing });
|
|
115
|
+
} catch {
|
|
116
|
+
return Response.json({ error: timeoutMessage }, { status: 502 });
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export { DEFAULT_MCP_TRANSPORT_HEADER, DEFAULT_MCP_TRANSPORT_LABEL, MCP_INTERNAL_PATH, MCP_RELAY_MARKER, MCP_RELAY_MAX_BODY_BYTES, MCP_RELAY_METHODS, MCP_RELAY_TIMEOUT_MS, MCP_TRANSPORT_SECRET_ENV, createMcpInternalRoute, createNetlifyMcpRelay, hasMcpTransportAuthorization, protectMcpHandlers, signMcpTransport };
|
|
122
|
+
//# sourceMappingURL=transport.mjs.map
|
|
123
|
+
//# sourceMappingURL=transport.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/mcp/transport.ts"],"names":[],"mappings":"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","file":"transport.mjs","sourcesContent":["/**\n * @sonordev/site-kit/mcp/transport — the rate-limited public MCP relay\n *\n * Netlify rate-limits a native function (declarative `config.rateLimit`), never\n * a Next.js route handler. So a public MCP endpoint on Netlify takes this path:\n *\n * agent ─► /api/mcp netlify/functions/mcp.mjs, rate-limited\n * │ createNetlifyMcpRelay: signs the request\n * │ (HMAC-SHA256 of MCP_TRANSPORT_SECRET over a label)\n * ▼\n * https://<deploy-id>--<site>.netlify.app/api/mcp-internal\n * │ createMcpInternalRoute: 403 unless signed,\n * ▼ then dispatches to the /api/mcp handlers\n * app/api/mcp/route.ts protectMcpHandlers(createMcpHandler(...))\n *\n * In production the function owns /api/mcp, and the Next route behind it\n * refuses unsigned calls too, so no request reaches a tool without passing\n * the rate limit. The relay targets the deploy permalink, so a request is\n * answered by the same immutable deploy that received it, and the base URL\n * comes from the platform (`context`), never from a client header.\n *\n * Single source of truth for the relay. It replaced per-site copies in\n * upforge-nextjs and wirsch-law-nextjs (`lib/mcp/transport-auth.ts`, the\n * `protect()` wrapper, the `/api/mcp-internal` relay and the function body);\n * don't fork it back into a site.\n *\n * Node only (`crypto`), and deliberately not re-exported from the\n * `@sonordev/site-kit/mcp` barrel so that barrel stays runtime-neutral.\n * Nothing here imports `server-only`: the Netlify function runs in plain Node,\n * where `server-only` throws on import.\n *\n * Setup: `MCP_TRANSPORT_SECRET` (`openssl rand -hex 32`) in every deploy\n * context, Functions scope. See the module README for the three files.\n */\n\nimport { createHmac, timingSafeEqual } from 'crypto'\nimport { readCappedBody } from '../shared/request-guards'\n\n// ============================================\n// Constants\n// ============================================\n\n/** Env var holding the relay's HMAC key. */\nexport const MCP_TRANSPORT_SECRET_ENV = 'MCP_TRANSPORT_SECRET'\n\n/** Default request header carrying the signature (and the response marker). */\nexport const DEFAULT_MCP_TRANSPORT_HEADER = 'x-site-mcp-transport'\n\n/** Default HMAC message. Changing it invalidates every signature at once. */\nexport const DEFAULT_MCP_TRANSPORT_LABEL = 'site-mcp-transport-v1'\n\n/** Path of the signed Next route the function relays to. */\nexport const MCP_INTERNAL_PATH = '/api/mcp-internal'\n\n/** Value of the marker header on every relayed response. Release checks assert it. */\nexport const MCP_RELAY_MARKER = 'netlify-rate-limited-v1'\n\n/** Largest POST body the relay forwards (tool arguments), in bytes. */\nexport const MCP_RELAY_MAX_BODY_BYTES = 64 * 1024\n\n/** Upstream timeout. Under Netlify's 60 s synchronous function limit, so the 502 is ours. */\nexport const MCP_RELAY_TIMEOUT_MS = 55_000\n\n/** Methods the MCP wire uses. Anything else gets a 405. */\nexport const MCP_RELAY_METHODS = ['GET', 'POST', 'OPTIONS', 'DELETE'] as const\n\n// ============================================\n// Types\n// ============================================\n\nexport interface McpTransportOptions {\n /**\n * Request header that carries the signature. The relay also stamps it on\n * responses with {@link MCP_RELAY_MARKER}. Must match between the function\n * and the Next routes. Default {@link DEFAULT_MCP_TRANSPORT_HEADER}.\n */\n header?: string\n /**\n * HMAC message. Must match between the function and the Next routes.\n * Default {@link DEFAULT_MCP_TRANSPORT_LABEL}.\n */\n label?: string\n /**\n * The HMAC key, or a getter for it. Default: `MCP_TRANSPORT_SECRET`, read on\n * every request (`Netlify.env` when present, else `process.env`).\n */\n secret?: string | (() => string | undefined)\n}\n\nexport type McpRouteHandler = (request: Request) => Response | Promise<Response>\n\n/** The four method handlers an MCP route exports (what `createMcpHandler` returns). */\nexport interface McpRouteHandlerSet {\n GET: McpRouteHandler\n POST: McpRouteHandler\n DELETE: McpRouteHandler\n OPTIONS: McpRouteHandler\n}\n\nexport interface ProtectMcpHandlersOptions extends McpTransportOptions {\n /**\n * Refuse unsigned requests. Default: `NODE_ENV === 'production'`, read per\n * request, so `next dev` still answers a local MCP client directly.\n */\n enforce?: boolean | (() => boolean)\n}\n\nexport interface NetlifyMcpRelayOptions extends McpTransportOptions {\n /** The signed Next route, on the same deploy. Default {@link MCP_INTERNAL_PATH}. */\n internalPath?: string\n /** Error text for the 502 when the upstream fails or times out. */\n timeoutMessage?: string\n}\n\n/** The parts of Netlify's function `context` the relay reads. */\nexport interface NetlifyRelayContext {\n deploy?: { id?: string }\n site?: { name?: string; url?: string }\n}\n\ninterface ResolvedTransport {\n header: string\n label: string\n secret: McpTransportOptions['secret']\n}\n\n// ============================================\n// Signing\n// ============================================\n\nfunction resolveTransport(options: McpTransportOptions = {}): ResolvedTransport {\n const header = (options.header ?? DEFAULT_MCP_TRANSPORT_HEADER).toLowerCase()\n const label = options.label ?? DEFAULT_MCP_TRANSPORT_LABEL\n if (!/^[a-z0-9-]+$/.test(header)) {\n throw new TypeError(`@sonordev/site-kit/mcp/transport: invalid header name ${JSON.stringify(options.header)}`)\n }\n if (!label) throw new TypeError('@sonordev/site-kit/mcp/transport: label must not be empty')\n return { header, label, secret: options.secret }\n}\n\nfunction readSecret(secret: McpTransportOptions['secret']): string | undefined {\n if (typeof secret === 'function') return secret()\n if (secret !== undefined) return secret\n const netlify = (globalThis as { Netlify?: { env?: { get(name: string): string | undefined } } }).Netlify\n return netlify?.env?.get(MCP_TRANSPORT_SECRET_ENV) || process.env[MCP_TRANSPORT_SECRET_ENV]\n}\n\n/** The signature a relayed request carries: hex HMAC-SHA256 of `label` under `secret`. */\nexport function signMcpTransport(secret: string, label: string = DEFAULT_MCP_TRANSPORT_LABEL): string {\n return createHmac('sha256', secret).update(label).digest('hex')\n}\n\nfunction verify(request: Request, transport: ResolvedTransport): boolean {\n const key = readSecret(transport.secret)\n const supplied = request.headers.get(transport.header) || ''\n if (!key || !/^[a-f0-9]{64}$/.test(supplied)) return false\n const expected = createHmac('sha256', key).update(transport.label).digest()\n return timingSafeEqual(expected, Buffer.from(supplied, 'hex'))\n}\n\n/**\n * True when the request came through the rate-limited relay: its transport\n * header holds the HMAC of `label` under `MCP_TRANSPORT_SECRET`, compared in\n * constant time. False when the secret is unset.\n */\nexport function hasMcpTransportAuthorization(request: Request, options: McpTransportOptions = {}): boolean {\n return verify(request, resolveTransport(options))\n}\n\n// ============================================\n// Next.js routes\n// ============================================\n\nfunction isEnforced(enforce: ProtectMcpHandlersOptions['enforce']): boolean {\n if (typeof enforce === 'function') return enforce()\n if (enforce !== undefined) return enforce\n return process.env.NODE_ENV === 'production'\n}\n\n/**\n * Wrap the `/api/mcp` handlers so, in production, they answer only relayed\n * (signed) requests. The public path is the function's; this closes the Next\n * handler behind it so nothing can skip the rate limit.\n *\n * @example\n * ```ts\n * // app/api/mcp/route.ts\n * export const { POST, GET, DELETE, OPTIONS } = protectMcpHandlers(\n * createMcpHandler({ server: mcpServer, baseUrl: SITE_URL, allowedOrigins: '*' }),\n * )\n * ```\n */\nexport function protectMcpHandlers(\n handlers: McpRouteHandlerSet,\n options: ProtectMcpHandlersOptions = {},\n): McpRouteHandlerSet {\n const transport = resolveTransport(options)\n const protect =\n (handler: McpRouteHandler): McpRouteHandler =>\n (request) => {\n if (isEnforced(options.enforce) && !verify(request, transport)) {\n return Response.json({ error: 'Use the public MCP endpoint' }, { status: 403 })\n }\n return handler(request)\n }\n return {\n GET: protect(handlers.GET),\n POST: protect(handlers.POST),\n DELETE: protect(handlers.DELETE),\n OPTIONS: protect(handlers.OPTIONS),\n }\n}\n\n/**\n * Handlers for `/api/mcp-internal`, the relay's target. 403 without a valid\n * signature in every environment, then dispatch by method to the `/api/mcp`\n * handlers.\n *\n * @example\n * ```ts\n * // app/api/mcp-internal/route.ts\n * import * as mcp from '../mcp/route'\n * export const { POST, GET, DELETE, OPTIONS } = createMcpInternalRoute(mcp)\n * ```\n */\nexport function createMcpInternalRoute(\n handlers: McpRouteHandlerSet,\n options: McpTransportOptions = {},\n): McpRouteHandlerSet {\n const transport = resolveTransport(options)\n const relay: McpRouteHandler = (request) => {\n if (!verify(request, transport)) return Response.json({ error: 'Forbidden' }, { status: 403 })\n switch (request.method) {\n case 'GET':\n return handlers.GET(request)\n case 'POST':\n return handlers.POST(request)\n case 'DELETE':\n return handlers.DELETE(request)\n case 'OPTIONS':\n return handlers.OPTIONS(request)\n default:\n return new Response(null, { status: 405 })\n }\n }\n return { GET: relay, POST: relay, DELETE: relay, OPTIONS: relay }\n}\n\n// ============================================\n// Netlify function\n// ============================================\n\n/**\n * The default export for `netlify/functions/mcp.mjs`. Signs the request and\n * relays it to {@link MCP_INTERNAL_PATH} on the same deploy.\n *\n * - 503 when `MCP_TRANSPORT_SECRET` is unset; 405 for methods MCP doesn't use.\n * - Strips `host` and `content-length`, overwrites any client-sent transport\n * header with the real signature.\n * - POST bodies over 64 KB get a 413 and are never forwarded.\n * - `redirect: 'error'` and a 55 s timeout; any upstream failure is a 502.\n * - Responses drop the encoding/length headers fetch already undid, and gain\n * `Cache-Control: no-store` plus the transport header set to\n * {@link MCP_RELAY_MARKER}.\n *\n * The function file must still declare its own literal `config`: Netlify\n * reads `path` and `rateLimit` statically from that file, so they can't come\n * from an import.\n *\n * @example\n * ```js\n * // netlify/functions/mcp.mjs\n * import { createNetlifyMcpRelay } from '@sonordev/site-kit/mcp/transport'\n *\n * export default createNetlifyMcpRelay()\n *\n * export const config = {\n * path: '/api/mcp',\n * rateLimit: { windowSize: 60, windowLimit: 60, aggregateBy: ['ip', 'domain'] },\n * }\n * ```\n */\nexport function createNetlifyMcpRelay(\n options: NetlifyMcpRelayOptions = {},\n): (request: Request, context: NetlifyRelayContext) => Promise<Response> {\n const transport = resolveTransport(options)\n const internalPath = options.internalPath ?? MCP_INTERNAL_PATH\n const timeoutMessage = options.timeoutMessage ?? 'MCP request timed out. Try again.'\n const unavailable = () => Response.json({ error: 'MCP is temporarily unavailable' }, { status: 503 })\n\n return async function relayMcp(request, context) {\n const key = readSecret(transport.secret)\n if (!key) return unavailable()\n if (!(MCP_RELAY_METHODS as readonly string[]).includes(request.method)) return new Response(null, { status: 405 })\n\n // context is platform-provided, never a client-controlled forwarding URL.\n // The deploy permalink keeps the relay on the deploy that took the call.\n const base =\n context?.deploy?.id && context.site?.name\n ? `https://${context.deploy.id}--${context.site.name}.netlify.app`\n : context?.site?.url\n if (!base) return unavailable()\n const target = new URL(internalPath, base)\n\n const headers = new Headers(request.headers)\n headers.delete('host')\n headers.delete('content-length')\n // set, not append: overwrite anything a client sent under this name.\n headers.set(transport.header, signMcpTransport(key, transport.label))\n\n let body: Uint8Array<ArrayBuffer> | undefined\n if (request.method === 'POST') {\n const bytes = await readCappedBody(request, MCP_RELAY_MAX_BODY_BYTES)\n if (!bytes) return Response.json({ error: 'Tool arguments are too large' }, { status: 413 })\n body = bytes\n }\n\n try {\n const response = await fetch(target, {\n method: request.method,\n headers,\n body,\n redirect: 'error',\n signal: AbortSignal.timeout(MCP_RELAY_TIMEOUT_MS),\n })\n const outgoing = new Headers(response.headers)\n // fetch decodes the upstream body; its compression/length headers no longer apply.\n for (const name of ['content-encoding', 'content-length', 'transfer-encoding']) outgoing.delete(name)\n outgoing.set('Cache-Control', 'no-store')\n outgoing.set(transport.header, MCP_RELAY_MARKER)\n return new Response(response.body, { status: response.status, headers: outgoing })\n } catch {\n return Response.json({ error: timeoutMessage }, { status: 502 })\n }\n }\n}\n"]}
|
package/dist/search/index.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var chunkCLO3K7PF_js = require('../chunk-CLO3K7PF.js');
|
|
5
|
-
var
|
|
6
|
-
require('../chunk-
|
|
7
|
-
require('../chunk-
|
|
5
|
+
var chunkC7J4XLBN_js = require('../chunk-C7J4XLBN.js');
|
|
6
|
+
require('../chunk-U5NFIHLY.js');
|
|
7
|
+
require('../chunk-CIB3RHNZ.js');
|
|
8
8
|
require('../chunk-SNAQBZPT.js');
|
|
9
9
|
var react = require('react');
|
|
10
10
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -39,7 +39,7 @@ function useSiteSearch(options = {}) {
|
|
|
39
39
|
const apiUrl = typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ || "https://api.sonor.io" : "https://api.sonor.io";
|
|
40
40
|
const apiKey = typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0;
|
|
41
41
|
const resolvedSite = site ?? (typeof window !== "undefined" ? window.__SITE_KIT_SITE__ : void 0);
|
|
42
|
-
const res = await
|
|
42
|
+
const res = await chunkC7J4XLBN_js.sonorFetch(
|
|
43
43
|
`${apiUrl}${chunkCLO3K7PF_js.SEARCH_ENDPOINT}`,
|
|
44
44
|
{
|
|
45
45
|
method: "POST",
|
package/dist/search/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { SEARCH_ENDPOINT } from '../chunk-CFRJ2MK5.mjs';
|
|
3
3
|
export { SEARCH_ENDPOINT } from '../chunk-CFRJ2MK5.mjs';
|
|
4
|
-
import { sonorFetch } from '../chunk-
|
|
5
|
-
import '../chunk-
|
|
6
|
-
import '../chunk-
|
|
4
|
+
import { sonorFetch } from '../chunk-5T3J24K4.mjs';
|
|
5
|
+
import '../chunk-YRKWJCML.mjs';
|
|
6
|
+
import '../chunk-K3PVUXKB.mjs';
|
|
7
7
|
import '../chunk-BEXTDHO4.mjs';
|
|
8
8
|
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
9
9
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
package/dist/seo/client.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunkU4CYO4NG_js = require('../chunk-U4CYO4NG.js');
|
|
5
5
|
require('../chunk-JONWE26J.js');
|
|
6
6
|
require('../chunk-5RNAUYWE.js');
|
|
7
|
-
require('../chunk-
|
|
8
|
-
require('../chunk-
|
|
9
|
-
require('../chunk-
|
|
7
|
+
require('../chunk-C7J4XLBN.js');
|
|
8
|
+
require('../chunk-U5NFIHLY.js');
|
|
9
|
+
require('../chunk-CIB3RHNZ.js');
|
|
10
10
|
require('../chunk-SNAQBZPT.js');
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
Object.defineProperty(exports, "SitemapSync", {
|
|
15
15
|
enumerable: true,
|
|
16
|
-
get: function () { return
|
|
16
|
+
get: function () { return chunkU4CYO4NG_js.SitemapSync; }
|
|
17
17
|
});
|
|
18
18
|
//# sourceMappingURL=client.js.map
|
|
19
19
|
//# sourceMappingURL=client.js.map
|
package/dist/seo/client.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { SitemapSync } from '../chunk-
|
|
2
|
+
export { SitemapSync } from '../chunk-M62L2N5A.mjs';
|
|
3
3
|
import '../chunk-C2CTLLIO.mjs';
|
|
4
4
|
import '../chunk-A6UYV475.mjs';
|
|
5
|
-
import '../chunk-
|
|
6
|
-
import '../chunk-
|
|
7
|
-
import '../chunk-
|
|
5
|
+
import '../chunk-5T3J24K4.mjs';
|
|
6
|
+
import '../chunk-YRKWJCML.mjs';
|
|
7
|
+
import '../chunk-K3PVUXKB.mjs';
|
|
8
8
|
import '../chunk-BEXTDHO4.mjs';
|
|
9
9
|
//# sourceMappingURL=client.mjs.map
|
|
10
10
|
//# sourceMappingURL=client.mjs.map
|
package/dist/seo/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
var chunkDV2LJYFD_js = require('../chunk-DV2LJYFD.js');
|
|
4
4
|
var chunkH6AU3WKF_js = require('../chunk-H6AU3WKF.js');
|
|
5
5
|
var chunkJ7QI3GDX_js = require('../chunk-J7QI3GDX.js');
|
|
6
|
-
var
|
|
6
|
+
var chunkU4CYO4NG_js = require('../chunk-U4CYO4NG.js');
|
|
7
7
|
var chunkTST2IKYO_js = require('../chunk-TST2IKYO.js');
|
|
8
8
|
var chunkOSU4QA5M_js = require('../chunk-OSU4QA5M.js');
|
|
9
9
|
require('../chunk-CXAXZFFW.js');
|
|
@@ -14,9 +14,9 @@ require('../chunk-IBJOGXQI.js');
|
|
|
14
14
|
require('../chunk-UZKXOZHR.js');
|
|
15
15
|
require('../chunk-SWIKKSKL.js');
|
|
16
16
|
require('../chunk-5RNAUYWE.js');
|
|
17
|
-
require('../chunk-
|
|
18
|
-
require('../chunk-
|
|
19
|
-
require('../chunk-
|
|
17
|
+
require('../chunk-C7J4XLBN.js');
|
|
18
|
+
require('../chunk-U5NFIHLY.js');
|
|
19
|
+
require('../chunk-CIB3RHNZ.js');
|
|
20
20
|
require('../chunk-SNAQBZPT.js');
|
|
21
21
|
var react = require('react');
|
|
22
22
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -706,7 +706,7 @@ Object.defineProperty(exports, "ManagedScripts", {
|
|
|
706
706
|
});
|
|
707
707
|
Object.defineProperty(exports, "SitemapSync", {
|
|
708
708
|
enumerable: true,
|
|
709
|
-
get: function () { return
|
|
709
|
+
get: function () { return chunkU4CYO4NG_js.SitemapSync; }
|
|
710
710
|
});
|
|
711
711
|
Object.defineProperty(exports, "generateSitemap", {
|
|
712
712
|
enumerable: true,
|
package/dist/seo/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { ManagedNoScripts, ManagedScripts } from '../chunk-6PJTLBRR.mjs';
|
|
2
2
|
import { pickManagedLlmSchemaForJsonLd } from '../chunk-PENNTSJE.mjs';
|
|
3
3
|
import { safeJsonLd } from '../chunk-662YHKWW.mjs';
|
|
4
|
-
export { SitemapSync } from '../chunk-
|
|
4
|
+
export { SitemapSync } from '../chunk-M62L2N5A.mjs';
|
|
5
5
|
import { getManagedMetadata } from '../chunk-JSXLTZUP.mjs';
|
|
6
6
|
export { generateSitemap, getABVariant, getManagedMetadata, getManagedMetadataWithAB, getRedirect, getRobotsDirective, isIndexable } from '../chunk-JSXLTZUP.mjs';
|
|
7
7
|
import { getContentBlock, getSchemaMarkups, getSEOPageData, getEntityEnhancedSchema, getFAQData, getInternalLinks, getEntities, pruneSchemaTypes } from '../chunk-NE6QGHFT.mjs';
|
|
@@ -14,9 +14,9 @@ import '../chunk-YPGUV6BT.mjs';
|
|
|
14
14
|
import '../chunk-KZVSB5WE.mjs';
|
|
15
15
|
import '../chunk-ZN4HBK5C.mjs';
|
|
16
16
|
import '../chunk-A6UYV475.mjs';
|
|
17
|
-
import '../chunk-
|
|
18
|
-
import '../chunk-
|
|
19
|
-
import '../chunk-
|
|
17
|
+
import '../chunk-5T3J24K4.mjs';
|
|
18
|
+
import '../chunk-YRKWJCML.mjs';
|
|
19
|
+
import '../chunk-K3PVUXKB.mjs';
|
|
20
20
|
import '../chunk-BEXTDHO4.mjs';
|
|
21
21
|
import { cache, Suspense } from 'react';
|
|
22
22
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunkZUQSVCMD_js = require('../chunk-ZUQSVCMD.js');
|
|
5
5
|
var chunkY2CP5J6Q_js = require('../chunk-Y2CP5J6Q.js');
|
|
6
6
|
var chunkJONWE26J_js = require('../chunk-JONWE26J.js');
|
|
7
7
|
var chunkIBJOGXQI_js = require('../chunk-IBJOGXQI.js');
|
|
@@ -18,7 +18,7 @@ var path__default = /*#__PURE__*/_interopDefault(path);
|
|
|
18
18
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
19
19
|
|
|
20
20
|
// src/seo/register-sitemap-cli.ts
|
|
21
|
-
var import_dotenv = chunkSNAQBZPT_js.__toESM(
|
|
21
|
+
var import_dotenv = chunkSNAQBZPT_js.__toESM(chunkZUQSVCMD_js.require_main());
|
|
22
22
|
var BRAND_PROFILE_EXTRACTOR_VERSION = 2;
|
|
23
23
|
function decideTheme(background, text) {
|
|
24
24
|
const bg = background ? chunkM2N7NY3V_js.colorLuminance(background) : null;
|
|
@@ -447,7 +447,7 @@ async function registerLocalSitemap(options) {
|
|
|
447
447
|
}
|
|
448
448
|
if (options.writeLlms && result.success) {
|
|
449
449
|
try {
|
|
450
|
-
const { writeLLMsTxtToPublic } = await import('../writeLLMsTxt-
|
|
450
|
+
const { writeLLMsTxtToPublic } = await import('../writeLLMsTxt-SQG4B63X.js');
|
|
451
451
|
const written = await writeLLMsTxtToPublic({
|
|
452
452
|
// Resolved here too: the sync's own `site` is scoped to the branch that
|
|
453
453
|
// posts, and this runs on the skip path as well.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { require_main } from '../chunk-
|
|
2
|
+
import { require_main } from '../chunk-RH4XEXTK.mjs';
|
|
3
3
|
import { findSitemapRoute, findAppDirForDiscovery, discoverNextJsRoutes } from '../chunk-UHYRVALN.mjs';
|
|
4
4
|
import { inferPageType } from '../chunk-C2CTLLIO.mjs';
|
|
5
5
|
import { resolveSyncSite, postRegisterSitemap } from '../chunk-YPGUV6BT.mjs';
|
|
@@ -440,7 +440,7 @@ async function registerLocalSitemap(options) {
|
|
|
440
440
|
}
|
|
441
441
|
if (options.writeLlms && result.success) {
|
|
442
442
|
try {
|
|
443
|
-
const { writeLLMsTxtToPublic } = await import('../writeLLMsTxt-
|
|
443
|
+
const { writeLLMsTxtToPublic } = await import('../writeLLMsTxt-IYJILIU3.mjs');
|
|
444
444
|
const written = await writeLLMsTxtToPublic({
|
|
445
445
|
// Resolved here too: the sync's own `site` is scoped to the branch that
|
|
446
446
|
// posts, and this runs on the skip path as well.
|
package/dist/server/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkKZBDH5A3_js = require('../chunk-KZBDH5A3.js');
|
|
4
4
|
require('../chunk-LVGSOW2F.js');
|
|
5
5
|
var chunkO5GHP7UO_js = require('../chunk-O5GHP7UO.js');
|
|
6
|
-
require('../chunk-
|
|
6
|
+
require('../chunk-CIB3RHNZ.js');
|
|
7
7
|
require('../chunk-SNAQBZPT.js');
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
Object.defineProperty(exports, "resolveClientCredential", {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
13
|
+
get: function () { return chunkKZBDH5A3_js.resolveClientCredential; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, "requireServerApiConfig", {
|
|
16
16
|
enumerable: true,
|
package/dist/server/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { resolveClientCredential } from '../chunk-
|
|
1
|
+
export { resolveClientCredential } from '../chunk-ZEBOOUBP.mjs';
|
|
2
2
|
import '../chunk-BQP6JIE2.mjs';
|
|
3
3
|
export { requireServerApiConfig, resolveApiOrigin, resolveServerApiConfig, serverApiFetch } from '../chunk-6XNEGG5B.mjs';
|
|
4
|
-
import '../chunk-
|
|
4
|
+
import '../chunk-K3PVUXKB.mjs';
|
|
5
5
|
import '../chunk-BEXTDHO4.mjs';
|
|
6
6
|
//# sourceMappingURL=index.mjs.map
|
|
7
7
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -74,6 +74,13 @@ export declare const entry: {
|
|
|
74
74
|
readonly 'mcp/index': 'src/mcp/index.ts';
|
|
75
75
|
/** Client half — <WebMcpTools> in-page registration. Stamped 'use client'. */
|
|
76
76
|
readonly 'mcp/client': 'src/mcp/client.ts';
|
|
77
|
+
/**
|
|
78
|
+
* Rate-limited public relay: the Netlify function body plus the signed Next
|
|
79
|
+
* routes behind it. Node only (`crypto`) and imported by a plain-Node
|
|
80
|
+
* Netlify function, so it stays out of the `mcp/index` barrel and never
|
|
81
|
+
* imports `server-only`.
|
|
82
|
+
*/
|
|
83
|
+
readonly 'mcp/transport': 'src/mcp/transport.ts';
|
|
77
84
|
readonly 'slots/index': 'src/slots/index.ts';
|
|
78
85
|
/** Pure contract + HMAC signing — import from `@sonordev/site-kit/slots/contract` in sonor-api */
|
|
79
86
|
readonly 'slots/contract': 'src/slots/contract.ts';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-entries.d.ts","sourceRoot":"","sources":["../../src/shared/build-entries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,KAAK;aAEhB,KAAO,EAAE,cAAc;aAIvB,cAAc,EAAE,qBAAqB;aAGrC,WAAW,EAAE,kBAAkB;aAC/B,YAAY,EAAE,mBAAmB;aACjC,YAAY,EAAE,mBAAmB;aACjC,0BAA0B,EAAE,iCAAiC;aAG7D,iBAAiB,EAAE,wBAAwB;aAG3C,cAAc,EAAE,qBAAqB;aAGrC,cAAc,EAAE,qBAAqB;aAGrC,aAAa,EAAE,oBAAoB;IACnC,gFAAgF;aAChF,gBAAgB,EAAE,uBAAuB;IACzC,yEAAyE;aACzE,cAAc,EAAE,qBAAqB;IACrC;;;;OAIG;aACH,cAAc,EAAE,qBAAqB;aAGrC,gBAAgB,EAAE,uBAAuB;aACzC,iBAAiB,EAAE,6BAA6B;aAChD,oBAAoB,EAAE,2BAA2B;aAGjD,gBAAgB,EAAE,uBAAuB;aACzC,iBAAiB,EAAE,wBAAwB;aAG3C,kBAAkB,EAAE,yBAAyB;aAG7C,YAAY,EAAE,mBAAmB;aAGjC,aAAa,EAAE,oBAAoB;aAGnC,eAAe,EAAE,sBAAsB;aAGvC,cAAc,EAAE,sBAAsB;IACtC,sEAAsE;aACtE,iBAAiB,EAAE,wBAAwB;aAG3C,UAAU,EAAE,iBAAiB;IAC7B,6EAA6E;aAC7E,UAAU,EAAE,kBAAkB;aAG9B,iBAAiB,EAAE,wBAAwB;IAC3C,6EAA6E;aAC7E,qBAAqB,EAAE,4BAA4B;aAGnD,cAAc,EAAE,qBAAqB;aACrC,eAAe,EAAE,sBAAsB;aAGvC,kBAAkB,EAAE,yBAAyB;aAC7C,mBAAmB,EAAE,0BAA0B;aAG/C,YAAY,EAAE,mBAAmB;IACjC;;;;OAIG;aACH,aAAa,EAAE,oBAAoB;IACnC,+FAA+F;aAC/F,eAAe,EAAE,sBAAsB;aAGvC,WAAW,EAAE,kBAAkB;IAC/B,8EAA8E;aAC9E,YAAY,EAAE,mBAAmB;
|
|
1
|
+
{"version":3,"file":"build-entries.d.ts","sourceRoot":"","sources":["../../src/shared/build-entries.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sonordev/site-kit shared - Request guards for secret-bearing route handlers
|
|
3
|
+
*
|
|
4
|
+
* Node only (`crypto`). Single source of truth for the two checks every
|
|
5
|
+
* webhook-style handler in the kit needs, so no module grows its own copy:
|
|
6
|
+
*
|
|
7
|
+
* - `secretsMatch`: constant-time secret comparison. Used by
|
|
8
|
+
* `createLlmsRevalidateHandler` and `createSeoRevalidationHandler`.
|
|
9
|
+
* - `readCappedBody`: read a request body without buffering past a cap. Used
|
|
10
|
+
* by `createSeoRevalidationHandler` (16 KB) and the MCP transport relay
|
|
11
|
+
* (64 KB).
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Constant-time equality for a supplied secret against the expected one.
|
|
15
|
+
* An empty expected secret never matches, so a misconfigured site (no env
|
|
16
|
+
* var) refuses everything instead of accepting an empty token.
|
|
17
|
+
*/
|
|
18
|
+
export declare function secretsMatch(supplied: string | null | undefined, expected: string | null | undefined): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Read a request body, giving up at the first chunk past `maxBytes`.
|
|
21
|
+
*
|
|
22
|
+
* Returns the bytes, or `null` when the body is larger than the cap (the
|
|
23
|
+
* stream is cancelled, so nothing past the cap is held in memory). A request
|
|
24
|
+
* with no body returns an empty array.
|
|
25
|
+
*/
|
|
26
|
+
export declare function readCappedBody(request: Request, maxBytes: number): Promise<Uint8Array<ArrayBuffer> | null>;
|
|
27
|
+
//# sourceMappingURL=request-guards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-guards.d.ts","sourceRoot":"","sources":["../../src/shared/request-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAK9G;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAsBhH"}
|
package/dist/shared/version.d.ts
CHANGED
package/dist/signal/index.js
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var
|
|
4
|
+
var chunkXZHR4E2D_js = require('../chunk-XZHR4E2D.js');
|
|
5
|
+
var chunkVDEQVXNV_js = require('../chunk-VDEQVXNV.js');
|
|
6
6
|
require('../chunk-SNAQBZPT.js');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, "ExperimentConversion", {
|
|
11
11
|
enumerable: true,
|
|
12
|
-
get: function () { return
|
|
12
|
+
get: function () { return chunkXZHR4E2D_js.ExperimentConversion; }
|
|
13
13
|
});
|
|
14
14
|
Object.defineProperty(exports, "SignalExperiment", {
|
|
15
15
|
enumerable: true,
|
|
16
|
-
get: function () { return
|
|
16
|
+
get: function () { return chunkXZHR4E2D_js.SignalExperiment; }
|
|
17
17
|
});
|
|
18
18
|
Object.defineProperty(exports, "useExperimentVariant", {
|
|
19
19
|
enumerable: true,
|
|
20
|
-
get: function () { return
|
|
20
|
+
get: function () { return chunkXZHR4E2D_js.useExperimentVariant; }
|
|
21
21
|
});
|
|
22
22
|
Object.defineProperty(exports, "SignalBridge", {
|
|
23
23
|
enumerable: true,
|
|
24
|
-
get: function () { return
|
|
24
|
+
get: function () { return chunkVDEQVXNV_js.SignalBridge; }
|
|
25
25
|
});
|
|
26
26
|
Object.defineProperty(exports, "useSignal", {
|
|
27
27
|
enumerable: true,
|
|
28
|
-
get: function () { return
|
|
28
|
+
get: function () { return chunkVDEQVXNV_js.useSignal; }
|
|
29
29
|
});
|
|
30
30
|
Object.defineProperty(exports, "useSignalConfig", {
|
|
31
31
|
enumerable: true,
|
|
32
|
-
get: function () { return
|
|
32
|
+
get: function () { return chunkVDEQVXNV_js.useSignalConfig; }
|
|
33
33
|
});
|
|
34
34
|
Object.defineProperty(exports, "useSignalEvent", {
|
|
35
35
|
enumerable: true,
|
|
36
|
-
get: function () { return
|
|
36
|
+
get: function () { return chunkVDEQVXNV_js.useSignalEvent; }
|
|
37
37
|
});
|
|
38
38
|
Object.defineProperty(exports, "useSignalExperiment", {
|
|
39
39
|
enumerable: true,
|
|
40
|
-
get: function () { return
|
|
40
|
+
get: function () { return chunkVDEQVXNV_js.useSignalExperiment; }
|
|
41
41
|
});
|
|
42
42
|
Object.defineProperty(exports, "useSignalOutcome", {
|
|
43
43
|
enumerable: true,
|
|
44
|
-
get: function () { return
|
|
44
|
+
get: function () { return chunkVDEQVXNV_js.useSignalOutcome; }
|
|
45
45
|
});
|
|
46
46
|
//# sourceMappingURL=index.js.map
|
|
47
47
|
//# sourceMappingURL=index.js.map
|
package/dist/signal/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { ExperimentConversion, SignalExperiment, useExperimentVariant } from '../chunk-
|
|
3
|
-
export { SignalBridge, useSignal, useSignalConfig, useSignalEvent, useSignalExperiment, useSignalOutcome } from '../chunk-
|
|
2
|
+
export { ExperimentConversion, SignalExperiment, useExperimentVariant } from '../chunk-TPDDSEL3.mjs';
|
|
3
|
+
export { SignalBridge, useSignal, useSignalConfig, useSignalEvent, useSignalExperiment, useSignalOutcome } from '../chunk-GSU6VTCZ.mjs';
|
|
4
4
|
import '../chunk-BEXTDHO4.mjs';
|
|
5
5
|
//# sourceMappingURL=index.mjs.map
|
|
6
6
|
//# sourceMappingURL=index.mjs.map
|
package/dist/sitemap/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkOIPG3EGM_js = require('../chunk-OIPG3EGM.js');
|
|
4
4
|
require('../chunk-KR7ATPAN.js');
|
|
5
|
-
require('../chunk-
|
|
5
|
+
require('../chunk-55J2KE7D.js');
|
|
6
6
|
var chunkJP5WGL75_js = require('../chunk-JP5WGL75.js');
|
|
7
7
|
var chunkLVGSOW2F_js = require('../chunk-LVGSOW2F.js');
|
|
8
8
|
require('../chunk-H6AU3WKF.js');
|
|
@@ -504,7 +504,7 @@ function createSitemap(config) {
|
|
|
504
504
|
try {
|
|
505
505
|
let llmsTimer;
|
|
506
506
|
const writeResult = await Promise.race([
|
|
507
|
-
|
|
507
|
+
chunkOIPG3EGM_js.writeLLMsTxtToPublic({
|
|
508
508
|
apiUrl,
|
|
509
509
|
apiKey,
|
|
510
510
|
site: siteHost || void 0,
|
package/dist/sitemap/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { writeLLMsTxtToPublic } from '../chunk-
|
|
1
|
+
import { writeLLMsTxtToPublic } from '../chunk-H4TSADY3.mjs';
|
|
2
2
|
import '../chunk-5YVQWLSQ.mjs';
|
|
3
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-6C47333H.mjs';
|
|
4
4
|
import { getSiteConfig } from '../chunk-B22WSN4L.mjs';
|
|
5
5
|
import { buildFetch } from '../chunk-BQP6JIE2.mjs';
|
|
6
6
|
import '../chunk-PENNTSJE.mjs';
|