@sonordev/site-kit 5.5.0 → 5.7.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 +11 -3
- package/dist/AnalyticsProvider-EWF7JN2X.mjs +11 -0
- package/dist/{AnalyticsProvider-KFXAH4GR.mjs.map → AnalyticsProvider-EWF7JN2X.mjs.map} +1 -1
- package/dist/AnalyticsProvider-GJFG7YXA.js +32 -0
- package/dist/{AnalyticsProvider-WDDW3IJW.js.map → AnalyticsProvider-GJFG7YXA.js.map} +1 -1
- package/dist/{BlogViewTracker-D4DIEP4Q.js → BlogViewTracker-2D3IJPJK.js} +6 -6
- package/dist/{BlogViewTracker-D4DIEP4Q.js.map → BlogViewTracker-2D3IJPJK.js.map} +1 -1
- package/dist/{BlogViewTracker-ZVEGGH3Y.mjs → BlogViewTracker-CKYG6MYU.mjs} +5 -5
- package/dist/{BlogViewTracker-ZVEGGH3Y.mjs.map → BlogViewTracker-CKYG6MYU.mjs.map} +1 -1
- package/dist/ChatWidget-AWP6GBVW.js +22 -0
- package/dist/{ChatWidget-2ZYPYIMQ.js.map → ChatWidget-AWP6GBVW.js.map} +1 -1
- package/dist/ChatWidget-Z5QXDZP3.mjs +13 -0
- package/dist/{ChatWidget-FYCCLMQE.mjs.map → ChatWidget-Z5QXDZP3.mjs.map} +1 -1
- package/dist/EngageWidget-BKEY5TPO.mjs +12 -0
- package/dist/{EngageWidget-6HUZYOY7.mjs.map → EngageWidget-BKEY5TPO.mjs.map} +1 -1
- package/dist/EngageWidget-VT4DYXVO.js +21 -0
- package/dist/{EngageWidget-MYQTBBW6.js.map → EngageWidget-VT4DYXVO.js.map} +1 -1
- package/dist/{FileField-JK2S24XU.js → FileField-62ZWZMQK.js} +6 -6
- package/dist/{FileField-JK2S24XU.js.map → FileField-62ZWZMQK.js.map} +1 -1
- package/dist/{FileField-OZZHWGPA.mjs → FileField-JJN5QKDL.mjs} +5 -5
- package/dist/{FileField-OZZHWGPA.mjs.map → FileField-JJN5QKDL.mjs.map} +1 -1
- package/dist/{FormSpotlight-XV42L72H.mjs → FormSpotlight-OTFB6QM5.mjs} +3 -3
- package/dist/{FormSpotlight-XV42L72H.mjs.map → FormSpotlight-OTFB6QM5.mjs.map} +1 -1
- package/dist/{FormSpotlight-5AXFQU5M.js → FormSpotlight-URS4XRS7.js} +15 -15
- package/dist/{FormSpotlight-5AXFQU5M.js.map → FormSpotlight-URS4XRS7.js.map} +1 -1
- package/dist/{FormStage-HATUHNRV.js → FormStage-FVKMIV73.js} +13 -13
- package/dist/{FormStage-HATUHNRV.js.map → FormStage-FVKMIV73.js.map} +1 -1
- package/dist/{FormStage-RUK675HV.mjs → FormStage-VPGOCMAV.mjs} +3 -3
- package/dist/{FormStage-RUK675HV.mjs.map → FormStage-VPGOCMAV.mjs.map} +1 -1
- package/dist/ManagedForm-CXVDJMHN.mjs +14 -0
- package/dist/{ManagedForm-OA3MNGXT.mjs.map → ManagedForm-CXVDJMHN.mjs.map} +1 -1
- package/dist/ManagedForm-FGNTDGED.js +23 -0
- package/dist/{ManagedForm-JWEXJEXK.js.map → ManagedForm-FGNTDGED.js.map} +1 -1
- package/dist/{ManagedNewsletterForm-AAHH63KT.js → ManagedNewsletterForm-3O5L44AZ.js} +8 -8
- package/dist/{ManagedNewsletterForm-AAHH63KT.js.map → ManagedNewsletterForm-3O5L44AZ.js.map} +1 -1
- package/dist/{ManagedNewsletterForm-HZKTNWLW.mjs → ManagedNewsletterForm-SQYB4BZU.mjs} +7 -7
- package/dist/{ManagedNewsletterForm-HZKTNWLW.mjs.map → ManagedNewsletterForm-SQYB4BZU.mjs.map} +1 -1
- package/dist/{SignalCore-X3GDGBZD.mjs → SignalCore-M2PKKIGH.mjs} +5 -5
- package/dist/{SignalCore-X3GDGBZD.mjs.map → SignalCore-M2PKKIGH.mjs.map} +1 -1
- package/dist/{SignalCore-YSNZYBKJ.js → SignalCore-RFBOBNLQ.js} +11 -11
- package/dist/{SignalCore-YSNZYBKJ.js.map → SignalCore-RFBOBNLQ.js.map} +1 -1
- package/dist/SitemapSync-4OVMIIGC.mjs +9 -0
- package/dist/{SitemapSync-2PTDBH5E.mjs.map → SitemapSync-4OVMIIGC.mjs.map} +1 -1
- package/dist/SitemapSync-RK3SQ4M2.js +18 -0
- package/dist/{SitemapSync-3SFAI546.js.map → SitemapSync-RK3SQ4M2.js.map} +1 -1
- package/dist/SitemapSync.d.ts +3 -2
- package/dist/SitemapSync.d.ts.map +1 -1
- package/dist/analytics/AnalyticsProvider.d.ts +3 -1
- package/dist/analytics/AnalyticsProvider.d.ts.map +1 -1
- package/dist/analytics/WebVitals.d.ts +3 -1
- package/dist/analytics/WebVitals.d.ts.map +1 -1
- package/dist/analytics/index.js +13 -13
- package/dist/analytics/index.mjs +5 -5
- package/dist/analytics/send-gate.d.ts +8 -37
- package/dist/analytics/send-gate.d.ts.map +1 -1
- package/dist/blog/index.js +20 -20
- package/dist/blog/index.mjs +3 -3
- package/dist/blog/metadata-images.test.d.ts +2 -0
- package/dist/blog/metadata-images.test.d.ts.map +1 -0
- package/dist/blog/server-core.d.ts +31 -6
- package/dist/blog/server-core.d.ts.map +1 -1
- package/dist/blog/server-ui.js +16 -16
- package/dist/blog/server-ui.mjs +3 -3
- package/dist/blog/server.d.ts +31 -6
- package/dist/blog/server.d.ts.map +1 -1
- package/dist/blog/server.js +40 -40
- package/dist/blog/server.mjs +1 -1
- package/dist/blog/static-params.test.d.ts +2 -0
- package/dist/blog/static-params.test.d.ts.map +1 -0
- package/dist/{chunk-KAUUGRYB.js → chunk-2N27LCZH.js} +26 -32
- package/dist/chunk-2N27LCZH.js.map +1 -0
- package/dist/{chunk-R4MX6EOM.mjs → chunk-3CLP35TT.mjs} +7 -7
- package/dist/{chunk-R4MX6EOM.mjs.map → chunk-3CLP35TT.mjs.map} +1 -1
- package/dist/{chunk-SQVYLIIN.js → chunk-3S5JN6KL.js} +16 -19
- package/dist/chunk-3S5JN6KL.js.map +1 -0
- package/dist/chunk-3UC6JETG.js +32 -0
- package/dist/chunk-3UC6JETG.js.map +1 -0
- package/dist/{chunk-CT5REGAK.js → chunk-3YQILJKJ.js} +14 -14
- package/dist/{chunk-CT5REGAK.js.map → chunk-3YQILJKJ.js.map} +1 -1
- package/dist/{chunk-3B6CXGAK.mjs → chunk-47XQWV4S.mjs} +3 -3
- package/dist/{chunk-3B6CXGAK.mjs.map → chunk-47XQWV4S.mjs.map} +1 -1
- package/dist/{chunk-RZUZMUTN.mjs → chunk-4A5V73SR.mjs} +21 -9
- package/dist/chunk-4A5V73SR.mjs.map +1 -0
- package/dist/{chunk-FYVLQ3OU.js → chunk-4UVM7E2W.js} +3 -3
- package/dist/{chunk-FYVLQ3OU.js.map → chunk-4UVM7E2W.js.map} +1 -1
- package/dist/{chunk-HFJQMIFM.js → chunk-4WBTM6YE.js} +4 -4
- package/dist/{chunk-HFJQMIFM.js.map → chunk-4WBTM6YE.js.map} +1 -1
- package/dist/{chunk-XQYC4KMH.mjs → chunk-57AFHENV.mjs} +48 -42
- package/dist/chunk-57AFHENV.mjs.map +1 -0
- package/dist/chunk-5RNAUYWE.js +50 -0
- package/dist/chunk-5RNAUYWE.js.map +1 -0
- package/dist/chunk-5TXXTYXL.js +8 -0
- package/dist/{chunk-SUZ3ZLB2.js.map → chunk-5TXXTYXL.js.map} +1 -1
- package/dist/{chunk-RU54J2PY.mjs → chunk-6FC5Q4KU.mjs} +3 -3
- package/dist/{chunk-RU54J2PY.mjs.map → chunk-6FC5Q4KU.mjs.map} +1 -1
- package/dist/{chunk-ZRQFG3L6.mjs → chunk-7ZX6TO6C.mjs} +4 -4
- package/dist/{chunk-ZRQFG3L6.mjs.map → chunk-7ZX6TO6C.mjs.map} +1 -1
- package/dist/chunk-A6UYV475.mjs +45 -0
- package/dist/chunk-A6UYV475.mjs.map +1 -0
- package/dist/{chunk-4XGACM7D.mjs → chunk-ABZGEHTC.mjs} +3 -3
- package/dist/{chunk-4XGACM7D.mjs.map → chunk-ABZGEHTC.mjs.map} +1 -1
- package/dist/chunk-AWK57R5S.mjs +29 -0
- package/dist/chunk-AWK57R5S.mjs.map +1 -0
- package/dist/{chunk-EEQYKMGH.mjs → chunk-BFJOZ3MU.mjs} +23 -17
- package/dist/chunk-BFJOZ3MU.mjs.map +1 -0
- package/dist/{chunk-HX3BRMOX.js → chunk-BFM5PEFV.js} +3 -3
- package/dist/{chunk-HX3BRMOX.js.map → chunk-BFM5PEFV.js.map} +1 -1
- package/dist/{chunk-VYHRAICF.mjs → chunk-BQGEVMIR.mjs} +4 -4
- package/dist/{chunk-VYHRAICF.mjs.map → chunk-BQGEVMIR.mjs.map} +1 -1
- package/dist/{chunk-S6FEC6UT.mjs → chunk-BUJWXSYZ.mjs} +14 -17
- package/dist/chunk-BUJWXSYZ.mjs.map +1 -0
- package/dist/{chunk-VAS3LH5W.js → chunk-C4PZ2R3B.js} +55 -49
- package/dist/chunk-C4PZ2R3B.js.map +1 -0
- package/dist/{chunk-MU7IEPDG.mjs → chunk-C563AHZZ.mjs} +3 -3
- package/dist/{chunk-MU7IEPDG.mjs.map → chunk-C563AHZZ.mjs.map} +1 -1
- package/dist/{chunk-746RKQHA.js → chunk-CPY74A4F.js} +23 -17
- package/dist/chunk-CPY74A4F.js.map +1 -0
- package/dist/{chunk-UNPEMSLK.js → chunk-D553G64G.js} +24 -12
- package/dist/chunk-D553G64G.js.map +1 -0
- package/dist/{chunk-KPKQKFT4.js → chunk-DOB37PV4.js} +3 -3
- package/dist/{chunk-KPKQKFT4.js.map → chunk-DOB37PV4.js.map} +1 -1
- package/dist/{chunk-2OU4KBUN.js → chunk-ELQ4SRRR.js} +15 -15
- package/dist/{chunk-2OU4KBUN.js.map → chunk-ELQ4SRRR.js.map} +1 -1
- package/dist/{chunk-Q26VZNM2.js → chunk-F3AKYZOH.js} +3 -3
- package/dist/{chunk-Q26VZNM2.js.map → chunk-F3AKYZOH.js.map} +1 -1
- package/dist/{chunk-X2XFLYZ3.mjs → chunk-FBDHKYNF.mjs} +3 -3
- package/dist/{chunk-X2XFLYZ3.mjs.map → chunk-FBDHKYNF.mjs.map} +1 -1
- package/dist/{chunk-BNOQXDPJ.js → chunk-FEWWGEQF.js} +4 -4
- package/dist/{chunk-BNOQXDPJ.js.map → chunk-FEWWGEQF.js.map} +1 -1
- package/dist/{chunk-NZSFOZJV.js → chunk-FO4KGPGF.js} +2 -2
- package/dist/{chunk-NZSFOZJV.js.map → chunk-FO4KGPGF.js.map} +1 -1
- package/dist/{chunk-QEGUI2Q2.js → chunk-H65OX263.js} +15 -15
- package/dist/{chunk-QEGUI2Q2.js.map → chunk-H65OX263.js.map} +1 -1
- package/dist/{chunk-46BMNWE6.js → chunk-H6YVT3BL.js} +2 -2
- package/dist/{chunk-46BMNWE6.js.map → chunk-H6YVT3BL.js.map} +1 -1
- package/dist/{chunk-TX2QQ7IX.mjs → chunk-HBN4A2N4.mjs} +3 -3
- package/dist/{chunk-TX2QQ7IX.mjs.map → chunk-HBN4A2N4.mjs.map} +1 -1
- package/dist/{chunk-AJQI3WTN.mjs → chunk-ILNCUSXW.mjs} +2 -2
- package/dist/{chunk-AJQI3WTN.mjs.map → chunk-ILNCUSXW.mjs.map} +1 -1
- package/dist/{chunk-RMMHWSPP.mjs → chunk-JNAXDFC4.mjs} +3 -3
- package/dist/{chunk-RMMHWSPP.mjs.map → chunk-JNAXDFC4.mjs.map} +1 -1
- package/dist/{chunk-TALEV3IH.mjs → chunk-JQ7M6CVL.mjs} +3 -3
- package/dist/{chunk-TALEV3IH.mjs.map → chunk-JQ7M6CVL.mjs.map} +1 -1
- package/dist/{chunk-2CMSWJWC.js → chunk-JTCQJKJE.js} +18 -18
- package/dist/{chunk-2CMSWJWC.js.map → chunk-JTCQJKJE.js.map} +1 -1
- package/dist/{chunk-7PPNXORV.mjs → chunk-JTF4DFUF.mjs} +25 -31
- package/dist/chunk-JTF4DFUF.mjs.map +1 -0
- package/dist/{chunk-MCJF2KJ6.js → chunk-KXGD4E7G.js} +5 -5
- package/dist/{chunk-MCJF2KJ6.js.map → chunk-KXGD4E7G.js.map} +1 -1
- package/dist/chunk-L4V6TKMJ.mjs +94 -0
- package/dist/chunk-L4V6TKMJ.mjs.map +1 -0
- package/dist/{chunk-W5NVW23S.js → chunk-L7ACQ6PC.js} +4 -4
- package/dist/{chunk-W5NVW23S.js.map → chunk-L7ACQ6PC.js.map} +1 -1
- package/dist/{chunk-WIZRCI6J.mjs → chunk-M5GY2AI3.mjs} +3 -3
- package/dist/{chunk-WIZRCI6J.mjs.map → chunk-M5GY2AI3.mjs.map} +1 -1
- package/dist/{chunk-HBI67P7Y.mjs → chunk-MW2M6O7A.mjs} +18 -14
- package/dist/chunk-MW2M6O7A.mjs.map +1 -0
- package/dist/{chunk-A3F5GRNJ.js → chunk-NOU3JQJK.js} +8 -8
- package/dist/{chunk-A3F5GRNJ.js.map → chunk-NOU3JQJK.js.map} +1 -1
- package/dist/{chunk-DYULWKDC.mjs → chunk-O2VJZOR2.mjs} +14 -33
- package/dist/chunk-O2VJZOR2.mjs.map +1 -0
- package/dist/{chunk-FF5N5D3D.js → chunk-OYOO2OO5.js} +8 -8
- package/dist/{chunk-FF5N5D3D.js.map → chunk-OYOO2OO5.js.map} +1 -1
- package/dist/chunk-P4TB4ROG.js +110 -0
- package/dist/chunk-P4TB4ROG.js.map +1 -0
- package/dist/{chunk-V6NOM7PJ.mjs → chunk-Q7347KP6.mjs} +3 -3
- package/dist/{chunk-V6NOM7PJ.mjs.map → chunk-Q7347KP6.mjs.map} +1 -1
- package/dist/chunk-QRBPT6Z6.mjs +6 -0
- package/dist/{chunk-WDBCXRTT.mjs.map → chunk-QRBPT6Z6.mjs.map} +1 -1
- package/dist/{chunk-G5HUI4BO.mjs → chunk-R2SXXFXZ.mjs} +3 -3
- package/dist/{chunk-G5HUI4BO.mjs.map → chunk-R2SXXFXZ.mjs.map} +1 -1
- package/dist/{chunk-PIPLBBDH.js → chunk-RCSTDJUH.js} +22 -41
- package/dist/chunk-RCSTDJUH.js.map +1 -0
- package/dist/{chunk-Z6S4MWSR.js → chunk-RNAGCAIB.js} +21 -17
- package/dist/chunk-RNAGCAIB.js.map +1 -0
- package/dist/{chunk-AEARU24Q.mjs → chunk-RVRN5U7W.mjs} +2 -2
- package/dist/{chunk-AEARU24Q.mjs.map → chunk-RVRN5U7W.mjs.map} +1 -1
- package/dist/{chunk-DRLHQQBH.mjs → chunk-TDJKGN5Q.mjs} +4 -4
- package/dist/{chunk-DRLHQQBH.mjs.map → chunk-TDJKGN5Q.mjs.map} +1 -1
- package/dist/{chunk-MNYM2XU4.js → chunk-TSZIACRC.js} +4 -4
- package/dist/{chunk-MNYM2XU4.js.map → chunk-TSZIACRC.js.map} +1 -1
- package/dist/{chunk-UZL2QU2V.mjs → chunk-UQ5YULFU.mjs} +4 -4
- package/dist/{chunk-UZL2QU2V.mjs.map → chunk-UQ5YULFU.mjs.map} +1 -1
- package/dist/{chunk-5TGAUWNO.mjs → chunk-V5THCFPG.mjs} +3 -3
- package/dist/{chunk-5TGAUWNO.mjs.map → chunk-V5THCFPG.mjs.map} +1 -1
- package/dist/{chunk-YNC5D3FT.js → chunk-VFGEY6FJ.js} +12 -12
- package/dist/{chunk-YNC5D3FT.js.map → chunk-VFGEY6FJ.js.map} +1 -1
- package/dist/{chunk-OFSA7LUH.mjs → chunk-XLPU3TEE.mjs} +4 -4
- package/dist/{chunk-OFSA7LUH.mjs.map → chunk-XLPU3TEE.mjs.map} +1 -1
- package/dist/{chunk-YYAFHIY7.js → chunk-YKUEFRZI.js} +14 -14
- package/dist/{chunk-YYAFHIY7.js.map → chunk-YKUEFRZI.js.map} +1 -1
- package/dist/{chunk-QFNSM77X.js → chunk-YYDZ2TYR.js} +3 -3
- package/dist/{chunk-QFNSM77X.js.map → chunk-YYDZ2TYR.js.map} +1 -1
- package/dist/cli/agent/checks.d.ts.map +1 -1
- package/dist/cli/api/{uptrade.d.ts → sonor.d.ts} +3 -2
- package/dist/cli/api/sonor.d.ts.map +1 -0
- package/dist/cli/commands/api-routes.d.ts.map +1 -1
- package/dist/cli/commands/config-regression.test.d.ts +2 -0
- package/dist/cli/commands/config-regression.test.d.ts.map +1 -0
- package/dist/cli/commands/faqs.d.ts.map +1 -1
- package/dist/cli/commands/geo.d.ts +4 -0
- package/dist/cli/commands/geo.d.ts.map +1 -1
- package/dist/cli/commands/geo.test.d.ts +2 -0
- package/dist/cli/commands/geo.test.d.ts.map +1 -0
- package/dist/cli/commands/images.d.ts.map +1 -1
- package/dist/cli/commands/locations.d.ts.map +1 -1
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/og.d.ts +10 -1
- package/dist/cli/commands/og.d.ts.map +1 -1
- package/dist/cli/commands/scaffold.d.ts +1 -2
- package/dist/cli/commands/scaffold.d.ts.map +1 -1
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/sync.d.ts.map +1 -1
- package/dist/cli/config.d.ts +31 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.test.d.ts +2 -0
- package/dist/cli/config.test.d.ts.map +1 -0
- package/dist/cli/generators/index.d.ts +5 -0
- package/dist/cli/generators/index.d.ts.map +1 -1
- package/dist/cli/generators/index.test.d.ts +2 -0
- package/dist/cli/generators/index.test.d.ts.map +1 -0
- package/dist/cli/index.js +717 -634
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +708 -625
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/migrator/index.d.ts +1 -0
- package/dist/cli/migrator/index.d.ts.map +1 -1
- package/dist/cli/state.d.ts +7 -0
- package/dist/cli/state.d.ts.map +1 -0
- package/dist/cli/state.test.d.ts +2 -0
- package/dist/cli/state.test.d.ts.map +1 -0
- 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 +6 -6
- package/dist/discover-FGTKWOL3.mjs +4 -0
- package/dist/{discover-BEJRYNFF.mjs.map → discover-FGTKWOL3.mjs.map} +1 -1
- package/dist/discover-NJZPWTDL.js +21 -0
- package/dist/{discover-WVDYDUJX.js.map → discover-NJZPWTDL.js.map} +1 -1
- package/dist/engage/EngageWidget.d.ts +3 -2
- package/dist/engage/EngageWidget.d.ts.map +1 -1
- package/dist/engage/index.js +11 -10
- package/dist/engage/index.js.map +1 -1
- package/dist/engage/index.mjs +8 -7
- package/dist/engage/index.mjs.map +1 -1
- package/dist/fleet/FleetHeartbeat.d.ts +3 -2
- package/dist/fleet/FleetHeartbeat.d.ts.map +1 -1
- package/dist/fleet/heartbeat.d.ts +3 -2
- package/dist/fleet/heartbeat.d.ts.map +1 -1
- package/dist/fleet/heartbeat.test.d.ts +2 -0
- package/dist/fleet/heartbeat.test.d.ts.map +1 -0
- package/dist/fleet/index.js +9 -8
- package/dist/fleet/index.mjs +5 -4
- package/dist/forms/index.js +16 -16
- package/dist/forms/index.mjs +9 -9
- package/dist/forms/server.js +10 -10
- package/dist/forms/server.mjs +8 -8
- package/dist/forms/static.js +7 -7
- package/dist/forms/static.mjs +6 -6
- package/dist/images/index.js +11 -11
- package/dist/images/index.mjs +4 -4
- package/dist/index.js +69 -69
- package/dist/index.mjs +11 -11
- package/dist/layout/SiteKitClientProviders.d.ts.map +1 -1
- package/dist/layout/client.d.ts.map +1 -1
- package/dist/layout/client.js +9 -8
- package/dist/layout/client.mjs +8 -7
- package/dist/layout/index.js +11 -10
- package/dist/layout/index.js.map +1 -1
- package/dist/layout/index.mjs +9 -8
- package/dist/layout/index.mjs.map +1 -1
- package/dist/layout/types.d.ts +2 -0
- package/dist/layout/types.d.ts.map +1 -1
- package/dist/llms/aiRobots.d.ts +4 -1
- package/dist/llms/aiRobots.d.ts.map +1 -1
- package/dist/llms/handlers.d.ts +20 -2
- package/dist/llms/handlers.d.ts.map +1 -1
- package/dist/llms/index.js +25 -18
- package/dist/llms/index.js.map +1 -1
- package/dist/llms/index.mjs +15 -8
- package/dist/llms/index.mjs.map +1 -1
- package/dist/llms/wiring.d.ts +81 -0
- package/dist/llms/wiring.d.ts.map +1 -0
- package/dist/llms/wiring.test.d.ts +2 -0
- package/dist/llms/wiring.test.d.ts.map +1 -0
- package/dist/maps/index.js +5 -5
- package/dist/maps/index.mjs +3 -3
- package/dist/og/wiring.d.ts +5 -1
- package/dist/og/wiring.d.ts.map +1 -1
- package/dist/proxy/index.d.ts +16 -11
- package/dist/proxy/index.d.ts.map +1 -1
- package/dist/proxy/index.js +3 -3
- package/dist/proxy/index.js.map +1 -1
- package/dist/proxy/index.mjs +1 -1
- package/dist/proxy/index.mjs.map +1 -1
- package/dist/redirects/index.d.ts +1 -1
- package/dist/redirects/index.js +8 -8
- package/dist/redirects/index.mjs +1 -1
- package/dist/redirects/not-found.d.ts +14 -29
- package/dist/redirects/not-found.d.ts.map +1 -1
- package/dist/redirects/not-found.js +12 -5
- package/dist/redirects/not-found.js.map +1 -1
- package/dist/redirects/not-found.mjs +8 -1
- package/dist/redirects/not-found.mjs.map +1 -1
- package/dist/robots/index.d.ts +5 -1
- package/dist/robots/index.d.ts.map +1 -1
- package/dist/robots/index.js +7 -1
- package/dist/robots/index.js.map +1 -1
- package/dist/robots/index.mjs +4 -1
- package/dist/robots/index.mjs.map +1 -1
- package/dist/robots/index.test.d.ts +2 -0
- package/dist/robots/index.test.d.ts.map +1 -0
- package/dist/robots/next-internals.d.ts +22 -0
- package/dist/robots/next-internals.d.ts.map +1 -0
- package/dist/search/index.js +4 -4
- package/dist/search/index.mjs +3 -3
- package/dist/seo/client.js +6 -6
- package/dist/seo/client.mjs +5 -5
- package/dist/seo/index.js +15 -15
- package/dist/seo/index.mjs +7 -7
- package/dist/seo/register-sitemap-cli.js +4 -4
- package/dist/seo/register-sitemap-cli.mjs +1 -1
- package/dist/seo/server.js +5 -5
- package/dist/seo/server.mjs +1 -1
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +2 -2
- package/dist/shared/next-files.d.ts +35 -0
- package/dist/shared/next-files.d.ts.map +1 -0
- package/dist/shared/next-files.test.d.ts +2 -0
- package/dist/shared/next-files.test.d.ts.map +1 -0
- package/dist/shared/reporting-gate.d.ts +43 -0
- package/dist/shared/reporting-gate.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/discover.d.ts.map +1 -1
- package/dist/sitemap/index.d.ts +6 -1
- package/dist/sitemap/index.d.ts.map +1 -1
- package/dist/sitemap/index.js +5 -12
- package/dist/sitemap/index.js.map +1 -1
- package/dist/sitemap/index.mjs +4 -11
- package/dist/sitemap/index.mjs.map +1 -1
- package/dist/sync/AddToCalendar.d.ts +19 -0
- package/dist/sync/AddToCalendar.d.ts.map +1 -0
- package/dist/sync/BookingWidget.d.ts.map +1 -1
- package/dist/sync/add-to-calendar.test.d.ts +2 -0
- package/dist/sync/add-to-calendar.test.d.ts.map +1 -0
- package/dist/sync/api-errors.test.d.ts +2 -0
- package/dist/sync/api-errors.test.d.ts.map +1 -0
- package/dist/sync/api.d.ts.map +1 -1
- package/dist/sync/index.js +17 -17
- package/dist/sync/index.mjs +4 -4
- package/dist/sync/types.d.ts +14 -0
- package/dist/sync/types.d.ts.map +1 -1
- package/package.json +22 -24
- package/dist/AnalyticsProvider-KFXAH4GR.mjs +0 -11
- package/dist/AnalyticsProvider-WDDW3IJW.js +0 -32
- package/dist/ChatWidget-2ZYPYIMQ.js +0 -22
- package/dist/ChatWidget-FYCCLMQE.mjs +0 -13
- package/dist/EngageWidget-6HUZYOY7.mjs +0 -11
- package/dist/EngageWidget-MYQTBBW6.js +0 -20
- package/dist/ManagedForm-JWEXJEXK.js +0 -23
- package/dist/ManagedForm-OA3MNGXT.mjs +0 -14
- package/dist/SitemapSync-2PTDBH5E.mjs +0 -9
- package/dist/SitemapSync-3SFAI546.js +0 -18
- package/dist/chunk-746RKQHA.js.map +0 -1
- package/dist/chunk-7PPNXORV.mjs.map +0 -1
- package/dist/chunk-DYULWKDC.mjs.map +0 -1
- package/dist/chunk-EEQYKMGH.mjs.map +0 -1
- package/dist/chunk-HBI67P7Y.mjs.map +0 -1
- package/dist/chunk-KAUUGRYB.js.map +0 -1
- package/dist/chunk-LOS5D6B3.js +0 -72
- package/dist/chunk-LOS5D6B3.js.map +0 -1
- package/dist/chunk-NVSWTDWU.mjs +0 -25
- package/dist/chunk-NVSWTDWU.mjs.map +0 -1
- package/dist/chunk-OL2QBWAU.js +0 -29
- package/dist/chunk-OL2QBWAU.js.map +0 -1
- package/dist/chunk-PIPLBBDH.js.map +0 -1
- package/dist/chunk-RZUZMUTN.mjs.map +0 -1
- package/dist/chunk-S6FEC6UT.mjs.map +0 -1
- package/dist/chunk-SQVYLIIN.js.map +0 -1
- package/dist/chunk-SUZ3ZLB2.js +0 -8
- package/dist/chunk-UNPEMSLK.js.map +0 -1
- package/dist/chunk-VAS3LH5W.js.map +0 -1
- package/dist/chunk-WDBCXRTT.mjs +0 -6
- package/dist/chunk-XIJ4F6IE.mjs +0 -63
- package/dist/chunk-XIJ4F6IE.mjs.map +0 -1
- package/dist/chunk-XQYC4KMH.mjs.map +0 -1
- package/dist/chunk-Z6S4MWSR.js.map +0 -1
- package/dist/cli/api/uptrade.d.ts.map +0 -1
- package/dist/discover-BEJRYNFF.mjs +0 -4
- package/dist/discover-WVDYDUJX.js +0 -21
package/dist/cli/index.mjs
CHANGED
|
@@ -3,12 +3,12 @@ import { traverse, isJSXIdentifier, isJSXAttribute, isFunctionDeclaration, isVar
|
|
|
3
3
|
import { parse } from '../chunk-5YA6SI4Z.mjs';
|
|
4
4
|
import { buildOgHtml, TITLE_MAX_PX, OG_REPORT_ATTR } from '../chunk-UJ6CHZAI.mjs';
|
|
5
5
|
import { require_main } from '../chunk-NNZDWY3L.mjs';
|
|
6
|
-
import { findAppDirForDiscovery, discoverNextJsRoutes } from '../chunk-
|
|
7
|
-
import { SITE_KIT_VERSION } from '../chunk-
|
|
6
|
+
import { findAppDirForDiscovery, NEXT_PROXY_FILES, NEXT_MIDDLEWARE_FILES, findConventionFile, NEXT_APP_DIRS, findSitemapRoute, findProxyFiles, findRootLayout, discoverNextJsRoutes, hasPageFile } from '../chunk-L4V6TKMJ.mjs';
|
|
7
|
+
import { SITE_KIT_VERSION } from '../chunk-QRBPT6Z6.mjs';
|
|
8
8
|
import { __commonJS, __require, __toESM, __export, __privateAdd, __publicField, __privateGet, __privateMethod, __privateSet, __privateWrapper } from '../chunk-BEXTDHO4.mjs';
|
|
9
9
|
import { EventEmitter } from 'events';
|
|
10
10
|
import childProcess, { execFile as execFile$1, execSync, spawnSync, spawn } from 'child_process';
|
|
11
|
-
import
|
|
11
|
+
import path12, { win32, posix } from 'path';
|
|
12
12
|
import * as fs from 'fs';
|
|
13
13
|
import fs__default, { realpathSync, existsSync, readFileSync, readdirSync, statSync, readlinkSync, readdir as readdir$1, lstatSync, rmSync, mkdtempSync, writeFileSync } from 'fs';
|
|
14
14
|
import process2 from 'process';
|
|
@@ -6202,10 +6202,10 @@ var require_lib2 = __commonJS({
|
|
|
6202
6202
|
exports.analyse = analyse;
|
|
6203
6203
|
var detectFile = (filepath, opts = {}) => new Promise((resolve, reject) => {
|
|
6204
6204
|
let fd;
|
|
6205
|
-
const
|
|
6205
|
+
const fs30 = (0, node_1.default)();
|
|
6206
6206
|
const handler = (err, buffer) => {
|
|
6207
6207
|
if (fd) {
|
|
6208
|
-
|
|
6208
|
+
fs30.closeSync(fd);
|
|
6209
6209
|
}
|
|
6210
6210
|
if (err) {
|
|
6211
6211
|
reject(err);
|
|
@@ -6217,9 +6217,9 @@ var require_lib2 = __commonJS({
|
|
|
6217
6217
|
};
|
|
6218
6218
|
const sampleSize = (opts === null || opts === void 0 ? void 0 : opts.sampleSize) || 0;
|
|
6219
6219
|
if (sampleSize > 0) {
|
|
6220
|
-
fd =
|
|
6220
|
+
fd = fs30.openSync(filepath, "r");
|
|
6221
6221
|
let sample = Buffer.allocUnsafe(sampleSize);
|
|
6222
|
-
|
|
6222
|
+
fs30.read(fd, sample, 0, sampleSize, opts.offset, (err, bytesRead) => {
|
|
6223
6223
|
if (err) {
|
|
6224
6224
|
handler(err, null);
|
|
6225
6225
|
} else {
|
|
@@ -6231,22 +6231,22 @@ var require_lib2 = __commonJS({
|
|
|
6231
6231
|
});
|
|
6232
6232
|
return;
|
|
6233
6233
|
}
|
|
6234
|
-
|
|
6234
|
+
fs30.readFile(filepath, handler);
|
|
6235
6235
|
});
|
|
6236
6236
|
exports.detectFile = detectFile;
|
|
6237
6237
|
var detectFileSync = (filepath, opts = {}) => {
|
|
6238
|
-
const
|
|
6238
|
+
const fs30 = (0, node_1.default)();
|
|
6239
6239
|
if (opts && opts.sampleSize) {
|
|
6240
|
-
const fd =
|
|
6240
|
+
const fd = fs30.openSync(filepath, "r");
|
|
6241
6241
|
let sample = Buffer.allocUnsafe(opts.sampleSize);
|
|
6242
|
-
const bytesRead =
|
|
6242
|
+
const bytesRead = fs30.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
|
|
6243
6243
|
if (bytesRead < opts.sampleSize) {
|
|
6244
6244
|
sample = sample.subarray(0, bytesRead);
|
|
6245
6245
|
}
|
|
6246
|
-
|
|
6246
|
+
fs30.closeSync(fd);
|
|
6247
6247
|
return (0, exports.detect)(sample);
|
|
6248
6248
|
}
|
|
6249
|
-
return (0, exports.detect)(
|
|
6249
|
+
return (0, exports.detect)(fs30.readFileSync(filepath));
|
|
6250
6250
|
};
|
|
6251
6251
|
exports.detectFileSync = detectFileSync;
|
|
6252
6252
|
exports.default = {
|
|
@@ -10135,7 +10135,7 @@ var require_run_async = __commonJS({
|
|
|
10135
10135
|
});
|
|
10136
10136
|
|
|
10137
10137
|
// src/cli/index.ts
|
|
10138
|
-
var
|
|
10138
|
+
var import_dotenv2 = __toESM(require_main());
|
|
10139
10139
|
|
|
10140
10140
|
// node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js
|
|
10141
10141
|
var CommanderError = class extends Error {
|
|
@@ -12264,9 +12264,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
12264
12264
|
args = args.slice();
|
|
12265
12265
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
12266
12266
|
function findFile(baseDir, baseName) {
|
|
12267
|
-
const localBin =
|
|
12267
|
+
const localBin = path12.resolve(baseDir, baseName);
|
|
12268
12268
|
if (fs__default.existsSync(localBin)) return localBin;
|
|
12269
|
-
if (sourceExt.includes(
|
|
12269
|
+
if (sourceExt.includes(path12.extname(baseName))) return void 0;
|
|
12270
12270
|
const foundExt = sourceExt.find(
|
|
12271
12271
|
(ext2) => fs__default.existsSync(`${localBin}${ext2}`)
|
|
12272
12272
|
);
|
|
@@ -12284,17 +12284,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
12284
12284
|
} catch {
|
|
12285
12285
|
resolvedScriptPath = this._scriptPath;
|
|
12286
12286
|
}
|
|
12287
|
-
executableDir =
|
|
12288
|
-
|
|
12287
|
+
executableDir = path12.resolve(
|
|
12288
|
+
path12.dirname(resolvedScriptPath),
|
|
12289
12289
|
executableDir
|
|
12290
12290
|
);
|
|
12291
12291
|
}
|
|
12292
12292
|
if (executableDir) {
|
|
12293
12293
|
let localFile = findFile(executableDir, executableFile);
|
|
12294
12294
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
12295
|
-
const legacyName =
|
|
12295
|
+
const legacyName = path12.basename(
|
|
12296
12296
|
this._scriptPath,
|
|
12297
|
-
|
|
12297
|
+
path12.extname(this._scriptPath)
|
|
12298
12298
|
);
|
|
12299
12299
|
if (legacyName !== this._name) {
|
|
12300
12300
|
localFile = findFile(
|
|
@@ -12305,7 +12305,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
12305
12305
|
}
|
|
12306
12306
|
executableFile = localFile || executableFile;
|
|
12307
12307
|
}
|
|
12308
|
-
const launchWithNode = sourceExt.includes(
|
|
12308
|
+
const launchWithNode = sourceExt.includes(path12.extname(executableFile));
|
|
12309
12309
|
let proc;
|
|
12310
12310
|
if (process2.platform !== "win32") {
|
|
12311
12311
|
if (launchWithNode) {
|
|
@@ -13222,7 +13222,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
13222
13222
|
* @return {Command}
|
|
13223
13223
|
*/
|
|
13224
13224
|
nameFromFilename(filename) {
|
|
13225
|
-
this._name =
|
|
13225
|
+
this._name = path12.basename(filename, path12.extname(filename));
|
|
13226
13226
|
return this;
|
|
13227
13227
|
}
|
|
13228
13228
|
/**
|
|
@@ -13236,9 +13236,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
13236
13236
|
* @param {string} [path]
|
|
13237
13237
|
* @return {(string|null|Command)}
|
|
13238
13238
|
*/
|
|
13239
|
-
executableDir(
|
|
13240
|
-
if (
|
|
13241
|
-
this._executableDir =
|
|
13239
|
+
executableDir(path30) {
|
|
13240
|
+
if (path30 === void 0) return this._executableDir;
|
|
13241
|
+
this._executableDir = path30;
|
|
13242
13242
|
return this;
|
|
13243
13243
|
}
|
|
13244
13244
|
/**
|
|
@@ -18747,7 +18747,7 @@ function createPrompt(view) {
|
|
|
18747
18747
|
if (nextView === void 0) {
|
|
18748
18748
|
let callerFilename = callSites[1]?.getFileName();
|
|
18749
18749
|
if (callerFilename && !callerFilename.startsWith("file://")) {
|
|
18750
|
-
callerFilename =
|
|
18750
|
+
callerFilename = path12.resolve(callerFilename);
|
|
18751
18751
|
}
|
|
18752
18752
|
throw new Error(`Prompt functions must return a string.
|
|
18753
18753
|
at ${callerFilename}`);
|
|
@@ -19136,13 +19136,13 @@ var ExternalEditor = class {
|
|
|
19136
19136
|
}
|
|
19137
19137
|
createTempFile() {
|
|
19138
19138
|
try {
|
|
19139
|
-
const baseDir =
|
|
19140
|
-
this.tempDir = mkdtempSync(
|
|
19139
|
+
const baseDir = path12.resolve(this.fileOptions.dir ?? os.tmpdir());
|
|
19140
|
+
this.tempDir = mkdtempSync(path12.join(baseDir, "inquirer-editor-"));
|
|
19141
19141
|
const id = randomUUID();
|
|
19142
19142
|
const prefix = sanitizeAffix(this.fileOptions.prefix);
|
|
19143
19143
|
const postfix = sanitizeAffix(this.fileOptions.postfix);
|
|
19144
19144
|
const filename = `${prefix}${id}${postfix}`;
|
|
19145
|
-
this.tempFile =
|
|
19145
|
+
this.tempFile = path12.join(this.tempDir, filename);
|
|
19146
19146
|
const opt = { encoding: "utf8", flag: "wx" };
|
|
19147
19147
|
if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
|
|
19148
19148
|
opt.mode = this.fileOptions.mode;
|
|
@@ -20345,9 +20345,9 @@ function observableToAsyncIterable(source) {
|
|
|
20345
20345
|
|
|
20346
20346
|
// node_modules/.pnpm/inquirer@14.0.2_@types+node@26.2.0/node_modules/inquirer/dist/ui/prompt.js
|
|
20347
20347
|
var _ = {
|
|
20348
|
-
set: (obj,
|
|
20348
|
+
set: (obj, path30 = "", value) => {
|
|
20349
20349
|
let pointer = obj;
|
|
20350
|
-
|
|
20350
|
+
path30.split(".").forEach((key, index, arr) => {
|
|
20351
20351
|
if (key === "__proto__" || key === "constructor")
|
|
20352
20352
|
return;
|
|
20353
20353
|
if (index === arr.length - 1) {
|
|
@@ -20358,8 +20358,8 @@ var _ = {
|
|
|
20358
20358
|
pointer = pointer[key];
|
|
20359
20359
|
});
|
|
20360
20360
|
},
|
|
20361
|
-
get: (obj,
|
|
20362
|
-
const travel = (regexp) => String.prototype.split.call(
|
|
20361
|
+
get: (obj, path30 = "", defaultValue) => {
|
|
20362
|
+
const travel = (regexp) => String.prototype.split.call(path30, regexp).filter(Boolean).reduce(
|
|
20363
20363
|
// @ts-expect-error implicit any on res[key]
|
|
20364
20364
|
(res, key) => res == null ? res : res[key],
|
|
20365
20365
|
obj
|
|
@@ -20649,7 +20649,7 @@ async function scanCodebase(rootDir) {
|
|
|
20649
20649
|
for (const file of files) {
|
|
20650
20650
|
try {
|
|
20651
20651
|
const content = await fs3.readFile(file, "utf-8");
|
|
20652
|
-
const relPath =
|
|
20652
|
+
const relPath = path12.relative(rootDir, file);
|
|
20653
20653
|
const ast = parse(content, {
|
|
20654
20654
|
sourceType: "module",
|
|
20655
20655
|
plugins: ["jsx", "typescript"]
|
|
@@ -20698,7 +20698,7 @@ async function scanCodebase(rootDir) {
|
|
|
20698
20698
|
async function findSourceFiles(dir, files = []) {
|
|
20699
20699
|
const entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
20700
20700
|
for (const entry of entries) {
|
|
20701
|
-
const fullPath =
|
|
20701
|
+
const fullPath = path12.join(dir, entry.name);
|
|
20702
20702
|
if (entry.isDirectory()) {
|
|
20703
20703
|
if (["node_modules", ".next", ".git", "dist", "build"].includes(entry.name)) {
|
|
20704
20704
|
continue;
|
|
@@ -20716,18 +20716,18 @@ function scanForForms(ast, content, filePath) {
|
|
|
20716
20716
|
const forms = [];
|
|
20717
20717
|
content.split("\n");
|
|
20718
20718
|
traverse(ast, {
|
|
20719
|
-
JSXElement(
|
|
20720
|
-
const opening =
|
|
20719
|
+
JSXElement(path30) {
|
|
20720
|
+
const opening = path30.node.openingElement;
|
|
20721
20721
|
if (isJSXIdentifier(opening.name) && opening.name.name === "form") {
|
|
20722
|
-
const fields = extractFieldsFromForm(
|
|
20722
|
+
const fields = extractFieldsFromForm(path30);
|
|
20723
20723
|
const hasOnSubmit = opening.attributes.some(
|
|
20724
20724
|
(attr) => isJSXAttribute(attr) && isJSXIdentifier(attr.name) && attr.name.name === "onSubmit"
|
|
20725
20725
|
);
|
|
20726
20726
|
if (hasOnSubmit && fields.length > 0) {
|
|
20727
|
-
const startLine =
|
|
20728
|
-
const endLine =
|
|
20727
|
+
const startLine = path30.node.loc?.start.line || 0;
|
|
20728
|
+
const endLine = path30.node.loc?.end.line || 0;
|
|
20729
20729
|
let componentName = "UnknownForm";
|
|
20730
|
-
let current =
|
|
20730
|
+
let current = path30.parentPath;
|
|
20731
20731
|
while (current) {
|
|
20732
20732
|
if (isFunctionDeclaration(current.node) && current.node.id) {
|
|
20733
20733
|
componentName = current.node.id.name;
|
|
@@ -20760,7 +20760,7 @@ function scanForForms(ast, content, filePath) {
|
|
|
20760
20760
|
}
|
|
20761
20761
|
if (isJSXIdentifier(opening.name) && opening.name.name === "Form") {
|
|
20762
20762
|
if (content.includes("Formik") || content.includes("formik")) {
|
|
20763
|
-
const fields = extractFieldsFromFormik(
|
|
20763
|
+
const fields = extractFieldsFromFormik(path30);
|
|
20764
20764
|
if (fields.length > 0) {
|
|
20765
20765
|
forms.push({
|
|
20766
20766
|
filePath,
|
|
@@ -20771,8 +20771,8 @@ function scanForForms(ast, content, filePath) {
|
|
|
20771
20771
|
submitsTo: null,
|
|
20772
20772
|
complexity: "moderate",
|
|
20773
20773
|
suggestedAction: "assisted",
|
|
20774
|
-
startLine:
|
|
20775
|
-
endLine:
|
|
20774
|
+
startLine: path30.node.loc?.start.line || 0,
|
|
20775
|
+
endLine: path30.node.loc?.end.line || 0
|
|
20776
20776
|
});
|
|
20777
20777
|
}
|
|
20778
20778
|
}
|
|
@@ -20790,8 +20790,8 @@ function extractFieldsFromForm(formPath) {
|
|
|
20790
20790
|
const radioGroups = /* @__PURE__ */ new Map();
|
|
20791
20791
|
const checkboxGroups = /* @__PURE__ */ new Map();
|
|
20792
20792
|
formPath.traverse({
|
|
20793
|
-
JSXElement(
|
|
20794
|
-
const opening =
|
|
20793
|
+
JSXElement(path30) {
|
|
20794
|
+
const opening = path30.node.openingElement;
|
|
20795
20795
|
const tagName = isJSXIdentifier(opening.name) ? opening.name.name : null;
|
|
20796
20796
|
if (["input", "textarea", "select"].includes(tagName || "")) {
|
|
20797
20797
|
const attrs = opening.attributes;
|
|
@@ -20838,7 +20838,7 @@ function extractFieldsFromForm(formPath) {
|
|
|
20838
20838
|
}
|
|
20839
20839
|
if (tagName === "select") {
|
|
20840
20840
|
const selectOptions = [];
|
|
20841
|
-
|
|
20841
|
+
path30.traverse({
|
|
20842
20842
|
JSXElement(optionPath) {
|
|
20843
20843
|
const optOpening = optionPath.node.openingElement;
|
|
20844
20844
|
const optTagName = isJSXIdentifier(optOpening.name) ? optOpening.name.name : null;
|
|
@@ -20913,8 +20913,8 @@ function extractFieldsFromForm(formPath) {
|
|
|
20913
20913
|
function extractFieldsFromFormik(formPath, content) {
|
|
20914
20914
|
const fields = [];
|
|
20915
20915
|
formPath.traverse({
|
|
20916
|
-
JSXElement(
|
|
20917
|
-
const opening =
|
|
20916
|
+
JSXElement(path30) {
|
|
20917
|
+
const opening = path30.node.openingElement;
|
|
20918
20918
|
const tagName = isJSXIdentifier(opening.name) ? opening.name.name : null;
|
|
20919
20919
|
if (tagName === "Field" || tagName === "FastField") {
|
|
20920
20920
|
const attrs = opening.attributes;
|
|
@@ -21033,11 +21033,11 @@ function scanForMetadata(ast, content, filePath) {
|
|
|
21033
21033
|
}
|
|
21034
21034
|
let hasHeadComponent = false;
|
|
21035
21035
|
traverse(ast, {
|
|
21036
|
-
JSXElement(
|
|
21037
|
-
const opening =
|
|
21036
|
+
JSXElement(path30) {
|
|
21037
|
+
const opening = path30.node.openingElement;
|
|
21038
21038
|
if (isJSXIdentifier(opening.name) && opening.name.name === "Head") {
|
|
21039
21039
|
hasHeadComponent = true;
|
|
21040
|
-
|
|
21040
|
+
path30.stop();
|
|
21041
21041
|
}
|
|
21042
21042
|
}
|
|
21043
21043
|
});
|
|
@@ -21072,8 +21072,8 @@ function scanForWidgets(ast, content, filePath) {
|
|
|
21072
21072
|
for (const { pattern, type } of widgetPatterns) {
|
|
21073
21073
|
if (pattern.test(content)) {
|
|
21074
21074
|
traverse(ast, {
|
|
21075
|
-
JSXElement(
|
|
21076
|
-
const opening =
|
|
21075
|
+
JSXElement(path30) {
|
|
21076
|
+
const opening = path30.node.openingElement;
|
|
21077
21077
|
if (isJSXIdentifier(opening.name) && (opening.name.name === "script" || opening.name.name === "Script")) {
|
|
21078
21078
|
const srcAttr = opening.attributes.find(
|
|
21079
21079
|
(attr) => isJSXAttribute(attr) && isJSXIdentifier(attr.name) && attr.name.name === "src"
|
|
@@ -21088,8 +21088,8 @@ function scanForWidgets(ast, content, filePath) {
|
|
|
21088
21088
|
filePath,
|
|
21089
21089
|
widgetType: type,
|
|
21090
21090
|
scriptTag: src,
|
|
21091
|
-
startLine:
|
|
21092
|
-
endLine:
|
|
21091
|
+
startLine: path30.node.loc?.start.line || 0,
|
|
21092
|
+
endLine: path30.node.loc?.end.line || 0
|
|
21093
21093
|
});
|
|
21094
21094
|
}
|
|
21095
21095
|
}
|
|
@@ -21163,7 +21163,7 @@ async function scanForSitemapFiles(rootDir) {
|
|
|
21163
21163
|
"next-sitemap.config.ts"
|
|
21164
21164
|
];
|
|
21165
21165
|
for (const configPath of configPaths) {
|
|
21166
|
-
const fullPath =
|
|
21166
|
+
const fullPath = path12.join(rootDir, configPath);
|
|
21167
21167
|
try {
|
|
21168
21168
|
await fs3.access(fullPath);
|
|
21169
21169
|
const content = await fs3.readFile(fullPath, "utf-8");
|
|
@@ -21181,7 +21181,7 @@ async function scanForSitemapFiles(rootDir) {
|
|
|
21181
21181
|
} catch {
|
|
21182
21182
|
}
|
|
21183
21183
|
}
|
|
21184
|
-
const staticSitemapPath =
|
|
21184
|
+
const staticSitemapPath = path12.join(rootDir, "public", "sitemap.xml");
|
|
21185
21185
|
try {
|
|
21186
21186
|
await fs3.access(staticSitemapPath);
|
|
21187
21187
|
const content = await fs3.readFile(staticSitemapPath, "utf-8");
|
|
@@ -21204,7 +21204,7 @@ async function scanForSitemapFiles(rootDir) {
|
|
|
21204
21204
|
"out/sitemap.xml"
|
|
21205
21205
|
];
|
|
21206
21206
|
for (const genPath of generatedPaths) {
|
|
21207
|
-
const fullPath =
|
|
21207
|
+
const fullPath = path12.join(rootDir, genPath);
|
|
21208
21208
|
try {
|
|
21209
21209
|
await fs3.access(fullPath);
|
|
21210
21210
|
} catch {
|
|
@@ -21228,8 +21228,8 @@ function scanForSchemas(ast, content, filePath) {
|
|
|
21228
21228
|
return schemas;
|
|
21229
21229
|
}
|
|
21230
21230
|
traverse(ast, {
|
|
21231
|
-
JSXElement(
|
|
21232
|
-
const opening =
|
|
21231
|
+
JSXElement(path30) {
|
|
21232
|
+
const opening = path30.node.openingElement;
|
|
21233
21233
|
if (isJSXIdentifier(opening.name) && (opening.name.name === "script" || opening.name.name === "Script")) {
|
|
21234
21234
|
const typeAttr = opening.attributes.find(
|
|
21235
21235
|
(attr) => isJSXAttribute(attr) && isJSXIdentifier(attr.name) && attr.name.name === "type"
|
|
@@ -21256,8 +21256,8 @@ function scanForSchemas(ast, content, filePath) {
|
|
|
21256
21256
|
filePath,
|
|
21257
21257
|
type: detectedType,
|
|
21258
21258
|
schemaType,
|
|
21259
|
-
startLine:
|
|
21260
|
-
endLine:
|
|
21259
|
+
startLine: path30.node.loc?.start.line || 0,
|
|
21260
|
+
endLine: path30.node.loc?.end.line || 0
|
|
21261
21261
|
});
|
|
21262
21262
|
}
|
|
21263
21263
|
}
|
|
@@ -21290,8 +21290,8 @@ function scanForFAQs(ast, content, filePath) {
|
|
|
21290
21290
|
/questions?\s*(?:and|&)?\s*answers?/i
|
|
21291
21291
|
];
|
|
21292
21292
|
traverse(ast, {
|
|
21293
|
-
JSXElement(
|
|
21294
|
-
const opening =
|
|
21293
|
+
JSXElement(path30) {
|
|
21294
|
+
const opening = path30.node.openingElement;
|
|
21295
21295
|
let tagName = "";
|
|
21296
21296
|
if (isJSXIdentifier(opening.name)) {
|
|
21297
21297
|
tagName = opening.name.name;
|
|
@@ -21304,8 +21304,8 @@ function scanForFAQs(ast, content, filePath) {
|
|
|
21304
21304
|
faqs.push({
|
|
21305
21305
|
filePath,
|
|
21306
21306
|
type: "details-summary",
|
|
21307
|
-
startLine:
|
|
21308
|
-
endLine:
|
|
21307
|
+
startLine: path30.node.loc?.start.line || 0,
|
|
21308
|
+
endLine: path30.node.loc?.end.line || 0,
|
|
21309
21309
|
hasSchema: content.includes("FAQPage") || content.includes("application/ld+json")
|
|
21310
21310
|
});
|
|
21311
21311
|
return;
|
|
@@ -21313,7 +21313,7 @@ function scanForFAQs(ast, content, filePath) {
|
|
|
21313
21313
|
for (const pattern of faqPatterns) {
|
|
21314
21314
|
if (pattern.test(tagName)) {
|
|
21315
21315
|
let itemCount = 0;
|
|
21316
|
-
|
|
21316
|
+
path30.traverse({
|
|
21317
21317
|
JSXElement(itemPath) {
|
|
21318
21318
|
const itemOpening = itemPath.node.openingElement;
|
|
21319
21319
|
if (isJSXIdentifier(itemOpening.name)) {
|
|
@@ -21329,8 +21329,8 @@ function scanForFAQs(ast, content, filePath) {
|
|
|
21329
21329
|
type: "accordion",
|
|
21330
21330
|
componentName: tagName,
|
|
21331
21331
|
itemCount: itemCount || void 0,
|
|
21332
|
-
startLine:
|
|
21333
|
-
endLine:
|
|
21332
|
+
startLine: path30.node.loc?.start.line || 0,
|
|
21333
|
+
endLine: path30.node.loc?.end.line || 0,
|
|
21334
21334
|
hasSchema: content.includes("FAQPage") || content.includes("application/ld+json")
|
|
21335
21335
|
});
|
|
21336
21336
|
return;
|
|
@@ -21453,8 +21453,8 @@ function scanForImages(ast, content, filePath) {
|
|
|
21453
21453
|
return images;
|
|
21454
21454
|
}
|
|
21455
21455
|
traverse(ast, {
|
|
21456
|
-
JSXElement(
|
|
21457
|
-
const opening =
|
|
21456
|
+
JSXElement(path30) {
|
|
21457
|
+
const opening = path30.node.openingElement;
|
|
21458
21458
|
if (!isJSXIdentifier(opening.name)) return;
|
|
21459
21459
|
const tagName = opening.name.name;
|
|
21460
21460
|
if (tagName === "img" || tagName === "Image") {
|
|
@@ -21482,8 +21482,8 @@ function scanForImages(ast, content, filePath) {
|
|
|
21482
21482
|
src: src || void 0,
|
|
21483
21483
|
alt: alt || void 0,
|
|
21484
21484
|
isLocal,
|
|
21485
|
-
startLine:
|
|
21486
|
-
endLine:
|
|
21485
|
+
startLine: path30.node.loc?.start.line || 0,
|
|
21486
|
+
endLine: path30.node.loc?.end.line || 0
|
|
21487
21487
|
});
|
|
21488
21488
|
}
|
|
21489
21489
|
}
|
|
@@ -21688,7 +21688,7 @@ async function migrateFiles(scanResults, options) {
|
|
|
21688
21688
|
}
|
|
21689
21689
|
async function migrateForm(form, options) {
|
|
21690
21690
|
const changes = [];
|
|
21691
|
-
const fullPath =
|
|
21691
|
+
const fullPath = path12.resolve(process.cwd(), form.filePath);
|
|
21692
21692
|
const formSlug = generateSlug(form.componentName);
|
|
21693
21693
|
let formId;
|
|
21694
21694
|
if (!options.dryRun) {
|
|
@@ -21827,7 +21827,7 @@ export default ${componentName}
|
|
|
21827
21827
|
`;
|
|
21828
21828
|
}
|
|
21829
21829
|
async function createFormInUptrade(form, slug, options) {
|
|
21830
|
-
const response = await fetch("https://api.sonor.io/forms
|
|
21830
|
+
const response = await fetch(`${options.apiUrl || "https://api.sonor.io"}/forms`, {
|
|
21831
21831
|
method: "POST",
|
|
21832
21832
|
headers: {
|
|
21833
21833
|
"Content-Type": "application/json",
|
|
@@ -21865,7 +21865,7 @@ async function migrateWidget(filePath, widget, options) {
|
|
|
21865
21865
|
changes.push("[DRY RUN] Sonor Engage chat would come from SiteKitLayout (engage is on by default)");
|
|
21866
21866
|
return { filePath, success: true, changes };
|
|
21867
21867
|
}
|
|
21868
|
-
const fullPath =
|
|
21868
|
+
const fullPath = path12.resolve(process.cwd(), filePath);
|
|
21869
21869
|
let content = await fs3.readFile(fullPath, "utf-8");
|
|
21870
21870
|
switch (widget.widgetType) {
|
|
21871
21871
|
case "intercom":
|
|
@@ -21902,15 +21902,15 @@ function matchBalancedBraces(content, startIndex) {
|
|
|
21902
21902
|
}
|
|
21903
21903
|
async function migrateMetadata(filePath, metadata, options) {
|
|
21904
21904
|
const changes = [];
|
|
21905
|
-
const fullPath =
|
|
21905
|
+
const fullPath = path12.resolve(process.cwd(), filePath);
|
|
21906
21906
|
let pagePath = filePath.replace(/^app\//, "/").replace(/^src\/app\//, "/").replace(/\/page\.(tsx?|jsx?)$/, "").replace(/\/layout\.(tsx?|jsx?)$/, "").replace(/\[([^\]]+)\]/g, ":$1");
|
|
21907
21907
|
if (pagePath === "") pagePath = "/";
|
|
21908
21908
|
let content = await fs3.readFile(fullPath, "utf-8");
|
|
21909
21909
|
const isTypeScript = filePath.endsWith(".tsx") || filePath.endsWith(".ts");
|
|
21910
21910
|
const ext2 = isTypeScript ? ".tsx" : ".jsx";
|
|
21911
21911
|
if (isClientComponent(content)) {
|
|
21912
|
-
const dir =
|
|
21913
|
-
const layoutPath =
|
|
21912
|
+
const dir = path12.dirname(fullPath);
|
|
21913
|
+
const layoutPath = path12.join(dir, `layout${ext2}`);
|
|
21914
21914
|
try {
|
|
21915
21915
|
await fs3.access(layoutPath);
|
|
21916
21916
|
const layoutContent = await fs3.readFile(layoutPath, "utf-8");
|
|
@@ -21933,7 +21933,7 @@ async function migrateMetadata(filePath, metadata, options) {
|
|
|
21933
21933
|
} catch (error2) {
|
|
21934
21934
|
changes.push(`Page metadata may already exist: ${pagePath}`);
|
|
21935
21935
|
}
|
|
21936
|
-
const dirName =
|
|
21936
|
+
const dirName = path12.basename(dir).replace(/^\[\.\.\.([^\]]+)\]$/, "$1").replace(/^\[([^\]]+)\]$/, "$1");
|
|
21937
21937
|
const layoutName = dirName.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("") + "Layout";
|
|
21938
21938
|
const layoutCode = `import { getManagedMetadata, ManagedSchema } from '@sonordev/site-kit/seo'
|
|
21939
21939
|
|
|
@@ -22042,7 +22042,7 @@ export async function generateMetadata() {
|
|
|
22042
22042
|
return { filePath, success: true, changes };
|
|
22043
22043
|
}
|
|
22044
22044
|
async function createPageMetadata(pagePath, metadata, options) {
|
|
22045
|
-
const response = await fetch("https://api.sonor.io/seo/pages
|
|
22045
|
+
const response = await fetch(`${options.apiUrl || "https://api.sonor.io"}/seo/pages`, {
|
|
22046
22046
|
method: "POST",
|
|
22047
22047
|
headers: {
|
|
22048
22048
|
"Content-Type": "application/json",
|
|
@@ -22127,7 +22127,7 @@ async function createSchemaRecord(pagePath, schemaType, schemaJson, options) {
|
|
|
22127
22127
|
}
|
|
22128
22128
|
async function migrateSchema(filePath, schema, options) {
|
|
22129
22129
|
const changes = [];
|
|
22130
|
-
const fullPath =
|
|
22130
|
+
const fullPath = path12.resolve(process.cwd(), filePath);
|
|
22131
22131
|
let pagePath = filePath.replace(/^app\//, "/").replace(/^src\/app\//, "/").replace(/\/page\.(tsx?|jsx?)$/, "").replace(/\[([^\]]+)\]/g, ":$1");
|
|
22132
22132
|
if (pagePath === "") pagePath = "/";
|
|
22133
22133
|
let content = await fs3.readFile(fullPath, "utf-8");
|
|
@@ -22238,7 +22238,7 @@ async function createFAQRecord(pagePath, items, options) {
|
|
|
22238
22238
|
}
|
|
22239
22239
|
async function migrateFAQ(filePath, faq, options) {
|
|
22240
22240
|
const changes = [];
|
|
22241
|
-
const fullPath =
|
|
22241
|
+
const fullPath = path12.resolve(process.cwd(), filePath);
|
|
22242
22242
|
let pagePath = filePath.replace(/^app\//, "/").replace(/^src\/app\//, "/").replace(/\/page\.(tsx?|jsx?)$/, "").replace(/\[([^\]]+)\]/g, ":$1");
|
|
22243
22243
|
if (pagePath === "") pagePath = "/";
|
|
22244
22244
|
let content = await fs3.readFile(fullPath, "utf-8");
|
|
@@ -22306,7 +22306,7 @@ async function migrateFAQ(filePath, faq, options) {
|
|
|
22306
22306
|
}
|
|
22307
22307
|
async function migrateSitemap(filePath, sitemap, options) {
|
|
22308
22308
|
const changes = [];
|
|
22309
|
-
const fullPath =
|
|
22309
|
+
const fullPath = path12.resolve(process.cwd(), filePath);
|
|
22310
22310
|
if (options.dryRun) {
|
|
22311
22311
|
changes.push(`[DRY RUN] Would migrate ${sitemap.type} to Site-Kit sitemap`);
|
|
22312
22312
|
if (sitemap.type === "next-sitemap-config") {
|
|
@@ -22348,8 +22348,8 @@ async function migrateAnalytics(filePath, analytics, options) {
|
|
|
22348
22348
|
return { filePath, success: true, changes };
|
|
22349
22349
|
}
|
|
22350
22350
|
async function migrateFile(filePath, options) {
|
|
22351
|
-
const fullPath =
|
|
22352
|
-
const relPath =
|
|
22351
|
+
const fullPath = path12.resolve(filePath);
|
|
22352
|
+
const relPath = path12.relative(process.cwd(), fullPath);
|
|
22353
22353
|
const content = await fs3.readFile(fullPath, "utf-8");
|
|
22354
22354
|
const hasFormTag = content.includes("<form") || content.includes("onSubmit");
|
|
22355
22355
|
const hasWidget = /intercom|crisp|drift|hubspot|zendesk/i.test(content);
|
|
@@ -22366,26 +22366,26 @@ async function migrateFile(filePath, options) {
|
|
|
22366
22366
|
return migrateWidget(relPath, {
|
|
22367
22367
|
widgetType}, options);
|
|
22368
22368
|
}
|
|
22369
|
-
const { parse:
|
|
22370
|
-
const ast =
|
|
22369
|
+
const { parse: parse3 } = await import('../lib-R7IQ4ZHE.mjs');
|
|
22370
|
+
const ast = parse3(content, {
|
|
22371
22371
|
sourceType: "module",
|
|
22372
22372
|
plugins: ["jsx", "typescript"]
|
|
22373
22373
|
});
|
|
22374
22374
|
let componentName = "Form";
|
|
22375
22375
|
const traverse2 = (await import('../lib-RSDMEKDQ.mjs')).default;
|
|
22376
22376
|
traverse2(ast, {
|
|
22377
|
-
ExportNamedDeclaration(
|
|
22378
|
-
const decl =
|
|
22377
|
+
ExportNamedDeclaration(path30) {
|
|
22378
|
+
const decl = path30.node.declaration;
|
|
22379
22379
|
if (decl && decl.type === "FunctionDeclaration" && decl.id) {
|
|
22380
22380
|
componentName = decl.id.name;
|
|
22381
|
-
|
|
22381
|
+
path30.stop();
|
|
22382
22382
|
}
|
|
22383
22383
|
},
|
|
22384
|
-
ExportDefaultDeclaration(
|
|
22385
|
-
const decl =
|
|
22384
|
+
ExportDefaultDeclaration(path30) {
|
|
22385
|
+
const decl = path30.node.declaration;
|
|
22386
22386
|
if (decl && decl.type === "FunctionDeclaration" && decl.id) {
|
|
22387
22387
|
componentName = decl.id.name;
|
|
22388
|
-
|
|
22388
|
+
path30.stop();
|
|
22389
22389
|
}
|
|
22390
22390
|
}
|
|
22391
22391
|
});
|
|
@@ -22442,7 +22442,7 @@ function detectFormType(form) {
|
|
|
22442
22442
|
return "contact";
|
|
22443
22443
|
}
|
|
22444
22444
|
async function generateEnvFile(options) {
|
|
22445
|
-
const envPath =
|
|
22445
|
+
const envPath = path12.join(process.cwd(), ".env.local");
|
|
22446
22446
|
let existingContent = "";
|
|
22447
22447
|
try {
|
|
22448
22448
|
existingContent = await fs3.readFile(envPath, "utf-8");
|
|
@@ -22501,7 +22501,7 @@ function addImportSafely2(content, importStatement) {
|
|
|
22501
22501
|
async function generateLayout() {
|
|
22502
22502
|
const layoutPath = await findLayoutFile();
|
|
22503
22503
|
if (!layoutPath) {
|
|
22504
|
-
throw new Error("Could not find layout.tsx
|
|
22504
|
+
throw new Error("Could not find a root layout (app/layout.tsx, .jsx, .ts or .js)");
|
|
22505
22505
|
}
|
|
22506
22506
|
const content = await fs3.readFile(layoutPath, "utf-8");
|
|
22507
22507
|
if (content.includes("SiteKitLayout") || content.includes("SiteKitProvider")) {
|
|
@@ -22535,22 +22535,7 @@ async function generateLayout() {
|
|
|
22535
22535
|
await fs3.writeFile(layoutPath, newContent, "utf-8");
|
|
22536
22536
|
}
|
|
22537
22537
|
async function findLayoutFile() {
|
|
22538
|
-
|
|
22539
|
-
"src/app/layout.tsx",
|
|
22540
|
-
"app/layout.tsx",
|
|
22541
|
-
"src/app/layout.jsx",
|
|
22542
|
-
"app/layout.jsx"
|
|
22543
|
-
];
|
|
22544
|
-
for (const relativePath of possiblePaths) {
|
|
22545
|
-
const fullPath = path10.join(process.cwd(), relativePath);
|
|
22546
|
-
try {
|
|
22547
|
-
await fs3.access(fullPath);
|
|
22548
|
-
return fullPath;
|
|
22549
|
-
} catch {
|
|
22550
|
-
continue;
|
|
22551
|
-
}
|
|
22552
|
-
}
|
|
22553
|
-
return null;
|
|
22538
|
+
return findRootLayout(process.cwd());
|
|
22554
22539
|
}
|
|
22555
22540
|
var isDockerCached;
|
|
22556
22541
|
function hasDockerEnv() {
|
|
@@ -22712,15 +22697,15 @@ var wslDefaultBrowser = async () => {
|
|
|
22712
22697
|
const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
|
|
22713
22698
|
return stdout.trim();
|
|
22714
22699
|
};
|
|
22715
|
-
var convertWslPathToWindows = async (
|
|
22716
|
-
if (/^[a-z]+:\/\//i.test(
|
|
22717
|
-
return
|
|
22700
|
+
var convertWslPathToWindows = async (path30) => {
|
|
22701
|
+
if (/^[a-z]+:\/\//i.test(path30)) {
|
|
22702
|
+
return path30;
|
|
22718
22703
|
}
|
|
22719
22704
|
try {
|
|
22720
|
-
const { stdout } = await execFile2("wslpath", ["-aw",
|
|
22705
|
+
const { stdout } = await execFile2("wslpath", ["-aw", path30], { encoding: "utf8" });
|
|
22721
22706
|
return stdout.trim();
|
|
22722
22707
|
} catch {
|
|
22723
|
-
return
|
|
22708
|
+
return path30;
|
|
22724
22709
|
}
|
|
22725
22710
|
};
|
|
22726
22711
|
|
|
@@ -22840,8 +22825,8 @@ var is_in_ssh_default = isInSsh;
|
|
|
22840
22825
|
|
|
22841
22826
|
// node_modules/.pnpm/open@11.0.0/node_modules/open/index.js
|
|
22842
22827
|
var fallbackAttemptSymbol = /* @__PURE__ */ Symbol("fallbackAttempt");
|
|
22843
|
-
var __dirname2 = import.meta.url ?
|
|
22844
|
-
var localXdgOpenPath =
|
|
22828
|
+
var __dirname2 = import.meta.url ? path12.dirname(fileURLToPath(import.meta.url)) : "";
|
|
22829
|
+
var localXdgOpenPath = path12.join(__dirname2, "xdg-open");
|
|
22845
22830
|
var { platform, arch } = process2;
|
|
22846
22831
|
var tryEachApp = async (apps2, opener) => {
|
|
22847
22832
|
if (apps2.length === 0) {
|
|
@@ -23119,8 +23104,37 @@ defineLazyProperty(apps, "safari", () => detectPlatformBinary({
|
|
|
23119
23104
|
darwin: "Safari"
|
|
23120
23105
|
}));
|
|
23121
23106
|
var open_default = open;
|
|
23107
|
+
var SONOR_STATE_DIR = ".sonor";
|
|
23108
|
+
var IMAGE_MANIFEST = ".sonor-images.json";
|
|
23109
|
+
var LEGACY_IMAGE_MANIFEST = ".uptrade-images.json";
|
|
23110
|
+
var LEGACY_STATE_DIR = ".uptrade";
|
|
23111
|
+
function resolveStateReadPath(relativePath, root = process.cwd()) {
|
|
23112
|
+
return preferCurrent(path12.join(root, SONOR_STATE_DIR, relativePath), path12.join(root, LEGACY_STATE_DIR, relativePath));
|
|
23113
|
+
}
|
|
23114
|
+
function resolveImageManifestReadPath(root) {
|
|
23115
|
+
return preferCurrent(path12.join(root, IMAGE_MANIFEST), path12.join(root, LEGACY_IMAGE_MANIFEST));
|
|
23116
|
+
}
|
|
23117
|
+
function preferCurrent(current, legacy) {
|
|
23118
|
+
return existsSync(current) || !existsSync(legacy) ? current : legacy;
|
|
23119
|
+
}
|
|
23120
|
+
async function listLocalTemplates(root = process.cwd()) {
|
|
23121
|
+
const names = /* @__PURE__ */ new Set();
|
|
23122
|
+
for (const dir of [SONOR_STATE_DIR, LEGACY_STATE_DIR]) {
|
|
23123
|
+
try {
|
|
23124
|
+
const files = await fs3.readdir(path12.join(root, dir, "templates"));
|
|
23125
|
+
for (const file of files) if (file.endsWith(".json")) names.add(file);
|
|
23126
|
+
} catch (error2) {
|
|
23127
|
+
if (error2.code !== "ENOENT") throw error2;
|
|
23128
|
+
}
|
|
23129
|
+
}
|
|
23130
|
+
return [...names].sort();
|
|
23131
|
+
}
|
|
23132
|
+
|
|
23133
|
+
// src/cli/api/sonor.ts
|
|
23122
23134
|
var PORTAL_URL = "https://app.sonor.io";
|
|
23123
|
-
|
|
23135
|
+
function getSonorApiUrl() {
|
|
23136
|
+
return (process.env.SONOR_API_URL || "https://api.sonor.io").replace(/\/+$/, "");
|
|
23137
|
+
}
|
|
23124
23138
|
async function authenticateWithSonor() {
|
|
23125
23139
|
return new Promise((resolve, reject) => {
|
|
23126
23140
|
const server = http.createServer(async (req, res) => {
|
|
@@ -23147,7 +23161,7 @@ async function authenticateWithSonor() {
|
|
|
23147
23161
|
server.close();
|
|
23148
23162
|
return;
|
|
23149
23163
|
}
|
|
23150
|
-
const tokenResponse = await fetch(`${
|
|
23164
|
+
const tokenResponse = await fetch(`${getSonorApiUrl()}/auth/cli-token`, {
|
|
23151
23165
|
method: "POST",
|
|
23152
23166
|
headers: { "Content-Type": "application/json" },
|
|
23153
23167
|
body: JSON.stringify({ code, redirect_uri: `http://localhost:${port}/callback` })
|
|
@@ -23193,32 +23207,41 @@ async function authenticateWithSonor() {
|
|
|
23193
23207
|
}, 5 * 60 * 1e3);
|
|
23194
23208
|
});
|
|
23195
23209
|
}
|
|
23196
|
-
async function authenticateWithApiKey(apiKey) {
|
|
23197
|
-
|
|
23198
|
-
|
|
23199
|
-
|
|
23200
|
-
|
|
23201
|
-
|
|
23202
|
-
|
|
23203
|
-
|
|
23204
|
-
|
|
23205
|
-
userId: "api-key-user",
|
|
23206
|
-
email: data.project?.name ? `Project: ${data.project.name}` : `API Key verified`,
|
|
23207
|
-
projectId: data.project?.id,
|
|
23208
|
-
projectName: data.project?.name,
|
|
23209
|
-
orgId: data.organization?.id,
|
|
23210
|
-
orgName: data.organization?.name,
|
|
23211
|
-
isApiKey: true
|
|
23212
|
-
};
|
|
23213
|
-
}
|
|
23210
|
+
async function authenticateWithApiKey(apiKey, apiUrl = getSonorApiUrl()) {
|
|
23211
|
+
let response;
|
|
23212
|
+
try {
|
|
23213
|
+
response = await fetch(`${apiUrl}/api/public/seo/verify-api-key`, {
|
|
23214
|
+
headers: { "X-API-Key": apiKey },
|
|
23215
|
+
signal: AbortSignal.timeout(15e3)
|
|
23216
|
+
});
|
|
23217
|
+
} catch {
|
|
23218
|
+
throw new NetworkError("PROJECT_LOOKUP_FAILED", "Could not reach the Sonor API to resolve the project. Check SONOR_API_URL and your connection.");
|
|
23214
23219
|
}
|
|
23215
|
-
if (response.
|
|
23216
|
-
throw new
|
|
23220
|
+
if (!response.ok) {
|
|
23221
|
+
throw new NetworkError("PROJECT_LOOKUP_FAILED", `Sonor API verification failed (HTTP ${response.status}). Check SONOR_API_KEY and SONOR_API_URL.`);
|
|
23217
23222
|
}
|
|
23218
|
-
|
|
23223
|
+
let data;
|
|
23224
|
+
try {
|
|
23225
|
+
data = await response.json();
|
|
23226
|
+
} catch {
|
|
23227
|
+
throw new NetworkError("INVALID_PROJECT_RESPONSE", "Sonor API returned an invalid project response.");
|
|
23228
|
+
}
|
|
23229
|
+
if (data?.valid !== true || typeof data.project?.id !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(data.project.id)) {
|
|
23230
|
+
throw new NetworkError("INVALID_PROJECT_RESPONSE", "Sonor API did not return a valid full project UUID. Check SONOR_API_KEY.");
|
|
23231
|
+
}
|
|
23232
|
+
return {
|
|
23233
|
+
accessToken: apiKey,
|
|
23234
|
+
userId: "api-key-user",
|
|
23235
|
+
email: data.project.name ? `Project: ${data.project.name}` : "API Key verified",
|
|
23236
|
+
projectId: data.project.id,
|
|
23237
|
+
projectName: data.project.name,
|
|
23238
|
+
orgId: data.organization?.id,
|
|
23239
|
+
orgName: data.organization?.name,
|
|
23240
|
+
isApiKey: true
|
|
23241
|
+
};
|
|
23219
23242
|
}
|
|
23220
23243
|
async function fetchOrganizations(accessToken) {
|
|
23221
|
-
const response = await fetch(`${
|
|
23244
|
+
const response = await fetch(`${getSonorApiUrl()}/organizations`, {
|
|
23222
23245
|
headers: { "Authorization": `Bearer ${accessToken}` }
|
|
23223
23246
|
});
|
|
23224
23247
|
if (!response.ok) {
|
|
@@ -23227,7 +23250,7 @@ async function fetchOrganizations(accessToken) {
|
|
|
23227
23250
|
return response.json();
|
|
23228
23251
|
}
|
|
23229
23252
|
async function fetchProjects(accessToken, orgId) {
|
|
23230
|
-
const response = await fetch(`${
|
|
23253
|
+
const response = await fetch(`${getSonorApiUrl()}/organizations/${orgId}/projects`, {
|
|
23231
23254
|
headers: { "Authorization": `Bearer ${accessToken}` }
|
|
23232
23255
|
});
|
|
23233
23256
|
if (!response.ok) {
|
|
@@ -23236,7 +23259,7 @@ async function fetchProjects(accessToken, orgId) {
|
|
|
23236
23259
|
return response.json();
|
|
23237
23260
|
}
|
|
23238
23261
|
async function createProject(accessToken, orgId, data) {
|
|
23239
|
-
const response = await fetch(`${
|
|
23262
|
+
const response = await fetch(`${getSonorApiUrl()}/organizations/${orgId}/projects`, {
|
|
23240
23263
|
method: "POST",
|
|
23241
23264
|
headers: {
|
|
23242
23265
|
"Authorization": `Bearer ${accessToken}`,
|
|
@@ -23250,7 +23273,7 @@ async function createProject(accessToken, orgId, data) {
|
|
|
23250
23273
|
return response.json();
|
|
23251
23274
|
}
|
|
23252
23275
|
async function generateApiKey(accessToken, projectId) {
|
|
23253
|
-
const response = await fetch(`${
|
|
23276
|
+
const response = await fetch(`${getSonorApiUrl()}/projects/${projectId}/api-keys`, {
|
|
23254
23277
|
method: "POST",
|
|
23255
23278
|
headers: {
|
|
23256
23279
|
"Authorization": `Bearer ${accessToken}`,
|
|
@@ -23454,7 +23477,7 @@ function progress(ctx, line) {
|
|
|
23454
23477
|
// src/cli/commands/init.ts
|
|
23455
23478
|
async function checkNextJsProject(cwd) {
|
|
23456
23479
|
try {
|
|
23457
|
-
const pkg = JSON.parse(await fs3.readFile(
|
|
23480
|
+
const pkg = JSON.parse(await fs3.readFile(path12.join(cwd, "package.json"), "utf-8"));
|
|
23458
23481
|
return !!(pkg.dependencies?.next || pkg.devDependencies?.next);
|
|
23459
23482
|
} catch {
|
|
23460
23483
|
return false;
|
|
@@ -23534,7 +23557,7 @@ async function run(ctx, options) {
|
|
|
23534
23557
|
]);
|
|
23535
23558
|
if (chosen === "new") {
|
|
23536
23559
|
const answers = await dist_default14.prompt([
|
|
23537
|
-
{ type: "input", name: "name", message: "Project name:", default:
|
|
23560
|
+
{ type: "input", name: "name", message: "Project name:", default: path12.basename(ctx.cwd) },
|
|
23538
23561
|
{ type: "input", name: "domain", message: "Project domain (optional):" }
|
|
23539
23562
|
]);
|
|
23540
23563
|
const project = await createProject(auth.accessToken, orgId, { name: answers.name, domain: answers.domain || "" });
|
|
@@ -23589,7 +23612,7 @@ async function run(ctx, options) {
|
|
|
23589
23612
|
};
|
|
23590
23613
|
}
|
|
23591
23614
|
async function ensureSitemapPostbuild(ctx) {
|
|
23592
|
-
const pkgPath =
|
|
23615
|
+
const pkgPath = path12.join(ctx.cwd, "package.json");
|
|
23593
23616
|
try {
|
|
23594
23617
|
const pkg = JSON.parse(await fs3.readFile(pkgPath, "utf-8"));
|
|
23595
23618
|
if (!pkg.scripts) pkg.scripts = {};
|
|
@@ -23631,7 +23654,7 @@ async function scanCommand(options) {
|
|
|
23631
23654
|
console.log("");
|
|
23632
23655
|
console.log(source_default.bold(" Scanning codebase..."));
|
|
23633
23656
|
console.log("");
|
|
23634
|
-
const targetDir =
|
|
23657
|
+
const targetDir = path12.resolve(options.dir || ".");
|
|
23635
23658
|
const spinner = ora("Looking for forms, metadata, widgets, schemas, FAQs, analytics, and images...").start();
|
|
23636
23659
|
let scanResults;
|
|
23637
23660
|
try {
|
|
@@ -23809,6 +23832,48 @@ async function scanCommand(options) {
|
|
|
23809
23832
|
process.exit(1);
|
|
23810
23833
|
}
|
|
23811
23834
|
}
|
|
23835
|
+
|
|
23836
|
+
// src/cli/config.ts
|
|
23837
|
+
var import_dotenv = __toESM(require_main());
|
|
23838
|
+
async function loadConfig({ resolveProject = false, cwd = process.cwd() } = {}) {
|
|
23839
|
+
const envFile = await readOptionalFile(path12.join(cwd, ".env.local"));
|
|
23840
|
+
const env3 = { ...(0, import_dotenv.parse)(envFile || ""), ...process.env };
|
|
23841
|
+
const configPath = resolveStateReadPath("config.json", cwd);
|
|
23842
|
+
const saved = await readOptionalFile(configPath);
|
|
23843
|
+
let stored = {};
|
|
23844
|
+
if (saved !== void 0) {
|
|
23845
|
+
try {
|
|
23846
|
+
stored = JSON.parse(saved);
|
|
23847
|
+
if (!stored || typeof stored !== "object" || Array.isArray(stored)) throw new Error();
|
|
23848
|
+
} catch {
|
|
23849
|
+
throw new ConfigError("INVALID_CONFIG", `Invalid JSON config: ${configPath}. Fix or remove it, then set SONOR_API_KEY in .env.local.`);
|
|
23850
|
+
}
|
|
23851
|
+
}
|
|
23852
|
+
const apiKey = String(env3.SONOR_API_KEY || stored.apiKey || stored.api_key || "").trim();
|
|
23853
|
+
if (!apiKey) {
|
|
23854
|
+
throw new ConfigError("MISSING_API_KEY", "Set SONOR_API_KEY in .env.local or run `sonor-setup init` first.");
|
|
23855
|
+
}
|
|
23856
|
+
if (!/^sonor_[0-9a-f]{8}_.+$/i.test(apiKey)) {
|
|
23857
|
+
throw new ConfigError("INVALID_API_KEY", "SONOR_API_KEY must be a sonor_ key from app.sonor.io.");
|
|
23858
|
+
}
|
|
23859
|
+
const config2 = {
|
|
23860
|
+
apiKey,
|
|
23861
|
+
apiUrl: (env3.SONOR_API_URL || getSonorApiUrl()).replace(/\/+$/, ""),
|
|
23862
|
+
siteUrl: env3.NEXT_PUBLIC_SITE_URL || env3.SITE_URL || stored.siteUrl || stored.site_url,
|
|
23863
|
+
businessInfo: stored.businessInfo || stored.business_info
|
|
23864
|
+
};
|
|
23865
|
+
if (!resolveProject) return config2;
|
|
23866
|
+
const auth = await authenticateWithApiKey(apiKey, config2.apiUrl);
|
|
23867
|
+
return { ...config2, projectId: auth.projectId };
|
|
23868
|
+
}
|
|
23869
|
+
async function readOptionalFile(file) {
|
|
23870
|
+
try {
|
|
23871
|
+
return await fs3.readFile(file, "utf-8");
|
|
23872
|
+
} catch (error2) {
|
|
23873
|
+
if (error2.code === "ENOENT") return void 0;
|
|
23874
|
+
throw new ConfigError("CONFIG_READ_FAILED", `Could not read ${file}. Check file permissions.`);
|
|
23875
|
+
}
|
|
23876
|
+
}
|
|
23812
23877
|
var IMAGE_EXTENSIONS = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".ico", ".bmp", ".avif"];
|
|
23813
23878
|
var MIME_TYPES = {
|
|
23814
23879
|
".jpg": "image/jpeg",
|
|
@@ -23831,7 +23896,7 @@ function filePathToPagePath(filePath) {
|
|
|
23831
23896
|
}
|
|
23832
23897
|
if (p.startsWith("pages/") || p.startsWith("src/pages/")) {
|
|
23833
23898
|
p = p.replace(/^pages\//, "").replace(/^src\/pages\//, "");
|
|
23834
|
-
const base =
|
|
23899
|
+
const base = path12.basename(p, path12.extname(p));
|
|
23835
23900
|
return base === "index" ? "/" : "/" + base;
|
|
23836
23901
|
}
|
|
23837
23902
|
p = p.replace(/\.[^.]+$/, "").replace(/^\.\//, "").replace(/\\/g, "/");
|
|
@@ -23874,8 +23939,8 @@ async function imagesCommand(subcommand, options) {
|
|
|
23874
23939
|
}
|
|
23875
23940
|
}
|
|
23876
23941
|
async function scanImages(options) {
|
|
23877
|
-
const targetDir =
|
|
23878
|
-
const publicDir =
|
|
23942
|
+
const targetDir = path12.resolve(options.dir || ".");
|
|
23943
|
+
const publicDir = path12.join(targetDir, "public");
|
|
23879
23944
|
try {
|
|
23880
23945
|
await fs3.access(publicDir);
|
|
23881
23946
|
} catch {
|
|
@@ -23945,7 +24010,7 @@ async function uploadImages(options) {
|
|
|
23945
24010
|
console.log("");
|
|
23946
24011
|
process.exit(1);
|
|
23947
24012
|
}
|
|
23948
|
-
const targetDir =
|
|
24013
|
+
const targetDir = path12.resolve(options.dir || ".");
|
|
23949
24014
|
const spinner = ora("Scanning for images...").start();
|
|
23950
24015
|
const results = await scanPublicImages(targetDir);
|
|
23951
24016
|
spinner.stop();
|
|
@@ -23998,7 +24063,7 @@ async function uploadImages(options) {
|
|
|
23998
24063
|
const uploadSpinner = ora(`Uploading ${img.filename}...`).start();
|
|
23999
24064
|
try {
|
|
24000
24065
|
const result = await uploadImageToPortal(
|
|
24001
|
-
|
|
24066
|
+
path12.join(targetDir, img.filePath),
|
|
24002
24067
|
img,
|
|
24003
24068
|
{ apiUrl, apiKey, category: options.category }
|
|
24004
24069
|
);
|
|
@@ -24017,7 +24082,7 @@ async function uploadImages(options) {
|
|
|
24017
24082
|
}
|
|
24018
24083
|
console.log("");
|
|
24019
24084
|
if (uploaded.length > 0) {
|
|
24020
|
-
const manifestPath =
|
|
24085
|
+
const manifestPath = path12.join(targetDir, IMAGE_MANIFEST);
|
|
24021
24086
|
await fs3.writeFile(manifestPath, JSON.stringify({
|
|
24022
24087
|
uploaded,
|
|
24023
24088
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -24030,8 +24095,8 @@ async function uploadImages(options) {
|
|
|
24030
24095
|
console.log("");
|
|
24031
24096
|
}
|
|
24032
24097
|
async function migrateImages(options) {
|
|
24033
|
-
const targetDir =
|
|
24034
|
-
const manifestPath =
|
|
24098
|
+
const targetDir = path12.resolve(options.dir || ".");
|
|
24099
|
+
const manifestPath = resolveImageManifestReadPath(targetDir);
|
|
24035
24100
|
const apiUrl = process.env.SONOR_API_URL || "https://api.sonor.io";
|
|
24036
24101
|
const apiKey = process.env.SONOR_API_KEY || "";
|
|
24037
24102
|
if (!apiKey) {
|
|
@@ -24134,9 +24199,9 @@ async function migrateImages(options) {
|
|
|
24134
24199
|
let successCount = 0;
|
|
24135
24200
|
let failCount = 0;
|
|
24136
24201
|
for (const [filePath, fileMigrations] of byFile) {
|
|
24137
|
-
const fileSpinner = ora(`Migrating ${
|
|
24202
|
+
const fileSpinner = ora(`Migrating ${path12.basename(filePath)}...`).start();
|
|
24138
24203
|
try {
|
|
24139
|
-
await migrateFileImages(
|
|
24204
|
+
await migrateFileImages(path12.join(targetDir, filePath), fileMigrations);
|
|
24140
24205
|
successCount += fileMigrations.length;
|
|
24141
24206
|
fileSpinner.succeed(`Migrated: ${filePath} (${fileMigrations.length} images)`);
|
|
24142
24207
|
} catch (error2) {
|
|
@@ -24158,7 +24223,7 @@ async function migrateImages(options) {
|
|
|
24158
24223
|
console.log("");
|
|
24159
24224
|
}
|
|
24160
24225
|
async function uploadAndMigrate(options) {
|
|
24161
|
-
const targetDir =
|
|
24226
|
+
const targetDir = path12.resolve(options.dir || ".");
|
|
24162
24227
|
const apiUrl = process.env.SONOR_API_URL || "https://api.sonor.io";
|
|
24163
24228
|
const apiKey = process.env.SONOR_API_KEY || "";
|
|
24164
24229
|
if (!apiKey) {
|
|
@@ -24225,7 +24290,7 @@ async function uploadAndMigrate(options) {
|
|
|
24225
24290
|
const uploadSpinner = ora(`Uploading ${img.filename}...`).start();
|
|
24226
24291
|
try {
|
|
24227
24292
|
const result = await uploadImageToPortal(
|
|
24228
|
-
|
|
24293
|
+
path12.join(targetDir, img.filePath),
|
|
24229
24294
|
img,
|
|
24230
24295
|
{ apiUrl, apiKey, category: options.category }
|
|
24231
24296
|
);
|
|
@@ -24297,9 +24362,9 @@ async function uploadAndMigrate(options) {
|
|
|
24297
24362
|
let successCount = 0;
|
|
24298
24363
|
let failCount = 0;
|
|
24299
24364
|
for (const [filePath, fileMigrations] of byFile) {
|
|
24300
|
-
const fileSpinner = ora(`Migrating ${
|
|
24365
|
+
const fileSpinner = ora(`Migrating ${path12.basename(filePath)}...`).start();
|
|
24301
24366
|
try {
|
|
24302
|
-
await migrateFileImages(
|
|
24367
|
+
await migrateFileImages(path12.join(targetDir, filePath), fileMigrations);
|
|
24303
24368
|
successCount += fileMigrations.length;
|
|
24304
24369
|
fileSpinner.succeed(`Migrated: ${filePath} (${fileMigrations.length} images)`);
|
|
24305
24370
|
} catch (error2) {
|
|
@@ -24307,7 +24372,7 @@ async function uploadAndMigrate(options) {
|
|
|
24307
24372
|
fileSpinner.fail(`Failed: ${filePath} - ${error2.message}`);
|
|
24308
24373
|
}
|
|
24309
24374
|
}
|
|
24310
|
-
const manifestPath =
|
|
24375
|
+
const manifestPath = path12.join(targetDir, IMAGE_MANIFEST);
|
|
24311
24376
|
await fs3.writeFile(manifestPath, JSON.stringify({
|
|
24312
24377
|
uploaded,
|
|
24313
24378
|
criticalKeptLocal: criticalImages.map((i) => i.filename),
|
|
@@ -24334,8 +24399,8 @@ async function uploadAndMigrate(options) {
|
|
|
24334
24399
|
console.log("");
|
|
24335
24400
|
}
|
|
24336
24401
|
async function replaceWithCdnUrls(options) {
|
|
24337
|
-
const targetDir =
|
|
24338
|
-
const manifestPath =
|
|
24402
|
+
const targetDir = path12.resolve(options.dir || ".");
|
|
24403
|
+
const manifestPath = resolveImageManifestReadPath(targetDir);
|
|
24339
24404
|
let manifest;
|
|
24340
24405
|
try {
|
|
24341
24406
|
const content = await fs3.readFile(manifestPath, "utf-8");
|
|
@@ -24383,7 +24448,7 @@ async function replaceWithCdnUrls(options) {
|
|
|
24383
24448
|
if (!seenFileLines.has(key)) {
|
|
24384
24449
|
seenFileLines.add(key);
|
|
24385
24450
|
replacements2.push({
|
|
24386
|
-
file:
|
|
24451
|
+
file: path12.relative(targetDir, file),
|
|
24387
24452
|
localPath: pattern,
|
|
24388
24453
|
cdnUrl: img.publicUrl,
|
|
24389
24454
|
line: i + 1
|
|
@@ -24431,9 +24496,9 @@ async function replaceWithCdnUrls(options) {
|
|
|
24431
24496
|
let successCount = 0;
|
|
24432
24497
|
let failCount = 0;
|
|
24433
24498
|
for (const [filePath, fileReplacements] of byFile) {
|
|
24434
|
-
const fileSpinner = ora(`Updating ${
|
|
24499
|
+
const fileSpinner = ora(`Updating ${path12.basename(filePath)}...`).start();
|
|
24435
24500
|
try {
|
|
24436
|
-
const fullPath =
|
|
24501
|
+
const fullPath = path12.join(targetDir, filePath);
|
|
24437
24502
|
let content = await fs3.readFile(fullPath, "utf-8");
|
|
24438
24503
|
for (const r of fileReplacements) {
|
|
24439
24504
|
const escaped = r.localPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -24461,8 +24526,8 @@ async function replaceWithCdnUrls(options) {
|
|
|
24461
24526
|
console.log("");
|
|
24462
24527
|
}
|
|
24463
24528
|
async function refreshManifest(options) {
|
|
24464
|
-
const targetDir =
|
|
24465
|
-
const manifestPath =
|
|
24529
|
+
const targetDir = path12.resolve(options.dir || ".");
|
|
24530
|
+
const manifestPath = path12.join(targetDir, IMAGE_MANIFEST);
|
|
24466
24531
|
const apiUrl = process.env.SONOR_API_URL || "https://api.sonor.io";
|
|
24467
24532
|
const apiKey = process.env.SONOR_API_KEY || "";
|
|
24468
24533
|
if (!apiKey) {
|
|
@@ -24471,7 +24536,7 @@ async function refreshManifest(options) {
|
|
|
24471
24536
|
}
|
|
24472
24537
|
let manifest;
|
|
24473
24538
|
try {
|
|
24474
|
-
const content = await fs3.readFile(
|
|
24539
|
+
const content = await fs3.readFile(resolveImageManifestReadPath(targetDir), "utf-8");
|
|
24475
24540
|
manifest = JSON.parse(content);
|
|
24476
24541
|
} catch {
|
|
24477
24542
|
console.log(source_default.yellow(" \u26A0 No upload manifest found"));
|
|
@@ -24524,12 +24589,12 @@ async function refreshManifest(options) {
|
|
|
24524
24589
|
}
|
|
24525
24590
|
async function findDataFiles(rootDir) {
|
|
24526
24591
|
const files = [];
|
|
24527
|
-
const excludeFiles = [
|
|
24592
|
+
const excludeFiles = [IMAGE_MANIFEST, LEGACY_IMAGE_MANIFEST];
|
|
24528
24593
|
async function scan(dir) {
|
|
24529
24594
|
try {
|
|
24530
24595
|
const entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
24531
24596
|
for (const entry of entries) {
|
|
24532
|
-
const fullPath =
|
|
24597
|
+
const fullPath = path12.join(dir, entry.name);
|
|
24533
24598
|
if (entry.isDirectory()) {
|
|
24534
24599
|
if (["node_modules", ".next", ".git", "dist", "build"].includes(entry.name)) {
|
|
24535
24600
|
continue;
|
|
@@ -24539,7 +24604,7 @@ async function findDataFiles(rootDir) {
|
|
|
24539
24604
|
if (excludeFiles.includes(entry.name)) {
|
|
24540
24605
|
continue;
|
|
24541
24606
|
}
|
|
24542
|
-
const ext2 =
|
|
24607
|
+
const ext2 = path12.extname(entry.name).toLowerCase();
|
|
24543
24608
|
if ([".js", ".ts", ".json", ".jsx", ".tsx", ".mjs", ".cjs"].includes(ext2)) {
|
|
24544
24609
|
files.push(fullPath);
|
|
24545
24610
|
}
|
|
@@ -24552,16 +24617,16 @@ async function findDataFiles(rootDir) {
|
|
|
24552
24617
|
return files;
|
|
24553
24618
|
}
|
|
24554
24619
|
async function scanPublicImages(rootDir) {
|
|
24555
|
-
const publicDir =
|
|
24620
|
+
const publicDir = path12.join(rootDir, "public");
|
|
24556
24621
|
const images = [];
|
|
24557
24622
|
let totalSize = 0;
|
|
24558
24623
|
let usageCount = 0;
|
|
24559
24624
|
const imageFiles = await findImagesRecursive(publicDir);
|
|
24560
24625
|
const sourceFiles = await findSourceFiles2(rootDir);
|
|
24561
24626
|
for (const imagePath of imageFiles) {
|
|
24562
|
-
const relPath =
|
|
24563
|
-
const filename =
|
|
24564
|
-
const ext2 =
|
|
24627
|
+
const relPath = path12.relative(rootDir, imagePath);
|
|
24628
|
+
const filename = path12.basename(imagePath);
|
|
24629
|
+
const ext2 = path12.extname(filename).toLowerCase();
|
|
24565
24630
|
const stat = await fs3.stat(imagePath);
|
|
24566
24631
|
const category = getCategoryFromPath(relPath);
|
|
24567
24632
|
const suggestedSlotId = generateSlotId(relPath);
|
|
@@ -24587,11 +24652,11 @@ async function findImagesRecursive(dir, files = []) {
|
|
|
24587
24652
|
try {
|
|
24588
24653
|
const entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
24589
24654
|
for (const entry of entries) {
|
|
24590
|
-
const fullPath =
|
|
24655
|
+
const fullPath = path12.join(dir, entry.name);
|
|
24591
24656
|
if (entry.isDirectory()) {
|
|
24592
24657
|
await findImagesRecursive(fullPath, files);
|
|
24593
24658
|
} else if (entry.isFile()) {
|
|
24594
|
-
const ext2 =
|
|
24659
|
+
const ext2 = path12.extname(entry.name).toLowerCase();
|
|
24595
24660
|
if (IMAGE_EXTENSIONS.includes(ext2)) {
|
|
24596
24661
|
files.push(fullPath);
|
|
24597
24662
|
}
|
|
@@ -24604,7 +24669,7 @@ async function findImagesRecursive(dir, files = []) {
|
|
|
24604
24669
|
async function findSourceFiles2(dir, files = []) {
|
|
24605
24670
|
const entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
24606
24671
|
for (const entry of entries) {
|
|
24607
|
-
const fullPath =
|
|
24672
|
+
const fullPath = path12.join(dir, entry.name);
|
|
24608
24673
|
if (entry.isDirectory()) {
|
|
24609
24674
|
if (["node_modules", ".next", ".git", "dist", "build", "public"].includes(entry.name)) {
|
|
24610
24675
|
continue;
|
|
@@ -24620,8 +24685,8 @@ async function findSourceFiles2(dir, files = []) {
|
|
|
24620
24685
|
}
|
|
24621
24686
|
async function findImageUsages(imagePath, sourceFiles, rootDir) {
|
|
24622
24687
|
const usages = [];
|
|
24623
|
-
const filename =
|
|
24624
|
-
const relPath =
|
|
24688
|
+
const filename = path12.basename(imagePath);
|
|
24689
|
+
const relPath = path12.relative(path12.join(rootDir, "public"), imagePath);
|
|
24625
24690
|
const patterns = [
|
|
24626
24691
|
`/${relPath}`,
|
|
24627
24692
|
// /images/hero.jpg
|
|
@@ -24643,7 +24708,7 @@ async function findImageUsages(imagePath, sourceFiles, rootDir) {
|
|
|
24643
24708
|
const elementType = detectElementType(line);
|
|
24644
24709
|
const canAutoMigrate = ["img", "Image"].includes(elementType);
|
|
24645
24710
|
usages.push({
|
|
24646
|
-
filePath:
|
|
24711
|
+
filePath: path12.relative(rootDir, sourceFile),
|
|
24647
24712
|
line: i + 1,
|
|
24648
24713
|
elementType,
|
|
24649
24714
|
altText: extractAltText(line),
|
|
@@ -24715,7 +24780,7 @@ function detectCriticalImage(filename, relPath, usages, fileSize) {
|
|
|
24715
24780
|
(u) => u.filePath.includes("layout.") || u.filePath.includes("/layout/")
|
|
24716
24781
|
);
|
|
24717
24782
|
const usedInCriticalComponent = usages.some((u) => {
|
|
24718
|
-
const fileName =
|
|
24783
|
+
const fileName = path12.basename(u.filePath).toLowerCase();
|
|
24719
24784
|
return fileName.includes("header") || fileName.includes("navbar") || fileName.includes("nav.") || fileName.includes("hero") || fileName.includes("footer");
|
|
24720
24785
|
});
|
|
24721
24786
|
const isSiteLogo = SITE_LOGO_PATTERNS.some((p) => p.test(filename));
|
|
@@ -24851,7 +24916,7 @@ async function uploadAndMigrateImages(scanResults, options) {
|
|
|
24851
24916
|
for (const img of scanResults.images) {
|
|
24852
24917
|
try {
|
|
24853
24918
|
const uploadResult = await uploadImageToPortal(
|
|
24854
|
-
|
|
24919
|
+
path12.join(rootDir, img.filePath),
|
|
24855
24920
|
img,
|
|
24856
24921
|
{
|
|
24857
24922
|
apiUrl: options.apiUrl,
|
|
@@ -24879,7 +24944,7 @@ async function uploadAndMigrateImages(scanResults, options) {
|
|
|
24879
24944
|
}
|
|
24880
24945
|
for (const [filePath, migrations] of byFile) {
|
|
24881
24946
|
try {
|
|
24882
|
-
await migrateFileImages(
|
|
24947
|
+
await migrateFileImages(path12.join(rootDir, filePath), migrations);
|
|
24883
24948
|
result.migrated += migrations.length;
|
|
24884
24949
|
} catch (error2) {
|
|
24885
24950
|
result.errors.push(`Migration failed for ${filePath}: ${error2.message}`);
|
|
@@ -24893,31 +24958,25 @@ async function migrateCommand(options) {
|
|
|
24893
24958
|
console.log("");
|
|
24894
24959
|
console.log(source_default.bold(" Site-Kit Migration"));
|
|
24895
24960
|
console.log("");
|
|
24896
|
-
const apiKey =
|
|
24897
|
-
const projectId = process.env.SONOR_PROJECT_ID;
|
|
24898
|
-
if (!apiKey || !projectId) {
|
|
24899
|
-
console.log(source_default.red(" \u2717 Missing environment variables"));
|
|
24900
|
-
console.log(source_default.gray(" Run `sonor-setup init` first to configure your project."));
|
|
24901
|
-
console.log("");
|
|
24902
|
-
process.exit(1);
|
|
24903
|
-
}
|
|
24961
|
+
const { apiKey, projectId, apiUrl } = await loadConfig({ resolveProject: true });
|
|
24904
24962
|
if (options.dryRun) {
|
|
24905
24963
|
console.log(source_default.yellow(" Running in dry-run mode - no files will be modified"));
|
|
24906
24964
|
console.log("");
|
|
24907
24965
|
}
|
|
24908
24966
|
if (options.file) {
|
|
24909
|
-
const filePath =
|
|
24967
|
+
const filePath = path12.resolve(options.file);
|
|
24910
24968
|
try {
|
|
24911
24969
|
await fs3.access(filePath);
|
|
24912
24970
|
} catch {
|
|
24913
24971
|
console.log(source_default.red(` \u2717 File not found: ${filePath}`));
|
|
24914
24972
|
process.exit(1);
|
|
24915
24973
|
}
|
|
24916
|
-
const spinner = ora(`Migrating ${
|
|
24974
|
+
const spinner = ora(`Migrating ${path12.basename(filePath)}...`).start();
|
|
24917
24975
|
try {
|
|
24918
24976
|
const result = await migrateFile(filePath, {
|
|
24919
24977
|
projectId,
|
|
24920
24978
|
apiKey,
|
|
24979
|
+
apiUrl,
|
|
24921
24980
|
dryRun: options.dryRun
|
|
24922
24981
|
});
|
|
24923
24982
|
if (result.success) {
|
|
@@ -24980,6 +25039,7 @@ async function migrateCommand(options) {
|
|
|
24980
25039
|
const results = await migrateFiles(scanResults, {
|
|
24981
25040
|
projectId,
|
|
24982
25041
|
apiKey,
|
|
25042
|
+
apiUrl,
|
|
24983
25043
|
dryRun: options.dryRun
|
|
24984
25044
|
});
|
|
24985
25045
|
const successful = results.filter((r) => r.success);
|
|
@@ -25009,10 +25069,9 @@ async function migrateCommand(options) {
|
|
|
25009
25069
|
process.exit(1);
|
|
25010
25070
|
}
|
|
25011
25071
|
console.log("");
|
|
25012
|
-
await handleImageMigration(options, apiKey);
|
|
25072
|
+
await handleImageMigration(options, apiKey, apiUrl);
|
|
25013
25073
|
}
|
|
25014
|
-
async function handleImageMigration(options, apiKey,
|
|
25015
|
-
const apiUrl = process.env.SONOR_API_URL || "https://api.sonor.io";
|
|
25074
|
+
async function handleImageMigration(options, apiKey, apiUrl) {
|
|
25016
25075
|
const imageScanSpinner = ora("Scanning for images...").start();
|
|
25017
25076
|
let imageResults;
|
|
25018
25077
|
try {
|
|
@@ -25076,17 +25135,11 @@ function formatBytes2(bytes) {
|
|
|
25076
25135
|
return `${parseFloat((bytes / Math.pow(k2, i)).toFixed(1))} ${sizes[i]}`;
|
|
25077
25136
|
}
|
|
25078
25137
|
var SKIP_PROPS = ["href", "src", "className", "style", "onClick", "ref", "key", "id", "target", "rel", "type", "name", "variant", "size", "icon"];
|
|
25079
|
-
var
|
|
25080
|
-
var TEMPLATES_DIR = ".uptrade/templates";
|
|
25138
|
+
var TEMPLATES_DIR = path12.join(SONOR_STATE_DIR, "templates");
|
|
25081
25139
|
async function locationsCommand(subcommand, arg, options) {
|
|
25082
25140
|
console.log("");
|
|
25083
25141
|
console.log(source_default.bold(" \u{1F4CD} Site-Kit Location Page Manager"));
|
|
25084
25142
|
console.log("");
|
|
25085
|
-
const config2 = await loadConfig();
|
|
25086
|
-
if (!config2?.projectId) {
|
|
25087
|
-
console.log(source_default.red(" \u2717 Not configured. Run `npx sonor-setup init` first."));
|
|
25088
|
-
return;
|
|
25089
|
-
}
|
|
25090
25143
|
switch (subcommand) {
|
|
25091
25144
|
case "template":
|
|
25092
25145
|
if (!arg) {
|
|
@@ -25094,6 +25147,7 @@ async function locationsCommand(subcommand, arg, options) {
|
|
|
25094
25147
|
console.log(source_default.gray(" Example: locations template ./app/services/plumbing/page.tsx"));
|
|
25095
25148
|
return;
|
|
25096
25149
|
}
|
|
25150
|
+
await loadConfig();
|
|
25097
25151
|
await templateCommand(arg, options);
|
|
25098
25152
|
break;
|
|
25099
25153
|
case "upload":
|
|
@@ -25101,17 +25155,17 @@ async function locationsCommand(subcommand, arg, options) {
|
|
|
25101
25155
|
console.log(source_default.red(" \u2717 Usage: locations upload --template <name>"));
|
|
25102
25156
|
return;
|
|
25103
25157
|
}
|
|
25104
|
-
await uploadCommand(options.template,
|
|
25158
|
+
await uploadCommand(options.template, await loadConfig({ resolveProject: true }));
|
|
25105
25159
|
break;
|
|
25106
25160
|
case "generate":
|
|
25107
25161
|
if (!options.template) {
|
|
25108
25162
|
console.log(source_default.red(' \u2717 Usage: locations generate --template <name> --locations "City, ST" ...'));
|
|
25109
25163
|
return;
|
|
25110
25164
|
}
|
|
25111
|
-
await generateCommand(options,
|
|
25165
|
+
await generateCommand(options, await loadConfig({ resolveProject: true }));
|
|
25112
25166
|
break;
|
|
25113
25167
|
case "list":
|
|
25114
|
-
await listCommand(
|
|
25168
|
+
await listCommand(await loadConfig({ resolveProject: true }));
|
|
25115
25169
|
break;
|
|
25116
25170
|
default:
|
|
25117
25171
|
console.log(source_default.yellow(" Available subcommands:"));
|
|
@@ -25123,10 +25177,10 @@ async function locationsCommand(subcommand, arg, options) {
|
|
|
25123
25177
|
console.log("");
|
|
25124
25178
|
}
|
|
25125
25179
|
}
|
|
25126
|
-
async function templateCommand(sourcePath, options
|
|
25180
|
+
async function templateCommand(sourcePath, options) {
|
|
25127
25181
|
const spinner = ora("Analyzing source page...").start();
|
|
25128
25182
|
try {
|
|
25129
|
-
const resolvedPath =
|
|
25183
|
+
const resolvedPath = path12.resolve(sourcePath);
|
|
25130
25184
|
if (!existsSync(resolvedPath)) {
|
|
25131
25185
|
spinner.fail(`File not found: ${sourcePath}`);
|
|
25132
25186
|
return;
|
|
@@ -25139,8 +25193,8 @@ async function templateCommand(sourcePath, options, config2) {
|
|
|
25139
25193
|
const slots = [];
|
|
25140
25194
|
const componentNames = [];
|
|
25141
25195
|
traverse(ast, {
|
|
25142
|
-
JSXElement(
|
|
25143
|
-
const openingElement =
|
|
25196
|
+
JSXElement(path30) {
|
|
25197
|
+
const openingElement = path30.node.openingElement;
|
|
25144
25198
|
if (isJSXIdentifier(openingElement.name)) {
|
|
25145
25199
|
const componentName = openingElement.name.name;
|
|
25146
25200
|
if (componentName[0] === componentName[0].toUpperCase()) {
|
|
@@ -25180,8 +25234,9 @@ async function templateCommand(sourcePath, options, config2) {
|
|
|
25180
25234
|
},
|
|
25181
25235
|
managed_components: ["schema", "faqs", "metadata"]
|
|
25182
25236
|
};
|
|
25183
|
-
|
|
25184
|
-
|
|
25237
|
+
const templatesDir = path12.join(process.cwd(), TEMPLATES_DIR);
|
|
25238
|
+
await fs3.mkdir(templatesDir, { recursive: true });
|
|
25239
|
+
const templatePath = path12.join(templatesDir, `${templateName}.json`);
|
|
25185
25240
|
await fs3.writeFile(templatePath, JSON.stringify(template, null, 2));
|
|
25186
25241
|
console.log("");
|
|
25187
25242
|
console.log(source_default.green(" \u2713 Template created:"), source_default.cyan(templatePath));
|
|
@@ -25260,7 +25315,7 @@ function inferGenerationHint(propName) {
|
|
|
25260
25315
|
return void 0;
|
|
25261
25316
|
}
|
|
25262
25317
|
function inferTemplateName(sourcePath) {
|
|
25263
|
-
const parts = sourcePath.split(
|
|
25318
|
+
const parts = sourcePath.split(path12.sep);
|
|
25264
25319
|
const pageIndex = parts.findIndex((p) => p === "page.tsx" || p === "page.jsx");
|
|
25265
25320
|
if (pageIndex > 0) {
|
|
25266
25321
|
return parts[pageIndex - 1];
|
|
@@ -25269,14 +25324,14 @@ function inferTemplateName(sourcePath) {
|
|
|
25269
25324
|
return filtered[filtered.length - 1] || "template";
|
|
25270
25325
|
}
|
|
25271
25326
|
function inferSourcePagePath(sourcePath) {
|
|
25272
|
-
const parts = sourcePath.split(
|
|
25327
|
+
const parts = sourcePath.split(path12.sep);
|
|
25273
25328
|
const appIndex = parts.findIndex((p) => p === "app" || p === "pages");
|
|
25274
25329
|
if (appIndex >= 0) {
|
|
25275
25330
|
const pathParts = parts.slice(appIndex + 1);
|
|
25276
25331
|
const filtered = pathParts.filter((p) => !["page.tsx", "page.jsx", "index.tsx", "index.jsx"].includes(p));
|
|
25277
25332
|
return "/" + filtered.join("/");
|
|
25278
25333
|
}
|
|
25279
|
-
return "/" +
|
|
25334
|
+
return "/" + path12.basename(sourcePath, path12.extname(sourcePath));
|
|
25280
25335
|
}
|
|
25281
25336
|
function toSnakeCase(str) {
|
|
25282
25337
|
return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
@@ -25288,22 +25343,22 @@ function truncate(str, maxLength) {
|
|
|
25288
25343
|
async function uploadCommand(templateName, config2) {
|
|
25289
25344
|
const spinner = ora("Uploading template to Portal...").start();
|
|
25290
25345
|
try {
|
|
25291
|
-
const templatePath =
|
|
25346
|
+
const templatePath = resolveStateReadPath(path12.join("templates", `${templateName}.json`));
|
|
25292
25347
|
if (!existsSync(templatePath)) {
|
|
25293
25348
|
spinner.fail(`Template not found: ${templatePath}`);
|
|
25294
25349
|
console.log(source_default.gray(` Run: npx sonor-setup locations template <page> --name ${templateName}`));
|
|
25295
25350
|
return;
|
|
25296
25351
|
}
|
|
25297
25352
|
const template = JSON.parse(readFileSync(templatePath, "utf-8"));
|
|
25298
|
-
const response = await fetch(`${
|
|
25353
|
+
const response = await fetch(`${config2.apiUrl}/seo/location-templates`, {
|
|
25299
25354
|
method: "POST",
|
|
25300
25355
|
headers: {
|
|
25301
25356
|
"Content-Type": "application/json",
|
|
25302
25357
|
"Authorization": `Bearer ${config2.apiKey}`
|
|
25303
25358
|
},
|
|
25304
25359
|
body: JSON.stringify({
|
|
25305
|
-
|
|
25306
|
-
|
|
25360
|
+
...template,
|
|
25361
|
+
project_id: config2.projectId
|
|
25307
25362
|
})
|
|
25308
25363
|
});
|
|
25309
25364
|
if (!response.ok) {
|
|
@@ -25311,11 +25366,11 @@ async function uploadCommand(templateName, config2) {
|
|
|
25311
25366
|
if (response.status === 409) {
|
|
25312
25367
|
spinner.text = "Template exists, updating...";
|
|
25313
25368
|
const existing = await fetch(
|
|
25314
|
-
`${
|
|
25369
|
+
`${config2.apiUrl}/seo/location-templates/by-name/${templateName}?project_id=${config2.projectId}`,
|
|
25315
25370
|
{ headers: { "Authorization": `Bearer ${config2.apiKey}` } }
|
|
25316
25371
|
);
|
|
25317
25372
|
const existingData = await existing.json();
|
|
25318
|
-
const updateResponse = await fetch(`${
|
|
25373
|
+
const updateResponse = await fetch(`${config2.apiUrl}/seo/location-templates/${existingData.id}`, {
|
|
25319
25374
|
method: "PUT",
|
|
25320
25375
|
headers: {
|
|
25321
25376
|
"Content-Type": "application/json",
|
|
@@ -25364,7 +25419,7 @@ async function generateCommand(options, config2) {
|
|
|
25364
25419
|
}
|
|
25365
25420
|
const spinner = ora(`Generating ${type || "service-location"} pages...`).start();
|
|
25366
25421
|
try {
|
|
25367
|
-
const response = await fetch(`${
|
|
25422
|
+
const response = await fetch(`${config2.apiUrl}/seo/location-pages/generate`, {
|
|
25368
25423
|
method: "POST",
|
|
25369
25424
|
headers: {
|
|
25370
25425
|
"Content-Type": "application/json",
|
|
@@ -25404,7 +25459,7 @@ async function listCommand(config2) {
|
|
|
25404
25459
|
const spinner = ora("Fetching templates...").start();
|
|
25405
25460
|
try {
|
|
25406
25461
|
const response = await fetch(
|
|
25407
|
-
`${
|
|
25462
|
+
`${config2.apiUrl}/seo/location-templates?project_id=${config2.projectId}`,
|
|
25408
25463
|
{ headers: { "Authorization": `Bearer ${config2.apiKey}` } }
|
|
25409
25464
|
);
|
|
25410
25465
|
if (!response.ok) {
|
|
@@ -25429,69 +25484,21 @@ async function listCommand(config2) {
|
|
|
25429
25484
|
});
|
|
25430
25485
|
}
|
|
25431
25486
|
console.log("");
|
|
25432
|
-
|
|
25433
|
-
|
|
25434
|
-
|
|
25435
|
-
|
|
25436
|
-
console.log(source_default.gray(
|
|
25437
|
-
|
|
25438
|
-
|
|
25439
|
-
});
|
|
25440
|
-
console.log("");
|
|
25441
|
-
}
|
|
25487
|
+
const localTemplates = await listLocalTemplates();
|
|
25488
|
+
if (localTemplates.length > 0) {
|
|
25489
|
+
console.log(source_default.gray(" Local (not uploaded):"));
|
|
25490
|
+
localTemplates.forEach((f) => {
|
|
25491
|
+
console.log(source_default.gray(` \u2022 ${f.replace(".json", "")}`));
|
|
25492
|
+
});
|
|
25493
|
+
console.log("");
|
|
25442
25494
|
}
|
|
25443
25495
|
} catch (error2) {
|
|
25444
25496
|
spinner.fail(`Failed to fetch templates: ${error2.message}`);
|
|
25445
25497
|
}
|
|
25446
25498
|
}
|
|
25447
|
-
async function loadConfig() {
|
|
25448
|
-
const configPath = path10.join(".uptrade", "config.json");
|
|
25449
|
-
if (existsSync(configPath)) {
|
|
25450
|
-
try {
|
|
25451
|
-
const config2 = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
25452
|
-
return {
|
|
25453
|
-
projectId: config2.projectId || config2.project_id,
|
|
25454
|
-
apiKey: config2.apiKey || config2.api_key
|
|
25455
|
-
};
|
|
25456
|
-
} catch {
|
|
25457
|
-
return null;
|
|
25458
|
-
}
|
|
25459
|
-
}
|
|
25460
|
-
const projectId = process.env.SONOR_PROJECT_ID;
|
|
25461
|
-
const apiKey = process.env.SONOR_API_KEY;
|
|
25462
|
-
if (projectId && apiKey) {
|
|
25463
|
-
return { projectId, apiKey };
|
|
25464
|
-
}
|
|
25465
|
-
return null;
|
|
25466
|
-
}
|
|
25467
|
-
var API_URL3 = process.env.SONOR_API_URL || "https://api.sonor.io";
|
|
25468
|
-
async function loadConfig2() {
|
|
25469
|
-
const configPath = path10.join(".uptrade", "config.json");
|
|
25470
|
-
if (existsSync(configPath)) {
|
|
25471
|
-
try {
|
|
25472
|
-
const config2 = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
25473
|
-
return {
|
|
25474
|
-
projectId: config2.projectId || config2.project_id,
|
|
25475
|
-
apiKey: config2.apiKey || config2.api_key
|
|
25476
|
-
};
|
|
25477
|
-
} catch {
|
|
25478
|
-
return null;
|
|
25479
|
-
}
|
|
25480
|
-
}
|
|
25481
|
-
const projectId = process.env.SONOR_PROJECT_ID;
|
|
25482
|
-
const apiKey = process.env.SONOR_API_KEY;
|
|
25483
|
-
if (projectId && apiKey) return { projectId, apiKey };
|
|
25484
|
-
return null;
|
|
25485
|
-
}
|
|
25486
25499
|
async function faqsCommand(subcommand, options) {
|
|
25487
25500
|
console.log("");
|
|
25488
|
-
const config2 = await
|
|
25489
|
-
if (!config2?.projectId || !config2?.apiKey) {
|
|
25490
|
-
console.log(source_default.red(" \u2717 Not configured. Run `npx sonor-setup init` first."));
|
|
25491
|
-
console.log(source_default.gray(" Set SONOR_API_KEY, or use .uptrade/config.json"));
|
|
25492
|
-
console.log("");
|
|
25493
|
-
return;
|
|
25494
|
-
}
|
|
25501
|
+
const config2 = await loadConfig({ resolveProject: true });
|
|
25495
25502
|
switch (subcommand) {
|
|
25496
25503
|
case "extract":
|
|
25497
25504
|
await extractCommand(options, config2);
|
|
@@ -25541,7 +25548,7 @@ async function extractCommand(options, config2) {
|
|
|
25541
25548
|
const faqContexts = [];
|
|
25542
25549
|
for (const faq of faqSections) {
|
|
25543
25550
|
try {
|
|
25544
|
-
const fullPath =
|
|
25551
|
+
const fullPath = path12.resolve(process.cwd(), faq.filePath);
|
|
25545
25552
|
const content = await fs3.readFile(fullPath, "utf-8");
|
|
25546
25553
|
let pagePath = faq.filePath.replace(/^app\//, "/").replace(/^src\/app\//, "/").replace(/\/page\.(tsx?|jsx?)$/, "").replace(/\[([^\]]+)\]/g, ":$1");
|
|
25547
25554
|
if (pagePath === "" || pagePath === "/page") pagePath = "/";
|
|
@@ -25556,7 +25563,7 @@ async function extractCommand(options, config2) {
|
|
|
25556
25563
|
if (importPath.startsWith("@/")) {
|
|
25557
25564
|
resolvedPath = importPath.replace("@/", "./");
|
|
25558
25565
|
} else if (importPath.startsWith(".")) {
|
|
25559
|
-
resolvedPath =
|
|
25566
|
+
resolvedPath = path12.resolve(path12.dirname(fullPath), importPath);
|
|
25560
25567
|
}
|
|
25561
25568
|
const extensions = ["", ".js", ".ts", ".jsx", ".tsx", ".json"];
|
|
25562
25569
|
for (const ext2 of extensions) {
|
|
@@ -25601,7 +25608,7 @@ async function extractCommand(options, config2) {
|
|
|
25601
25608
|
}
|
|
25602
25609
|
const extractSpinner = ora("Extracting FAQs via AI...").start();
|
|
25603
25610
|
try {
|
|
25604
|
-
const response = await fetch(`${
|
|
25611
|
+
const response = await fetch(`${config2.apiUrl}/seo/managed/faqs/extract`, {
|
|
25605
25612
|
method: "POST",
|
|
25606
25613
|
headers: {
|
|
25607
25614
|
"Content-Type": "application/json",
|
|
@@ -25636,7 +25643,7 @@ async function extractCommand(options, config2) {
|
|
|
25636
25643
|
let failed = 0;
|
|
25637
25644
|
for (const faq of extractedFaqs) {
|
|
25638
25645
|
try {
|
|
25639
|
-
const res = await fetch(`${
|
|
25646
|
+
const res = await fetch(`${config2.apiUrl}/seo/managed/faqs`, {
|
|
25640
25647
|
method: "POST",
|
|
25641
25648
|
headers: {
|
|
25642
25649
|
"Content-Type": "application/json",
|
|
@@ -25661,7 +25668,7 @@ async function extractCommand(options, config2) {
|
|
|
25661
25668
|
uploaded++;
|
|
25662
25669
|
console.log(source_default.green(` \u2713 ${faq.path}`) + source_default.gray(` (${faq.items.length} items)`));
|
|
25663
25670
|
} else if (res.status === 409 || res.status === 400) {
|
|
25664
|
-
const updateRes = await fetch(`${
|
|
25671
|
+
const updateRes = await fetch(`${config2.apiUrl}/seo/managed/faqs/by-path`, {
|
|
25665
25672
|
method: "PUT",
|
|
25666
25673
|
headers: {
|
|
25667
25674
|
"Content-Type": "application/json",
|
|
@@ -25748,7 +25755,7 @@ async function syncCommand(options, config2) {
|
|
|
25748
25755
|
const listSpinner = ora("Fetching existing FAQ sections from Portal...").start();
|
|
25749
25756
|
let existing = [];
|
|
25750
25757
|
try {
|
|
25751
|
-
const res = await fetch(`${
|
|
25758
|
+
const res = await fetch(`${config2.apiUrl}/seo/managed/faqs/project/${config2.projectId}`, {
|
|
25752
25759
|
headers: { Authorization: `Bearer ${config2.apiKey}` }
|
|
25753
25760
|
});
|
|
25754
25761
|
if (!res.ok) {
|
|
@@ -25777,7 +25784,7 @@ async function syncCommand(options, config2) {
|
|
|
25777
25784
|
let failed = 0;
|
|
25778
25785
|
for (const p of toCreate) {
|
|
25779
25786
|
try {
|
|
25780
|
-
const res = await fetch(`${
|
|
25787
|
+
const res = await fetch(`${config2.apiUrl}/seo/managed/faqs`, {
|
|
25781
25788
|
method: "POST",
|
|
25782
25789
|
headers: {
|
|
25783
25790
|
"Content-Type": "application/json",
|
|
@@ -25814,44 +25821,12 @@ async function syncCommand(options, config2) {
|
|
|
25814
25821
|
console.log(source_default.gray(" Add questions and answers there; they will appear on your site."));
|
|
25815
25822
|
console.log("");
|
|
25816
25823
|
}
|
|
25817
|
-
function getApiUrl() {
|
|
25818
|
-
return process.env.SONOR_API_URL || "https://api.sonor.io";
|
|
25819
|
-
}
|
|
25820
|
-
async function loadConfig3() {
|
|
25821
|
-
const configPath = path10.join(".uptrade", "config.json");
|
|
25822
|
-
if (existsSync(configPath)) {
|
|
25823
|
-
try {
|
|
25824
|
-
const config2 = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
25825
|
-
return {
|
|
25826
|
-
projectId: config2.projectId || config2.project_id,
|
|
25827
|
-
apiKey: config2.apiKey || config2.api_key,
|
|
25828
|
-
siteUrl: config2.siteUrl || config2.site_url,
|
|
25829
|
-
businessInfo: config2.businessInfo || config2.business_info
|
|
25830
|
-
};
|
|
25831
|
-
} catch {
|
|
25832
|
-
return null;
|
|
25833
|
-
}
|
|
25834
|
-
}
|
|
25835
|
-
const projectId = process.env.SONOR_PROJECT_ID;
|
|
25836
|
-
const apiKey = process.env.SONOR_API_KEY;
|
|
25837
|
-
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || process.env.SITE_URL;
|
|
25838
|
-
if (projectId && apiKey) {
|
|
25839
|
-
return { projectId, apiKey, siteUrl };
|
|
25840
|
-
}
|
|
25841
|
-
return null;
|
|
25842
|
-
}
|
|
25843
25824
|
async function setupCommand(options) {
|
|
25844
25825
|
console.log("");
|
|
25845
25826
|
console.log(source_default.bold.blue(" \u{1F680} Signal-Enhanced SEO Setup"));
|
|
25846
25827
|
console.log(source_default.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
25847
25828
|
console.log("");
|
|
25848
|
-
const config2 = await
|
|
25849
|
-
if (!config2?.projectId || !config2?.apiKey) {
|
|
25850
|
-
console.log(source_default.red(" \u2717 Not configured. Run `npx sonor-setup init` first."));
|
|
25851
|
-
console.log(source_default.gray(" Set SONOR_API_KEY"));
|
|
25852
|
-
console.log("");
|
|
25853
|
-
return;
|
|
25854
|
-
}
|
|
25829
|
+
const config2 = await loadConfig();
|
|
25855
25830
|
const capabilities = [];
|
|
25856
25831
|
if (options.faqsOnly) {
|
|
25857
25832
|
capabilities.push("extract_faqs");
|
|
@@ -25949,14 +25924,13 @@ async function setupCommand(options) {
|
|
|
25949
25924
|
const batch = batches[batchIndex];
|
|
25950
25925
|
const batchSpinner = ora(`Batch ${batchIndex + 1}/${batches.length}: Analyzing ${batch.length} pages...`).start();
|
|
25951
25926
|
try {
|
|
25952
|
-
const response = await fetch(`${
|
|
25927
|
+
const response = await fetch(`${config2.apiUrl}/api/public/seo/site-setup`, {
|
|
25953
25928
|
method: "POST",
|
|
25954
25929
|
headers: {
|
|
25955
25930
|
"Content-Type": "application/json",
|
|
25956
25931
|
"x-api-key": config2.apiKey
|
|
25957
25932
|
},
|
|
25958
25933
|
body: JSON.stringify({
|
|
25959
|
-
project_id: config2.projectId,
|
|
25960
25934
|
site_url: config2.siteUrl || "https://example.com",
|
|
25961
25935
|
// Only send business_info on first batch (for org schema)
|
|
25962
25936
|
business_info: batchIndex === 0 ? config2.businessInfo : void 0,
|
|
@@ -26048,10 +26022,10 @@ async function setupCommand(options) {
|
|
|
26048
26022
|
}
|
|
26049
26023
|
async function scanForPageFiles(rootDir) {
|
|
26050
26024
|
const pages = [];
|
|
26051
|
-
const appDir =
|
|
26052
|
-
const srcAppDir =
|
|
26053
|
-
const pagesDir =
|
|
26054
|
-
const srcPagesDir =
|
|
26025
|
+
const appDir = path12.join(rootDir, "app");
|
|
26026
|
+
const srcAppDir = path12.join(rootDir, "src", "app");
|
|
26027
|
+
const pagesDir = path12.join(rootDir, "pages");
|
|
26028
|
+
const srcPagesDir = path12.join(rootDir, "src", "pages");
|
|
26055
26029
|
const dirs = [appDir, srcAppDir, pagesDir, srcPagesDir];
|
|
26056
26030
|
for (const dir of dirs) {
|
|
26057
26031
|
if (existsSync(dir)) {
|
|
@@ -26063,7 +26037,7 @@ async function scanForPageFiles(rootDir) {
|
|
|
26063
26037
|
async function scanDirectory(dir, baseDir, pages) {
|
|
26064
26038
|
const entries = await fs3.readdir(dir, { withFileTypes: true });
|
|
26065
26039
|
for (const entry of entries) {
|
|
26066
|
-
const fullPath =
|
|
26040
|
+
const fullPath = path12.join(dir, entry.name);
|
|
26067
26041
|
if (entry.isDirectory()) {
|
|
26068
26042
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "api") {
|
|
26069
26043
|
continue;
|
|
@@ -26074,8 +26048,8 @@ async function scanDirectory(dir, baseDir, pages) {
|
|
|
26074
26048
|
const isLegacyPage = baseDir.includes("/pages") && entry.name.match(/\.(tsx?|jsx?)$/) && !entry.name.startsWith("_");
|
|
26075
26049
|
if (isPage || isLegacyPage) {
|
|
26076
26050
|
const content = await fs3.readFile(fullPath, "utf-8");
|
|
26077
|
-
const relativePath =
|
|
26078
|
-
let pagePath = "/" +
|
|
26051
|
+
const relativePath = path12.relative(baseDir, fullPath);
|
|
26052
|
+
let pagePath = "/" + path12.dirname(relativePath).replace(/\\/g, "/").replace(/\/page$/, "");
|
|
26079
26053
|
pagePath = pagePath.replace(/\[([^\]]+)\]/g, ":$1").replace(/^\/\.$/, "/");
|
|
26080
26054
|
if (pagePath === "/.") pagePath = "/";
|
|
26081
26055
|
pages.push({
|
|
@@ -26095,10 +26069,10 @@ async function gatherImportedFiles(page, rootDir) {
|
|
|
26095
26069
|
if (importPath.toLowerCase().includes("faq") || importPath.includes("@/data") || importPath.includes("./data") || importPath.includes("../data") || importPath.includes("/constants") || importPath.includes("/content") || importPath.includes("practice-areas") || importPath.includes("subpages") || importPath.includes("pages-data")) {
|
|
26096
26070
|
let resolvedPath = importPath;
|
|
26097
26071
|
if (importPath.startsWith("@/")) {
|
|
26098
|
-
resolvedPath =
|
|
26072
|
+
resolvedPath = path12.join(rootDir, importPath.replace("@/", ""));
|
|
26099
26073
|
} else if (importPath.startsWith(".")) {
|
|
26100
|
-
const pageDir =
|
|
26101
|
-
resolvedPath =
|
|
26074
|
+
const pageDir = path12.dirname(path12.join(rootDir, "app", page.filePath));
|
|
26075
|
+
resolvedPath = path12.resolve(pageDir, importPath);
|
|
26102
26076
|
}
|
|
26103
26077
|
const extensions = ["", ".js", ".ts", ".jsx", ".tsx", ".json"];
|
|
26104
26078
|
for (const ext2 of extensions) {
|
|
@@ -26154,20 +26128,20 @@ async function expandDynamicRoutes(pages, rootDir) {
|
|
|
26154
26128
|
async function findDynamicRouteData(page, parentPath, rootDir) {
|
|
26155
26129
|
const results = [];
|
|
26156
26130
|
const dataFilePaths = [
|
|
26157
|
-
|
|
26158
|
-
|
|
26159
|
-
|
|
26160
|
-
|
|
26161
|
-
|
|
26162
|
-
|
|
26163
|
-
|
|
26164
|
-
|
|
26165
|
-
|
|
26166
|
-
|
|
26167
|
-
|
|
26168
|
-
|
|
26169
|
-
|
|
26170
|
-
|
|
26131
|
+
path12.join(rootDir, "data", "practice-areas.js"),
|
|
26132
|
+
path12.join(rootDir, "data", "practice-areas.ts"),
|
|
26133
|
+
path12.join(rootDir, "data", "personal-injury-pages.js"),
|
|
26134
|
+
path12.join(rootDir, "data", "personal-injury-pages.ts"),
|
|
26135
|
+
path12.join(rootDir, "data", "pages.js"),
|
|
26136
|
+
path12.join(rootDir, "data", "pages.ts"),
|
|
26137
|
+
path12.join(rootDir, "data", "content.js"),
|
|
26138
|
+
path12.join(rootDir, "data", "content.ts"),
|
|
26139
|
+
path12.join(rootDir, "data", "services.js"),
|
|
26140
|
+
path12.join(rootDir, "data", "services.ts"),
|
|
26141
|
+
path12.join(rootDir, "data", "subpages.js"),
|
|
26142
|
+
path12.join(rootDir, "data", "subpages.ts"),
|
|
26143
|
+
path12.join(rootDir, "src", "data", "practice-areas.js"),
|
|
26144
|
+
path12.join(rootDir, "src", "data", "practice-areas.ts")
|
|
26171
26145
|
];
|
|
26172
26146
|
const routeSegment = parentPath.replace(/^\//, "").split("/")[0];
|
|
26173
26147
|
const routeSegmentNormalized = routeSegment.replace(/-/g, "");
|
|
@@ -26259,7 +26233,7 @@ async function uploadFaqs(pages, config2) {
|
|
|
26259
26233
|
for (const page of pages) {
|
|
26260
26234
|
if (!page.faqs?.items?.length) continue;
|
|
26261
26235
|
try {
|
|
26262
|
-
const res = await fetch(`${
|
|
26236
|
+
const res = await fetch(`${config2.apiUrl}/api/public/seo/register-faq`, {
|
|
26263
26237
|
method: "POST",
|
|
26264
26238
|
headers: {
|
|
26265
26239
|
"Content-Type": "application/json",
|
|
@@ -26294,7 +26268,7 @@ async function uploadFaqs(pages, config2) {
|
|
|
26294
26268
|
async function uploadSchemas(pages, globalSchema, config2) {
|
|
26295
26269
|
if (globalSchema) {
|
|
26296
26270
|
try {
|
|
26297
|
-
const res = await fetch(`${
|
|
26271
|
+
const res = await fetch(`${config2.apiUrl}/api/public/seo/register-schema`, {
|
|
26298
26272
|
method: "POST",
|
|
26299
26273
|
headers: {
|
|
26300
26274
|
"Content-Type": "application/json",
|
|
@@ -26320,7 +26294,7 @@ async function uploadSchemas(pages, globalSchema, config2) {
|
|
|
26320
26294
|
if (!page.schemas?.length) continue;
|
|
26321
26295
|
for (const schema of page.schemas) {
|
|
26322
26296
|
try {
|
|
26323
|
-
const res = await fetch(`${
|
|
26297
|
+
const res = await fetch(`${config2.apiUrl}/api/public/seo/register-schema`, {
|
|
26324
26298
|
method: "POST",
|
|
26325
26299
|
headers: {
|
|
26326
26300
|
"Content-Type": "application/json",
|
|
@@ -26344,8 +26318,7 @@ async function uploadSchemas(pages, globalSchema, config2) {
|
|
|
26344
26318
|
}
|
|
26345
26319
|
}
|
|
26346
26320
|
}
|
|
26347
|
-
var
|
|
26348
|
-
var CARD_FILE = /^(opengraph-image|twitter-image)\b.*\.(png|jpe?g|gif|webp)$/i;
|
|
26321
|
+
var CARD_FILE = /^(opengraph-image|twitter-image)\b.*\.(png|jpe?g|gif|webp|tsx|ts|jsx|js)$/i;
|
|
26349
26322
|
function safeExists(p) {
|
|
26350
26323
|
try {
|
|
26351
26324
|
return fs__default.existsSync(p);
|
|
@@ -26364,19 +26337,19 @@ function findPageCards(cwd) {
|
|
|
26364
26337
|
}
|
|
26365
26338
|
for (const entry of entries) {
|
|
26366
26339
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
26367
|
-
const full =
|
|
26340
|
+
const full = path12.join(dir, entry.name);
|
|
26368
26341
|
if (entry.isDirectory()) walk(full);
|
|
26369
26342
|
else if (CARD_FILE.test(entry.name)) found.push(full);
|
|
26370
26343
|
}
|
|
26371
26344
|
};
|
|
26372
|
-
for (const rel of
|
|
26345
|
+
for (const rel of NEXT_APP_DIRS) walk(path12.join(cwd, rel));
|
|
26373
26346
|
return found;
|
|
26374
26347
|
}
|
|
26375
26348
|
function readOgWiring(cwd) {
|
|
26376
26349
|
const siteCard = ["public/og.png", "public/og.jpg", "public/opengraph.png"].some(
|
|
26377
|
-
(rel) => safeExists(
|
|
26350
|
+
(rel) => safeExists(path12.join(cwd, rel))
|
|
26378
26351
|
);
|
|
26379
|
-
const layoutPath =
|
|
26352
|
+
const layoutPath = findRootLayout(cwd);
|
|
26380
26353
|
let layout = "";
|
|
26381
26354
|
if (layoutPath) {
|
|
26382
26355
|
try {
|
|
@@ -26396,7 +26369,12 @@ function readOgWiring(cwd) {
|
|
|
26396
26369
|
function judgeOgWiring(facts) {
|
|
26397
26370
|
const problems = [];
|
|
26398
26371
|
if (!facts.layoutFound) {
|
|
26399
|
-
return [
|
|
26372
|
+
return [
|
|
26373
|
+
{
|
|
26374
|
+
message: "no root layout (app/layout.{tsx,ts,jsx,js} or src/app/layout.*) found to verify metadata",
|
|
26375
|
+
fix: "Run this from the site root."
|
|
26376
|
+
}
|
|
26377
|
+
];
|
|
26400
26378
|
}
|
|
26401
26379
|
if (!facts.siteCard && !facts.pageCards.length) {
|
|
26402
26380
|
return [
|
|
@@ -26443,7 +26421,7 @@ var SSR_BAILOUT_FIX = `Keep the layout: ${LAYOUT_ALREADY_DEFERS}, so it is not t
|
|
|
26443
26421
|
var ANALYTICS_WRAPPER_FIX = `Remove the <AnalyticsProvider> wrapper: ${LAYOUT_ALREADY_DEFERS} (configure it with analytics={{ ... }}). Track custom events with trackEvent / trackConversion from @sonordev/site-kit/analytics, which need no provider, instead of useAnalytics(). ` + LEGACY_STOPGAP;
|
|
26444
26422
|
|
|
26445
26423
|
// src/cli/agent/checks.ts
|
|
26446
|
-
var
|
|
26424
|
+
var API_URL = process.env.SONOR_API_URL || "https://api.sonor.io";
|
|
26447
26425
|
async function readFileOrNull(p) {
|
|
26448
26426
|
try {
|
|
26449
26427
|
return await fs3.readFile(p, "utf-8");
|
|
@@ -26451,26 +26429,6 @@ async function readFileOrNull(p) {
|
|
|
26451
26429
|
return null;
|
|
26452
26430
|
}
|
|
26453
26431
|
}
|
|
26454
|
-
async function findFirst(cwd, candidates) {
|
|
26455
|
-
for (const rel of candidates) {
|
|
26456
|
-
const full = path10.join(cwd, rel);
|
|
26457
|
-
if (await readFileOrNull(full)) return full;
|
|
26458
|
-
}
|
|
26459
|
-
return null;
|
|
26460
|
-
}
|
|
26461
|
-
var LAYOUT_CANDIDATES = [
|
|
26462
|
-
"app/layout.tsx",
|
|
26463
|
-
"app/layout.jsx",
|
|
26464
|
-
"src/app/layout.tsx",
|
|
26465
|
-
"src/app/layout.jsx"
|
|
26466
|
-
];
|
|
26467
|
-
var SITEMAP_CANDIDATES = [
|
|
26468
|
-
"app/sitemap.ts",
|
|
26469
|
-
"app/sitemap.tsx",
|
|
26470
|
-
"app/sitemap.js",
|
|
26471
|
-
"src/app/sitemap.ts",
|
|
26472
|
-
"src/app/sitemap.tsx"
|
|
26473
|
-
];
|
|
26474
26432
|
function checkApiKeyEnv() {
|
|
26475
26433
|
const key = process.env.SONOR_API_KEY;
|
|
26476
26434
|
if (key && key.startsWith("sonor_")) {
|
|
@@ -26505,7 +26463,7 @@ function checkApiKeyEnv() {
|
|
|
26505
26463
|
};
|
|
26506
26464
|
}
|
|
26507
26465
|
async function checkPackageInstalled(cwd) {
|
|
26508
|
-
const raw = await readFileOrNull(
|
|
26466
|
+
const raw = await readFileOrNull(path12.join(cwd, "package.json"));
|
|
26509
26467
|
if (!raw) {
|
|
26510
26468
|
return {
|
|
26511
26469
|
id: "package.installed",
|
|
@@ -26557,7 +26515,7 @@ async function checkPackageInstalled(cwd) {
|
|
|
26557
26515
|
};
|
|
26558
26516
|
}
|
|
26559
26517
|
async function checkSiteKitLayout(cwd) {
|
|
26560
|
-
const layoutPath =
|
|
26518
|
+
const layoutPath = findRootLayout(cwd);
|
|
26561
26519
|
if (!layoutPath) {
|
|
26562
26520
|
return {
|
|
26563
26521
|
id: "layout.sitekit",
|
|
@@ -26569,7 +26527,7 @@ async function checkSiteKitLayout(cwd) {
|
|
|
26569
26527
|
};
|
|
26570
26528
|
}
|
|
26571
26529
|
const content = await readFileOrNull(layoutPath) || "";
|
|
26572
|
-
const rel =
|
|
26530
|
+
const rel = path12.relative(cwd, layoutPath);
|
|
26573
26531
|
if (content.includes("SiteKitLayout")) {
|
|
26574
26532
|
return {
|
|
26575
26533
|
id: "layout.sitekit",
|
|
@@ -26601,8 +26559,8 @@ async function checkSiteKitLayout(cwd) {
|
|
|
26601
26559
|
};
|
|
26602
26560
|
}
|
|
26603
26561
|
async function checkSitemap(cwd) {
|
|
26604
|
-
const
|
|
26605
|
-
if (!
|
|
26562
|
+
const sitemapRel = findSitemapRoute(cwd);
|
|
26563
|
+
if (!sitemapRel) {
|
|
26606
26564
|
return {
|
|
26607
26565
|
id: "sitemap.managed",
|
|
26608
26566
|
title: "Sitemap",
|
|
@@ -26612,7 +26570,7 @@ async function checkSitemap(cwd) {
|
|
|
26612
26570
|
fixCommand: "npx sonor-setup scaffold --yes"
|
|
26613
26571
|
};
|
|
26614
26572
|
}
|
|
26615
|
-
const content = await readFileOrNull(
|
|
26573
|
+
const content = await readFileOrNull(path12.join(cwd, sitemapRel)) || "";
|
|
26616
26574
|
if (content.includes("createSitemap") || content.includes("@sonordev/site-kit")) {
|
|
26617
26575
|
return { id: "sitemap.managed", title: "Sitemap", level: "ok", message: "Using Site-Kit sitemap" };
|
|
26618
26576
|
}
|
|
@@ -26625,7 +26583,7 @@ async function checkSitemap(cwd) {
|
|
|
26625
26583
|
};
|
|
26626
26584
|
}
|
|
26627
26585
|
async function checkPostbuildSitemap(cwd) {
|
|
26628
|
-
const raw = await readFileOrNull(
|
|
26586
|
+
const raw = await readFileOrNull(path12.join(cwd, "package.json"));
|
|
26629
26587
|
let pkg = {};
|
|
26630
26588
|
try {
|
|
26631
26589
|
pkg = raw ? JSON.parse(raw) : {};
|
|
@@ -26662,18 +26620,18 @@ async function checkPostbuildSitemap(cwd) {
|
|
|
26662
26620
|
async function checkApiReachable(timeoutMs = 5e3) {
|
|
26663
26621
|
const key = process.env.SONOR_API_KEY;
|
|
26664
26622
|
try {
|
|
26665
|
-
const res = await fetch(`${
|
|
26623
|
+
const res = await fetch(`${API_URL}/health`, {
|
|
26666
26624
|
headers: key ? { "x-api-key": key } : {},
|
|
26667
26625
|
signal: AbortSignal.timeout(timeoutMs)
|
|
26668
26626
|
});
|
|
26669
26627
|
if (res.ok) {
|
|
26670
|
-
return { id: "api.reachable", title: "Sonor API", level: "ok", message: `Reachable (${
|
|
26628
|
+
return { id: "api.reachable", title: "Sonor API", level: "ok", message: `Reachable (${API_URL})` };
|
|
26671
26629
|
}
|
|
26672
26630
|
return {
|
|
26673
26631
|
id: "api.reachable",
|
|
26674
26632
|
title: "Sonor API",
|
|
26675
26633
|
level: "warn",
|
|
26676
|
-
message: `HTTP ${res.status} from ${
|
|
26634
|
+
message: `HTTP ${res.status} from ${API_URL}`
|
|
26677
26635
|
};
|
|
26678
26636
|
} catch (err) {
|
|
26679
26637
|
return {
|
|
@@ -26698,7 +26656,7 @@ async function checkKeyValid(timeoutMs = 8e3) {
|
|
|
26698
26656
|
};
|
|
26699
26657
|
}
|
|
26700
26658
|
try {
|
|
26701
|
-
const res = await fetch(`${
|
|
26659
|
+
const res = await fetch(`${API_URL}/api/public/seo/verify-api-key`, {
|
|
26702
26660
|
headers: { "x-api-key": key },
|
|
26703
26661
|
signal: AbortSignal.timeout(timeoutMs)
|
|
26704
26662
|
});
|
|
@@ -26801,7 +26759,7 @@ async function checkClientAuth(timeoutMs = 8e3) {
|
|
|
26801
26759
|
}
|
|
26802
26760
|
const qs2 = host ? `?host=${encodeURIComponent(host)}` : "";
|
|
26803
26761
|
try {
|
|
26804
|
-
const res = await fetch(`${
|
|
26762
|
+
const res = await fetch(`${API_URL}/api/public/site-token/status${qs2}`, {
|
|
26805
26763
|
headers: { "x-api-key": key },
|
|
26806
26764
|
signal: AbortSignal.timeout(timeoutMs)
|
|
26807
26765
|
});
|
|
@@ -26946,7 +26904,7 @@ async function checkSsrRenderFromUrl(url, timeoutMs = 12e3) {
|
|
|
26946
26904
|
}
|
|
26947
26905
|
}
|
|
26948
26906
|
async function checkSsrRenderFromBuild(cwd) {
|
|
26949
|
-
const appDir =
|
|
26907
|
+
const appDir = path12.join(cwd, ".next", "server", "app");
|
|
26950
26908
|
let entries;
|
|
26951
26909
|
try {
|
|
26952
26910
|
entries = await fs3.readdir(appDir);
|
|
@@ -26969,7 +26927,7 @@ async function checkSsrRenderFromBuild(cwd) {
|
|
|
26969
26927
|
detail: "The root route may be fully dynamic. Pass --url to verify a running instance."
|
|
26970
26928
|
};
|
|
26971
26929
|
}
|
|
26972
|
-
const html = await readFileOrNull(
|
|
26930
|
+
const html = await readFileOrNull(path12.join(appDir, htmlName)) || "";
|
|
26973
26931
|
const { rendered, contentTags } = looksServerRendered(html);
|
|
26974
26932
|
if (rendered) {
|
|
26975
26933
|
return {
|
|
@@ -26990,9 +26948,8 @@ async function checkSsrRenderFromBuild(cwd) {
|
|
|
26990
26948
|
}
|
|
26991
26949
|
async function checkNetlifyMiddleware(cwd) {
|
|
26992
26950
|
const runtimeRe = /runtime\s*[:=]\s*['"](nodejs|edge)['"]/;
|
|
26993
|
-
const
|
|
26994
|
-
|
|
26995
|
-
const content = await readFileOrNull(path10.join(cwd, rel));
|
|
26951
|
+
for (const rel of NEXT_PROXY_FILES) {
|
|
26952
|
+
const content = await readFileOrNull(path12.join(cwd, rel));
|
|
26996
26953
|
if (content === null) continue;
|
|
26997
26954
|
if (runtimeRe.test(content)) {
|
|
26998
26955
|
return {
|
|
@@ -27007,9 +26964,8 @@ async function checkNetlifyMiddleware(cwd) {
|
|
|
27007
26964
|
}
|
|
27008
26965
|
return { id: "middleware.netlify", title: "Proxy / middleware", level: "ok", message: `${rel} present` };
|
|
27009
26966
|
}
|
|
27010
|
-
const
|
|
27011
|
-
|
|
27012
|
-
const content = await readFileOrNull(path10.join(cwd, rel));
|
|
26967
|
+
for (const rel of NEXT_MIDDLEWARE_FILES) {
|
|
26968
|
+
const content = await readFileOrNull(path12.join(cwd, rel));
|
|
27013
26969
|
if (content === null) continue;
|
|
27014
26970
|
if (/runtime\s*[:=]\s*['"]nodejs['"]/.test(content)) {
|
|
27015
26971
|
return {
|
|
@@ -27036,7 +26992,7 @@ async function checkNetlifyMiddleware(cwd) {
|
|
|
27036
26992
|
}
|
|
27037
26993
|
async function checkImageDimsDrift(cwd) {
|
|
27038
26994
|
const scanRoots = ["app", "src/app", "components", "src/components"];
|
|
27039
|
-
const publicDir =
|
|
26995
|
+
const publicDir = path12.join(cwd, "public");
|
|
27040
26996
|
const files = [];
|
|
27041
26997
|
async function walk(dir, depth) {
|
|
27042
26998
|
if (depth > 4) return;
|
|
@@ -27048,19 +27004,19 @@ async function checkImageDimsDrift(cwd) {
|
|
|
27048
27004
|
}
|
|
27049
27005
|
for (const e of entries) {
|
|
27050
27006
|
if (e.name === "node_modules" || e.name.startsWith(".")) continue;
|
|
27051
|
-
const full =
|
|
27007
|
+
const full = path12.join(dir, e.name);
|
|
27052
27008
|
if (e.isDirectory()) await walk(full, depth + 1);
|
|
27053
27009
|
else if (/\.(tsx|jsx)$/.test(e.name)) files.push(full);
|
|
27054
27010
|
}
|
|
27055
27011
|
}
|
|
27056
|
-
for (const root of scanRoots) await walk(
|
|
27012
|
+
for (const root of scanRoots) await walk(path12.join(cwd, root), 0);
|
|
27057
27013
|
if (files.length === 0) {
|
|
27058
27014
|
return { id: "images.dims-drift", title: "Image dims vs SVG", level: "skip", message: "No component files found" };
|
|
27059
27015
|
}
|
|
27060
27016
|
const viewBoxCache = /* @__PURE__ */ new Map();
|
|
27061
27017
|
async function svgAspect(publicPath) {
|
|
27062
27018
|
if (viewBoxCache.has(publicPath)) return viewBoxCache.get(publicPath);
|
|
27063
|
-
const svg = await readFileOrNull(
|
|
27019
|
+
const svg = await readFileOrNull(path12.join(publicDir, publicPath.replace(/^\//, "")));
|
|
27064
27020
|
let aspect = null;
|
|
27065
27021
|
if (svg) {
|
|
27066
27022
|
const vb = svg.match(/viewBox="([\d.\s-]+)"/);
|
|
@@ -27087,7 +27043,7 @@ async function checkImageDimsDrift(cwd) {
|
|
|
27087
27043
|
const drift = Math.abs(declared - actual) / actual;
|
|
27088
27044
|
if (drift > 0.02) {
|
|
27089
27045
|
drifts.push(
|
|
27090
|
-
`${
|
|
27046
|
+
`${path12.relative(cwd, file)}: ${src} is ${actual.toFixed(2)}:1 but width/height declare ${declared.toFixed(2)}:1 (${Math.round(drift * 100)}% off)`
|
|
27091
27047
|
);
|
|
27092
27048
|
}
|
|
27093
27049
|
}
|
|
@@ -27203,8 +27159,8 @@ async function statusCommand(options) {
|
|
|
27203
27159
|
|
|
27204
27160
|
// src/og/pages.ts
|
|
27205
27161
|
var DYNAMIC = "*";
|
|
27206
|
-
function pathSegments(
|
|
27207
|
-
return
|
|
27162
|
+
function pathSegments(path30) {
|
|
27163
|
+
return path30.split("/").filter(Boolean);
|
|
27208
27164
|
}
|
|
27209
27165
|
function stripBrandSuffix(title, brand) {
|
|
27210
27166
|
const cleaned = title.replace(/\s*[|–—-]\s*[^|–—-]+$/, "").trim();
|
|
@@ -27212,13 +27168,13 @@ function stripBrandSuffix(title, brand) {
|
|
|
27212
27168
|
if (brand && cleaned.toLowerCase() === brand.toLowerCase()) return title.trim();
|
|
27213
27169
|
return cleaned;
|
|
27214
27170
|
}
|
|
27215
|
-
function titleFromPath(
|
|
27216
|
-
const last = pathSegments(
|
|
27171
|
+
function titleFromPath(path30) {
|
|
27172
|
+
const last = pathSegments(path30).filter((s) => s !== DYNAMIC).pop();
|
|
27217
27173
|
if (!last) return "Home";
|
|
27218
27174
|
return last.replace(/[-_]+/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()).trim();
|
|
27219
27175
|
}
|
|
27220
|
-
function kickerFromPath(
|
|
27221
|
-
const parts = pathSegments(
|
|
27176
|
+
function kickerFromPath(path30, fallback) {
|
|
27177
|
+
const parts = pathSegments(path30);
|
|
27222
27178
|
const section = parts.includes(DYNAMIC) ? parts.filter((s) => s !== DYNAMIC) : parts.slice(0, -1);
|
|
27223
27179
|
if (!section.length) return fallback;
|
|
27224
27180
|
return section.join(" / ").replace(/[-_]+/g, " ");
|
|
@@ -27242,8 +27198,8 @@ function kickerIsRedundant(kicker, title) {
|
|
|
27242
27198
|
const titleWords = new Set(t.split(" "));
|
|
27243
27199
|
return k2.split(" ").every((w) => titleWords.has(w));
|
|
27244
27200
|
}
|
|
27245
|
-
function slugForPath(
|
|
27246
|
-
const segments = pathSegments(
|
|
27201
|
+
function slugForPath(path30) {
|
|
27202
|
+
const segments = pathSegments(path30);
|
|
27247
27203
|
if (!segments.length) return "home";
|
|
27248
27204
|
return segments.map((s) => s === DYNAMIC ? "any" : s).join("-").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
|
|
27249
27205
|
}
|
|
@@ -27297,10 +27253,10 @@ function findChrome() {
|
|
|
27297
27253
|
}
|
|
27298
27254
|
return null;
|
|
27299
27255
|
}
|
|
27300
|
-
async function
|
|
27256
|
+
async function loadConfig2(cwd) {
|
|
27301
27257
|
const candidates = ["og.config.ts", "og.config.mts", "og.config.mjs", "og.config.js"];
|
|
27302
27258
|
for (const rel of candidates) {
|
|
27303
|
-
const full =
|
|
27259
|
+
const full = path12.join(cwd, rel);
|
|
27304
27260
|
if (!existsSync(full)) continue;
|
|
27305
27261
|
try {
|
|
27306
27262
|
const mod = await import(
|
|
@@ -27325,7 +27281,7 @@ async function loadConfig4(cwd) {
|
|
|
27325
27281
|
return null;
|
|
27326
27282
|
}
|
|
27327
27283
|
async function seedConfig(cwd) {
|
|
27328
|
-
let name =
|
|
27284
|
+
let name = path12.basename(cwd).replace(/-nextjs$/, "").replace(/-/g, " ");
|
|
27329
27285
|
let accent = "#111111";
|
|
27330
27286
|
let logo;
|
|
27331
27287
|
try {
|
|
@@ -27338,7 +27294,7 @@ async function seedConfig(cwd) {
|
|
|
27338
27294
|
} catch {
|
|
27339
27295
|
}
|
|
27340
27296
|
for (const candidate of ["/logo-mark.svg", "/logo.svg", "/logohorizontal.svg"]) {
|
|
27341
|
-
if (existsSync(
|
|
27297
|
+
if (existsSync(path12.join(cwd, "public", candidate))) {
|
|
27342
27298
|
logo = candidate;
|
|
27343
27299
|
break;
|
|
27344
27300
|
}
|
|
@@ -27352,14 +27308,14 @@ async function seedConfig(cwd) {
|
|
|
27352
27308
|
}
|
|
27353
27309
|
function inlinePublicPaths(html, cwd) {
|
|
27354
27310
|
return html.replace(/src="(\/[^"]+)"/g, (_3, p) => {
|
|
27355
|
-
const full =
|
|
27311
|
+
const full = path12.join(cwd, "public", p);
|
|
27356
27312
|
return existsSync(full) ? `src="file://${full}"` : `src="${p}"`;
|
|
27357
27313
|
});
|
|
27358
27314
|
}
|
|
27359
27315
|
async function renderCard(config2, outPath, cwd, chrome, tmpSuffix) {
|
|
27360
|
-
const tmpHtml =
|
|
27316
|
+
const tmpHtml = path12.join(cwd, `.sonor-og-${tmpSuffix}.html`);
|
|
27361
27317
|
try {
|
|
27362
|
-
await fs3.mkdir(
|
|
27318
|
+
await fs3.mkdir(path12.dirname(outPath), { recursive: true });
|
|
27363
27319
|
await fs3.writeFile(tmpHtml, inlinePublicPaths(buildOgHtml(config2), cwd));
|
|
27364
27320
|
const { stdout } = await execFileAsync5(
|
|
27365
27321
|
chrome,
|
|
@@ -27394,7 +27350,7 @@ function parseReport(dom) {
|
|
|
27394
27350
|
}
|
|
27395
27351
|
async function compressCard(pngPath, cwd) {
|
|
27396
27352
|
try {
|
|
27397
|
-
const require_ = (await import('module')).createRequire(
|
|
27353
|
+
const require_ = (await import('module')).createRequire(path12.join(cwd, "package.json"));
|
|
27398
27354
|
const sharp = require_("sharp");
|
|
27399
27355
|
const jpgPath = pngPath.replace(/\.png$/, ".jpg");
|
|
27400
27356
|
await sharp(pngPath).jpeg({ quality: 84, mozjpeg: true }).toFile(jpgPath);
|
|
@@ -27404,6 +27360,9 @@ async function compressCard(pngPath, cwd) {
|
|
|
27404
27360
|
return pngPath;
|
|
27405
27361
|
}
|
|
27406
27362
|
}
|
|
27363
|
+
function codeOgImageFile(dir) {
|
|
27364
|
+
return findConventionFile(dir, "opengraph-image");
|
|
27365
|
+
}
|
|
27407
27366
|
function discoverDynamicSegments(appDir) {
|
|
27408
27367
|
const found = [];
|
|
27409
27368
|
const walk = (dir, urlSegments, pattern) => {
|
|
@@ -27411,14 +27370,13 @@ function discoverDynamicSegments(appDir) {
|
|
|
27411
27370
|
if (!entry.isDirectory()) continue;
|
|
27412
27371
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
27413
27372
|
if (entry.name === "api" || entry.name === "node_modules") continue;
|
|
27414
|
-
const full =
|
|
27373
|
+
const full = path12.join(dir, entry.name);
|
|
27415
27374
|
const isGroup = entry.name.startsWith("(") && entry.name.endsWith(")");
|
|
27416
27375
|
const isDynamic = entry.name.startsWith("[") && entry.name.endsWith("]");
|
|
27417
27376
|
const nextUrl = isGroup || isDynamic ? urlSegments : [...urlSegments, entry.name];
|
|
27418
27377
|
const nextPattern = isGroup ? pattern : [...pattern, isDynamic ? DYNAMIC : entry.name];
|
|
27419
27378
|
if (isDynamic) {
|
|
27420
|
-
|
|
27421
|
-
if (hasPage) {
|
|
27379
|
+
if (hasPageFile(full)) {
|
|
27422
27380
|
found.push({ dir: full, path: `/${nextPattern.join("/")}`, parent: `/${urlSegments.join("/")}` });
|
|
27423
27381
|
}
|
|
27424
27382
|
}
|
|
@@ -27493,7 +27451,7 @@ async function runOg(options) {
|
|
|
27493
27451
|
errors: [{ code: "chrome_missing", message: "No Chrome or Chromium binary found", fix: "Install Chrome, or set SONOR_CHROME_PATH to its path." }]
|
|
27494
27452
|
};
|
|
27495
27453
|
}
|
|
27496
|
-
let config2 = await
|
|
27454
|
+
let config2 = await loadConfig2(cwd);
|
|
27497
27455
|
let seeded = false;
|
|
27498
27456
|
if (!config2) {
|
|
27499
27457
|
config2 = await seedConfig(cwd);
|
|
@@ -27501,7 +27459,7 @@ async function runOg(options) {
|
|
|
27501
27459
|
console.log(source_default.yellow(" ! No og.config.ts \u2014 generating a seed card from Sonor brand data."));
|
|
27502
27460
|
console.log(source_default.gray(" The site owns its theme: add og.config.ts (defineOgCard) with the real palette."));
|
|
27503
27461
|
}
|
|
27504
|
-
const outPath =
|
|
27462
|
+
const outPath = path12.resolve(cwd, options.out || "public/og.png");
|
|
27505
27463
|
let clean = true;
|
|
27506
27464
|
let cardKeyFix = null;
|
|
27507
27465
|
let pageCardsWritten = 0;
|
|
@@ -27511,8 +27469,8 @@ async function runOg(options) {
|
|
|
27511
27469
|
const report = await renderCard(config2, outPath, cwd, chrome, "site");
|
|
27512
27470
|
spinner.stop();
|
|
27513
27471
|
console.log(source_default.bold(` Site card${seeded ? source_default.gray(" (seed)") : ""}`));
|
|
27514
|
-
clean = reportCard(`${
|
|
27515
|
-
checks.push(cardCheck("site card",
|
|
27472
|
+
clean = reportCard(`${path12.relative(cwd, outPath)} \u2014 1200x630`, report) && clean;
|
|
27473
|
+
checks.push(cardCheck("site card", path12.relative(cwd, outPath), report));
|
|
27516
27474
|
} catch (err) {
|
|
27517
27475
|
const message = err instanceof Error ? err.message.split("\n")[0] : String(err);
|
|
27518
27476
|
spinner.fail(`Render failed: ${message}`);
|
|
@@ -27571,20 +27529,30 @@ async function runOg(options) {
|
|
|
27571
27529
|
});
|
|
27572
27530
|
cardKeyFix = CARD_KEY_FIX;
|
|
27573
27531
|
}
|
|
27574
|
-
const
|
|
27532
|
+
const placed = targets.map((route) => ({ ...route, dir: route.dir ?? routeOutputDir(appDir, route.path) }));
|
|
27533
|
+
const toRender = placed.filter((route) => !codeOgImageFile(route.dir));
|
|
27534
|
+
for (const route of placed.filter((r) => codeOgImageFile(r.dir))) {
|
|
27535
|
+
for (const ext2 of ["png", "jpg", "jpeg"]) {
|
|
27536
|
+
await fs3.rm(path12.join(route.dir, `opengraph-image.${ext2}`), { force: true });
|
|
27537
|
+
}
|
|
27538
|
+
const file = path12.relative(cwd, codeOgImageFile(route.dir));
|
|
27539
|
+
console.log(source_default.gray(` \u21B7 ${route.path} keeps its own ${file}`));
|
|
27540
|
+
checks.push({ id: "og.code-card", title: route.path, level: "ok", message: `Code-based card kept: ${file}` });
|
|
27541
|
+
}
|
|
27542
|
+
const reports = await pooled(toRender, RENDER_CONCURRENCY, async (route, i) => {
|
|
27575
27543
|
const pageConfig = pageCardConfig(config2, route, brand);
|
|
27576
|
-
const dir = route.dir
|
|
27544
|
+
const dir = route.dir;
|
|
27577
27545
|
for (const ext2 of ["png", "jpg", "jpeg"]) {
|
|
27578
|
-
await fs3.rm(
|
|
27546
|
+
await fs3.rm(path12.join(dir, `opengraph-image.${ext2}`), { force: true });
|
|
27579
27547
|
}
|
|
27580
|
-
const png =
|
|
27548
|
+
const png = path12.join(dir, "opengraph-image.png");
|
|
27581
27549
|
const report = await renderCard(pageConfig, png, cwd, chrome, `page-${i}`);
|
|
27582
27550
|
const file = await compressCard(png, cwd);
|
|
27583
27551
|
return { route, file, report };
|
|
27584
27552
|
});
|
|
27585
27553
|
for (const { route, file, report } of reports) {
|
|
27586
|
-
clean = reportCard(`${route.path} ${source_default.gray(
|
|
27587
|
-
checks.push(cardCheck(route.path,
|
|
27554
|
+
clean = reportCard(`${route.path} ${source_default.gray(path12.relative(cwd, file))}`, report) && clean;
|
|
27555
|
+
checks.push(cardCheck(route.path, path12.relative(cwd, file), report));
|
|
27588
27556
|
}
|
|
27589
27557
|
pageCardsWritten = reports.length;
|
|
27590
27558
|
const bytes = await totalBytes(reports.map((r) => r.file));
|
|
@@ -27595,13 +27563,13 @@ async function runOg(options) {
|
|
|
27595
27563
|
}
|
|
27596
27564
|
if (options.preview !== false) {
|
|
27597
27565
|
try {
|
|
27598
|
-
const require_ = (await import('module')).createRequire(
|
|
27566
|
+
const require_ = (await import('module')).createRequire(path12.join(cwd, "package.json"));
|
|
27599
27567
|
const sharp = require_("sharp");
|
|
27600
|
-
const previewPath =
|
|
27601
|
-
await fs3.mkdir(
|
|
27568
|
+
const previewPath = path12.join(cwd, ".sonor", "og-preview.png");
|
|
27569
|
+
await fs3.mkdir(path12.dirname(previewPath), { recursive: true });
|
|
27602
27570
|
await sharp(outPath).resize(300).toFile(previewPath);
|
|
27603
27571
|
console.log("");
|
|
27604
|
-
console.log(source_default.gray(` Thumbnail check: ${
|
|
27572
|
+
console.log(source_default.gray(` Thumbnail check: ${path12.relative(cwd, previewPath)} \u2014 if text is mush there, fix the card.`));
|
|
27605
27573
|
} catch {
|
|
27606
27574
|
console.log(source_default.gray(" (sharp not resolvable \u2014 skipped the 300px preview)"));
|
|
27607
27575
|
}
|
|
@@ -27660,15 +27628,15 @@ function routeOutputDir(appDir, urlPath) {
|
|
|
27660
27628
|
const segments = urlPath.split("/").filter(Boolean);
|
|
27661
27629
|
let dir = appDir;
|
|
27662
27630
|
for (const segment of segments) {
|
|
27663
|
-
const direct =
|
|
27631
|
+
const direct = path12.join(dir, segment);
|
|
27664
27632
|
if (existsSync(direct)) {
|
|
27665
27633
|
dir = direct;
|
|
27666
27634
|
continue;
|
|
27667
27635
|
}
|
|
27668
27636
|
const group = existsSync(dir) ? readdirSync(dir, { withFileTypes: true }).find(
|
|
27669
|
-
(e) => e.isDirectory() && e.name.startsWith("(") && e.name.endsWith(")") && existsSync(
|
|
27637
|
+
(e) => e.isDirectory() && e.name.startsWith("(") && e.name.endsWith(")") && existsSync(path12.join(dir, e.name, segment))
|
|
27670
27638
|
) : void 0;
|
|
27671
|
-
dir = group ?
|
|
27639
|
+
dir = group ? path12.join(dir, group.name, segment) : direct;
|
|
27672
27640
|
}
|
|
27673
27641
|
return dir;
|
|
27674
27642
|
}
|
|
@@ -27683,7 +27651,7 @@ async function totalBytes(files) {
|
|
|
27683
27651
|
return total;
|
|
27684
27652
|
}
|
|
27685
27653
|
async function siteDomain(cwd) {
|
|
27686
|
-
const envFile =
|
|
27654
|
+
const envFile = path12.join(cwd, ".env.local");
|
|
27687
27655
|
if (existsSync(envFile)) {
|
|
27688
27656
|
const env3 = await fs3.readFile(envFile, "utf-8").catch(() => "");
|
|
27689
27657
|
const url = env3.match(/^NEXT_PUBLIC_SITE_URL=(.+)$/m)?.[1]?.trim();
|
|
@@ -27808,14 +27776,14 @@ var hs = new RegExp(pe, "g");
|
|
|
27808
27776
|
var as = /\\\\/g;
|
|
27809
27777
|
var ls = /\\{/g;
|
|
27810
27778
|
var cs = /\\}/g;
|
|
27811
|
-
var
|
|
27779
|
+
var fs22 = /\\,/g;
|
|
27812
27780
|
var us = /\\./g;
|
|
27813
27781
|
var ds = 1e5;
|
|
27814
27782
|
function Ht(n5) {
|
|
27815
27783
|
return isNaN(n5) ? n5.charCodeAt(0) : parseInt(n5, 10);
|
|
27816
27784
|
}
|
|
27817
27785
|
function ps(n5) {
|
|
27818
|
-
return n5.replace(as, fe).replace(ls, ue).replace(cs, qt).replace(
|
|
27786
|
+
return n5.replace(as, fe).replace(ls, ue).replace(cs, qt).replace(fs22, de).replace(us, pe);
|
|
27819
27787
|
}
|
|
27820
27788
|
function ms(n5) {
|
|
27821
27789
|
return n5.replace(is, "\\").replace(rs, "{").replace(ns, "}").replace(os5, ",").replace(hs, ".");
|
|
@@ -30847,10 +30815,10 @@ function unifiedDiff(before, after, filePath, context = 2) {
|
|
|
30847
30815
|
return lines.join("\n");
|
|
30848
30816
|
}
|
|
30849
30817
|
function ext(filePath) {
|
|
30850
|
-
return
|
|
30818
|
+
return path12.extname(filePath).toLowerCase();
|
|
30851
30819
|
}
|
|
30852
30820
|
function basename(filePath) {
|
|
30853
|
-
return
|
|
30821
|
+
return path12.basename(filePath).toLowerCase();
|
|
30854
30822
|
}
|
|
30855
30823
|
var CODE_EXT = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
30856
30824
|
var TEXT_EXT = /* @__PURE__ */ new Set([...CODE_EXT, ".css", ".scss", ".json", ".md", ".mdx"]);
|
|
@@ -31004,7 +30972,7 @@ var IGNORE = [
|
|
|
31004
30972
|
];
|
|
31005
30973
|
async function listFiles(cwd, onlyPath) {
|
|
31006
30974
|
if (onlyPath) {
|
|
31007
|
-
const rel =
|
|
30975
|
+
const rel = path12.isAbsolute(onlyPath) ? path12.relative(cwd, onlyPath) : onlyPath;
|
|
31008
30976
|
return [rel];
|
|
31009
30977
|
}
|
|
31010
30978
|
const matches = await Ze(SCAN_PATTERNS, { cwd, ignore: IGNORE, dot: true, nodir: true });
|
|
@@ -31016,7 +30984,7 @@ async function runCodemod(options) {
|
|
|
31016
30984
|
const files = await listFiles(cwd, onlyPath);
|
|
31017
30985
|
const changes = [];
|
|
31018
30986
|
for (const rel of files) {
|
|
31019
|
-
const full =
|
|
30987
|
+
const full = path12.join(cwd, rel);
|
|
31020
30988
|
let source;
|
|
31021
30989
|
try {
|
|
31022
30990
|
source = await fs3.readFile(full, "utf-8");
|
|
@@ -31165,9 +31133,9 @@ function findManifestPath() {
|
|
|
31165
31133
|
const baseDir = typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
31166
31134
|
let dir = baseDir;
|
|
31167
31135
|
for (let i = 0; i < 8; i++) {
|
|
31168
|
-
const candidate =
|
|
31136
|
+
const candidate = path12.join(dir, "agent-manifest.json");
|
|
31169
31137
|
if (fs__default.existsSync(candidate)) return candidate;
|
|
31170
|
-
const parent =
|
|
31138
|
+
const parent = path12.dirname(dir);
|
|
31171
31139
|
if (parent === dir) break;
|
|
31172
31140
|
dir = parent;
|
|
31173
31141
|
}
|
|
@@ -31246,7 +31214,7 @@ async function syncCommand2(options) {
|
|
|
31246
31214
|
}
|
|
31247
31215
|
async function syncPagesToPortal(apiUrl, apiKey, dryRun) {
|
|
31248
31216
|
const spinner = ora("Discovering pages...").start();
|
|
31249
|
-
const appDir =
|
|
31217
|
+
const appDir = findAppDirForDiscovery();
|
|
31250
31218
|
if (!appDir) {
|
|
31251
31219
|
spinner.fail("Could not find app directory");
|
|
31252
31220
|
return;
|
|
@@ -31307,20 +31275,8 @@ async function syncPagesToPortal(apiUrl, apiKey, dryRun) {
|
|
|
31307
31275
|
syncSpinner.fail(`Sync failed: ${error2.message}`);
|
|
31308
31276
|
}
|
|
31309
31277
|
}
|
|
31310
|
-
function findAppDir() {
|
|
31311
|
-
const candidates = [
|
|
31312
|
-
path10.join(process.cwd(), "app"),
|
|
31313
|
-
path10.join(process.cwd(), "src", "app")
|
|
31314
|
-
];
|
|
31315
|
-
for (const candidate of candidates) {
|
|
31316
|
-
if (existsSync(candidate)) {
|
|
31317
|
-
return candidate;
|
|
31318
|
-
}
|
|
31319
|
-
}
|
|
31320
|
-
return null;
|
|
31321
|
-
}
|
|
31322
31278
|
function discoverPages(appDir, currentPath = "", pages = []) {
|
|
31323
|
-
const fullPath =
|
|
31279
|
+
const fullPath = path12.join(appDir, currentPath);
|
|
31324
31280
|
if (!existsSync(fullPath)) {
|
|
31325
31281
|
return pages;
|
|
31326
31282
|
}
|
|
@@ -31342,7 +31298,7 @@ function discoverPages(appDir, currentPath = "", pages = []) {
|
|
|
31342
31298
|
});
|
|
31343
31299
|
}
|
|
31344
31300
|
for (const entry of entries) {
|
|
31345
|
-
const entryPath =
|
|
31301
|
+
const entryPath = path12.join(fullPath, entry);
|
|
31346
31302
|
const stat = statSync(entryPath);
|
|
31347
31303
|
if (stat.isDirectory()) {
|
|
31348
31304
|
const folderName = entry.toLowerCase();
|
|
@@ -31355,21 +31311,21 @@ function discoverPages(appDir, currentPath = "", pages = []) {
|
|
|
31355
31311
|
if (entry.startsWith("_")) {
|
|
31356
31312
|
continue;
|
|
31357
31313
|
}
|
|
31358
|
-
discoverPages(appDir,
|
|
31314
|
+
discoverPages(appDir, path12.join(currentPath, entry), pages);
|
|
31359
31315
|
}
|
|
31360
31316
|
}
|
|
31361
31317
|
return pages;
|
|
31362
31318
|
}
|
|
31363
31319
|
function findNextBuildDir() {
|
|
31364
31320
|
const cwd = process.cwd();
|
|
31365
|
-
const candidate =
|
|
31321
|
+
const candidate = path12.join(cwd, ".next", "server", "app");
|
|
31366
31322
|
return existsSync(candidate) ? candidate : null;
|
|
31367
31323
|
}
|
|
31368
31324
|
function extractPageContent(buildDir, pagePath) {
|
|
31369
31325
|
const baseName = pagePath === "/" ? "index" : pagePath.replace(/^\//, "");
|
|
31370
31326
|
const htmlCandidates = [
|
|
31371
|
-
|
|
31372
|
-
|
|
31327
|
+
path12.join(buildDir, `${baseName}.html`),
|
|
31328
|
+
path12.join(buildDir, baseName, "index.html")
|
|
31373
31329
|
];
|
|
31374
31330
|
let html = null;
|
|
31375
31331
|
for (const candidate of htmlCandidates) {
|
|
@@ -31383,8 +31339,8 @@ function extractPageContent(buildDir, pagePath) {
|
|
|
31383
31339
|
}
|
|
31384
31340
|
}
|
|
31385
31341
|
const rscCandidates = [
|
|
31386
|
-
|
|
31387
|
-
|
|
31342
|
+
path12.join(buildDir, `${baseName}.rsc`),
|
|
31343
|
+
path12.join(buildDir, baseName, "index.rsc")
|
|
31388
31344
|
];
|
|
31389
31345
|
let rsc = null;
|
|
31390
31346
|
for (const candidate of rscCandidates) {
|
|
@@ -31495,7 +31451,7 @@ var BLOG_EXTENSIONS = [".mdx", ".md"];
|
|
|
31495
31451
|
function findBlogDir() {
|
|
31496
31452
|
const cwd = process.cwd();
|
|
31497
31453
|
for (const dir of BLOG_DIRS) {
|
|
31498
|
-
const full =
|
|
31454
|
+
const full = path12.join(cwd, dir);
|
|
31499
31455
|
if (existsSync(full)) return full;
|
|
31500
31456
|
}
|
|
31501
31457
|
return null;
|
|
@@ -31505,7 +31461,7 @@ async function discoverBlogPosts(dir) {
|
|
|
31505
31461
|
async function walk(currentDir) {
|
|
31506
31462
|
const entries = readdirSync(currentDir);
|
|
31507
31463
|
for (const entry of entries) {
|
|
31508
|
-
const fullPath =
|
|
31464
|
+
const fullPath = path12.join(currentDir, entry);
|
|
31509
31465
|
const stat = statSync(fullPath);
|
|
31510
31466
|
if (stat.isDirectory()) {
|
|
31511
31467
|
await walk(fullPath);
|
|
@@ -31522,7 +31478,7 @@ async function discoverBlogPosts(dir) {
|
|
|
31522
31478
|
date: frontmatter.date,
|
|
31523
31479
|
tags: frontmatter.tags,
|
|
31524
31480
|
author: frontmatter.author,
|
|
31525
|
-
filePath:
|
|
31481
|
+
filePath: path12.relative(process.cwd(), fullPath)
|
|
31526
31482
|
});
|
|
31527
31483
|
}
|
|
31528
31484
|
}
|
|
@@ -31555,7 +31511,7 @@ async function syncBlogToPortal(_apiUrl, _apiKey, _dryRun) {
|
|
|
31555
31511
|
}
|
|
31556
31512
|
const spinner = ora("Discovering blog posts...").start();
|
|
31557
31513
|
const posts = await discoverBlogPosts(blogDir);
|
|
31558
|
-
spinner.succeed(`Found ${posts.length} local markdown post(s) in ${
|
|
31514
|
+
spinner.succeed(`Found ${posts.length} local markdown post(s) in ${path12.relative(process.cwd(), blogDir)}`);
|
|
31559
31515
|
if (posts.length === 0) return;
|
|
31560
31516
|
for (const post of posts.slice(0, 10)) {
|
|
31561
31517
|
console.log(source_default.gray(` ${post.slug}: ${post.title || "(no title)"}`));
|
|
@@ -31572,11 +31528,11 @@ async function discoverSchemaUsage(appDir) {
|
|
|
31572
31528
|
async function walk(currentDir, currentPath = "") {
|
|
31573
31529
|
const entries = readdirSync(currentDir);
|
|
31574
31530
|
for (const entry of entries) {
|
|
31575
|
-
const fullPath =
|
|
31531
|
+
const fullPath = path12.join(currentDir, entry);
|
|
31576
31532
|
const stat = statSync(fullPath);
|
|
31577
31533
|
if (stat.isDirectory()) {
|
|
31578
31534
|
if (entry.startsWith(".") || entry === "node_modules") continue;
|
|
31579
|
-
await walk(fullPath,
|
|
31535
|
+
await walk(fullPath, path12.join(currentPath, entry));
|
|
31580
31536
|
continue;
|
|
31581
31537
|
}
|
|
31582
31538
|
if (!/\.(tsx?|jsx?)$/.test(entry)) continue;
|
|
@@ -31590,7 +31546,7 @@ async function discoverSchemaUsage(appDir) {
|
|
|
31590
31546
|
pagePath: pathMatch[1],
|
|
31591
31547
|
schemaTypes: ["managed"],
|
|
31592
31548
|
source: "ManagedSchema",
|
|
31593
|
-
filePath:
|
|
31549
|
+
filePath: path12.relative(process.cwd(), fullPath)
|
|
31594
31550
|
});
|
|
31595
31551
|
}
|
|
31596
31552
|
}
|
|
@@ -31608,7 +31564,7 @@ async function discoverSchemaUsage(appDir) {
|
|
|
31608
31564
|
pagePath,
|
|
31609
31565
|
schemaTypes: [...new Set(types)],
|
|
31610
31566
|
source: "json-ld",
|
|
31611
|
-
filePath:
|
|
31567
|
+
filePath: path12.relative(process.cwd(), fullPath)
|
|
31612
31568
|
});
|
|
31613
31569
|
}
|
|
31614
31570
|
}
|
|
@@ -31618,7 +31574,7 @@ async function discoverSchemaUsage(appDir) {
|
|
|
31618
31574
|
return usages;
|
|
31619
31575
|
}
|
|
31620
31576
|
async function syncSchemasToPortal(apiUrl, apiKey, dryRun) {
|
|
31621
|
-
const appDir =
|
|
31577
|
+
const appDir = findAppDirForDiscovery();
|
|
31622
31578
|
if (!appDir) {
|
|
31623
31579
|
console.log(source_default.gray(" No app directory found"));
|
|
31624
31580
|
return;
|
|
@@ -31661,15 +31617,15 @@ async function apiRoutesCommand(options) {
|
|
|
31661
31617
|
console.log("");
|
|
31662
31618
|
console.log(source_default.bold(" Site-Kit API Routes"));
|
|
31663
31619
|
console.log("");
|
|
31664
|
-
const appDir =
|
|
31620
|
+
const appDir = findAppDirForDiscovery();
|
|
31665
31621
|
if (!appDir) {
|
|
31666
31622
|
console.log(source_default.red(" \u2717 Could not find app directory"));
|
|
31667
31623
|
console.log(source_default.gray(" Make sure you are in a Next.js project with an app directory"));
|
|
31668
31624
|
console.log("");
|
|
31669
31625
|
process.exit(1);
|
|
31670
31626
|
}
|
|
31671
|
-
const routeDir =
|
|
31672
|
-
const routeFile =
|
|
31627
|
+
const routeDir = path12.join(appDir, "_uptrade", "api", "[...path]");
|
|
31628
|
+
const routeFile = path12.join(routeDir, "route.ts");
|
|
31673
31629
|
if (existsSync(routeFile) && !options.force) {
|
|
31674
31630
|
console.log(source_default.yellow(" \u26A0 API routes already exist"));
|
|
31675
31631
|
console.log(source_default.gray(` ${routeFile}`));
|
|
@@ -31704,18 +31660,6 @@ async function apiRoutesCommand(options) {
|
|
|
31704
31660
|
spinner.fail(`Failed to create API routes: ${error2.message}`);
|
|
31705
31661
|
}
|
|
31706
31662
|
}
|
|
31707
|
-
function findAppDir2() {
|
|
31708
|
-
const candidates = [
|
|
31709
|
-
path10.join(process.cwd(), "app"),
|
|
31710
|
-
path10.join(process.cwd(), "src", "app")
|
|
31711
|
-
];
|
|
31712
|
-
for (const candidate of candidates) {
|
|
31713
|
-
if (existsSync(candidate)) {
|
|
31714
|
-
return candidate;
|
|
31715
|
-
}
|
|
31716
|
-
}
|
|
31717
|
-
return null;
|
|
31718
|
-
}
|
|
31719
31663
|
function generateRouteHandler() {
|
|
31720
31664
|
return `/**
|
|
31721
31665
|
* Sonor API Proxy
|
|
@@ -31820,12 +31764,12 @@ async function handleRequest(
|
|
|
31820
31764
|
`;
|
|
31821
31765
|
}
|
|
31822
31766
|
function detectPackageManager(cwd) {
|
|
31823
|
-
if (existsSync(
|
|
31824
|
-
if (existsSync(
|
|
31767
|
+
if (existsSync(path12.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
31768
|
+
if (existsSync(path12.join(cwd, "yarn.lock"))) return "yarn";
|
|
31825
31769
|
return "npm";
|
|
31826
31770
|
}
|
|
31827
31771
|
async function run6(ctx, options) {
|
|
31828
|
-
if (!existsSync(
|
|
31772
|
+
if (!existsSync(path12.join(ctx.cwd, "package.json"))) {
|
|
31829
31773
|
throw new UsageError(
|
|
31830
31774
|
"NO_PACKAGE_JSON",
|
|
31831
31775
|
"No package.json found",
|
|
@@ -31870,12 +31814,12 @@ async function installCommand(options) {
|
|
|
31870
31814
|
await runCommand(ctx, (c) => run6(c, options), renderHuman4);
|
|
31871
31815
|
}
|
|
31872
31816
|
function detectPackageManager2(cwd) {
|
|
31873
|
-
if (existsSync(
|
|
31874
|
-
if (existsSync(
|
|
31817
|
+
if (existsSync(path12.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
31818
|
+
if (existsSync(path12.join(cwd, "yarn.lock"))) return "yarn";
|
|
31875
31819
|
return "npm";
|
|
31876
31820
|
}
|
|
31877
31821
|
async function run7(ctx, options) {
|
|
31878
|
-
const pkgPath =
|
|
31822
|
+
const pkgPath = path12.join(ctx.cwd, "package.json");
|
|
31879
31823
|
if (!existsSync(pkgPath)) {
|
|
31880
31824
|
throw new UsageError("NO_PACKAGE_JSON", "No package.json found", "Run this from your project root.");
|
|
31881
31825
|
}
|
|
@@ -31930,21 +31874,21 @@ async function scaffoldCommand(options) {
|
|
|
31930
31874
|
);
|
|
31931
31875
|
console.log("");
|
|
31932
31876
|
const cwd = process.cwd();
|
|
31933
|
-
const appDir =
|
|
31877
|
+
const appDir = findAppDirForDiscovery(cwd);
|
|
31934
31878
|
if (!appDir) {
|
|
31935
31879
|
console.log(source_default.red(" \u2717 No app directory found (app/ or src/app/)"));
|
|
31936
31880
|
process.exit(1);
|
|
31937
31881
|
}
|
|
31938
31882
|
const files = [
|
|
31939
31883
|
{
|
|
31940
|
-
path:
|
|
31884
|
+
path: path12.join(appDir, "sitemap.ts"),
|
|
31941
31885
|
label: "Sitemap",
|
|
31942
31886
|
content: `import { createSitemap } from '@sonordev/site-kit/sitemap'
|
|
31943
31887
|
|
|
31944
31888
|
export default createSitemap({
|
|
31945
31889
|
// baseUrl auto-resolved from Portal via API key
|
|
31946
|
-
|
|
31947
|
-
|
|
31890
|
+
// llms.txt stays out of the sitemap on purpose: it's a plain-text duplicate
|
|
31891
|
+
// of these pages, and AI crawlers find it at /llms.txt anyway.
|
|
31948
31892
|
// optimizedLLMsTxt: true, // optional: static build writes optimized llms (CI)
|
|
31949
31893
|
// llmsPublicSummaryOnly: true, // optional: page list from Portal public summaries only
|
|
31950
31894
|
// additionalPaths: async () => [...],
|
|
@@ -31952,7 +31896,7 @@ export default createSitemap({
|
|
|
31952
31896
|
`
|
|
31953
31897
|
},
|
|
31954
31898
|
{
|
|
31955
|
-
path:
|
|
31899
|
+
path: path12.join(appDir, "robots.txt", "route.ts"),
|
|
31956
31900
|
label: "Robots.txt",
|
|
31957
31901
|
content: `import { createRobots } from '@sonordev/site-kit/robots'
|
|
31958
31902
|
|
|
@@ -31960,7 +31904,7 @@ export const GET = createRobots({})
|
|
|
31960
31904
|
`
|
|
31961
31905
|
},
|
|
31962
31906
|
{
|
|
31963
|
-
path:
|
|
31907
|
+
path: path12.join(appDir, "llms.txt", "route.ts"),
|
|
31964
31908
|
label: "llms.txt",
|
|
31965
31909
|
content: `import { createLLMsTxtHandler } from '@sonordev/site-kit/llms'
|
|
31966
31910
|
|
|
@@ -31968,7 +31912,7 @@ export const GET = createLLMsTxtHandler({ preferStatic: true })
|
|
|
31968
31912
|
`
|
|
31969
31913
|
},
|
|
31970
31914
|
{
|
|
31971
|
-
path:
|
|
31915
|
+
path: path12.join(appDir, "llms-full.txt", "route.ts"),
|
|
31972
31916
|
label: "llms-full.txt",
|
|
31973
31917
|
content: `import { createLLMsFullTxtHandler } from '@sonordev/site-kit/llms'
|
|
31974
31918
|
|
|
@@ -31979,14 +31923,14 @@ export const GET = createLLMsFullTxtHandler({ preferStatic: true })
|
|
|
31979
31923
|
if (!options.minimal) {
|
|
31980
31924
|
files.push(
|
|
31981
31925
|
{
|
|
31982
|
-
path:
|
|
31983
|
-
label: "Proxy (security headers
|
|
31926
|
+
path: path12.join(cwd, "proxy.ts"),
|
|
31927
|
+
label: "Proxy (security headers, managed redirects)",
|
|
31984
31928
|
content: `import { createProxy } from '@sonordev/site-kit/proxy'
|
|
31985
31929
|
|
|
31986
|
-
// redirects
|
|
31987
|
-
//
|
|
31988
|
-
//
|
|
31989
|
-
export default createProxy({ redirects:
|
|
31930
|
+
// Sonor-managed redirects apply here. The rule list is cached in memory for
|
|
31931
|
+
// five minutes, so page loads rarely wait on it. Don't move them into
|
|
31932
|
+
// app/not-found.tsx: reading request headers there makes every page dynamic.
|
|
31933
|
+
export default createProxy({ redirects: true })
|
|
31990
31934
|
|
|
31991
31935
|
// Inlined on purpose: Next statically parses \`config.matcher\` at build time
|
|
31992
31936
|
// and rejects an imported value (Turbopack build error). Keep in sync with
|
|
@@ -31999,7 +31943,7 @@ export const config = {
|
|
|
31999
31943
|
`
|
|
32000
31944
|
},
|
|
32001
31945
|
{
|
|
32002
|
-
path:
|
|
31946
|
+
path: path12.join(appDir, "manifest.webmanifest", "route.ts"),
|
|
32003
31947
|
label: "PWA Manifest",
|
|
32004
31948
|
content: `import { createManifest } from '@sonordev/site-kit/manifest'
|
|
32005
31949
|
|
|
@@ -32007,19 +31951,12 @@ export const GET = createManifest()
|
|
|
32007
31951
|
`
|
|
32008
31952
|
},
|
|
32009
31953
|
{
|
|
32010
|
-
path:
|
|
32011
|
-
label: "404 Page
|
|
32012
|
-
content:
|
|
32013
|
-
|
|
32014
|
-
|
|
32015
|
-
export default
|
|
32016
|
-
// Sonor-managed redirects resolve here, at the only place they can matter:
|
|
32017
|
-
// a URL that would otherwise 404. Successful page loads pay nothing.
|
|
32018
|
-
const managed = await resolveManagedRedirect()
|
|
32019
|
-
if (managed) {
|
|
32020
|
-
;(managed.permanent ? permanentRedirect : redirect)(managed.destination)
|
|
32021
|
-
}
|
|
32022
|
-
|
|
31954
|
+
path: path12.join(appDir, "not-found.tsx"),
|
|
31955
|
+
label: "404 Page",
|
|
31956
|
+
content: `// Keep this component free of request APIs (headers, cookies). Next
|
|
31957
|
+
// renders the root 404 inside every page, so one headers() call here makes
|
|
31958
|
+
// the whole site dynamic. Managed redirects run in proxy.ts instead.
|
|
31959
|
+
export default function NotFound() {
|
|
32023
31960
|
return (
|
|
32024
31961
|
<div style={{ textAlign: 'center', padding: '4rem 1rem' }}>
|
|
32025
31962
|
<h1 style={{ fontSize: '3rem', fontWeight: 700, marginBottom: '0.5rem' }}>404</h1>
|
|
@@ -32047,7 +31984,7 @@ export default async function NotFound() {
|
|
|
32047
31984
|
`
|
|
32048
31985
|
},
|
|
32049
31986
|
{
|
|
32050
|
-
path:
|
|
31987
|
+
path: path12.join(appDir, "error.tsx"),
|
|
32051
31988
|
label: "Error Boundary",
|
|
32052
31989
|
content: `'use client'
|
|
32053
31990
|
|
|
@@ -32087,7 +32024,7 @@ export default function Error({
|
|
|
32087
32024
|
`
|
|
32088
32025
|
},
|
|
32089
32026
|
{
|
|
32090
|
-
path:
|
|
32027
|
+
path: path12.join(cwd, "og.config.ts"),
|
|
32091
32028
|
label: "OG card config (run: sonor-setup og)",
|
|
32092
32029
|
content: `import { defineOgCard } from '@sonordev/site-kit/og'
|
|
32093
32030
|
|
|
@@ -32116,7 +32053,7 @@ export default defineOgCard({
|
|
|
32116
32053
|
// .env.local, not .env.example: one real env file per project. The
|
|
32117
32054
|
// deployer copies these values into the host's env settings. Skipped
|
|
32118
32055
|
// when the file already exists, so real keys are never touched.
|
|
32119
|
-
path:
|
|
32056
|
+
path: path12.join(cwd, ".env.local"),
|
|
32120
32057
|
label: ".env.local",
|
|
32121
32058
|
content: `# ===================================
|
|
32122
32059
|
# @sonordev/site-kit \u2014 Environment Variables
|
|
@@ -32138,10 +32075,10 @@ SONOR_API_KEY=sonor_your-project-uuid_your-secret-key
|
|
|
32138
32075
|
if (options.dryRun) {
|
|
32139
32076
|
console.log(source_default.yellow(" [DRY RUN] Would create:"));
|
|
32140
32077
|
for (const f of files) {
|
|
32141
|
-
const rel =
|
|
32142
|
-
const
|
|
32078
|
+
const rel = path12.relative(cwd, f.path);
|
|
32079
|
+
const exists2 = existsSync(f.path);
|
|
32143
32080
|
console.log(
|
|
32144
|
-
source_default.gray(` ${rel}`) + (
|
|
32081
|
+
source_default.gray(` ${rel}`) + (exists2 ? source_default.yellow(" (exists, would skip)") : "")
|
|
32145
32082
|
);
|
|
32146
32083
|
}
|
|
32147
32084
|
console.log("");
|
|
@@ -32153,13 +32090,13 @@ SONOR_API_KEY=sonor_your-project-uuid_your-secret-key
|
|
|
32153
32090
|
for (const f of files) {
|
|
32154
32091
|
try {
|
|
32155
32092
|
if (existsSync(f.path) && !options.force) {
|
|
32156
|
-
spinner.warn(`Skipped (exists): ${
|
|
32093
|
+
spinner.warn(`Skipped (exists): ${path12.relative(cwd, f.path)}`);
|
|
32157
32094
|
skipped++;
|
|
32158
32095
|
continue;
|
|
32159
32096
|
}
|
|
32160
|
-
await fs3.mkdir(
|
|
32097
|
+
await fs3.mkdir(path12.dirname(f.path), { recursive: true });
|
|
32161
32098
|
await fs3.writeFile(f.path, f.content, "utf-8");
|
|
32162
|
-
spinner.succeed(`${f.label}: ${
|
|
32099
|
+
spinner.succeed(`${f.label}: ${path12.relative(cwd, f.path)}`);
|
|
32163
32100
|
created++;
|
|
32164
32101
|
} catch (err) {
|
|
32165
32102
|
spinner.fail(`Failed: ${f.path}`);
|
|
@@ -32205,17 +32142,209 @@ SONOR_API_KEY=sonor_your-project-uuid_your-secret-key
|
|
|
32205
32142
|
console.log("");
|
|
32206
32143
|
}
|
|
32207
32144
|
}
|
|
32208
|
-
|
|
32209
|
-
|
|
32210
|
-
|
|
32211
|
-
|
|
32212
|
-
|
|
32213
|
-
|
|
32214
|
-
|
|
32215
|
-
|
|
32145
|
+
var LLMS_FILES = [
|
|
32146
|
+
{ path: "/llms.txt", handler: "createLLMsTxtHandler" },
|
|
32147
|
+
{ path: "/llms-full.txt", handler: "createLLMsFullTxtHandler" }
|
|
32148
|
+
];
|
|
32149
|
+
var NEXT_CONFIGS = ["next.config.ts", "next.config.mts", "next.config.mjs", "next.config.js", "next.config.cjs"];
|
|
32150
|
+
function read(cwd, rel) {
|
|
32151
|
+
try {
|
|
32152
|
+
return fs__default.readFileSync(path12.join(cwd, rel), "utf-8");
|
|
32153
|
+
} catch {
|
|
32154
|
+
return "";
|
|
32155
|
+
}
|
|
32156
|
+
}
|
|
32157
|
+
function exists(cwd, rel) {
|
|
32158
|
+
try {
|
|
32159
|
+
return fs__default.existsSync(path12.join(cwd, rel));
|
|
32160
|
+
} catch {
|
|
32161
|
+
return false;
|
|
32162
|
+
}
|
|
32163
|
+
}
|
|
32164
|
+
function patternMatches(pattern, urlPath) {
|
|
32165
|
+
const re2 = pattern.trim().split(/\(\.\*\)|:\w+\*|\*/).map((part) => part.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join(".*");
|
|
32166
|
+
return new RegExp(`^${re2}$`).test(urlPath);
|
|
32167
|
+
}
|
|
32168
|
+
var NOINDEX = /noindex/i;
|
|
32169
|
+
function netlifyTomlNoindex(toml, urlPath) {
|
|
32170
|
+
const blocks = [];
|
|
32171
|
+
for (const line of toml.split("\n")) {
|
|
32172
|
+
const header = line.match(/^\s*\[\[?\s*([^\]]+?)\s*\]\]?\s*$/);
|
|
32173
|
+
if (header && header[1] !== "headers.values") blocks.push(line);
|
|
32174
|
+
else if (blocks.length) blocks[blocks.length - 1] += `
|
|
32175
|
+
${line}`;
|
|
32176
|
+
}
|
|
32177
|
+
return blocks.some((block) => {
|
|
32178
|
+
if (!/^\s*\[\[\s*headers\s*\]\]/.test(block)) return false;
|
|
32179
|
+
const pattern = block.match(/^\s*for\s*=\s*["']([^"']+)["']/m)?.[1];
|
|
32180
|
+
const value = block.match(/^\s*["']?X-Robots-Tag["']?\s*=\s*["']([^"']*)["']/im)?.[1];
|
|
32181
|
+
return !!pattern && !!value && NOINDEX.test(value) && patternMatches(pattern, urlPath);
|
|
32182
|
+
});
|
|
32183
|
+
}
|
|
32184
|
+
function headersFileNoindex(text, urlPath) {
|
|
32185
|
+
let current = null;
|
|
32186
|
+
for (const line of text.split("\n")) {
|
|
32187
|
+
if (!line.trim() || line.trim().startsWith("#")) continue;
|
|
32188
|
+
if (!/^\s/.test(line)) {
|
|
32189
|
+
current = line.trim();
|
|
32190
|
+
continue;
|
|
32191
|
+
}
|
|
32192
|
+
const m = line.match(/^\s+X-Robots-Tag\s*:\s*(.+)$/i);
|
|
32193
|
+
if (current && m && NOINDEX.test(m[1]) && patternMatches(current, urlPath)) return true;
|
|
32194
|
+
}
|
|
32195
|
+
return false;
|
|
32196
|
+
}
|
|
32197
|
+
function vercelJsonNoindex(text, urlPath) {
|
|
32198
|
+
try {
|
|
32199
|
+
const json = JSON.parse(text);
|
|
32200
|
+
return (json.headers ?? []).some(
|
|
32201
|
+
(rule) => !!rule.source && patternMatches(rule.source, urlPath) && (rule.headers ?? []).some((h) => /^x-robots-tag$/i.test(h.key ?? "") && NOINDEX.test(h.value ?? ""))
|
|
32202
|
+
);
|
|
32203
|
+
} catch {
|
|
32204
|
+
return false;
|
|
32205
|
+
}
|
|
32206
|
+
}
|
|
32207
|
+
function findHostNoindex(cwd, urlPath) {
|
|
32208
|
+
const toml = read(cwd, "netlify.toml");
|
|
32209
|
+
if (toml && netlifyTomlNoindex(toml, urlPath)) return "netlify.toml";
|
|
32210
|
+
const headers = read(cwd, "public/_headers");
|
|
32211
|
+
if (headers && headersFileNoindex(headers, urlPath)) return "public/_headers";
|
|
32212
|
+
const vercel = read(cwd, "vercel.json");
|
|
32213
|
+
if (vercel && vercelJsonNoindex(vercel, urlPath)) return "vercel.json";
|
|
32214
|
+
return null;
|
|
32215
|
+
}
|
|
32216
|
+
var LINK_DISCOVERY_LINE = /^.*\bLink\b.*(llms[^\n]*describedby|describedby[^\n]*llms).*$/im;
|
|
32217
|
+
function findDiscoverySource(cwd) {
|
|
32218
|
+
for (const rel of findProxyFiles(cwd)) {
|
|
32219
|
+
const src = read(cwd, rel);
|
|
32220
|
+
const viaFactory = /\bcreate(Proxy|Middleware)\s*\(/.test(src) && /\bllmsDiscovery\b(?!\s*:\s*false\b)/.test(src);
|
|
32221
|
+
if (viaFactory) return `${rel} (createProxy llmsDiscovery)`;
|
|
32222
|
+
if (src.includes("buildAiDiscoveryHeaders")) return `${rel} (buildAiDiscoveryHeaders)`;
|
|
32223
|
+
}
|
|
32224
|
+
for (const rel of NEXT_CONFIGS) {
|
|
32225
|
+
const src = read(cwd, rel);
|
|
32226
|
+
if (!src) continue;
|
|
32227
|
+
if (/\bllmsTxtDiscoveryLink\s*:(?!\s*false\b)/.test(src)) return `${rel} (llmsTxtDiscoveryLink)`;
|
|
32228
|
+
if (src.includes("buildAiDiscoveryHeaders")) return `${rel} (buildAiDiscoveryHeaders)`;
|
|
32229
|
+
break;
|
|
32230
|
+
}
|
|
32231
|
+
const layout = findRootLayout(cwd);
|
|
32232
|
+
if (layout) {
|
|
32233
|
+
const src = read(cwd, path12.relative(cwd, layout));
|
|
32234
|
+
if (src.includes("buildAiDiscoveryHeaders") || src.includes("llmsTxtDiscoveryLink")) {
|
|
32235
|
+
return path12.relative(cwd, layout);
|
|
32236
|
+
}
|
|
32237
|
+
}
|
|
32238
|
+
for (const rel of ["netlify.toml", "public/_headers"]) {
|
|
32239
|
+
if (LINK_DISCOVERY_LINE.test(read(cwd, rel))) return rel;
|
|
32216
32240
|
}
|
|
32217
32241
|
return null;
|
|
32218
32242
|
}
|
|
32243
|
+
function readGeoWiring(cwd) {
|
|
32244
|
+
const appDir = NEXT_APP_DIRS.find((rel) => exists(cwd, rel)) ?? null;
|
|
32245
|
+
const sitemap = findSitemapRoute(cwd);
|
|
32246
|
+
const sitemapSrc = sitemap ? read(cwd, sitemap) : "";
|
|
32247
|
+
const sitemapListsLlms = /\bincludeLlms(Full)?TxtInSitemap\s*:\s*true\b/.test(sitemapSrc) || /['"`/]llms(-full)?\.txt['"`]/.test(sitemapSrc);
|
|
32248
|
+
const sitemapWritesStatic = /\bcreateSitemap\s*\(/.test(sitemapSrc);
|
|
32249
|
+
const writesLlms = sitemapWritesStatic && !/\boptimizedLLMsTxt\s*:\s*false\b/.test(sitemapSrc);
|
|
32250
|
+
const writesLlmsFull = writesLlms && /\boptimizedLLMsFullTxt\s*:\s*true\b/.test(sitemapSrc);
|
|
32251
|
+
const llms = LLMS_FILES.map(({ path: urlPath, handler }) => {
|
|
32252
|
+
const file = urlPath.slice(1);
|
|
32253
|
+
const routeAbs = appDir ? findConventionFile(path12.join(cwd, appDir, file), "route") : null;
|
|
32254
|
+
const route = routeAbs ? path12.relative(cwd, routeAbs) : null;
|
|
32255
|
+
const routeSrc = route ? read(cwd, route) : "";
|
|
32256
|
+
const publicFile = exists(cwd, path12.join("public", file));
|
|
32257
|
+
const built = urlPath === "/llms.txt" ? writesLlms : writesLlmsFull;
|
|
32258
|
+
return {
|
|
32259
|
+
path: urlPath,
|
|
32260
|
+
route,
|
|
32261
|
+
routeUsesKitHandler: routeSrc.includes(handler),
|
|
32262
|
+
routeOptsOutOfNoindex: /\bnoindex\s*:\s*false\b/.test(routeSrc),
|
|
32263
|
+
routeSetsNoindex: /X-Robots-Tag/i.test(routeSrc) && NOINDEX.test(routeSrc),
|
|
32264
|
+
servedStatic: publicFile || built,
|
|
32265
|
+
staticReason: publicFile ? `public/${file}` : built ? `public/${file} (written by createSitemap at build)` : null,
|
|
32266
|
+
hostNoindex: findHostNoindex(cwd, urlPath)
|
|
32267
|
+
};
|
|
32268
|
+
});
|
|
32269
|
+
return { appDir, llms, sitemap, sitemapListsLlms, discovery: findDiscoverySource(cwd) };
|
|
32270
|
+
}
|
|
32271
|
+
var DISCOVERY_FIX = "Add llmsDiscovery to the proxy: createProxy({ llmsDiscovery: { siteUrl } }) in proxy.ts. Or withSiteKitConfig({ llmsTxtDiscoveryLink: true }) in next.config.";
|
|
32272
|
+
var SITEMAP_FIX = "Drop includeLlmsTxtInSitemap / includeLlmsFullTxtInSitemap (and any hand-added /llms*.txt entry) from the sitemap. A sitemap lists indexable HTML pages; AI crawlers find llms.txt at /llms.txt.";
|
|
32273
|
+
function hostNoindexFix(urlPath) {
|
|
32274
|
+
return `The CDN serves it before any route handler runs, so set the header in host config. netlify.toml: [[headers]] for = "${urlPath}" [headers.values] X-Robots-Tag = "noindex"`;
|
|
32275
|
+
}
|
|
32276
|
+
function judgeGeoWiring(facts) {
|
|
32277
|
+
const rows = [];
|
|
32278
|
+
for (const f of facts.llms) {
|
|
32279
|
+
const name = f.path.slice(1);
|
|
32280
|
+
const id = f.path === "/llms.txt" ? "llms" : "llms-full";
|
|
32281
|
+
const served = !!f.route || f.servedStatic;
|
|
32282
|
+
rows.push(
|
|
32283
|
+
served ? { id: `${id}.served`, label: `${name} served`, level: "ok", detail: f.route ?? f.staticReason ?? void 0 } : {
|
|
32284
|
+
id: `${id}.served`,
|
|
32285
|
+
label: `${name} served`,
|
|
32286
|
+
level: "fail",
|
|
32287
|
+
detail: `no ${facts.appDir ?? "app"}/${name}/route.* and no public/${name}`,
|
|
32288
|
+
fix: "Run: sonor-setup geo --ensure-routes"
|
|
32289
|
+
}
|
|
32290
|
+
);
|
|
32291
|
+
}
|
|
32292
|
+
if (!facts.sitemap) {
|
|
32293
|
+
rows.push({ id: "geo.sitemap", label: "sitemap leaves llms files out", level: "info", detail: "no sitemap route to check" });
|
|
32294
|
+
} else if (facts.sitemapListsLlms) {
|
|
32295
|
+
rows.push({
|
|
32296
|
+
id: "geo.sitemap",
|
|
32297
|
+
label: "sitemap leaves llms files out",
|
|
32298
|
+
level: "warn",
|
|
32299
|
+
detail: `${facts.sitemap} lists /llms.txt, inviting search engines to index a thin plain-text duplicate`,
|
|
32300
|
+
fix: SITEMAP_FIX
|
|
32301
|
+
});
|
|
32302
|
+
} else {
|
|
32303
|
+
rows.push({ id: "geo.sitemap", label: "sitemap leaves llms files out", level: "ok", detail: facts.sitemap });
|
|
32304
|
+
}
|
|
32305
|
+
rows.push(
|
|
32306
|
+
facts.discovery ? { id: "geo.discovery", label: 'discovery header (Link rel="describedby")', level: "ok", detail: facts.discovery } : {
|
|
32307
|
+
id: "geo.discovery",
|
|
32308
|
+
label: 'discovery header (Link rel="describedby")',
|
|
32309
|
+
level: "fail",
|
|
32310
|
+
detail: "not wired in proxy, next.config, root layout, or host config",
|
|
32311
|
+
fix: DISCOVERY_FIX
|
|
32312
|
+
}
|
|
32313
|
+
);
|
|
32314
|
+
for (const f of facts.llms) {
|
|
32315
|
+
if (!f.route && !f.servedStatic) continue;
|
|
32316
|
+
const name = f.path.slice(1);
|
|
32317
|
+
const id = `${f.path === "/llms.txt" ? "llms" : "llms-full"}.noindex`;
|
|
32318
|
+
const label = `${name} sends X-Robots-Tag: noindex`;
|
|
32319
|
+
if (f.servedStatic) {
|
|
32320
|
+
rows.push(
|
|
32321
|
+
f.hostNoindex ? { id, label, level: "ok", detail: f.hostNoindex } : { id, label, level: "warn", detail: `${f.staticReason} is served without it`, fix: hostNoindexFix(f.path) }
|
|
32322
|
+
);
|
|
32323
|
+
continue;
|
|
32324
|
+
}
|
|
32325
|
+
if (f.hostNoindex) {
|
|
32326
|
+
rows.push({ id, label, level: "ok", detail: f.hostNoindex });
|
|
32327
|
+
} else if (f.routeUsesKitHandler && !f.routeOptsOutOfNoindex) {
|
|
32328
|
+
rows.push({ id, label, level: "ok", detail: `${f.route} (site-kit handler default)` });
|
|
32329
|
+
} else if (f.routeSetsNoindex) {
|
|
32330
|
+
rows.push({ id, label, level: "ok", detail: f.route });
|
|
32331
|
+
} else {
|
|
32332
|
+
rows.push({
|
|
32333
|
+
id,
|
|
32334
|
+
label,
|
|
32335
|
+
level: "warn",
|
|
32336
|
+
detail: f.routeOptsOutOfNoindex ? `${f.route} passes noindex: false` : `${f.route} doesn't set it`,
|
|
32337
|
+
fix: f.routeOptsOutOfNoindex ? "Drop noindex: false unless you want llms.txt in search results." : "Serve it with createLLMsTxtHandler (sends the header by default), or add X-Robots-Tag: noindex to the response."
|
|
32338
|
+
});
|
|
32339
|
+
}
|
|
32340
|
+
}
|
|
32341
|
+
return rows;
|
|
32342
|
+
}
|
|
32343
|
+
function checkGeoWiring(cwd) {
|
|
32344
|
+
return judgeGeoWiring(readGeoWiring(cwd));
|
|
32345
|
+
}
|
|
32346
|
+
|
|
32347
|
+
// src/cli/commands/geo.ts
|
|
32219
32348
|
var LLMS_ROUTE = `import { createLLMsTxtHandler } from '@sonordev/site-kit/llms'
|
|
32220
32349
|
|
|
32221
32350
|
export const GET = createLLMsTxtHandler({ preferStatic: true })
|
|
@@ -32224,40 +32353,36 @@ var LLMS_FULL_ROUTE = `import { createLLMsFullTxtHandler } from '@sonordev/site-
|
|
|
32224
32353
|
|
|
32225
32354
|
export const GET = createLLMsFullTxtHandler({ preferStatic: true })
|
|
32226
32355
|
`;
|
|
32227
|
-
|
|
32228
|
-
|
|
32229
|
-
|
|
32230
|
-
|
|
32231
|
-
|
|
32232
|
-
|
|
32233
|
-
}
|
|
32234
|
-
}
|
|
32356
|
+
var ICON = {
|
|
32357
|
+
ok: source_default.green(" \u2713 "),
|
|
32358
|
+
info: source_default.gray(" \xB7 "),
|
|
32359
|
+
warn: source_default.yellow(" ! "),
|
|
32360
|
+
fail: source_default.red(" \u2717 ")
|
|
32361
|
+
};
|
|
32235
32362
|
async function ensureLlmsRouteFiles(appDir, dryRun) {
|
|
32236
|
-
const llms = path10.join(appDir, "llms.txt", "route.ts");
|
|
32237
|
-
const llmsFull = path10.join(appDir, "llms-full.txt", "route.ts");
|
|
32238
32363
|
let n5 = 0;
|
|
32239
32364
|
if (dryRun) return 0;
|
|
32240
|
-
|
|
32241
|
-
|
|
32242
|
-
|
|
32243
|
-
|
|
32244
|
-
|
|
32245
|
-
|
|
32246
|
-
await fs3.mkdir(
|
|
32247
|
-
await fs3.writeFile(
|
|
32365
|
+
for (const [dir, source] of [
|
|
32366
|
+
["llms.txt", LLMS_ROUTE],
|
|
32367
|
+
["llms-full.txt", LLMS_FULL_ROUTE]
|
|
32368
|
+
]) {
|
|
32369
|
+
if (findConventionFile(path12.join(appDir, dir), "route")) continue;
|
|
32370
|
+
const file = path12.join(appDir, dir, "route.ts");
|
|
32371
|
+
await fs3.mkdir(path12.dirname(file), { recursive: true });
|
|
32372
|
+
await fs3.writeFile(file, source, "utf-8");
|
|
32248
32373
|
n5++;
|
|
32249
32374
|
}
|
|
32250
32375
|
return n5;
|
|
32251
32376
|
}
|
|
32252
32377
|
async function geoCommand(options) {
|
|
32253
32378
|
if (options.forInstall) {
|
|
32254
|
-
const appDir2 =
|
|
32379
|
+
const appDir2 = findAppDirForDiscovery();
|
|
32255
32380
|
if (!appDir2) return;
|
|
32256
32381
|
const created = await ensureLlmsRouteFiles(appDir2, options.dryRun);
|
|
32257
32382
|
if (created > 0) {
|
|
32258
32383
|
console.log(
|
|
32259
32384
|
source_default.cyan(
|
|
32260
|
-
`[@sonordev/site-kit] Created ${created} llms route file(s). Set NEXT_PUBLIC_SITE_URL
|
|
32385
|
+
`[@sonordev/site-kit] Created ${created} llms route file(s). Set NEXT_PUBLIC_SITE_URL and add createProxy({ llmsDiscovery: { siteUrl } }) to proxy.ts when ready.`
|
|
32261
32386
|
)
|
|
32262
32387
|
);
|
|
32263
32388
|
}
|
|
@@ -32272,59 +32397,20 @@ async function geoCommand(options) {
|
|
|
32272
32397
|
)
|
|
32273
32398
|
);
|
|
32274
32399
|
console.log("");
|
|
32275
|
-
const appDir =
|
|
32400
|
+
const appDir = findAppDirForDiscovery();
|
|
32276
32401
|
if (!appDir) {
|
|
32277
32402
|
console.log(source_default.red(" \u2717 No app directory (app/ or src/app/)"));
|
|
32278
32403
|
process.exit(1);
|
|
32279
32404
|
}
|
|
32280
|
-
const llms = path10.join(appDir, "llms.txt", "route.ts");
|
|
32281
|
-
const llmsFull = path10.join(appDir, "llms-full.txt", "route.ts");
|
|
32282
|
-
const sitemap = path10.join(appDir, "sitemap.ts");
|
|
32283
32405
|
let allOk = true;
|
|
32284
|
-
const row
|
|
32285
|
-
if (
|
|
32286
|
-
|
|
32287
|
-
|
|
32288
|
-
)
|
|
32289
|
-
|
|
32290
|
-
row("llms.txt route", existsSync(llms));
|
|
32291
|
-
row("llms-full.txt route", existsSync(llmsFull));
|
|
32292
|
-
let sitemapHasLlms = false;
|
|
32293
|
-
if (existsSync(sitemap)) {
|
|
32294
|
-
const txt = await readIfExists(sitemap);
|
|
32295
|
-
sitemapHasLlms = txt.includes("includeLlmsTxtInSitemap") || txt.includes("includeLlmsFullTxtInSitemap");
|
|
32296
|
-
row("sitemap.ts lists llms URLs", sitemapHasLlms);
|
|
32297
|
-
} else {
|
|
32298
|
-
row("sitemap.ts lists llms URLs", false);
|
|
32299
|
-
}
|
|
32300
|
-
const nextConfigs = [
|
|
32301
|
-
path10.join(cwd, "next.config.ts"),
|
|
32302
|
-
path10.join(cwd, "next.config.mjs"),
|
|
32303
|
-
path10.join(cwd, "next.config.js")
|
|
32304
|
-
];
|
|
32305
|
-
let nextCfg = "";
|
|
32306
|
-
for (const p of nextConfigs) {
|
|
32307
|
-
if (existsSync(p)) {
|
|
32308
|
-
nextCfg = await readIfExists(p);
|
|
32309
|
-
break;
|
|
32406
|
+
for (const row of checkGeoWiring(cwd)) {
|
|
32407
|
+
if (row.level === "fail") allOk = false;
|
|
32408
|
+
const detail = row.detail ? source_default.gray(` ${row.detail}`) : "";
|
|
32409
|
+
console.log(`${ICON[row.level]}${row.label}${detail}`);
|
|
32410
|
+
if (row.fix && (row.level === "fail" || row.level === "warn")) {
|
|
32411
|
+
console.log(source_default.gray(` ${row.fix}`));
|
|
32310
32412
|
}
|
|
32311
32413
|
}
|
|
32312
|
-
const layoutCandidates = [
|
|
32313
|
-
path10.join(appDir, "layout.tsx"),
|
|
32314
|
-
path10.join(appDir, "layout.jsx"),
|
|
32315
|
-
path10.join(appDir, "layout.js")
|
|
32316
|
-
];
|
|
32317
|
-
let layoutTxt = "";
|
|
32318
|
-
for (const p of layoutCandidates) {
|
|
32319
|
-
layoutTxt = await readIfExists(p);
|
|
32320
|
-
if (layoutTxt) break;
|
|
32321
|
-
}
|
|
32322
|
-
const hasLayoutDiscovery = layoutTxt.includes("buildAiDiscoveryHeaders") || layoutTxt.includes("llmsTxtDiscoveryLink");
|
|
32323
|
-
const hasConfigDiscovery = nextCfg.includes("llmsTxtDiscoveryLink");
|
|
32324
|
-
row(
|
|
32325
|
-
"discovery header (next.config or root layout)",
|
|
32326
|
-
hasConfigDiscovery || hasLayoutDiscovery
|
|
32327
|
-
);
|
|
32328
32414
|
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL?.trim() || process.env.SITE_BASE_URL?.trim() || (process.env.VERCEL_URL?.trim() ? `https://${process.env.VERCEL_URL.replace(/\/$/, "")}` : "");
|
|
32329
32415
|
if (siteUrl) {
|
|
32330
32416
|
console.log(source_default.gray(` Public origin (env): ${siteUrl}`));
|
|
@@ -32350,19 +32436,16 @@ async function geoCommand(options) {
|
|
|
32350
32436
|
console.log(source_default.bold(" Automation"));
|
|
32351
32437
|
console.log("");
|
|
32352
32438
|
console.log(
|
|
32353
|
-
source_default.gray(
|
|
32354
|
-
" \u2022 next.config: withSiteKitConfig({ llmsTxtDiscoveryLink: true })"
|
|
32355
|
-
)
|
|
32439
|
+
source_default.gray(' \u2022 proxy.ts: createProxy({ llmsDiscovery: { siteUrl } }) (Link rel="describedby")')
|
|
32356
32440
|
);
|
|
32357
32441
|
console.log(
|
|
32358
|
-
source_default.gray(
|
|
32359
|
-
" (If you define your own headers() on nextConfig, merge Link manually.)"
|
|
32360
|
-
)
|
|
32442
|
+
source_default.gray(" or next.config: withSiteKitConfig({ llmsTxtDiscoveryLink: true })")
|
|
32361
32443
|
);
|
|
32362
32444
|
console.log(
|
|
32363
|
-
source_default.gray(
|
|
32364
|
-
|
|
32365
|
-
|
|
32445
|
+
source_default.gray(" \u2022 createLLMsTxtHandler sends X-Robots-Tag: noindex; a static public/llms.txt needs it in netlify.toml")
|
|
32446
|
+
);
|
|
32447
|
+
console.log(
|
|
32448
|
+
source_default.gray(" \u2022 Keep llms.txt out of the sitemap: AI crawlers find it at /llms.txt")
|
|
32366
32449
|
);
|
|
32367
32450
|
console.log(
|
|
32368
32451
|
source_default.gray(" \u2022 npx sonor-setup scaffold --minimal (routes + sitemap template)")
|
|
@@ -32372,8 +32455,8 @@ async function geoCommand(options) {
|
|
|
32372
32455
|
}
|
|
32373
32456
|
|
|
32374
32457
|
// src/cli/index.ts
|
|
32375
|
-
(0,
|
|
32376
|
-
(0,
|
|
32458
|
+
(0, import_dotenv2.config)({ path: ".env.local", quiet: true });
|
|
32459
|
+
(0, import_dotenv2.config)({ path: ".env", quiet: true });
|
|
32377
32460
|
var program2 = new Command();
|
|
32378
32461
|
program2.name("sonor-setup").description("Setup + verification toolchain for @sonordev/site-kit").version(SITE_KIT_VERSION);
|
|
32379
32462
|
withAgentFlags(
|