@farm.js/core 0.1.0-beta.1 → 0.1.0-beta.11
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/README.md +1 -1
- package/dist/agent-runtime.d.mts +3 -2
- package/dist/agent-runtime.d.ts +3 -2
- package/dist/api/route-manager.cjs +410 -15
- package/dist/api/route-manager.cjs.map +1 -1
- package/dist/api/route-manager.d.mts +7 -5
- package/dist/api/route-manager.d.ts +7 -5
- package/dist/api/route-manager.mjs +9 -8
- package/dist/api/runtime.cjs +748 -9
- package/dist/api/runtime.cjs.map +1 -1
- package/dist/api/runtime.d.mts +3 -16
- package/dist/api/runtime.d.ts +3 -16
- package/dist/api/runtime.mjs +8 -1
- package/dist/api.cjs +1243 -342
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.mts +8 -150
- package/dist/api.d.ts +8 -150
- package/dist/api.mjs +51 -21
- package/dist/{app-BiX4qb-d.d.mts → app-BNE2FoZ4.d.mts} +42 -5
- package/dist/{app-CFRNJXP1.d.ts → app-DRGUmJ3s.d.ts} +42 -5
- package/dist/app-markdown.cjs +32 -8
- package/dist/app-markdown.cjs.map +1 -1
- package/dist/app-markdown.d.mts +3 -2
- package/dist/app-markdown.d.ts +3 -2
- package/dist/app-markdown.mjs +2 -1
- package/dist/cache.cjs +414 -12
- package/dist/cache.cjs.map +1 -1
- package/dist/cache.d.mts +120 -6
- package/dist/cache.d.ts +120 -6
- package/dist/cache.mjs +11 -3
- package/dist/{chunk-QF4PHCMA.mjs → chunk-2ED5Q2GH.mjs} +3 -3
- package/dist/chunk-2ED5Q2GH.mjs.map +1 -0
- package/dist/{chunk-GZP5W4K3.mjs → chunk-32W4QEJP.mjs} +1 -1
- package/dist/chunk-32W4QEJP.mjs.map +1 -0
- package/dist/{chunk-G3B5BRDY.mjs → chunk-4677KXB7.mjs} +646 -86
- package/dist/chunk-4677KXB7.mjs.map +1 -0
- package/dist/{chunk-3QJO55ZF.mjs → chunk-4LND3PXF.mjs} +30 -38
- package/dist/chunk-4LND3PXF.mjs.map +1 -0
- package/dist/chunk-5EVQFRL2.mjs +10 -0
- package/dist/chunk-5EVQFRL2.mjs.map +1 -0
- package/dist/{chunk-25D7G34K.mjs → chunk-65A7QIKI.mjs} +5 -5
- package/dist/{chunk-25D7G34K.mjs.map → chunk-65A7QIKI.mjs.map} +1 -1
- package/dist/{chunk-CHFHNEMO.mjs → chunk-77BOAQHI.mjs} +1972 -188
- package/dist/chunk-77BOAQHI.mjs.map +1 -0
- package/dist/{chunk-LLC7BNXW.mjs → chunk-7FBJLMQH.mjs} +73 -10
- package/dist/chunk-7FBJLMQH.mjs.map +1 -0
- package/dist/{chunk-TRORP7E4.mjs → chunk-7N62DNSO.mjs} +2 -2
- package/dist/chunk-ALCLXXTY.mjs +187 -0
- package/dist/chunk-ALCLXXTY.mjs.map +1 -0
- package/dist/chunk-AW6I64AP.mjs +25 -0
- package/dist/chunk-AW6I64AP.mjs.map +1 -0
- package/dist/{chunk-B6N4ZB2H.mjs → chunk-C2ROET2V.mjs} +3 -3
- package/dist/{chunk-BHG3LVHH.mjs → chunk-CGIXMLSY.mjs} +15 -7
- package/dist/chunk-CGIXMLSY.mjs.map +1 -0
- package/dist/{chunk-C3DLZMBU.mjs → chunk-DJSGLHCN.mjs} +2 -2
- package/dist/{chunk-JN3UU635.mjs → chunk-EJ7T4TPB.mjs} +2 -2
- package/dist/chunk-EJ7T4TPB.mjs.map +1 -0
- package/dist/{chunk-ZJQNATYV.mjs → chunk-FRPWCMMG.mjs} +3 -3
- package/dist/chunk-FRPWCMMG.mjs.map +1 -0
- package/dist/{chunk-QM6VV26B.mjs → chunk-GQVGIUSN.mjs} +3 -3
- package/dist/{chunk-QM6VV26B.mjs.map → chunk-GQVGIUSN.mjs.map} +1 -1
- package/dist/{chunk-UREJA4GZ.mjs → chunk-GXASWWJU.mjs} +1 -1
- package/dist/{chunk-UREJA4GZ.mjs.map → chunk-GXASWWJU.mjs.map} +1 -1
- package/dist/chunk-I4CUBGVF.mjs +93 -0
- package/dist/chunk-I4CUBGVF.mjs.map +1 -0
- package/dist/{chunk-HXP3ZSPC.mjs → chunk-J5YWQVI5.mjs} +4 -4
- package/dist/chunk-J5YWQVI5.mjs.map +1 -0
- package/dist/{chunk-PRNYWD7K.mjs → chunk-JDEOUK5V.mjs} +67 -239
- package/dist/chunk-JDEOUK5V.mjs.map +1 -0
- package/dist/{chunk-UHE2TTLK.mjs → chunk-K5ZTUF22.mjs} +34 -17
- package/dist/chunk-K5ZTUF22.mjs.map +1 -0
- package/dist/{chunk-O3HADRW6.mjs → chunk-MIUW47JX.mjs} +2 -2
- package/dist/{chunk-O3HADRW6.mjs.map → chunk-MIUW47JX.mjs.map} +1 -1
- package/dist/chunk-PFE6GMNE.mjs +603 -0
- package/dist/chunk-PFE6GMNE.mjs.map +1 -0
- package/dist/{chunk-RKI6TN3A.mjs → chunk-QM746KUO.mjs} +9 -2
- package/dist/chunk-QM746KUO.mjs.map +1 -0
- package/dist/{chunk-TU4YJICB.mjs → chunk-QTZZ2ISQ.mjs} +41 -16
- package/dist/chunk-QTZZ2ISQ.mjs.map +1 -0
- package/dist/chunk-RBRLLZL5.mjs +81 -0
- package/dist/chunk-RBRLLZL5.mjs.map +1 -0
- package/dist/{chunk-RSKVYESE.mjs → chunk-RQ633A5I.mjs} +1 -1
- package/dist/chunk-RQ633A5I.mjs.map +1 -0
- package/dist/{chunk-6XDUHOEM.mjs → chunk-TQAEEJB4.mjs} +3 -3
- package/dist/{chunk-AGS7UJ52.mjs → chunk-UB5UOSHB.mjs} +24 -12
- package/dist/chunk-UB5UOSHB.mjs.map +1 -0
- package/dist/{chunk-SXZTEK3V.mjs → chunk-UXUAWNO5.mjs} +2 -2
- package/dist/chunk-V3XURYJO.mjs +756 -0
- package/dist/chunk-V3XURYJO.mjs.map +1 -0
- package/dist/{chunk-JLWMCADZ.mjs → chunk-VY2UYN5R.mjs} +24 -4
- package/dist/chunk-VY2UYN5R.mjs.map +1 -0
- package/dist/{chunk-QFQRHRZS.mjs → chunk-W2CRQFF6.mjs} +151 -23
- package/dist/chunk-W2CRQFF6.mjs.map +1 -0
- package/dist/{chunk-Y7A27276.mjs → chunk-WDU6QXNK.mjs} +349 -15
- package/dist/chunk-WDU6QXNK.mjs.map +1 -0
- package/dist/{chunk-Y2OJJD7R.mjs → chunk-XIVV5IWN.mjs} +7 -9
- package/dist/chunk-XIVV5IWN.mjs.map +1 -0
- package/dist/{chunk-OYXO65LI.mjs → chunk-YW7OBE6Q.mjs} +4 -4
- package/dist/chunk-YW7OBE6Q.mjs.map +1 -0
- package/dist/{chunk-YHU7SS6L.mjs → chunk-Z5CQMP54.mjs} +11 -11
- package/dist/{chunk-S2XHZS7W.mjs → chunk-ZVWA4ZQ3.mjs} +18 -9
- package/dist/chunk-ZVWA4ZQ3.mjs.map +1 -0
- package/dist/{chunk-SOU3Q3ZA.mjs → chunk-ZZ57EH5Z.mjs} +1 -1
- package/dist/chunk-ZZ57EH5Z.mjs.map +1 -0
- package/dist/{client-D_yUjVhe.d.mts → client-BT1mFQas.d.mts} +55 -10
- package/dist/{client-Dkc03WP8.d.ts → client-Nn0q4eO4.d.ts} +55 -10
- package/dist/{client-plugins-BZnpeTGA.d.ts → client-plugins-Bc5jHcNr.d.ts} +85 -6
- package/dist/{client-plugins-g4bzuCmo.d.mts → client-plugins-jsk-ZLzJ.d.mts} +85 -6
- package/dist/client-plugins.d.mts +3 -2
- package/dist/client-plugins.d.ts +3 -2
- package/dist/client.cjs +922 -91
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.mts +124 -6
- package/dist/client.d.ts +124 -6
- package/dist/client.mjs +23 -16
- package/dist/config.d.mts +3 -2
- package/dist/config.d.ts +3 -2
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.mjs +1 -1
- package/dist/{devtools-AE4RVXCM.mjs → devtools-A22KUJZT.mjs} +13 -12
- package/dist/{devtools-AE4RVXCM.mjs.map → devtools-A22KUJZT.mjs.map} +1 -1
- package/dist/{devtools-client-6WPY2AQU.mjs → devtools-client-3XRTBND5.mjs} +2 -11
- package/dist/devtools-client-3XRTBND5.mjs.map +1 -0
- package/dist/docs.cjs +65 -58
- package/dist/docs.cjs.map +1 -1
- package/dist/docs.mjs +13 -12
- package/dist/env-types.cjs +14 -5
- package/dist/env-types.cjs.map +1 -1
- package/dist/env-types.d.mts +2 -1
- package/dist/env-types.d.ts +2 -1
- package/dist/env-types.mjs +3 -1
- package/dist/env.cjs.map +1 -1
- package/dist/env.d.mts +1 -1
- package/dist/env.d.ts +1 -1
- package/dist/env.mjs +1 -1
- package/dist/font.cjs +47 -0
- package/dist/font.cjs.map +1 -0
- package/dist/font.d.mts +70 -0
- package/dist/font.d.ts +70 -0
- package/dist/font.mjs +10 -0
- package/dist/font.mjs.map +1 -0
- package/dist/i18n/client.d.mts +2 -2
- package/dist/i18n/client.d.ts +2 -2
- package/dist/i18n/index.d.mts +3 -3
- package/dist/i18n/index.d.ts +3 -3
- package/dist/i18n/server.cjs +2 -2
- package/dist/i18n/server.cjs.map +1 -1
- package/dist/i18n/server.d.mts +5 -5
- package/dist/i18n/server.d.ts +5 -5
- package/dist/i18n/server.mjs +1 -1
- package/dist/index.cjs +5016 -1108
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +23 -19
- package/dist/index.d.ts +23 -19
- package/dist/index.mjs +177 -121
- package/dist/index.mjs.map +1 -1
- package/dist/integrations.d.mts +3 -2
- package/dist/integrations.d.ts +3 -2
- package/dist/internal/build-runtime.cjs +3504 -581
- package/dist/internal/build-runtime.cjs.map +1 -1
- package/dist/internal/build-runtime.d.mts +5 -4
- package/dist/internal/build-runtime.d.ts +5 -4
- package/dist/internal/build-runtime.mjs +32 -29
- package/dist/internal/client-runtime.cjs.map +1 -1
- package/dist/internal/client-runtime.mjs +1 -1
- package/dist/internal/config-runtime.cjs +148 -41
- package/dist/internal/config-runtime.cjs.map +1 -1
- package/dist/internal/config-runtime.d.mts +4 -3
- package/dist/internal/config-runtime.d.ts +4 -3
- package/dist/internal/config-runtime.mjs +12 -11
- package/dist/internal/production-runtime.cjs +300 -9
- package/dist/internal/production-runtime.cjs.map +1 -1
- package/dist/internal/production-runtime.d.mts +10 -8
- package/dist/internal/production-runtime.d.ts +10 -8
- package/dist/internal/production-runtime.mjs +27 -9
- package/dist/internal/production-runtime.mjs.map +1 -1
- package/dist/markdown.cjs +73 -8
- package/dist/markdown.cjs.map +1 -1
- package/dist/markdown.d.mts +19 -2
- package/dist/markdown.d.ts +19 -2
- package/dist/markdown.mjs +5 -1
- package/dist/{metadata-C9NZxMDW.d.mts → metadata-7ffpT3jr.d.mts} +1 -1
- package/dist/{metadata-DAXRaOHx.d.ts → metadata-JHn-8eht.d.ts} +1 -1
- package/dist/middleware.cjs +2 -2
- package/dist/middleware.cjs.map +1 -1
- package/dist/middleware.d.mts +5 -4
- package/dist/middleware.d.ts +5 -4
- package/dist/middleware.mjs +3 -3
- package/dist/navigation.cjs +40 -15
- package/dist/navigation.cjs.map +1 -1
- package/dist/navigation.mjs +3 -3
- package/dist/{nitro-KME62MWG.mjs → nitro-QO5LV6QK.mjs} +11 -13
- package/dist/{nitro-KME62MWG.mjs.map → nitro-QO5LV6QK.mjs.map} +1 -1
- package/dist/plugin.cjs +2854 -590
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.mts +3 -2
- package/dist/plugin.d.ts +3 -2
- package/dist/plugin.mjs +28 -25
- package/dist/{production-runtime-DRkCHUvJ.d.ts → production-runtime-9KG7GuvW.d.ts} +2 -2
- package/dist/{production-runtime-flrjp_nC.d.mts → production-runtime-B-fweKts.d.mts} +2 -2
- package/dist/{request-BrFBuc8G.d.mts → request-Dsq4kGW0.d.mts} +1 -1
- package/dist/{request-BslSZIRz.d.ts → request-udtobOLv.d.ts} +1 -1
- package/dist/request.d.mts +2 -2
- package/dist/request.d.ts +2 -2
- package/dist/{resolver-DlOPpjkB.d.mts → resolver-DJqjLMg_.d.mts} +1 -1
- package/dist/{resolver-C6iecsDV.d.ts → resolver-IH4RmPEl.d.ts} +1 -1
- package/dist/routes.cjs +276 -6
- package/dist/routes.cjs.map +1 -1
- package/dist/routes.d.mts +2 -2
- package/dist/routes.d.ts +2 -2
- package/dist/routes.mjs +4 -4
- package/dist/runtime-9nQjVM7X.d.mts +206 -0
- package/dist/{runtime-DeAAZ6gO.d.mts → runtime-Cxpq6xZN.d.mts} +2 -2
- package/dist/runtime-DgeS2skB.d.ts +206 -0
- package/dist/{runtime-B6GvwDS1.d.ts → runtime-bv63eUiO.d.ts} +2 -2
- package/dist/server-action-security.cjs +28 -10
- package/dist/server-action-security.cjs.map +1 -1
- package/dist/server-action-security.d.mts +2 -1
- package/dist/server-action-security.d.ts +2 -1
- package/dist/server-action-security.mjs +2 -2
- package/dist/server-fn-client.cjs.map +1 -1
- package/dist/server-fn-client.d.mts +1 -0
- package/dist/server-fn-client.d.ts +1 -0
- package/dist/server-fn-client.mjs +1 -1
- package/dist/server-fn.cjs +785 -3
- package/dist/server-fn.cjs.map +1 -1
- package/dist/server-fn.d.mts +10 -1
- package/dist/server-fn.d.ts +10 -1
- package/dist/server-fn.mjs +6 -3
- package/dist/server-plugins.d.mts +4 -3
- package/dist/server-plugins.d.ts +4 -3
- package/dist/server-query-client.cjs +279 -8
- package/dist/server-query-client.cjs.map +1 -1
- package/dist/server-query-client.mjs +4 -4
- package/dist/server-query.cjs +381 -10
- package/dist/server-query.cjs.map +1 -1
- package/dist/server-query.mjs +5 -5
- package/dist/server.cjs +3319 -841
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.mts +12 -11
- package/dist/server.d.ts +12 -11
- package/dist/server.mjs +57 -36
- package/dist/server.mjs.map +1 -1
- package/dist/testing.cjs +436 -25
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.mts +5 -4
- package/dist/testing.d.ts +5 -4
- package/dist/testing.mjs +19 -18
- package/dist/testing.mjs.map +1 -1
- package/dist/transport-BmbGTXA5.d.mts +49 -0
- package/dist/transport-BmbGTXA5.d.ts +49 -0
- package/dist/{types-BH1lhg5G.d.ts → types-BMxWr97v.d.mts} +2 -2
- package/dist/{types-BH1lhg5G.d.mts → types-BMxWr97v.d.ts} +2 -2
- package/dist/{utils-DA1yo54_.d.ts → utils-CA0z0c-2.d.ts} +1 -1
- package/dist/{utils-DOXXivjL.d.mts → utils-mYVkSOt2.d.mts} +1 -1
- package/dist/version.cjs +36 -0
- package/dist/version.cjs.map +1 -0
- package/dist/version.d.mts +3 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.mjs +8 -0
- package/dist/version.mjs.map +1 -0
- package/dist/vite.cjs +2938 -668
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.mts +3 -2
- package/dist/vite.d.ts +3 -2
- package/dist/vite.mjs +26 -23
- package/dist/workflows.cjs +6 -8
- package/dist/workflows.cjs.map +1 -1
- package/dist/workflows.mjs +1 -1
- package/package.json +22 -6
- package/types/api.d.ts +44 -0
- package/types/client.d.ts +221 -17
- package/types/image.d.ts +4 -0
- package/types/images.d.ts +59 -0
- package/dist/chunk-3QJO55ZF.mjs.map +0 -1
- package/dist/chunk-4PTK6KT4.mjs +0 -364
- package/dist/chunk-4PTK6KT4.mjs.map +0 -1
- package/dist/chunk-AGS7UJ52.mjs.map +0 -1
- package/dist/chunk-BHG3LVHH.mjs.map +0 -1
- package/dist/chunk-CHFHNEMO.mjs.map +0 -1
- package/dist/chunk-EVGBEZDF.mjs +0 -215
- package/dist/chunk-EVGBEZDF.mjs.map +0 -1
- package/dist/chunk-G3B5BRDY.mjs.map +0 -1
- package/dist/chunk-GZP5W4K3.mjs.map +0 -1
- package/dist/chunk-HXP3ZSPC.mjs.map +0 -1
- package/dist/chunk-JLWMCADZ.mjs.map +0 -1
- package/dist/chunk-JN3UU635.mjs.map +0 -1
- package/dist/chunk-LLC7BNXW.mjs.map +0 -1
- package/dist/chunk-OYXO65LI.mjs.map +0 -1
- package/dist/chunk-PRNYWD7K.mjs.map +0 -1
- package/dist/chunk-QF4PHCMA.mjs.map +0 -1
- package/dist/chunk-QFQRHRZS.mjs.map +0 -1
- package/dist/chunk-RKI6TN3A.mjs.map +0 -1
- package/dist/chunk-RSKVYESE.mjs.map +0 -1
- package/dist/chunk-S2XHZS7W.mjs.map +0 -1
- package/dist/chunk-SOU3Q3ZA.mjs.map +0 -1
- package/dist/chunk-TU4YJICB.mjs.map +0 -1
- package/dist/chunk-TXCFGOHW.mjs +0 -42
- package/dist/chunk-TXCFGOHW.mjs.map +0 -1
- package/dist/chunk-UHE2TTLK.mjs.map +0 -1
- package/dist/chunk-Y2OJJD7R.mjs.map +0 -1
- package/dist/chunk-Y7A27276.mjs.map +0 -1
- package/dist/chunk-ZJQNATYV.mjs.map +0 -1
- package/dist/devtools-client-6WPY2AQU.mjs.map +0 -1
- /package/dist/{chunk-TRORP7E4.mjs.map → chunk-7N62DNSO.mjs.map} +0 -0
- /package/dist/{chunk-B6N4ZB2H.mjs.map → chunk-C2ROET2V.mjs.map} +0 -0
- /package/dist/{chunk-C3DLZMBU.mjs.map → chunk-DJSGLHCN.mjs.map} +0 -0
- /package/dist/{chunk-6XDUHOEM.mjs.map → chunk-TQAEEJB4.mjs.map} +0 -0
- /package/dist/{chunk-SXZTEK3V.mjs.map → chunk-UXUAWNO5.mjs.map} +0 -0
- /package/dist/{chunk-YHU7SS6L.mjs.map → chunk-Z5CQMP54.mjs.map} +0 -0
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
addMetadataImageReference,
|
|
6
6
|
mergeMetadata,
|
|
7
7
|
renderMetadataHead
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-FRPWCMMG.mjs";
|
|
9
9
|
import {
|
|
10
10
|
farmEnvironmentFunctionsPlugin
|
|
11
11
|
} from "./chunk-V6WE6JSZ.mjs";
|
|
@@ -13,11 +13,23 @@ import {
|
|
|
13
13
|
createFarmImageHandler
|
|
14
14
|
} from "./chunk-3XNTL3FQ.mjs";
|
|
15
15
|
import {
|
|
16
|
+
createEnvTypeDeclarations,
|
|
16
17
|
generateEnvTypes
|
|
17
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-CGIXMLSY.mjs";
|
|
18
19
|
import {
|
|
19
20
|
writeFileIfChanged
|
|
20
21
|
} from "./chunk-USWZZUEH.mjs";
|
|
22
|
+
import {
|
|
23
|
+
getFarmRedirectError,
|
|
24
|
+
isFarmNotFoundError,
|
|
25
|
+
isFarmRedirectError
|
|
26
|
+
} from "./chunk-7HO6AEOP.mjs";
|
|
27
|
+
import {
|
|
28
|
+
resolveFarmAuthConfig
|
|
29
|
+
} from "./chunk-I4CUBGVF.mjs";
|
|
30
|
+
import {
|
|
31
|
+
normalizeRouteRules
|
|
32
|
+
} from "./chunk-YW7OBE6Q.mjs";
|
|
21
33
|
import {
|
|
22
34
|
getFarmAppDirectories,
|
|
23
35
|
getFarmLayerAliases,
|
|
@@ -28,33 +40,31 @@ import {
|
|
|
28
40
|
FARM_DEVTOOLS_PATH,
|
|
29
41
|
resolveFarmDevtoolsConfig
|
|
30
42
|
} from "./chunk-7MABZJIM.mjs";
|
|
31
|
-
import {
|
|
32
|
-
normalizeRouteRules
|
|
33
|
-
} from "./chunk-OYXO65LI.mjs";
|
|
34
43
|
import {
|
|
35
44
|
getPublicFarmImageConfig,
|
|
36
45
|
resolveFarmImageConfig
|
|
37
46
|
} from "./chunk-GY2STC2S.mjs";
|
|
38
47
|
import {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
} from "./chunk-LLC7BNXW.mjs";
|
|
48
|
+
resolveServerActionsConfig
|
|
49
|
+
} from "./chunk-UB5UOSHB.mjs";
|
|
42
50
|
import {
|
|
43
51
|
createFarmMarkdownRouteModuleFromFile,
|
|
44
52
|
createFarmMarkdownSourceResponse,
|
|
45
53
|
isFarmMarkdownPageFile,
|
|
46
54
|
loadFarmMdxComponents,
|
|
47
55
|
resolveMdxConfig
|
|
48
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-ZVWA4ZQ3.mjs";
|
|
57
|
+
import {
|
|
58
|
+
createMarkdownMirrorResponse,
|
|
59
|
+
resolveMarkdownConfig,
|
|
60
|
+
resolveMarkdownMirrorTarget
|
|
61
|
+
} from "./chunk-7FBJLMQH.mjs";
|
|
49
62
|
import {
|
|
50
63
|
resolveWorkflowsConfig
|
|
51
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-XIVV5IWN.mjs";
|
|
52
65
|
import {
|
|
53
66
|
resolveCronConfig
|
|
54
|
-
} from "./chunk-
|
|
55
|
-
import {
|
|
56
|
-
resolveServerActionsConfig
|
|
57
|
-
} from "./chunk-AGS7UJ52.mjs";
|
|
67
|
+
} from "./chunk-GXASWWJU.mjs";
|
|
58
68
|
import {
|
|
59
69
|
dispatchIntegrationRequest,
|
|
60
70
|
getIntegrationDocumentNavigationMatchers,
|
|
@@ -63,14 +73,9 @@ import {
|
|
|
63
73
|
getRequestContextSnapshot,
|
|
64
74
|
matchIntegrationRoute
|
|
65
75
|
} from "./chunk-K4667E2Q.mjs";
|
|
66
|
-
import {
|
|
67
|
-
getFarmRedirectError,
|
|
68
|
-
isFarmNotFoundError,
|
|
69
|
-
isFarmRedirectError
|
|
70
|
-
} from "./chunk-7HO6AEOP.mjs";
|
|
71
76
|
import {
|
|
72
77
|
MiddlewareManager
|
|
73
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-MIUW47JX.mjs";
|
|
74
79
|
import {
|
|
75
80
|
_clearCurrentMiddlewareContext,
|
|
76
81
|
_clearCurrentMiddlewareData,
|
|
@@ -91,14 +96,14 @@ import {
|
|
|
91
96
|
discoverProgrammaticRoutePaths,
|
|
92
97
|
findProgrammaticRouteFiles,
|
|
93
98
|
loadProgrammaticRouteManifests
|
|
94
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-Z5CQMP54.mjs";
|
|
95
100
|
import {
|
|
96
101
|
_runWithFarmI18nRequest,
|
|
97
102
|
_setDefaultFarmI18nRuntime,
|
|
98
103
|
createFarmI18nRuntime,
|
|
99
104
|
getFarmI18nClientSnapshot,
|
|
100
105
|
readFarmI18nCatalogs
|
|
101
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-2ED5Q2GH.mjs";
|
|
102
107
|
import {
|
|
103
108
|
createFarmLocaleCookie,
|
|
104
109
|
getFarmLocaleVaryHeaders
|
|
@@ -106,19 +111,6 @@ import {
|
|
|
106
111
|
import {
|
|
107
112
|
resolveFarmI18nConfig
|
|
108
113
|
} from "./chunk-FQYDHKKU.mjs";
|
|
109
|
-
import {
|
|
110
|
-
fileExists,
|
|
111
|
-
globFiles,
|
|
112
|
-
logger,
|
|
113
|
-
matchRoute,
|
|
114
|
-
parseRoutePath,
|
|
115
|
-
resolveAppPath,
|
|
116
|
-
toViteModuleId
|
|
117
|
-
} from "./chunk-J4FNJ5IU.mjs";
|
|
118
|
-
import {
|
|
119
|
-
_runWithCurrentRequest,
|
|
120
|
-
createWebRequestFromFarmRequest
|
|
121
|
-
} from "./chunk-RHIFZZUI.mjs";
|
|
122
114
|
import {
|
|
123
115
|
createLayoutModuleFromProgrammaticLayout,
|
|
124
116
|
createProgrammaticRouteModuleId,
|
|
@@ -128,7 +120,7 @@ import {
|
|
|
128
120
|
parseProgrammaticRouteModuleId,
|
|
129
121
|
parseProgrammaticRoutePath,
|
|
130
122
|
scanProgrammaticPagePaths
|
|
131
|
-
} from "./chunk-
|
|
123
|
+
} from "./chunk-C2ROET2V.mjs";
|
|
132
124
|
import {
|
|
133
125
|
resolveFarmRouteContext,
|
|
134
126
|
withFarmRouteContext
|
|
@@ -139,7 +131,23 @@ import {
|
|
|
139
131
|
normalizeFarmRouteRuntimeConfig,
|
|
140
132
|
resolveFarmRouteRuleRuntimeConfig,
|
|
141
133
|
resolveFarmRouteRuntimeConfig
|
|
142
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-GQVGIUSN.mjs";
|
|
135
|
+
import {
|
|
136
|
+
fileExists,
|
|
137
|
+
globFiles,
|
|
138
|
+
logger,
|
|
139
|
+
matchRoute,
|
|
140
|
+
parseRoutePath,
|
|
141
|
+
resolveAppPath,
|
|
142
|
+
toViteModuleId
|
|
143
|
+
} from "./chunk-J4FNJ5IU.mjs";
|
|
144
|
+
import {
|
|
145
|
+
_runWithCurrentRequest,
|
|
146
|
+
createWebRequestFromFarmRequest
|
|
147
|
+
} from "./chunk-RHIFZZUI.mjs";
|
|
148
|
+
import {
|
|
149
|
+
FARM_VERSION
|
|
150
|
+
} from "./chunk-5EVQFRL2.mjs";
|
|
143
151
|
import {
|
|
144
152
|
FARM_DEPLOYMENT_ID_HEADER,
|
|
145
153
|
createFarmDeploymentCookie,
|
|
@@ -158,10 +166,11 @@ import {
|
|
|
158
166
|
stripFarmLocaleFromPathname
|
|
159
167
|
} from "./chunk-44ZCFSKE.mjs";
|
|
160
168
|
import {
|
|
169
|
+
configureFarmCache,
|
|
161
170
|
createFarmCacheKey,
|
|
162
171
|
getFarmDataCache,
|
|
163
172
|
normalizeRevalidatePath
|
|
164
|
-
} from "./chunk-
|
|
173
|
+
} from "./chunk-V3XURYJO.mjs";
|
|
165
174
|
import {
|
|
166
175
|
configureFarmObservability,
|
|
167
176
|
emitFarmEvent
|
|
@@ -775,6 +784,76 @@ async function readAltText(filePath) {
|
|
|
775
784
|
}
|
|
776
785
|
__name(readAltText, "readAltText");
|
|
777
786
|
|
|
787
|
+
// src/routing/route-slots.ts
|
|
788
|
+
var SLOT_SEGMENT = /^@([A-Za-z][A-Za-z0-9_-]*)$/;
|
|
789
|
+
function parseRouteSlotFile(filePath) {
|
|
790
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
791
|
+
const parts = normalized.split("/").filter(Boolean);
|
|
792
|
+
const fileName = parts.at(-1) ?? "";
|
|
793
|
+
const baseName = fileName.replace(/\.(tsx?|jsx?)$/, "");
|
|
794
|
+
if (baseName !== "page" && baseName !== "default") return null;
|
|
795
|
+
const slotIndex = parts.findIndex((part) => SLOT_SEGMENT.test(part));
|
|
796
|
+
if (slotIndex < 0) return null;
|
|
797
|
+
if (parts.slice(slotIndex + 1, -1).some((part) => SLOT_SEGMENT.test(part))) {
|
|
798
|
+
throw new Error(`Nested route slots are not supported in "${filePath}"`);
|
|
799
|
+
}
|
|
800
|
+
const slotMatch = parts[slotIndex].match(SLOT_SEGMENT);
|
|
801
|
+
const name = slotMatch?.[1];
|
|
802
|
+
if (!name) return null;
|
|
803
|
+
const ownerParts = parts.slice(0, slotIndex);
|
|
804
|
+
const contentParts = parts.slice(slotIndex + 1, -1);
|
|
805
|
+
const marker = parseInterceptionMarker(contentParts[0]);
|
|
806
|
+
let targetBase = ownerParts;
|
|
807
|
+
let targetParts = contentParts;
|
|
808
|
+
if (marker) {
|
|
809
|
+
targetBase = marker.root === true ? [] : ownerParts.slice(0, Math.max(0, ownerParts.length - marker.up));
|
|
810
|
+
targetParts = [...marker.remainder ? [marker.remainder] : [], ...contentParts.slice(1)];
|
|
811
|
+
}
|
|
812
|
+
const ownerFile = [...ownerParts, "layout.tsx"].join("/");
|
|
813
|
+
const routeFile = [
|
|
814
|
+
...baseName === "default" ? ownerParts : targetBase,
|
|
815
|
+
...baseName === "default" ? [] : targetParts,
|
|
816
|
+
"page.tsx"
|
|
817
|
+
].join("/");
|
|
818
|
+
return {
|
|
819
|
+
name,
|
|
820
|
+
ownerRoute: parseRoutePath(ownerFile || "layout.tsx"),
|
|
821
|
+
route: parseRoutePath(routeFile || "page.tsx"),
|
|
822
|
+
interception: marker !== null,
|
|
823
|
+
fallback: baseName === "default"
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
__name(parseRouteSlotFile, "parseRouteSlotFile");
|
|
827
|
+
function createRouteSlotContainerId(name, ownerPattern) {
|
|
828
|
+
const owner = ownerPattern === "/" ? "root" : ownerPattern.replace(/^\//, "").replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
829
|
+
return `__farm_slot_${name}_${owner || "root"}__`;
|
|
830
|
+
}
|
|
831
|
+
__name(createRouteSlotContainerId, "createRouteSlotContainerId");
|
|
832
|
+
function parseInterceptionMarker(segment) {
|
|
833
|
+
if (!segment) return null;
|
|
834
|
+
if (segment.startsWith("(...)")) {
|
|
835
|
+
return {
|
|
836
|
+
up: 0,
|
|
837
|
+
root: true,
|
|
838
|
+
remainder: segment.slice(5)
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
if (segment.startsWith("(.)")) {
|
|
842
|
+
return {
|
|
843
|
+
up: 0,
|
|
844
|
+
remainder: segment.slice(3)
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
let remainder = segment;
|
|
848
|
+
let up = 0;
|
|
849
|
+
while (remainder.startsWith("(..)")) {
|
|
850
|
+
up += 1;
|
|
851
|
+
remainder = remainder.slice(4);
|
|
852
|
+
}
|
|
853
|
+
return up > 0 ? { up, remainder } : null;
|
|
854
|
+
}
|
|
855
|
+
__name(parseInterceptionMarker, "parseInterceptionMarker");
|
|
856
|
+
|
|
778
857
|
// src/routing/route-manager.ts
|
|
779
858
|
function routeSpecificity(entry) {
|
|
780
859
|
return entry.route.segments.reduce((score, segment) => {
|
|
@@ -788,6 +867,7 @@ var _RouteManager = class _RouteManager {
|
|
|
788
867
|
constructor(config, viteServer) {
|
|
789
868
|
this.routes = /* @__PURE__ */ new Map();
|
|
790
869
|
this.layouts = /* @__PURE__ */ new Map();
|
|
870
|
+
this.routeSlots = /* @__PURE__ */ new Map();
|
|
791
871
|
this.loadings = /* @__PURE__ */ new Map();
|
|
792
872
|
this.errors = /* @__PURE__ */ new Map();
|
|
793
873
|
this.metadataImages = /* @__PURE__ */ new Map();
|
|
@@ -803,6 +883,7 @@ var _RouteManager = class _RouteManager {
|
|
|
803
883
|
async discoverRoutes() {
|
|
804
884
|
this.routes.clear();
|
|
805
885
|
this.layouts.clear();
|
|
886
|
+
this.routeSlots.clear();
|
|
806
887
|
this.loadings.clear();
|
|
807
888
|
this.errors.clear();
|
|
808
889
|
this.metadataImages.clear();
|
|
@@ -813,6 +894,13 @@ var _RouteManager = class _RouteManager {
|
|
|
813
894
|
await this.discoverFileRoutes(source);
|
|
814
895
|
await this.discoverProgrammaticRoutes(source);
|
|
815
896
|
}
|
|
897
|
+
for (const slot of this.routeSlots.values()) {
|
|
898
|
+
if (slot.interception && !this.routes.has(slot.pattern)) {
|
|
899
|
+
throw new Error(
|
|
900
|
+
`Intercepting route slot "${slot.name}" targets "${slot.pattern}", but no canonical page exists for that URL`
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
816
904
|
this.routes = new Map(
|
|
817
905
|
Array.from(this.routes.entries()).sort(
|
|
818
906
|
([, left], [, right]) => routeSpecificity(right) - routeSpecificity(left)
|
|
@@ -828,7 +916,7 @@ var _RouteManager = class _RouteManager {
|
|
|
828
916
|
/**
|
|
829
917
|
* Find matching route for a given URL path
|
|
830
918
|
*/
|
|
831
|
-
matchRoute(pathname) {
|
|
919
|
+
matchRoute(pathname, options = {}) {
|
|
832
920
|
const routePathname = this.toRoutePathname(pathname);
|
|
833
921
|
const normalizedPath = routePathname === "/" ? "/" : routePathname.replace(/\/$/, "");
|
|
834
922
|
let matchedRoute = null;
|
|
@@ -842,10 +930,12 @@ var _RouteManager = class _RouteManager {
|
|
|
842
930
|
}
|
|
843
931
|
}
|
|
844
932
|
const layouts = this.findMatchingLayouts(normalizedPath);
|
|
933
|
+
const slots = this.findMatchingRouteSlots(normalizedPath, options.interceptFrom);
|
|
845
934
|
return {
|
|
846
935
|
route: matchedRoute,
|
|
847
936
|
params,
|
|
848
|
-
layouts
|
|
937
|
+
layouts,
|
|
938
|
+
slots
|
|
849
939
|
};
|
|
850
940
|
}
|
|
851
941
|
/**
|
|
@@ -860,6 +950,9 @@ var _RouteManager = class _RouteManager {
|
|
|
860
950
|
getLayouts() {
|
|
861
951
|
return new Map(this.layouts);
|
|
862
952
|
}
|
|
953
|
+
getRouteSlots() {
|
|
954
|
+
return new Map(this.routeSlots);
|
|
955
|
+
}
|
|
863
956
|
/** Resolve route rules, inherited layouts, and the page export in precedence order. */
|
|
864
957
|
async resolveRouteRuntimeConfig(pattern) {
|
|
865
958
|
const routeEntry = this.routes.get(pattern);
|
|
@@ -1018,7 +1111,22 @@ var _RouteManager = class _RouteManager {
|
|
|
1018
1111
|
pattern: entry.pattern,
|
|
1019
1112
|
modulePath: toUrlPath(entry.modulePath)
|
|
1020
1113
|
}));
|
|
1021
|
-
|
|
1114
|
+
const slots = Array.from(this.routeSlots.values()).map((entry) => {
|
|
1115
|
+
const metadata = getClientModuleMetadata(entry.modulePath, projectRoot);
|
|
1116
|
+
return {
|
|
1117
|
+
name: entry.name,
|
|
1118
|
+
ownerPattern: entry.ownerPattern,
|
|
1119
|
+
pattern: entry.pattern,
|
|
1120
|
+
modulePath: toUrlPath(entry.modulePath),
|
|
1121
|
+
containerId: entry.containerId,
|
|
1122
|
+
interception: entry.interception,
|
|
1123
|
+
fallback: entry.fallback,
|
|
1124
|
+
shouldHydrate: metadata.shouldHydrate,
|
|
1125
|
+
isClientComponent: metadata.isClientComponent,
|
|
1126
|
+
segments: entry.route.segments
|
|
1127
|
+
};
|
|
1128
|
+
});
|
|
1129
|
+
return { routes, layouts, slots };
|
|
1022
1130
|
}
|
|
1023
1131
|
/**
|
|
1024
1132
|
* Load a route module dynamically
|
|
@@ -1095,6 +1203,7 @@ var _RouteManager = class _RouteManager {
|
|
|
1095
1203
|
async discoverFileRoutes(source) {
|
|
1096
1204
|
const appDir = resolveAppPath(source.root, source.srcDir, "app");
|
|
1097
1205
|
const pageFiles = await safeGlobFiles("**/page.{ts,tsx,js,jsx,md,mdx}", appDir);
|
|
1206
|
+
const slotDefaultFiles = await safeGlobFiles("**/@*/**/default.{ts,tsx,js,jsx}", appDir);
|
|
1098
1207
|
const layoutFiles = await safeGlobFiles("**/layout.{ts,tsx,js,jsx}", appDir);
|
|
1099
1208
|
const loadingFiles = await safeGlobFiles("**/loading.{ts,tsx,js,jsx}", appDir);
|
|
1100
1209
|
const errorFiles = await safeGlobFiles("**/error.{ts,tsx,js,jsx}", appDir);
|
|
@@ -1102,8 +1211,56 @@ var _RouteManager = class _RouteManager {
|
|
|
1102
1211
|
"**/{opengraph-image,twitter-image}.{ts,tsx,js,jsx,png,jpg,jpeg,gif,webp}",
|
|
1103
1212
|
appDir
|
|
1104
1213
|
);
|
|
1214
|
+
const canonicalPageGroups = /* @__PURE__ */ new Map();
|
|
1215
|
+
for (const file of pageFiles.filter((candidate) => parseRouteSlotFile(candidate) === null)) {
|
|
1216
|
+
const route = parseRoutePath(file);
|
|
1217
|
+
const pattern = this.createRoutePattern(route);
|
|
1218
|
+
const group = canonicalPageGroups.get(pattern);
|
|
1219
|
+
if (group) {
|
|
1220
|
+
group.files.push(file);
|
|
1221
|
+
} else {
|
|
1222
|
+
canonicalPageGroups.set(pattern, {
|
|
1223
|
+
route,
|
|
1224
|
+
files: [file]
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
for (const [pattern, group] of canonicalPageGroups) {
|
|
1229
|
+
const componentFiles = group.files.filter((file) => !isFarmMarkdownPageFile(file));
|
|
1230
|
+
const markdownFiles = group.files.filter(isFarmMarkdownPageFile);
|
|
1231
|
+
if (componentFiles.length > 1) {
|
|
1232
|
+
throw new Error(
|
|
1233
|
+
`Duplicate page route "${pattern}". Found ${componentFiles.map((file) => path3.join(appDir, file)).join(" and ")}.`
|
|
1234
|
+
);
|
|
1235
|
+
}
|
|
1236
|
+
if (markdownFiles.length > 1) {
|
|
1237
|
+
throw new Error(
|
|
1238
|
+
`Duplicate markdown representation for page route "${pattern}". Found ${markdownFiles.map((file) => path3.join(appDir, file)).join(" and ")}.`
|
|
1239
|
+
);
|
|
1240
|
+
}
|
|
1241
|
+
const componentFile = componentFiles[0];
|
|
1242
|
+
const markdownFile = markdownFiles[0];
|
|
1243
|
+
const primaryFile = componentFile || markdownFile;
|
|
1244
|
+
if (!primaryFile) continue;
|
|
1245
|
+
const modulePath = path3.join(appDir, primaryFile);
|
|
1246
|
+
const existing = this.routes.get(pattern);
|
|
1247
|
+
if (existing?.sourceRoot === source.root) {
|
|
1248
|
+
throw new Error(
|
|
1249
|
+
`Duplicate page route "${pattern}". Found both ${existing.modulePath} and ${modulePath}.`
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
this.routes.set(pattern, {
|
|
1253
|
+
route: group.route,
|
|
1254
|
+
modulePath,
|
|
1255
|
+
...markdownFile ? {
|
|
1256
|
+
markdownSourcePath: path3.join(appDir, markdownFile)
|
|
1257
|
+
} : {},
|
|
1258
|
+
pattern,
|
|
1259
|
+
source: "file",
|
|
1260
|
+
sourceRoot: source.root
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1105
1263
|
for (const [kind, files, target] of [
|
|
1106
|
-
["page", pageFiles, this.routes],
|
|
1107
1264
|
["layout", layoutFiles, this.layouts],
|
|
1108
1265
|
["loading", loadingFiles, this.loadings],
|
|
1109
1266
|
["error", errorFiles, this.errors]
|
|
@@ -1127,6 +1284,32 @@ var _RouteManager = class _RouteManager {
|
|
|
1127
1284
|
});
|
|
1128
1285
|
}
|
|
1129
1286
|
}
|
|
1287
|
+
for (const file of [...pageFiles, ...slotDefaultFiles]) {
|
|
1288
|
+
const slot = parseRouteSlotFile(file);
|
|
1289
|
+
if (!slot) continue;
|
|
1290
|
+
const modulePath = path3.join(appDir, file);
|
|
1291
|
+
const pattern = this.createRoutePattern(slot.route);
|
|
1292
|
+
const ownerPattern = this.createRoutePattern(slot.ownerRoute);
|
|
1293
|
+
const key = `${ownerPattern}:${slot.name}:${slot.interception ? "intercept" : "slot"}:${slot.fallback ? "default" : pattern}`;
|
|
1294
|
+
const existing = this.routeSlots.get(key);
|
|
1295
|
+
if (existing?.sourceRoot === source.root) {
|
|
1296
|
+
throw new Error(
|
|
1297
|
+
`Duplicate route slot "${slot.name}" for "${pattern}". Found both ${existing.modulePath} and ${modulePath}.`
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
this.routeSlots.set(key, {
|
|
1301
|
+
route: slot.route,
|
|
1302
|
+
modulePath,
|
|
1303
|
+
pattern,
|
|
1304
|
+
source: "file",
|
|
1305
|
+
sourceRoot: source.root,
|
|
1306
|
+
name: slot.name,
|
|
1307
|
+
ownerPattern,
|
|
1308
|
+
interception: slot.interception,
|
|
1309
|
+
fallback: slot.fallback,
|
|
1310
|
+
containerId: createRouteSlotContainerId(slot.name, ownerPattern)
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1130
1313
|
for (const file of metadataImageFiles) {
|
|
1131
1314
|
const fileBase = path3.basename(file, path3.extname(file));
|
|
1132
1315
|
const kind = fileBase === "twitter-image" ? "twitter" : "opengraph";
|
|
@@ -1252,6 +1435,71 @@ var _RouteManager = class _RouteManager {
|
|
|
1252
1435
|
}
|
|
1253
1436
|
return matchingLayouts;
|
|
1254
1437
|
}
|
|
1438
|
+
findMatchingRouteSlots(pathname, interceptFrom) {
|
|
1439
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1440
|
+
for (const entry of this.routeSlots.values()) {
|
|
1441
|
+
if (!this.matchesRoutePrefix(pathname, entry.ownerPattern)) continue;
|
|
1442
|
+
const key = `${entry.ownerPattern}:${entry.name}`;
|
|
1443
|
+
const entries = groups.get(key) ?? [];
|
|
1444
|
+
entries.push(entry);
|
|
1445
|
+
groups.set(key, entries);
|
|
1446
|
+
}
|
|
1447
|
+
const normalizedFrom = interceptFrom ? this.toRoutePathname(new URL(interceptFrom, "http://farm.local").pathname) : void 0;
|
|
1448
|
+
const matches = [];
|
|
1449
|
+
for (const entries of groups.values()) {
|
|
1450
|
+
const candidates = entries.filter((entry) => !entry.fallback).filter(
|
|
1451
|
+
(entry) => !entry.interception || normalizedFrom !== void 0 && this.matchesRoutePrefix(normalizedFrom, entry.ownerPattern)
|
|
1452
|
+
).map((entry) => ({
|
|
1453
|
+
entry,
|
|
1454
|
+
match: matchRoute(pathname, entry.route.segments)
|
|
1455
|
+
})).filter((candidate) => candidate.match.matches).sort((left, right) => {
|
|
1456
|
+
if (left.entry.interception !== right.entry.interception) {
|
|
1457
|
+
return left.entry.interception ? -1 : 1;
|
|
1458
|
+
}
|
|
1459
|
+
return routeSpecificity(right.entry) - routeSpecificity(left.entry);
|
|
1460
|
+
});
|
|
1461
|
+
const selected = candidates[0];
|
|
1462
|
+
if (selected) {
|
|
1463
|
+
matches.push({
|
|
1464
|
+
name: selected.entry.name,
|
|
1465
|
+
ownerPattern: selected.entry.ownerPattern,
|
|
1466
|
+
containerId: selected.entry.containerId,
|
|
1467
|
+
interception: selected.entry.interception,
|
|
1468
|
+
fallback: false,
|
|
1469
|
+
route: selected.entry,
|
|
1470
|
+
params: selected.match.params
|
|
1471
|
+
});
|
|
1472
|
+
continue;
|
|
1473
|
+
}
|
|
1474
|
+
const fallback = entries.find((entry) => entry.fallback);
|
|
1475
|
+
if (fallback) {
|
|
1476
|
+
matches.push({
|
|
1477
|
+
name: fallback.name,
|
|
1478
|
+
ownerPattern: fallback.ownerPattern,
|
|
1479
|
+
containerId: fallback.containerId,
|
|
1480
|
+
interception: false,
|
|
1481
|
+
fallback: true,
|
|
1482
|
+
route: fallback,
|
|
1483
|
+
params: {}
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
return matches.sort((left, right) => {
|
|
1488
|
+
const ownerDifference = left.route.route.segments.length - right.route.route.segments.length;
|
|
1489
|
+
return ownerDifference || left.name.localeCompare(right.name);
|
|
1490
|
+
});
|
|
1491
|
+
}
|
|
1492
|
+
matchesRoutePrefix(pathname, pattern) {
|
|
1493
|
+
if (pattern === "/") return true;
|
|
1494
|
+
const patternSegments = parseRoutePath(`${pattern}/page.tsx`).segments;
|
|
1495
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
1496
|
+
if (patternSegments.length > pathSegments.length) return false;
|
|
1497
|
+
for (let index = 0; index < patternSegments.length; index++) {
|
|
1498
|
+
const segment = patternSegments[index];
|
|
1499
|
+
if (!segment.isDynamic && segment.segment !== pathSegments[index]) return false;
|
|
1500
|
+
}
|
|
1501
|
+
return true;
|
|
1502
|
+
}
|
|
1255
1503
|
findNearestBoundary(pathname, boundaries) {
|
|
1256
1504
|
const normalizedPath = pathname === "/" ? "/" : pathname.replace(/\/$/, "");
|
|
1257
1505
|
const pathSegments = normalizedPath.split("/").filter(Boolean);
|
|
@@ -1447,8 +1695,1052 @@ __name(safeGlobFiles, "safeGlobFiles");
|
|
|
1447
1695
|
import React from "react";
|
|
1448
1696
|
import { renderToPipeableStream, renderToStaticMarkup } from "react-dom/server";
|
|
1449
1697
|
import * as fs2 from "fs";
|
|
1450
|
-
import * as
|
|
1698
|
+
import * as path5 from "path";
|
|
1451
1699
|
import { Writable } from "stream";
|
|
1700
|
+
|
|
1701
|
+
// src/font-vite.ts
|
|
1702
|
+
import { createHash as createHash2, timingSafeEqual } from "crypto";
|
|
1703
|
+
import { existsSync } from "fs";
|
|
1704
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
1705
|
+
import path4 from "path";
|
|
1706
|
+
import { createRequire } from "module";
|
|
1707
|
+
import { pathToFileURL } from "url";
|
|
1708
|
+
var FONT_IMPORTS = /* @__PURE__ */ new Set(["@farm.js/core", "@farm.js/core/font"]);
|
|
1709
|
+
var FONT_FUNCTIONS = /* @__PURE__ */ new Set(["localFont", "remoteFont"]);
|
|
1710
|
+
var FONT_CSS_PREFIX = "\0farm:font-css:";
|
|
1711
|
+
var FONT_RUNTIME_ID = "\0farm:font-runtime";
|
|
1712
|
+
var PUBLIC_FONT_RUNTIME_ID = "virtual:farm-font-runtime";
|
|
1713
|
+
var PRELOAD_HEADER_MARKER = "__FARM_FONT_PRELOAD_HEADER__";
|
|
1714
|
+
var FONT_SECTION_START = "/* farm-fonts:start */";
|
|
1715
|
+
var FONT_SECTION_END = "/* farm-fonts:end */";
|
|
1716
|
+
var MODULE_EXTENSION_RE = /\.[cm]?[jt]sx?$/;
|
|
1717
|
+
var FONT_EXTENSION_RE = /\.(woff2?|ttf|otf)$/i;
|
|
1718
|
+
var MAX_REMOTE_FONT_BYTES = 20 * 1024 * 1024;
|
|
1719
|
+
var FONT_REGISTRIES_KEY = /* @__PURE__ */ Symbol.for("farm.fontRegistries");
|
|
1720
|
+
var FONT_REMOTE_BYTES_KEY = /* @__PURE__ */ Symbol.for("farm.fontRemoteBytes");
|
|
1721
|
+
var registries = getGlobalMap(FONT_REGISTRIES_KEY);
|
|
1722
|
+
var remoteBytes = getGlobalMap(FONT_REMOTE_BYTES_KEY);
|
|
1723
|
+
function farmFontImportsPlugin(options = {}) {
|
|
1724
|
+
let root = normalizeRoot(options.root || process.cwd());
|
|
1725
|
+
let production = process.env.NODE_ENV === "production";
|
|
1726
|
+
let registry = getOrCreateRegistry(root, options.basePath, options.publicDir);
|
|
1727
|
+
const updateRoot = /* @__PURE__ */ __name((nextRoot, basePath, publicDir) => {
|
|
1728
|
+
const normalized = normalizeRoot(nextRoot);
|
|
1729
|
+
root = normalized;
|
|
1730
|
+
registry = getOrCreateRegistry(root, basePath, publicDir);
|
|
1731
|
+
}, "updateRoot");
|
|
1732
|
+
return {
|
|
1733
|
+
name: "farm:font-imports",
|
|
1734
|
+
enforce: "post",
|
|
1735
|
+
configResolved(config) {
|
|
1736
|
+
production = config.command === "build";
|
|
1737
|
+
updateRoot(
|
|
1738
|
+
config.root,
|
|
1739
|
+
options.basePath || config.base,
|
|
1740
|
+
options.publicDir === void 0 ? config.publicDir : options.publicDir
|
|
1741
|
+
);
|
|
1742
|
+
registry.production = production;
|
|
1743
|
+
},
|
|
1744
|
+
configureServer(server) {
|
|
1745
|
+
updateRoot(
|
|
1746
|
+
server.config.root,
|
|
1747
|
+
options.basePath || server.config.base,
|
|
1748
|
+
options.publicDir === void 0 ? server.config.publicDir : options.publicDir
|
|
1749
|
+
);
|
|
1750
|
+
registry.production = false;
|
|
1751
|
+
server.middlewares.use(async (req, res, next) => {
|
|
1752
|
+
const pathname = new URL(req.url || "/", "http://farm.local").pathname;
|
|
1753
|
+
if (pathname === "/@farm/fonts.css") {
|
|
1754
|
+
res.statusCode = 200;
|
|
1755
|
+
res.setHeader("Content-Type", "text/css; charset=utf-8");
|
|
1756
|
+
res.setHeader("Cache-Control", "no-store");
|
|
1757
|
+
res.end(registry.renderCss(false));
|
|
1758
|
+
return;
|
|
1759
|
+
}
|
|
1760
|
+
const resource = registry.getDevResource(pathname);
|
|
1761
|
+
if (!resource?.bytes) {
|
|
1762
|
+
next();
|
|
1763
|
+
return;
|
|
1764
|
+
}
|
|
1765
|
+
res.statusCode = 200;
|
|
1766
|
+
res.setHeader("Content-Type", fontContentType(resource.extension));
|
|
1767
|
+
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
1768
|
+
res.end(resource.bytes);
|
|
1769
|
+
});
|
|
1770
|
+
},
|
|
1771
|
+
resolveId(id) {
|
|
1772
|
+
if (id === PUBLIC_FONT_RUNTIME_ID || id === FONT_RUNTIME_ID) return FONT_RUNTIME_ID;
|
|
1773
|
+
if (id.startsWith("virtual:farm-font-css/")) {
|
|
1774
|
+
return `${FONT_CSS_PREFIX}${id.slice("virtual:farm-font-css/".length)}`;
|
|
1775
|
+
}
|
|
1776
|
+
if (id.startsWith(FONT_CSS_PREFIX)) return id;
|
|
1777
|
+
return null;
|
|
1778
|
+
},
|
|
1779
|
+
load(id) {
|
|
1780
|
+
if (id === FONT_RUNTIME_ID) {
|
|
1781
|
+
return `export const farmFontPreloadHeader = decodeURIComponent(${JSON.stringify(PRELOAD_HEADER_MARKER)});`;
|
|
1782
|
+
}
|
|
1783
|
+
if (!id.startsWith(FONT_CSS_PREFIX)) return null;
|
|
1784
|
+
return registry.renderFontCss(
|
|
1785
|
+
id.slice(FONT_CSS_PREFIX.length).replace(/\.css$/, ""),
|
|
1786
|
+
production
|
|
1787
|
+
);
|
|
1788
|
+
},
|
|
1789
|
+
async transform(code, id) {
|
|
1790
|
+
const result = await transformFarmFontCalls({
|
|
1791
|
+
code,
|
|
1792
|
+
id,
|
|
1793
|
+
root,
|
|
1794
|
+
production,
|
|
1795
|
+
parse: /* @__PURE__ */ __name((source) => this.parse(source), "parse"),
|
|
1796
|
+
register: /* @__PURE__ */ __name((moduleId, calls) => registry.register(moduleId, calls, production), "register")
|
|
1797
|
+
});
|
|
1798
|
+
if (!result) registry.clearModule(id.split("?", 1)[0]);
|
|
1799
|
+
return result ? { code: result.code, map: null } : null;
|
|
1800
|
+
},
|
|
1801
|
+
async generateBundle(_options, bundle) {
|
|
1802
|
+
registry.emitAssets(this, bundle);
|
|
1803
|
+
}
|
|
1804
|
+
};
|
|
1805
|
+
}
|
|
1806
|
+
__name(farmFontImportsPlugin, "farmFontImportsPlugin");
|
|
1807
|
+
async function transformFarmFontCalls(options) {
|
|
1808
|
+
const cleanId = options.id.split("?", 1)[0];
|
|
1809
|
+
if (!MODULE_EXTENSION_RE.test(cleanId) || /\.d\.[cm]?ts$/.test(cleanId) || !containsFontFunction(options.code)) {
|
|
1810
|
+
return null;
|
|
1811
|
+
}
|
|
1812
|
+
const ast = options.parse(options.code);
|
|
1813
|
+
const bindings = findFontBindings(ast);
|
|
1814
|
+
if (bindings.named.size === 0 && bindings.namespaces.size === 0) return null;
|
|
1815
|
+
const calls = findFontCalls(ast, bindings);
|
|
1816
|
+
if (calls.length === 0) return null;
|
|
1817
|
+
validateFontBindingReferences(ast, calls, cleanId);
|
|
1818
|
+
const registeredCalls = calls.map((call) => ({
|
|
1819
|
+
kind: call.kind,
|
|
1820
|
+
options: readFontOptions(options.code, cleanId, call)
|
|
1821
|
+
}));
|
|
1822
|
+
const fonts = await options.register(cleanId, registeredCalls);
|
|
1823
|
+
const replacements = calls.map((call, index) => ({
|
|
1824
|
+
start: call.node.start,
|
|
1825
|
+
end: call.node.end,
|
|
1826
|
+
code: serializeFontResult(fonts[index])
|
|
1827
|
+
}));
|
|
1828
|
+
replacements.push(
|
|
1829
|
+
...createFontImportReplacements(
|
|
1830
|
+
options.code,
|
|
1831
|
+
ast,
|
|
1832
|
+
new Set(calls.map((call) => call.binding).filter((value) => Boolean(value)))
|
|
1833
|
+
)
|
|
1834
|
+
);
|
|
1835
|
+
const imports = options.production ? "" : Array.from(new Set(fonts.map((font) => font.id))).map((id) => `import ${JSON.stringify(`virtual:farm-font-css/${id}.css`)};`).join("\n");
|
|
1836
|
+
return {
|
|
1837
|
+
code: `${applyReplacements(options.code, replacements)}
|
|
1838
|
+
${imports}
|
|
1839
|
+
`,
|
|
1840
|
+
fonts
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
__name(transformFarmFontCalls, "transformFarmFontCalls");
|
|
1844
|
+
function renderFarmFontDevHead(root) {
|
|
1845
|
+
const registry = registries.get(normalizeRoot(root));
|
|
1846
|
+
if (!registry || registry.production || registry.size === 0) return "";
|
|
1847
|
+
return `${registry.renderPreloadTags(false)}
|
|
1848
|
+
<link rel="stylesheet" href="/@farm/fonts.css">`;
|
|
1849
|
+
}
|
|
1850
|
+
__name(renderFarmFontDevHead, "renderFarmFontDevHead");
|
|
1851
|
+
var _FarmFontRegistry = class _FarmFontRegistry {
|
|
1852
|
+
constructor(root, basePath = "/", publicDir) {
|
|
1853
|
+
this.production = false;
|
|
1854
|
+
this.modules = /* @__PURE__ */ new Map();
|
|
1855
|
+
this.definitions = /* @__PURE__ */ new Map();
|
|
1856
|
+
this.resources = /* @__PURE__ */ new Map();
|
|
1857
|
+
this.root = root;
|
|
1858
|
+
this.basePath = normalizeBasePath(basePath);
|
|
1859
|
+
this.publicDir = normalizePublicDir(root, publicDir);
|
|
1860
|
+
}
|
|
1861
|
+
get size() {
|
|
1862
|
+
return this.getDefinitions().length;
|
|
1863
|
+
}
|
|
1864
|
+
async register(moduleId, calls, production) {
|
|
1865
|
+
const definitions = [];
|
|
1866
|
+
for (const call of calls) {
|
|
1867
|
+
definitions.push(await this.createDefinition(moduleId, call.kind, call.options, production));
|
|
1868
|
+
}
|
|
1869
|
+
this.modules.set(moduleId, definitions);
|
|
1870
|
+
for (const definition of definitions) this.definitions.set(definition.id, definition);
|
|
1871
|
+
return definitions;
|
|
1872
|
+
}
|
|
1873
|
+
clearModule(moduleId) {
|
|
1874
|
+
this.modules.delete(moduleId);
|
|
1875
|
+
}
|
|
1876
|
+
renderFontCss(id, production) {
|
|
1877
|
+
const definition = this.definitions.get(id);
|
|
1878
|
+
return definition ? renderFontDefinitionCss(definition, production, this.basePath) : "";
|
|
1879
|
+
}
|
|
1880
|
+
renderCss(production) {
|
|
1881
|
+
const css = this.getDefinitions().map((definition) => renderFontDefinitionCss(definition, production, this.basePath)).join("\n\n");
|
|
1882
|
+
return css ? `${FONT_SECTION_START}
|
|
1883
|
+
${css}
|
|
1884
|
+
${FONT_SECTION_END}
|
|
1885
|
+
` : "";
|
|
1886
|
+
}
|
|
1887
|
+
renderPreloadHeader(production) {
|
|
1888
|
+
return this.getPreloadResources(production).map(
|
|
1889
|
+
({ url, resource }) => `<${url}>; rel=preload; as=font; type=${fontContentType(resource.extension)}; crossorigin`
|
|
1890
|
+
).join(", ");
|
|
1891
|
+
}
|
|
1892
|
+
renderPreloadTags(production) {
|
|
1893
|
+
return this.getPreloadResources(production).map(
|
|
1894
|
+
({ url, resource }) => `<link rel="preload" href="${escapeHtmlAttribute(url)}" as="font" type="${fontContentType(resource.extension)}" crossorigin>`
|
|
1895
|
+
).join("\n ");
|
|
1896
|
+
}
|
|
1897
|
+
getDevResource(pathname) {
|
|
1898
|
+
for (const resource of this.getActiveResources()) {
|
|
1899
|
+
if (resource.bytes && resourceUrl(resource, false, this.basePath) === pathname) {
|
|
1900
|
+
return resource;
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
return void 0;
|
|
1904
|
+
}
|
|
1905
|
+
emitAssets(context, bundle) {
|
|
1906
|
+
for (const resource of this.getActiveResources()) {
|
|
1907
|
+
if (!resource.bytes || !resource.outputFileName) continue;
|
|
1908
|
+
if (bundle[resource.outputFileName]) continue;
|
|
1909
|
+
context.emitFile({
|
|
1910
|
+
type: "asset",
|
|
1911
|
+
fileName: resource.outputFileName,
|
|
1912
|
+
source: resource.bytes
|
|
1913
|
+
});
|
|
1914
|
+
}
|
|
1915
|
+
const css = this.renderCss(true);
|
|
1916
|
+
if (css) {
|
|
1917
|
+
const cssAssets = Object.values(bundle).filter(
|
|
1918
|
+
(entry) => entry.type === "asset" && entry.fileName.endsWith(".css")
|
|
1919
|
+
);
|
|
1920
|
+
const clientCss = cssAssets.find(
|
|
1921
|
+
(entry) => entry.type === "asset" && entry.fileName === "farm-client.css"
|
|
1922
|
+
) ?? (cssAssets.length === 1 ? cssAssets[0] : void 0);
|
|
1923
|
+
if (clientCss) {
|
|
1924
|
+
clientCss.source = replaceFontSection(assetSourceToString(clientCss.source), css);
|
|
1925
|
+
} else if (!bundle["farm-fonts.css"]) {
|
|
1926
|
+
context.emitFile({
|
|
1927
|
+
type: "asset",
|
|
1928
|
+
fileName: "farm-fonts.css",
|
|
1929
|
+
source: css
|
|
1930
|
+
});
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
const preloadHeader = encodeURIComponent(this.renderPreloadHeader(true));
|
|
1934
|
+
for (const entry of Object.values(bundle)) {
|
|
1935
|
+
if (entry.type === "chunk" && entry.code.includes(PRELOAD_HEADER_MARKER)) {
|
|
1936
|
+
entry.code = entry.code.split(PRELOAD_HEADER_MARKER).join(preloadHeader);
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
getDefinitions() {
|
|
1941
|
+
const active = /* @__PURE__ */ new Map();
|
|
1942
|
+
for (const definitions of this.modules.values()) {
|
|
1943
|
+
for (const definition of definitions) active.set(definition.id, definition);
|
|
1944
|
+
}
|
|
1945
|
+
return Array.from(active.values()).sort((left, right) => left.id.localeCompare(right.id));
|
|
1946
|
+
}
|
|
1947
|
+
getActiveResources() {
|
|
1948
|
+
const active = /* @__PURE__ */ new Set();
|
|
1949
|
+
for (const definition of this.getDefinitions()) {
|
|
1950
|
+
for (const source of definition.sources) active.add(source.resource);
|
|
1951
|
+
}
|
|
1952
|
+
return Array.from(active);
|
|
1953
|
+
}
|
|
1954
|
+
getPreloadResources(production) {
|
|
1955
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1956
|
+
const resources = [];
|
|
1957
|
+
for (const definition of this.getDefinitions()) {
|
|
1958
|
+
if (!definition.preload) continue;
|
|
1959
|
+
for (const source of definition.sources) {
|
|
1960
|
+
const url = resourceUrl(source.resource, production, this.basePath);
|
|
1961
|
+
if (seen.has(url)) continue;
|
|
1962
|
+
seen.add(url);
|
|
1963
|
+
resources.push({ url, resource: source.resource });
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
return resources;
|
|
1967
|
+
}
|
|
1968
|
+
async createDefinition(moduleId, kind, raw, production) {
|
|
1969
|
+
validateOptionKeys(moduleId, kind, raw);
|
|
1970
|
+
const family = requireString(raw.family, moduleId, `${kind}() family`);
|
|
1971
|
+
const display = raw.display ?? "swap";
|
|
1972
|
+
if (!["auto", "block", "swap", "fallback", "optional"].includes(display)) {
|
|
1973
|
+
throw fontError(moduleId, `invalid font-display value ${JSON.stringify(display)}`);
|
|
1974
|
+
}
|
|
1975
|
+
const variable = optionalString(raw.variable, moduleId, `${kind}() variable`);
|
|
1976
|
+
if (variable && !/^--[A-Za-z_][\w-]*$/.test(variable)) {
|
|
1977
|
+
throw fontError(moduleId, `font variable must be a CSS custom property such as --font-sans`);
|
|
1978
|
+
}
|
|
1979
|
+
const fallback = readStringArray(raw.fallback, moduleId, `${kind}() fallback`);
|
|
1980
|
+
const defaultWeight = optionalWeight(raw.weight, moduleId);
|
|
1981
|
+
const defaultStyle = optionalCssDescriptor(raw.style, moduleId, "style") || "normal";
|
|
1982
|
+
const sources = readSources(raw.src, moduleId, kind, defaultWeight, defaultStyle);
|
|
1983
|
+
const strategy = kind === "remoteFont" ? raw.strategy ?? "self-host" : "self-host";
|
|
1984
|
+
if (strategy !== "self-host" && strategy !== "external") {
|
|
1985
|
+
throw fontError(moduleId, `remoteFont() strategy must be "self-host" or "external"`);
|
|
1986
|
+
}
|
|
1987
|
+
const integrity = optionalString(raw.integrity, moduleId, `${kind}() integrity`);
|
|
1988
|
+
const normalizedSources = [];
|
|
1989
|
+
for (const source of sources) {
|
|
1990
|
+
const resource = await this.resolveResource({
|
|
1991
|
+
kind,
|
|
1992
|
+
moduleId,
|
|
1993
|
+
source: source.path,
|
|
1994
|
+
strategy,
|
|
1995
|
+
integrity: source.integrity ?? integrity,
|
|
1996
|
+
production
|
|
1997
|
+
});
|
|
1998
|
+
normalizedSources.push({
|
|
1999
|
+
source: source.path,
|
|
2000
|
+
weight: String(source.weight ?? defaultWeight ?? "400"),
|
|
2001
|
+
style: source.style || defaultStyle,
|
|
2002
|
+
unicodeRange: source.unicodeRange,
|
|
2003
|
+
resource
|
|
2004
|
+
});
|
|
2005
|
+
}
|
|
2006
|
+
const identity = JSON.stringify({
|
|
2007
|
+
family,
|
|
2008
|
+
display,
|
|
2009
|
+
variable,
|
|
2010
|
+
fallback,
|
|
2011
|
+
preload: raw.preload !== false,
|
|
2012
|
+
sources: normalizedSources.map((source) => ({
|
|
2013
|
+
hash: source.resource.hash,
|
|
2014
|
+
url: source.resource.publicUrl,
|
|
2015
|
+
weight: source.weight,
|
|
2016
|
+
style: source.style,
|
|
2017
|
+
unicodeRange: source.unicodeRange
|
|
2018
|
+
}))
|
|
2019
|
+
});
|
|
2020
|
+
const id = createHash2("sha256").update(identity).digest("hex").slice(0, 10);
|
|
2021
|
+
return {
|
|
2022
|
+
id,
|
|
2023
|
+
family,
|
|
2024
|
+
className: `farm-font-${id}`,
|
|
2025
|
+
variableClassName: variable ? `farm-font-variable-${id}` : "",
|
|
2026
|
+
variable,
|
|
2027
|
+
fallback,
|
|
2028
|
+
display,
|
|
2029
|
+
preload: raw.preload !== false,
|
|
2030
|
+
weight: defaultWeight,
|
|
2031
|
+
style: raw.style === void 0 ? void 0 : defaultStyle,
|
|
2032
|
+
sources: normalizedSources
|
|
2033
|
+
};
|
|
2034
|
+
}
|
|
2035
|
+
async resolveResource(input) {
|
|
2036
|
+
if (input.kind === "remoteFont") {
|
|
2037
|
+
let url;
|
|
2038
|
+
try {
|
|
2039
|
+
url = new URL(input.source);
|
|
2040
|
+
} catch {
|
|
2041
|
+
throw fontError(input.moduleId, `remoteFont() source must be an absolute HTTPS URL`);
|
|
2042
|
+
}
|
|
2043
|
+
if (url.protocol !== "https:") {
|
|
2044
|
+
throw fontError(input.moduleId, `remoteFont() only accepts HTTPS URLs`);
|
|
2045
|
+
}
|
|
2046
|
+
const extension = extensionFromPath(url.pathname);
|
|
2047
|
+
if (input.strategy === "external") {
|
|
2048
|
+
const hash = createHash2("sha256").update(url.href).digest("hex").slice(0, 12);
|
|
2049
|
+
const resource = {
|
|
2050
|
+
extension,
|
|
2051
|
+
format: fontFormat(extension),
|
|
2052
|
+
hash,
|
|
2053
|
+
publicUrl: url.href
|
|
2054
|
+
};
|
|
2055
|
+
this.resources.set(`external:${url.href}`, resource);
|
|
2056
|
+
return resource;
|
|
2057
|
+
}
|
|
2058
|
+
const bytes2 = await fetchRemoteFont(url, input.integrity);
|
|
2059
|
+
return this.createSelfHostedResource(bytes2, extension, path4.basename(url.pathname));
|
|
2060
|
+
}
|
|
2061
|
+
if (input.source.startsWith("/")) {
|
|
2062
|
+
return this.createPublicResource(input.moduleId, input.source);
|
|
2063
|
+
}
|
|
2064
|
+
const resolvedPath = resolveLocalFontPath(input.source, input.moduleId, this.root);
|
|
2065
|
+
if (!FONT_EXTENSION_RE.test(resolvedPath)) {
|
|
2066
|
+
throw fontError(
|
|
2067
|
+
input.moduleId,
|
|
2068
|
+
`unsupported local font file ${JSON.stringify(input.source)}`
|
|
2069
|
+
);
|
|
2070
|
+
}
|
|
2071
|
+
let bytes;
|
|
2072
|
+
try {
|
|
2073
|
+
bytes = await readFile3(resolvedPath);
|
|
2074
|
+
} catch (error) {
|
|
2075
|
+
throw fontError(
|
|
2076
|
+
input.moduleId,
|
|
2077
|
+
`could not read ${JSON.stringify(input.source)}: ${error.message}`
|
|
2078
|
+
);
|
|
2079
|
+
}
|
|
2080
|
+
return this.createSelfHostedResource(
|
|
2081
|
+
bytes,
|
|
2082
|
+
path4.extname(resolvedPath),
|
|
2083
|
+
path4.basename(resolvedPath)
|
|
2084
|
+
);
|
|
2085
|
+
}
|
|
2086
|
+
async createPublicResource(moduleId, source) {
|
|
2087
|
+
if (!this.publicDir) {
|
|
2088
|
+
throw fontError(
|
|
2089
|
+
moduleId,
|
|
2090
|
+
`cannot resolve ${JSON.stringify(source)} because publicDir is disabled`
|
|
2091
|
+
);
|
|
2092
|
+
}
|
|
2093
|
+
const publicPath = normalizePublicFontPath(source, moduleId);
|
|
2094
|
+
const resolvedPath = path4.resolve(this.publicDir, `.${publicPath}`);
|
|
2095
|
+
if (!isPathInside(this.publicDir, resolvedPath)) {
|
|
2096
|
+
throw fontError(moduleId, `public font path must stay inside publicDir`);
|
|
2097
|
+
}
|
|
2098
|
+
if (!FONT_EXTENSION_RE.test(resolvedPath)) {
|
|
2099
|
+
throw fontError(moduleId, `unsupported public font file ${JSON.stringify(source)}`);
|
|
2100
|
+
}
|
|
2101
|
+
let bytes;
|
|
2102
|
+
try {
|
|
2103
|
+
bytes = await readFile3(resolvedPath);
|
|
2104
|
+
} catch (error) {
|
|
2105
|
+
throw fontError(
|
|
2106
|
+
moduleId,
|
|
2107
|
+
`could not read ${JSON.stringify(source)} from publicDir: ${error.message}`
|
|
2108
|
+
);
|
|
2109
|
+
}
|
|
2110
|
+
const extension = path4.extname(resolvedPath).toLowerCase();
|
|
2111
|
+
const hash = createHash2("sha256").update(bytes).digest("hex").slice(0, 12);
|
|
2112
|
+
const resource = {
|
|
2113
|
+
extension,
|
|
2114
|
+
format: fontFormat(extension),
|
|
2115
|
+
hash,
|
|
2116
|
+
publicPath,
|
|
2117
|
+
publicUrl: ""
|
|
2118
|
+
};
|
|
2119
|
+
this.resources.set(`public:${publicPath}`, resource);
|
|
2120
|
+
return resource;
|
|
2121
|
+
}
|
|
2122
|
+
createSelfHostedResource(bytes, extension, fileName) {
|
|
2123
|
+
const normalizedExtension = extension.toLowerCase();
|
|
2124
|
+
const hash = createHash2("sha256").update(bytes).digest("hex").slice(0, 12);
|
|
2125
|
+
const baseName = sanitizeFileName(path4.basename(fileName, extension)) || "font";
|
|
2126
|
+
const outputFileName = `assets/fonts/${baseName}-${hash}${normalizedExtension}`;
|
|
2127
|
+
const key = `${hash}${normalizedExtension}`;
|
|
2128
|
+
const existing = this.resources.get(key);
|
|
2129
|
+
if (existing) return existing;
|
|
2130
|
+
const resource = {
|
|
2131
|
+
bytes,
|
|
2132
|
+
extension: normalizedExtension,
|
|
2133
|
+
format: fontFormat(normalizedExtension),
|
|
2134
|
+
hash,
|
|
2135
|
+
outputFileName,
|
|
2136
|
+
publicUrl: ""
|
|
2137
|
+
};
|
|
2138
|
+
this.resources.set(key, resource);
|
|
2139
|
+
return resource;
|
|
2140
|
+
}
|
|
2141
|
+
};
|
|
2142
|
+
__name(_FarmFontRegistry, "FarmFontRegistry");
|
|
2143
|
+
var FarmFontRegistry = _FarmFontRegistry;
|
|
2144
|
+
function findFontBindings(ast) {
|
|
2145
|
+
const named = /* @__PURE__ */ new Map();
|
|
2146
|
+
const namespaces = /* @__PURE__ */ new Set();
|
|
2147
|
+
const body = Array.isArray(ast.body) ? ast.body : [];
|
|
2148
|
+
for (const statement of body) {
|
|
2149
|
+
if (!isAstNode(statement) || statement.type !== "ImportDeclaration") continue;
|
|
2150
|
+
const source = isAstNode(statement.source) ? statement.source.value : void 0;
|
|
2151
|
+
if (typeof source !== "string" || !FONT_IMPORTS.has(source)) continue;
|
|
2152
|
+
const specifiers = Array.isArray(statement.specifiers) ? statement.specifiers : [];
|
|
2153
|
+
for (const specifier of specifiers) {
|
|
2154
|
+
if (!isAstNode(specifier) || !isAstNode(specifier.local)) continue;
|
|
2155
|
+
const localName = specifier.local.name;
|
|
2156
|
+
if (typeof localName !== "string") continue;
|
|
2157
|
+
if (specifier.type === "ImportNamespaceSpecifier") {
|
|
2158
|
+
namespaces.add(localName);
|
|
2159
|
+
continue;
|
|
2160
|
+
}
|
|
2161
|
+
if (specifier.type !== "ImportSpecifier" || !isAstNode(specifier.imported)) continue;
|
|
2162
|
+
const importedName = specifier.imported.name ?? specifier.imported.value;
|
|
2163
|
+
if (isFontLoaderKind(importedName)) named.set(localName, importedName);
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
return { named, namespaces };
|
|
2167
|
+
}
|
|
2168
|
+
__name(findFontBindings, "findFontBindings");
|
|
2169
|
+
function findFontCalls(ast, bindings) {
|
|
2170
|
+
const calls = [];
|
|
2171
|
+
walkAst(ast, (node, ancestors) => {
|
|
2172
|
+
if (node.type !== "CallExpression" || !isAstNode(node.callee)) return;
|
|
2173
|
+
let kind;
|
|
2174
|
+
if (node.callee.type === "Identifier" && typeof node.callee.name === "string") {
|
|
2175
|
+
kind = bindings.named.get(node.callee.name);
|
|
2176
|
+
if (kind) calls.push({ kind, binding: node.callee.name, node, ancestors });
|
|
2177
|
+
} else if (node.callee.type === "MemberExpression" && node.callee.computed !== true && isAstNode(node.callee.object) && isAstNode(node.callee.property) && node.callee.object.type === "Identifier" && node.callee.property.type === "Identifier" && typeof node.callee.object.name === "string" && typeof node.callee.property.name === "string" && bindings.namespaces.has(node.callee.object.name) && isFontLoaderKind(node.callee.property.name)) {
|
|
2178
|
+
kind = node.callee.property.name;
|
|
2179
|
+
}
|
|
2180
|
+
if (kind && node.callee.type !== "Identifier") calls.push({ kind, node, ancestors });
|
|
2181
|
+
});
|
|
2182
|
+
return calls;
|
|
2183
|
+
}
|
|
2184
|
+
__name(findFontCalls, "findFontCalls");
|
|
2185
|
+
function validateFontBindingReferences(ast, calls, id) {
|
|
2186
|
+
const calledBindings = new Set(
|
|
2187
|
+
calls.map((call) => call.binding).filter((binding) => Boolean(binding))
|
|
2188
|
+
);
|
|
2189
|
+
const transformedCallees = new Set(
|
|
2190
|
+
calls.flatMap((call) => {
|
|
2191
|
+
const callee = call.node.callee;
|
|
2192
|
+
return call.binding && isAstNode(callee) ? [`${callee.start}:${callee.end}`] : [];
|
|
2193
|
+
})
|
|
2194
|
+
);
|
|
2195
|
+
walkAst(ast, (node, ancestors) => {
|
|
2196
|
+
if (node.type !== "Identifier" || typeof node.name !== "string" || !calledBindings.has(node.name)) {
|
|
2197
|
+
return;
|
|
2198
|
+
}
|
|
2199
|
+
const parent = ancestors.at(-1);
|
|
2200
|
+
if (!parent || isNonReferenceIdentifier(node, parent)) return;
|
|
2201
|
+
if (transformedCallees.has(`${node.start}:${node.end}`)) return;
|
|
2202
|
+
throw fontError(
|
|
2203
|
+
id,
|
|
2204
|
+
`${node.name} can only be referenced by statically compiled font declarations`
|
|
2205
|
+
);
|
|
2206
|
+
});
|
|
2207
|
+
}
|
|
2208
|
+
__name(validateFontBindingReferences, "validateFontBindingReferences");
|
|
2209
|
+
function isNonReferenceIdentifier(node, parent) {
|
|
2210
|
+
if (parent.type === "ImportSpecifier") return true;
|
|
2211
|
+
if ((parent.type === "MemberExpression" || parent.type === "OptionalMemberExpression") && parent.property === node && parent.computed !== true) {
|
|
2212
|
+
return true;
|
|
2213
|
+
}
|
|
2214
|
+
if ((parent.type === "Property" || parent.type === "PropertyDefinition") && parent.key === node && parent.computed !== true && parent.shorthand !== true) {
|
|
2215
|
+
return true;
|
|
2216
|
+
}
|
|
2217
|
+
return false;
|
|
2218
|
+
}
|
|
2219
|
+
__name(isNonReferenceIdentifier, "isNonReferenceIdentifier");
|
|
2220
|
+
function createFontImportReplacements(code, ast, calledBindings) {
|
|
2221
|
+
if (calledBindings.size === 0) return [];
|
|
2222
|
+
const replacements = [];
|
|
2223
|
+
const body = Array.isArray(ast.body) ? ast.body : [];
|
|
2224
|
+
for (const statement of body) {
|
|
2225
|
+
if (!isAstNode(statement) || statement.type !== "ImportDeclaration") continue;
|
|
2226
|
+
const source = isAstNode(statement.source) ? statement.source.value : void 0;
|
|
2227
|
+
if (typeof source !== "string" || !FONT_IMPORTS.has(source)) continue;
|
|
2228
|
+
const specifiers = (Array.isArray(statement.specifiers) ? statement.specifiers : []).filter(
|
|
2229
|
+
isAstNode
|
|
2230
|
+
);
|
|
2231
|
+
const retained = specifiers.filter((specifier) => {
|
|
2232
|
+
if (specifier.type !== "ImportSpecifier" || !isAstNode(specifier.local)) return true;
|
|
2233
|
+
return typeof specifier.local.name !== "string" || !calledBindings.has(specifier.local.name);
|
|
2234
|
+
});
|
|
2235
|
+
if (retained.length === specifiers.length) continue;
|
|
2236
|
+
replacements.push({
|
|
2237
|
+
start: statement.start,
|
|
2238
|
+
end: statement.end,
|
|
2239
|
+
code: renderImportDeclaration(code, source, retained)
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
return replacements;
|
|
2243
|
+
}
|
|
2244
|
+
__name(createFontImportReplacements, "createFontImportReplacements");
|
|
2245
|
+
function renderImportDeclaration(code, source, specifiers) {
|
|
2246
|
+
if (specifiers.length === 0) return "";
|
|
2247
|
+
const defaultSpecifier = specifiers.find(
|
|
2248
|
+
(specifier) => specifier.type === "ImportDefaultSpecifier"
|
|
2249
|
+
);
|
|
2250
|
+
const namespaceSpecifier = specifiers.find(
|
|
2251
|
+
(specifier) => specifier.type === "ImportNamespaceSpecifier"
|
|
2252
|
+
);
|
|
2253
|
+
const namedSpecifiers = specifiers.filter((specifier) => specifier.type === "ImportSpecifier");
|
|
2254
|
+
const parts = [];
|
|
2255
|
+
if (defaultSpecifier && isAstNode(defaultSpecifier.local)) {
|
|
2256
|
+
parts.push(code.slice(defaultSpecifier.local.start, defaultSpecifier.local.end));
|
|
2257
|
+
}
|
|
2258
|
+
if (namespaceSpecifier && isAstNode(namespaceSpecifier.local)) {
|
|
2259
|
+
parts.push(`* as ${code.slice(namespaceSpecifier.local.start, namespaceSpecifier.local.end)}`);
|
|
2260
|
+
}
|
|
2261
|
+
if (namedSpecifiers.length > 0) {
|
|
2262
|
+
parts.push(
|
|
2263
|
+
`{ ${namedSpecifiers.map((specifier) => code.slice(specifier.start, specifier.end)).join(", ")} }`
|
|
2264
|
+
);
|
|
2265
|
+
}
|
|
2266
|
+
return parts.length > 0 ? `import ${parts.join(", ")} from ${JSON.stringify(source)};` : "";
|
|
2267
|
+
}
|
|
2268
|
+
__name(renderImportDeclaration, "renderImportDeclaration");
|
|
2269
|
+
function readFontOptions(code, id, call) {
|
|
2270
|
+
if (!call.binding) {
|
|
2271
|
+
throw fontError(id, `${call.kind}() must use a named import from @farm.js/core/font`);
|
|
2272
|
+
}
|
|
2273
|
+
const args = Array.isArray(call.node.arguments) ? call.node.arguments : [];
|
|
2274
|
+
if (args.length !== 1 || !isAstNode(args[0]) || args[0].type !== "ObjectExpression") {
|
|
2275
|
+
throw fontError(id, `${call.kind}() requires one inline options object`);
|
|
2276
|
+
}
|
|
2277
|
+
const parent = call.ancestors.at(-1);
|
|
2278
|
+
if (!parent || parent.type !== "VariableDeclarator" || parent.init !== call.node) {
|
|
2279
|
+
throw fontError(id, `${call.kind}() must initialize a module-scope variable`);
|
|
2280
|
+
}
|
|
2281
|
+
const declaration = call.ancestors.at(-2);
|
|
2282
|
+
const statement = call.ancestors.at(-3);
|
|
2283
|
+
const statementParent = call.ancestors.at(-4);
|
|
2284
|
+
const isModuleScope = declaration?.type === "VariableDeclaration" && (statement?.type === "Program" || statement?.type === "ExportNamedDeclaration" && statementParent?.type === "Program");
|
|
2285
|
+
if (!isModuleScope || call.ancestors.some((ancestor) => isFunctionNode(ancestor))) {
|
|
2286
|
+
throw fontError(id, `${call.kind}() must be declared directly at module scope`);
|
|
2287
|
+
}
|
|
2288
|
+
return evaluateStaticObject(code, id, args[0]);
|
|
2289
|
+
}
|
|
2290
|
+
__name(readFontOptions, "readFontOptions");
|
|
2291
|
+
function evaluateStaticObject(code, id, node) {
|
|
2292
|
+
const result = {};
|
|
2293
|
+
const properties = Array.isArray(node.properties) ? node.properties : [];
|
|
2294
|
+
for (const property of properties) {
|
|
2295
|
+
if (!isAstNode(property) || property.type !== "Property" || property.computed === true) {
|
|
2296
|
+
throw fontError(id, "font options do not support spreads or computed properties");
|
|
2297
|
+
}
|
|
2298
|
+
const key = readPropertyName(property.key);
|
|
2299
|
+
if (!key || !isAstNode(property.value)) {
|
|
2300
|
+
throw fontError(id, "font options must use static property names and values");
|
|
2301
|
+
}
|
|
2302
|
+
result[key] = evaluateStaticValue(code, id, property.value);
|
|
2303
|
+
}
|
|
2304
|
+
return result;
|
|
2305
|
+
}
|
|
2306
|
+
__name(evaluateStaticObject, "evaluateStaticObject");
|
|
2307
|
+
function evaluateStaticValue(code, id, node) {
|
|
2308
|
+
if (node.type === "Literal") return node.value;
|
|
2309
|
+
if (node.type === "TemplateLiteral") {
|
|
2310
|
+
const expressions = Array.isArray(node.expressions) ? node.expressions : [];
|
|
2311
|
+
const quasis = Array.isArray(node.quasis) ? node.quasis : [];
|
|
2312
|
+
if (expressions.length === 0 && quasis.length === 1 && isAstNode(quasis[0])) {
|
|
2313
|
+
const templateValue = quasis[0].value;
|
|
2314
|
+
const value = templateValue && typeof templateValue === "object" ? templateValue.cooked : void 0;
|
|
2315
|
+
if (typeof value === "string") return value;
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
if (node.type === "ArrayExpression") {
|
|
2319
|
+
const elements = Array.isArray(node.elements) ? node.elements : [];
|
|
2320
|
+
return elements.map((element) => {
|
|
2321
|
+
if (!isAstNode(element) || element.type === "SpreadElement") {
|
|
2322
|
+
throw fontError(id, "font option arrays must contain static values");
|
|
2323
|
+
}
|
|
2324
|
+
return evaluateStaticValue(code, id, element);
|
|
2325
|
+
});
|
|
2326
|
+
}
|
|
2327
|
+
if (node.type === "ObjectExpression") return evaluateStaticObject(code, id, node);
|
|
2328
|
+
if (node.type === "UnaryExpression" && (node.operator === "+" || node.operator === "-") && isAstNode(node.argument)) {
|
|
2329
|
+
const value = evaluateStaticValue(code, id, node.argument);
|
|
2330
|
+
if (typeof value === "number") return node.operator === "-" ? -value : value;
|
|
2331
|
+
}
|
|
2332
|
+
throw fontError(
|
|
2333
|
+
id,
|
|
2334
|
+
`font options must be statically analyzable near ${code.slice(node.start, node.end)}`
|
|
2335
|
+
);
|
|
2336
|
+
}
|
|
2337
|
+
__name(evaluateStaticValue, "evaluateStaticValue");
|
|
2338
|
+
function readSources(value, id, kind, weight, style) {
|
|
2339
|
+
if (typeof value === "string") return [{ path: value, weight, style }];
|
|
2340
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
2341
|
+
throw fontError(id, `${kind}() src must be a string or a non-empty source array`);
|
|
2342
|
+
}
|
|
2343
|
+
return value.map((entry, index) => {
|
|
2344
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
2345
|
+
throw fontError(id, `${kind}() src[${index}] must be an object`);
|
|
2346
|
+
}
|
|
2347
|
+
const source = entry;
|
|
2348
|
+
const unknown = Object.keys(source).filter(
|
|
2349
|
+
(key) => ![
|
|
2350
|
+
"path",
|
|
2351
|
+
"weight",
|
|
2352
|
+
"style",
|
|
2353
|
+
"unicodeRange",
|
|
2354
|
+
...kind === "remoteFont" ? ["integrity"] : []
|
|
2355
|
+
].includes(key)
|
|
2356
|
+
);
|
|
2357
|
+
if (unknown.length) throw fontError(id, `unknown src[${index}] option ${unknown[0]}`);
|
|
2358
|
+
return {
|
|
2359
|
+
path: requireString(source.path, id, `${kind}() src[${index}].path`),
|
|
2360
|
+
weight: optionalWeight(source.weight, id) ?? weight,
|
|
2361
|
+
style: optionalCssDescriptor(source.style, id, "style") || style,
|
|
2362
|
+
unicodeRange: optionalUnicodeRange(source.unicodeRange, id),
|
|
2363
|
+
integrity: optionalString(source.integrity, id, `${kind}() src[${index}].integrity`)
|
|
2364
|
+
};
|
|
2365
|
+
});
|
|
2366
|
+
}
|
|
2367
|
+
__name(readSources, "readSources");
|
|
2368
|
+
function validateOptionKeys(id, kind, raw) {
|
|
2369
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
2370
|
+
"src",
|
|
2371
|
+
"family",
|
|
2372
|
+
"weight",
|
|
2373
|
+
"style",
|
|
2374
|
+
"display",
|
|
2375
|
+
"variable",
|
|
2376
|
+
"fallback",
|
|
2377
|
+
"preload",
|
|
2378
|
+
...kind === "remoteFont" ? ["strategy", "integrity"] : []
|
|
2379
|
+
]);
|
|
2380
|
+
const unknown = Object.keys(raw).find((key) => !allowed.has(key));
|
|
2381
|
+
if (unknown) throw fontError(id, `unknown ${kind}() option ${JSON.stringify(unknown)}`);
|
|
2382
|
+
if (typeof raw.preload !== "undefined" && typeof raw.preload !== "boolean") {
|
|
2383
|
+
throw fontError(id, `${kind}() preload must be a boolean`);
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
__name(validateOptionKeys, "validateOptionKeys");
|
|
2387
|
+
function serializeFontResult(font) {
|
|
2388
|
+
const stack = renderFamilyStack(font.family, font.fallback);
|
|
2389
|
+
return JSON.stringify({
|
|
2390
|
+
className: font.className,
|
|
2391
|
+
variable: font.variableClassName,
|
|
2392
|
+
style: {
|
|
2393
|
+
fontFamily: stack,
|
|
2394
|
+
...font.style ? { fontStyle: font.style } : {},
|
|
2395
|
+
...font.weight !== void 0 && !String(font.weight).includes(" ") ? { fontWeight: font.weight } : {}
|
|
2396
|
+
}
|
|
2397
|
+
});
|
|
2398
|
+
}
|
|
2399
|
+
__name(serializeFontResult, "serializeFontResult");
|
|
2400
|
+
function renderFontDefinitionCss(font, production, basePath) {
|
|
2401
|
+
const faces = font.sources.map((source) => {
|
|
2402
|
+
const descriptors = [
|
|
2403
|
+
` font-family: ${quoteCssString(font.family)};`,
|
|
2404
|
+
` src: url(${quoteCssString(resourceUrl(source.resource, production, basePath))}) format(${quoteCssString(source.resource.format)});`,
|
|
2405
|
+
` font-display: ${font.display};`,
|
|
2406
|
+
` font-weight: ${source.weight};`,
|
|
2407
|
+
` font-style: ${source.style};`,
|
|
2408
|
+
...source.unicodeRange ? [` unicode-range: ${source.unicodeRange};`] : []
|
|
2409
|
+
];
|
|
2410
|
+
return `@font-face {
|
|
2411
|
+
${descriptors.join("\n")}
|
|
2412
|
+
}`;
|
|
2413
|
+
});
|
|
2414
|
+
const stack = renderFamilyStack(font.family, font.fallback);
|
|
2415
|
+
faces.push(`.${font.className} {
|
|
2416
|
+
font-family: ${stack};
|
|
2417
|
+
}`);
|
|
2418
|
+
if (font.variable && font.variableClassName) {
|
|
2419
|
+
faces.push(`.${font.variableClassName} {
|
|
2420
|
+
${font.variable}: ${stack};
|
|
2421
|
+
}`);
|
|
2422
|
+
}
|
|
2423
|
+
return faces.join("\n\n");
|
|
2424
|
+
}
|
|
2425
|
+
__name(renderFontDefinitionCss, "renderFontDefinitionCss");
|
|
2426
|
+
function resourceUrl(resource, production, basePath) {
|
|
2427
|
+
if (resource.publicPath) {
|
|
2428
|
+
return production ? joinBasePath(basePath, resource.publicPath) : resource.publicPath;
|
|
2429
|
+
}
|
|
2430
|
+
if (!resource.bytes) return resource.publicUrl;
|
|
2431
|
+
if (!production) {
|
|
2432
|
+
return joinBasePath(basePath, `/@farm/font/${resource.hash}${resource.extension}`);
|
|
2433
|
+
}
|
|
2434
|
+
return joinBasePath(basePath, `/${resource.outputFileName}`);
|
|
2435
|
+
}
|
|
2436
|
+
__name(resourceUrl, "resourceUrl");
|
|
2437
|
+
async function fetchRemoteFont(url, integrity) {
|
|
2438
|
+
const key = `${url.href}\0${integrity || ""}`;
|
|
2439
|
+
let pending = remoteBytes.get(key);
|
|
2440
|
+
if (!pending) {
|
|
2441
|
+
pending = (async () => {
|
|
2442
|
+
const response = await fetch(url, {
|
|
2443
|
+
headers: { "User-Agent": "Farm.js font compiler" },
|
|
2444
|
+
redirect: "follow"
|
|
2445
|
+
});
|
|
2446
|
+
if (!response.ok)
|
|
2447
|
+
throw new Error(`request returned ${response.status} ${response.statusText}`);
|
|
2448
|
+
const length = Number(response.headers.get("content-length") || 0);
|
|
2449
|
+
if (length > MAX_REMOTE_FONT_BYTES) throw new Error("font exceeds the 20 MB limit");
|
|
2450
|
+
const bytes = await readResponseBodyWithLimit(response, MAX_REMOTE_FONT_BYTES);
|
|
2451
|
+
if (integrity) verifyIntegrity(bytes, integrity);
|
|
2452
|
+
return bytes;
|
|
2453
|
+
})().catch((error) => {
|
|
2454
|
+
throw new Error(`[Farm fonts] Failed to download ${url.href}: ${error.message}`);
|
|
2455
|
+
});
|
|
2456
|
+
remoteBytes.set(key, pending);
|
|
2457
|
+
const clearPending = /* @__PURE__ */ __name(() => {
|
|
2458
|
+
if (remoteBytes.get(key) === pending) remoteBytes.delete(key);
|
|
2459
|
+
}, "clearPending");
|
|
2460
|
+
void pending.then(clearPending, clearPending);
|
|
2461
|
+
}
|
|
2462
|
+
return pending;
|
|
2463
|
+
}
|
|
2464
|
+
__name(fetchRemoteFont, "fetchRemoteFont");
|
|
2465
|
+
async function readResponseBodyWithLimit(response, limit) {
|
|
2466
|
+
if (!response.body) return Buffer.alloc(0);
|
|
2467
|
+
const reader = response.body.getReader();
|
|
2468
|
+
const chunks = [];
|
|
2469
|
+
let total = 0;
|
|
2470
|
+
while (true) {
|
|
2471
|
+
const chunk = await reader.read();
|
|
2472
|
+
if (chunk.done) break;
|
|
2473
|
+
total += chunk.value.byteLength;
|
|
2474
|
+
if (total > limit) {
|
|
2475
|
+
await reader.cancel("font exceeds the configured byte limit");
|
|
2476
|
+
throw new Error("font exceeds the 20 MB limit");
|
|
2477
|
+
}
|
|
2478
|
+
chunks.push(chunk.value);
|
|
2479
|
+
}
|
|
2480
|
+
return Buffer.concat(chunks, total);
|
|
2481
|
+
}
|
|
2482
|
+
__name(readResponseBodyWithLimit, "readResponseBodyWithLimit");
|
|
2483
|
+
function verifyIntegrity(bytes, integrity) {
|
|
2484
|
+
const entries = integrity.trim().split(/\s+/);
|
|
2485
|
+
const supported = entries.map((entry) => entry.match(/^(sha(?:256|384|512))-(.+)$/)).filter((entry) => Boolean(entry));
|
|
2486
|
+
if (supported.length === 0) throw new Error("integrity must use sha256, sha384, or sha512");
|
|
2487
|
+
const matches = supported.some((entry) => {
|
|
2488
|
+
const actual = createHash2(entry[1]).update(bytes).digest();
|
|
2489
|
+
const expected = Buffer.from(entry[2], "base64");
|
|
2490
|
+
return actual.length === expected.length && timingSafeEqual(actual, expected);
|
|
2491
|
+
});
|
|
2492
|
+
if (!matches) throw new Error("downloaded font did not match its integrity value");
|
|
2493
|
+
}
|
|
2494
|
+
__name(verifyIntegrity, "verifyIntegrity");
|
|
2495
|
+
function resolveLocalFontPath(source, importer, root) {
|
|
2496
|
+
if (source.startsWith(".")) return path4.resolve(path4.dirname(importer), source);
|
|
2497
|
+
if (path4.isAbsolute(source)) {
|
|
2498
|
+
return source;
|
|
2499
|
+
}
|
|
2500
|
+
try {
|
|
2501
|
+
return createRequire(pathToFileURL(importer)).resolve(source);
|
|
2502
|
+
} catch {
|
|
2503
|
+
const segments = source.replace(/\\/g, "/").split("/");
|
|
2504
|
+
if (segments.includes("..")) return path4.resolve(root, source);
|
|
2505
|
+
let current = path4.dirname(importer);
|
|
2506
|
+
const filesystemRoot = path4.parse(current).root;
|
|
2507
|
+
while (true) {
|
|
2508
|
+
const candidate = path4.join(current, "node_modules", ...segments);
|
|
2509
|
+
if (existsSync(candidate)) return candidate;
|
|
2510
|
+
if (current === filesystemRoot) break;
|
|
2511
|
+
current = path4.dirname(current);
|
|
2512
|
+
}
|
|
2513
|
+
return path4.resolve(root, "node_modules", ...segments);
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
__name(resolveLocalFontPath, "resolveLocalFontPath");
|
|
2517
|
+
function replaceFontSection(css, section) {
|
|
2518
|
+
const start = css.indexOf(FONT_SECTION_START);
|
|
2519
|
+
const end = css.indexOf(FONT_SECTION_END);
|
|
2520
|
+
const withoutExisting = start >= 0 && end >= start ? `${css.slice(0, start)}${css.slice(end + FONT_SECTION_END.length)}`.trimEnd() : css.trimEnd();
|
|
2521
|
+
return `${withoutExisting}${withoutExisting ? "\n\n" : ""}${section}`;
|
|
2522
|
+
}
|
|
2523
|
+
__name(replaceFontSection, "replaceFontSection");
|
|
2524
|
+
function mergeFarmFontCss(clientCss, fontCss) {
|
|
2525
|
+
return replaceFontSection(clientCss, fontCss);
|
|
2526
|
+
}
|
|
2527
|
+
__name(mergeFarmFontCss, "mergeFarmFontCss");
|
|
2528
|
+
function getOrCreateRegistry(root, basePath = "/", publicDir) {
|
|
2529
|
+
const normalized = normalizeRoot(root);
|
|
2530
|
+
const existing = registries.get(normalized);
|
|
2531
|
+
if (existing) {
|
|
2532
|
+
existing.basePath = normalizeBasePath(basePath);
|
|
2533
|
+
existing.publicDir = normalizePublicDir(normalized, publicDir);
|
|
2534
|
+
return existing;
|
|
2535
|
+
}
|
|
2536
|
+
const registry = new FarmFontRegistry(normalized, basePath, publicDir);
|
|
2537
|
+
registries.set(normalized, registry);
|
|
2538
|
+
return registry;
|
|
2539
|
+
}
|
|
2540
|
+
__name(getOrCreateRegistry, "getOrCreateRegistry");
|
|
2541
|
+
function getGlobalMap(key) {
|
|
2542
|
+
const runtime = globalThis;
|
|
2543
|
+
const existing = runtime[key];
|
|
2544
|
+
if (existing instanceof Map) return existing;
|
|
2545
|
+
const created = /* @__PURE__ */ new Map();
|
|
2546
|
+
runtime[key] = created;
|
|
2547
|
+
return created;
|
|
2548
|
+
}
|
|
2549
|
+
__name(getGlobalMap, "getGlobalMap");
|
|
2550
|
+
function normalizeRoot(root) {
|
|
2551
|
+
return path4.resolve(root).replace(/\\/g, "/");
|
|
2552
|
+
}
|
|
2553
|
+
__name(normalizeRoot, "normalizeRoot");
|
|
2554
|
+
function normalizePublicDir(root, publicDir) {
|
|
2555
|
+
if (publicDir === false || publicDir === "") return false;
|
|
2556
|
+
return path4.resolve(root, publicDir || "public");
|
|
2557
|
+
}
|
|
2558
|
+
__name(normalizePublicDir, "normalizePublicDir");
|
|
2559
|
+
function normalizePublicFontPath(source, moduleId) {
|
|
2560
|
+
if (source.includes("?") || source.includes("#")) {
|
|
2561
|
+
throw fontError(moduleId, `public font paths cannot contain a query string or fragment`);
|
|
2562
|
+
}
|
|
2563
|
+
return `/${source.replace(/\\/g, "/").replace(/^\/+/, "")}`;
|
|
2564
|
+
}
|
|
2565
|
+
__name(normalizePublicFontPath, "normalizePublicFontPath");
|
|
2566
|
+
function isPathInside(parent, child) {
|
|
2567
|
+
const relative = path4.relative(parent, child);
|
|
2568
|
+
return relative === "" || !relative.startsWith("..") && !path4.isAbsolute(relative);
|
|
2569
|
+
}
|
|
2570
|
+
__name(isPathInside, "isPathInside");
|
|
2571
|
+
function normalizeBasePath(value) {
|
|
2572
|
+
if (!value || value === "/") return "/";
|
|
2573
|
+
return `/${value.replace(/^\/+|\/+$/g, "")}/`;
|
|
2574
|
+
}
|
|
2575
|
+
__name(normalizeBasePath, "normalizeBasePath");
|
|
2576
|
+
function joinBasePath(basePath, value) {
|
|
2577
|
+
return basePath === "/" ? value : `${basePath.replace(/\/$/, "")}${value}`;
|
|
2578
|
+
}
|
|
2579
|
+
__name(joinBasePath, "joinBasePath");
|
|
2580
|
+
function extensionFromPath(pathname) {
|
|
2581
|
+
const extension = path4.extname(pathname).toLowerCase();
|
|
2582
|
+
if (!FONT_EXTENSION_RE.test(extension)) {
|
|
2583
|
+
throw new Error(`[Farm fonts] Remote font URL must end in .woff2, .woff, .ttf, or .otf`);
|
|
2584
|
+
}
|
|
2585
|
+
return extension;
|
|
2586
|
+
}
|
|
2587
|
+
__name(extensionFromPath, "extensionFromPath");
|
|
2588
|
+
function fontFormat(extension) {
|
|
2589
|
+
switch (extension.toLowerCase()) {
|
|
2590
|
+
case ".woff2":
|
|
2591
|
+
return "woff2";
|
|
2592
|
+
case ".woff":
|
|
2593
|
+
return "woff";
|
|
2594
|
+
case ".ttf":
|
|
2595
|
+
return "truetype";
|
|
2596
|
+
case ".otf":
|
|
2597
|
+
return "opentype";
|
|
2598
|
+
default:
|
|
2599
|
+
throw new Error(`[Farm fonts] Unsupported font extension ${extension}`);
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
__name(fontFormat, "fontFormat");
|
|
2603
|
+
function fontContentType(extension) {
|
|
2604
|
+
switch (extension.toLowerCase()) {
|
|
2605
|
+
case ".woff2":
|
|
2606
|
+
return "font/woff2";
|
|
2607
|
+
case ".woff":
|
|
2608
|
+
return "font/woff";
|
|
2609
|
+
case ".ttf":
|
|
2610
|
+
return "font/ttf";
|
|
2611
|
+
case ".otf":
|
|
2612
|
+
return "font/otf";
|
|
2613
|
+
default:
|
|
2614
|
+
return "application/octet-stream";
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
__name(fontContentType, "fontContentType");
|
|
2618
|
+
function renderFamilyStack(family, fallback) {
|
|
2619
|
+
return [quoteCssString(family), ...fallback.map(formatFallbackFamily)].join(", ");
|
|
2620
|
+
}
|
|
2621
|
+
__name(renderFamilyStack, "renderFamilyStack");
|
|
2622
|
+
function formatFallbackFamily(value) {
|
|
2623
|
+
return /^(?:serif|sans-serif|monospace|cursive|fantasy|system-ui|ui-serif|ui-sans-serif|ui-monospace|emoji|math|fangsong)$/.test(
|
|
2624
|
+
value
|
|
2625
|
+
) ? value : quoteCssString(value);
|
|
2626
|
+
}
|
|
2627
|
+
__name(formatFallbackFamily, "formatFallbackFamily");
|
|
2628
|
+
function quoteCssString(value) {
|
|
2629
|
+
return JSON.stringify(value.replace(/[\n\r\f]/g, " "));
|
|
2630
|
+
}
|
|
2631
|
+
__name(quoteCssString, "quoteCssString");
|
|
2632
|
+
function sanitizeFileName(value) {
|
|
2633
|
+
return value.replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
2634
|
+
}
|
|
2635
|
+
__name(sanitizeFileName, "sanitizeFileName");
|
|
2636
|
+
function assetSourceToString(source) {
|
|
2637
|
+
return typeof source === "string" ? source : Buffer.from(source).toString("utf8");
|
|
2638
|
+
}
|
|
2639
|
+
__name(assetSourceToString, "assetSourceToString");
|
|
2640
|
+
function applyReplacements(code, replacements) {
|
|
2641
|
+
let output = code;
|
|
2642
|
+
for (const replacement of replacements.sort((left, right) => right.start - left.start)) {
|
|
2643
|
+
output = output.slice(0, replacement.start) + replacement.code + output.slice(replacement.end);
|
|
2644
|
+
}
|
|
2645
|
+
return output;
|
|
2646
|
+
}
|
|
2647
|
+
__name(applyReplacements, "applyReplacements");
|
|
2648
|
+
function walkAst(node, visit, ancestors = []) {
|
|
2649
|
+
visit(node, ancestors);
|
|
2650
|
+
const childAncestors = [...ancestors, node];
|
|
2651
|
+
for (const [key, value] of Object.entries(node)) {
|
|
2652
|
+
if (["start", "end", "loc", "range"].includes(key)) continue;
|
|
2653
|
+
if (isAstNode(value)) walkAst(value, visit, childAncestors);
|
|
2654
|
+
else if (Array.isArray(value)) {
|
|
2655
|
+
for (const item of value) if (isAstNode(item)) walkAst(item, visit, childAncestors);
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
__name(walkAst, "walkAst");
|
|
2660
|
+
function readPropertyName(value) {
|
|
2661
|
+
if (!isAstNode(value)) return void 0;
|
|
2662
|
+
if (value.type === "Identifier" && typeof value.name === "string") return value.name;
|
|
2663
|
+
if (value.type === "Literal" && typeof value.value === "string") return value.value;
|
|
2664
|
+
return void 0;
|
|
2665
|
+
}
|
|
2666
|
+
__name(readPropertyName, "readPropertyName");
|
|
2667
|
+
function isAstNode(value) {
|
|
2668
|
+
return Boolean(value) && typeof value === "object" && typeof value.type === "string" && typeof value.start === "number" && typeof value.end === "number";
|
|
2669
|
+
}
|
|
2670
|
+
__name(isAstNode, "isAstNode");
|
|
2671
|
+
function isFunctionNode(node) {
|
|
2672
|
+
return node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
|
|
2673
|
+
}
|
|
2674
|
+
__name(isFunctionNode, "isFunctionNode");
|
|
2675
|
+
function isFontLoaderKind(value) {
|
|
2676
|
+
return typeof value === "string" && FONT_FUNCTIONS.has(value);
|
|
2677
|
+
}
|
|
2678
|
+
__name(isFontLoaderKind, "isFontLoaderKind");
|
|
2679
|
+
function containsFontFunction(code) {
|
|
2680
|
+
return Array.from(FONT_FUNCTIONS).some((name) => code.includes(name));
|
|
2681
|
+
}
|
|
2682
|
+
__name(containsFontFunction, "containsFontFunction");
|
|
2683
|
+
function requireString(value, id, label) {
|
|
2684
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
2685
|
+
throw fontError(id, `${label} must be a non-empty string`);
|
|
2686
|
+
}
|
|
2687
|
+
return value;
|
|
2688
|
+
}
|
|
2689
|
+
__name(requireString, "requireString");
|
|
2690
|
+
function optionalString(value, id, label) {
|
|
2691
|
+
if (value === void 0) return void 0;
|
|
2692
|
+
return requireString(value, id, label);
|
|
2693
|
+
}
|
|
2694
|
+
__name(optionalString, "optionalString");
|
|
2695
|
+
function readStringArray(value, id, label) {
|
|
2696
|
+
if (value === void 0) return [];
|
|
2697
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
|
|
2698
|
+
throw fontError(id, `${label} must be an array of family names`);
|
|
2699
|
+
}
|
|
2700
|
+
return value;
|
|
2701
|
+
}
|
|
2702
|
+
__name(readStringArray, "readStringArray");
|
|
2703
|
+
function optionalWeight(value, id) {
|
|
2704
|
+
if (value === void 0) return void 0;
|
|
2705
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= 1e3) {
|
|
2706
|
+
return value;
|
|
2707
|
+
}
|
|
2708
|
+
if (typeof value === "string" && /^(?:[1-9]\d{0,2}|1000)(?:\s+(?:[1-9]\d{0,2}|1000))?$/.test(value)) {
|
|
2709
|
+
const bounds = value.split(/\s+/).map(Number);
|
|
2710
|
+
if (bounds.length === 2 && bounds[0] > bounds[1]) {
|
|
2711
|
+
throw fontError(id, `font weight range must be ordered from lowest to highest`);
|
|
2712
|
+
}
|
|
2713
|
+
return value;
|
|
2714
|
+
}
|
|
2715
|
+
throw fontError(id, `font weight must be a number or range such as "100 900"`);
|
|
2716
|
+
}
|
|
2717
|
+
__name(optionalWeight, "optionalWeight");
|
|
2718
|
+
function optionalCssDescriptor(value, id, label) {
|
|
2719
|
+
if (value === void 0) return void 0;
|
|
2720
|
+
if (typeof value !== "string" || !/^[A-Za-z0-9 .-]+$/.test(value)) {
|
|
2721
|
+
throw fontError(id, `font ${label} contains unsupported characters`);
|
|
2722
|
+
}
|
|
2723
|
+
return value;
|
|
2724
|
+
}
|
|
2725
|
+
__name(optionalCssDescriptor, "optionalCssDescriptor");
|
|
2726
|
+
function optionalUnicodeRange(value, id) {
|
|
2727
|
+
if (value === void 0) return void 0;
|
|
2728
|
+
if (typeof value !== "string" || !/^[Uu+0-9A-Fa-f?*, -]+$/.test(value)) {
|
|
2729
|
+
throw fontError(id, `font unicodeRange contains unsupported characters`);
|
|
2730
|
+
}
|
|
2731
|
+
return value;
|
|
2732
|
+
}
|
|
2733
|
+
__name(optionalUnicodeRange, "optionalUnicodeRange");
|
|
2734
|
+
function escapeHtmlAttribute(value) {
|
|
2735
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
2736
|
+
}
|
|
2737
|
+
__name(escapeHtmlAttribute, "escapeHtmlAttribute");
|
|
2738
|
+
function fontError(id, message) {
|
|
2739
|
+
return new Error(`[Farm fonts] ${message} in ${id.split("?", 1)[0]}`);
|
|
2740
|
+
}
|
|
2741
|
+
__name(fontError, "fontError");
|
|
2742
|
+
|
|
2743
|
+
// src/server/renderer.ts
|
|
1452
2744
|
var cachedClerkProvider = null;
|
|
1453
2745
|
var importRuntimeModule = new Function("specifier", "return import(specifier);");
|
|
1454
2746
|
function hasRequestHeader(req, name) {
|
|
@@ -1460,10 +2752,10 @@ function serializeInlineValue(value) {
|
|
|
1460
2752
|
return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
1461
2753
|
}
|
|
1462
2754
|
__name(serializeInlineValue, "serializeInlineValue");
|
|
1463
|
-
function
|
|
2755
|
+
function escapeHtmlAttribute2(value) {
|
|
1464
2756
|
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
1465
2757
|
}
|
|
1466
|
-
__name(
|
|
2758
|
+
__name(escapeHtmlAttribute2, "escapeHtmlAttribute");
|
|
1467
2759
|
function appendResponseHeader(res, name, value) {
|
|
1468
2760
|
const current = res.getHeader(name);
|
|
1469
2761
|
if (current === void 0) {
|
|
@@ -1489,10 +2781,10 @@ function renderI18nAlternateLinks(requestPath, snapshot) {
|
|
|
1489
2781
|
const url = new URL(requestPath, "http://farm.local");
|
|
1490
2782
|
const links = snapshot.locales.map((locale) => {
|
|
1491
2783
|
const href = localizeFarmPathname(url.pathname, locale, snapshot);
|
|
1492
|
-
return `<link rel="alternate" hreflang="${
|
|
2784
|
+
return `<link rel="alternate" hreflang="${escapeHtmlAttribute2(locale)}" href="${escapeHtmlAttribute2(href)}">`;
|
|
1493
2785
|
});
|
|
1494
2786
|
links.push(
|
|
1495
|
-
`<link rel="alternate" hreflang="x-default" href="${
|
|
2787
|
+
`<link rel="alternate" hreflang="x-default" href="${escapeHtmlAttribute2(
|
|
1496
2788
|
localizeFarmPathname(url.pathname, snapshot.defaultLocale, snapshot)
|
|
1497
2789
|
)}">`
|
|
1498
2790
|
);
|
|
@@ -1656,7 +2948,9 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1656
2948
|
async runWithRequestContext(request, fn) {
|
|
1657
2949
|
return _runWithCurrentRequest(
|
|
1658
2950
|
request,
|
|
1659
|
-
() => this.i18nRuntime?.config.enabled ? _runWithFarmI18nRequest(this.i18nRuntime, request, fn, {
|
|
2951
|
+
() => this.i18nRuntime?.config.enabled ? _runWithFarmI18nRequest(this.i18nRuntime, request, fn, {
|
|
2952
|
+
redirect: false
|
|
2953
|
+
}) : fn()
|
|
1660
2954
|
);
|
|
1661
2955
|
}
|
|
1662
2956
|
async resolveRouteContext(input) {
|
|
@@ -1667,7 +2961,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1667
2961
|
*/
|
|
1668
2962
|
loadSSGManifest() {
|
|
1669
2963
|
try {
|
|
1670
|
-
const manifestPath =
|
|
2964
|
+
const manifestPath = path5.join(this.config.root, this.config.outDir, "__ssg_manifest.json");
|
|
1671
2965
|
if (fs2.existsSync(manifestPath)) {
|
|
1672
2966
|
const content = fs2.readFileSync(manifestPath, "utf-8");
|
|
1673
2967
|
this.ssgManifest = JSON.parse(content);
|
|
@@ -1679,11 +2973,11 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1679
2973
|
/**
|
|
1680
2974
|
* Check if a path should be served from SSG cache
|
|
1681
2975
|
*/
|
|
1682
|
-
shouldServeSSG(pathname) {
|
|
2976
|
+
async shouldServeSSG(pathname) {
|
|
1683
2977
|
const ssgPage = matchSSGPage(pathname, this.ssgManifest);
|
|
1684
2978
|
if (!ssgPage) return null;
|
|
1685
|
-
const cached = this.getCachedSSGPage(pathname);
|
|
1686
|
-
if (cached && this.dataCache.
|
|
2979
|
+
const cached = await this.getCachedSSGPage(pathname);
|
|
2980
|
+
if (cached && await this.dataCache.isStaleAsync(cached)) {
|
|
1687
2981
|
this.regenerateSSGPage(ssgPage);
|
|
1688
2982
|
}
|
|
1689
2983
|
return ssgPage;
|
|
@@ -1695,12 +2989,12 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1695
2989
|
return createFarmCacheKey(["ppr", normalizeRevalidatePath(pathname), search]);
|
|
1696
2990
|
}
|
|
1697
2991
|
getCachedSSGPage(urlPath) {
|
|
1698
|
-
return this.dataCache.
|
|
2992
|
+
return this.dataCache.getEntryAsync(this.getSSGCacheKey(urlPath), {
|
|
1699
2993
|
allowStale: true
|
|
1700
2994
|
});
|
|
1701
2995
|
}
|
|
1702
|
-
cacheSSGPage(page, html, options) {
|
|
1703
|
-
this.dataCache.
|
|
2996
|
+
async cacheSSGPage(page, html, options) {
|
|
2997
|
+
await this.dataCache.setAsync(
|
|
1704
2998
|
this.getSSGCacheKey(page.urlPath),
|
|
1705
2999
|
{ html, document: options.document },
|
|
1706
3000
|
{
|
|
@@ -1712,11 +3006,11 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1712
3006
|
);
|
|
1713
3007
|
}
|
|
1714
3008
|
getCachedPPRShell(pathname, search) {
|
|
1715
|
-
return this.dataCache.
|
|
3009
|
+
return this.dataCache.getEntryAsync(this.getPPRCacheKey(pathname, search));
|
|
1716
3010
|
}
|
|
1717
|
-
cachePPRShell(options, html) {
|
|
3011
|
+
async cachePPRShell(options, html) {
|
|
1718
3012
|
const key = this.getPPRCacheKey(options.pathname, options.search);
|
|
1719
|
-
this.dataCache.
|
|
3013
|
+
await this.dataCache.setAsync(
|
|
1720
3014
|
key,
|
|
1721
3015
|
{ html },
|
|
1722
3016
|
{
|
|
@@ -1814,7 +3108,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1814
3108
|
}
|
|
1815
3109
|
const { renderToString } = await import("react-dom/server");
|
|
1816
3110
|
const html = renderToString(await this.wrapWithIntegrationProviders(pageElement));
|
|
1817
|
-
this.cacheSSGPage(page, html, { document: false });
|
|
3111
|
+
await this.cacheSSGPage(page, html, { document: false });
|
|
1818
3112
|
logger.info(`ISR: Regenerated ${page.urlPath}`);
|
|
1819
3113
|
} catch (error) {
|
|
1820
3114
|
logger.error(`ISR regeneration failed for ${page.urlPath}: ${error}`);
|
|
@@ -1828,7 +3122,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1828
3122
|
* Serve a pre-rendered SSG page
|
|
1829
3123
|
*/
|
|
1830
3124
|
async serveSSGPage(req, res, page) {
|
|
1831
|
-
const cached = this.getCachedSSGPage(page.urlPath);
|
|
3125
|
+
const cached = await this.getCachedSSGPage(page.urlPath);
|
|
1832
3126
|
if (cached) {
|
|
1833
3127
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
1834
3128
|
res.setHeader("X-Farm-SSG", "cached");
|
|
@@ -1842,13 +3136,16 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1842
3136
|
return true;
|
|
1843
3137
|
}
|
|
1844
3138
|
try {
|
|
1845
|
-
const htmlPath = page.urlPath === "/" ?
|
|
3139
|
+
const htmlPath = page.urlPath === "/" ? path5.join(this.config.root, this.config.outDir, "client", "index.html") : path5.join(this.config.root, this.config.outDir, "client", page.urlPath + ".html");
|
|
1846
3140
|
if (fs2.existsSync(htmlPath)) {
|
|
1847
3141
|
const stat = fs2.statSync(htmlPath);
|
|
1848
3142
|
const html = fs2.readFileSync(htmlPath, "utf-8");
|
|
1849
|
-
this.cacheSSGPage(page, html, {
|
|
1850
|
-
|
|
1851
|
-
|
|
3143
|
+
await this.cacheSSGPage(page, html, {
|
|
3144
|
+
document: true,
|
|
3145
|
+
createdAt: stat.mtimeMs
|
|
3146
|
+
});
|
|
3147
|
+
const fileCacheEntry = await this.getCachedSSGPage(page.urlPath);
|
|
3148
|
+
if (fileCacheEntry && await this.dataCache.isStaleAsync(fileCacheEntry)) {
|
|
1852
3149
|
this.regenerateSSGPage(page);
|
|
1853
3150
|
}
|
|
1854
3151
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
@@ -1894,6 +3191,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1894
3191
|
let pathname = "/";
|
|
1895
3192
|
let params = {};
|
|
1896
3193
|
let layouts = [];
|
|
3194
|
+
let routeSlots = [];
|
|
1897
3195
|
let searchParamsObject = {};
|
|
1898
3196
|
let middlewareMap = /* @__PURE__ */ new Map();
|
|
1899
3197
|
let middlewareContext = /* @__PURE__ */ new Map();
|
|
@@ -1926,7 +3224,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1926
3224
|
}
|
|
1927
3225
|
this.applyDeploymentHeaders(req, res);
|
|
1928
3226
|
if (process.env.NODE_ENV === "production") {
|
|
1929
|
-
const ssgPage = this.shouldServeSSG(pathname);
|
|
3227
|
+
const ssgPage = await this.shouldServeSSG(pathname);
|
|
1930
3228
|
if (ssgPage) {
|
|
1931
3229
|
const served = await this.serveSSGPage(req, res, ssgPage);
|
|
1932
3230
|
if (served) {
|
|
@@ -1939,6 +3237,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1939
3237
|
const route = match.route;
|
|
1940
3238
|
params = match.params;
|
|
1941
3239
|
layouts = match.layouts;
|
|
3240
|
+
routeSlots = match.slots ?? [];
|
|
1942
3241
|
if (!route) {
|
|
1943
3242
|
emitFarmEvent({ type: "route.notFound", pathname });
|
|
1944
3243
|
await this.render404(req, res);
|
|
@@ -1955,7 +3254,9 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
1955
3254
|
errorBoundaryEntry = this.routeManager.getMatchingError(pathname);
|
|
1956
3255
|
middlewareMap = toMiddlewareMap(req.__FARM_MIDDLEWARE_DATA__);
|
|
1957
3256
|
middlewareContext = toMiddlewareMap(req.__FARM_MIDDLEWARE_CONTEXT__);
|
|
1958
|
-
pluginExposedContext = getRequestContextSnapshot(req, {
|
|
3257
|
+
pluginExposedContext = getRequestContextSnapshot(req, {
|
|
3258
|
+
exposedOnly: true
|
|
3259
|
+
});
|
|
1959
3260
|
const currentRequest = createWebRequestFromFarmRequest(req);
|
|
1960
3261
|
const routeContext = await this.resolveRouteContext({
|
|
1961
3262
|
request: currentRequest,
|
|
@@ -2019,8 +3320,16 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
2019
3320
|
revalidate: renderingConfig.revalidate
|
|
2020
3321
|
} : void 0;
|
|
2021
3322
|
if (renderingConfig.ppr && pprBypassReason) {
|
|
2022
|
-
emitFarmEvent({
|
|
2023
|
-
|
|
3323
|
+
emitFarmEvent({
|
|
3324
|
+
type: "ppr.shell.bypass",
|
|
3325
|
+
route: pathname,
|
|
3326
|
+
reason: pprBypassReason
|
|
3327
|
+
});
|
|
3328
|
+
emitFarmEvent({
|
|
3329
|
+
type: "cache.bypass",
|
|
3330
|
+
route: pathname,
|
|
3331
|
+
reason: pprBypassReason
|
|
3332
|
+
});
|
|
2024
3333
|
if (pprBypassReason === "refresh") {
|
|
2025
3334
|
pprRefreshRoute = pathname;
|
|
2026
3335
|
emitFarmEvent({ type: "ppr.refresh.start", route: pathname });
|
|
@@ -2028,14 +3337,22 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
2028
3337
|
}
|
|
2029
3338
|
if (pprShellOptions) {
|
|
2030
3339
|
const pprCacheKey = this.getPPRCacheKey(pathname, url.search);
|
|
2031
|
-
const cachedPPRShell = this.getCachedPPRShell(pathname, url.search);
|
|
3340
|
+
const cachedPPRShell = await this.getCachedPPRShell(pathname, url.search);
|
|
2032
3341
|
if (cachedPPRShell) {
|
|
2033
|
-
emitFarmEvent({
|
|
3342
|
+
emitFarmEvent({
|
|
3343
|
+
type: "ppr.shell.hit",
|
|
3344
|
+
route: pathname,
|
|
3345
|
+
key: pprCacheKey
|
|
3346
|
+
});
|
|
2034
3347
|
this.serveCachedPPRShell(res, cachedPPRShell.value, renderingConfig.revalidate);
|
|
2035
3348
|
completeRender(res.statusCode || 200, pathname);
|
|
2036
3349
|
return;
|
|
2037
3350
|
}
|
|
2038
|
-
emitFarmEvent({
|
|
3351
|
+
emitFarmEvent({
|
|
3352
|
+
type: "ppr.shell.miss",
|
|
3353
|
+
route: pathname,
|
|
3354
|
+
key: pprCacheKey
|
|
3355
|
+
});
|
|
2039
3356
|
}
|
|
2040
3357
|
let LoadingFallbackComponent = null;
|
|
2041
3358
|
if (loadingBoundaryEntry) {
|
|
@@ -2059,14 +3376,77 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
2059
3376
|
);
|
|
2060
3377
|
const moduleMetadata = routeManifestEntry || getClientModuleMetadata(route.modulePath, this.config.root);
|
|
2061
3378
|
const isClientComponent = moduleMetadata.isClientComponent;
|
|
3379
|
+
const renderedRouteSlots = await Promise.all(
|
|
3380
|
+
routeSlots.map(async (slot) => {
|
|
3381
|
+
const slotModule = await this.routeManager.loadRouteModule(slot.route.modulePath);
|
|
3382
|
+
if (!slotModule.default) {
|
|
3383
|
+
throw new Error(
|
|
3384
|
+
`Route slot "${slot.name}" module ${slot.route.modulePath} does not export a default component`
|
|
3385
|
+
);
|
|
3386
|
+
}
|
|
3387
|
+
const slotContext = await this.resolveRouteContext({
|
|
3388
|
+
request: currentRequest,
|
|
3389
|
+
rawRequest: req,
|
|
3390
|
+
params: slot.params,
|
|
3391
|
+
search: searchParamsObject,
|
|
3392
|
+
path: pathname
|
|
3393
|
+
});
|
|
3394
|
+
const rawSlotProps = withFarmRouteContext(
|
|
3395
|
+
{
|
|
3396
|
+
params: slot.params,
|
|
3397
|
+
searchParams: Promise.resolve(searchParamsObject),
|
|
3398
|
+
path: pathname,
|
|
3399
|
+
middleware: middlewareMap.size > 0 ? { data: middlewareMap } : void 0,
|
|
3400
|
+
context: pluginExposedContext.size > 0 ? { data: pluginExposedContext } : void 0
|
|
3401
|
+
},
|
|
3402
|
+
slotContext
|
|
3403
|
+
);
|
|
3404
|
+
const slotProps = await parseRouteModuleProps(slotModule, {
|
|
3405
|
+
props: rawSlotProps,
|
|
3406
|
+
search: searchParamsObject,
|
|
3407
|
+
routePath: slot.route.pattern
|
|
3408
|
+
});
|
|
3409
|
+
const metadata = getClientModuleMetadata(slot.route.modulePath, this.config.root);
|
|
3410
|
+
return {
|
|
3411
|
+
...slot,
|
|
3412
|
+
module: slotModule,
|
|
3413
|
+
props: slotProps,
|
|
3414
|
+
isClientComponent: metadata.isClientComponent,
|
|
3415
|
+
shouldHydrate: metadata.shouldHydrate
|
|
3416
|
+
};
|
|
3417
|
+
})
|
|
3418
|
+
);
|
|
2062
3419
|
const shouldHydrate = moduleMetadata.shouldHydrate;
|
|
3420
|
+
const hasHydratableRouteSlots = renderedRouteSlots.some(
|
|
3421
|
+
(slot) => slot.isClientComponent || slot.shouldHydrate
|
|
3422
|
+
);
|
|
2063
3423
|
req.__FARM_PAGE_PATH__ = route.modulePath;
|
|
2064
3424
|
req.__FARM_ROUTE__ = pathname;
|
|
2065
3425
|
req.__FARM_IS_CLIENT_COMPONENT__ = isClientComponent;
|
|
2066
3426
|
req.__FARM_SHOULD_HYDRATE__ = shouldHydrate;
|
|
3427
|
+
req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ = hasHydratableRouteSlots;
|
|
2067
3428
|
req.__FARM_LOADING_MODULE_PATH__ = loadingBoundaryEntry?.modulePath ? loadingBoundaryEntry.modulePath.substring(
|
|
2068
3429
|
loadingBoundaryEntry.modulePath.indexOf("/src/app/")
|
|
2069
3430
|
) : null;
|
|
3431
|
+
req.__FARM_ROUTE_SLOTS__ = renderedRouteSlots.map((slot) => ({
|
|
3432
|
+
name: slot.name,
|
|
3433
|
+
ownerPattern: slot.ownerPattern,
|
|
3434
|
+
containerId: slot.containerId,
|
|
3435
|
+
interception: slot.interception,
|
|
3436
|
+
fallback: slot.fallback,
|
|
3437
|
+
modulePath: slot.route.modulePath,
|
|
3438
|
+
isClientComponent: slot.isClientComponent,
|
|
3439
|
+
shouldHydrate: slot.shouldHydrate,
|
|
3440
|
+
props: {
|
|
3441
|
+
params: slot.props.params,
|
|
3442
|
+
search: slot.props.search,
|
|
3443
|
+
searchParams: slot.props.search,
|
|
3444
|
+
..."data" in slot.props ? { data: slot.props.data } : {},
|
|
3445
|
+
...slot.props.__farmCanonicalPath ? { __farmCanonicalPath: slot.props.__farmCanonicalPath } : {},
|
|
3446
|
+
...slot.props.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
|
|
3447
|
+
path: pathname
|
|
3448
|
+
}
|
|
3449
|
+
}));
|
|
2070
3450
|
req.__FARM_PROPS__ = {
|
|
2071
3451
|
params: pageProps.params,
|
|
2072
3452
|
search: pageProps.search,
|
|
@@ -2126,12 +3506,32 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
2126
3506
|
let wrappedElement = pageElement;
|
|
2127
3507
|
for (let i = layoutModules.length - 1; i >= 0; i--) {
|
|
2128
3508
|
const layoutModule = layoutModules[i];
|
|
3509
|
+
const layoutEntry = layouts[i];
|
|
2129
3510
|
const LayoutComponent = layoutModule.default;
|
|
3511
|
+
const slotProps = {};
|
|
3512
|
+
for (const slot of renderedRouteSlots) {
|
|
3513
|
+
if (slot.ownerPattern !== layoutEntry.pattern) continue;
|
|
3514
|
+
let slotElement = React.createElement(
|
|
3515
|
+
slot.module.default,
|
|
3516
|
+
slot.props
|
|
3517
|
+
);
|
|
3518
|
+
slotElement = React.createElement(
|
|
3519
|
+
"div",
|
|
3520
|
+
{
|
|
3521
|
+
id: slot.containerId,
|
|
3522
|
+
"data-farm-route-slot": slot.name,
|
|
3523
|
+
"data-farm-slot-owner": slot.ownerPattern
|
|
3524
|
+
},
|
|
3525
|
+
slotElement
|
|
3526
|
+
);
|
|
3527
|
+
slotProps[slot.name] = slotElement;
|
|
3528
|
+
}
|
|
2130
3529
|
wrappedElement = React.createElement(
|
|
2131
3530
|
LayoutComponent,
|
|
2132
3531
|
{
|
|
2133
3532
|
children: wrappedElement,
|
|
2134
|
-
params
|
|
3533
|
+
params,
|
|
3534
|
+
...slotProps
|
|
2135
3535
|
}
|
|
2136
3536
|
);
|
|
2137
3537
|
}
|
|
@@ -2168,7 +3568,10 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
2168
3568
|
routeManifest,
|
|
2169
3569
|
captureStaticShell: Boolean(pprShellOptions),
|
|
2170
3570
|
observabilityRoute: pathname,
|
|
2171
|
-
onSuspenseHoleDetected: pprShellOptions ? () => emitFarmEvent({
|
|
3571
|
+
onSuspenseHoleDetected: pprShellOptions ? () => emitFarmEvent({
|
|
3572
|
+
type: "ppr.suspense.holeDetected",
|
|
3573
|
+
route: pathname
|
|
3574
|
+
}) : void 0,
|
|
2172
3575
|
onComplete: pprShellOptions && req.method !== "HEAD" ? (html) => this.cachePPRShell(pprShellOptions, html) : void 0
|
|
2173
3576
|
}
|
|
2174
3577
|
);
|
|
@@ -2184,6 +3587,15 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
2184
3587
|
});
|
|
2185
3588
|
});
|
|
2186
3589
|
} catch (error) {
|
|
3590
|
+
if (isWebResponse(error)) {
|
|
3591
|
+
if (!res.headersSent && !res.writableEnded) {
|
|
3592
|
+
await sendWebResponse(res, error);
|
|
3593
|
+
} else if (!res.writableEnded) {
|
|
3594
|
+
res.end();
|
|
3595
|
+
}
|
|
3596
|
+
completeRender(error.status, pathname);
|
|
3597
|
+
return;
|
|
3598
|
+
}
|
|
2187
3599
|
if (isFarmRedirectError(error)) {
|
|
2188
3600
|
const redirect = getFarmRedirectError(error);
|
|
2189
3601
|
const snapshot = getFarmI18nClientSnapshot();
|
|
@@ -2216,7 +3628,11 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
2216
3628
|
}
|
|
2217
3629
|
emitFarmEvent({ type: "render.error", route: pathname, error });
|
|
2218
3630
|
if (pprRefreshRoute) {
|
|
2219
|
-
emitFarmEvent({
|
|
3631
|
+
emitFarmEvent({
|
|
3632
|
+
type: "ppr.refresh.error",
|
|
3633
|
+
route: pprRefreshRoute,
|
|
3634
|
+
error
|
|
3635
|
+
});
|
|
2220
3636
|
}
|
|
2221
3637
|
logger.error(`Error rendering page: ${error}`);
|
|
2222
3638
|
if (res.headersSent || res.writableEnded) {
|
|
@@ -2269,7 +3685,9 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
2269
3685
|
if (typeof layoutModule.generateMetadata === "function") {
|
|
2270
3686
|
metadata = mergeMetadata(
|
|
2271
3687
|
metadata,
|
|
2272
|
-
await layoutModule.generateMetadata({
|
|
3688
|
+
await layoutModule.generateMetadata({
|
|
3689
|
+
params: options.pageProps.params
|
|
3690
|
+
})
|
|
2273
3691
|
);
|
|
2274
3692
|
}
|
|
2275
3693
|
}
|
|
@@ -2478,7 +3896,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
2478
3896
|
}
|
|
2479
3897
|
}
|
|
2480
3898
|
async renderWithSSR(element, req, res, clearMiddlewareData, options = {}) {
|
|
2481
|
-
return new Promise((
|
|
3899
|
+
return new Promise((resolve5, reject) => {
|
|
2482
3900
|
const streamStartTime = Date.now();
|
|
2483
3901
|
const observabilityRoute = options.observabilityRoute || req.__FARM_ROUTE__ || req.url || "/";
|
|
2484
3902
|
const deploymentId = this.getDeploymentId();
|
|
@@ -2500,7 +3918,13 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
2500
3918
|
clientEntry: "/@farm/client.js",
|
|
2501
3919
|
routes: {},
|
|
2502
3920
|
layouts: {},
|
|
2503
|
-
|
|
3921
|
+
slots: [],
|
|
3922
|
+
sharedAssets: [
|
|
3923
|
+
{
|
|
3924
|
+
tag: "link",
|
|
3925
|
+
attrs: { rel: "stylesheet", href: "/src/app/globals.css" }
|
|
3926
|
+
}
|
|
3927
|
+
]
|
|
2504
3928
|
};
|
|
2505
3929
|
for (const routeEntry of manifest.routes) {
|
|
2506
3930
|
clientManifest.routes[routeEntry.pattern] = {
|
|
@@ -2522,9 +3946,26 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
2522
3946
|
assets: []
|
|
2523
3947
|
};
|
|
2524
3948
|
}
|
|
2525
|
-
const
|
|
3949
|
+
for (const slotEntry of manifest.slots ?? []) {
|
|
3950
|
+
clientManifest.slots.push({
|
|
3951
|
+
...slotEntry,
|
|
3952
|
+
preloads: [slotEntry.modulePath],
|
|
3953
|
+
assets: []
|
|
3954
|
+
});
|
|
3955
|
+
}
|
|
3956
|
+
const routeSlotPayload = (req.__FARM_ROUTE_SLOTS__ || []).map(
|
|
3957
|
+
(slot) => ({
|
|
3958
|
+
...slot,
|
|
3959
|
+
modulePath: typeof slot.modulePath === "string" && slot.modulePath.startsWith(this.config.root) ? slot.modulePath.slice(this.config.root.length) : slot.modulePath
|
|
3960
|
+
})
|
|
3961
|
+
);
|
|
3962
|
+
const deferredProps = prepareDeferredData({
|
|
3963
|
+
page: req.__FARM_PROPS__ || {},
|
|
3964
|
+
slots: routeSlotPayload
|
|
3965
|
+
});
|
|
2526
3966
|
const propsScript = `<script>
|
|
2527
|
-
window.__FARM_PROPS__ = ${serializeInlineValue(deferredProps.data)};
|
|
3967
|
+
window.__FARM_PROPS__ = ${serializeInlineValue(deferredProps.data.page)};
|
|
3968
|
+
window.__FARM_ROUTE_SLOTS__ = ${serializeInlineValue(deferredProps.data.slots)};
|
|
2528
3969
|
window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(deploymentId)};
|
|
2529
3970
|
window.__FARM_PATH__ = ${JSON.stringify(req.__FARM_ROUTE__ || req.url || "/")};
|
|
2530
3971
|
window.__FARM_IS_CLIENT__ = ${JSON.stringify(isClientComponent)};
|
|
@@ -2537,7 +3978,7 @@ window.__FARM_MANIFEST__ = ${JSON.stringify(clientManifest)};
|
|
|
2537
3978
|
window.__FARM_INTEGRATION_API_MANIFEST__ = ${JSON.stringify(getRegisteredIntegrationAPIManifest())};
|
|
2538
3979
|
${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(getFarmI18nClientSnapshot())};` : ""}
|
|
2539
3980
|
</script>`;
|
|
2540
|
-
const hydrationClickQueueScript = isClientComponent || req.__FARM_SHOULD_HYDRATE__ === true ? createPreHydrationClickQueueScript() : "";
|
|
3981
|
+
const hydrationClickQueueScript = isClientComponent || req.__FARM_SHOULD_HYDRATE__ === true || req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ === true ? createPreHydrationClickQueueScript() : "";
|
|
2541
3982
|
const {
|
|
2542
3983
|
title,
|
|
2543
3984
|
tags: metaTags,
|
|
@@ -2545,6 +3986,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
2545
3986
|
} = renderMetadataHead(req.__FARM_METADATA__);
|
|
2546
3987
|
const i18nSnapshot = getFarmI18nClientSnapshot();
|
|
2547
3988
|
const i18nAlternateTags = i18nSnapshot ? renderI18nAlternateLinks(req.__FARM_ROUTE__ || req.url || "/", i18nSnapshot) : "";
|
|
3989
|
+
const fontHead = renderFarmFontDevHead(this.config.root || process.cwd());
|
|
2548
3990
|
const streamRoot = React.createElement("div", { style: { display: "contents" } }, element);
|
|
2549
3991
|
const { pipe, abort } = renderToPipeableStream(streamRoot, {
|
|
2550
3992
|
onShellReady() {
|
|
@@ -2558,13 +4000,14 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
2558
4000
|
console.log(`[FARM STREAM] onShellReady at ${shellReadyMs}ms`);
|
|
2559
4001
|
}
|
|
2560
4002
|
const shell = `<!DOCTYPE html>
|
|
2561
|
-
<html lang="${
|
|
4003
|
+
<html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}>
|
|
2562
4004
|
<head>
|
|
2563
4005
|
<meta charset="utf-8">
|
|
2564
4006
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
2565
|
-
<meta name="farm-deployment-id" content="${
|
|
4007
|
+
<meta name="farm-deployment-id" content="${escapeHtmlAttribute2(deploymentId)}">
|
|
2566
4008
|
${hasFavicon ? "" : '<link rel="icon" href="data:,">'}
|
|
2567
4009
|
<title>${title}</title>${metaTags}${i18nAlternateTags}
|
|
4010
|
+
${fontHead}
|
|
2568
4011
|
<link rel="stylesheet" href="/src/app/globals.css" />
|
|
2569
4012
|
<script type="module" src="/@vite/client"></script>
|
|
2570
4013
|
${propsScript}
|
|
@@ -2635,7 +4078,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
2635
4078
|
route: observabilityRoute,
|
|
2636
4079
|
durationMs: Date.now() - streamStartTime
|
|
2637
4080
|
});
|
|
2638
|
-
|
|
4081
|
+
resolve5();
|
|
2639
4082
|
}
|
|
2640
4083
|
});
|
|
2641
4084
|
res.write(shell);
|
|
@@ -2646,9 +4089,13 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
2646
4089
|
},
|
|
2647
4090
|
onShellError(error) {
|
|
2648
4091
|
didError = true;
|
|
2649
|
-
if (!isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
|
|
4092
|
+
if (!isWebResponse(error) && !isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
|
|
2650
4093
|
logger.error(`SSR shell error: ${error}`);
|
|
2651
|
-
emitFarmEvent({
|
|
4094
|
+
emitFarmEvent({
|
|
4095
|
+
type: "render.error",
|
|
4096
|
+
route: observabilityRoute,
|
|
4097
|
+
error
|
|
4098
|
+
});
|
|
2652
4099
|
}
|
|
2653
4100
|
if (clearMiddlewareData) {
|
|
2654
4101
|
clearMiddlewareData();
|
|
@@ -2657,9 +4104,13 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
2657
4104
|
},
|
|
2658
4105
|
onError(error) {
|
|
2659
4106
|
didError = true;
|
|
2660
|
-
if (!isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
|
|
4107
|
+
if (!isWebResponse(error) && !isFarmRedirectError(error) && !isFarmNotFoundError(error)) {
|
|
2661
4108
|
logger.error(`SSR streaming error: ${error}`);
|
|
2662
|
-
emitFarmEvent({
|
|
4109
|
+
emitFarmEvent({
|
|
4110
|
+
type: "render.error",
|
|
4111
|
+
route: observabilityRoute,
|
|
4112
|
+
error
|
|
4113
|
+
});
|
|
2663
4114
|
}
|
|
2664
4115
|
}
|
|
2665
4116
|
});
|
|
@@ -2669,11 +4120,11 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
2669
4120
|
res.statusCode = 404;
|
|
2670
4121
|
const pathname = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`).pathname;
|
|
2671
4122
|
try {
|
|
2672
|
-
const appDir =
|
|
4123
|
+
const appDir = path5.join(this.config.root, this.config.srcDir, "app");
|
|
2673
4124
|
const notFoundExtensions = [".tsx", ".jsx", ".ts", ".js"];
|
|
2674
4125
|
let notFoundPath = null;
|
|
2675
4126
|
for (const ext of notFoundExtensions) {
|
|
2676
|
-
const checkPath =
|
|
4127
|
+
const checkPath = path5.join(appDir, `not-found${ext}`);
|
|
2677
4128
|
if (fs2.existsSync(checkPath)) {
|
|
2678
4129
|
notFoundPath = checkPath;
|
|
2679
4130
|
break;
|
|
@@ -2685,7 +4136,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
2685
4136
|
if (NotFoundComponent) {
|
|
2686
4137
|
let LayoutComponent = null;
|
|
2687
4138
|
for (const ext of notFoundExtensions) {
|
|
2688
|
-
const layoutPath =
|
|
4139
|
+
const layoutPath = path5.join(appDir, `layout${ext}`);
|
|
2689
4140
|
if (fs2.existsSync(layoutPath)) {
|
|
2690
4141
|
try {
|
|
2691
4142
|
const layoutModule = await this.routeManager.loadLayoutModule(layoutPath);
|
|
@@ -2766,14 +4217,16 @@ window.__FARM_INTEGRATION_API_MANIFEST__ = ${JSON.stringify(getRegisteredIntegra
|
|
|
2766
4217
|
${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue(i18nSnapshot)};` : ""}
|
|
2767
4218
|
</script>`;
|
|
2768
4219
|
const alternateLinks = i18nSnapshot ? renderI18nAlternateLinks(requestPath, i18nSnapshot) : "";
|
|
4220
|
+
const fontHead = renderFarmFontDevHead(this.config.root || process.cwd());
|
|
2769
4221
|
return `<!DOCTYPE html>
|
|
2770
|
-
<html lang="${
|
|
4222
|
+
<html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}>
|
|
2771
4223
|
<head>
|
|
2772
4224
|
<meta charset="utf-8">
|
|
2773
4225
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
2774
|
-
<meta name="farm-deployment-id" content="${
|
|
4226
|
+
<meta name="farm-deployment-id" content="${escapeHtmlAttribute2(this.getDeploymentId())}">
|
|
2775
4227
|
<link rel="icon" href="data:,">
|
|
2776
4228
|
<title>Farm.js App</title>${alternateLinks}
|
|
4229
|
+
${fontHead}
|
|
2777
4230
|
<link rel="stylesheet" href="/src/app/globals.css" />
|
|
2778
4231
|
<script type="module" src="/@vite/client"></script>
|
|
2779
4232
|
${integrationManifestScript}
|
|
@@ -2808,7 +4261,7 @@ __name(_ServerRenderer, "ServerRenderer");
|
|
|
2808
4261
|
var ServerRenderer = _ServerRenderer;
|
|
2809
4262
|
|
|
2810
4263
|
// src/app.ts
|
|
2811
|
-
import
|
|
4264
|
+
import path6 from "path";
|
|
2812
4265
|
var defaultDocsConfig = {
|
|
2813
4266
|
enabled: false,
|
|
2814
4267
|
entry: "/docs",
|
|
@@ -2826,17 +4279,14 @@ var _FarmApp = class _FarmApp {
|
|
|
2826
4279
|
_setDefaultFarmI18nRuntime(this.i18nRuntime);
|
|
2827
4280
|
this.viteServer = viteServer;
|
|
2828
4281
|
this.routeManager = new RouteManager(this.config, viteServer);
|
|
2829
|
-
this.serverRenderer = new ServerRenderer(
|
|
2830
|
-
this.config,
|
|
2831
|
-
this.routeManager,
|
|
2832
|
-
this.i18nRuntime
|
|
2833
|
-
);
|
|
4282
|
+
this.serverRenderer = new ServerRenderer(this.config, this.routeManager, this.i18nRuntime);
|
|
2834
4283
|
}
|
|
2835
4284
|
async initialize() {
|
|
2836
4285
|
if (process.env.FARM_VERBOSE) {
|
|
2837
4286
|
logger.info("Initializing Farm.js application...");
|
|
2838
4287
|
}
|
|
2839
4288
|
await initStorage(this.config.storage);
|
|
4289
|
+
await configureFarmCache(this.config.cache);
|
|
2840
4290
|
await this.i18nRuntime.initialize();
|
|
2841
4291
|
await this.verifyAppStructure();
|
|
2842
4292
|
await this.routeManager.discoverRoutes();
|
|
@@ -2868,6 +4318,8 @@ var _FarmApp = class _FarmApp {
|
|
|
2868
4318
|
preset: config.preset ?? "node-server",
|
|
2869
4319
|
deploy: config.deploy || {},
|
|
2870
4320
|
storage: config.storage || {},
|
|
4321
|
+
cache: config.cache || {},
|
|
4322
|
+
auth: isResolvedAuthConfig(config.auth) ? config.auth : resolveFarmAuthConfig(config.auth),
|
|
2871
4323
|
integrations: config.integrations || {},
|
|
2872
4324
|
plugins: config.plugins || [],
|
|
2873
4325
|
migrations: config.migrations || { commands: [] },
|
|
@@ -2919,10 +4371,10 @@ var _FarmApp = class _FarmApp {
|
|
|
2919
4371
|
);
|
|
2920
4372
|
}
|
|
2921
4373
|
const rootLayoutPaths = appDirs.flatMap((appDir) => [
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
4374
|
+
path6.join(appDir, "layout.tsx"),
|
|
4375
|
+
path6.join(appDir, "layout.ts"),
|
|
4376
|
+
path6.join(appDir, "layout.jsx"),
|
|
4377
|
+
path6.join(appDir, "layout.js")
|
|
2926
4378
|
]);
|
|
2927
4379
|
const hasRootLayout = await Promise.all(rootLayoutPaths.map((p) => fileExists(p))).then(
|
|
2928
4380
|
(results) => results.some(Boolean)
|
|
@@ -2940,6 +4392,12 @@ function isResolvedI18nConfig(value) {
|
|
|
2940
4392
|
return Boolean(value && typeof value === "object" && "enabled" in value);
|
|
2941
4393
|
}
|
|
2942
4394
|
__name(isResolvedI18nConfig, "isResolvedI18nConfig");
|
|
4395
|
+
function isResolvedAuthConfig(value) {
|
|
4396
|
+
return Boolean(
|
|
4397
|
+
value && typeof value === "object" && "enabled" in value && "emailAndPassword" in value && "database" in value
|
|
4398
|
+
);
|
|
4399
|
+
}
|
|
4400
|
+
__name(isResolvedAuthConfig, "isResolvedAuthConfig");
|
|
2943
4401
|
function createFarmApp(config, viteServer) {
|
|
2944
4402
|
return new FarmApp(config, viteServer);
|
|
2945
4403
|
}
|
|
@@ -3275,11 +4733,11 @@ __name(_HMRManager, "HMRManager");
|
|
|
3275
4733
|
var HMRManager = _HMRManager;
|
|
3276
4734
|
|
|
3277
4735
|
// src/type-artifacts.ts
|
|
3278
|
-
import { mkdirSync as mkdirSync4 } from "fs";
|
|
3279
|
-
import { dirname as dirname3, join as join4, resolve as
|
|
4736
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync2, unlinkSync } from "fs";
|
|
4737
|
+
import { dirname as dirname3, join as join4, resolve as resolve3 } from "path";
|
|
3280
4738
|
|
|
3281
4739
|
// src/routing/generate-route-types.ts
|
|
3282
|
-
import * as
|
|
4740
|
+
import * as path7 from "path";
|
|
3283
4741
|
import * as fs3 from "fs";
|
|
3284
4742
|
function routeSegmentsToTsTypeLiteral(segments) {
|
|
3285
4743
|
if (segments.length === 0) return '"/"';
|
|
@@ -3321,25 +4779,30 @@ function createRoutePattern(route) {
|
|
|
3321
4779
|
__name(createRoutePattern, "createRoutePattern");
|
|
3322
4780
|
var DEFAULT_OUT_FILE = "farm-routes.d.ts";
|
|
3323
4781
|
async function generateRouteTypes(options) {
|
|
3324
|
-
const
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
4782
|
+
const root = path7.resolve(options.root);
|
|
4783
|
+
const srcDir = options.srcDir || "src";
|
|
4784
|
+
const outFile = options.outFile || DEFAULT_OUT_FILE;
|
|
4785
|
+
const outPath = path7.isAbsolute(outFile) ? outFile : path7.join(root, srcDir, outFile);
|
|
4786
|
+
const content = await createRouteTypeDeclarations(options, outPath);
|
|
4787
|
+
fs3.mkdirSync(path7.dirname(outPath), { recursive: true });
|
|
4788
|
+
writeFileIfChanged(outPath, content);
|
|
4789
|
+
return outPath;
|
|
4790
|
+
}
|
|
4791
|
+
__name(generateRouteTypes, "generateRouteTypes");
|
|
4792
|
+
async function createRouteTypeDeclarations(options, outPath) {
|
|
4793
|
+
const { root, srcDir = "src", extraRoutes = [], suppressLintOnLink = false } = options;
|
|
3331
4794
|
const sourceRoots = options.sourceRoots ?? [{ name: "project", root, srcDir, layer: false }];
|
|
3332
|
-
const outPath = path6.join(root, srcDir, outFile);
|
|
3333
4795
|
const patterns = /* @__PURE__ */ new Set();
|
|
3334
4796
|
const glob = await import("fast-glob");
|
|
3335
4797
|
for (const source of sourceRoots) {
|
|
3336
|
-
const appDir =
|
|
4798
|
+
const appDir = path7.join(source.root, source.srcDir, "app");
|
|
3337
4799
|
if (fs3.existsSync(appDir)) {
|
|
3338
4800
|
const pageFiles = await glob.default("**/page.{ts,tsx,js,jsx,md,mdx}", {
|
|
3339
4801
|
cwd: appDir,
|
|
3340
4802
|
absolute: false
|
|
3341
4803
|
});
|
|
3342
4804
|
for (const file of pageFiles) {
|
|
4805
|
+
if (parseRouteSlotFile(file)) continue;
|
|
3343
4806
|
const route = parseRoutePath(file);
|
|
3344
4807
|
if (route.type === "page") {
|
|
3345
4808
|
const pattern = createRoutePattern(route);
|
|
@@ -3361,18 +4824,19 @@ async function generateRouteTypes(options) {
|
|
|
3361
4824
|
const patternLiterals = sortedPatterns.map(routePatternToRouteLiteral);
|
|
3362
4825
|
const routePathType = suppressLintOnLink ? "string" : typeLiterals.length ? typeLiterals.join(" | ") : "never";
|
|
3363
4826
|
const routePatternType = suppressLintOnLink ? "string" : patternLiterals.length ? patternLiterals.join(" | ") : "never";
|
|
4827
|
+
const routeTypesImportPath = `./${path7.basename(outPath).replace(/\.d\.ts$/, "")}`;
|
|
3364
4828
|
const augmentationBlock = suppressLintOnLink ? "" : `
|
|
3365
4829
|
declare module "@farm.js/core/client" {
|
|
3366
4830
|
interface LinkDefaultRoute {
|
|
3367
|
-
_: import(
|
|
3368
|
-
pattern: import(
|
|
4831
|
+
_: import(${JSON.stringify(routeTypesImportPath)}).RoutePath;
|
|
4832
|
+
pattern: import(${JSON.stringify(routeTypesImportPath)}).RoutePattern;
|
|
3369
4833
|
}
|
|
3370
4834
|
}
|
|
3371
4835
|
|
|
3372
4836
|
declare module "@farm.js/core" {
|
|
3373
4837
|
interface LinkDefaultRoute {
|
|
3374
|
-
_: import(
|
|
3375
|
-
pattern: import(
|
|
4838
|
+
_: import(${JSON.stringify(routeTypesImportPath)}).RoutePath;
|
|
4839
|
+
pattern: import(${JSON.stringify(routeTypesImportPath)}).RoutePattern;
|
|
3376
4840
|
}
|
|
3377
4841
|
// Ensure root import ("@farm.js/core") uses the same typed Link signature as client entry.
|
|
3378
4842
|
const Link: typeof import("@farm.js/core/client").Link;
|
|
@@ -3381,8 +4845,8 @@ declare module "@farm.js/core" {
|
|
|
3381
4845
|
// Internal declaration path used by @farm.js/core root type re-exports.
|
|
3382
4846
|
declare module "@farm.js/core/dist/client.js" {
|
|
3383
4847
|
interface LinkDefaultRoute {
|
|
3384
|
-
_: import(
|
|
3385
|
-
pattern: import(
|
|
4848
|
+
_: import(${JSON.stringify(routeTypesImportPath)}).RoutePath;
|
|
4849
|
+
pattern: import(${JSON.stringify(routeTypesImportPath)}).RoutePattern;
|
|
3386
4850
|
}
|
|
3387
4851
|
}
|
|
3388
4852
|
`;
|
|
@@ -3394,19 +4858,17 @@ declare module "@farm.js/core/dist/client.js" {
|
|
|
3394
4858
|
export type RoutePath = ${routePathType};
|
|
3395
4859
|
export type RoutePattern = ${routePatternType};${augmentationBlock}
|
|
3396
4860
|
`;
|
|
3397
|
-
|
|
3398
|
-
writeFileIfChanged(outPath, content);
|
|
3399
|
-
return outPath;
|
|
4861
|
+
return content;
|
|
3400
4862
|
}
|
|
3401
|
-
__name(
|
|
4863
|
+
__name(createRouteTypeDeclarations, "createRouteTypeDeclarations");
|
|
3402
4864
|
|
|
3403
4865
|
// src/image-types.ts
|
|
3404
4866
|
import { mkdirSync as mkdirSync2 } from "fs";
|
|
3405
|
-
import
|
|
4867
|
+
import path8 from "path";
|
|
3406
4868
|
var FARM_STATIC_IMAGE_EXTENSIONS = ["avif", "gif", "jpeg", "jpg", "png", "webp"];
|
|
3407
4869
|
function generateFarmImageTypes(options) {
|
|
3408
|
-
const outputPath = options.outFile ?
|
|
3409
|
-
mkdirSync2(
|
|
4870
|
+
const outputPath = options.outFile ? path8.resolve(options.root, options.outFile) : path8.join(options.root, options.srcDir || "src", "farm-images.d.ts");
|
|
4871
|
+
mkdirSync2(path8.dirname(outputPath), { recursive: true });
|
|
3410
4872
|
writeFileIfChanged(outputPath, createFarmImageTypeDeclarations());
|
|
3411
4873
|
return outputPath;
|
|
3412
4874
|
}
|
|
@@ -3435,11 +4897,11 @@ __name(createFarmImageTypeDeclarations, "createFarmImageTypeDeclarations");
|
|
|
3435
4897
|
|
|
3436
4898
|
// src/i18n/type-generator.ts
|
|
3437
4899
|
import { mkdirSync as mkdirSync3 } from "fs";
|
|
3438
|
-
import { dirname as dirname2, join as join3, resolve } from "path";
|
|
4900
|
+
import { dirname as dirname2, join as join3, resolve as resolve2 } from "path";
|
|
3439
4901
|
async function generateFarmI18nTypes(options) {
|
|
3440
4902
|
if (!options.config.enabled) return void 0;
|
|
3441
4903
|
const { signatures } = await readFarmI18nCatalogs(options.config);
|
|
3442
|
-
const outFile = options.outFile ?
|
|
4904
|
+
const outFile = options.outFile ? resolve2(options.root, options.outFile) : join3(resolve2(options.root), options.srcDir || "src", "farm-i18n.d.ts");
|
|
3443
4905
|
const content = renderFarmI18nTypes(options.config.locales, signatures);
|
|
3444
4906
|
mkdirSync3(dirname2(outFile), { recursive: true });
|
|
3445
4907
|
writeFileIfChanged(outFile, content);
|
|
@@ -3489,7 +4951,7 @@ __name(argumentType, "argumentType");
|
|
|
3489
4951
|
|
|
3490
4952
|
// src/type-artifacts.ts
|
|
3491
4953
|
async function generateFarmTypeArtifacts(options) {
|
|
3492
|
-
const root =
|
|
4954
|
+
const root = resolve3(options.root);
|
|
3493
4955
|
const srcDir = options.srcDir || "src";
|
|
3494
4956
|
const shouldGenerateRoutes = options.routes !== false;
|
|
3495
4957
|
const shouldGenerateApi = options.api !== false;
|
|
@@ -3501,7 +4963,10 @@ async function generateFarmTypeArtifacts(options) {
|
|
|
3501
4963
|
const result = {
|
|
3502
4964
|
apiRoutes: []
|
|
3503
4965
|
};
|
|
3504
|
-
|
|
4966
|
+
const unifiedTypesPath = join4(root, srcDir, "farm.d.ts");
|
|
4967
|
+
const shouldRefreshUnifiedTypes = shouldGenerateRoutes && !options.routeTypesOutFile || shouldGenerateEnv && !options.envTypesOutFile || shouldGenerateI18n && !options.i18nTypesOutFile;
|
|
4968
|
+
const unifiedSections = [];
|
|
4969
|
+
if (shouldRefreshUnifiedTypes && !options.routeTypesOutFile) {
|
|
3505
4970
|
const routeOptions = {
|
|
3506
4971
|
root,
|
|
3507
4972
|
srcDir,
|
|
@@ -3509,37 +4974,62 @@ async function generateFarmTypeArtifacts(options) {
|
|
|
3509
4974
|
suppressLintOnLink: options.suppressLintOnLink,
|
|
3510
4975
|
sourceRoots
|
|
3511
4976
|
};
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
result.routeTypesPath = await generateRouteTypes(
|
|
4977
|
+
unifiedSections.push(await createRouteTypeDeclarations(routeOptions, unifiedTypesPath));
|
|
4978
|
+
result.routeTypesPath = unifiedTypesPath;
|
|
4979
|
+
} else if (shouldGenerateRoutes) {
|
|
4980
|
+
result.routeTypesPath = await generateRouteTypes({
|
|
4981
|
+
root,
|
|
4982
|
+
srcDir,
|
|
4983
|
+
outFile: options.routeTypesOutFile,
|
|
4984
|
+
extraRoutes: options.extraRoutes || [],
|
|
4985
|
+
suppressLintOnLink: options.suppressLintOnLink,
|
|
4986
|
+
sourceRoots
|
|
4987
|
+
});
|
|
3516
4988
|
}
|
|
3517
4989
|
if (shouldGenerateApi) {
|
|
3518
4990
|
const generator = new APITypeGenerator(appDirs);
|
|
3519
4991
|
const apiRoutes = generator.scanAPIRoutes();
|
|
3520
|
-
const apiTypesPath = options.apiTypesOutFile ?
|
|
4992
|
+
const apiTypesPath = options.apiTypesOutFile ? resolve3(root, options.apiTypesOutFile) : join4(root, srcDir, "lib", "api.generated.ts");
|
|
3521
4993
|
const content = generator.generateAPIRouter(apiRoutes, { outFile: apiTypesPath });
|
|
3522
4994
|
mkdirSync4(dirname3(apiTypesPath), { recursive: true });
|
|
3523
4995
|
writeFileIfChanged(apiTypesPath, content);
|
|
3524
4996
|
result.apiTypesPath = apiTypesPath;
|
|
3525
4997
|
result.apiRoutes = apiRoutes;
|
|
3526
4998
|
}
|
|
3527
|
-
if (
|
|
4999
|
+
if (shouldRefreshUnifiedTypes && !options.envTypesOutFile) {
|
|
5000
|
+
unifiedSections.push(
|
|
5001
|
+
createEnvTypeDeclarations(
|
|
5002
|
+
{
|
|
5003
|
+
root,
|
|
5004
|
+
srcDir,
|
|
5005
|
+
configPath: options.configPath,
|
|
5006
|
+
layerConfigPaths: (options.layers ?? []).map((layer) => layer.configFile).filter((configFile) => Boolean(configFile))
|
|
5007
|
+
},
|
|
5008
|
+
unifiedTypesPath
|
|
5009
|
+
)
|
|
5010
|
+
);
|
|
5011
|
+
result.envTypesPath = unifiedTypesPath;
|
|
5012
|
+
} else if (shouldGenerateEnv) {
|
|
3528
5013
|
result.envTypesPath = await generateEnvTypes({
|
|
3529
5014
|
root,
|
|
3530
5015
|
srcDir,
|
|
3531
5016
|
outFile: options.envTypesOutFile,
|
|
5017
|
+
configPath: options.configPath,
|
|
3532
5018
|
layerConfigPaths: (options.layers ?? []).map((layer) => layer.configFile).filter((configFile) => Boolean(configFile))
|
|
3533
5019
|
});
|
|
3534
5020
|
}
|
|
3535
|
-
if (shouldGenerateImages) {
|
|
5021
|
+
if (shouldGenerateImages && options.imageTypesOutFile) {
|
|
3536
5022
|
result.imageTypesPath = generateFarmImageTypes({
|
|
3537
5023
|
root,
|
|
3538
5024
|
srcDir,
|
|
3539
5025
|
outFile: options.imageTypesOutFile
|
|
3540
5026
|
});
|
|
3541
5027
|
}
|
|
3542
|
-
if (
|
|
5028
|
+
if (shouldRefreshUnifiedTypes && options.i18nConfig?.enabled && !options.i18nTypesOutFile) {
|
|
5029
|
+
const { signatures } = await readFarmI18nCatalogs(options.i18nConfig);
|
|
5030
|
+
unifiedSections.push(renderFarmI18nTypes(options.i18nConfig.locales, signatures));
|
|
5031
|
+
result.i18nTypesPath = unifiedTypesPath;
|
|
5032
|
+
} else if (shouldGenerateI18n && options.i18nConfig) {
|
|
3543
5033
|
result.i18nTypesPath = await generateFarmI18nTypes({
|
|
3544
5034
|
root,
|
|
3545
5035
|
srcDir,
|
|
@@ -3547,17 +5037,50 @@ async function generateFarmTypeArtifacts(options) {
|
|
|
3547
5037
|
outFile: options.i18nTypesOutFile
|
|
3548
5038
|
});
|
|
3549
5039
|
}
|
|
5040
|
+
if (shouldRefreshUnifiedTypes) {
|
|
5041
|
+
mkdirSync4(dirname3(unifiedTypesPath), { recursive: true });
|
|
5042
|
+
writeFileIfChanged(
|
|
5043
|
+
unifiedTypesPath,
|
|
5044
|
+
`/**
|
|
5045
|
+
* Generated by Farm.js. Do not edit.
|
|
5046
|
+
* Contains project-specific route, environment, and internationalization types.
|
|
5047
|
+
*/
|
|
5048
|
+
|
|
5049
|
+
import "@farm.js/core/image";
|
|
5050
|
+
|
|
5051
|
+
${unifiedSections.join("\n")}`
|
|
5052
|
+
);
|
|
5053
|
+
result.typesPath = unifiedTypesPath;
|
|
5054
|
+
removeLegacyTypeArtifacts(root, srcDir);
|
|
5055
|
+
}
|
|
3550
5056
|
return result;
|
|
3551
5057
|
}
|
|
3552
5058
|
__name(generateFarmTypeArtifacts, "generateFarmTypeArtifacts");
|
|
5059
|
+
var LEGACY_TYPE_ARTIFACTS = [
|
|
5060
|
+
["farm-routes.d.ts", "Auto-generated route types"],
|
|
5061
|
+
["farm-env.d.ts", "Auto-generated env types"],
|
|
5062
|
+
["farm-images.d.ts", "Generated by Farm.js"],
|
|
5063
|
+
["farm-i18n.d.ts", "Generated by Farm.js"]
|
|
5064
|
+
];
|
|
5065
|
+
function removeLegacyTypeArtifacts(root, srcDir) {
|
|
5066
|
+
for (const [fileName, marker] of LEGACY_TYPE_ARTIFACTS) {
|
|
5067
|
+
const filePath = join4(root, srcDir, fileName);
|
|
5068
|
+
if (!existsSync4(filePath)) continue;
|
|
5069
|
+
const source = readFileSync2(filePath, "utf8");
|
|
5070
|
+
if (source.includes(marker)) {
|
|
5071
|
+
unlinkSync(filePath);
|
|
5072
|
+
}
|
|
5073
|
+
}
|
|
5074
|
+
}
|
|
5075
|
+
__name(removeLegacyTypeArtifacts, "removeLegacyTypeArtifacts");
|
|
3553
5076
|
|
|
3554
5077
|
// src/vite.ts
|
|
3555
5078
|
import * as fs4 from "fs";
|
|
3556
|
-
import * as
|
|
5079
|
+
import * as path10 from "path";
|
|
3557
5080
|
|
|
3558
5081
|
// src/image-vite.ts
|
|
3559
|
-
import { readFile as
|
|
3560
|
-
import
|
|
5082
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
5083
|
+
import path9 from "path";
|
|
3561
5084
|
import { imageSize as imageSize2 } from "image-size";
|
|
3562
5085
|
var FARM_IMAGE_ID_PREFIX = "\0farm:image:";
|
|
3563
5086
|
var STATIC_IMAGE_RE = /\.(?:avif|gif|jpe?g|png|webp)$/i;
|
|
@@ -3591,7 +5114,7 @@ function farmImageImportsPlugin() {
|
|
|
3591
5114
|
}
|
|
3592
5115
|
__name(farmImageImportsPlugin, "farmImageImportsPlugin");
|
|
3593
5116
|
async function createStaticImageModule(filePath, sourceDeclaration) {
|
|
3594
|
-
const bytes = await
|
|
5117
|
+
const bytes = await readFile4(filePath);
|
|
3595
5118
|
const dimensions = imageSize2(bytes);
|
|
3596
5119
|
if (!dimensions.width || !dimensions.height) {
|
|
3597
5120
|
throw new Error(`Could not determine image dimensions for ${filePath}`);
|
|
@@ -3629,7 +5152,7 @@ var ALL_TYPE_ARTIFACTS = {
|
|
|
3629
5152
|
routes: true,
|
|
3630
5153
|
api: true,
|
|
3631
5154
|
env: true,
|
|
3632
|
-
images:
|
|
5155
|
+
images: false,
|
|
3633
5156
|
i18n: true
|
|
3634
5157
|
};
|
|
3635
5158
|
var createEmptyTypeArtifactSelection = /* @__PURE__ */ __name(() => ({
|
|
@@ -3666,7 +5189,7 @@ function loadFarmWorkflowsDevRuntime() {
|
|
|
3666
5189
|
}
|
|
3667
5190
|
__name(loadFarmWorkflowsDevRuntime, "loadFarmWorkflowsDevRuntime");
|
|
3668
5191
|
function loadFarmDevtoolsSnapshotRuntime() {
|
|
3669
|
-
return import("./devtools-
|
|
5192
|
+
return import("./devtools-A22KUJZT.mjs");
|
|
3670
5193
|
}
|
|
3671
5194
|
__name(loadFarmDevtoolsSnapshotRuntime, "loadFarmDevtoolsSnapshotRuntime");
|
|
3672
5195
|
function loadFarmDevtoolsUIRuntime() {
|
|
@@ -3674,7 +5197,7 @@ function loadFarmDevtoolsUIRuntime() {
|
|
|
3674
5197
|
}
|
|
3675
5198
|
__name(loadFarmDevtoolsUIRuntime, "loadFarmDevtoolsUIRuntime");
|
|
3676
5199
|
function loadFarmDevtoolsClientRuntime() {
|
|
3677
|
-
return import("./devtools-client-
|
|
5200
|
+
return import("./devtools-client-3XRTBND5.mjs");
|
|
3678
5201
|
}
|
|
3679
5202
|
__name(loadFarmDevtoolsClientRuntime, "loadFarmDevtoolsClientRuntime");
|
|
3680
5203
|
function farmI18nClientBridgePlugin() {
|
|
@@ -3829,7 +5352,7 @@ function isResolvedEnvScope(value) {
|
|
|
3829
5352
|
}
|
|
3830
5353
|
__name(isResolvedEnvScope, "isResolvedEnvScope");
|
|
3831
5354
|
function isPotentialProgrammaticRouteSourceFile(normalizedFile, srcDirSlug) {
|
|
3832
|
-
return normalizedFile.startsWith(`${srcDirSlug}/`) && /\.(ts|tsx|js|jsx)$/.test(normalizedFile) &&
|
|
5355
|
+
return normalizedFile.startsWith(`${srcDirSlug}/`) && /\.(ts|tsx|js|jsx)$/.test(normalizedFile) && !normalizedFile.endsWith(".d.ts") && !normalizedFile.endsWith("/farm-routes.d.ts") && !normalizedFile.endsWith("/farm-env.d.ts") && !normalizedFile.endsWith("/lib/api.generated.ts");
|
|
3833
5356
|
}
|
|
3834
5357
|
__name(isPotentialProgrammaticRouteSourceFile, "isPotentialProgrammaticRouteSourceFile");
|
|
3835
5358
|
function fileContainsProgrammaticPageRoute(file) {
|
|
@@ -3845,7 +5368,7 @@ function fileContainsProgrammaticPageRoute(file) {
|
|
|
3845
5368
|
__name(fileContainsProgrammaticPageRoute, "fileContainsProgrammaticPageRoute");
|
|
3846
5369
|
function rewriteEarlySsrRelativeImports(options) {
|
|
3847
5370
|
const cleanId = options.id.split("?", 1)[0];
|
|
3848
|
-
if (!
|
|
5371
|
+
if (!path10.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
|
|
3849
5372
|
return null;
|
|
3850
5373
|
}
|
|
3851
5374
|
const replacements = [];
|
|
@@ -3865,7 +5388,7 @@ function rewriteEarlySsrRelativeImports(options) {
|
|
|
3865
5388
|
const suffixIndex = source.value.search(/[?#]/);
|
|
3866
5389
|
const sourcePath = suffixIndex === -1 ? source.value : source.value.slice(0, suffixIndex);
|
|
3867
5390
|
const suffix = suffixIndex === -1 ? "" : source.value.slice(suffixIndex);
|
|
3868
|
-
const resolvedPath =
|
|
5391
|
+
const resolvedPath = path10.resolve(path10.dirname(cleanId), sourcePath);
|
|
3869
5392
|
replacements.push({
|
|
3870
5393
|
start: source.start,
|
|
3871
5394
|
end: source.end,
|
|
@@ -3909,6 +5432,11 @@ function isFarmConfigFile(file, root) {
|
|
|
3909
5432
|
__name(isFarmConfigFile, "isFarmConfigFile");
|
|
3910
5433
|
function farmPlugin(options = {}, initialPluginManager) {
|
|
3911
5434
|
const imageImports = farmImageImportsPlugin();
|
|
5435
|
+
const fontImports = farmFontImportsPlugin({
|
|
5436
|
+
root: options.root,
|
|
5437
|
+
basePath: options.basePath,
|
|
5438
|
+
publicDir: options.publicDir
|
|
5439
|
+
});
|
|
3912
5440
|
let farmApp;
|
|
3913
5441
|
let server;
|
|
3914
5442
|
let hmrManager;
|
|
@@ -3945,15 +5473,21 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
3945
5473
|
...layerRoots.length ? {
|
|
3946
5474
|
server: {
|
|
3947
5475
|
fs: {
|
|
3948
|
-
allow: [
|
|
5476
|
+
allow: [path10.resolve(options.root || process.cwd()), ...layerRoots]
|
|
3949
5477
|
}
|
|
3950
5478
|
}
|
|
3951
5479
|
} : {}
|
|
3952
5480
|
};
|
|
3953
5481
|
},
|
|
3954
5482
|
async configResolved(config) {
|
|
5483
|
+
if (typeof fontImports.configResolved === "function") {
|
|
5484
|
+
await fontImports.configResolved.call(this, config);
|
|
5485
|
+
}
|
|
3955
5486
|
},
|
|
3956
5487
|
async configureServer(viteServer) {
|
|
5488
|
+
if (typeof fontImports.configureServer === "function") {
|
|
5489
|
+
await fontImports.configureServer.call(this, viteServer);
|
|
5490
|
+
}
|
|
3957
5491
|
server = viteServer;
|
|
3958
5492
|
const pm = initialPluginManager;
|
|
3959
5493
|
const emitPluginError = /* @__PURE__ */ __name(async (phase, error, meta) => {
|
|
@@ -3970,9 +5504,9 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
3970
5504
|
},
|
|
3971
5505
|
server
|
|
3972
5506
|
);
|
|
3973
|
-
const globalsCSSPath =
|
|
5507
|
+
const globalsCSSPath = path10.join(server.config.root, "src/app/globals.css");
|
|
3974
5508
|
if (!fs4.existsSync(globalsCSSPath)) {
|
|
3975
|
-
const appDir =
|
|
5509
|
+
const appDir = path10.join(server.config.root, "src/app");
|
|
3976
5510
|
if (!fs4.existsSync(appDir)) {
|
|
3977
5511
|
fs4.mkdirSync(appDir, { recursive: true });
|
|
3978
5512
|
}
|
|
@@ -3994,10 +5528,10 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
3994
5528
|
});
|
|
3995
5529
|
}
|
|
3996
5530
|
const sourceRoots = getFarmSourceRoots(farmConfig);
|
|
3997
|
-
server.watcher.add(sourceRoots.map((source) =>
|
|
5531
|
+
server.watcher.add(sourceRoots.map((source) => path10.join(source.root, source.srcDir)));
|
|
3998
5532
|
if (farmConfig.i18n.enabled) {
|
|
3999
5533
|
server.watcher.add(
|
|
4000
|
-
farmConfig.i18n.messages.includes("{locale}") ?
|
|
5534
|
+
farmConfig.i18n.messages.includes("{locale}") ? path10.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
|
|
4001
5535
|
);
|
|
4002
5536
|
}
|
|
4003
5537
|
const workflowConfig = farmConfig.workflows;
|
|
@@ -4007,7 +5541,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4007
5541
|
...farmDocsDevRuntime?.getFarmDocsRouteTypeEntries(farmConfig.docs) ?? []
|
|
4008
5542
|
], "getExtraRouteTypes");
|
|
4009
5543
|
const appDirSlugs = sourceRoots.map(
|
|
4010
|
-
(source) =>
|
|
5544
|
+
(source) => path10.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
|
|
4011
5545
|
);
|
|
4012
5546
|
const generateTypeArtifacts = /* @__PURE__ */ __name(async (reason, selection = ALL_TYPE_ARTIFACTS, log = false) => {
|
|
4013
5547
|
try {
|
|
@@ -4047,7 +5581,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4047
5581
|
}, "generateTypeArtifacts");
|
|
4048
5582
|
await generateTypeArtifacts("startup");
|
|
4049
5583
|
const srcDirSlugs = sourceRoots.map(
|
|
4050
|
-
(source) =>
|
|
5584
|
+
(source) => path10.join(source.root, source.srcDir).replace(/\\/g, "/")
|
|
4051
5585
|
);
|
|
4052
5586
|
const layerConfigFiles = new Set(
|
|
4053
5587
|
farmConfig.layers.map((layer) => layer.configFile?.replace(/\\/g, "/")).filter((file) => Boolean(file))
|
|
@@ -4072,7 +5606,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4072
5606
|
}, "isProgrammaticRouteSourceFile");
|
|
4073
5607
|
const isAppRuntimeFile = /* @__PURE__ */ __name((file) => {
|
|
4074
5608
|
const normalized = file.replace(/\\/g, "/");
|
|
4075
|
-
return appDirSlugs.some((appDir) => normalized.startsWith(`${appDir}/`)) && /\/(?:page|layout|loading|error|middleware|route)\.(?:ts|tsx|js|jsx|md|mdx)$|\/(?:opengraph-image|twitter-image)(?:\.(?:ts|tsx|js|jsx|png|jpg|jpeg|gif|webp)|\.alt\.txt)$/.test(
|
|
5609
|
+
return appDirSlugs.some((appDir) => normalized.startsWith(`${appDir}/`)) && /\/(?:page|default|layout|loading|error|middleware|route)\.(?:ts|tsx|js|jsx|md|mdx)$|\/(?:opengraph-image|twitter-image)(?:\.(?:ts|tsx|js|jsx|png|jpg|jpeg|gif|webp)|\.alt\.txt)$/.test(
|
|
4076
5610
|
normalized
|
|
4077
5611
|
);
|
|
4078
5612
|
}, "isAppRuntimeFile");
|
|
@@ -4165,7 +5699,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4165
5699
|
await apiRouteManager.discoverRoutes();
|
|
4166
5700
|
let discoveredWorkflows = [];
|
|
4167
5701
|
const hasWorkflowDirectory = workflowConfig.enabled && workflowConfig.dirs.some(
|
|
4168
|
-
(dir) => fs4.existsSync(
|
|
5702
|
+
(dir) => fs4.existsSync(path10.isAbsolute(dir) ? dir : path10.join(farmConfig.root, dir))
|
|
4169
5703
|
);
|
|
4170
5704
|
if (hasWorkflowDirectory) {
|
|
4171
5705
|
const { createFarmWorkflowRequestHandler, discoverFarmWorkflows } = await loadFarmWorkflowsDevRuntime();
|
|
@@ -4243,14 +5777,14 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4243
5777
|
farmDocsDevRuntime ? [
|
|
4244
5778
|
[
|
|
4245
5779
|
"/assets/Geist-Variable-CrgPqtmy.woff2",
|
|
4246
|
-
|
|
5780
|
+
path10.join(
|
|
4247
5781
|
farmConfig.root,
|
|
4248
5782
|
"node_modules/geist/dist/fonts/geist-sans/Geist-Variable.woff2"
|
|
4249
5783
|
)
|
|
4250
5784
|
],
|
|
4251
5785
|
[
|
|
4252
5786
|
"/assets/GeistMono-Variable-BNLlm6Cd.woff2",
|
|
4253
|
-
|
|
5787
|
+
path10.join(
|
|
4254
5788
|
farmConfig.root,
|
|
4255
5789
|
"node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2"
|
|
4256
5790
|
)
|
|
@@ -4414,12 +5948,13 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4414
5948
|
config: farmApp.getConfig().mdx,
|
|
4415
5949
|
resolveSource: /* @__PURE__ */ __name(async (pathname2) => {
|
|
4416
5950
|
const match = farmApp.getRouteManager().matchRoute(pathname2);
|
|
4417
|
-
|
|
5951
|
+
const sourcePath = match.route?.markdownSourcePath || (match.route && isFarmMarkdownPageFile(match.route.modulePath) ? match.route.modulePath : null);
|
|
5952
|
+
if (!sourcePath) {
|
|
4418
5953
|
return null;
|
|
4419
5954
|
}
|
|
4420
5955
|
return {
|
|
4421
|
-
source: await fs4.promises.readFile(
|
|
4422
|
-
filePath:
|
|
5956
|
+
source: await fs4.promises.readFile(sourcePath, "utf8"),
|
|
5957
|
+
filePath: sourcePath
|
|
4423
5958
|
};
|
|
4424
5959
|
}, "resolveSource")
|
|
4425
5960
|
});
|
|
@@ -4440,16 +5975,37 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4440
5975
|
await sendWebResponse(res, markdownResponse);
|
|
4441
5976
|
return;
|
|
4442
5977
|
}
|
|
5978
|
+
const markdownPageTarget = resolveMarkdownMirrorTarget(
|
|
5979
|
+
farmApp.getConfig().md,
|
|
5980
|
+
requestPathname,
|
|
5981
|
+
{
|
|
5982
|
+
accept: "text/markdown"
|
|
5983
|
+
}
|
|
5984
|
+
);
|
|
5985
|
+
if (markdownPageTarget && farmApp.getRouteManager().matchRoute(markdownPageTarget.pathname).route) {
|
|
5986
|
+
const vary = res.getHeader("Vary");
|
|
5987
|
+
const varyValues = String(vary || "").split(",").map((value) => value.trim()).filter(Boolean);
|
|
5988
|
+
if (!varyValues.some((value) => value.toLowerCase() === "accept")) {
|
|
5989
|
+
res.setHeader("Vary", [...varyValues, "Accept"].join(", "));
|
|
5990
|
+
}
|
|
5991
|
+
const alternatePath = markdownPageTarget.pathname === "/" ? "/index.md" : `${markdownPageTarget.pathname}.md`;
|
|
5992
|
+
const alternateLink = `<${alternatePath}>; rel="alternate"; type="text/markdown"`;
|
|
5993
|
+
const currentLink = res.getHeader("Link");
|
|
5994
|
+
res.setHeader(
|
|
5995
|
+
"Link",
|
|
5996
|
+
currentLink ? `${String(currentLink)}, ${alternateLink}` : alternateLink
|
|
5997
|
+
);
|
|
5998
|
+
}
|
|
4443
5999
|
if (workflowHandler && (requestPathname === workflowConfig.route || requestPathname.startsWith(`${workflowConfig.route}/`))) {
|
|
4444
6000
|
let workflowBody;
|
|
4445
6001
|
if (requestMethod !== "GET" && requestMethod !== "HEAD") {
|
|
4446
|
-
workflowBody = await new Promise((
|
|
6002
|
+
workflowBody = await new Promise((resolve5) => {
|
|
4447
6003
|
let data = "";
|
|
4448
6004
|
req.on("data", (chunk) => {
|
|
4449
6005
|
data += chunk;
|
|
4450
6006
|
});
|
|
4451
6007
|
req.on("end", () => {
|
|
4452
|
-
|
|
6008
|
+
resolve5(data);
|
|
4453
6009
|
});
|
|
4454
6010
|
});
|
|
4455
6011
|
}
|
|
@@ -4492,13 +6048,13 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4492
6048
|
}
|
|
4493
6049
|
let body;
|
|
4494
6050
|
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
4495
|
-
body = await new Promise((
|
|
6051
|
+
body = await new Promise((resolve5) => {
|
|
4496
6052
|
let data = "";
|
|
4497
6053
|
req.on("data", (chunk) => {
|
|
4498
6054
|
data += chunk;
|
|
4499
6055
|
});
|
|
4500
6056
|
req.on("end", () => {
|
|
4501
|
-
|
|
6057
|
+
resolve5(data);
|
|
4502
6058
|
});
|
|
4503
6059
|
});
|
|
4504
6060
|
}
|
|
@@ -4604,13 +6160,13 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4604
6160
|
}
|
|
4605
6161
|
let body;
|
|
4606
6162
|
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
4607
|
-
body = await new Promise((
|
|
6163
|
+
body = await new Promise((resolve5) => {
|
|
4608
6164
|
let data = "";
|
|
4609
6165
|
req.on("data", (chunk) => {
|
|
4610
6166
|
data += chunk;
|
|
4611
6167
|
});
|
|
4612
6168
|
req.on("end", () => {
|
|
4613
|
-
|
|
6169
|
+
resolve5(data);
|
|
4614
6170
|
});
|
|
4615
6171
|
});
|
|
4616
6172
|
}
|
|
@@ -4667,13 +6223,13 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4667
6223
|
}
|
|
4668
6224
|
let body;
|
|
4669
6225
|
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
4670
|
-
body = await new Promise((
|
|
6226
|
+
body = await new Promise((resolve5) => {
|
|
4671
6227
|
let data = "";
|
|
4672
6228
|
req.on("data", (chunk) => {
|
|
4673
6229
|
data += chunk;
|
|
4674
6230
|
});
|
|
4675
6231
|
req.on("end", () => {
|
|
4676
|
-
|
|
6232
|
+
resolve5(data);
|
|
4677
6233
|
});
|
|
4678
6234
|
});
|
|
4679
6235
|
}
|
|
@@ -4763,7 +6319,10 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4763
6319
|
method: req.method || "GET"
|
|
4764
6320
|
});
|
|
4765
6321
|
}
|
|
4766
|
-
const
|
|
6322
|
+
const interceptFromHeader = request.headers.get("x-farm-intercept-from") || void 0;
|
|
6323
|
+
const match = routeManager3.matchRoute(targetRequestUrl.pathname, {
|
|
6324
|
+
interceptFrom: interceptFromHeader
|
|
6325
|
+
});
|
|
4767
6326
|
if (pm) {
|
|
4768
6327
|
await pm.runHookParallel("afterRouteMatch", {
|
|
4769
6328
|
pathname: targetPath,
|
|
@@ -4779,7 +6338,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4779
6338
|
res.end(JSON.stringify({ error: "Route not found" }));
|
|
4780
6339
|
return;
|
|
4781
6340
|
}
|
|
4782
|
-
const { route, params, layouts } = match;
|
|
6341
|
+
const { route, params, layouts, slots } = match;
|
|
4783
6342
|
if (!route) {
|
|
4784
6343
|
res.statusCode = 404;
|
|
4785
6344
|
res.setHeader("Content-Type", "application/json");
|
|
@@ -4834,6 +6393,54 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4834
6393
|
search: searchParams,
|
|
4835
6394
|
routePath: route.pattern
|
|
4836
6395
|
});
|
|
6396
|
+
const routeSlots = await Promise.all(
|
|
6397
|
+
slots.map(async (slot) => {
|
|
6398
|
+
const slotModule = await routeManager3.loadRouteModule(slot.route.modulePath);
|
|
6399
|
+
const slotMetadata = getClientModuleMetadata(
|
|
6400
|
+
slot.route.modulePath,
|
|
6401
|
+
server.config.root
|
|
6402
|
+
);
|
|
6403
|
+
const slotContext = await resolveFarmRouteContext(farmApp.getConfig(), {
|
|
6404
|
+
request,
|
|
6405
|
+
params: slot.params,
|
|
6406
|
+
search: searchParams,
|
|
6407
|
+
path: targetUrl.pathname
|
|
6408
|
+
});
|
|
6409
|
+
const slotProps = await parseRouteModuleProps2(slotModule, {
|
|
6410
|
+
props: withFarmRouteContext(
|
|
6411
|
+
{
|
|
6412
|
+
params: slot.params,
|
|
6413
|
+
searchParams: Promise.resolve(searchParams),
|
|
6414
|
+
path: targetUrl.pathname
|
|
6415
|
+
},
|
|
6416
|
+
slotContext
|
|
6417
|
+
),
|
|
6418
|
+
search: searchParams,
|
|
6419
|
+
routePath: slot.route.pattern
|
|
6420
|
+
});
|
|
6421
|
+
return {
|
|
6422
|
+
name: slot.name,
|
|
6423
|
+
ownerPattern: slot.ownerPattern,
|
|
6424
|
+
containerId: slot.containerId,
|
|
6425
|
+
interception: slot.interception,
|
|
6426
|
+
fallback: slot.fallback,
|
|
6427
|
+
modulePath: slot.route.modulePath,
|
|
6428
|
+
isClientComponent: slotMetadata.isClientComponent,
|
|
6429
|
+
shouldHydrate: slotMetadata.shouldHydrate,
|
|
6430
|
+
props: {
|
|
6431
|
+
params: slotProps.params,
|
|
6432
|
+
search: slotProps.search,
|
|
6433
|
+
searchParams: slotProps.search,
|
|
6434
|
+
..."data" in slotProps ? { data: slotProps.data } : {},
|
|
6435
|
+
...slotProps.__farmCanonicalPath ? {
|
|
6436
|
+
__farmCanonicalPath: slotProps.__farmCanonicalPath
|
|
6437
|
+
} : {},
|
|
6438
|
+
...slotProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
|
|
6439
|
+
path: targetUrl.pathname
|
|
6440
|
+
}
|
|
6441
|
+
};
|
|
6442
|
+
})
|
|
6443
|
+
);
|
|
4837
6444
|
const projectRoot = server.config.root;
|
|
4838
6445
|
const toUrlPath = /* @__PURE__ */ __name((absolutePath) => {
|
|
4839
6446
|
if (absolutePath.startsWith(projectRoot)) {
|
|
@@ -4854,13 +6461,21 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
4854
6461
|
},
|
|
4855
6462
|
canonicalPath: routeProps.__farmCanonicalPath,
|
|
4856
6463
|
modulePath: toUrlPath(route.modulePath),
|
|
4857
|
-
isClientComponent,
|
|
4858
|
-
shouldHydrate,
|
|
6464
|
+
isClientComponent: routeSlots.length > 0 ? false : isClientComponent,
|
|
6465
|
+
shouldHydrate: shouldHydrate || routeSlots.some((slot) => slot.isClientComponent || slot.shouldHydrate),
|
|
4859
6466
|
metadata: {
|
|
4860
6467
|
title: mergedMetadata.title,
|
|
4861
6468
|
description: mergedMetadata.description
|
|
4862
6469
|
},
|
|
4863
6470
|
layoutModules: layouts.map((l) => toUrlPath(l.modulePath)),
|
|
6471
|
+
routeSlots: routeSlots.map((slot) => ({
|
|
6472
|
+
...slot,
|
|
6473
|
+
modulePath: toUrlPath(slot.modulePath)
|
|
6474
|
+
})),
|
|
6475
|
+
interception: routeSlots.some((slot) => slot.interception) ? {
|
|
6476
|
+
from: interceptFromHeader,
|
|
6477
|
+
slots: routeSlots.filter((slot) => slot.interception).map((slot) => slot.name)
|
|
6478
|
+
} : void 0,
|
|
4864
6479
|
i18n: getFarmI18nClientSnapshot()
|
|
4865
6480
|
};
|
|
4866
6481
|
await sendWebResponse(
|
|
@@ -5132,6 +6747,10 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5132
6747
|
);
|
|
5133
6748
|
},
|
|
5134
6749
|
async resolveId(id, importer, resolveOptions) {
|
|
6750
|
+
if (typeof fontImports.resolveId === "function") {
|
|
6751
|
+
const fontId = await fontImports.resolveId.call(this, id, importer, resolveOptions);
|
|
6752
|
+
if (fontId) return fontId;
|
|
6753
|
+
}
|
|
5135
6754
|
if (typeof imageImports.resolveId === "function") {
|
|
5136
6755
|
const imageId = await imageImports.resolveId.call(this, id, importer, resolveOptions);
|
|
5137
6756
|
if (imageId) return imageId;
|
|
@@ -5150,6 +6769,10 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5150
6769
|
}
|
|
5151
6770
|
},
|
|
5152
6771
|
async load(id) {
|
|
6772
|
+
if (typeof fontImports.load === "function") {
|
|
6773
|
+
const fontModule = await fontImports.load.call(this, id);
|
|
6774
|
+
if (fontModule) return fontModule;
|
|
6775
|
+
}
|
|
5153
6776
|
if (typeof imageImports.load === "function") {
|
|
5154
6777
|
const imageModule = await imageImports.load.call(this, id);
|
|
5155
6778
|
if (imageModule) return imageModule;
|
|
@@ -5196,6 +6819,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
5196
6819
|
export const getManifest = () => ({
|
|
5197
6820
|
routes: {},
|
|
5198
6821
|
layouts: {},
|
|
6822
|
+
slots: [],
|
|
5199
6823
|
clientEntry: "/@farm/client.js",
|
|
5200
6824
|
sharedAssets: []
|
|
5201
6825
|
});
|
|
@@ -5206,6 +6830,7 @@ export const getManifest = () => ({
|
|
|
5206
6830
|
clientEntry: "/@farm/client.js",
|
|
5207
6831
|
routes: {},
|
|
5208
6832
|
layouts: {},
|
|
6833
|
+
slots: [],
|
|
5209
6834
|
sharedAssets: [
|
|
5210
6835
|
{
|
|
5211
6836
|
tag: "link",
|
|
@@ -5235,6 +6860,13 @@ export const getManifest = () => ({
|
|
|
5235
6860
|
assets: []
|
|
5236
6861
|
};
|
|
5237
6862
|
}
|
|
6863
|
+
for (const slot of manifest.slots) {
|
|
6864
|
+
fullManifest.slots.push({
|
|
6865
|
+
...slot,
|
|
6866
|
+
preloads: [slot.modulePath],
|
|
6867
|
+
assets: []
|
|
6868
|
+
});
|
|
6869
|
+
}
|
|
5238
6870
|
return `
|
|
5239
6871
|
// Auto-generated manifest for SPA navigation (TanStack Start pattern)
|
|
5240
6872
|
// This manifest is inlined in the server bundle - no file on disk
|
|
@@ -5251,6 +6883,19 @@ export const manifest = getManifest();
|
|
|
5251
6883
|
}
|
|
5252
6884
|
let transformedCode = code;
|
|
5253
6885
|
let transformed = false;
|
|
6886
|
+
if (typeof fontImports.transform === "function") {
|
|
6887
|
+
const fontResult = await fontImports.transform.call(
|
|
6888
|
+
this,
|
|
6889
|
+
transformedCode,
|
|
6890
|
+
id,
|
|
6891
|
+
transformOptions
|
|
6892
|
+
);
|
|
6893
|
+
const fontCode = typeof fontResult === "string" ? fontResult : fontResult?.code;
|
|
6894
|
+
if (fontCode) {
|
|
6895
|
+
transformedCode = fontCode;
|
|
6896
|
+
transformed = true;
|
|
6897
|
+
}
|
|
6898
|
+
}
|
|
5254
6899
|
if (transformOptions?.ssr && server) {
|
|
5255
6900
|
const rewrittenImports = rewriteEarlySsrRelativeImports({
|
|
5256
6901
|
code: transformedCode,
|
|
@@ -5305,7 +6950,10 @@ if (import.meta.hot) {
|
|
|
5305
6950
|
}
|
|
5306
6951
|
return transformed ? { code: transformedCode, map: null } : null;
|
|
5307
6952
|
},
|
|
5308
|
-
generateBundle(options2, bundle) {
|
|
6953
|
+
async generateBundle(options2, bundle) {
|
|
6954
|
+
if (typeof fontImports.generateBundle === "function") {
|
|
6955
|
+
await fontImports.generateBundle.call(this, options2, bundle, false);
|
|
6956
|
+
}
|
|
5309
6957
|
const clientManifest = generateClientManifest(bundle);
|
|
5310
6958
|
this.emitFile({
|
|
5311
6959
|
type: "asset",
|
|
@@ -5325,8 +6973,8 @@ if (import.meta.hot) {
|
|
|
5325
6973
|
}
|
|
5326
6974
|
logger.info(`Found ${ssgPages.length} SSG pages, ${ssrRoutes.length} SSR routes`);
|
|
5327
6975
|
logger.info("Pre-rendering SSG pages...");
|
|
5328
|
-
const outDir =
|
|
5329
|
-
const clientDir =
|
|
6976
|
+
const outDir = path10.join(server?.config.root || process.cwd(), options.outDir || "dist");
|
|
6977
|
+
const clientDir = path10.join(outDir, "client");
|
|
5330
6978
|
for (const page of ssgPages) {
|
|
5331
6979
|
try {
|
|
5332
6980
|
const staticRequest = new Request(new URL(page.urlPath, "http://farm.static"));
|
|
@@ -5378,8 +7026,8 @@ if (import.meta.hot) {
|
|
|
5378
7026
|
<script type="module" src="/assets/client.js"></script>
|
|
5379
7027
|
</body>
|
|
5380
7028
|
</html>`;
|
|
5381
|
-
const outputPath = page.urlPath === "/" ?
|
|
5382
|
-
fs4.mkdirSync(
|
|
7029
|
+
const outputPath = page.urlPath === "/" ? path10.join(clientDir, "index.html") : path10.join(clientDir, page.urlPath + ".html");
|
|
7030
|
+
fs4.mkdirSync(path10.dirname(outputPath), { recursive: true });
|
|
5383
7031
|
fs4.writeFileSync(outputPath, fullHtml);
|
|
5384
7032
|
const revalidateInfo = page.revalidate ? ` (revalidate: ${page.revalidate}s)` : "";
|
|
5385
7033
|
logger.success(` \u2713 ${page.urlPath}${revalidateInfo}`);
|
|
@@ -5388,7 +7036,7 @@ if (import.meta.hot) {
|
|
|
5388
7036
|
logger.error(` \u2717 ${page.urlPath}: ${error}`);
|
|
5389
7037
|
}
|
|
5390
7038
|
}
|
|
5391
|
-
const manifestPath =
|
|
7039
|
+
const manifestPath = path10.join(outDir, "__ssg_manifest.json");
|
|
5392
7040
|
fs4.writeFileSync(
|
|
5393
7041
|
manifestPath,
|
|
5394
7042
|
JSON.stringify(
|
|
@@ -5424,9 +7072,9 @@ if (import.meta.hot) {
|
|
|
5424
7072
|
}
|
|
5425
7073
|
const currentFarmConfig = farmApp?.getConfig();
|
|
5426
7074
|
const normalizedFile = file.replace(/\\/g, "/");
|
|
5427
|
-
const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) =>
|
|
7075
|
+
const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path10.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
|
|
5428
7076
|
if (currentSrcRoot && normalizedFile.startsWith(`${currentSrcRoot}/`) && isProgrammaticRoutesFileName(normalizedFile)) {
|
|
5429
|
-
logUpdate("PAGE", `updated ${
|
|
7077
|
+
logUpdate("PAGE", `updated ${path10.basename(file)}`);
|
|
5430
7078
|
for (const mod of modules) {
|
|
5431
7079
|
server2.moduleGraph.invalidateModule(mod);
|
|
5432
7080
|
}
|
|
@@ -5877,7 +7525,7 @@ window.__FARM_WRAP_PROVIDERS__ = wrapWithIntegrationProviders;
|
|
|
5877
7525
|
|
|
5878
7526
|
// Get manifest from window (inlined by server in HTML)
|
|
5879
7527
|
// Fallback to empty manifest if not available yet
|
|
5880
|
-
const getManifest = () => window.__FARM_MANIFEST__ || { routes: {}, layouts: {}, clientEntry: '', sharedAssets: [] };
|
|
7528
|
+
const getManifest = () => window.__FARM_MANIFEST__ || { routes: {}, layouts: {}, slots: [], clientEntry: '', sharedAssets: [] };
|
|
5881
7529
|
|
|
5882
7530
|
// ====== CLIENT-SIDE ROUTE MATCHING ======
|
|
5883
7531
|
// Matches URL to route using manifest (no server request!)
|
|
@@ -6216,6 +7864,9 @@ let LayoutComponent = null;
|
|
|
6216
7864
|
|
|
6217
7865
|
// Track if we've taken over rendering from SSR
|
|
6218
7866
|
let hasClientTakenOver = false;
|
|
7867
|
+
const routeSlotRoots = new Map();
|
|
7868
|
+
const routeSlotDefinitions = new Map();
|
|
7869
|
+
let activeRouteInterception = null;
|
|
6219
7870
|
|
|
6220
7871
|
function normalizeServerProps(rawProps) {
|
|
6221
7872
|
const props = rawProps && typeof rawProps === 'object' ? { ...rawProps } : {};
|
|
@@ -6228,6 +7879,123 @@ function normalizeServerProps(rawProps) {
|
|
|
6228
7879
|
return props;
|
|
6229
7880
|
}
|
|
6230
7881
|
|
|
7882
|
+
function getRouteSlotKey(slot) {
|
|
7883
|
+
return slot.ownerPattern + ':' + slot.name;
|
|
7884
|
+
}
|
|
7885
|
+
|
|
7886
|
+
async function renderRouteSlot(slot, mode = 'render') {
|
|
7887
|
+
const container = document.getElementById(slot.containerId);
|
|
7888
|
+
if (!container || !slot.modulePath) return false;
|
|
7889
|
+
if (mode === 'intercept' && !slot.isClientComponent && !slot.shouldHydrate) {
|
|
7890
|
+
return false;
|
|
7891
|
+
}
|
|
7892
|
+
|
|
7893
|
+
let slotModule = pageModuleCache.get(slot.modulePath);
|
|
7894
|
+
if (!slotModule) {
|
|
7895
|
+
slotModule = await import(/* @vite-ignore */ slot.modulePath);
|
|
7896
|
+
pageModuleCache.set(slot.modulePath, slotModule);
|
|
7897
|
+
}
|
|
7898
|
+
const SlotComponent = slotModule?.default;
|
|
7899
|
+
if (!SlotComponent) return false;
|
|
7900
|
+
|
|
7901
|
+
const props = reviveDeferredData(
|
|
7902
|
+
normalizeServerProps(slot.props || {}),
|
|
7903
|
+
window.__FARM_DEFERRED_DATA__ || {},
|
|
7904
|
+
);
|
|
7905
|
+
const element = wrapWithIntegrationProviders(
|
|
7906
|
+
React.createElement(SlotComponent, props),
|
|
7907
|
+
);
|
|
7908
|
+
const key = getRouteSlotKey(slot);
|
|
7909
|
+
const existingRoot = routeSlotRoots.get(key);
|
|
7910
|
+
|
|
7911
|
+
if (mode === 'hydrate') {
|
|
7912
|
+
if (existingRoot) return true;
|
|
7913
|
+
const root = hydrateRoot(container, element);
|
|
7914
|
+
routeSlotRoots.set(key, root);
|
|
7915
|
+
} else {
|
|
7916
|
+
if (existingRoot) {
|
|
7917
|
+
try { existingRoot.unmount(); } catch (error) {}
|
|
7918
|
+
}
|
|
7919
|
+
const root = createRoot(container);
|
|
7920
|
+
root.render(element);
|
|
7921
|
+
routeSlotRoots.set(key, root);
|
|
7922
|
+
}
|
|
7923
|
+
|
|
7924
|
+
routeSlotDefinitions.set(key, slot);
|
|
7925
|
+
return true;
|
|
7926
|
+
}
|
|
7927
|
+
|
|
7928
|
+
async function hydrateInitialRouteSlots() {
|
|
7929
|
+
const slots = Array.isArray(window.__FARM_ROUTE_SLOTS__)
|
|
7930
|
+
? window.__FARM_ROUTE_SLOTS__
|
|
7931
|
+
: [];
|
|
7932
|
+
let hydrated = false;
|
|
7933
|
+
|
|
7934
|
+
for (const slot of slots) {
|
|
7935
|
+
routeSlotDefinitions.set(getRouteSlotKey(slot), slot);
|
|
7936
|
+
if (!slot.isClientComponent && !slot.shouldHydrate) continue;
|
|
7937
|
+
try {
|
|
7938
|
+
hydrated = (await renderRouteSlot(slot, 'hydrate')) || hydrated;
|
|
7939
|
+
} catch (error) {
|
|
7940
|
+
console.warn('[Farm.js] Could not hydrate route slot:', slot.name, error);
|
|
7941
|
+
}
|
|
7942
|
+
}
|
|
7943
|
+
|
|
7944
|
+
return hydrated;
|
|
7945
|
+
}
|
|
7946
|
+
|
|
7947
|
+
async function renderRouteInterception(pageData) {
|
|
7948
|
+
const slots = Array.isArray(pageData.routeSlots)
|
|
7949
|
+
? pageData.routeSlots.filter((slot) => slot.interception)
|
|
7950
|
+
: [];
|
|
7951
|
+
if (!pageData.interception || slots.length === 0) return false;
|
|
7952
|
+
|
|
7953
|
+
const previous = new Map();
|
|
7954
|
+
for (const slot of slots) {
|
|
7955
|
+
const key = getRouteSlotKey(slot);
|
|
7956
|
+
previous.set(key, routeSlotDefinitions.get(key) || null);
|
|
7957
|
+
if (!(await renderRouteSlot(slot, 'intercept'))) {
|
|
7958
|
+
return false;
|
|
7959
|
+
}
|
|
7960
|
+
}
|
|
7961
|
+
|
|
7962
|
+
activeRouteInterception = {
|
|
7963
|
+
from: pageData.interception.from,
|
|
7964
|
+
slots,
|
|
7965
|
+
previous,
|
|
7966
|
+
};
|
|
7967
|
+
return true;
|
|
7968
|
+
}
|
|
7969
|
+
|
|
7970
|
+
async function clearRouteInterception(destination) {
|
|
7971
|
+
if (!activeRouteInterception) return false;
|
|
7972
|
+
const active = activeRouteInterception;
|
|
7973
|
+
activeRouteInterception = null;
|
|
7974
|
+
|
|
7975
|
+
for (const slot of active.slots) {
|
|
7976
|
+
const key = getRouteSlotKey(slot);
|
|
7977
|
+
const root = routeSlotRoots.get(key);
|
|
7978
|
+
if (root) {
|
|
7979
|
+
try { root.unmount(); } catch (error) {}
|
|
7980
|
+
routeSlotRoots.delete(key);
|
|
7981
|
+
}
|
|
7982
|
+
|
|
7983
|
+
const previous = active.previous.get(key);
|
|
7984
|
+
if (previous && (previous.isClientComponent || previous.shouldHydrate)) {
|
|
7985
|
+
await renderRouteSlot(previous, 'render');
|
|
7986
|
+
} else {
|
|
7987
|
+
const container = document.getElementById(slot.containerId);
|
|
7988
|
+
if (container) container.replaceChildren();
|
|
7989
|
+
if (previous) routeSlotDefinitions.set(key, previous);
|
|
7990
|
+
else routeSlotDefinitions.delete(key);
|
|
7991
|
+
}
|
|
7992
|
+
}
|
|
7993
|
+
|
|
7994
|
+
if (!active.from) return false;
|
|
7995
|
+
const background = new URL(active.from, window.location.origin);
|
|
7996
|
+
return destination === background.pathname + background.search;
|
|
7997
|
+
}
|
|
7998
|
+
|
|
6231
7999
|
function applyCanonicalPathFromProps(props) {
|
|
6232
8000
|
const canonicalPath = props && typeof props.__farmCanonicalPath === 'string'
|
|
6233
8001
|
? props.__farmCanonicalPath
|
|
@@ -6349,6 +8117,7 @@ async function buildRouteComponentProps(pageModule, params, searchParams, path,
|
|
|
6349
8117
|
const parsedSearch = parseClientRouteSchema(schemas?.search, searchParams, 'search');
|
|
6350
8118
|
|
|
6351
8119
|
return {
|
|
8120
|
+
...(existingProps || {}),
|
|
6352
8121
|
params: parsedParams,
|
|
6353
8122
|
search: parsedSearch,
|
|
6354
8123
|
searchParams: schemas ? Promise.resolve(parsedSearch) : parsedSearch,
|
|
@@ -6462,6 +8231,17 @@ async function tryHydrateImportedPage(
|
|
|
6462
8231
|
async function renderPage(pageData) {
|
|
6463
8232
|
const container = document.getElementById('root');
|
|
6464
8233
|
if (!container) return;
|
|
8234
|
+
const destination = window.location.pathname + window.location.search;
|
|
8235
|
+
|
|
8236
|
+
if (pageData.interception) {
|
|
8237
|
+
if (await renderRouteInterception(pageData)) return;
|
|
8238
|
+
window.location.assign(destination);
|
|
8239
|
+
return;
|
|
8240
|
+
}
|
|
8241
|
+
|
|
8242
|
+
if (await clearRouteInterception(destination)) {
|
|
8243
|
+
return;
|
|
8244
|
+
}
|
|
6465
8245
|
|
|
6466
8246
|
const route = {
|
|
6467
8247
|
modulePath: pageData.modulePath,
|
|
@@ -6690,7 +8470,9 @@ async function hydrate() {
|
|
|
6690
8470
|
window.__FARM_SHOULD_HYDRATE__ === true ||
|
|
6691
8471
|
isClientComponent ||
|
|
6692
8472
|
await moduleLooksClient(modulePath);
|
|
8473
|
+
const hydratedSlots = await hydrateInitialRouteSlots();
|
|
6693
8474
|
if (!shouldHydrate) {
|
|
8475
|
+
if (hydratedSlots) replayPreHydrationClicks();
|
|
6694
8476
|
console.log('[Farm.js] Server component - SPA router ready')
|
|
6695
8477
|
return
|
|
6696
8478
|
}
|
|
@@ -6852,7 +8634,7 @@ function generateClientManifest(bundle) {
|
|
|
6852
8634
|
__name(generateClientManifest, "generateClientManifest");
|
|
6853
8635
|
async function defineConfig(config = {}) {
|
|
6854
8636
|
const tailwindcss = (await import("@tailwindcss/vite")).default;
|
|
6855
|
-
const appRoot =
|
|
8637
|
+
const appRoot = path10.resolve(config.root || process.cwd());
|
|
6856
8638
|
if (config.extends?.length) {
|
|
6857
8639
|
const { config: layeredConfig } = await import("./layers-VWVDTPUZ.mjs").then(
|
|
6858
8640
|
({ resolveFarmLayers }) => resolveFarmLayers(config, {
|
|
@@ -6955,7 +8737,7 @@ async function defineConfig(config = {}) {
|
|
|
6955
8737
|
const isExposed = hostConfig === true || hostConfig === "0.0.0.0";
|
|
6956
8738
|
console.log("");
|
|
6957
8739
|
console.log(
|
|
6958
|
-
` ${pc.bold(pc.green("Farm.js"))} ${pc.dim(
|
|
8740
|
+
` ${pc.bold(pc.green("Farm.js"))} ${pc.dim(`v${FARM_VERSION}`)} ${pc.dim(`ready in ${elapsed}ms`)}`
|
|
6959
8741
|
);
|
|
6960
8742
|
console.log("");
|
|
6961
8743
|
console.log(
|
|
@@ -7038,7 +8820,7 @@ async function defineConfig(config = {}) {
|
|
|
7038
8820
|
// Stub out problematic server-only modules during dev mode
|
|
7039
8821
|
alias: {
|
|
7040
8822
|
...getFarmLayerAliases(config.layers),
|
|
7041
|
-
"@":
|
|
8823
|
+
"@": path10.resolve(appRoot, "src"),
|
|
7042
8824
|
// Nitro internals that should not be resolved in browser
|
|
7043
8825
|
"supports-color": "data:text/javascript,export default false; export const supportsColor = false; export const stdout = false; export const stderr = false;",
|
|
7044
8826
|
"@poppinss/dumper": "data:text/javascript,export default {};",
|
|
@@ -7070,6 +8852,8 @@ export {
|
|
|
7070
8852
|
matchSSGPage,
|
|
7071
8853
|
getClientModuleMetadata,
|
|
7072
8854
|
RouteManager,
|
|
8855
|
+
farmFontImportsPlugin,
|
|
8856
|
+
mergeFarmFontCss,
|
|
7073
8857
|
ServerRenderer,
|
|
7074
8858
|
FarmApp,
|
|
7075
8859
|
createFarmApp,
|
|
@@ -7085,4 +8869,4 @@ export {
|
|
|
7085
8869
|
farmPlugin,
|
|
7086
8870
|
defineConfig
|
|
7087
8871
|
};
|
|
7088
|
-
//# sourceMappingURL=chunk-
|
|
8872
|
+
//# sourceMappingURL=chunk-77BOAQHI.mjs.map
|