@farm.js/core 0.1.0-beta.10 → 0.1.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-3QDB3IA6.mjs → chunk-3WIRO3N7.mjs} +2 -2
- package/dist/chunk-3WIRO3N7.mjs.map +1 -0
- package/dist/chunk-53MVSX3R.mjs +168 -0
- package/dist/chunk-53MVSX3R.mjs.map +1 -0
- package/dist/{chunk-AW6I64AP.mjs → chunk-6ZXIQSXE.mjs} +16 -1
- package/dist/chunk-6ZXIQSXE.mjs.map +1 -0
- package/dist/chunk-7ZVN3YZI.mjs +333 -0
- package/dist/chunk-7ZVN3YZI.mjs.map +1 -0
- package/dist/{chunk-7N62DNSO.mjs → chunk-H3TE3LOV.mjs} +2 -2
- package/dist/{chunk-QTZZ2ISQ.mjs → chunk-KLA67WKG.mjs} +1 -1
- package/dist/chunk-KLA67WKG.mjs.map +1 -0
- package/dist/{chunk-K5ZTUF22.mjs → chunk-L2PE36GQ.mjs} +7 -3
- package/dist/chunk-L2PE36GQ.mjs.map +1 -0
- package/dist/{chunk-4LND3PXF.mjs → chunk-OPHK6OJN.mjs} +513 -48
- package/dist/chunk-OPHK6OJN.mjs.map +1 -0
- package/dist/chunk-USLFXFFH.mjs +46 -0
- package/dist/chunk-USLFXFFH.mjs.map +1 -0
- package/dist/{chunk-DTOWEQRV.mjs → chunk-VSDZEB5M.mjs} +368 -103
- package/dist/chunk-VSDZEB5M.mjs.map +1 -0
- package/dist/{chunk-E2AI2CW7.mjs → chunk-Z3YG4OZT.mjs} +727 -148
- package/dist/chunk-Z3YG4OZT.mjs.map +1 -0
- package/dist/client.cjs.map +1 -1
- package/dist/client.mjs +1 -1
- package/dist/{devtools-A22KUJZT.mjs → devtools-GAZ7F3KL.mjs} +4 -3
- package/dist/{devtools-A22KUJZT.mjs.map → devtools-GAZ7F3KL.mjs.map} +1 -1
- package/dist/docs.cjs +622 -124
- package/dist/docs.cjs.map +1 -1
- package/dist/docs.mjs +5 -3
- package/dist/font.cjs +19 -2
- package/dist/font.cjs.map +1 -1
- package/dist/font.mjs +7 -3
- package/dist/index.cjs +2208 -681
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +27 -19
- package/dist/index.mjs.map +1 -1
- package/dist/internal/build-runtime.cjs +2035 -517
- package/dist/internal/build-runtime.cjs.map +1 -1
- package/dist/internal/build-runtime.mjs +13 -10
- package/dist/internal/client-runtime.cjs +169 -2
- package/dist/internal/client-runtime.cjs.map +1 -1
- package/dist/internal/client-runtime.mjs +170 -2
- package/dist/internal/client-runtime.mjs.map +1 -1
- package/dist/internal/config-runtime.cjs +22 -0
- package/dist/internal/config-runtime.cjs.map +1 -1
- package/dist/internal/config-runtime.mjs +3 -2
- package/dist/internal/metadata-image-runtime.cjs +199 -0
- package/dist/internal/metadata-image-runtime.cjs.map +1 -0
- package/dist/internal/metadata-image-runtime.mjs +8 -0
- package/dist/internal/metadata-image-runtime.mjs.map +1 -0
- package/dist/internal/production-runtime.cjs +310 -0
- package/dist/internal/production-runtime.cjs.map +1 -1
- package/dist/internal/production-runtime.mjs +10 -0
- package/dist/internal/production-runtime.mjs.map +1 -1
- package/dist/navigation.cjs.map +1 -1
- package/dist/navigation.mjs +2 -2
- package/dist/plugin.cjs +1523 -340
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.mjs +9 -5
- package/dist/server.cjs +1636 -411
- package/dist/server.cjs.map +1 -1
- package/dist/server.mjs +17 -19
- package/dist/server.mjs.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.mjs +1 -1
- package/dist/vite.cjs +1577 -350
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +9 -5
- package/package.json +10 -1
- package/dist/chunk-3QDB3IA6.mjs.map +0 -1
- package/dist/chunk-4LND3PXF.mjs.map +0 -1
- package/dist/chunk-AW6I64AP.mjs.map +0 -1
- package/dist/chunk-DTOWEQRV.mjs.map +0 -1
- package/dist/chunk-E2AI2CW7.mjs.map +0 -1
- package/dist/chunk-K5ZTUF22.mjs.map +0 -1
- package/dist/chunk-QM746KUO.mjs +0 -56
- package/dist/chunk-QM746KUO.mjs.map +0 -1
- package/dist/chunk-QTZZ2ISQ.mjs.map +0 -1
- /package/dist/{chunk-7N62DNSO.mjs.map → chunk-H3TE3LOV.mjs.map} +0 -0
package/dist/plugin.cjs
CHANGED
|
@@ -843,26 +843,26 @@ async function prepareFarmWorkflowsForNitro(config) {
|
|
|
843
843
|
const root = config.root || process.cwd();
|
|
844
844
|
const distDir = config.distDir || ".farm";
|
|
845
845
|
const fs8 = await import("fs/promises");
|
|
846
|
-
const
|
|
847
|
-
const generatedDir =
|
|
846
|
+
const path26 = await import("path");
|
|
847
|
+
const generatedDir = path26.join(root, distDir, ".nitro", "farm-workflows");
|
|
848
848
|
await fs8.mkdir(generatedDir, { recursive: true });
|
|
849
849
|
const tasks = {};
|
|
850
850
|
const scheduledTasks = createScheduledTasks(workflows);
|
|
851
851
|
for (const workflow of workflows) {
|
|
852
|
-
const wrapperPath =
|
|
852
|
+
const wrapperPath = path26.join(generatedDir, `${safeFileName(workflow.id)}.mjs`);
|
|
853
853
|
await fs8.writeFile(wrapperPath, createNitroTaskWrapper(workflow), "utf8");
|
|
854
854
|
tasks[workflow.id] = {
|
|
855
855
|
handler: wrapperPath,
|
|
856
856
|
description: workflow.description || `Farm workflow ${workflow.id}`
|
|
857
857
|
};
|
|
858
858
|
}
|
|
859
|
-
const handlerPath =
|
|
859
|
+
const handlerPath = path26.join(generatedDir, "http-handler.mjs");
|
|
860
860
|
await fs8.writeFile(
|
|
861
861
|
handlerPath,
|
|
862
862
|
createNitroWorkflowHTTPHandler(workflowConfig, workflows),
|
|
863
863
|
"utf8"
|
|
864
864
|
);
|
|
865
|
-
const manifestPath =
|
|
865
|
+
const manifestPath = path26.join(generatedDir, "manifest.json");
|
|
866
866
|
await fs8.writeFile(
|
|
867
867
|
manifestPath,
|
|
868
868
|
JSON.stringify(
|
|
@@ -945,10 +945,10 @@ function resolveWorkflowDefinition(module2) {
|
|
|
945
945
|
}
|
|
946
946
|
async function findWorkflowFiles(root, dirs) {
|
|
947
947
|
const fs8 = await import("fs/promises");
|
|
948
|
-
const
|
|
948
|
+
const path26 = await import("path");
|
|
949
949
|
const files = [];
|
|
950
950
|
for (const dir of dirs) {
|
|
951
|
-
const absoluteDir =
|
|
951
|
+
const absoluteDir = path26.isAbsolute(dir) ? dir : path26.join(root, dir);
|
|
952
952
|
if (!await pathExists(absoluteDir)) continue;
|
|
953
953
|
await walkWorkflowDir(absoluteDir, files);
|
|
954
954
|
}
|
|
@@ -956,10 +956,10 @@ async function findWorkflowFiles(root, dirs) {
|
|
|
956
956
|
}
|
|
957
957
|
async function walkWorkflowDir(dir, files) {
|
|
958
958
|
const fs8 = await import("fs/promises");
|
|
959
|
-
const
|
|
959
|
+
const path26 = await import("path");
|
|
960
960
|
const entries = await fs8.readdir(dir, { withFileTypes: true });
|
|
961
961
|
for (const entry of entries) {
|
|
962
|
-
const filePath =
|
|
962
|
+
const filePath = path26.join(dir, entry.name);
|
|
963
963
|
if (entry.isDirectory()) {
|
|
964
964
|
if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
|
|
965
965
|
await walkWorkflowDir(filePath, files);
|
|
@@ -979,12 +979,12 @@ function isWorkflowFile(fileName) {
|
|
|
979
979
|
}
|
|
980
980
|
async function loadWorkflowModule(filePath, root) {
|
|
981
981
|
const fs8 = await import("fs/promises");
|
|
982
|
-
const
|
|
982
|
+
const path26 = await import("path");
|
|
983
983
|
const { pathToFileURL: pathToFileURL5 } = await import("url");
|
|
984
984
|
const { build } = await import("esbuild");
|
|
985
|
-
const outDir =
|
|
985
|
+
const outDir = path26.join(root, ".farm", ".workflow-loader");
|
|
986
986
|
await fs8.mkdir(outDir, { recursive: true });
|
|
987
|
-
const outfile =
|
|
987
|
+
const outfile = path26.join(
|
|
988
988
|
outDir,
|
|
989
989
|
`workflow-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`
|
|
990
990
|
);
|
|
@@ -1267,7 +1267,7 @@ function normalizeCronJob(name, job) {
|
|
|
1267
1267
|
if (!job || typeof job !== "object" || Array.isArray(job)) {
|
|
1268
1268
|
throw new TypeError(`Farm cron ${JSON.stringify(name)} must be a configuration object.`);
|
|
1269
1269
|
}
|
|
1270
|
-
const
|
|
1270
|
+
const path26 = normalizeCronPath(name, job.path);
|
|
1271
1271
|
const rawSchedule = Array.isArray(job.schedule) ? job.schedule : [job.schedule];
|
|
1272
1272
|
const schedule = [...new Set(rawSchedule.map((value) => normalizeCronExpression(name, value)))];
|
|
1273
1273
|
if (schedule.length === 0) {
|
|
@@ -1276,7 +1276,7 @@ function normalizeCronJob(name, job) {
|
|
|
1276
1276
|
return {
|
|
1277
1277
|
name,
|
|
1278
1278
|
schedule,
|
|
1279
|
-
path:
|
|
1279
|
+
path: path26,
|
|
1280
1280
|
description: job.description?.trim() || void 0
|
|
1281
1281
|
};
|
|
1282
1282
|
}
|
|
@@ -1284,13 +1284,13 @@ function normalizeCronPath(name, value) {
|
|
|
1284
1284
|
if (typeof value !== "string" || !value.trim().startsWith("/")) {
|
|
1285
1285
|
throw new TypeError(`Farm cron ${JSON.stringify(name)} path must start with "/".`);
|
|
1286
1286
|
}
|
|
1287
|
-
const
|
|
1288
|
-
if (
|
|
1287
|
+
const path26 = value.trim();
|
|
1288
|
+
if (path26.startsWith("//") || path26.includes("?") || path26.includes("#")) {
|
|
1289
1289
|
throw new TypeError(
|
|
1290
1290
|
`Farm cron ${JSON.stringify(name)} path must be an application pathname without a host, query, or hash.`
|
|
1291
1291
|
);
|
|
1292
1292
|
}
|
|
1293
|
-
return
|
|
1293
|
+
return path26.length > 1 ? path26.replace(/\/+$/, "") : path26;
|
|
1294
1294
|
}
|
|
1295
1295
|
function normalizeCronExpression(name, value) {
|
|
1296
1296
|
if (typeof value !== "string") {
|
|
@@ -2147,7 +2147,7 @@ var init_server_action_security = __esm({
|
|
|
2147
2147
|
|
|
2148
2148
|
// src/image-config.ts
|
|
2149
2149
|
function resolveFarmImageConfig(config) {
|
|
2150
|
-
const
|
|
2150
|
+
const path26 = normalizeImagePath(config?.path ?? DEFAULT_FARM_IMAGE_PATH);
|
|
2151
2151
|
const deviceSizes = normalizeIntegerList(
|
|
2152
2152
|
config?.deviceSizes ?? DEFAULT_FARM_IMAGE_DEVICE_SIZES,
|
|
2153
2153
|
"images.deviceSizes"
|
|
@@ -2175,7 +2175,7 @@ function resolveFarmImageConfig(config) {
|
|
|
2175
2175
|
);
|
|
2176
2176
|
return Object.freeze({
|
|
2177
2177
|
provider: config?.provider ?? "auto",
|
|
2178
|
-
path:
|
|
2178
|
+
path: path26,
|
|
2179
2179
|
domains: Object.freeze([
|
|
2180
2180
|
...new Set(
|
|
2181
2181
|
(config?.domains ?? []).map((domain) => domain.trim().toLowerCase()).filter(Boolean)
|
|
@@ -2214,11 +2214,11 @@ function getPublicFarmImageConfig(config) {
|
|
|
2214
2214
|
};
|
|
2215
2215
|
}
|
|
2216
2216
|
function normalizeImagePath(value) {
|
|
2217
|
-
const
|
|
2218
|
-
if (!
|
|
2217
|
+
const path26 = value.trim().replace(/\/+$/, "") || "/";
|
|
2218
|
+
if (!path26.startsWith("/") || path26.includes("?") || path26.includes("#")) {
|
|
2219
2219
|
throw new TypeError("images.path must be an absolute pathname without a query or hash");
|
|
2220
2220
|
}
|
|
2221
|
-
return
|
|
2221
|
+
return path26;
|
|
2222
2222
|
}
|
|
2223
2223
|
function normalizeIntegerList(values, name, max) {
|
|
2224
2224
|
if (values.length === 0) {
|
|
@@ -2567,9 +2567,9 @@ var init_integration_orm = __esm({
|
|
|
2567
2567
|
});
|
|
2568
2568
|
|
|
2569
2569
|
// src/integrations.ts
|
|
2570
|
-
function defineTypedIntegrationRoute(method,
|
|
2570
|
+
function defineTypedIntegrationRoute(method, path26, input) {
|
|
2571
2571
|
return {
|
|
2572
|
-
path:
|
|
2572
|
+
path: path26,
|
|
2573
2573
|
method,
|
|
2574
2574
|
middleware: input.middleware,
|
|
2575
2575
|
before: input.before,
|
|
@@ -2579,7 +2579,7 @@ function defineTypedIntegrationRoute(method, path24, input) {
|
|
|
2579
2579
|
input: normalizeIntegrationRouteInputSchemas(input),
|
|
2580
2580
|
handler: input.handler,
|
|
2581
2581
|
__operation: defineIntegrationAPIOperation({
|
|
2582
|
-
path:
|
|
2582
|
+
path: path26,
|
|
2583
2583
|
method,
|
|
2584
2584
|
bodyFormat: input.bodyFormat,
|
|
2585
2585
|
responseFormat: input.responseFormat,
|
|
@@ -2591,52 +2591,52 @@ function defineTypedIntegrationRoute(method, path24, input) {
|
|
|
2591
2591
|
}
|
|
2592
2592
|
function createIntegrationRouteFactory() {
|
|
2593
2593
|
return {
|
|
2594
|
-
get(
|
|
2594
|
+
get(path26, input) {
|
|
2595
2595
|
return defineTypedIntegrationRoute(
|
|
2596
2596
|
"GET",
|
|
2597
|
-
|
|
2597
|
+
path26,
|
|
2598
2598
|
input
|
|
2599
2599
|
);
|
|
2600
2600
|
},
|
|
2601
|
-
post(
|
|
2601
|
+
post(path26, input) {
|
|
2602
2602
|
return defineTypedIntegrationRoute(
|
|
2603
2603
|
"POST",
|
|
2604
|
-
|
|
2604
|
+
path26,
|
|
2605
2605
|
{
|
|
2606
2606
|
bodyFormat: "json",
|
|
2607
2607
|
...input
|
|
2608
2608
|
}
|
|
2609
2609
|
);
|
|
2610
2610
|
},
|
|
2611
|
-
put(
|
|
2611
|
+
put(path26, input) {
|
|
2612
2612
|
return defineTypedIntegrationRoute(
|
|
2613
2613
|
"PUT",
|
|
2614
|
-
|
|
2614
|
+
path26,
|
|
2615
2615
|
{
|
|
2616
2616
|
bodyFormat: "json",
|
|
2617
2617
|
...input
|
|
2618
2618
|
}
|
|
2619
2619
|
);
|
|
2620
2620
|
},
|
|
2621
|
-
patch(
|
|
2622
|
-
return defineTypedIntegrationRoute("PATCH",
|
|
2621
|
+
patch(path26, input) {
|
|
2622
|
+
return defineTypedIntegrationRoute("PATCH", path26, {
|
|
2623
2623
|
bodyFormat: "json",
|
|
2624
2624
|
...input
|
|
2625
2625
|
});
|
|
2626
2626
|
},
|
|
2627
|
-
delete(
|
|
2628
|
-
return defineTypedIntegrationRoute("DELETE",
|
|
2627
|
+
delete(path26, input) {
|
|
2628
|
+
return defineTypedIntegrationRoute("DELETE", path26, {
|
|
2629
2629
|
bodyFormat: "json",
|
|
2630
2630
|
...input
|
|
2631
2631
|
});
|
|
2632
2632
|
},
|
|
2633
|
-
options(
|
|
2634
|
-
return defineTypedIntegrationRoute("OPTIONS",
|
|
2633
|
+
options(path26, input) {
|
|
2634
|
+
return defineTypedIntegrationRoute("OPTIONS", path26, input);
|
|
2635
2635
|
},
|
|
2636
|
-
head(
|
|
2636
|
+
head(path26, input) {
|
|
2637
2637
|
return defineTypedIntegrationRoute(
|
|
2638
2638
|
"HEAD",
|
|
2639
|
-
|
|
2639
|
+
path26,
|
|
2640
2640
|
input
|
|
2641
2641
|
);
|
|
2642
2642
|
}
|
|
@@ -2973,8 +2973,8 @@ function normalizeIntegrationValidationIssues(source, error) {
|
|
|
2973
2973
|
}
|
|
2974
2974
|
];
|
|
2975
2975
|
}
|
|
2976
|
-
function normalizeIntegrationValidationPath(
|
|
2977
|
-
return (
|
|
2976
|
+
function normalizeIntegrationValidationPath(path26) {
|
|
2977
|
+
return (path26 || []).map((segment) => {
|
|
2978
2978
|
const key = typeof segment === "object" && segment !== null && "key" in segment ? segment.key : segment;
|
|
2979
2979
|
return typeof key === "symbol" ? key.description || key.toString() : key;
|
|
2980
2980
|
});
|
|
@@ -3663,8 +3663,8 @@ function createFarmDeploymentMismatchResponse(mismatch) {
|
|
|
3663
3663
|
}
|
|
3664
3664
|
);
|
|
3665
3665
|
}
|
|
3666
|
-
function createFarmDeploymentCookie(deploymentId,
|
|
3667
|
-
const normalizedPath =
|
|
3666
|
+
function createFarmDeploymentCookie(deploymentId, path26 = "/", secure = false) {
|
|
3667
|
+
const normalizedPath = path26.startsWith("/") ? path26 : `/${path26}`;
|
|
3668
3668
|
return [
|
|
3669
3669
|
`${FARM_DEPLOYMENT_COOKIE}=${encodeURIComponent(deploymentId)}`,
|
|
3670
3670
|
`Path=${normalizedPath}`,
|
|
@@ -3920,6 +3920,33 @@ var init_auth_config = __esm({
|
|
|
3920
3920
|
}
|
|
3921
3921
|
});
|
|
3922
3922
|
|
|
3923
|
+
// src/preload.ts
|
|
3924
|
+
function resolveFarmPerformanceConfig(config) {
|
|
3925
|
+
return {
|
|
3926
|
+
preload: {
|
|
3927
|
+
mode: config?.preload?.mode === "warn" ? "warn" : "enforce",
|
|
3928
|
+
maxImages: normalizeBudget(config?.preload?.maxImages, DEFAULT_PRELOAD_CONFIG.maxImages),
|
|
3929
|
+
maxFonts: normalizeBudget(config?.preload?.maxFonts, DEFAULT_PRELOAD_CONFIG.maxFonts)
|
|
3930
|
+
}
|
|
3931
|
+
};
|
|
3932
|
+
}
|
|
3933
|
+
function normalizeBudget(value, fallback) {
|
|
3934
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : fallback;
|
|
3935
|
+
}
|
|
3936
|
+
var DEFAULT_PRELOAD_CONFIG;
|
|
3937
|
+
var init_preload = __esm({
|
|
3938
|
+
"src/preload.ts"() {
|
|
3939
|
+
"use strict";
|
|
3940
|
+
DEFAULT_PRELOAD_CONFIG = {
|
|
3941
|
+
mode: "enforce",
|
|
3942
|
+
maxImages: 1,
|
|
3943
|
+
maxFonts: 2
|
|
3944
|
+
};
|
|
3945
|
+
__name(resolveFarmPerformanceConfig, "resolveFarmPerformanceConfig");
|
|
3946
|
+
__name(normalizeBudget, "normalizeBudget");
|
|
3947
|
+
}
|
|
3948
|
+
});
|
|
3949
|
+
|
|
3923
3950
|
// src/write-file-if-changed.ts
|
|
3924
3951
|
function writeFileIfChanged(filePath, content) {
|
|
3925
3952
|
try {
|
|
@@ -4039,11 +4066,11 @@ var init_type_generator = __esm({
|
|
|
4039
4066
|
routeGroups.get(key).push(route);
|
|
4040
4067
|
}
|
|
4041
4068
|
const nestedStructure = {};
|
|
4042
|
-
for (const [
|
|
4069
|
+
for (const [path26, routeList] of routeGroups) {
|
|
4043
4070
|
const route = routeList[0];
|
|
4044
4071
|
const importPath = this.getRouteImportPath(route, options.outFile);
|
|
4045
4072
|
const routeName = this.pathToRouteName(route.path);
|
|
4046
|
-
const cleanPath =
|
|
4073
|
+
const cleanPath = path26 === "/api" ? "" : path26.replace(/^\/api\//, "");
|
|
4047
4074
|
const parts = cleanPath ? cleanPath.split("/") : [];
|
|
4048
4075
|
const allMethods = routeList.flatMap((r) => r.methods);
|
|
4049
4076
|
for (const method of allMethods) {
|
|
@@ -4102,8 +4129,8 @@ ${typeExports}
|
|
|
4102
4129
|
const relativeImport = (0, import_path7.relative)((0, import_path7.dirname)(outFile), route.filePath).replace(/\\/g, "/").replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
4103
4130
|
return relativeImport.startsWith(".") ? relativeImport : `./${relativeImport}`;
|
|
4104
4131
|
}
|
|
4105
|
-
pathToRouteName(
|
|
4106
|
-
return (
|
|
4132
|
+
pathToRouteName(path26) {
|
|
4133
|
+
return (path26 === "/api" ? "root" : path26.replace(/^\/api\//, "")).replace(/\//g, "_").replace(/[^a-zA-Z0-9_]/g, "");
|
|
4107
4134
|
}
|
|
4108
4135
|
structureToTypeString(obj, indent) {
|
|
4109
4136
|
const spaces = " ".repeat(indent);
|
|
@@ -4123,15 +4150,15 @@ ${typeExports}
|
|
|
4123
4150
|
toTypePropertyKey(key) {
|
|
4124
4151
|
return /^[$A-Z_][0-9A-Z_$]*$/i.test(key) ? key : JSON.stringify(key);
|
|
4125
4152
|
}
|
|
4126
|
-
getBaseExportName(
|
|
4127
|
-
const cleanPath =
|
|
4153
|
+
getBaseExportName(path26) {
|
|
4154
|
+
const cleanPath = path26.replace(/^\/api\//, "");
|
|
4128
4155
|
if (cleanPath === "") {
|
|
4129
4156
|
return "api";
|
|
4130
4157
|
}
|
|
4131
4158
|
return cleanPath;
|
|
4132
4159
|
}
|
|
4133
|
-
getExportName(
|
|
4134
|
-
const cleanPath =
|
|
4160
|
+
getExportName(path26, method) {
|
|
4161
|
+
const cleanPath = path26.replace(/^\/api\//, "");
|
|
4135
4162
|
if (cleanPath === "") {
|
|
4136
4163
|
return method.toLowerCase();
|
|
4137
4164
|
}
|
|
@@ -4573,28 +4600,71 @@ var init_image_server = __esm({
|
|
|
4573
4600
|
}
|
|
4574
4601
|
});
|
|
4575
4602
|
|
|
4603
|
+
// src/docs/fonts.ts
|
|
4604
|
+
function resolveFarmDocsFontAssets(root) {
|
|
4605
|
+
return FARM_DOCS_FONT_SOURCES.flatMap(({ family, packagePath }) => {
|
|
4606
|
+
const sourcePath = import_node_path10.default.join(root, "node_modules", packagePath);
|
|
4607
|
+
if (!(0, import_node_fs6.existsSync)(sourcePath)) return [];
|
|
4608
|
+
const source = (0, import_node_fs6.readFileSync)(sourcePath);
|
|
4609
|
+
const fingerprint = (0, import_node_crypto3.createHash)("sha256").update(source).digest("hex").slice(0, 12);
|
|
4610
|
+
const extension = import_node_path10.default.extname(packagePath);
|
|
4611
|
+
const baseName = import_node_path10.default.basename(packagePath, extension);
|
|
4612
|
+
return [
|
|
4613
|
+
{
|
|
4614
|
+
family,
|
|
4615
|
+
sourcePath,
|
|
4616
|
+
url: `/assets/fonts/${baseName}-h${fingerprint}${extension}`
|
|
4617
|
+
}
|
|
4618
|
+
];
|
|
4619
|
+
});
|
|
4620
|
+
}
|
|
4621
|
+
function toFarmDocsPublicFontAssets(assets) {
|
|
4622
|
+
return assets.map(({ family, url }) => ({ family, url }));
|
|
4623
|
+
}
|
|
4624
|
+
var import_node_crypto3, import_node_fs6, import_node_path10, FARM_DOCS_FONT_SOURCES;
|
|
4625
|
+
var init_fonts = __esm({
|
|
4626
|
+
"src/docs/fonts.ts"() {
|
|
4627
|
+
"use strict";
|
|
4628
|
+
import_node_crypto3 = require("crypto");
|
|
4629
|
+
import_node_fs6 = require("fs");
|
|
4630
|
+
import_node_path10 = __toESM(require("path"));
|
|
4631
|
+
FARM_DOCS_FONT_SOURCES = [
|
|
4632
|
+
{
|
|
4633
|
+
family: "Geist Sans",
|
|
4634
|
+
packagePath: "geist/dist/fonts/geist-sans/Geist-Variable.woff2"
|
|
4635
|
+
},
|
|
4636
|
+
{
|
|
4637
|
+
family: "Geist Mono",
|
|
4638
|
+
packagePath: "geist/dist/fonts/geist-mono/GeistMono-Variable.woff2"
|
|
4639
|
+
}
|
|
4640
|
+
];
|
|
4641
|
+
__name(resolveFarmDocsFontAssets, "resolveFarmDocsFontAssets");
|
|
4642
|
+
__name(toFarmDocsPublicFontAssets, "toFarmDocsPublicFontAssets");
|
|
4643
|
+
}
|
|
4644
|
+
});
|
|
4645
|
+
|
|
4576
4646
|
// src/docs/last-modified.ts
|
|
4577
4647
|
function normalizeRelativePath(value) {
|
|
4578
4648
|
return value.replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
4579
4649
|
}
|
|
4580
4650
|
function resolveExistingPath(filePath) {
|
|
4581
4651
|
try {
|
|
4582
|
-
return (0,
|
|
4652
|
+
return (0, import_node_fs7.realpathSync)(filePath);
|
|
4583
4653
|
} catch {
|
|
4584
|
-
return
|
|
4654
|
+
return import_node_path11.default.resolve(filePath);
|
|
4585
4655
|
}
|
|
4586
4656
|
}
|
|
4587
4657
|
function isDocsSourceFile(filePath) {
|
|
4588
|
-
return DOCS_FILE_EXTENSIONS.has(
|
|
4658
|
+
return DOCS_FILE_EXTENSIONS.has(import_node_path11.default.extname(filePath).toLowerCase());
|
|
4589
4659
|
}
|
|
4590
4660
|
function discoverDocsSourceFiles(contentDir) {
|
|
4591
4661
|
const files = [];
|
|
4592
4662
|
const visit = /* @__PURE__ */ __name((dir) => {
|
|
4593
|
-
for (const entry of (0,
|
|
4663
|
+
for (const entry of (0, import_node_fs7.readdirSync)(dir, { withFileTypes: true }).sort(
|
|
4594
4664
|
(a, b) => a.name.localeCompare(b.name)
|
|
4595
4665
|
)) {
|
|
4596
4666
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
4597
|
-
const absolutePath =
|
|
4667
|
+
const absolutePath = import_node_path11.default.join(dir, entry.name);
|
|
4598
4668
|
if (entry.isDirectory()) {
|
|
4599
4669
|
visit(absolutePath);
|
|
4600
4670
|
} else if (entry.isFile() && isDocsSourceFile(absolutePath)) {
|
|
@@ -4602,7 +4672,7 @@ function discoverDocsSourceFiles(contentDir) {
|
|
|
4602
4672
|
}
|
|
4603
4673
|
}
|
|
4604
4674
|
}, "visit");
|
|
4605
|
-
if ((0,
|
|
4675
|
+
if ((0, import_node_fs7.existsSync)(contentDir)) visit(contentDir);
|
|
4606
4676
|
return files;
|
|
4607
4677
|
}
|
|
4608
4678
|
function getGitLastModifiedDates(contentDir) {
|
|
@@ -4612,7 +4682,7 @@ function getGitLastModifiedDates(contentDir) {
|
|
|
4612
4682
|
stdio: ["ignore", "pipe", "ignore"]
|
|
4613
4683
|
}).trim();
|
|
4614
4684
|
if (!gitRoot) return {};
|
|
4615
|
-
const contentPathspec = normalizeRelativePath(
|
|
4685
|
+
const contentPathspec = normalizeRelativePath(import_node_path11.default.relative(gitRoot, contentDir)) || ".";
|
|
4616
4686
|
const contentPrefix = contentPathspec === "." ? "" : `${contentPathspec}/`;
|
|
4617
4687
|
const history = (0, import_node_child_process.execFileSync)(
|
|
4618
4688
|
"git",
|
|
@@ -4654,11 +4724,11 @@ function getGitLastModifiedDates(contentDir) {
|
|
|
4654
4724
|
}
|
|
4655
4725
|
}
|
|
4656
4726
|
function readManifest(contentDir) {
|
|
4657
|
-
const manifestPath =
|
|
4658
|
-
if (!(0,
|
|
4727
|
+
const manifestPath = import_node_path11.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
|
|
4728
|
+
if (!(0, import_node_fs7.existsSync)(manifestPath)) return null;
|
|
4659
4729
|
try {
|
|
4660
4730
|
const parsed = JSON.parse(
|
|
4661
|
-
(0,
|
|
4731
|
+
(0, import_node_fs7.readFileSync)(manifestPath, "utf8")
|
|
4662
4732
|
);
|
|
4663
4733
|
if (parsed.version !== 1 || !parsed.pages || typeof parsed.pages !== "object") return null;
|
|
4664
4734
|
const pages = Object.fromEntries(
|
|
@@ -4677,15 +4747,15 @@ function createFarmDocsLastModifiedManifest(contentDir, options = {}) {
|
|
|
4677
4747
|
const fallbackDate = (options.now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
4678
4748
|
const pages = {};
|
|
4679
4749
|
for (const sourcePath of discoverDocsSourceFiles(resolvedContentDir)) {
|
|
4680
|
-
const relativePath2 = normalizeRelativePath(
|
|
4681
|
-
pages[relativePath2] = gitDates[relativePath2] || (options.fallback === "now" ? fallbackDate : (0,
|
|
4750
|
+
const relativePath2 = normalizeRelativePath(import_node_path11.default.relative(resolvedContentDir, sourcePath));
|
|
4751
|
+
pages[relativePath2] = gitDates[relativePath2] || (options.fallback === "now" ? fallbackDate : (0, import_node_fs7.statSync)(sourcePath).mtime.toISOString());
|
|
4682
4752
|
}
|
|
4683
4753
|
return { version: 1, pages };
|
|
4684
4754
|
}
|
|
4685
4755
|
function getLastModifiedManifest(contentDir) {
|
|
4686
4756
|
const resolvedContentDir = resolveExistingPath(contentDir);
|
|
4687
|
-
const manifestPath =
|
|
4688
|
-
const manifestStat = (0,
|
|
4757
|
+
const manifestPath = import_node_path11.default.join(resolvedContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
|
|
4758
|
+
const manifestStat = (0, import_node_fs7.existsSync)(manifestPath) ? (0, import_node_fs7.statSync)(manifestPath) : null;
|
|
4689
4759
|
const signature = manifestStat ? `file:${manifestStat.mtimeMs}:${manifestStat.size}` : "generated";
|
|
4690
4760
|
const cached = manifestCache.get(resolvedContentDir);
|
|
4691
4761
|
if (cached?.signature === signature) return cached.manifest;
|
|
@@ -4698,21 +4768,21 @@ function resolveFarmDocsPageLastModified(contentDir, sourcePath, frontmatter) {
|
|
|
4698
4768
|
if (configured) return configured;
|
|
4699
4769
|
const resolvedContentDir = resolveExistingPath(contentDir);
|
|
4700
4770
|
const resolvedSourcePath = resolveExistingPath(sourcePath);
|
|
4701
|
-
const relativePath2 = normalizeRelativePath(
|
|
4702
|
-
const isInsideContentDir = relativePath2 !== ".." && !relativePath2.startsWith("../") && !
|
|
4771
|
+
const relativePath2 = normalizeRelativePath(import_node_path11.default.relative(resolvedContentDir, resolvedSourcePath));
|
|
4772
|
+
const isInsideContentDir = relativePath2 !== ".." && !relativePath2.startsWith("../") && !import_node_path11.default.isAbsolute(relativePath2);
|
|
4703
4773
|
if (isInsideContentDir) {
|
|
4704
4774
|
const generated = getLastModifiedManifest(resolvedContentDir).pages[relativePath2];
|
|
4705
4775
|
if (generated) return generated;
|
|
4706
4776
|
}
|
|
4707
|
-
return (0,
|
|
4777
|
+
return (0, import_node_fs7.statSync)(resolvedSourcePath).mtime.toISOString();
|
|
4708
4778
|
}
|
|
4709
|
-
var import_node_child_process,
|
|
4779
|
+
var import_node_child_process, import_node_fs7, import_node_path11, FARM_DOCS_LAST_MODIFIED_MANIFEST, COMMIT_MARKER, DOCS_FILE_EXTENSIONS, manifestCache;
|
|
4710
4780
|
var init_last_modified = __esm({
|
|
4711
4781
|
"src/docs/last-modified.ts"() {
|
|
4712
4782
|
"use strict";
|
|
4713
4783
|
import_node_child_process = require("child_process");
|
|
4714
|
-
|
|
4715
|
-
|
|
4784
|
+
import_node_fs7 = require("fs");
|
|
4785
|
+
import_node_path11 = __toESM(require("path"));
|
|
4716
4786
|
FARM_DOCS_LAST_MODIFIED_MANIFEST = ".farm-docs-last-modified.json";
|
|
4717
4787
|
COMMIT_MARKER = "__FARM_DOCS_COMMIT__";
|
|
4718
4788
|
DOCS_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".mdx"]);
|
|
@@ -4774,8 +4844,8 @@ var init_pixel_border_css = __esm({
|
|
|
4774
4844
|
--scrollbar-thumb-hover: var(--color-fd-ring);
|
|
4775
4845
|
--scrollbar-track: transparent;
|
|
4776
4846
|
--radius: 0px;
|
|
4777
|
-
--font-geist-sans:
|
|
4778
|
-
--font-geist-mono:
|
|
4847
|
+
--font-geist-sans: ui-sans-serif, system-ui, sans-serif;
|
|
4848
|
+
--font-geist-mono: ui-monospace, monospace;
|
|
4779
4849
|
}
|
|
4780
4850
|
|
|
4781
4851
|
.dark {
|
|
@@ -4788,28 +4858,6 @@ body,
|
|
|
4788
4858
|
background-color: var(--color-fd-background) !important;
|
|
4789
4859
|
}
|
|
4790
4860
|
|
|
4791
|
-
@font-face {
|
|
4792
|
-
font-family: "Geist Sans";
|
|
4793
|
-
font-display: block;
|
|
4794
|
-
font-style: normal;
|
|
4795
|
-
font-weight: 100 900;
|
|
4796
|
-
src:
|
|
4797
|
-
local("Geist Sans"),
|
|
4798
|
-
url("/assets/Geist-Variable-CrgPqtmy.woff2") format("woff2"),
|
|
4799
|
-
url("/node_modules/geist/dist/fonts/geist-sans/Geist-Variable.woff2") format("woff2");
|
|
4800
|
-
}
|
|
4801
|
-
|
|
4802
|
-
@font-face {
|
|
4803
|
-
font-family: "Geist Mono";
|
|
4804
|
-
font-display: block;
|
|
4805
|
-
font-style: normal;
|
|
4806
|
-
font-weight: 100 900;
|
|
4807
|
-
src:
|
|
4808
|
-
local("Geist Mono"),
|
|
4809
|
-
url("/assets/GeistMono-Variable-BNLlm6Cd.woff2") format("woff2"),
|
|
4810
|
-
url("/node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2") format("woff2");
|
|
4811
|
-
}
|
|
4812
|
-
|
|
4813
4861
|
* {
|
|
4814
4862
|
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
|
|
4815
4863
|
scrollbar-width: thin;
|
|
@@ -6016,10 +6064,10 @@ function isFarmDocsSearchEnabled(docs) {
|
|
|
6016
6064
|
}
|
|
6017
6065
|
function resolveFarmDocsSearchClientModule(root) {
|
|
6018
6066
|
try {
|
|
6019
|
-
const requireFromApp = (0, import_node_module4.createRequire)(
|
|
6067
|
+
const requireFromApp = (0, import_node_module4.createRequire)(import_node_path12.default.join(import_node_path12.default.resolve(root), "package.json"));
|
|
6020
6068
|
const themeEntry = requireFromApp.resolve("@farming-labs/theme");
|
|
6021
|
-
const commandSearchModule =
|
|
6022
|
-
if ((0,
|
|
6069
|
+
const commandSearchModule = import_node_path12.default.join(import_node_path12.default.dirname(themeEntry), "docs-command-search.mjs");
|
|
6070
|
+
if ((0, import_node_fs8.existsSync)(commandSearchModule)) return commandSearchModule;
|
|
6023
6071
|
} catch {
|
|
6024
6072
|
}
|
|
6025
6073
|
return void 0;
|
|
@@ -6158,13 +6206,13 @@ async function mountFarmDocsSearch() {
|
|
|
6158
6206
|
window.__FARM_MOUNT_DOCS_SEARCH__ = mountFarmDocsSearch;
|
|
6159
6207
|
`;
|
|
6160
6208
|
}
|
|
6161
|
-
var
|
|
6209
|
+
var import_node_fs8, import_node_module4, import_node_path12;
|
|
6162
6210
|
var init_search_client = __esm({
|
|
6163
6211
|
"src/docs/search-client.ts"() {
|
|
6164
6212
|
"use strict";
|
|
6165
|
-
|
|
6213
|
+
import_node_fs8 = require("fs");
|
|
6166
6214
|
import_node_module4 = require("module");
|
|
6167
|
-
|
|
6215
|
+
import_node_path12 = __toESM(require("path"));
|
|
6168
6216
|
__name(isFarmDocsSearchEnabled, "isFarmDocsSearchEnabled");
|
|
6169
6217
|
__name(resolveFarmDocsSearchClientModule, "resolveFarmDocsSearchClientModule");
|
|
6170
6218
|
__name(generateFarmDocsSearchBootstrapRuntime, "generateFarmDocsSearchBootstrapRuntime");
|
|
@@ -6172,11 +6220,418 @@ var init_search_client = __esm({
|
|
|
6172
6220
|
}
|
|
6173
6221
|
});
|
|
6174
6222
|
|
|
6223
|
+
// src/docs/social-image.ts
|
|
6224
|
+
function normalizeEntry(entry) {
|
|
6225
|
+
if (!entry || entry === "/") return "";
|
|
6226
|
+
return `/${entry.replace(/^\/+|\/+$/g, "")}`;
|
|
6227
|
+
}
|
|
6228
|
+
function encodeSlugPath(slug) {
|
|
6229
|
+
return slug.split("/").filter(Boolean).map((segment) => encodeURIComponent(segment)).join("/");
|
|
6230
|
+
}
|
|
6231
|
+
function getSocialImageConfig(docs) {
|
|
6232
|
+
return typeof docs.config.socialImage === "object" && docs.config.socialImage ? docs.config.socialImage : void 0;
|
|
6233
|
+
}
|
|
6234
|
+
function getNavTitle(docs) {
|
|
6235
|
+
if (typeof docs.config.nav !== "object" || !docs.config.nav || !("title" in docs.config.nav)) {
|
|
6236
|
+
return "Farm.js";
|
|
6237
|
+
}
|
|
6238
|
+
return String(docs.config.nav.title || "Farm.js");
|
|
6239
|
+
}
|
|
6240
|
+
function isFalse(value) {
|
|
6241
|
+
return value ? /^(false|no|none|off|disabled)$/i.test(value.trim()) : false;
|
|
6242
|
+
}
|
|
6243
|
+
function isExternalOrRootPath(value) {
|
|
6244
|
+
return /^(https?:)?\/\//i.test(value) || value.startsWith("/");
|
|
6245
|
+
}
|
|
6246
|
+
function isFarmDocsSocialImageEnabled(page2, docs) {
|
|
6247
|
+
if (docs.config.socialImage === false || getSocialImageConfig(docs)?.enabled === false) {
|
|
6248
|
+
return false;
|
|
6249
|
+
}
|
|
6250
|
+
return !isFalse(page2.frontmatter.socialImage);
|
|
6251
|
+
}
|
|
6252
|
+
function getFarmDocsCustomSocialImage(page2) {
|
|
6253
|
+
const value = page2.frontmatter.socialImage || page2.frontmatter.openGraphImage || page2.frontmatter.ogImage;
|
|
6254
|
+
return value && !isFalse(value) && isExternalOrRootPath(value) ? value : void 0;
|
|
6255
|
+
}
|
|
6256
|
+
function resolveIllustration(page2) {
|
|
6257
|
+
const explicit = page2.frontmatter.socialIllustration?.toLowerCase();
|
|
6258
|
+
if (explicit === "auth" || explicit === "cache" || explicit === "cli" || explicit === "integrations" || explicit === "project" || explicit === "routing" || explicit === "runtime") {
|
|
6259
|
+
return explicit;
|
|
6260
|
+
}
|
|
6261
|
+
const source = `${page2.slug} ${page2.title} ${page2.section || ""}`.toLowerCase();
|
|
6262
|
+
if (/auth|session|security|csrf/.test(source)) return "auth";
|
|
6263
|
+
if (/cache|ppr|render|static|revalid|stream/.test(source)) return "cache";
|
|
6264
|
+
if (/integration|stripe|prisma|better.auth|email|job|workflow/.test(source)) {
|
|
6265
|
+
return "integrations";
|
|
6266
|
+
}
|
|
6267
|
+
if (/cli|test|deploy|preview|upgrade|migration|install/.test(source)) return "cli";
|
|
6268
|
+
if (/project|structure|config|environment|markdown|docs.engine/.test(source)) {
|
|
6269
|
+
return "project";
|
|
6270
|
+
}
|
|
6271
|
+
if (/rout|endpoint|middleware|navigation|server.function|server.action|api/.test(source)) {
|
|
6272
|
+
return "routing";
|
|
6273
|
+
}
|
|
6274
|
+
return "runtime";
|
|
6275
|
+
}
|
|
6276
|
+
function createHashValue(value) {
|
|
6277
|
+
return (0, import_node_crypto4.createHash)("sha256").update(JSON.stringify(value)).digest("hex").slice(0, 16);
|
|
6278
|
+
}
|
|
6279
|
+
function resolveBaseUrl(requestUrl, config) {
|
|
6280
|
+
return config?.baseUrl ? new URL(config.baseUrl) : new URL(requestUrl.origin);
|
|
6281
|
+
}
|
|
6282
|
+
function createFarmDocsSocialImageDescriptor(page2, docs, requestUrl) {
|
|
6283
|
+
const config = getSocialImageConfig(docs);
|
|
6284
|
+
const siteName = config?.siteName || getNavTitle(docs);
|
|
6285
|
+
const brand = config?.brand || siteName;
|
|
6286
|
+
const title = page2.frontmatter.socialTitle || page2.title;
|
|
6287
|
+
const description = page2.frontmatter.socialDescription || page2.description || docs.config.metadata?.description || `Documentation for ${siteName}`;
|
|
6288
|
+
const section = page2.frontmatter.section || page2.section || "Documentation";
|
|
6289
|
+
const illustration = resolveIllustration(page2);
|
|
6290
|
+
const entry = normalizeEntry(docs.entry);
|
|
6291
|
+
const slugPath = encodeSlugPath(page2.slug) || "index";
|
|
6292
|
+
const imagePath = `${entry}/_social/${slugPath}/opengraph-image.svg`;
|
|
6293
|
+
const baseUrl = resolveBaseUrl(requestUrl, config);
|
|
6294
|
+
const pageUrl = new URL(page2.href, baseUrl).href;
|
|
6295
|
+
const imageAlt = `${title} \u2014 ${siteName} documentation`;
|
|
6296
|
+
const hash = createHashValue({
|
|
6297
|
+
version: FARM_DOCS_SOCIAL_IMAGE_VERSION,
|
|
6298
|
+
title,
|
|
6299
|
+
description,
|
|
6300
|
+
section,
|
|
6301
|
+
siteName,
|
|
6302
|
+
brand,
|
|
6303
|
+
pageHref: page2.href,
|
|
6304
|
+
illustration,
|
|
6305
|
+
fonts: config?.fonts
|
|
6306
|
+
});
|
|
6307
|
+
return {
|
|
6308
|
+
title,
|
|
6309
|
+
description,
|
|
6310
|
+
section,
|
|
6311
|
+
siteName,
|
|
6312
|
+
brand,
|
|
6313
|
+
pageHref: page2.href,
|
|
6314
|
+
pageUrl,
|
|
6315
|
+
imagePath,
|
|
6316
|
+
imageUrl: new URL(`${imagePath}?v=${hash}`, baseUrl).href,
|
|
6317
|
+
imageAlt,
|
|
6318
|
+
illustration,
|
|
6319
|
+
fonts: config?.fonts,
|
|
6320
|
+
hash
|
|
6321
|
+
};
|
|
6322
|
+
}
|
|
6323
|
+
function getFarmDocsSocialImageSlug(docs, requestUrl) {
|
|
6324
|
+
const entry = normalizeEntry(docs.entry);
|
|
6325
|
+
const prefix = `${entry}/_social/`;
|
|
6326
|
+
const suffix = "/opengraph-image.svg";
|
|
6327
|
+
if (!requestUrl.pathname.startsWith(prefix) || !requestUrl.pathname.endsWith(suffix)) {
|
|
6328
|
+
return null;
|
|
6329
|
+
}
|
|
6330
|
+
const rawSlug = requestUrl.pathname.slice(prefix.length, -suffix.length);
|
|
6331
|
+
if (!rawSlug) return null;
|
|
6332
|
+
try {
|
|
6333
|
+
const slug = rawSlug.split("/").map((segment) => decodeURIComponent(segment)).join("/");
|
|
6334
|
+
if (slug.split("/").some((segment) => !segment || segment === ".." || segment === ".")) {
|
|
6335
|
+
return null;
|
|
6336
|
+
}
|
|
6337
|
+
return slug === "index" ? "" : slug;
|
|
6338
|
+
} catch {
|
|
6339
|
+
return null;
|
|
6340
|
+
}
|
|
6341
|
+
}
|
|
6342
|
+
function escapeXml(value) {
|
|
6343
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
6344
|
+
}
|
|
6345
|
+
function truncate(value, length) {
|
|
6346
|
+
if (value.length <= length) return value;
|
|
6347
|
+
return `${value.slice(0, Math.max(0, length - 1)).trimEnd()}\u2026`;
|
|
6348
|
+
}
|
|
6349
|
+
function wrapText(value, maxCharacters, maxLines) {
|
|
6350
|
+
const words = value.trim().split(/\s+/).filter(Boolean);
|
|
6351
|
+
const lines = [];
|
|
6352
|
+
let current = "";
|
|
6353
|
+
let consumedWords = 0;
|
|
6354
|
+
for (const word of words) {
|
|
6355
|
+
const candidate = current ? `${current} ${word}` : word;
|
|
6356
|
+
if (candidate.length <= maxCharacters || !current) {
|
|
6357
|
+
current = candidate;
|
|
6358
|
+
consumedWords += 1;
|
|
6359
|
+
continue;
|
|
6360
|
+
}
|
|
6361
|
+
lines.push(current);
|
|
6362
|
+
if (lines.length === maxLines) break;
|
|
6363
|
+
current = word;
|
|
6364
|
+
consumedWords += 1;
|
|
6365
|
+
}
|
|
6366
|
+
if (current && lines.length < maxLines) lines.push(current);
|
|
6367
|
+
if (consumedWords < words.length && lines.length) {
|
|
6368
|
+
lines[lines.length - 1] = truncate(`${lines[lines.length - 1]}\u2026`, maxCharacters);
|
|
6369
|
+
}
|
|
6370
|
+
return lines;
|
|
6371
|
+
}
|
|
6372
|
+
function renderTextLines(lines, x, y, lineHeight, attributes) {
|
|
6373
|
+
return lines.map(
|
|
6374
|
+
(line, index) => `<text x="${x}" y="${y + index * lineHeight}" ${attributes}>${escapeXml(line)}</text>`
|
|
6375
|
+
).join("");
|
|
6376
|
+
}
|
|
6377
|
+
function renderEmbeddedFont(name, source, weight) {
|
|
6378
|
+
if (!source) return "";
|
|
6379
|
+
return `@font-face{font-family:"${name}";src:url("${escapeXml(source)}") format("woff2");font-style:normal;font-weight:${weight};font-display:block;}`;
|
|
6380
|
+
}
|
|
6381
|
+
function renderArrow(x1, y, x2, color = "#8b8b8b") {
|
|
6382
|
+
return `<path d="M${x1} ${y}H${x2 - 9}" fill="none" stroke="${color}"/><path d="m${x2 - 9} ${y - 5} 9 5-9 5" fill="none" stroke="${color}"/>`;
|
|
6383
|
+
}
|
|
6384
|
+
function renderPanelHeader(label, status) {
|
|
6385
|
+
return `<text x="819" y="171" class="label">${escapeXml(label)}</text><text x="1134" y="171" class="label bright" text-anchor="end">${escapeXml(status)}</text>`;
|
|
6386
|
+
}
|
|
6387
|
+
function renderRoutingIllustration() {
|
|
6388
|
+
return `${renderPanelHeader("ROUTE BLUEPRINT", "TYPED")}
|
|
6389
|
+
<rect x="819" y="296" width="92" height="54" fill="#a3a3a3"/>
|
|
6390
|
+
<text x="832" y="327" class="diagram-title ink">src/app</text>
|
|
6391
|
+
<path d="M911 323h41M952 232v181M952 232h44M952 323h44M952 413h44" fill="none" stroke="#696969"/>
|
|
6392
|
+
<rect x="996" y="205" width="138" height="54" fill="#0a0a0a" stroke="#414141"/>
|
|
6393
|
+
<text x="1010" y="228" class="diagram-title">/</text><text x="1010" y="246" class="micro">STATIC</text>
|
|
6394
|
+
<rect x="996" y="296" width="138" height="54" fill="#0a0a0a" stroke="#414141"/>
|
|
6395
|
+
<text x="1010" y="319" class="diagram-title">/blog/:slug</text><text x="1010" y="337" class="micro">DYNAMIC</text>
|
|
6396
|
+
<rect x="996" y="386" width="138" height="55" fill="#f0f0f0"/>
|
|
6397
|
+
<text x="1010" y="410" class="diagram-title ink">/docs/:path*</text><text x="1010" y="428" class="micro ink-muted">CATCH-ALL</text>
|
|
6398
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
6399
|
+
<text x="819" y="475" class="label bright">FILE ROUTES</text><text x="1134" y="475" class="label" text-anchor="end">TYPES INCLUDED</text>`;
|
|
6400
|
+
}
|
|
6401
|
+
function renderAuthIllustration() {
|
|
6402
|
+
return `${renderPanelHeader("REQUEST GUARD", "SERVER VERIFIED")}
|
|
6403
|
+
<rect x="819" y="269" width="86" height="54" fill="#0a0a0a" stroke="#454545"/>
|
|
6404
|
+
<text x="837" y="292" class="micro bright">REQUEST</text><text x="837" y="310" class="diagram-title">GET /app</text>
|
|
6405
|
+
${renderArrow(905, 296, 943)}
|
|
6406
|
+
<rect x="943" y="224" width="104" height="118" fill="#f0f0f0"/>
|
|
6407
|
+
<path d="M974 271v-12a21 21 0 0 1 42 0v12M968 271h54v45h-54z" fill="#050505"/>
|
|
6408
|
+
<circle cx="995" cy="292" r="4" fill="#f0f0f0"/><path d="M995 296v8" stroke="#f0f0f0" stroke-width="3"/>
|
|
6409
|
+
<text x="995" y="332" class="micro ink" text-anchor="middle">auth()</text>
|
|
6410
|
+
${renderArrow(1047, 296, 1071)}
|
|
6411
|
+
<rect x="1071" y="269" width="63" height="54" fill="#0a0a0a" stroke="#454545"/>
|
|
6412
|
+
<text x="1082" y="292" class="micro bright">ALLOW</text><text x="1082" y="310" class="micro">/app</text>
|
|
6413
|
+
<rect x="819" y="372" width="315" height="38" fill="#090909" stroke="#3d3d3d"/>
|
|
6414
|
+
<rect x="832" y="385" width="11" height="11" fill="#a3a3a3"/>
|
|
6415
|
+
<text x="856" y="395" class="code">session.user / verified</text>
|
|
6416
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
6417
|
+
<text x="819" y="475" class="label bright">SESSION TYPED</text><text x="1134" y="475" class="label" text-anchor="end">CSRF PROTECTED</text>`;
|
|
6418
|
+
}
|
|
6419
|
+
function renderCacheIllustration() {
|
|
6420
|
+
return `${renderPanelHeader("PAGE / PRODUCT", "CACHE + PPR")}
|
|
6421
|
+
<rect x="819" y="204" width="315" height="54" fill="#f0f0f0"/>
|
|
6422
|
+
<text x="836" y="235" class="diagram-title ink">STATIC SHELL</text><text x="1116" y="235" class="micro ink-muted" text-anchor="end">BUILD</text>
|
|
6423
|
+
<rect x="819" y="271" width="198" height="76" fill="#a3a3a3"/>
|
|
6424
|
+
<text x="836" y="301" class="diagram-title ink">CACHED DATA</text><text x="836" y="326" class="micro ink-muted">tag: products</text>
|
|
6425
|
+
<rect x="1029" y="271" width="105" height="76" fill="#0a0a0a" stroke="#555"/>
|
|
6426
|
+
<text x="1045" y="301" class="diagram-title">LIVE</text><text x="1045" y="326" class="micro">stream</text>
|
|
6427
|
+
<path d="M1081 347v43m-8-9 8 9 8-9" fill="none" stroke="#d4d4d4"/>
|
|
6428
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
6429
|
+
<text x="819" y="475" class="label bright">STATIC FIRST</text><text x="1134" y="475" class="label" text-anchor="end">DYNAMIC WHERE NEEDED</text>`;
|
|
6430
|
+
}
|
|
6431
|
+
function renderIntegrationsIllustration() {
|
|
6432
|
+
return `${renderPanelHeader("INTEGRATION GRAPH", "ONE PRODUCT")}
|
|
6433
|
+
<path d="M976 309H879V247M976 309H879v87M1030 309h93V247M1030 309h93v87" fill="none" stroke="#4a4a4a"/>
|
|
6434
|
+
<rect x="819" y="214" width="120" height="57" fill="#0a0a0a" stroke="#4b4b4b"/><text x="839" y="247" class="diagram-title">BETTER AUTH</text>
|
|
6435
|
+
<rect x="819" y="368" width="120" height="57" fill="#0a0a0a" stroke="#4b4b4b"/><text x="851" y="401" class="diagram-title">PRISMA</text>
|
|
6436
|
+
<rect x="1061" y="214" width="73" height="57" fill="#0a0a0a" stroke="#4b4b4b"/><text x="1077" y="247" class="diagram-title">STRIPE</text>
|
|
6437
|
+
<rect x="1061" y="368" width="73" height="57" fill="#a3a3a3"/><text x="1075" y="401" class="diagram-title ink">VERCEL</text>
|
|
6438
|
+
<rect x="976" y="277" width="94" height="64" fill="#f0f0f0"/>
|
|
6439
|
+
<text x="994" y="304" class="diagram-title ink">FARM.JS</text><text x="994" y="324" class="micro ink-muted">CORE</text>
|
|
6440
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
6441
|
+
<text x="819" y="475" class="label bright">BRING YOUR STACK</text><text x="1134" y="475" class="label" text-anchor="end">CONNECTED ONCE</text>`;
|
|
6442
|
+
}
|
|
6443
|
+
function renderCliIllustration() {
|
|
6444
|
+
return `${renderPanelHeader("TERMINAL", "PRODUCTION OUTPUT")}
|
|
6445
|
+
<rect x="819" y="203" width="315" height="213" fill="#050505" stroke="#555"/>
|
|
6446
|
+
<line x1="819" y1="236" x2="1134" y2="236" stroke="#555"/>
|
|
6447
|
+
<circle cx="837" cy="220" r="4" fill="#5d5d5d"/><circle cx="850" cy="220" r="4" fill="#7a7a7a"/><circle cx="863" cy="220" r="4" fill="#a3a3a3"/>
|
|
6448
|
+
<text x="837" y="273" class="code bright"><tspan fill="#7a7a7a">$</tspan> farm build</text>
|
|
6449
|
+
<rect x="837" y="293" width="11" height="11" fill="#a3a3a3"/><path d="m839 298 3 3 6-7" fill="none" stroke="#050505" stroke-width="1.5"/>
|
|
6450
|
+
<text x="861" y="303" class="code">64 routes discovered</text>
|
|
6451
|
+
<rect x="837" y="320" width="11" height="11" fill="#a3a3a3"/><path d="m839 325 3 3 6-7" fill="none" stroke="#050505" stroke-width="1.5"/>
|
|
6452
|
+
<text x="861" y="330" class="code">client + server bundles</text>
|
|
6453
|
+
<rect x="837" y="355" width="126" height="30" fill="#f0f0f0"/><text x="853" y="374" class="micro ink">BUILD COMPLETE</text>
|
|
6454
|
+
<text x="1115" y="374" class="micro" text-anchor="end">/dist</text>
|
|
6455
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
6456
|
+
<text x="819" y="475" class="label bright">REAL COMMANDS</text><text x="1134" y="475" class="label" text-anchor="end">842MS</text>`;
|
|
6457
|
+
}
|
|
6458
|
+
function renderProjectIllustration() {
|
|
6459
|
+
return `${renderPanelHeader("PROJECT MAP", "CONVENTION TYPED")}
|
|
6460
|
+
<rect x="819" y="202" width="315" height="216" fill="#050505" stroke="#555"/>
|
|
6461
|
+
<text x="837" y="227" class="diagram-title bright">my-app/</text>
|
|
6462
|
+
<path d="M847 243v143M847 259h23M847 293h23M847 327h23M847 361h23" fill="none" stroke="#666"/>
|
|
6463
|
+
<rect x="870" y="243" width="246" height="33" fill="#0a0a0a" stroke="#444"/><text x="886" y="264" class="code">src/app</text><text x="1098" y="264" class="micro" text-anchor="end">ROUTES</text>
|
|
6464
|
+
<rect x="870" y="277" width="246" height="33" fill="#f0f0f0"/><text x="886" y="298" class="code ink">src/app/page.tsx</text>
|
|
6465
|
+
<rect x="870" y="311" width="246" height="33" fill="#0a0a0a" stroke="#444"/><text x="886" y="332" class="code">src/app/api/users/route.ts</text><text x="1098" y="332" class="micro" text-anchor="end">API</text>
|
|
6466
|
+
<rect x="870" y="345" width="246" height="33" fill="#0a0a0a" stroke="#444"/><text x="886" y="366" class="code">farm.config.ts</text><text x="1098" y="366" class="micro" text-anchor="end">CONFIG</text>
|
|
6467
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
6468
|
+
<text x="819" y="475" class="label bright">FILES BECOME FEATURES</text><text x="1134" y="475" class="label" text-anchor="end">ONE CONFIG</text>`;
|
|
6469
|
+
}
|
|
6470
|
+
function renderRuntimeIllustration() {
|
|
6471
|
+
return `${renderPanelHeader("PRODUCT ARCHITECTURE", "FULL STACK")}
|
|
6472
|
+
<rect x="819" y="211" width="315" height="55" fill="#f0f0f0"/>
|
|
6473
|
+
<text x="836" y="244" class="diagram-title ink">PRODUCT SURFACE</text><text x="1116" y="244" class="micro ink-muted" text-anchor="end">UI + ROUTES</text>
|
|
6474
|
+
<path d="M976 266v20m0 61v20" stroke="#727272"/>
|
|
6475
|
+
<rect x="855" y="286" width="242" height="61" fill="#a3a3a3"/>
|
|
6476
|
+
<text x="874" y="314" class="diagram-title ink">APPLICATION CORE</text><text x="874" y="334" class="micro ink-muted">APIS \xB7 MIDDLEWARE</text>
|
|
6477
|
+
<rect x="819" y="367" width="315" height="55" fill="#4c4c4c"/>
|
|
6478
|
+
<text x="836" y="400" class="diagram-title bright">CONNECTED STACK</text><text x="1116" y="400" class="micro" text-anchor="end">DATA \xB7 AUTH \xB7 DEPLOY</text>
|
|
6479
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
6480
|
+
<text x="819" y="475" class="label bright">ONE FRAMEWORK</text><text x="1134" y="475" class="label" text-anchor="end">ONE DEPLOYMENT MODEL</text>`;
|
|
6481
|
+
}
|
|
6482
|
+
function renderIllustration(type) {
|
|
6483
|
+
switch (type) {
|
|
6484
|
+
case "auth":
|
|
6485
|
+
return renderAuthIllustration();
|
|
6486
|
+
case "cache":
|
|
6487
|
+
return renderCacheIllustration();
|
|
6488
|
+
case "cli":
|
|
6489
|
+
return renderCliIllustration();
|
|
6490
|
+
case "integrations":
|
|
6491
|
+
return renderIntegrationsIllustration();
|
|
6492
|
+
case "project":
|
|
6493
|
+
return renderProjectIllustration();
|
|
6494
|
+
case "routing":
|
|
6495
|
+
return renderRoutingIllustration();
|
|
6496
|
+
default:
|
|
6497
|
+
return renderRuntimeIllustration();
|
|
6498
|
+
}
|
|
6499
|
+
}
|
|
6500
|
+
function renderFarmDocsSocialImageSvg(descriptor) {
|
|
6501
|
+
const titleLines = wrapText(descriptor.title, 22, 2);
|
|
6502
|
+
const longestTitleLine = Math.max(...titleLines.map((line) => line.length));
|
|
6503
|
+
const titleSize = titleLines.length === 1 ? longestTitleLine > 17 ? 62 : 74 : 56;
|
|
6504
|
+
const titleLineHeight = Math.round(titleSize * 0.98);
|
|
6505
|
+
const titleY = titleLines.length === 1 ? 294 : 266;
|
|
6506
|
+
const descriptionY = titleY + (titleLines.length - 1) * titleLineHeight + 59;
|
|
6507
|
+
const descriptionLines = wrapText(descriptor.description, 68, 2);
|
|
6508
|
+
const routeY = Math.max(418, descriptionY + descriptionLines.length * 29 + 24);
|
|
6509
|
+
const section = truncate(descriptor.section.toUpperCase(), 27);
|
|
6510
|
+
const route = truncate(descriptor.pageHref, 42);
|
|
6511
|
+
const footerUrl = truncate(descriptor.pageUrl.replace(/^https?:\/\//, ""), 70);
|
|
6512
|
+
const brand = truncate(descriptor.brand.toUpperCase(), 25);
|
|
6513
|
+
const titleId = `farm-docs-og-${descriptor.hash}`;
|
|
6514
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
6515
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${FARM_DOCS_SOCIAL_IMAGE_WIDTH}" height="${FARM_DOCS_SOCIAL_IMAGE_HEIGHT}" viewBox="0 0 ${FARM_DOCS_SOCIAL_IMAGE_WIDTH} ${FARM_DOCS_SOCIAL_IMAGE_HEIGHT}" role="img" aria-labelledby="${titleId}-title ${titleId}-description">
|
|
6516
|
+
<title id="${titleId}-title">${escapeXml(descriptor.imageAlt)}</title>
|
|
6517
|
+
<desc id="${titleId}-description">${escapeXml(descriptor.description)}</desc>
|
|
6518
|
+
<metadata>${escapeXml(JSON.stringify({ generator: "Farm.js docs", page: descriptor.pageUrl, illustration: descriptor.illustration }))}</metadata>
|
|
6519
|
+
<style type="text/css">
|
|
6520
|
+
${renderEmbeddedFont("Farm Sans", descriptor.fonts?.sans, "100 900")}
|
|
6521
|
+
${renderEmbeddedFont("Farm Mono", descriptor.fonts?.mono, "100 900")}
|
|
6522
|
+
${renderEmbeddedFont("Farm Pixel", descriptor.fonts?.display, "400 700")}
|
|
6523
|
+
.sans{font-family:"Farm Sans","Arial",sans-serif}.mono,.label,.code,.diagram-title,.micro{font-family:"Farm Mono","Menlo","DejaVu Sans Mono",monospace}.pixel{font-family:"Farm Pixel","Farm Mono",monospace}.label{fill:#8b8b8b;font-size:10px;font-weight:600;letter-spacing:1.2px}.code{fill:#8b8b8b;font-size:11px}.diagram-title{fill:#e7e7e7;font-size:11px;font-weight:650}.micro{fill:#777;font-size:8px;letter-spacing:.45px}.bright{fill:#f5f5f4}.ink{fill:#050505}.ink-muted{fill:#4c4c4c}
|
|
6524
|
+
</style>
|
|
6525
|
+
<defs>
|
|
6526
|
+
<pattern id="canvas-grid" width="40" height="40" patternUnits="userSpaceOnUse"><path d="M40 0H0V40" fill="none" stroke="#151515"/></pattern>
|
|
6527
|
+
<pattern id="diagonal" width="12" height="12" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="12" stroke="#171717" stroke-width="2"/></pattern>
|
|
6528
|
+
<clipPath id="frame-clip"><rect x="28" y="28" width="1144" height="574"/></clipPath>
|
|
6529
|
+
</defs>
|
|
6530
|
+
<rect width="1200" height="630" fill="#050505"/>
|
|
6531
|
+
<rect width="1200" height="630" fill="url(#canvas-grid)"/>
|
|
6532
|
+
<g clip-path="url(#frame-clip)">
|
|
6533
|
+
<rect x="28" y="28" width="1144" height="574" fill="#020202"/>
|
|
6534
|
+
<rect x="782" y="114" width="390" height="411" fill="url(#diagonal)"/>
|
|
6535
|
+
</g>
|
|
6536
|
+
<rect x="28.5" y="28.5" width="1143" height="573" fill="none" stroke="#323232"/>
|
|
6537
|
+
<path d="M28 114.5h1144M28 525.5h1144M781.5 114v411" fill="none" stroke="#303030"/>
|
|
6538
|
+
|
|
6539
|
+
<g transform="translate(71 51)">
|
|
6540
|
+
<rect width="11" height="11" rx="1" fill="#f5f5f4"/><rect x="15" width="28" height="11" rx="1" fill="#f5f5f4"/>
|
|
6541
|
+
<rect y="15" width="11" height="11" rx="1" fill="#9b9b9b"/><rect x="15" y="15" width="28" height="11" rx="1" fill="#9b9b9b"/>
|
|
6542
|
+
<rect y="30" width="11" height="11" rx="1" fill="#5f5f5f"/><rect x="15" y="30" width="20" height="11" rx="1" fill="#5f5f5f"/>
|
|
6543
|
+
<text x="61" y="24" class="mono bright" font-size="24" font-weight="550">FARM<tspan fill="#777">.JS</tspan></text>
|
|
6544
|
+
<text x="61" y="43" class="label">BY FARMING LABS</text>
|
|
6545
|
+
</g>
|
|
6546
|
+
<text x="1134" y="72" class="label" text-anchor="end">${escapeXml(brand)} \xB7 DOCUMENTATION</text>
|
|
6547
|
+
|
|
6548
|
+
<text x="71" y="198" class="mono bright" font-size="13" font-weight="650">DOCS</text>
|
|
6549
|
+
<line x1="117" y1="193" x2="155" y2="193" stroke="#696969"/>
|
|
6550
|
+
<text x="166" y="198" class="mono" fill="#9b9b9b" font-size="13">${escapeXml(section)}</text>
|
|
6551
|
+
${renderTextLines(titleLines, 71, titleY, titleLineHeight, `class="pixel bright" font-size="${titleSize}" font-weight="500" letter-spacing="-2.4"`)}
|
|
6552
|
+
${renderTextLines(descriptionLines, 71, descriptionY, 29, 'class="sans" fill="#a3a3a3" font-size="20" font-weight="430" letter-spacing="-.3"')}
|
|
6553
|
+
<rect x="71" y="${routeY}" width="${Math.min(390, 56 + route.length * 8)}" height="36" fill="#050505" stroke="#3c3c3c"/>
|
|
6554
|
+
<text x="85" y="${routeY + 23}" class="mono bright" font-size="11" font-weight="600">GET</text>
|
|
6555
|
+
<text x="119" y="${routeY + 23}" class="mono" fill="#898989" font-size="11">${escapeXml(route)}</text>
|
|
6556
|
+
|
|
6557
|
+
${renderIllustration(descriptor.illustration)}
|
|
6558
|
+
|
|
6559
|
+
<text x="71" y="570" class="mono bright" font-size="13" font-weight="550">${escapeXml(footerUrl)}</text>
|
|
6560
|
+
<text x="1134" y="570" class="mono" fill="#9b9b9b" font-size="12" text-anchor="end">FARM.JS DOCUMENTATION</text>
|
|
6561
|
+
<path d="M20 20h10M20 20v10M1180 20h-10M1180 20v10M20 610h10M20 610v-10M1180 610h-10M1180 610v-10" fill="none" stroke="#9b9b9b"/>
|
|
6562
|
+
</svg>`;
|
|
6563
|
+
}
|
|
6564
|
+
function renderFarmDocsSocialMetadata(descriptor, customImage) {
|
|
6565
|
+
const imageUrl = customImage ? new URL(customImage, descriptor.pageUrl).href : descriptor.imageUrl;
|
|
6566
|
+
const customExtension = customImage?.toLowerCase().split(/[?#]/, 1)[0];
|
|
6567
|
+
const imageType = customExtension?.endsWith(".webp") ? "image/webp" : customExtension?.endsWith(".png") ? "image/png" : customExtension?.match(/\.jpe?g$/) ? "image/jpeg" : "image/svg+xml";
|
|
6568
|
+
const tag = /* @__PURE__ */ __name((property, content, name = false) => `<meta ${name ? "name" : "property"}="${property}" content="${escapeXml(content)}">`, "tag");
|
|
6569
|
+
return [
|
|
6570
|
+
tag("og:type", "article"),
|
|
6571
|
+
tag("og:site_name", descriptor.siteName),
|
|
6572
|
+
tag("og:title", descriptor.title),
|
|
6573
|
+
tag("og:description", descriptor.description),
|
|
6574
|
+
tag("og:url", descriptor.pageUrl),
|
|
6575
|
+
tag("og:image", imageUrl),
|
|
6576
|
+
tag("og:image:type", imageType),
|
|
6577
|
+
...customImage ? [] : [
|
|
6578
|
+
tag("og:image:width", String(FARM_DOCS_SOCIAL_IMAGE_WIDTH)),
|
|
6579
|
+
tag("og:image:height", String(FARM_DOCS_SOCIAL_IMAGE_HEIGHT))
|
|
6580
|
+
],
|
|
6581
|
+
tag("og:image:alt", descriptor.imageAlt),
|
|
6582
|
+
tag("twitter:card", "summary_large_image", true),
|
|
6583
|
+
tag("twitter:title", descriptor.title, true),
|
|
6584
|
+
tag("twitter:description", descriptor.description, true),
|
|
6585
|
+
tag("twitter:image", imageUrl, true),
|
|
6586
|
+
tag("twitter:image:alt", descriptor.imageAlt, true)
|
|
6587
|
+
].join("\n ");
|
|
6588
|
+
}
|
|
6589
|
+
var import_node_crypto4, FARM_DOCS_SOCIAL_IMAGE_WIDTH, FARM_DOCS_SOCIAL_IMAGE_HEIGHT, FARM_DOCS_SOCIAL_IMAGE_VERSION;
|
|
6590
|
+
var init_social_image = __esm({
|
|
6591
|
+
"src/docs/social-image.ts"() {
|
|
6592
|
+
"use strict";
|
|
6593
|
+
import_node_crypto4 = require("crypto");
|
|
6594
|
+
FARM_DOCS_SOCIAL_IMAGE_WIDTH = 1200;
|
|
6595
|
+
FARM_DOCS_SOCIAL_IMAGE_HEIGHT = 630;
|
|
6596
|
+
FARM_DOCS_SOCIAL_IMAGE_VERSION = 3;
|
|
6597
|
+
__name(normalizeEntry, "normalizeEntry");
|
|
6598
|
+
__name(encodeSlugPath, "encodeSlugPath");
|
|
6599
|
+
__name(getSocialImageConfig, "getSocialImageConfig");
|
|
6600
|
+
__name(getNavTitle, "getNavTitle");
|
|
6601
|
+
__name(isFalse, "isFalse");
|
|
6602
|
+
__name(isExternalOrRootPath, "isExternalOrRootPath");
|
|
6603
|
+
__name(isFarmDocsSocialImageEnabled, "isFarmDocsSocialImageEnabled");
|
|
6604
|
+
__name(getFarmDocsCustomSocialImage, "getFarmDocsCustomSocialImage");
|
|
6605
|
+
__name(resolveIllustration, "resolveIllustration");
|
|
6606
|
+
__name(createHashValue, "createHashValue");
|
|
6607
|
+
__name(resolveBaseUrl, "resolveBaseUrl");
|
|
6608
|
+
__name(createFarmDocsSocialImageDescriptor, "createFarmDocsSocialImageDescriptor");
|
|
6609
|
+
__name(getFarmDocsSocialImageSlug, "getFarmDocsSocialImageSlug");
|
|
6610
|
+
__name(escapeXml, "escapeXml");
|
|
6611
|
+
__name(truncate, "truncate");
|
|
6612
|
+
__name(wrapText, "wrapText");
|
|
6613
|
+
__name(renderTextLines, "renderTextLines");
|
|
6614
|
+
__name(renderEmbeddedFont, "renderEmbeddedFont");
|
|
6615
|
+
__name(renderArrow, "renderArrow");
|
|
6616
|
+
__name(renderPanelHeader, "renderPanelHeader");
|
|
6617
|
+
__name(renderRoutingIllustration, "renderRoutingIllustration");
|
|
6618
|
+
__name(renderAuthIllustration, "renderAuthIllustration");
|
|
6619
|
+
__name(renderCacheIllustration, "renderCacheIllustration");
|
|
6620
|
+
__name(renderIntegrationsIllustration, "renderIntegrationsIllustration");
|
|
6621
|
+
__name(renderCliIllustration, "renderCliIllustration");
|
|
6622
|
+
__name(renderProjectIllustration, "renderProjectIllustration");
|
|
6623
|
+
__name(renderRuntimeIllustration, "renderRuntimeIllustration");
|
|
6624
|
+
__name(renderIllustration, "renderIllustration");
|
|
6625
|
+
__name(renderFarmDocsSocialImageSvg, "renderFarmDocsSocialImageSvg");
|
|
6626
|
+
__name(renderFarmDocsSocialMetadata, "renderFarmDocsSocialMetadata");
|
|
6627
|
+
}
|
|
6628
|
+
});
|
|
6629
|
+
|
|
6175
6630
|
// src/docs/handler.ts
|
|
6176
6631
|
function trimSlashes2(value) {
|
|
6177
6632
|
return value.replace(/^\/+|\/+$/g, "");
|
|
6178
6633
|
}
|
|
6179
|
-
function
|
|
6634
|
+
function normalizeEntry2(entry) {
|
|
6180
6635
|
if (!entry || entry === "/") return "/";
|
|
6181
6636
|
return `/${trimSlashes2(entry)}`;
|
|
6182
6637
|
}
|
|
@@ -6188,10 +6643,10 @@ function resolveFarmDocsFavicon(docs, options) {
|
|
|
6188
6643
|
if (typeof configuredFavicon === "string" && configuredFavicon.trim()) {
|
|
6189
6644
|
return configuredFavicon.trim();
|
|
6190
6645
|
}
|
|
6191
|
-
const publicDir =
|
|
6646
|
+
const publicDir = import_node_path13.default.join(import_node_path13.default.resolve(options.root), "public");
|
|
6192
6647
|
for (const fileName of FARM_DOCS_FAVICON_FILES) {
|
|
6193
|
-
const faviconPath =
|
|
6194
|
-
if ((0,
|
|
6648
|
+
const faviconPath = import_node_path13.default.join(publicDir, fileName);
|
|
6649
|
+
if ((0, import_node_fs9.existsSync)(faviconPath) && (0, import_node_fs9.statSync)(faviconPath).isFile()) {
|
|
6195
6650
|
return `/${fileName}`;
|
|
6196
6651
|
}
|
|
6197
6652
|
}
|
|
@@ -6225,10 +6680,10 @@ function isSafeSegment(segment) {
|
|
|
6225
6680
|
return segment !== ".." && !segment.includes("/") && !segment.includes("\\");
|
|
6226
6681
|
}
|
|
6227
6682
|
function resolveInside(root, target) {
|
|
6228
|
-
const resolvedRoot =
|
|
6229
|
-
const resolvedTarget =
|
|
6230
|
-
const relative4 =
|
|
6231
|
-
if (relative4 === "" || !relative4.startsWith("..") && !
|
|
6683
|
+
const resolvedRoot = import_node_path13.default.resolve(root);
|
|
6684
|
+
const resolvedTarget = import_node_path13.default.resolve(target);
|
|
6685
|
+
const relative4 = import_node_path13.default.relative(resolvedRoot, resolvedTarget);
|
|
6686
|
+
if (relative4 === "" || !relative4.startsWith("..") && !import_node_path13.default.isAbsolute(relative4)) {
|
|
6232
6687
|
return resolvedTarget;
|
|
6233
6688
|
}
|
|
6234
6689
|
return null;
|
|
@@ -6237,36 +6692,36 @@ function isFarmDocsRequest(docs, request) {
|
|
|
6237
6692
|
if (!docs?.enabled) return false;
|
|
6238
6693
|
if (request.method !== "GET" && request.method !== "HEAD") return false;
|
|
6239
6694
|
const pathname = new URL(request.url).pathname;
|
|
6240
|
-
const entry =
|
|
6695
|
+
const entry = normalizeEntry2(docs.entry);
|
|
6241
6696
|
if (entry === "/") return true;
|
|
6242
6697
|
return pathname === entry || pathname === `${entry}.md` || pathname.startsWith(`${entry}/`);
|
|
6243
6698
|
}
|
|
6244
6699
|
function resolveFarmDocsContentDir(docs, options) {
|
|
6245
|
-
const root =
|
|
6700
|
+
const root = import_node_path13.default.resolve(options.root);
|
|
6246
6701
|
const srcDir = options.srcDir || "src";
|
|
6247
6702
|
const configuredContentDir = docs.contentDir || docs.config.contentDir;
|
|
6248
6703
|
if (configuredContentDir) {
|
|
6249
|
-
return
|
|
6704
|
+
return import_node_path13.default.isAbsolute(configuredContentDir) ? configuredContentDir : import_node_path13.default.join(root, configuredContentDir);
|
|
6250
6705
|
}
|
|
6251
6706
|
const entryDir = docs.config.entry || trimSlashes2(docs.entry) || "docs";
|
|
6252
|
-
const appDocsDir =
|
|
6253
|
-
if ((0,
|
|
6254
|
-
return
|
|
6707
|
+
const appDocsDir = import_node_path13.default.join(root, srcDir, "app", entryDir);
|
|
6708
|
+
if ((0, import_node_fs9.existsSync)(appDocsDir)) return appDocsDir;
|
|
6709
|
+
return import_node_path13.default.join(root, entryDir);
|
|
6255
6710
|
}
|
|
6256
6711
|
function getFarmDocsRouteTypeEntries(docs) {
|
|
6257
6712
|
if (!docs?.enabled) return [];
|
|
6258
|
-
const entry =
|
|
6713
|
+
const entry = normalizeEntry2(docs.entry);
|
|
6259
6714
|
if (entry === "/") return ["/", "/[...docs]"];
|
|
6260
6715
|
return [entry, `${entry}/[...docs]`];
|
|
6261
6716
|
}
|
|
6262
6717
|
function getFarmDocsDocumentNavigationMatchers(docs) {
|
|
6263
6718
|
if (!docs?.enabled) return [];
|
|
6264
|
-
const entry =
|
|
6719
|
+
const entry = normalizeEntry2(docs.entry);
|
|
6265
6720
|
return [entry === "/" ? "/(.*)" : `${entry}(.*)`];
|
|
6266
6721
|
}
|
|
6267
6722
|
function getRequestSlug(docs, request) {
|
|
6268
6723
|
const pathname = new URL(request.url).pathname;
|
|
6269
|
-
const entry =
|
|
6724
|
+
const entry = normalizeEntry2(docs.entry);
|
|
6270
6725
|
if (entry === "/") return normalizeSlug(pathname);
|
|
6271
6726
|
if (pathname === entry || pathname === `${entry}.md`) return "";
|
|
6272
6727
|
return normalizeSlug(pathname.slice(entry.length));
|
|
@@ -6274,14 +6729,14 @@ function getRequestSlug(docs, request) {
|
|
|
6274
6729
|
function findDocsPageFile(contentDir, slug) {
|
|
6275
6730
|
const segments = slug ? slug.split("/").filter(Boolean) : [];
|
|
6276
6731
|
if (!segments.every(isSafeSegment)) return null;
|
|
6277
|
-
const slugDir =
|
|
6278
|
-
const candidates = segments.length === 0 ? DOCS_FILE_NAMES.map((filename) =>
|
|
6279
|
-
...DOCS_FILE_NAMES.map((filename) =>
|
|
6280
|
-
...DOCS_FILE_EXTENSIONS2.map((extension) =>
|
|
6732
|
+
const slugDir = import_node_path13.default.join(contentDir, ...segments);
|
|
6733
|
+
const candidates = segments.length === 0 ? DOCS_FILE_NAMES.map((filename) => import_node_path13.default.join(contentDir, filename)) : [
|
|
6734
|
+
...DOCS_FILE_NAMES.map((filename) => import_node_path13.default.join(slugDir, filename)),
|
|
6735
|
+
...DOCS_FILE_EXTENSIONS2.map((extension) => import_node_path13.default.join(contentDir, `${slug}${extension}`))
|
|
6281
6736
|
];
|
|
6282
6737
|
for (const candidate of candidates) {
|
|
6283
6738
|
const safePath = resolveInside(contentDir, candidate);
|
|
6284
|
-
if (safePath && (0,
|
|
6739
|
+
if (safePath && (0, import_node_fs9.existsSync)(safePath) && (0, import_node_fs9.statSync)(safePath).isFile()) {
|
|
6285
6740
|
return safePath;
|
|
6286
6741
|
}
|
|
6287
6742
|
}
|
|
@@ -6316,7 +6771,7 @@ function titleFromMarkdown2(body, fallback) {
|
|
|
6316
6771
|
function loadFarmDocsPage(contentDir, docs, slug) {
|
|
6317
6772
|
const sourcePath = findDocsPageFile(contentDir, slug);
|
|
6318
6773
|
if (!sourcePath) return null;
|
|
6319
|
-
const source = (0,
|
|
6774
|
+
const source = (0, import_node_fs9.readFileSync)(sourcePath, "utf8");
|
|
6320
6775
|
const { frontmatter, body } = parseFrontmatter(source);
|
|
6321
6776
|
const title = frontmatter.title || titleFromMarkdown2(body, titleFromSlug(slug));
|
|
6322
6777
|
const href = createDocsHref(docs.entry, slug);
|
|
@@ -6324,6 +6779,7 @@ function loadFarmDocsPage(contentDir, docs, slug) {
|
|
|
6324
6779
|
slug,
|
|
6325
6780
|
title,
|
|
6326
6781
|
description: frontmatter.description,
|
|
6782
|
+
section: frontmatter.section,
|
|
6327
6783
|
href,
|
|
6328
6784
|
sourcePath,
|
|
6329
6785
|
lastModified: resolveFarmDocsPageLastModified(contentDir, sourcePath, frontmatter),
|
|
@@ -6332,15 +6788,15 @@ function loadFarmDocsPage(contentDir, docs, slug) {
|
|
|
6332
6788
|
};
|
|
6333
6789
|
}
|
|
6334
6790
|
function createDocsHref(entry, slug) {
|
|
6335
|
-
const normalizedEntry =
|
|
6791
|
+
const normalizedEntry = normalizeEntry2(entry);
|
|
6336
6792
|
const normalizedSlug = trimSlashes2(slug);
|
|
6337
6793
|
if (normalizedEntry === "/") return normalizedSlug ? `/${normalizedSlug}` : "/";
|
|
6338
6794
|
return normalizedSlug ? `${normalizedEntry}/${normalizedSlug}` : normalizedEntry;
|
|
6339
6795
|
}
|
|
6340
6796
|
function pathToSlug(contentDir, filePath) {
|
|
6341
|
-
const relative4 =
|
|
6797
|
+
const relative4 = import_node_path13.default.relative(contentDir, filePath).replace(/\\/g, "/");
|
|
6342
6798
|
if (relative4.startsWith("..")) return null;
|
|
6343
|
-
const extension =
|
|
6799
|
+
const extension = import_node_path13.default.extname(relative4);
|
|
6344
6800
|
if (!DOCS_FILE_EXTENSIONS2.includes(extension)) return null;
|
|
6345
6801
|
const withoutExtension = relative4.slice(0, -extension.length);
|
|
6346
6802
|
if (withoutExtension === "page" || withoutExtension === "index") return "";
|
|
@@ -6353,12 +6809,12 @@ function loadPage(contentDir, docs, request) {
|
|
|
6353
6809
|
return loadFarmDocsPage(contentDir, docs, getRequestSlug(docs, request));
|
|
6354
6810
|
}
|
|
6355
6811
|
function discoverFarmDocsPages(contentDir, docs) {
|
|
6356
|
-
if (!(0,
|
|
6812
|
+
if (!(0, import_node_fs9.existsSync)(contentDir)) return [];
|
|
6357
6813
|
const pages = [];
|
|
6358
6814
|
const visit = /* @__PURE__ */ __name((dir) => {
|
|
6359
|
-
for (const entry of (0,
|
|
6815
|
+
for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
|
|
6360
6816
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
6361
|
-
const absolutePath =
|
|
6817
|
+
const absolutePath = import_node_path13.default.join(dir, entry.name);
|
|
6362
6818
|
if (entry.isDirectory()) {
|
|
6363
6819
|
visit(absolutePath);
|
|
6364
6820
|
continue;
|
|
@@ -6366,7 +6822,7 @@ function discoverFarmDocsPages(contentDir, docs) {
|
|
|
6366
6822
|
if (!entry.isFile()) continue;
|
|
6367
6823
|
const slug = pathToSlug(contentDir, absolutePath);
|
|
6368
6824
|
if (slug === null) continue;
|
|
6369
|
-
const source = (0,
|
|
6825
|
+
const source = (0, import_node_fs9.readFileSync)(absolutePath, "utf8");
|
|
6370
6826
|
const { frontmatter, body } = parseFrontmatter(source);
|
|
6371
6827
|
pages.push({
|
|
6372
6828
|
slug,
|
|
@@ -7144,7 +7600,7 @@ function renderPixelBreadcrumb(page2, docs) {
|
|
|
7144
7600
|
const parentSegments = segments.slice(0, -1);
|
|
7145
7601
|
const parentSegment = parentSegments[parentSegments.length - 1];
|
|
7146
7602
|
const currentSegment = segments[segments.length - 1];
|
|
7147
|
-
const entry =
|
|
7603
|
+
const entry = normalizeEntry2(docs.entry);
|
|
7148
7604
|
const parentPath = parentSegments.join("/");
|
|
7149
7605
|
const parentHref = entry === "/" ? `/${parentPath}` : `${entry}/${parentPath}`;
|
|
7150
7606
|
return `<nav class="fd-breadcrumb" aria-label="Breadcrumb">
|
|
@@ -7182,7 +7638,7 @@ ${items.map(
|
|
|
7182
7638
|
</div>`;
|
|
7183
7639
|
}
|
|
7184
7640
|
function renderDocsRuntimeScript(docs) {
|
|
7185
|
-
const docsEntry = JSON.stringify(
|
|
7641
|
+
const docsEntry = JSON.stringify(normalizeEntry2(docs.entry));
|
|
7186
7642
|
return `<script>(()=>{if(window.__farmDocsRuntime)return;window.__farmDocsRuntime=true;document.documentElement.dataset.farmDocsRuntime="true";document.documentElement.dataset.farmDocsRuntimeId=Math.random().toString(36).slice(2);const docsEntry=${docsEntry};let cleanupToc=()=>{};let closeMobileSidebar=()=>{};const normalizePath=(path)=>path.length>1?path.replace(/\\/+$/,""):path;const isDocsPath=(path)=>{const next=normalizePath(path);const entry=normalizePath(docsEntry);if(next.endsWith(".md"))return false;if(entry==="/")return true;return next===entry||next.startsWith(entry+"/")};const initToc=()=>{cleanupToc();const toc=document.getElementById("nd-toc");if(!toc){cleanupToc=()=>{};return}const links=Array.from(toc.querySelectorAll("[data-toc-item]"));const thumb=toc.querySelector("[data-toc-thumb]");const pairs=links.map((link)=>{let id=link.hash.slice(1);try{id=decodeURIComponent(id)}catch{}return{link,heading:document.getElementById(id)}}).filter((item)=>item.heading);const setActive=(active)=>{for(const {link} of pairs)link.dataset.active=link===active.link?"true":"false";if(!thumb)return;const styles=getComputedStyle(active.link);const top=active.link.offsetTop+parseFloat(styles.paddingTop||"0");const bottom=active.link.offsetTop+active.link.clientHeight-parseFloat(styles.paddingBottom||"0");thumb.style.clipPath="polygon(0 "+top+"px,100% "+top+"px,100% "+bottom+"px,0 "+bottom+"px)"};const update=()=>{if(pairs.length===0)return;const offset=Math.min(window.innerHeight*0.3,160);let active=pairs[0];for(const pair of pairs){if(pair.heading.getBoundingClientRect().top<=offset)active=pair;else break}setActive(active)};let frame=0;const schedule=()=>{if(frame)return;frame=requestAnimationFrame(()=>{frame=0;update()})};const onHashChange=()=>setTimeout(schedule,0);window.addEventListener("scroll",schedule,{passive:true});window.addEventListener("resize",schedule);window.addEventListener("hashchange",onHashChange);cleanupToc=()=>{window.removeEventListener("scroll",schedule);window.removeEventListener("resize",schedule);window.removeEventListener("hashchange",onHashChange);if(frame)cancelAnimationFrame(frame);frame=0};update()};const getSidebar=()=>document.getElementById("nd-sidebar");const ensureActiveVisible=()=>{const sidebar=getSidebar();if(!sidebar)return;const active=sidebar.querySelector('a[data-active="true"]');if(!(active instanceof HTMLElement))return;const activeRect=active.getBoundingClientRect();const sidebarRect=sidebar.getBoundingClientRect();if(activeRect.top<sidebarRect.top||activeRect.bottom>sidebarRect.bottom)sidebar.scrollTop+=activeRect.top-sidebarRect.top-(sidebar.clientHeight-activeRect.height)/2};const setSidebarActive=(path)=>{const sidebar=getSidebar();if(!sidebar)return;const current=normalizePath(path);for(const link of Array.from(sidebar.querySelectorAll("a[href]"))){try{link.dataset.active=normalizePath(new URL(link.href,location.href).pathname)===current?"true":"false"}catch{}}ensureActiveVisible()};const initMobileSidebar=()=>{const layout=document.getElementById("nd-docs-layout");const sidebar=getSidebar();const toggle=document.querySelector("[data-sidebar-toggle]");const backdrop=document.querySelector("[data-sidebar-backdrop]");if(!layout||!sidebar||!(toggle instanceof HTMLButtonElement))return;const setOpen=(open)=>{layout.dataset.sidebarOpen=open?"true":"false";document.documentElement.dataset.farmDocsSidebar=open?"open":"closed";toggle.setAttribute("aria-expanded",open?"true":"false");toggle.setAttribute("aria-label",open?"Close menu":"Open menu")};const toggleOpen=()=>setOpen(layout.dataset.sidebarOpen!=="true");closeMobileSidebar=()=>setOpen(false);toggle.addEventListener("click",(event)=>{event.preventDefault();toggleOpen()});backdrop?.addEventListener("click",()=>closeMobileSidebar());document.addEventListener("keydown",(event)=>{if(event.key==="Escape")closeMobileSidebar()});sidebar.addEventListener("click",(event)=>{const target=event.target instanceof Element?event.target.closest("a[href]"):null;if(target)closeMobileSidebar()});closeMobileSidebar()};const initSidebarScroll=()=>{const sidebar=getSidebar();if(!sidebar)return;const key="farmdocs:sidebar-scroll:"+location.origin;const getStorage=()=>{try{return window.sessionStorage}catch{return null}};const readSaved=()=>{try{const raw=getStorage()?.getItem(key);if(!raw)return null;const parsed=JSON.parse(raw);return parsed&&typeof parsed==="object"?parsed:null}catch{return null}};const save=(path=location.pathname)=>{try{getStorage()?.setItem(key,JSON.stringify({path,scrollTop:sidebar.scrollTop}))}catch{}};const saved=readSaved();if(saved?.path===location.pathname&&Number.isFinite(Number(saved.scrollTop)))sidebar.scrollTop=Number(saved.scrollTop);ensureActiveVisible();save();sidebar.addEventListener("scroll",()=>save(),{passive:true});sidebar.addEventListener("click",(event)=>{const target=event.target instanceof Element?event.target.closest("a[href]"):null;if(!target)return;try{save(new URL(target.href,location.href).pathname)}catch{save()}});window.addEventListener("beforeunload",()=>save())};let navigateController=null;const getPageKey=(root)=>{const article=root.getElementById("nd-page");if(!article)return"";return article.querySelector("h1")?.textContent?.trim()||article.textContent?.replace(/\\s+/g," ").trim().slice(0,160)||""};const swapDocsPage=(html,url)=>{const nextDoc=new DOMParser().parseFromString(html,"text/html");const nextArticle=nextDoc.getElementById("nd-page");const currentArticle=document.getElementById("nd-page");if(!nextArticle||!currentArticle)return false;const nextKey=getPageKey(nextDoc);const importedArticle=document.importNode(nextArticle,true);currentArticle.replaceWith(importedArticle);const renderedArticle=document.getElementById("nd-page");if(!renderedArticle||renderedArticle===currentArticle||(nextKey&&getPageKey(document)!==nextKey))return false;const nextToc=nextDoc.getElementById("nd-toc");const currentToc=document.getElementById("nd-toc");if(nextToc&¤tToc)currentToc.replaceWith(document.importNode(nextToc,true));if(nextDoc.title)document.title=nextDoc.title;const nextDescription=nextDoc.querySelector('meta[name="description"]');const currentDescription=document.querySelector('meta[name="description"]');if(nextDescription&¤tDescription)currentDescription.setAttribute("content",nextDescription.getAttribute("content")||"");setSidebarActive(url.pathname);initToc();closeMobileSidebar();return true};const navigateDocs=async(url,{replace=false,scroll=true}={})=>{if(!isDocsPath(url.pathname))return false;if(navigateController)navigateController.abort();const controller=new AbortController();navigateController=controller;document.documentElement.dataset.farmDocsNavigating="true";try{const response=await fetch(url.href,{cache:"no-store",headers:{accept:"text/html","x-farm-docs-navigate":"1"},signal:controller.signal});if(!response.ok||!((response.headers.get("content-type")||"").includes("text/html")))return false;const html=await response.text();if(!swapDocsPage(html,url))return false;if(replace)history.replaceState({farmDocs:true},"",url.href);else history.pushState({farmDocs:true},"",url.href);if(scroll){if(url.hash){let id=url.hash.slice(1);try{id=decodeURIComponent(id)}catch{}document.getElementById(id)?.scrollIntoView({block:"start"})}else window.scrollTo({top:0,left:0})}return true}catch(error){if(error?.name==="AbortError")return true;return false}finally{if(navigateController===controller){delete document.documentElement.dataset.farmDocsNavigating;navigateController=null}}};const initClientNavigation=()=>{document.addEventListener("click",(event)=>{if(event.defaultPrevented||event.button!==0||event.metaKey||event.ctrlKey||event.shiftKey||event.altKey)return;const target=event.target instanceof Element?event.target.closest("a[href]"):null;if(!target||target.target||target.hasAttribute("download"))return;let url;try{url=new URL(target.href,location.href)}catch{return}if(url.origin!==location.origin||!isDocsPath(url.pathname))return;if(normalizePath(url.pathname)===normalizePath(location.pathname)&&url.hash)return;event.preventDefault();navigateDocs(url).then((handled)=>{if(!handled)location.href=url.href})});window.addEventListener("popstate",()=>{navigateDocs(new URL(location.href),{replace:true,scroll:false}).then((handled)=>{if(!handled)location.reload()})})};const init=()=>{initToc();initMobileSidebar();initSidebarScroll();initClientNavigation()};if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",init,{once:true});else init()})();</script>`;
|
|
7187
7643
|
}
|
|
7188
7644
|
function renderDocsPageActionsRuntimeScript() {
|
|
@@ -7197,13 +7653,13 @@ ${renderDocsHashRuntimeScript()}
|
|
|
7197
7653
|
${renderDocsPageActionsRuntimeScript()}`;
|
|
7198
7654
|
}
|
|
7199
7655
|
function readCssWithImports(filePath, seen = /* @__PURE__ */ new Set()) {
|
|
7200
|
-
const resolved =
|
|
7656
|
+
const resolved = import_node_path13.default.resolve(filePath);
|
|
7201
7657
|
if (seen.has(resolved)) return "";
|
|
7202
7658
|
seen.add(resolved);
|
|
7203
|
-
const source = (0,
|
|
7659
|
+
const source = (0, import_node_fs9.readFileSync)(resolved, "utf8");
|
|
7204
7660
|
return source.replace(/@import\s+["']([^"']+)["'];?/g, (_match, importPath) => {
|
|
7205
7661
|
try {
|
|
7206
|
-
const importedPath = importPath.startsWith(".") ?
|
|
7662
|
+
const importedPath = importPath.startsWith(".") ? import_node_path13.default.resolve(import_node_path13.default.dirname(resolved), importPath) : (0, import_node_module5.createRequire)(resolved).resolve(importPath);
|
|
7207
7663
|
return readCssWithImports(importedPath, seen);
|
|
7208
7664
|
} catch {
|
|
7209
7665
|
return "";
|
|
@@ -7211,11 +7667,11 @@ function readCssWithImports(filePath, seen = /* @__PURE__ */ new Set()) {
|
|
|
7211
7667
|
});
|
|
7212
7668
|
}
|
|
7213
7669
|
function resolvePixelBorderThemeCss(options) {
|
|
7214
|
-
const cacheKey =
|
|
7670
|
+
const cacheKey = import_node_path13.default.resolve(options.root);
|
|
7215
7671
|
const cached = themeCssCache.get(cacheKey);
|
|
7216
7672
|
if (cached !== void 0) return cached;
|
|
7217
7673
|
try {
|
|
7218
|
-
const requireFromApp = (0, import_node_module5.createRequire)(
|
|
7674
|
+
const requireFromApp = (0, import_node_module5.createRequire)(import_node_path13.default.join(cacheKey, "package.json"));
|
|
7219
7675
|
const themeCssPath = requireFromApp.resolve("@farming-labs/theme/pixel-border/css");
|
|
7220
7676
|
const requireFromTheme = (0, import_node_module5.createRequire)(themeCssPath);
|
|
7221
7677
|
const fumadocsCssPath = requireFromTheme.resolve("fumadocs-ui/style.css");
|
|
@@ -7228,17 +7684,28 @@ ${readCssWithImports(themeCssPath)}`;
|
|
|
7228
7684
|
return "";
|
|
7229
7685
|
}
|
|
7230
7686
|
}
|
|
7231
|
-
function renderFarmDocsBridgeCss(docs) {
|
|
7687
|
+
function renderFarmDocsBridgeCss(docs, fontAssets, layoutFonts) {
|
|
7232
7688
|
const sidebarWidth = getThemeLayoutValue(docs, "sidebarWidth", 320);
|
|
7233
7689
|
const contentWidth = getThemeLayoutValue(docs, "contentWidth", 860);
|
|
7690
|
+
const fontFaces = fontAssets.map(
|
|
7691
|
+
({ family, url }) => `@font-face { font-family: "${family}"; src: url("${url}") format("woff2"); font-style: normal; font-weight: 100 900; font-display: block; }`
|
|
7692
|
+
).join("\n");
|
|
7693
|
+
const fontVariables = [
|
|
7694
|
+
fontAssets.some(({ family }) => family === "Geist Sans") ? '--font-geist-sans: "Geist Sans", ui-sans-serif, system-ui, sans-serif;' : "",
|
|
7695
|
+
fontAssets.some(({ family }) => family === "Geist Mono") ? '--font-geist-mono: "Geist Mono", ui-monospace, monospace;' : ""
|
|
7696
|
+
].filter(Boolean).join(" ");
|
|
7697
|
+
const fontCss = fontFaces ? `${fontFaces}
|
|
7698
|
+
:root { ${fontVariables} }` : "";
|
|
7699
|
+
const layoutFontVariables = [
|
|
7700
|
+
renderFarmDocsLayoutFontVariable("--fd-layout-font-body", layoutFonts?.body),
|
|
7701
|
+
renderFarmDocsLayoutFontVariable("--fd-layout-font-code", layoutFonts?.code)
|
|
7702
|
+
].filter(Boolean).join(" ");
|
|
7234
7703
|
return `
|
|
7235
|
-
|
|
7236
|
-
@font-face { font-family: "Geist Mono"; src: local("Geist Mono"), url("${GEIST_MONO_FONT_URL}") format("woff2"), url("/node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2") format("woff2"); font-display: block; font-style: normal; font-weight: 100 900; }
|
|
7237
|
-
:root { color-scheme: dark; --font-geist-sans: "Geist Sans"; --font-geist-mono: "Geist Mono"; --fd-sidebar-width: ${sidebarWidth}px; --fd-content-width: ${contentWidth}px; --fd-toc-width: 240px; --fd-docs-height: 100vh; --fd-docs-row-1: var(--fd-nav-height, 44px); --fd-docs-font-sans: var(--font-geist-sans, "Geist Sans", var(--font-sans, system-ui, -apple-system, sans-serif)); --fd-docs-font-mono: var(--font-geist-mono, "Geist Mono", var(--font-mono, ui-monospace, monospace)); --fd-font-sans: var(--fd-docs-font-sans); --fd-font-mono: var(--fd-docs-font-mono); --fd-pixel-rail-width: 12px; --fd-sidebar-edge: calc(var(--fd-pixel-rail-width) + 18px); --fd-sidebar-guide-x: calc(var(--fd-sidebar-edge) + 16px); --fd-sidebar-link-x: calc(var(--fd-sidebar-guide-x) + 22px); --fd-sidebar-sub-guide-x: calc(var(--fd-sidebar-link-x) + 7px); --fd-sidebar-sub-link-x: calc(var(--fd-sidebar-sub-guide-x) + 28px); --fd-sidebar-branch-gap: 0px; --fd-sidebar-nested-icon-gap: 0px; --fd-sidebar-line-color: color-mix(in srgb, var(--color-fd-border, hsl(0 0% 15%)) 88%, transparent); }
|
|
7704
|
+
:root { color-scheme: dark; --font-geist-sans: ui-sans-serif, system-ui, sans-serif; --font-geist-mono: ui-monospace, monospace; ${layoutFontVariables} --fd-sidebar-width: ${sidebarWidth}px; --fd-content-width: ${contentWidth}px; --fd-toc-width: 240px; --fd-docs-height: 100vh; --fd-docs-row-1: var(--fd-nav-height, 44px); --fd-docs-font-sans: var(--fd-layout-font-body, var(--font-geist-sans, var(--font-sans, system-ui, -apple-system, sans-serif))); --fd-docs-font-mono: var(--fd-layout-font-code, var(--font-geist-mono, var(--font-mono, ui-monospace, monospace))); --fd-font-sans: var(--fd-docs-font-sans); --fd-font-mono: var(--fd-docs-font-mono); --fd-pixel-rail-width: 12px; --fd-sidebar-edge: calc(var(--fd-pixel-rail-width) + 18px); --fd-sidebar-guide-x: calc(var(--fd-sidebar-edge) + 16px); --fd-sidebar-link-x: calc(var(--fd-sidebar-guide-x) + 22px); --fd-sidebar-sub-guide-x: calc(var(--fd-sidebar-link-x) + 7px); --fd-sidebar-sub-link-x: calc(var(--fd-sidebar-sub-guide-x) + 28px); --fd-sidebar-branch-gap: 0px; --fd-sidebar-nested-icon-gap: 0px; --fd-sidebar-line-color: color-mix(in srgb, var(--color-fd-border, hsl(0 0% 15%)) 88%, transparent); }
|
|
7238
7705
|
* { box-sizing: border-box; }
|
|
7239
7706
|
html { background: var(--color-fd-background, hsl(0 0% 2%)); scroll-padding-top: calc(var(--fd-nav-height, 44px) + 24px); }
|
|
7240
7707
|
html[data-farm-docs-sidebar="open"], html[data-farm-docs-sidebar="open"] body { overflow: hidden; }
|
|
7241
|
-
body { margin: 0; min-height: 100vh; background: var(--color-fd-background, hsl(0 0% 2%)); color: var(--color-fd-foreground, oklch(0.985 0.001 106.423)); font-family: var(--fd-docs-font-sans); text-rendering: optimizeLegibility; }
|
|
7708
|
+
body { margin: 0; min-height: 100vh; background: var(--color-fd-background, hsl(0 0% 2%)); color: var(--color-fd-foreground, oklch(0.985 0.001 106.423)); font-family: var(--fd-docs-font-sans); font-synthesis: none; text-rendering: optimizeLegibility; }
|
|
7242
7709
|
::selection { background: var(--color-fd-foreground, #fff); color: var(--color-fd-background, #000); }
|
|
7243
7710
|
a { color: inherit; }
|
|
7244
7711
|
#nd-docs-layout { --fd-sidebar-col: var(--fd-sidebar-width); display: grid; grid-template: "sidebar header header" var(--fd-nav-height, 44px) "sidebar main toc" 1fr / var(--fd-sidebar-width) minmax(0, 1fr) var(--fd-toc-width) !important; min-height: 100vh; border-top: 1px solid var(--color-fd-border, hsl(0 0% 15%)); background: var(--color-fd-background, hsl(0 0% 2%)); }
|
|
@@ -7418,14 +7885,45 @@ function renderFarmDocsBridgeCss(docs) {
|
|
|
7418
7885
|
.sh__line { min-height: 1.6em; }
|
|
7419
7886
|
}
|
|
7420
7887
|
${farmDocsPixelBorderCss}
|
|
7888
|
+
${fontCss}
|
|
7421
7889
|
`;
|
|
7422
7890
|
}
|
|
7423
|
-
function
|
|
7891
|
+
function renderFarmDocsLayoutFontVariable(name, font) {
|
|
7892
|
+
const family = font?.style.fontFamily;
|
|
7893
|
+
if (!family || /[;{}<>]/.test(family)) return "";
|
|
7894
|
+
return `${name}: ${family};`;
|
|
7895
|
+
}
|
|
7896
|
+
function renderFarmDocsFontPreloads(fontAssets) {
|
|
7897
|
+
return fontAssets.map(
|
|
7898
|
+
({ url }) => `<link rel="preload" href="${escapeAttribute2(url)}" as="font" type="font/woff2" crossorigin>`
|
|
7899
|
+
).join("\n ");
|
|
7900
|
+
}
|
|
7901
|
+
function renderFarmDocsFontPreloadHeader(fontAssets) {
|
|
7902
|
+
return fontAssets.map(({ url }) => `<${url}>; rel=preload; as=font; type=font/woff2; crossorigin`).join(", ");
|
|
7903
|
+
}
|
|
7904
|
+
function getFarmLayoutFontPreloads(layoutFonts) {
|
|
7905
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7906
|
+
return [layoutFonts?.body, layoutFonts?.code].flatMap(
|
|
7907
|
+
(font) => (font?.preloads || []).filter(({ href }) => {
|
|
7908
|
+
if (seen.has(href)) return false;
|
|
7909
|
+
seen.add(href);
|
|
7910
|
+
return true;
|
|
7911
|
+
})
|
|
7912
|
+
);
|
|
7913
|
+
}
|
|
7914
|
+
function renderFarmLayoutFontPreloadHeader(layoutFonts) {
|
|
7915
|
+
return getFarmLayoutFontPreloads(layoutFonts).map(({ href, type }) => `<${href}>; rel=preload; as=font; type=${type}; crossorigin`).join(", ");
|
|
7916
|
+
}
|
|
7917
|
+
function renderPixelDocsHtml(page2, pages, docs, themeCss, clientEntry, faviconHref, requestUrl, fontAssets, layoutFonts, fontStylesheetHref) {
|
|
7424
7918
|
const navTitle = typeof docs.config.nav === "object" && docs.config.nav && "title" in docs.config.nav ? String(docs.config.nav.title || "Docs") : "Docs";
|
|
7425
7919
|
const description = page2.description || docs.config.metadata?.description || "";
|
|
7426
7920
|
const tocItems = extractTocItems(page2.body, getThemeTocDepth(docs));
|
|
7427
7921
|
const themeName = getThemeName(docs);
|
|
7428
7922
|
const searchEnabled = isFarmDocsSearchEnabled(docs);
|
|
7923
|
+
const socialMetadata = isFarmDocsSocialImageEnabled(page2, docs) ? renderFarmDocsSocialMetadata(
|
|
7924
|
+
createFarmDocsSocialImageDescriptor(page2, docs, requestUrl),
|
|
7925
|
+
getFarmDocsCustomSocialImage(page2)
|
|
7926
|
+
) : "";
|
|
7429
7927
|
return `<!DOCTYPE html>
|
|
7430
7928
|
<html class="dark" lang="en" data-docs-theme="${escapeAttribute2(themeName)}">
|
|
7431
7929
|
<head>
|
|
@@ -7434,11 +7932,12 @@ function renderPixelDocsHtml(page2, pages, docs, themeCss, clientEntry, faviconH
|
|
|
7434
7932
|
<meta name="generator" content="@farming-labs/docs via Farm.js">
|
|
7435
7933
|
<title>${escapeHtml(page2.title)}</title>
|
|
7436
7934
|
${renderFarmDocsFaviconLink(faviconHref)}
|
|
7437
|
-
|
|
7438
|
-
|
|
7935
|
+
${renderFarmDocsFontPreloads(fontAssets)}
|
|
7936
|
+
${fontStylesheetHref ? `<link rel="stylesheet" href="${escapeAttribute2(fontStylesheetHref)}">` : ""}
|
|
7439
7937
|
${description ? `<meta name="description" content="${escapeHtml(description)}">` : ""}
|
|
7938
|
+
${socialMetadata}
|
|
7440
7939
|
<style>${themeCss}
|
|
7441
|
-
${renderFarmDocsBridgeCss(docs)}</style>
|
|
7940
|
+
${renderFarmDocsBridgeCss(docs, fontAssets, layoutFonts)}</style>
|
|
7442
7941
|
${searchEnabled ? renderDocsSearchBootstrapScript() : ""}
|
|
7443
7942
|
</head>
|
|
7444
7943
|
<body>
|
|
@@ -7490,9 +7989,34 @@ ${renderMarkdownHtmlWithTitleMeta(page2, docs)}
|
|
|
7490
7989
|
}
|
|
7491
7990
|
function createFarmDocsHandler(docs, options) {
|
|
7492
7991
|
const faviconHref = resolveFarmDocsFavicon(docs, options);
|
|
7992
|
+
const fontAssets = options.fontAssets ?? toFarmDocsPublicFontAssets(resolveFarmDocsFontAssets(options.root));
|
|
7993
|
+
const fallbackFontPreloadHeader = renderFarmDocsFontPreloadHeader(fontAssets);
|
|
7493
7994
|
return /* @__PURE__ */ __name(async function handleFarmDocsRequest(request) {
|
|
7494
7995
|
if (!docs?.enabled || request.method !== "GET" && request.method !== "HEAD") return null;
|
|
7495
7996
|
const contentDir = resolveFarmDocsContentDir(docs, options);
|
|
7997
|
+
const requestUrl = new URL(request.url);
|
|
7998
|
+
const socialImageSlug = getFarmDocsSocialImageSlug(docs, requestUrl);
|
|
7999
|
+
if (socialImageSlug !== null) {
|
|
8000
|
+
const socialImagePage = loadFarmDocsPage(contentDir, docs, socialImageSlug);
|
|
8001
|
+
if (!socialImagePage || !isFarmDocsSocialImageEnabled(socialImagePage, docs) || getFarmDocsCustomSocialImage(socialImagePage)) {
|
|
8002
|
+
return null;
|
|
8003
|
+
}
|
|
8004
|
+
const descriptor = createFarmDocsSocialImageDescriptor(socialImagePage, docs, requestUrl);
|
|
8005
|
+
if (requestUrl.pathname !== descriptor.imagePath) return null;
|
|
8006
|
+
const etag = `"${descriptor.hash}"`;
|
|
8007
|
+
const immutable = requestUrl.searchParams.get("v") === descriptor.hash;
|
|
8008
|
+
const headers = new Headers({
|
|
8009
|
+
"Content-Type": "image/svg+xml; charset=utf-8",
|
|
8010
|
+
"Cache-Control": immutable ? "public, max-age=31536000, immutable" : "public, max-age=0, must-revalidate",
|
|
8011
|
+
ETag: etag,
|
|
8012
|
+
"X-Content-Type-Options": "nosniff"
|
|
8013
|
+
});
|
|
8014
|
+
if (request.headers.get("if-none-match") === etag) {
|
|
8015
|
+
return new Response(null, { status: 304, headers });
|
|
8016
|
+
}
|
|
8017
|
+
if (request.method === "HEAD") return new Response(null, { status: 200, headers });
|
|
8018
|
+
return new Response(renderFarmDocsSocialImageSvg(descriptor), { status: 200, headers });
|
|
8019
|
+
}
|
|
7496
8020
|
const publicResponse = createFarmDocsPublicResponse(contentDir, docs, request);
|
|
7497
8021
|
if (publicResponse) return publicResponse;
|
|
7498
8022
|
if (!isFarmDocsRequest(docs, request)) return null;
|
|
@@ -7515,6 +8039,11 @@ function createFarmDocsHandler(docs, options) {
|
|
|
7515
8039
|
}
|
|
7516
8040
|
);
|
|
7517
8041
|
}
|
|
8042
|
+
const pathname = new URL(request.url).pathname;
|
|
8043
|
+
const layoutFonts = await options.resolveLayoutFonts?.(pathname);
|
|
8044
|
+
const usesLayoutFonts = Boolean(layoutFonts?.body || layoutFonts?.code);
|
|
8045
|
+
const activeFontAssets = usesLayoutFonts ? [] : fontAssets;
|
|
8046
|
+
const fontPreloadHeader = usesLayoutFonts ? renderFarmLayoutFontPreloadHeader(layoutFonts) : fallbackFontPreloadHeader;
|
|
7518
8047
|
return new Response(
|
|
7519
8048
|
renderPixelDocsHtml(
|
|
7520
8049
|
page2,
|
|
@@ -7522,39 +8051,44 @@ function createFarmDocsHandler(docs, options) {
|
|
|
7522
8051
|
docs,
|
|
7523
8052
|
resolvePixelBorderThemeCss(options),
|
|
7524
8053
|
options.clientEntry || "/farm-client.js",
|
|
7525
|
-
faviconHref
|
|
8054
|
+
faviconHref,
|
|
8055
|
+
requestUrl,
|
|
8056
|
+
activeFontAssets,
|
|
8057
|
+
layoutFonts,
|
|
8058
|
+
usesLayoutFonts ? options.fontStylesheetHref : void 0
|
|
7526
8059
|
),
|
|
7527
8060
|
{
|
|
7528
8061
|
status: 200,
|
|
7529
8062
|
headers: {
|
|
7530
8063
|
"Content-Type": "text/html; charset=utf-8",
|
|
7531
|
-
"Cache-Control": "public, s-maxage=60, stale-while-revalidate=300"
|
|
8064
|
+
"Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
|
|
8065
|
+
...fontPreloadHeader ? { Link: fontPreloadHeader } : {}
|
|
7532
8066
|
}
|
|
7533
8067
|
}
|
|
7534
8068
|
);
|
|
7535
8069
|
}, "handleFarmDocsRequest");
|
|
7536
8070
|
}
|
|
7537
|
-
var
|
|
8071
|
+
var import_node_fs9, import_node_module5, import_node_path13, import_docs, import_marked, import_sugar_high, DOCS_FILE_NAMES, DOCS_FILE_EXTENSIONS2, FARM_DOCS_FALLBACK_FAVICON, FARM_DOCS_FAVICON_FILES, CODE_LANGUAGE_LABELS, EXTENSIONLESS_CODE_FILENAMES, SIDEBAR_SECTION_ORDER, SIDEBAR_PAGE_ORDER, themeCssCache;
|
|
7538
8072
|
var init_handler = __esm({
|
|
7539
8073
|
"src/docs/handler.ts"() {
|
|
7540
8074
|
"use strict";
|
|
7541
|
-
|
|
8075
|
+
import_node_fs9 = require("fs");
|
|
7542
8076
|
import_node_module5 = require("module");
|
|
7543
|
-
|
|
8077
|
+
import_node_path13 = __toESM(require("path"));
|
|
7544
8078
|
import_docs = require("@farming-labs/docs");
|
|
7545
8079
|
import_marked = require("marked");
|
|
7546
8080
|
import_sugar_high = require("sugar-high");
|
|
8081
|
+
init_fonts();
|
|
7547
8082
|
init_last_modified();
|
|
7548
8083
|
init_pixel_border_css();
|
|
7549
8084
|
init_search_client();
|
|
8085
|
+
init_social_image();
|
|
7550
8086
|
DOCS_FILE_NAMES = ["page.mdx", "page.md", "index.mdx", "index.md"];
|
|
7551
8087
|
DOCS_FILE_EXTENSIONS2 = [".mdx", ".md"];
|
|
7552
8088
|
FARM_DOCS_FALLBACK_FAVICON = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='black'/%3E%3Cpath d='M7 8h18v3H10v5h12v3H10v5H7z' fill='white'/%3E%3C/svg%3E";
|
|
7553
8089
|
FARM_DOCS_FAVICON_FILES = ["favicon.svg", "favicon.ico", "favicon.png"];
|
|
7554
|
-
GEIST_SANS_FONT_URL = "/assets/Geist-Variable-CrgPqtmy.woff2";
|
|
7555
|
-
GEIST_MONO_FONT_URL = "/assets/GeistMono-Variable-BNLlm6Cd.woff2";
|
|
7556
8090
|
__name(trimSlashes2, "trimSlashes");
|
|
7557
|
-
__name(
|
|
8091
|
+
__name(normalizeEntry2, "normalizeEntry");
|
|
7558
8092
|
__name(normalizeSlug, "normalizeSlug");
|
|
7559
8093
|
__name(resolveFarmDocsFavicon, "resolveFarmDocsFavicon");
|
|
7560
8094
|
__name(renderFarmDocsFaviconLink, "renderFarmDocsFaviconLink");
|
|
@@ -7744,6 +8278,11 @@ var init_handler = __esm({
|
|
|
7744
8278
|
__name(readCssWithImports, "readCssWithImports");
|
|
7745
8279
|
__name(resolvePixelBorderThemeCss, "resolvePixelBorderThemeCss");
|
|
7746
8280
|
__name(renderFarmDocsBridgeCss, "renderFarmDocsBridgeCss");
|
|
8281
|
+
__name(renderFarmDocsLayoutFontVariable, "renderFarmDocsLayoutFontVariable");
|
|
8282
|
+
__name(renderFarmDocsFontPreloads, "renderFarmDocsFontPreloads");
|
|
8283
|
+
__name(renderFarmDocsFontPreloadHeader, "renderFarmDocsFontPreloadHeader");
|
|
8284
|
+
__name(getFarmLayoutFontPreloads, "getFarmLayoutFontPreloads");
|
|
8285
|
+
__name(renderFarmLayoutFontPreloadHeader, "renderFarmLayoutFontPreloadHeader");
|
|
7747
8286
|
__name(renderPixelDocsHtml, "renderPixelDocsHtml");
|
|
7748
8287
|
__name(createFarmDocsHandler, "createFarmDocsHandler");
|
|
7749
8288
|
}
|
|
@@ -7818,18 +8357,18 @@ function sanitizeDocsConfig(config) {
|
|
|
7818
8357
|
return cloneSerializable(config) || {};
|
|
7819
8358
|
}
|
|
7820
8359
|
async function findDocsConfigPath(rootDir, configPath) {
|
|
7821
|
-
const { existsSync:
|
|
8360
|
+
const { existsSync: existsSync16 } = await import("fs");
|
|
7822
8361
|
const root = import_path9.default.resolve(rootDir || process.cwd());
|
|
7823
8362
|
if (configPath) {
|
|
7824
8363
|
const resolvedPath = import_path9.default.isAbsolute(configPath) ? configPath : import_path9.default.join(root, configPath);
|
|
7825
|
-
if (!
|
|
8364
|
+
if (!existsSync16(resolvedPath)) {
|
|
7826
8365
|
throw new Error(`Could not find docs config at ${configPath}.`);
|
|
7827
8366
|
}
|
|
7828
8367
|
return import_path9.default.resolve(resolvedPath);
|
|
7829
8368
|
}
|
|
7830
8369
|
for (const filename of DOCS_CONFIG_FILENAMES) {
|
|
7831
8370
|
const resolvedPath = import_path9.default.join(root, filename);
|
|
7832
|
-
if (
|
|
8371
|
+
if (existsSync16(resolvedPath)) {
|
|
7833
8372
|
return resolvedPath;
|
|
7834
8373
|
}
|
|
7835
8374
|
}
|
|
@@ -7965,6 +8504,7 @@ var init_config2 = __esm({
|
|
|
7965
8504
|
init_image_config();
|
|
7966
8505
|
init_config();
|
|
7967
8506
|
init_auth_config();
|
|
8507
|
+
init_preload();
|
|
7968
8508
|
init_config_entry();
|
|
7969
8509
|
__name(getDeployTargetForPreset, "getDeployTargetForPreset");
|
|
7970
8510
|
DOCS_CONFIG_FILENAMES = [
|
|
@@ -8753,8 +9293,8 @@ var init_generator = __esm({
|
|
|
8753
9293
|
}
|
|
8754
9294
|
routeGroups.get(key).push(route);
|
|
8755
9295
|
}
|
|
8756
|
-
for (const [
|
|
8757
|
-
const openAPIPath = this.convertToOpenAPIPath(
|
|
9296
|
+
for (const [path26, routeList] of routeGroups) {
|
|
9297
|
+
const openAPIPath = this.convertToOpenAPIPath(path26);
|
|
8758
9298
|
spec.paths[openAPIPath] = {};
|
|
8759
9299
|
for (const route of routeList) {
|
|
8760
9300
|
for (const method of route.methods) {
|
|
@@ -8768,8 +9308,8 @@ var init_generator = __esm({
|
|
|
8768
9308
|
/**
|
|
8769
9309
|
* Convert Farm.js API path to OpenAPI path format
|
|
8770
9310
|
*/
|
|
8771
|
-
convertToOpenAPIPath(
|
|
8772
|
-
return
|
|
9311
|
+
convertToOpenAPIPath(path26) {
|
|
9312
|
+
return path26.replace(/^\/api/, "");
|
|
8773
9313
|
}
|
|
8774
9314
|
/**
|
|
8775
9315
|
* Extract request body schema from endpoint
|
|
@@ -8931,8 +9471,8 @@ var init_generator = __esm({
|
|
|
8931
9471
|
/**
|
|
8932
9472
|
* Generate operation summary
|
|
8933
9473
|
*/
|
|
8934
|
-
generateSummary(
|
|
8935
|
-
const cleanPath =
|
|
9474
|
+
generateSummary(path26, method) {
|
|
9475
|
+
const cleanPath = path26.replace(/^\/api\//, "");
|
|
8936
9476
|
const pathParts = cleanPath.split("/");
|
|
8937
9477
|
const lastPart = pathParts[pathParts.length - 1];
|
|
8938
9478
|
const action = method === "GET" ? "Get" : method === "POST" ? "Create" : method === "PUT" ? "Update" : method === "DELETE" ? "Delete" : method === "PATCH" ? "Update" : method;
|
|
@@ -8941,22 +9481,22 @@ var init_generator = __esm({
|
|
|
8941
9481
|
/**
|
|
8942
9482
|
* Generate operation description
|
|
8943
9483
|
*/
|
|
8944
|
-
generateDescription(
|
|
8945
|
-
const cleanPath =
|
|
9484
|
+
generateDescription(path26, method) {
|
|
9485
|
+
const cleanPath = path26.replace(/^\/api\//, "");
|
|
8946
9486
|
return `${method} ${cleanPath} endpoint`;
|
|
8947
9487
|
}
|
|
8948
9488
|
/**
|
|
8949
9489
|
* Generate operation ID
|
|
8950
9490
|
*/
|
|
8951
|
-
generateOperationId(
|
|
8952
|
-
const cleanPath =
|
|
9491
|
+
generateOperationId(path26, method) {
|
|
9492
|
+
const cleanPath = path26.replace(/^\/api\//, "").replace(/\//g, "_");
|
|
8953
9493
|
return `${method.toLowerCase()}_${cleanPath}`;
|
|
8954
9494
|
}
|
|
8955
9495
|
/**
|
|
8956
9496
|
* Generate tags for grouping operations
|
|
8957
9497
|
*/
|
|
8958
|
-
generateTags(
|
|
8959
|
-
const cleanPath =
|
|
9498
|
+
generateTags(path26) {
|
|
9499
|
+
const cleanPath = path26.replace(/^\/api\//, "");
|
|
8960
9500
|
const pathParts = cleanPath.split("/");
|
|
8961
9501
|
if (pathParts.length > 1) {
|
|
8962
9502
|
return [pathParts[0]];
|
|
@@ -8969,8 +9509,8 @@ var init_generator = __esm({
|
|
|
8969
9509
|
async generateSpecFile(routes, outputPath) {
|
|
8970
9510
|
const spec = await this.generateSpec(routes);
|
|
8971
9511
|
const fs8 = require("fs");
|
|
8972
|
-
const
|
|
8973
|
-
const dir =
|
|
9512
|
+
const path26 = require("path");
|
|
9513
|
+
const dir = path26.dirname(outputPath);
|
|
8974
9514
|
if (!fs8.existsSync(dir)) {
|
|
8975
9515
|
fs8.mkdirSync(dir, { recursive: true });
|
|
8976
9516
|
}
|
|
@@ -9390,7 +9930,7 @@ async function createFarmDevtoolsSnapshot(input) {
|
|
|
9390
9930
|
generatedAt: (input.now?.() || /* @__PURE__ */ new Date()).toISOString(),
|
|
9391
9931
|
health: resolveHealth(diagnostics),
|
|
9392
9932
|
project: {
|
|
9393
|
-
name:
|
|
9933
|
+
name: import_node_path14.default.basename(import_node_path14.default.resolve(input.root)),
|
|
9394
9934
|
root: input.root,
|
|
9395
9935
|
srcDir: input.srcDir,
|
|
9396
9936
|
basePath: config.basePath || "/",
|
|
@@ -9439,11 +9979,11 @@ async function createFarmDevtoolsSnapshot(input) {
|
|
|
9439
9979
|
diagnostics
|
|
9440
9980
|
};
|
|
9441
9981
|
}
|
|
9442
|
-
var
|
|
9982
|
+
var import_node_path14;
|
|
9443
9983
|
var init_devtools = __esm({
|
|
9444
9984
|
"src/devtools.ts"() {
|
|
9445
9985
|
"use strict";
|
|
9446
|
-
|
|
9986
|
+
import_node_path14 = __toESM(require("path"));
|
|
9447
9987
|
init_config2();
|
|
9448
9988
|
init_cron();
|
|
9449
9989
|
init_route_runtime();
|
|
@@ -11402,6 +11942,22 @@ var import_promises3 = require("fs/promises");
|
|
|
11402
11942
|
var OPTIONAL_CATCH_ALL_SEGMENT = /^\[\[\.\.\.([^\]]+)\]\]$/;
|
|
11403
11943
|
var REQUIRED_CATCH_ALL_SEGMENT = /^\[\.\.\.([^\]]+)\]$/;
|
|
11404
11944
|
var REQUIRED_DYNAMIC_SEGMENT = /^\[([^\]]+)\]$/;
|
|
11945
|
+
var REQUEST_API_LABELS = /* @__PURE__ */ new Map([
|
|
11946
|
+
["cookies", "request cookies"],
|
|
11947
|
+
["headers", "request headers"],
|
|
11948
|
+
["getCurrentRequest", "the current Request"],
|
|
11949
|
+
["useSearchParams", "URL search parameters"],
|
|
11950
|
+
["auth", "request authentication"],
|
|
11951
|
+
["getServerSession", "request authentication"],
|
|
11952
|
+
["getSession", "request authentication"],
|
|
11953
|
+
["currentUser", "request authentication"]
|
|
11954
|
+
]);
|
|
11955
|
+
var ROUTE_PROP_LABELS = /* @__PURE__ */ new Map([
|
|
11956
|
+
["searchParams", "URL search parameters"],
|
|
11957
|
+
["middleware", "middleware request data"],
|
|
11958
|
+
["middlewareData", "middleware request data"],
|
|
11959
|
+
["context", "request context"]
|
|
11960
|
+
]);
|
|
11405
11961
|
function resolveRouteRenderingConfig(mod, source) {
|
|
11406
11962
|
const directiveConfig = parseRouteRenderingDirective(source);
|
|
11407
11963
|
let ssg = directiveConfig?.ssg ?? false;
|
|
@@ -11454,6 +12010,221 @@ async function resolveRouteRenderingConfigFromFile(mod, filePath) {
|
|
|
11454
12010
|
return resolveRouteRenderingConfig(mod, source);
|
|
11455
12011
|
}
|
|
11456
12012
|
__name(resolveRouteRenderingConfigFromFile, "resolveRouteRenderingConfigFromFile");
|
|
12013
|
+
function analyzeStaticRouteCandidate(mod, source, options = {}) {
|
|
12014
|
+
const blockers = [];
|
|
12015
|
+
if (!source) {
|
|
12016
|
+
blockers.push("route source is unavailable");
|
|
12017
|
+
}
|
|
12018
|
+
if (options.isDynamic) {
|
|
12019
|
+
blockers.push("the route has dynamic path segments");
|
|
12020
|
+
}
|
|
12021
|
+
if (hasExplicitRenderingConfig(mod, source)) {
|
|
12022
|
+
blockers.push("the route already has explicit rendering config");
|
|
12023
|
+
}
|
|
12024
|
+
if (source) {
|
|
12025
|
+
blockers.push(...findRequestBoundSourceBlockers(source));
|
|
12026
|
+
}
|
|
12027
|
+
return {
|
|
12028
|
+
candidate: blockers.length === 0,
|
|
12029
|
+
blockers
|
|
12030
|
+
};
|
|
12031
|
+
}
|
|
12032
|
+
__name(analyzeStaticRouteCandidate, "analyzeStaticRouteCandidate");
|
|
12033
|
+
function findRequestBoundSourceBlockers(source) {
|
|
12034
|
+
const blockers = /* @__PURE__ */ new Set();
|
|
12035
|
+
const code = stripCommentsAndLiteralContents(source);
|
|
12036
|
+
const sourceWithoutComments = stripComments(source);
|
|
12037
|
+
for (const binding of readRequestApiImportBindings(sourceWithoutComments)) {
|
|
12038
|
+
if (new RegExp(`\\b${escapeRegExp2(binding.local)}\\s*(?:\\?\\.\\s*)?\\(`).test(code)) {
|
|
12039
|
+
blockers.add(`the route reads ${binding.label}`);
|
|
12040
|
+
}
|
|
12041
|
+
}
|
|
12042
|
+
for (const namespace of readNamespaceImportBindings(sourceWithoutComments)) {
|
|
12043
|
+
for (const [name, label] of REQUEST_API_LABELS) {
|
|
12044
|
+
if (new RegExp(
|
|
12045
|
+
`\\b${escapeRegExp2(namespace)}\\s*(?:\\?\\.\\s*|\\.\\s*)${name}\\s*(?:\\?\\.\\s*)?\\(`
|
|
12046
|
+
).test(code)) {
|
|
12047
|
+
blockers.add(`the route reads ${label}`);
|
|
12048
|
+
}
|
|
12049
|
+
}
|
|
12050
|
+
}
|
|
12051
|
+
const params = readDefaultRouteParameters(code);
|
|
12052
|
+
if (params) {
|
|
12053
|
+
for (const [name, label] of ROUTE_PROP_LABELS) {
|
|
12054
|
+
if (new RegExp(`\\b${name}\\b`).test(params)) {
|
|
12055
|
+
blockers.add(`the route reads ${label}`);
|
|
12056
|
+
}
|
|
12057
|
+
}
|
|
12058
|
+
const propsName = params.match(/^\s*([A-Za-z_$][\w$]*)\s*(?::|,|$)/)?.[1];
|
|
12059
|
+
if (propsName) {
|
|
12060
|
+
for (const [name, label] of ROUTE_PROP_LABELS) {
|
|
12061
|
+
if (new RegExp(`\\b${escapeRegExp2(propsName)}\\s*\\.\\s*${name}\\b`).test(code)) {
|
|
12062
|
+
blockers.add(`the route reads ${label}`);
|
|
12063
|
+
}
|
|
12064
|
+
if (new RegExp(`\\{[^}]*\\b${name}\\b[^}]*\\}\\s*=\\s*${escapeRegExp2(propsName)}\\b`).test(
|
|
12065
|
+
code
|
|
12066
|
+
)) {
|
|
12067
|
+
blockers.add(`the route reads ${label}`);
|
|
12068
|
+
}
|
|
12069
|
+
}
|
|
12070
|
+
}
|
|
12071
|
+
}
|
|
12072
|
+
return [...blockers];
|
|
12073
|
+
}
|
|
12074
|
+
__name(findRequestBoundSourceBlockers, "findRequestBoundSourceBlockers");
|
|
12075
|
+
function readRequestApiImportBindings(source) {
|
|
12076
|
+
const bindings = [];
|
|
12077
|
+
for (const clause of readStaticImportClauses(source)) {
|
|
12078
|
+
const namedGroup = clause.match(/\{([\s\S]*?)\}/)?.[1];
|
|
12079
|
+
for (const rawSpecifier of (namedGroup ?? "").split(",")) {
|
|
12080
|
+
const specifier = rawSpecifier.trim().replace(/^type\s+/, "");
|
|
12081
|
+
const imported = specifier.match(/^([A-Za-z_$][\w$]*)(?:\s+as\s+([A-Za-z_$][\w$]*))?$/);
|
|
12082
|
+
if (!imported?.[1]) continue;
|
|
12083
|
+
const label = REQUEST_API_LABELS.get(imported[1]);
|
|
12084
|
+
if (label) bindings.push({ local: imported[2] ?? imported[1], label });
|
|
12085
|
+
}
|
|
12086
|
+
const local = clause.match(/^\s*([A-Za-z_$][\w$]*)\s*(?:,|$)/)?.[1];
|
|
12087
|
+
if (local) {
|
|
12088
|
+
const label = REQUEST_API_LABELS.get(local);
|
|
12089
|
+
if (label) bindings.push({ local, label });
|
|
12090
|
+
}
|
|
12091
|
+
}
|
|
12092
|
+
return bindings;
|
|
12093
|
+
}
|
|
12094
|
+
__name(readRequestApiImportBindings, "readRequestApiImportBindings");
|
|
12095
|
+
function readNamespaceImportBindings(source) {
|
|
12096
|
+
return readStaticImportClauses(source).map((clause) => clause.match(/\*\s*as\s*([A-Za-z_$][\w$]*)/)?.[1]).filter((binding) => Boolean(binding));
|
|
12097
|
+
}
|
|
12098
|
+
__name(readNamespaceImportBindings, "readNamespaceImportBindings");
|
|
12099
|
+
function readStaticImportClauses(source) {
|
|
12100
|
+
return [...source.matchAll(/\bimport\s+(?!\()([\s\S]*?)\s+from\s*["'][^"']+["']/g)].map((match) => match[1]).filter((clause) => Boolean(clause));
|
|
12101
|
+
}
|
|
12102
|
+
__name(readStaticImportClauses, "readStaticImportClauses");
|
|
12103
|
+
function readDefaultRouteParameters(code) {
|
|
12104
|
+
const inlineParams = code.match(/\bexport\s+default\s+(?:async\s+)?function\b[^(]*\(([^)]*)\)/)?.[1] ?? code.match(/\bexport\s+default\s+(?:async\s+)?\(([^)]*)\)\s*=>/)?.[1];
|
|
12105
|
+
if (inlineParams !== void 0) return inlineParams;
|
|
12106
|
+
const binding = code.match(/\bexport\s+default\s+([A-Za-z_$][\w$]*)\s*;?/)?.[1] ?? code.match(/\bexport\s*\{\s*([A-Za-z_$][\w$]*)\s+as\s+default\s*\}/)?.[1];
|
|
12107
|
+
if (!binding) return void 0;
|
|
12108
|
+
const escapedBinding = escapeRegExp2(binding);
|
|
12109
|
+
return code.match(new RegExp(`\\bfunction\\s+${escapedBinding}\\s*\\(([^)]*)\\)`))?.[1] ?? code.match(
|
|
12110
|
+
new RegExp(
|
|
12111
|
+
`\\b(?:const|let|var)\\s+${escapedBinding}\\s*=\\s*(?:async\\s+)?\\(([^)]*)\\)\\s*=>`
|
|
12112
|
+
)
|
|
12113
|
+
)?.[1] ?? code.match(
|
|
12114
|
+
new RegExp(`\\b(?:const|let|var)\\s+${escapedBinding}\\s*=\\s*function\\s*\\(([^)]*)\\)`)
|
|
12115
|
+
)?.[1];
|
|
12116
|
+
}
|
|
12117
|
+
__name(readDefaultRouteParameters, "readDefaultRouteParameters");
|
|
12118
|
+
function stripCommentsAndLiteralContents(source) {
|
|
12119
|
+
return sanitizeSource(source, true);
|
|
12120
|
+
}
|
|
12121
|
+
__name(stripCommentsAndLiteralContents, "stripCommentsAndLiteralContents");
|
|
12122
|
+
function stripComments(source) {
|
|
12123
|
+
return sanitizeSource(source, false);
|
|
12124
|
+
}
|
|
12125
|
+
__name(stripComments, "stripComments");
|
|
12126
|
+
function sanitizeSource(source, maskLiterals) {
|
|
12127
|
+
const output = [...source];
|
|
12128
|
+
const mask = /* @__PURE__ */ __name((index) => {
|
|
12129
|
+
if (output[index] !== "\n" && output[index] !== "\r") output[index] = " ";
|
|
12130
|
+
}, "mask");
|
|
12131
|
+
const scanQuoted = /* @__PURE__ */ __name((start, quote) => {
|
|
12132
|
+
let index = start;
|
|
12133
|
+
if (maskLiterals) mask(index);
|
|
12134
|
+
index += 1;
|
|
12135
|
+
while (index < source.length) {
|
|
12136
|
+
if (source[index] === "\\") {
|
|
12137
|
+
if (maskLiterals) mask(index);
|
|
12138
|
+
if (index + 1 < source.length && maskLiterals) mask(index + 1);
|
|
12139
|
+
index += 2;
|
|
12140
|
+
continue;
|
|
12141
|
+
}
|
|
12142
|
+
const character = source[index];
|
|
12143
|
+
if (maskLiterals) mask(index);
|
|
12144
|
+
index += 1;
|
|
12145
|
+
if (character === quote) break;
|
|
12146
|
+
}
|
|
12147
|
+
return index;
|
|
12148
|
+
}, "scanQuoted");
|
|
12149
|
+
const scanCode = /* @__PURE__ */ __name((start, stopAtTemplateBrace) => {
|
|
12150
|
+
let index = start;
|
|
12151
|
+
let braceDepth = 0;
|
|
12152
|
+
while (index < source.length) {
|
|
12153
|
+
const character = source[index];
|
|
12154
|
+
const next = source[index + 1];
|
|
12155
|
+
if (character === "/" && next === "/") {
|
|
12156
|
+
while (index < source.length && source[index] !== "\n" && source[index] !== "\r") {
|
|
12157
|
+
mask(index++);
|
|
12158
|
+
}
|
|
12159
|
+
continue;
|
|
12160
|
+
}
|
|
12161
|
+
if (character === "/" && next === "*") {
|
|
12162
|
+
mask(index++);
|
|
12163
|
+
mask(index++);
|
|
12164
|
+
while (index < source.length) {
|
|
12165
|
+
const closesComment = source[index] === "*" && source[index + 1] === "/";
|
|
12166
|
+
mask(index++);
|
|
12167
|
+
if (closesComment) {
|
|
12168
|
+
mask(index++);
|
|
12169
|
+
break;
|
|
12170
|
+
}
|
|
12171
|
+
}
|
|
12172
|
+
continue;
|
|
12173
|
+
}
|
|
12174
|
+
if (character === "'" || character === '"') {
|
|
12175
|
+
index = scanQuoted(index, character);
|
|
12176
|
+
continue;
|
|
12177
|
+
}
|
|
12178
|
+
if (character === "`") {
|
|
12179
|
+
if (maskLiterals) mask(index);
|
|
12180
|
+
index += 1;
|
|
12181
|
+
while (index < source.length) {
|
|
12182
|
+
if (source[index] === "\\") {
|
|
12183
|
+
if (maskLiterals) mask(index);
|
|
12184
|
+
if (index + 1 < source.length && maskLiterals) mask(index + 1);
|
|
12185
|
+
index += 2;
|
|
12186
|
+
} else if (source[index] === "`") {
|
|
12187
|
+
if (maskLiterals) mask(index);
|
|
12188
|
+
index += 1;
|
|
12189
|
+
break;
|
|
12190
|
+
} else if (source[index] === "$" && source[index + 1] === "{") {
|
|
12191
|
+
if (maskLiterals) {
|
|
12192
|
+
mask(index);
|
|
12193
|
+
mask(index + 1);
|
|
12194
|
+
}
|
|
12195
|
+
index = scanCode(index + 2, true);
|
|
12196
|
+
} else {
|
|
12197
|
+
if (maskLiterals) mask(index);
|
|
12198
|
+
index += 1;
|
|
12199
|
+
}
|
|
12200
|
+
}
|
|
12201
|
+
continue;
|
|
12202
|
+
}
|
|
12203
|
+
if (character === "{") {
|
|
12204
|
+
braceDepth += 1;
|
|
12205
|
+
} else if (character === "}") {
|
|
12206
|
+
if (stopAtTemplateBrace && braceDepth === 0) {
|
|
12207
|
+
if (maskLiterals) mask(index);
|
|
12208
|
+
return index + 1;
|
|
12209
|
+
}
|
|
12210
|
+
braceDepth = Math.max(0, braceDepth - 1);
|
|
12211
|
+
}
|
|
12212
|
+
index += 1;
|
|
12213
|
+
}
|
|
12214
|
+
return index;
|
|
12215
|
+
}, "scanCode");
|
|
12216
|
+
scanCode(0, false);
|
|
12217
|
+
return output.join("");
|
|
12218
|
+
}
|
|
12219
|
+
__name(sanitizeSource, "sanitizeSource");
|
|
12220
|
+
function escapeRegExp2(value) {
|
|
12221
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
12222
|
+
}
|
|
12223
|
+
__name(escapeRegExp2, "escapeRegExp");
|
|
12224
|
+
function hasExplicitRenderingConfig(mod, source) {
|
|
12225
|
+
return typeof mod?.ssg === "boolean" || typeof mod?.ppr === "boolean" || typeof mod?.experimental_ppr === "boolean" || typeof mod?.revalidate !== "undefined" || typeof mod?.dynamic !== "undefined" || typeof parseRouteRenderingDirective(source) !== "undefined";
|
|
12226
|
+
}
|
|
12227
|
+
__name(hasExplicitRenderingConfig, "hasExplicitRenderingConfig");
|
|
11457
12228
|
function parseRouteRenderingDirective(source) {
|
|
11458
12229
|
if (!source) {
|
|
11459
12230
|
return void 0;
|
|
@@ -11585,9 +12356,10 @@ function skipHorizontalWhitespace(source, start) {
|
|
|
11585
12356
|
return index;
|
|
11586
12357
|
}
|
|
11587
12358
|
__name(skipHorizontalWhitespace, "skipHorizontalWhitespace");
|
|
11588
|
-
async function collectSSGPages(routes, loadModule2) {
|
|
12359
|
+
async function collectSSGPages(routes, loadModule2, options = {}) {
|
|
11589
12360
|
const ssgPages = [];
|
|
11590
12361
|
const ssrRoutes = [];
|
|
12362
|
+
const staticCandidateRoutes = [];
|
|
11591
12363
|
for (const route of routes) {
|
|
11592
12364
|
try {
|
|
11593
12365
|
const mod = await loadModule2(route.filePath);
|
|
@@ -11595,7 +12367,8 @@ async function collectSSGPages(routes, loadModule2) {
|
|
|
11595
12367
|
ssrRoutes.push(route.path);
|
|
11596
12368
|
continue;
|
|
11597
12369
|
}
|
|
11598
|
-
const
|
|
12370
|
+
const source = await (0, import_promises3.readFile)(route.filePath, "utf8").catch(() => void 0);
|
|
12371
|
+
const rendering = resolveRouteRenderingConfig(mod, source);
|
|
11599
12372
|
if (rendering.ssg) {
|
|
11600
12373
|
if (route.isDynamic) {
|
|
11601
12374
|
const getStaticPaths = mod.getStaticPaths || mod.generateStaticParams;
|
|
@@ -11622,12 +12395,26 @@ async function collectSSGPages(routes, loadModule2) {
|
|
|
11622
12395
|
}
|
|
11623
12396
|
} else {
|
|
11624
12397
|
ssrRoutes.push(route.path);
|
|
12398
|
+
if (options.suggestStaticRendering !== false && analyzeStaticRouteCandidate(mod, source, { isDynamic: route.isDynamic }).candidate) {
|
|
12399
|
+
staticCandidateRoutes.push(route.path);
|
|
12400
|
+
}
|
|
11625
12401
|
}
|
|
11626
12402
|
} catch (error) {
|
|
11627
12403
|
console.error(`Error processing route ${route.path}:`, error);
|
|
11628
12404
|
ssrRoutes.push(route.path);
|
|
11629
12405
|
}
|
|
11630
12406
|
}
|
|
12407
|
+
if (staticCandidateRoutes.length > 0) {
|
|
12408
|
+
const visibleRoutes = staticCandidateRoutes.slice(0, 10);
|
|
12409
|
+
const remainingCount = staticCandidateRoutes.length - visibleRoutes.length;
|
|
12410
|
+
const remainingSuffix = remainingCount > 0 ? `
|
|
12411
|
+
\u2026and ${remainingCount} more` : "";
|
|
12412
|
+
console.warn(
|
|
12413
|
+
`[Farm.js] ${staticCandidateRoutes.length} route${staticCandidateRoutes.length === 1 ? " appears" : "s appear"} eligible for static rendering:
|
|
12414
|
+
${visibleRoutes.join("\n ")}${remainingSuffix}
|
|
12415
|
+
Add \`export const dynamic = "force-static";\` after verifying that imported code does not read cookies, headers, authentication, or other request data.`
|
|
12416
|
+
);
|
|
12417
|
+
}
|
|
11631
12418
|
return { ssg: ssgPages, ssr: ssrRoutes };
|
|
11632
12419
|
}
|
|
11633
12420
|
__name(collectSSGPages, "collectSSGPages");
|
|
@@ -12390,25 +13177,25 @@ function defineRoutes(input) {
|
|
|
12390
13177
|
}
|
|
12391
13178
|
__name(defineRoutes, "defineRoutes");
|
|
12392
13179
|
var routesBuilder = {
|
|
12393
|
-
page(
|
|
13180
|
+
page(path26, options) {
|
|
12394
13181
|
return normalizeProgrammaticRoute({
|
|
12395
13182
|
kind: "page",
|
|
12396
|
-
path:
|
|
13183
|
+
path: path26,
|
|
12397
13184
|
...options
|
|
12398
13185
|
});
|
|
12399
13186
|
},
|
|
12400
|
-
layout(
|
|
13187
|
+
layout(path26, options) {
|
|
12401
13188
|
return normalizeProgrammaticRoute({
|
|
12402
13189
|
kind: "layout",
|
|
12403
|
-
path:
|
|
13190
|
+
path: path26,
|
|
12404
13191
|
...options
|
|
12405
13192
|
});
|
|
12406
13193
|
},
|
|
12407
|
-
api(
|
|
13194
|
+
api(path26, options) {
|
|
12408
13195
|
const { render, runtime, regions, maxDuration, ...methods } = options;
|
|
12409
13196
|
return normalizeProgrammaticRoute({
|
|
12410
13197
|
kind: "api",
|
|
12411
|
-
path:
|
|
13198
|
+
path: path26,
|
|
12412
13199
|
render,
|
|
12413
13200
|
runtime,
|
|
12414
13201
|
regions,
|
|
@@ -12444,7 +13231,7 @@ function getProgrammaticRouteSearchClientOptions(search) {
|
|
|
12444
13231
|
return Object.keys(options).length > 0 ? options : void 0;
|
|
12445
13232
|
}
|
|
12446
13233
|
__name(getProgrammaticRouteSearchClientOptions, "getProgrammaticRouteSearchClientOptions");
|
|
12447
|
-
function resolveProgrammaticRouteSearch(searchConfig, rawSearch,
|
|
13234
|
+
function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path26, routePath) {
|
|
12448
13235
|
const schema = getProgrammaticRouteSearchSchema(searchConfig);
|
|
12449
13236
|
const search = parseProgrammaticSchema(schema, rawSearch, "search", routePath);
|
|
12450
13237
|
const options = getProgrammaticRouteSearchOptions(searchConfig);
|
|
@@ -12453,7 +13240,7 @@ function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path24, routePa
|
|
|
12453
13240
|
schema,
|
|
12454
13241
|
rawSearch,
|
|
12455
13242
|
parsedSearch: search,
|
|
12456
|
-
path:
|
|
13243
|
+
path: path26
|
|
12457
13244
|
});
|
|
12458
13245
|
return { search, canonicalPath };
|
|
12459
13246
|
}
|
|
@@ -12636,7 +13423,7 @@ function createRouteModuleFromProgrammaticPage(route) {
|
|
|
12636
13423
|
mod.__farmRouteData = route.data;
|
|
12637
13424
|
mod.__farmRouteParsesProps = true;
|
|
12638
13425
|
mod.__farmResolveRouteProps = (props) => resolveProgrammaticRouteProps(route, props);
|
|
12639
|
-
mod.__farmResolveRouteCanonicalPath = (rawSearch,
|
|
13426
|
+
mod.__farmResolveRouteCanonicalPath = (rawSearch, path26) => resolveProgrammaticRouteSearch(route.search, rawSearch, path26, route.path).canonicalPath;
|
|
12640
13427
|
}
|
|
12641
13428
|
if (route.pending || route.error || route.notFound) {
|
|
12642
13429
|
mod.__farmRouteComponents = {
|
|
@@ -13112,6 +13899,15 @@ var import_path5 = __toESM(require("path"));
|
|
|
13112
13899
|
var import_fs2 = __toESM(require("fs"));
|
|
13113
13900
|
var import_path4 = __toESM(require("path"));
|
|
13114
13901
|
var import_url2 = require("url");
|
|
13902
|
+
|
|
13903
|
+
// src/island.ts
|
|
13904
|
+
var FARM_ISLAND_STRATEGIES = ["load", "interaction", "visible", "idle"];
|
|
13905
|
+
function isFarmIslandStrategy(value) {
|
|
13906
|
+
return FARM_ISLAND_STRATEGIES.includes(value);
|
|
13907
|
+
}
|
|
13908
|
+
__name(isFarmIslandStrategy, "isFarmIslandStrategy");
|
|
13909
|
+
|
|
13910
|
+
// src/utils/client-component.ts
|
|
13115
13911
|
function readIfExists(filePath) {
|
|
13116
13912
|
try {
|
|
13117
13913
|
if (!filePath || !import_fs2.default.existsSync(filePath)) {
|
|
@@ -13182,56 +13978,186 @@ function hasHydrateExport(content) {
|
|
|
13182
13978
|
return /\bexport\s+const\s+hydrate\s*=\s*true\b/.test(content) || /\bexport\s*\{\s*hydrate\s*\}\b/.test(content);
|
|
13183
13979
|
}
|
|
13184
13980
|
__name(hasHydrateExport, "hasHydrateExport");
|
|
13981
|
+
function tokenizeModuleSource(content) {
|
|
13982
|
+
const tokens = [];
|
|
13983
|
+
let index = 0;
|
|
13984
|
+
let line = 1;
|
|
13985
|
+
while (index < content.length) {
|
|
13986
|
+
const character = content[index];
|
|
13987
|
+
if (/\s/.test(character)) {
|
|
13988
|
+
if (character === "\n") line++;
|
|
13989
|
+
index++;
|
|
13990
|
+
continue;
|
|
13991
|
+
}
|
|
13992
|
+
if (character === "/" && content[index + 1] === "/") {
|
|
13993
|
+
index += 2;
|
|
13994
|
+
while (index < content.length && content[index] !== "\n") index++;
|
|
13995
|
+
continue;
|
|
13996
|
+
}
|
|
13997
|
+
if (character === "/" && content[index + 1] === "*") {
|
|
13998
|
+
index += 2;
|
|
13999
|
+
while (index < content.length) {
|
|
14000
|
+
if (content[index] === "\n") line++;
|
|
14001
|
+
if (content[index] === "*" && content[index + 1] === "/") {
|
|
14002
|
+
index += 2;
|
|
14003
|
+
break;
|
|
14004
|
+
}
|
|
14005
|
+
index++;
|
|
14006
|
+
}
|
|
14007
|
+
continue;
|
|
14008
|
+
}
|
|
14009
|
+
if (character === '"' || character === "'") {
|
|
14010
|
+
const quote = character;
|
|
14011
|
+
const tokenLine = line;
|
|
14012
|
+
let value = "";
|
|
14013
|
+
index++;
|
|
14014
|
+
while (index < content.length) {
|
|
14015
|
+
const next = content[index];
|
|
14016
|
+
if (next === "\\") {
|
|
14017
|
+
value += next;
|
|
14018
|
+
if (index + 1 < content.length) value += content[index + 1];
|
|
14019
|
+
index += 2;
|
|
14020
|
+
continue;
|
|
14021
|
+
}
|
|
14022
|
+
if (next === quote) {
|
|
14023
|
+
index++;
|
|
14024
|
+
break;
|
|
14025
|
+
}
|
|
14026
|
+
if (next === "\n") line++;
|
|
14027
|
+
value += next;
|
|
14028
|
+
index++;
|
|
14029
|
+
}
|
|
14030
|
+
tokens.push({ kind: "string", value, line: tokenLine });
|
|
14031
|
+
continue;
|
|
14032
|
+
}
|
|
14033
|
+
if (character === "`") {
|
|
14034
|
+
index++;
|
|
14035
|
+
while (index < content.length) {
|
|
14036
|
+
const next = content[index];
|
|
14037
|
+
if (next === "\\") {
|
|
14038
|
+
index += 2;
|
|
14039
|
+
continue;
|
|
14040
|
+
}
|
|
14041
|
+
if (next === "`") {
|
|
14042
|
+
index++;
|
|
14043
|
+
break;
|
|
14044
|
+
}
|
|
14045
|
+
if (next === "\n") line++;
|
|
14046
|
+
index++;
|
|
14047
|
+
}
|
|
14048
|
+
continue;
|
|
14049
|
+
}
|
|
14050
|
+
if (/[A-Za-z_$]/.test(character)) {
|
|
14051
|
+
const start = index++;
|
|
14052
|
+
while (index < content.length && /[\w$]/.test(content[index])) index++;
|
|
14053
|
+
tokens.push({ kind: "identifier", value: content.slice(start, index), line });
|
|
14054
|
+
continue;
|
|
14055
|
+
}
|
|
14056
|
+
tokens.push({ kind: "punctuation", value: character, line });
|
|
14057
|
+
index++;
|
|
14058
|
+
}
|
|
14059
|
+
return tokens;
|
|
14060
|
+
}
|
|
14061
|
+
__name(tokenizeModuleSource, "tokenizeModuleSource");
|
|
14062
|
+
function isIslandExportStart(tokens, index) {
|
|
14063
|
+
const token = tokens[index];
|
|
14064
|
+
const previous = tokens[index - 1];
|
|
14065
|
+
const startsStatement = !previous || previous.value === ";" || previous.value === "{" || previous.value === "}" || token.line > previous.line;
|
|
14066
|
+
return startsStatement && token.value === "export" && tokens[index + 1]?.value === "const" && tokens[index + 2]?.value === "island";
|
|
14067
|
+
}
|
|
14068
|
+
__name(isIslandExportStart, "isIslandExportStart");
|
|
14069
|
+
function getIslandStrategyExport(content) {
|
|
14070
|
+
if (!content) return null;
|
|
14071
|
+
const tokens = tokenizeModuleSource(content);
|
|
14072
|
+
for (let index = 0; index < tokens.length - 2; index++) {
|
|
14073
|
+
if (!isIslandExportStart(tokens, index)) continue;
|
|
14074
|
+
let valueIndex = index + 3;
|
|
14075
|
+
if (tokens[valueIndex]?.value === ":") {
|
|
14076
|
+
while (valueIndex < tokens.length && tokens[valueIndex].value !== "=") valueIndex++;
|
|
14077
|
+
}
|
|
14078
|
+
if (tokens[valueIndex]?.value !== "=") break;
|
|
14079
|
+
valueIndex++;
|
|
14080
|
+
const literal = tokens[valueIndex];
|
|
14081
|
+
if (!literal || literal.kind !== "string" || !isFarmIslandStrategy(literal.value)) break;
|
|
14082
|
+
let trailingIndex = valueIndex + 1;
|
|
14083
|
+
if (tokens[trailingIndex]?.value === "as" && tokens[trailingIndex + 1]?.value === "const") {
|
|
14084
|
+
trailingIndex += 2;
|
|
14085
|
+
}
|
|
14086
|
+
const trailing = tokens[trailingIndex];
|
|
14087
|
+
if (trailing && trailing.value !== ";" && trailing.line === literal.line) break;
|
|
14088
|
+
return literal.value;
|
|
14089
|
+
}
|
|
14090
|
+
if (tokens.some((_token, index) => isIslandExportStart(tokens, index))) {
|
|
14091
|
+
throw new Error(
|
|
14092
|
+
'Farm island configuration must be a static "load", "interaction", "visible", or "idle" string literal.'
|
|
14093
|
+
);
|
|
14094
|
+
}
|
|
14095
|
+
return null;
|
|
14096
|
+
}
|
|
14097
|
+
__name(getIslandStrategyExport, "getIslandStrategyExport");
|
|
13185
14098
|
function stripUseClientDirective(content) {
|
|
13186
14099
|
return content.replace(/^\s*(["'])use client\1\s*;?\s*/, "");
|
|
13187
14100
|
}
|
|
13188
14101
|
__name(stripUseClientDirective, "stripUseClientDirective");
|
|
13189
|
-
function parseClientModuleMetadata(content) {
|
|
14102
|
+
function parseClientModuleMetadata(content, inspectIslandExport) {
|
|
13190
14103
|
if (!content) {
|
|
13191
14104
|
return {
|
|
13192
14105
|
isClientComponent: false,
|
|
13193
|
-
hasHydrateExport: false
|
|
14106
|
+
hasHydrateExport: false,
|
|
14107
|
+
islandStrategy: null
|
|
13194
14108
|
};
|
|
13195
14109
|
}
|
|
14110
|
+
const isClientComponent = hasUseClientDirective(content);
|
|
14111
|
+
const hasHydrate = hasHydrateExport(content);
|
|
13196
14112
|
return {
|
|
13197
|
-
isClientComponent
|
|
13198
|
-
hasHydrateExport:
|
|
14113
|
+
isClientComponent,
|
|
14114
|
+
hasHydrateExport: hasHydrate,
|
|
14115
|
+
islandStrategy: inspectIslandExport || isClientComponent || hasHydrate ? getIslandStrategyExport(content) : null
|
|
13199
14116
|
};
|
|
13200
14117
|
}
|
|
13201
14118
|
__name(parseClientModuleMetadata, "parseClientModuleMetadata");
|
|
13202
14119
|
function getClientModuleMetadata(modulePath, root) {
|
|
13203
14120
|
const resolvedPath = resolveModuleSourcePath(modulePath, root);
|
|
13204
|
-
return inspectClientModuleMetadata(resolvedPath, root, /* @__PURE__ */ new Set());
|
|
14121
|
+
return inspectClientModuleMetadata(resolvedPath, root, /* @__PURE__ */ new Set(), true);
|
|
13205
14122
|
}
|
|
13206
14123
|
__name(getClientModuleMetadata, "getClientModuleMetadata");
|
|
13207
|
-
function inspectClientModuleMetadata(resolvedPath, root, visited) {
|
|
14124
|
+
function inspectClientModuleMetadata(resolvedPath, root, visited, inspectIslandExport) {
|
|
13208
14125
|
if (!resolvedPath || visited.has(resolvedPath)) {
|
|
13209
14126
|
return {
|
|
13210
14127
|
isClientComponent: false,
|
|
13211
|
-
shouldHydrate: false
|
|
14128
|
+
shouldHydrate: false,
|
|
14129
|
+
islandStrategy: null
|
|
13212
14130
|
};
|
|
13213
14131
|
}
|
|
13214
14132
|
visited.add(resolvedPath);
|
|
13215
14133
|
const content = readIfExists(resolvedPath);
|
|
13216
|
-
const parsed = parseClientModuleMetadata(content);
|
|
14134
|
+
const parsed = parseClientModuleMetadata(content, inspectIslandExport);
|
|
13217
14135
|
if (parsed.isClientComponent) {
|
|
13218
14136
|
return {
|
|
13219
14137
|
isClientComponent: true,
|
|
13220
|
-
shouldHydrate: true
|
|
14138
|
+
shouldHydrate: true,
|
|
14139
|
+
islandStrategy: parsed.islandStrategy ?? "load"
|
|
13221
14140
|
};
|
|
13222
14141
|
}
|
|
13223
14142
|
let importsClientBoundary = false;
|
|
14143
|
+
let importedIslandStrategy = null;
|
|
13224
14144
|
for (const specifier of getRelativeImportSpecifiers(content)) {
|
|
13225
14145
|
const importedPath = resolveImportedModuleSourcePath(resolvedPath, specifier, root);
|
|
13226
|
-
const importedMetadata = inspectClientModuleMetadata(importedPath, root, visited);
|
|
14146
|
+
const importedMetadata = inspectClientModuleMetadata(importedPath, root, visited, false);
|
|
13227
14147
|
if (importedMetadata.isClientComponent || importedMetadata.shouldHydrate) {
|
|
13228
14148
|
importsClientBoundary = true;
|
|
13229
|
-
|
|
14149
|
+
if (importedIslandStrategy === null) {
|
|
14150
|
+
importedIslandStrategy = importedMetadata.islandStrategy;
|
|
14151
|
+
} else if (importedIslandStrategy !== importedMetadata.islandStrategy) {
|
|
14152
|
+
importedIslandStrategy = "load";
|
|
14153
|
+
}
|
|
13230
14154
|
}
|
|
13231
14155
|
}
|
|
14156
|
+
const shouldHydrate = parsed.hasHydrateExport || importsClientBoundary;
|
|
13232
14157
|
return {
|
|
13233
14158
|
isClientComponent: false,
|
|
13234
|
-
shouldHydrate
|
|
14159
|
+
shouldHydrate,
|
|
14160
|
+
islandStrategy: shouldHydrate ? parsed.islandStrategy ?? importedIslandStrategy ?? "load" : null
|
|
13235
14161
|
};
|
|
13236
14162
|
}
|
|
13237
14163
|
__name(inspectClientModuleMetadata, "inspectClientModuleMetadata");
|
|
@@ -13487,6 +14413,10 @@ function parseInterceptionMarker(segment) {
|
|
|
13487
14413
|
__name(parseInterceptionMarker, "parseInterceptionMarker");
|
|
13488
14414
|
|
|
13489
14415
|
// src/routing/route-manager.ts
|
|
14416
|
+
function shouldSuggestStaticRenderingForI18n(i18n) {
|
|
14417
|
+
return !i18n || i18n.routing === "prefix-always" || i18n.routing === "prefix-except-default" && i18n.detection.every((signal) => signal === "url");
|
|
14418
|
+
}
|
|
14419
|
+
__name(shouldSuggestStaticRenderingForI18n, "shouldSuggestStaticRenderingForI18n");
|
|
13490
14420
|
function routeSpecificity(entry) {
|
|
13491
14421
|
return entry.route.segments.reduce((score, segment) => {
|
|
13492
14422
|
if (!segment.isDynamic) return score + 100;
|
|
@@ -13730,6 +14660,7 @@ var _RouteManager = class _RouteManager {
|
|
|
13730
14660
|
modulePath: toUrlPath(entry.modulePath),
|
|
13731
14661
|
shouldHydrate: metadata.shouldHydrate,
|
|
13732
14662
|
isClientComponent: metadata.isClientComponent,
|
|
14663
|
+
islandStrategy: metadata.islandStrategy,
|
|
13733
14664
|
search: getProgrammaticRouteSearchClientOptions(programmaticPage?.search),
|
|
13734
14665
|
segments: entry.route.segments.map((seg) => ({
|
|
13735
14666
|
segment: seg.segment,
|
|
@@ -14192,8 +15123,10 @@ var _RouteManager = class _RouteManager {
|
|
|
14192
15123
|
isDynamic: entry.route.segments.some((seg) => seg.isDynamic),
|
|
14193
15124
|
pattern: entry.pattern
|
|
14194
15125
|
}));
|
|
14195
|
-
const result = await collectSSGPages(routes, (filePath) => this.loadRouteModule(filePath));
|
|
14196
15126
|
const i18n = this.getI18nConfig();
|
|
15127
|
+
const result = await collectSSGPages(routes, (filePath) => this.loadRouteModule(filePath), {
|
|
15128
|
+
suggestStaticRendering: shouldSuggestStaticRenderingForI18n(i18n)
|
|
15129
|
+
});
|
|
14197
15130
|
if (!i18n) {
|
|
14198
15131
|
return result;
|
|
14199
15132
|
}
|
|
@@ -14324,8 +15257,8 @@ async function safeGlobFiles(pattern, cwd) {
|
|
|
14324
15257
|
__name(safeGlobFiles, "safeGlobFiles");
|
|
14325
15258
|
|
|
14326
15259
|
// src/server/renderer.ts
|
|
14327
|
-
var
|
|
14328
|
-
var
|
|
15260
|
+
var import_react5 = __toESM(require("react"));
|
|
15261
|
+
var import_server2 = require("react-dom/server");
|
|
14329
15262
|
var fs2 = __toESM(require("fs"));
|
|
14330
15263
|
var path9 = __toESM(require("path"));
|
|
14331
15264
|
var import_stream = require("stream");
|
|
@@ -15601,7 +16534,8 @@ __name(transformFarmFontCalls, "transformFarmFontCalls");
|
|
|
15601
16534
|
function renderFarmFontDevHead(root) {
|
|
15602
16535
|
const registry = registries.get(normalizeRoot(root));
|
|
15603
16536
|
if (!registry || registry.production || registry.size === 0) return "";
|
|
15604
|
-
return registry.renderPreloadTags(false)
|
|
16537
|
+
return `${registry.renderPreloadTags(false)}
|
|
16538
|
+
<link rel="stylesheet" href="/@farm/fonts.css">`;
|
|
15605
16539
|
}
|
|
15606
16540
|
__name(renderFarmFontDevHead, "renderFarmFontDevHead");
|
|
15607
16541
|
var _FarmFontRegistry = class _FarmFontRegistry {
|
|
@@ -15783,6 +16717,10 @@ ${FONT_SECTION_END}
|
|
|
15783
16717
|
fallback,
|
|
15784
16718
|
display,
|
|
15785
16719
|
preload: raw.preload !== false,
|
|
16720
|
+
preloadResources: raw.preload === false ? [] : normalizedSources.map(({ resource }) => ({
|
|
16721
|
+
href: resourceUrl(resource, production, this.basePath),
|
|
16722
|
+
type: fontContentType(resource.extension)
|
|
16723
|
+
})),
|
|
15786
16724
|
weight: defaultWeight,
|
|
15787
16725
|
style: raw.style === void 0 ? void 0 : defaultStyle,
|
|
15788
16726
|
sources: normalizedSources
|
|
@@ -15879,7 +16817,7 @@ ${FONT_SECTION_END}
|
|
|
15879
16817
|
const normalizedExtension = extension.toLowerCase();
|
|
15880
16818
|
const hash = (0, import_node_crypto2.createHash)("sha256").update(bytes).digest("hex").slice(0, 12);
|
|
15881
16819
|
const baseName = sanitizeFileName(import_node_path4.default.basename(fileName, extension)) || "font";
|
|
15882
|
-
const outputFileName = `assets/fonts/${baseName}
|
|
16820
|
+
const outputFileName = `assets/fonts/${baseName}-h${hash}${normalizedExtension}`;
|
|
15883
16821
|
const key = `${hash}${normalizedExtension}`;
|
|
15884
16822
|
const existing = this.resources.get(key);
|
|
15885
16823
|
if (existing) return existing;
|
|
@@ -16149,7 +17087,8 @@ function serializeFontResult(font) {
|
|
|
16149
17087
|
fontFamily: stack,
|
|
16150
17088
|
...font.style ? { fontStyle: font.style } : {},
|
|
16151
17089
|
...font.weight !== void 0 && !String(font.weight).includes(" ") ? { fontWeight: font.weight } : {}
|
|
16152
|
-
}
|
|
17090
|
+
},
|
|
17091
|
+
preloads: font.preloadResources
|
|
16153
17092
|
});
|
|
16154
17093
|
}
|
|
16155
17094
|
__name(serializeFontResult, "serializeFontResult");
|
|
@@ -16492,6 +17431,166 @@ function fontError(id, message) {
|
|
|
16492
17431
|
}
|
|
16493
17432
|
__name(fontError, "fontError");
|
|
16494
17433
|
|
|
17434
|
+
// src/metadata-image.ts
|
|
17435
|
+
var import_react4 = __toESM(require("react"));
|
|
17436
|
+
var import_server = require("react-dom/server");
|
|
17437
|
+
var REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref");
|
|
17438
|
+
var REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo");
|
|
17439
|
+
var REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy");
|
|
17440
|
+
function isResponse(value) {
|
|
17441
|
+
return typeof Response !== "undefined" && (value instanceof Response || Boolean(
|
|
17442
|
+
value && typeof value === "object" && typeof value.arrayBuffer === "function" && value.headers
|
|
17443
|
+
));
|
|
17444
|
+
}
|
|
17445
|
+
__name(isResponse, "isResponse");
|
|
17446
|
+
function isThenable(value) {
|
|
17447
|
+
return Boolean(
|
|
17448
|
+
value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function"
|
|
17449
|
+
);
|
|
17450
|
+
}
|
|
17451
|
+
__name(isThenable, "isThenable");
|
|
17452
|
+
async function prepareMetadataImageNode(node) {
|
|
17453
|
+
if (isThenable(node)) {
|
|
17454
|
+
return prepareMetadataImageNode(await node);
|
|
17455
|
+
}
|
|
17456
|
+
if (Array.isArray(node)) {
|
|
17457
|
+
return Promise.all(node.map((child) => prepareMetadataImageNode(child)));
|
|
17458
|
+
}
|
|
17459
|
+
if (!import_react4.default.isValidElement(node)) {
|
|
17460
|
+
return node;
|
|
17461
|
+
}
|
|
17462
|
+
const element = node;
|
|
17463
|
+
const type = element.type;
|
|
17464
|
+
const props = element.props || {};
|
|
17465
|
+
if (typeof type === "function") {
|
|
17466
|
+
if (type.prototype?.isReactComponent) {
|
|
17467
|
+
throw new Error(
|
|
17468
|
+
"Metadata image components must be stateless function components; React class components are not supported."
|
|
17469
|
+
);
|
|
17470
|
+
}
|
|
17471
|
+
return prepareMetadataImageNode(await type(props));
|
|
17472
|
+
}
|
|
17473
|
+
if (type && typeof type === "object") {
|
|
17474
|
+
if (type.$$typeof === REACT_MEMO_TYPE) {
|
|
17475
|
+
return prepareMetadataImageNode(import_react4.default.createElement(type.type, props));
|
|
17476
|
+
}
|
|
17477
|
+
if (type.$$typeof === REACT_FORWARD_REF_TYPE) {
|
|
17478
|
+
return prepareMetadataImageNode(await type.render(props, null));
|
|
17479
|
+
}
|
|
17480
|
+
if (type.$$typeof === REACT_LAZY_TYPE) {
|
|
17481
|
+
return prepareMetadataImageNode(import_react4.default.createElement(type._init(type._payload), props));
|
|
17482
|
+
}
|
|
17483
|
+
}
|
|
17484
|
+
const preparedChildren = await prepareMetadataImageNode(props.children);
|
|
17485
|
+
const preparedProps = { ...props };
|
|
17486
|
+
if (typeof preparedProps.className === "string") {
|
|
17487
|
+
preparedProps.tw = [preparedProps.tw, preparedProps.className].filter(Boolean).join(" ");
|
|
17488
|
+
delete preparedProps.className;
|
|
17489
|
+
}
|
|
17490
|
+
delete preparedProps.children;
|
|
17491
|
+
return import_react4.default.createElement(type, {
|
|
17492
|
+
...preparedProps,
|
|
17493
|
+
key: element.key,
|
|
17494
|
+
children: preparedChildren
|
|
17495
|
+
});
|
|
17496
|
+
}
|
|
17497
|
+
__name(prepareMetadataImageNode, "prepareMetadataImageNode");
|
|
17498
|
+
async function normalizeFonts(fonts) {
|
|
17499
|
+
if (!fonts?.length) return void 0;
|
|
17500
|
+
return Promise.all(
|
|
17501
|
+
fonts.map(async (font) => {
|
|
17502
|
+
const data = await font.data;
|
|
17503
|
+
const arrayBuffer = ArrayBuffer.isView(data) ? toArrayBuffer(data) : data;
|
|
17504
|
+
return { ...font, data: arrayBuffer };
|
|
17505
|
+
})
|
|
17506
|
+
);
|
|
17507
|
+
}
|
|
17508
|
+
__name(normalizeFonts, "normalizeFonts");
|
|
17509
|
+
function resolveCacheControl(revalidate) {
|
|
17510
|
+
if (revalidate === false) {
|
|
17511
|
+
return "public, max-age=31536000, immutable";
|
|
17512
|
+
}
|
|
17513
|
+
if (typeof revalidate === "number" && Number.isFinite(revalidate) && revalidate > 0) {
|
|
17514
|
+
return `public, s-maxage=${Math.floor(revalidate)}, stale-while-revalidate=300`;
|
|
17515
|
+
}
|
|
17516
|
+
return "public, max-age=0, must-revalidate";
|
|
17517
|
+
}
|
|
17518
|
+
__name(resolveCacheControl, "resolveCacheControl");
|
|
17519
|
+
function toArrayBuffer(value) {
|
|
17520
|
+
if (value instanceof ArrayBuffer) return value;
|
|
17521
|
+
const bytes = new Uint8Array(value.byteLength);
|
|
17522
|
+
bytes.set(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
|
|
17523
|
+
return bytes.buffer;
|
|
17524
|
+
}
|
|
17525
|
+
__name(toArrayBuffer, "toArrayBuffer");
|
|
17526
|
+
async function createEntityTag(body) {
|
|
17527
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", body);
|
|
17528
|
+
const hash = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, 32);
|
|
17529
|
+
return `"${hash}"`;
|
|
17530
|
+
}
|
|
17531
|
+
__name(createEntityTag, "createEntityTag");
|
|
17532
|
+
async function finalizeMetadataImageResponse(body, headers, options) {
|
|
17533
|
+
const responseHeaders = new Headers(headers);
|
|
17534
|
+
const etag = await createEntityTag(body);
|
|
17535
|
+
responseHeaders.set("ETag", etag);
|
|
17536
|
+
responseHeaders.set("Content-Length", String(body.byteLength));
|
|
17537
|
+
responseHeaders.set("X-Content-Type-Options", "nosniff");
|
|
17538
|
+
const matchesEntityTag = options.ifNoneMatch?.trim() === "*" || options.ifNoneMatch?.split(",").some((candidate) => candidate.trim().replace(/^W\//, "") === etag);
|
|
17539
|
+
if (matchesEntityTag) {
|
|
17540
|
+
return new Response(null, { status: 304, headers: responseHeaders });
|
|
17541
|
+
}
|
|
17542
|
+
return new Response(options.method?.toUpperCase() === "HEAD" ? null : body, {
|
|
17543
|
+
status: 200,
|
|
17544
|
+
headers: responseHeaders
|
|
17545
|
+
});
|
|
17546
|
+
}
|
|
17547
|
+
__name(finalizeMetadataImageResponse, "finalizeMetadataImageResponse");
|
|
17548
|
+
async function createFarmMetadataImageResponse(value, imageModule, options = {}) {
|
|
17549
|
+
const method = (options.method || "GET").toUpperCase();
|
|
17550
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
17551
|
+
return new Response(null, { status: 405, headers: { Allow: "GET, HEAD" } });
|
|
17552
|
+
}
|
|
17553
|
+
if (isResponse(value)) {
|
|
17554
|
+
return method === "HEAD" ? new Response(null, { status: value.status, headers: value.headers }) : value;
|
|
17555
|
+
}
|
|
17556
|
+
const cacheControl = resolveCacheControl(imageModule.revalidate);
|
|
17557
|
+
const explicitContentType = imageModule.contentType?.split(";", 1)[0]?.trim().toLowerCase();
|
|
17558
|
+
if (import_react4.default.isValidElement(value) && explicitContentType !== "image/svg+xml") {
|
|
17559
|
+
const { ImageResponse } = await import("@vercel/og");
|
|
17560
|
+
const element = await prepareMetadataImageNode(value);
|
|
17561
|
+
const response = new ImageResponse(element, {
|
|
17562
|
+
width: imageModule.size?.width || 1200,
|
|
17563
|
+
height: imageModule.size?.height || 630,
|
|
17564
|
+
fonts: await normalizeFonts(imageModule.fonts),
|
|
17565
|
+
emoji: imageModule.emoji,
|
|
17566
|
+
debug: imageModule.debug,
|
|
17567
|
+
headers: { "cache-control": cacheControl }
|
|
17568
|
+
});
|
|
17569
|
+
const headers = new Headers(response.headers);
|
|
17570
|
+
headers.set("Cache-Control", cacheControl);
|
|
17571
|
+
return finalizeMetadataImageResponse(await response.arrayBuffer(), headers, options);
|
|
17572
|
+
}
|
|
17573
|
+
let body;
|
|
17574
|
+
if (typeof value === "string") {
|
|
17575
|
+
body = toArrayBuffer(new TextEncoder().encode(value));
|
|
17576
|
+
} else if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {
|
|
17577
|
+
body = toArrayBuffer(value);
|
|
17578
|
+
} else if (import_react4.default.isValidElement(value)) {
|
|
17579
|
+
body = toArrayBuffer(new TextEncoder().encode((0, import_server.renderToStaticMarkup)(value)));
|
|
17580
|
+
} else {
|
|
17581
|
+
throw new Error("Metadata image must return a Response, string, bytes, or React element");
|
|
17582
|
+
}
|
|
17583
|
+
return finalizeMetadataImageResponse(
|
|
17584
|
+
body,
|
|
17585
|
+
{
|
|
17586
|
+
"Content-Type": imageModule.contentType || "image/svg+xml; charset=utf-8",
|
|
17587
|
+
"Cache-Control": cacheControl
|
|
17588
|
+
},
|
|
17589
|
+
options
|
|
17590
|
+
);
|
|
17591
|
+
}
|
|
17592
|
+
__name(createFarmMetadataImageResponse, "createFarmMetadataImageResponse");
|
|
17593
|
+
|
|
16495
17594
|
// src/server/renderer.ts
|
|
16496
17595
|
var cachedClerkProvider = null;
|
|
16497
17596
|
var importRuntimeModule = new Function("specifier", "return import(specifier);");
|
|
@@ -16565,7 +17664,7 @@ function createPPRRefreshScript() {
|
|
|
16565
17664
|
}
|
|
16566
17665
|
__name(createPPRRefreshScript, "createPPRRefreshScript");
|
|
16567
17666
|
function createPreHydrationClickQueueScript() {
|
|
16568
|
-
return `<script>(function(){if(window.__FARM_PREHYDRATION_CLICK_QUEUE__)return;var queue=[];window.__FARM_PREHYDRATION_CLICK_QUEUE__=queue;window.__FARM_HYDRATED__=false;document.documentElement.dataset.farmHydrated="false";function isModified(event){return !!(event.metaKey||event.altKey||event.ctrlKey||event.shiftKey)}function closestQueuedTarget(target){while(target&&target!==document.documentElement){if(target.matches&&target.matches('button,[role="button"],input[type="button"],input[type="submit"],input[type="reset"]'))return target;target=target.parentElement}return null}document.addEventListener("click",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented||event.button!==0||isModified(event))return;var target=closestQueuedTarget(event.target);if(!target||target.closest&&target.closest("a[href]"))return;if(queue.some(function(item){return item.target===target}))return;queue.push({target:target,createdAt:Date.now()});event.preventDefault();event.stopImmediatePropagation()},true);})();</script>`;
|
|
17667
|
+
return `<script>(function(){if(window.__FARM_PREHYDRATION_CLICK_QUEUE__)return;var queue=[];window.__FARM_PREHYDRATION_CLICK_QUEUE__=queue;window.__FARM_HYDRATED__=false;document.documentElement.dataset.farmHydrated="false";function isModified(event){return !!(event.metaKey||event.altKey||event.ctrlKey||event.shiftKey)}function closestQueuedTarget(target){while(target&&target!==document.documentElement){if(target.matches&&target.matches('button,[role="button"],input[type="button"],input[type="submit"],input[type="reset"]'))return target;target=target.parentElement}return null}document.addEventListener("click",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented||event.button!==0||isModified(event))return;var target=closestQueuedTarget(event.target);if(!target||target.closest&&target.closest("a[href]")||target.closest&&target.closest('[data-farm-island-hydrated="true"]'))return;if(queue.some(function(item){return item.target===target}))return;queue.push({target:target,createdAt:Date.now()});document.dispatchEvent(new CustomEvent("farm:island-interaction",{detail:{target:target}}));event.preventDefault();event.stopImmediatePropagation()},true);})();</script>`;
|
|
16569
17668
|
}
|
|
16570
17669
|
__name(createPreHydrationClickQueueScript, "createPreHydrationClickQueueScript");
|
|
16571
17670
|
function searchParamsToObject(searchParams) {
|
|
@@ -16616,7 +17715,7 @@ function isWebResponse(value) {
|
|
|
16616
17715
|
return typeof Response !== "undefined" && value instanceof Response && typeof value.arrayBuffer === "function";
|
|
16617
17716
|
}
|
|
16618
17717
|
__name(isWebResponse, "isWebResponse");
|
|
16619
|
-
var _FarmRouteErrorBoundary = class _FarmRouteErrorBoundary extends
|
|
17718
|
+
var _FarmRouteErrorBoundary = class _FarmRouteErrorBoundary extends import_react5.default.Component {
|
|
16620
17719
|
constructor(props) {
|
|
16621
17720
|
super(props);
|
|
16622
17721
|
this.state = { hasError: false, error: null };
|
|
@@ -16627,7 +17726,7 @@ var _FarmRouteErrorBoundary = class _FarmRouteErrorBoundary extends import_react
|
|
|
16627
17726
|
render() {
|
|
16628
17727
|
if (this.state.hasError) {
|
|
16629
17728
|
const Fallback = this.props.Fallback;
|
|
16630
|
-
return
|
|
17729
|
+
return import_react5.default.createElement(Fallback, {
|
|
16631
17730
|
...this.props.fallbackProps,
|
|
16632
17731
|
error: this.state.error,
|
|
16633
17732
|
reset: /* @__PURE__ */ __name(() => this.setState({ hasError: false, error: null }), "reset")
|
|
@@ -16843,14 +17942,14 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
16843
17942
|
searchParams: Promise.resolve({}),
|
|
16844
17943
|
path: page2.urlPath
|
|
16845
17944
|
};
|
|
16846
|
-
let pageElement =
|
|
17945
|
+
let pageElement = import_react5.default.createElement(
|
|
16847
17946
|
PageComponent,
|
|
16848
17947
|
pageProps
|
|
16849
17948
|
);
|
|
16850
17949
|
for (let i = layoutModules.length - 1; i >= 0; i--) {
|
|
16851
17950
|
const layoutModule = layoutModules[i];
|
|
16852
17951
|
const LayoutComponent = layoutModule.default;
|
|
16853
|
-
pageElement =
|
|
17952
|
+
pageElement = import_react5.default.createElement(
|
|
16854
17953
|
LayoutComponent,
|
|
16855
17954
|
{
|
|
16856
17955
|
children: pageElement,
|
|
@@ -17176,6 +18275,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17176
18275
|
req.__FARM_ROUTE__ = pathname;
|
|
17177
18276
|
req.__FARM_IS_CLIENT_COMPONENT__ = isClientComponent;
|
|
17178
18277
|
req.__FARM_SHOULD_HYDRATE__ = shouldHydrate;
|
|
18278
|
+
req.__FARM_ISLAND_STRATEGY__ = moduleMetadata.islandStrategy;
|
|
17179
18279
|
req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ = hasHydratableRouteSlots;
|
|
17180
18280
|
req.__FARM_LOADING_MODULE_PATH__ = loadingBoundaryEntry?.modulePath ? loadingBoundaryEntry.modulePath.substring(
|
|
17181
18281
|
loadingBoundaryEntry.modulePath.indexOf("/src/app/")
|
|
@@ -17228,12 +18328,12 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17228
18328
|
await _runWithMiddlewareData(middlewareDataForContext, async () => {
|
|
17229
18329
|
await _runWithMiddlewareContext(middlewareContext, async () => {
|
|
17230
18330
|
await _runWithCurrentRequest(currentRequest, async () => {
|
|
17231
|
-
let pageElement =
|
|
18331
|
+
let pageElement = import_react5.default.createElement(
|
|
17232
18332
|
PageComponent,
|
|
17233
18333
|
pageProps
|
|
17234
18334
|
);
|
|
17235
18335
|
if (LoadingFallbackComponent) {
|
|
17236
|
-
const loadingFallback =
|
|
18336
|
+
const loadingFallback = import_react5.default.createElement(LoadingFallbackComponent, {
|
|
17237
18337
|
...createRouteStateProps({
|
|
17238
18338
|
params,
|
|
17239
18339
|
searchParamsObject,
|
|
@@ -17242,16 +18342,21 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17242
18342
|
pluginExposedContext
|
|
17243
18343
|
})
|
|
17244
18344
|
});
|
|
17245
|
-
pageElement =
|
|
17246
|
-
|
|
18345
|
+
pageElement = import_react5.default.createElement(
|
|
18346
|
+
import_react5.default.Suspense,
|
|
17247
18347
|
{ fallback: loadingFallback },
|
|
17248
18348
|
pageElement
|
|
17249
18349
|
);
|
|
17250
18350
|
}
|
|
17251
18351
|
if (isClientComponent || shouldHydrate) {
|
|
17252
|
-
pageElement =
|
|
18352
|
+
pageElement = import_react5.default.createElement(
|
|
17253
18353
|
"div",
|
|
17254
|
-
{
|
|
18354
|
+
{
|
|
18355
|
+
id: "__farm_page__",
|
|
18356
|
+
"data-farm-client": "true",
|
|
18357
|
+
"data-farm-island": "page",
|
|
18358
|
+
"data-farm-island-strategy": moduleMetadata.islandStrategy ?? "load"
|
|
18359
|
+
},
|
|
17255
18360
|
pageElement
|
|
17256
18361
|
);
|
|
17257
18362
|
}
|
|
@@ -17263,11 +18368,11 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17263
18368
|
const slotProps = {};
|
|
17264
18369
|
for (const slot of renderedRouteSlots) {
|
|
17265
18370
|
if (slot.ownerPattern !== layoutEntry.pattern) continue;
|
|
17266
|
-
let slotElement =
|
|
18371
|
+
let slotElement = import_react5.default.createElement(
|
|
17267
18372
|
slot.module.default,
|
|
17268
18373
|
slot.props
|
|
17269
18374
|
);
|
|
17270
|
-
slotElement =
|
|
18375
|
+
slotElement = import_react5.default.createElement(
|
|
17271
18376
|
"div",
|
|
17272
18377
|
{
|
|
17273
18378
|
id: slot.containerId,
|
|
@@ -17278,7 +18383,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17278
18383
|
);
|
|
17279
18384
|
slotProps[slot.name] = slotElement;
|
|
17280
18385
|
}
|
|
17281
|
-
wrappedElement =
|
|
18386
|
+
wrappedElement = import_react5.default.createElement(
|
|
17282
18387
|
LayoutComponent,
|
|
17283
18388
|
{
|
|
17284
18389
|
children: wrappedElement,
|
|
@@ -17288,7 +18393,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17288
18393
|
);
|
|
17289
18394
|
}
|
|
17290
18395
|
if (ErrorFallbackComponent) {
|
|
17291
|
-
wrappedElement =
|
|
18396
|
+
wrappedElement = import_react5.default.createElement(
|
|
17292
18397
|
FarmRouteErrorBoundary,
|
|
17293
18398
|
{
|
|
17294
18399
|
Fallback: ErrorFallbackComponent,
|
|
@@ -17421,7 +18526,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17421
18526
|
if (!cachedClerkProvider) {
|
|
17422
18527
|
cachedClerkProvider = await importRuntimeModule("@clerk/react");
|
|
17423
18528
|
}
|
|
17424
|
-
wrapped =
|
|
18529
|
+
wrapped = import_react5.default.createElement(
|
|
17425
18530
|
cachedClerkProvider.ClerkProvider,
|
|
17426
18531
|
provider.props || {},
|
|
17427
18532
|
wrapped
|
|
@@ -17496,6 +18601,13 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17496
18601
|
return reference;
|
|
17497
18602
|
}
|
|
17498
18603
|
async renderMetadataImage(req, res, options) {
|
|
18604
|
+
const method = (req.method || "GET").toUpperCase();
|
|
18605
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
18606
|
+
res.statusCode = 405;
|
|
18607
|
+
res.setHeader("Allow", "GET, HEAD");
|
|
18608
|
+
res.end();
|
|
18609
|
+
return;
|
|
18610
|
+
}
|
|
17499
18611
|
if (options.image.sourceType === "static") {
|
|
17500
18612
|
if (!options.image.staticInfo) {
|
|
17501
18613
|
throw new Error(`Static metadata image ${options.image.modulePath} is missing file info`);
|
|
@@ -17521,42 +18633,12 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17521
18633
|
await this.writeMetadataImageResponse(req, res, handlerResult, imageModule);
|
|
17522
18634
|
}
|
|
17523
18635
|
async writeMetadataImageResponse(req, res, value, imageModule) {
|
|
17524
|
-
|
|
17525
|
-
|
|
17526
|
-
|
|
17527
|
-
|
|
17528
|
-
|
|
17529
|
-
|
|
17530
|
-
res.end();
|
|
17531
|
-
return;
|
|
17532
|
-
}
|
|
17533
|
-
const body2 = Buffer.from(await value.arrayBuffer());
|
|
17534
|
-
res.write(body2);
|
|
17535
|
-
res.end();
|
|
17536
|
-
return;
|
|
17537
|
-
}
|
|
17538
|
-
const contentType = imageModule.contentType || "image/svg+xml; charset=utf-8";
|
|
17539
|
-
let body;
|
|
17540
|
-
if (typeof value === "string") {
|
|
17541
|
-
body = value;
|
|
17542
|
-
} else if (value instanceof ArrayBuffer) {
|
|
17543
|
-
body = Buffer.from(value);
|
|
17544
|
-
} else if (ArrayBuffer.isView(value)) {
|
|
17545
|
-
body = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
17546
|
-
} else if (import_react4.default.isValidElement(value)) {
|
|
17547
|
-
body = (0, import_server.renderToStaticMarkup)(value);
|
|
17548
|
-
} else {
|
|
17549
|
-
throw new Error("Metadata image must return a Response, string, bytes, or React element");
|
|
17550
|
-
}
|
|
17551
|
-
res.statusCode = res.statusCode || 200;
|
|
17552
|
-
res.setHeader("Content-Type", contentType);
|
|
17553
|
-
res.setHeader("Cache-Control", "public, max-age=0, must-revalidate");
|
|
17554
|
-
if (req.method === "HEAD") {
|
|
17555
|
-
res.end();
|
|
17556
|
-
return;
|
|
17557
|
-
}
|
|
17558
|
-
res.write(body);
|
|
17559
|
-
res.end();
|
|
18636
|
+
const ifNoneMatch = req.headers["if-none-match"];
|
|
18637
|
+
const response = await createFarmMetadataImageResponse(value, imageModule, {
|
|
18638
|
+
method: req.method,
|
|
18639
|
+
ifNoneMatch: Array.isArray(ifNoneMatch) ? ifNoneMatch[0] : ifNoneMatch
|
|
18640
|
+
});
|
|
18641
|
+
await sendWebResponse(res, response);
|
|
17560
18642
|
}
|
|
17561
18643
|
async writeStaticMetadataImageResponse(req, res, image) {
|
|
17562
18644
|
const method = (req.method || "GET").toUpperCase();
|
|
@@ -17603,7 +18685,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17603
18685
|
return false;
|
|
17604
18686
|
}
|
|
17605
18687
|
const ErrorComponent = errorModule.default;
|
|
17606
|
-
const errorElement =
|
|
18688
|
+
const errorElement = import_react5.default.createElement(ErrorComponent, {
|
|
17607
18689
|
...createRouteStateProps({
|
|
17608
18690
|
params: options.params,
|
|
17609
18691
|
searchParamsObject: options.searchParamsObject,
|
|
@@ -17621,7 +18703,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17621
18703
|
);
|
|
17622
18704
|
for (let i = layoutModules.length - 1; i >= 0; i--) {
|
|
17623
18705
|
const LayoutComponent = layoutModules[i].default;
|
|
17624
|
-
wrapped =
|
|
18706
|
+
wrapped = import_react5.default.createElement(
|
|
17625
18707
|
LayoutComponent,
|
|
17626
18708
|
{
|
|
17627
18709
|
children: wrapped,
|
|
@@ -17686,6 +18768,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
17686
18768
|
search: routeEntry.search,
|
|
17687
18769
|
isClientComponent: routeEntry.isClientComponent,
|
|
17688
18770
|
shouldHydrate: routeEntry.shouldHydrate,
|
|
18771
|
+
islandStrategy: routeEntry.islandStrategy,
|
|
17689
18772
|
preloads: [routeEntry.modulePath],
|
|
17690
18773
|
assets: []
|
|
17691
18774
|
};
|
|
@@ -17722,6 +18805,7 @@ window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(deploymentId)};
|
|
|
17722
18805
|
window.__FARM_PATH__ = ${JSON.stringify(req.__FARM_ROUTE__ || req.url || "/")};
|
|
17723
18806
|
window.__FARM_IS_CLIENT__ = ${JSON.stringify(isClientComponent)};
|
|
17724
18807
|
window.__FARM_SHOULD_HYDRATE__ = ${JSON.stringify(req.__FARM_SHOULD_HYDRATE__ === true)};
|
|
18808
|
+
window.__FARM_ISLAND_STRATEGY__ = ${JSON.stringify(req.__FARM_ISLAND_STRATEGY__ || "load")};
|
|
17725
18809
|
window.__FARM_PAGE_MODULE__ = ${JSON.stringify(relativePath2)};
|
|
17726
18810
|
window.__FARM_LOADING_MODULE__ = ${JSON.stringify(
|
|
17727
18811
|
req.__FARM_LOADING_MODULE_PATH__ || null
|
|
@@ -17739,8 +18823,8 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
17739
18823
|
const i18nSnapshot = getFarmI18nClientSnapshot();
|
|
17740
18824
|
const i18nAlternateTags = i18nSnapshot ? renderI18nAlternateLinks(req.__FARM_ROUTE__ || req.url || "/", i18nSnapshot) : "";
|
|
17741
18825
|
const fontHead = renderFarmFontDevHead(this.config.root || process.cwd());
|
|
17742
|
-
const streamRoot =
|
|
17743
|
-
const { pipe, abort } = (0,
|
|
18826
|
+
const streamRoot = import_react5.default.createElement("div", { style: { display: "contents" } }, element);
|
|
18827
|
+
const { pipe, abort } = (0, import_server2.renderToPipeableStream)(streamRoot, {
|
|
17744
18828
|
onShellReady() {
|
|
17745
18829
|
const shellReadyMs = Date.now() - streamStartTime;
|
|
17746
18830
|
emitFarmEvent({
|
|
@@ -17898,12 +18982,12 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
17898
18982
|
break;
|
|
17899
18983
|
}
|
|
17900
18984
|
}
|
|
17901
|
-
let element =
|
|
18985
|
+
let element = import_react5.default.createElement(
|
|
17902
18986
|
NotFoundComponent,
|
|
17903
18987
|
{ pathname }
|
|
17904
18988
|
);
|
|
17905
18989
|
if (LayoutComponent) {
|
|
17906
|
-
element =
|
|
18990
|
+
element = import_react5.default.createElement(
|
|
17907
18991
|
LayoutComponent,
|
|
17908
18992
|
{ children: element }
|
|
17909
18993
|
);
|
|
@@ -18017,6 +19101,7 @@ var import_path6 = __toESM(require("path"));
|
|
|
18017
19101
|
init_devtools_config();
|
|
18018
19102
|
init_config();
|
|
18019
19103
|
init_auth_config();
|
|
19104
|
+
init_preload();
|
|
18020
19105
|
var defaultDocsConfig = {
|
|
18021
19106
|
enabled: false,
|
|
18022
19107
|
entry: "/docs",
|
|
@@ -18085,6 +19170,7 @@ var _FarmApp = class _FarmApp {
|
|
|
18085
19170
|
context: config.context || (() => void 0),
|
|
18086
19171
|
serverActions: resolveServerActionsConfig(config.serverActions),
|
|
18087
19172
|
images: resolveFarmImageConfig(config.images),
|
|
19173
|
+
performance: resolveFarmPerformanceConfig(config.performance),
|
|
18088
19174
|
i18n: isResolvedI18nConfig(config.i18n) ? config.i18n : resolveFarmI18nConfig(config.i18n, {
|
|
18089
19175
|
root,
|
|
18090
19176
|
mode: process.env.NODE_ENV === "production" ? "production" : "development"
|
|
@@ -20317,7 +21403,7 @@ init_response();
|
|
|
20317
21403
|
init_integrations();
|
|
20318
21404
|
init_devtools_config();
|
|
20319
21405
|
var fs7 = __toESM(require("fs"));
|
|
20320
|
-
var
|
|
21406
|
+
var path25 = __toESM(require("path"));
|
|
20321
21407
|
init_layers();
|
|
20322
21408
|
|
|
20323
21409
|
// src/after.ts
|
|
@@ -20494,8 +21580,25 @@ async function createBlurDataURL(bytes) {
|
|
|
20494
21580
|
}
|
|
20495
21581
|
__name(createBlurDataURL, "createBlurDataURL");
|
|
20496
21582
|
|
|
21583
|
+
// src/font.ts
|
|
21584
|
+
function resolveFarmLayoutFonts(layouts) {
|
|
21585
|
+
let resolved;
|
|
21586
|
+
for (const layout2 of layouts) {
|
|
21587
|
+
if (!layout2.fonts) continue;
|
|
21588
|
+
resolved = { ...resolved, ...layout2.fonts };
|
|
21589
|
+
}
|
|
21590
|
+
return resolved;
|
|
21591
|
+
}
|
|
21592
|
+
__name(resolveFarmLayoutFonts, "resolveFarmLayoutFonts");
|
|
21593
|
+
|
|
20497
21594
|
// src/vite.ts
|
|
20498
21595
|
init_image_server();
|
|
21596
|
+
|
|
21597
|
+
// src/server/vite-config.ts
|
|
21598
|
+
var import_node_path9 = __toESM(require("path"));
|
|
21599
|
+
|
|
21600
|
+
// src/vite.ts
|
|
21601
|
+
init_fonts();
|
|
20499
21602
|
var ALL_TYPE_ARTIFACTS = {
|
|
20500
21603
|
routes: true,
|
|
20501
21604
|
api: true,
|
|
@@ -20698,7 +21801,7 @@ function fileContainsProgrammaticPageRoute(file) {
|
|
|
20698
21801
|
__name(fileContainsProgrammaticPageRoute, "fileContainsProgrammaticPageRoute");
|
|
20699
21802
|
function rewriteEarlySsrRelativeImports(options) {
|
|
20700
21803
|
const cleanId = options.id.split("?", 1)[0];
|
|
20701
|
-
if (!
|
|
21804
|
+
if (!path25.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
|
|
20702
21805
|
return null;
|
|
20703
21806
|
}
|
|
20704
21807
|
const replacements = [];
|
|
@@ -20718,7 +21821,7 @@ function rewriteEarlySsrRelativeImports(options) {
|
|
|
20718
21821
|
const suffixIndex = source.value.search(/[?#]/);
|
|
20719
21822
|
const sourcePath = suffixIndex === -1 ? source.value : source.value.slice(0, suffixIndex);
|
|
20720
21823
|
const suffix = suffixIndex === -1 ? "" : source.value.slice(suffixIndex);
|
|
20721
|
-
const resolvedPath =
|
|
21824
|
+
const resolvedPath = path25.resolve(path25.dirname(cleanId), sourcePath);
|
|
20722
21825
|
replacements.push({
|
|
20723
21826
|
start: source.start,
|
|
20724
21827
|
end: source.end,
|
|
@@ -20803,7 +21906,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
20803
21906
|
...layerRoots.length ? {
|
|
20804
21907
|
server: {
|
|
20805
21908
|
fs: {
|
|
20806
|
-
allow: [
|
|
21909
|
+
allow: [path25.resolve(options.root || process.cwd()), ...layerRoots]
|
|
20807
21910
|
}
|
|
20808
21911
|
}
|
|
20809
21912
|
} : {}
|
|
@@ -20834,9 +21937,9 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
20834
21937
|
},
|
|
20835
21938
|
server
|
|
20836
21939
|
);
|
|
20837
|
-
const globalsCSSPath =
|
|
21940
|
+
const globalsCSSPath = path25.join(server.config.root, "src/app/globals.css");
|
|
20838
21941
|
if (!fs7.existsSync(globalsCSSPath)) {
|
|
20839
|
-
const appDir =
|
|
21942
|
+
const appDir = path25.join(server.config.root, "src/app");
|
|
20840
21943
|
if (!fs7.existsSync(appDir)) {
|
|
20841
21944
|
fs7.mkdirSync(appDir, { recursive: true });
|
|
20842
21945
|
}
|
|
@@ -20858,10 +21961,10 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
20858
21961
|
});
|
|
20859
21962
|
}
|
|
20860
21963
|
const sourceRoots = getFarmSourceRoots(farmConfig);
|
|
20861
|
-
server.watcher.add(sourceRoots.map((source) =>
|
|
21964
|
+
server.watcher.add(sourceRoots.map((source) => path25.join(source.root, source.srcDir)));
|
|
20862
21965
|
if (farmConfig.i18n.enabled) {
|
|
20863
21966
|
server.watcher.add(
|
|
20864
|
-
farmConfig.i18n.messages.includes("{locale}") ?
|
|
21967
|
+
farmConfig.i18n.messages.includes("{locale}") ? path25.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
|
|
20865
21968
|
);
|
|
20866
21969
|
}
|
|
20867
21970
|
const workflowConfig = farmConfig.workflows;
|
|
@@ -20871,7 +21974,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
20871
21974
|
...farmDocsDevRuntime?.getFarmDocsRouteTypeEntries(farmConfig.docs) ?? []
|
|
20872
21975
|
], "getExtraRouteTypes");
|
|
20873
21976
|
const appDirSlugs = sourceRoots.map(
|
|
20874
|
-
(source) =>
|
|
21977
|
+
(source) => path25.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
|
|
20875
21978
|
);
|
|
20876
21979
|
const generateTypeArtifacts = /* @__PURE__ */ __name(async (reason, selection = ALL_TYPE_ARTIFACTS, log = false) => {
|
|
20877
21980
|
try {
|
|
@@ -20911,7 +22014,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
20911
22014
|
}, "generateTypeArtifacts");
|
|
20912
22015
|
await generateTypeArtifacts("startup");
|
|
20913
22016
|
const srcDirSlugs = sourceRoots.map(
|
|
20914
|
-
(source) =>
|
|
22017
|
+
(source) => path25.join(source.root, source.srcDir).replace(/\\/g, "/")
|
|
20915
22018
|
);
|
|
20916
22019
|
const layerConfigFiles = new Set(
|
|
20917
22020
|
farmConfig.layers.map((layer) => layer.configFile?.replace(/\\/g, "/")).filter((file) => Boolean(file))
|
|
@@ -21029,7 +22132,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21029
22132
|
await apiRouteManager.discoverRoutes();
|
|
21030
22133
|
let discoveredWorkflows = [];
|
|
21031
22134
|
const hasWorkflowDirectory = workflowConfig.enabled && workflowConfig.dirs.some(
|
|
21032
|
-
(dir) => fs7.existsSync(
|
|
22135
|
+
(dir) => fs7.existsSync(path25.isAbsolute(dir) ? dir : path25.join(farmConfig.root, dir))
|
|
21033
22136
|
);
|
|
21034
22137
|
if (hasWorkflowDirectory) {
|
|
21035
22138
|
const { createFarmWorkflowRequestHandler: createFarmWorkflowRequestHandler2, discoverFarmWorkflows: discoverFarmWorkflows2 } = await loadFarmWorkflowsDevRuntime();
|
|
@@ -21093,10 +22196,20 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21093
22196
|
logger.info(`Refreshed routes: ${reason}`);
|
|
21094
22197
|
}
|
|
21095
22198
|
}, "refreshRouteDiscovery");
|
|
22199
|
+
const farmDocsFontAssetList = farmDocsDevRuntime ? resolveFarmDocsFontAssets(farmConfig.root) : [];
|
|
21096
22200
|
const farmDocsHandler = farmDocsDevRuntime ? farmDocsDevRuntime.createFarmDocsHandler(farmConfig.docs, {
|
|
21097
22201
|
root: farmConfig.root,
|
|
21098
22202
|
srcDir: farmConfig.srcDir,
|
|
21099
|
-
clientEntry: "/@farm/client.js"
|
|
22203
|
+
clientEntry: "/@farm/client.js",
|
|
22204
|
+
fontAssets: toFarmDocsPublicFontAssets(farmDocsFontAssetList),
|
|
22205
|
+
resolveLayoutFonts: /* @__PURE__ */ __name(async (pathname) => {
|
|
22206
|
+
const layouts = routeManager.matchRoute(pathname).layouts;
|
|
22207
|
+
const layoutModules = await Promise.all(
|
|
22208
|
+
layouts.map((layout2) => routeManager.loadLayoutModule(layout2.modulePath))
|
|
22209
|
+
);
|
|
22210
|
+
return resolveFarmLayoutFonts(layoutModules);
|
|
22211
|
+
}, "resolveLayoutFonts"),
|
|
22212
|
+
fontStylesheetHref: "/@farm/fonts.css"
|
|
21100
22213
|
}) : null;
|
|
21101
22214
|
const farmDocsAPIHandler = farmDocsDevRuntime ? farmDocsDevRuntime.createFarmDocsAPIHandler({
|
|
21102
22215
|
rootDir: farmConfig.root,
|
|
@@ -21104,22 +22217,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21104
22217
|
docs: farmConfig.docs
|
|
21105
22218
|
}) : null;
|
|
21106
22219
|
const farmDocsFontAssets = new Map(
|
|
21107
|
-
|
|
21108
|
-
[
|
|
21109
|
-
"/assets/Geist-Variable-CrgPqtmy.woff2",
|
|
21110
|
-
path23.join(
|
|
21111
|
-
farmConfig.root,
|
|
21112
|
-
"node_modules/geist/dist/fonts/geist-sans/Geist-Variable.woff2"
|
|
21113
|
-
)
|
|
21114
|
-
],
|
|
21115
|
-
[
|
|
21116
|
-
"/assets/GeistMono-Variable-BNLlm6Cd.woff2",
|
|
21117
|
-
path23.join(
|
|
21118
|
-
farmConfig.root,
|
|
21119
|
-
"node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2"
|
|
21120
|
-
)
|
|
21121
|
-
]
|
|
21122
|
-
] : []
|
|
22220
|
+
farmDocsFontAssetList.map(({ url, sourcePath }) => [url, sourcePath])
|
|
21123
22221
|
);
|
|
21124
22222
|
const logRequest = /* @__PURE__ */ __name((method, urlPath, tag) => {
|
|
21125
22223
|
try {
|
|
@@ -21183,11 +22281,12 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21183
22281
|
}
|
|
21184
22282
|
}
|
|
21185
22283
|
const farmDocsFontPath = farmDocsFontAssets.get(requestPathname);
|
|
21186
|
-
if (farmDocsFontPath && fs7.existsSync(farmDocsFontPath)) {
|
|
22284
|
+
if ((requestMethod === "GET" || requestMethod === "HEAD") && farmDocsFontPath && fs7.existsSync(farmDocsFontPath)) {
|
|
21187
22285
|
res.statusCode = 200;
|
|
21188
22286
|
res.setHeader("Content-Type", "font/woff2");
|
|
21189
22287
|
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
21190
|
-
|
|
22288
|
+
if (requestMethod === "HEAD") res.end();
|
|
22289
|
+
else fs7.createReadStream(farmDocsFontPath).pipe(res);
|
|
21191
22290
|
return;
|
|
21192
22291
|
}
|
|
21193
22292
|
if (requestMethod === "GET" && (requestPathname === FARM_DEVTOOLS_PATH || requestPathname === `${FARM_DEVTOOLS_PATH}.json`)) {
|
|
@@ -21793,6 +22892,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
21793
22892
|
modulePath: toUrlPath(route.modulePath),
|
|
21794
22893
|
isClientComponent: routeSlots.length > 0 ? false : isClientComponent,
|
|
21795
22894
|
shouldHydrate: shouldHydrate || routeSlots.some((slot) => slot.isClientComponent || slot.shouldHydrate),
|
|
22895
|
+
islandStrategy: moduleMetadata.islandStrategy,
|
|
21796
22896
|
metadata: {
|
|
21797
22897
|
title: mergedMetadata.title,
|
|
21798
22898
|
description: mergedMetadata.description
|
|
@@ -22177,6 +23277,7 @@ export const getManifest = () => ({
|
|
|
22177
23277
|
search: route.search,
|
|
22178
23278
|
isClientComponent: moduleMetadata.isClientComponent,
|
|
22179
23279
|
shouldHydrate: moduleMetadata.shouldHydrate,
|
|
23280
|
+
islandStrategy: moduleMetadata.islandStrategy,
|
|
22180
23281
|
preloads: [route.modulePath],
|
|
22181
23282
|
// In dev, preload is just the module
|
|
22182
23283
|
assets: []
|
|
@@ -22303,8 +23404,8 @@ if (import.meta.hot) {
|
|
|
22303
23404
|
}
|
|
22304
23405
|
logger.info(`Found ${ssgPages.length} SSG pages, ${ssrRoutes.length} SSR routes`);
|
|
22305
23406
|
logger.info("Pre-rendering SSG pages...");
|
|
22306
|
-
const outDir =
|
|
22307
|
-
const clientDir =
|
|
23407
|
+
const outDir = path25.join(server?.config.root || process.cwd(), options.outDir || "dist");
|
|
23408
|
+
const clientDir = path25.join(outDir, "client");
|
|
22308
23409
|
for (const page2 of ssgPages) {
|
|
22309
23410
|
try {
|
|
22310
23411
|
const staticRequest = new Request(new URL(page2.urlPath, "http://farm.static"));
|
|
@@ -22315,7 +23416,7 @@ if (import.meta.hot) {
|
|
|
22315
23416
|
const layoutModules = await Promise.all(
|
|
22316
23417
|
layouts.map((l) => routeManager.loadLayoutModule(l.modulePath))
|
|
22317
23418
|
);
|
|
22318
|
-
const
|
|
23419
|
+
const React4 = await import("react");
|
|
22319
23420
|
const { renderToString } = await import("react-dom/server");
|
|
22320
23421
|
const PageComponent = mod.default;
|
|
22321
23422
|
const pageProps = {
|
|
@@ -22323,14 +23424,14 @@ if (import.meta.hot) {
|
|
|
22323
23424
|
searchParams: Promise.resolve({}),
|
|
22324
23425
|
path: page2.urlPath
|
|
22325
23426
|
};
|
|
22326
|
-
let pageElement =
|
|
23427
|
+
let pageElement = React4.createElement(
|
|
22327
23428
|
PageComponent,
|
|
22328
23429
|
pageProps
|
|
22329
23430
|
);
|
|
22330
23431
|
for (let i = layoutModules.length - 1; i >= 0; i--) {
|
|
22331
23432
|
const layoutModule = layoutModules[i];
|
|
22332
23433
|
const LayoutComponent = layoutModule.default;
|
|
22333
|
-
pageElement =
|
|
23434
|
+
pageElement = React4.createElement(
|
|
22334
23435
|
LayoutComponent,
|
|
22335
23436
|
{
|
|
22336
23437
|
children: pageElement,
|
|
@@ -22356,8 +23457,8 @@ if (import.meta.hot) {
|
|
|
22356
23457
|
<script type="module" src="/assets/client.js"></script>
|
|
22357
23458
|
</body>
|
|
22358
23459
|
</html>`;
|
|
22359
|
-
const outputPath = page2.urlPath === "/" ?
|
|
22360
|
-
fs7.mkdirSync(
|
|
23460
|
+
const outputPath = page2.urlPath === "/" ? path25.join(clientDir, "index.html") : path25.join(clientDir, page2.urlPath + ".html");
|
|
23461
|
+
fs7.mkdirSync(path25.dirname(outputPath), { recursive: true });
|
|
22361
23462
|
fs7.writeFileSync(outputPath, fullHtml);
|
|
22362
23463
|
const revalidateInfo = page2.revalidate ? ` (revalidate: ${page2.revalidate}s)` : "";
|
|
22363
23464
|
logger.success(` \u2713 ${page2.urlPath}${revalidateInfo}`);
|
|
@@ -22366,7 +23467,7 @@ if (import.meta.hot) {
|
|
|
22366
23467
|
logger.error(` \u2717 ${page2.urlPath}: ${error}`);
|
|
22367
23468
|
}
|
|
22368
23469
|
}
|
|
22369
|
-
const manifestPath =
|
|
23470
|
+
const manifestPath = path25.join(outDir, "__ssg_manifest.json");
|
|
22370
23471
|
fs7.writeFileSync(
|
|
22371
23472
|
manifestPath,
|
|
22372
23473
|
JSON.stringify(
|
|
@@ -22402,9 +23503,9 @@ if (import.meta.hot) {
|
|
|
22402
23503
|
}
|
|
22403
23504
|
const currentFarmConfig = farmApp?.getConfig();
|
|
22404
23505
|
const normalizedFile = file.replace(/\\/g, "/");
|
|
22405
|
-
const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) =>
|
|
23506
|
+
const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path25.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
|
|
22406
23507
|
if (currentSrcRoot && normalizedFile.startsWith(`${currentSrcRoot}/`) && isProgrammaticRoutesFileName(normalizedFile)) {
|
|
22407
|
-
logUpdate("PAGE", `updated ${
|
|
23508
|
+
logUpdate("PAGE", `updated ${path25.basename(file)}`);
|
|
22408
23509
|
for (const mod of modules) {
|
|
22409
23510
|
server2.moduleGraph.invalidateModule(mod);
|
|
22410
23511
|
}
|
|
@@ -22801,6 +23902,7 @@ import React from 'react'
|
|
|
22801
23902
|
import { hydrateRoot, createRoot } from 'react-dom/client'
|
|
22802
23903
|
import { installChunkErrorRecovery, SPARouter } from '@farm.js/core/client'
|
|
22803
23904
|
import { createClientPluginManager } from '@farm.js/core/plugin/client'
|
|
23905
|
+
import { scheduleFarmIslandHydration } from '@farm.js/core/internal/client-runtime'
|
|
22804
23906
|
import { reviveDeferredData } from '@farm.js/core/deferred'
|
|
22805
23907
|
import {
|
|
22806
23908
|
createFarmDeploymentMismatchError,
|
|
@@ -23053,6 +24155,7 @@ class LegacyManifestSPARouter {
|
|
|
23053
24155
|
|
|
23054
24156
|
// Only prefetch routes that will hydrate on the client.
|
|
23055
24157
|
if (!match.route.isClientComponent && !match.route.shouldHydrate) return;
|
|
24158
|
+
if (match.route.islandStrategy && match.route.islandStrategy !== 'load') return;
|
|
23056
24159
|
|
|
23057
24160
|
const modulePath = match.route.modulePath;
|
|
23058
24161
|
if (this.moduleCache.has(modulePath)) return;
|
|
@@ -23197,6 +24300,12 @@ let hasClientTakenOver = false;
|
|
|
23197
24300
|
const routeSlotRoots = new Map();
|
|
23198
24301
|
const routeSlotDefinitions = new Map();
|
|
23199
24302
|
let activeRouteInterception = null;
|
|
24303
|
+
let pendingPageHydrationController = null;
|
|
24304
|
+
|
|
24305
|
+
function cancelPendingPageHydration() {
|
|
24306
|
+
pendingPageHydrationController?.abort();
|
|
24307
|
+
pendingPageHydrationController = null;
|
|
24308
|
+
}
|
|
23200
24309
|
|
|
23201
24310
|
function normalizeServerProps(rawProps) {
|
|
23202
24311
|
const props = rawProps && typeof rawProps === 'object' ? { ...rawProps } : {};
|
|
@@ -23265,7 +24374,11 @@ async function hydrateInitialRouteSlots() {
|
|
|
23265
24374
|
routeSlotDefinitions.set(getRouteSlotKey(slot), slot);
|
|
23266
24375
|
if (!slot.isClientComponent && !slot.shouldHydrate) continue;
|
|
23267
24376
|
try {
|
|
23268
|
-
|
|
24377
|
+
const slotHydrated = await renderRouteSlot(slot, 'hydrate');
|
|
24378
|
+
hydrated = slotHydrated || hydrated;
|
|
24379
|
+
if (slotHydrated) {
|
|
24380
|
+
replayPreHydrationClicks(document.getElementById(slot.containerId));
|
|
24381
|
+
}
|
|
23269
24382
|
} catch (error) {
|
|
23270
24383
|
console.warn('[Farm.js] Could not hydrate route slot:', slot.name, error);
|
|
23271
24384
|
}
|
|
@@ -23336,16 +24449,29 @@ function applyCanonicalPathFromProps(props) {
|
|
|
23336
24449
|
window.history.replaceState({ ...(window.history.state || {}), path: canonicalPath }, '', canonicalPath);
|
|
23337
24450
|
}
|
|
23338
24451
|
|
|
23339
|
-
function replayPreHydrationClicks() {
|
|
23340
|
-
|
|
23341
|
-
|
|
24452
|
+
function replayPreHydrationClicks(container = null) {
|
|
24453
|
+
if (!container) {
|
|
24454
|
+
markFarmHydrated();
|
|
24455
|
+
} else {
|
|
24456
|
+
container.dataset.farmIslandHydrated = 'true';
|
|
24457
|
+
}
|
|
23342
24458
|
|
|
23343
24459
|
const queue = Array.isArray(window.__FARM_PREHYDRATION_CLICK_QUEUE__)
|
|
23344
24460
|
? window.__FARM_PREHYDRATION_CLICK_QUEUE__
|
|
23345
24461
|
: [];
|
|
23346
24462
|
if (queue.length === 0) return;
|
|
23347
24463
|
|
|
23348
|
-
const queuedClicks =
|
|
24464
|
+
const queuedClicks = [];
|
|
24465
|
+
const remainingClicks = [];
|
|
24466
|
+
for (const queuedClick of queue) {
|
|
24467
|
+
const target = queuedClick?.target;
|
|
24468
|
+
if (!container || (target instanceof Node && container.contains(target))) {
|
|
24469
|
+
queuedClicks.push(queuedClick);
|
|
24470
|
+
} else {
|
|
24471
|
+
remainingClicks.push(queuedClick);
|
|
24472
|
+
}
|
|
24473
|
+
}
|
|
24474
|
+
queue.splice(0, queue.length, ...remainingClicks);
|
|
23349
24475
|
for (const queuedClick of queuedClicks) {
|
|
23350
24476
|
const target = queuedClick?.target;
|
|
23351
24477
|
if (!target || typeof target.click !== 'function') continue;
|
|
@@ -23354,6 +24480,11 @@ function replayPreHydrationClicks() {
|
|
|
23354
24480
|
}
|
|
23355
24481
|
}
|
|
23356
24482
|
|
|
24483
|
+
function markFarmHydrated() {
|
|
24484
|
+
window.__FARM_HYDRATED__ = true;
|
|
24485
|
+
document.documentElement.dataset.farmHydrated = 'true';
|
|
24486
|
+
}
|
|
24487
|
+
|
|
23357
24488
|
async function buildClientHydrationElement(PageComponent, pageProps) {
|
|
23358
24489
|
let element = React.createElement(PageComponent, pageProps);
|
|
23359
24490
|
const loadingModulePath = window.__FARM_LOADING_MODULE__;
|
|
@@ -23496,9 +24627,10 @@ async function tryHydrateImportedPage(
|
|
|
23496
24627
|
layouts,
|
|
23497
24628
|
useHydrate = false,
|
|
23498
24629
|
existingProps = null,
|
|
24630
|
+
signal = null,
|
|
23499
24631
|
) {
|
|
23500
24632
|
const modulePath = route?.modulePath;
|
|
23501
|
-
if (!modulePath) {
|
|
24633
|
+
if (!modulePath || signal?.aborted) {
|
|
23502
24634
|
return false;
|
|
23503
24635
|
}
|
|
23504
24636
|
|
|
@@ -23507,6 +24639,7 @@ async function tryHydrateImportedPage(
|
|
|
23507
24639
|
pageModule = await import(/* @vite-ignore */ modulePath);
|
|
23508
24640
|
pageModuleCache.set(modulePath, pageModule);
|
|
23509
24641
|
}
|
|
24642
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
23510
24643
|
|
|
23511
24644
|
const PageComponent = pageModule?.default;
|
|
23512
24645
|
if (!PageComponent) {
|
|
@@ -23521,6 +24654,7 @@ async function tryHydrateImportedPage(
|
|
|
23521
24654
|
window.location.pathname,
|
|
23522
24655
|
existingProps,
|
|
23523
24656
|
);
|
|
24657
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
23524
24658
|
|
|
23525
24659
|
const wrappedElement = useHydrate && container?.id === '__farm_page__'
|
|
23526
24660
|
? wrapWithIntegrationProviders(
|
|
@@ -23531,6 +24665,7 @@ async function tryHydrateImportedPage(
|
|
|
23531
24665
|
currentPageProps,
|
|
23532
24666
|
layouts,
|
|
23533
24667
|
);
|
|
24668
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
23534
24669
|
|
|
23535
24670
|
if (useHydrate) {
|
|
23536
24671
|
try {
|
|
@@ -23561,6 +24696,7 @@ async function tryHydrateImportedPage(
|
|
|
23561
24696
|
async function renderPage(pageData) {
|
|
23562
24697
|
const container = document.getElementById('root');
|
|
23563
24698
|
if (!container) return;
|
|
24699
|
+
cancelPendingPageHydration();
|
|
23564
24700
|
const destination = window.location.pathname + window.location.search;
|
|
23565
24701
|
|
|
23566
24702
|
if (pageData.interception) {
|
|
@@ -23577,6 +24713,7 @@ async function renderPage(pageData) {
|
|
|
23577
24713
|
modulePath: pageData.modulePath,
|
|
23578
24714
|
isClientComponent: pageData.isClientComponent === true,
|
|
23579
24715
|
shouldHydrate: pageData.shouldHydrate === true,
|
|
24716
|
+
islandStrategy: pageData.islandStrategy || 'load',
|
|
23580
24717
|
};
|
|
23581
24718
|
const params = pageData.props?.params || {};
|
|
23582
24719
|
const layouts = (pageData.layoutModules || []).map((modulePath, index) => ({
|
|
@@ -23776,14 +24913,6 @@ async function hydrate() {
|
|
|
23776
24913
|
}
|
|
23777
24914
|
|
|
23778
24915
|
try {
|
|
23779
|
-
// Pre-load layout for SPA navigation
|
|
23780
|
-
try {
|
|
23781
|
-
const layoutModule = await import(/* @vite-ignore */ '/src/app/layout.tsx');
|
|
23782
|
-
LayoutComponent = layoutModule.default;
|
|
23783
|
-
} catch (e) {
|
|
23784
|
-
console.warn('[Farm.js] Could not preload layout:', e);
|
|
23785
|
-
}
|
|
23786
|
-
|
|
23787
24916
|
// Check if this is a client component (set by SSR)
|
|
23788
24917
|
const isClientComponent = window.__FARM_IS_CLIENT__ === true;
|
|
23789
24918
|
const modulePath = window.__FARM_PAGE_MODULE__;
|
|
@@ -23831,34 +24960,88 @@ async function hydrate() {
|
|
|
23831
24960
|
return
|
|
23832
24961
|
}
|
|
23833
24962
|
|
|
23834
|
-
const
|
|
23835
|
-
|
|
23836
|
-
|
|
23837
|
-
|
|
24963
|
+
const currentRoute = findRoute(window.location.pathname)?.route;
|
|
24964
|
+
const islandStrategy = window.__FARM_ISLAND_STRATEGY__ || currentRoute?.islandStrategy || 'load';
|
|
24965
|
+
pageContainer.dataset.farmIsland = 'page';
|
|
24966
|
+
pageContainer.dataset.farmIslandStrategy = islandStrategy;
|
|
23838
24967
|
|
|
23839
|
-
|
|
24968
|
+
const hydrationPathname = window.location.pathname;
|
|
24969
|
+
const hydrationController = new AbortController();
|
|
24970
|
+
pendingPageHydrationController = hydrationController;
|
|
23840
24971
|
try {
|
|
23841
|
-
|
|
23842
|
-
pageContainer,
|
|
23843
|
-
|
|
23844
|
-
|
|
23845
|
-
|
|
23846
|
-
|
|
23847
|
-
|
|
23848
|
-
|
|
23849
|
-
|
|
23850
|
-
|
|
23851
|
-
|
|
23852
|
-
|
|
23853
|
-
}
|
|
24972
|
+
await scheduleFarmIslandHydration({
|
|
24973
|
+
container: pageContainer,
|
|
24974
|
+
strategy: islandStrategy,
|
|
24975
|
+
signal: hydrationController.signal,
|
|
24976
|
+
hydrate: async () => {
|
|
24977
|
+
if (
|
|
24978
|
+
hydrationController.signal.aborted ||
|
|
24979
|
+
!pageContainer.isConnected ||
|
|
24980
|
+
window.location.pathname !== hydrationPathname
|
|
24981
|
+
) {
|
|
24982
|
+
return;
|
|
24983
|
+
}
|
|
23854
24984
|
|
|
23855
|
-
|
|
23856
|
-
|
|
23857
|
-
|
|
23858
|
-
|
|
23859
|
-
|
|
24985
|
+
// Layout code is only needed when this route boundary actually hydrates.
|
|
24986
|
+
try {
|
|
24987
|
+
const layoutModule = await import(/* @vite-ignore */ '/src/app/layout.tsx');
|
|
24988
|
+
LayoutComponent = layoutModule.default;
|
|
24989
|
+
} catch (e) {
|
|
24990
|
+
console.warn('[Farm.js] Could not preload layout:', e);
|
|
24991
|
+
}
|
|
24992
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) return;
|
|
24993
|
+
|
|
24994
|
+
const hydrationSession = await farmClientRuntime.beginHydration({
|
|
24995
|
+
container: pageContainer,
|
|
24996
|
+
mode: shouldHydrate ? 'hydrate' : 'render',
|
|
24997
|
+
});
|
|
24998
|
+
|
|
24999
|
+
let hydrated = false;
|
|
25000
|
+
try {
|
|
25001
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) {
|
|
25002
|
+
await farmClientRuntime.failHydration(
|
|
25003
|
+
hydrationSession,
|
|
25004
|
+
new DOMException('Route hydration was cancelled', 'AbortError'),
|
|
25005
|
+
);
|
|
25006
|
+
return;
|
|
25007
|
+
}
|
|
25008
|
+
hydrated = await tryHydrateImportedPage(
|
|
25009
|
+
pageContainer,
|
|
25010
|
+
{ modulePath },
|
|
25011
|
+
currentPageProps.params || {},
|
|
25012
|
+
layouts,
|
|
25013
|
+
shouldHydrate,
|
|
25014
|
+
currentPageProps,
|
|
25015
|
+
hydrationController.signal,
|
|
25016
|
+
);
|
|
25017
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) {
|
|
25018
|
+
await farmClientRuntime.failHydration(
|
|
25019
|
+
hydrationSession,
|
|
25020
|
+
new DOMException('Route hydration was cancelled', 'AbortError'),
|
|
25021
|
+
);
|
|
25022
|
+
return;
|
|
25023
|
+
}
|
|
25024
|
+
await farmClientRuntime.completeHydration(hydrationSession);
|
|
25025
|
+
} catch (error) {
|
|
25026
|
+
await farmClientRuntime.failHydration(hydrationSession, error);
|
|
25027
|
+
throw error;
|
|
25028
|
+
}
|
|
25029
|
+
|
|
25030
|
+
if (hydrated) {
|
|
25031
|
+
// The scheduler owns queue draining and exactly-once click replay.
|
|
25032
|
+
markFarmHydrated();
|
|
25033
|
+
console.log('[Farm.js] \u2705 Hydrated:', modulePath, '(' + islandStrategy + ')');
|
|
25034
|
+
return;
|
|
25035
|
+
}
|
|
23860
25036
|
|
|
23861
|
-
|
|
25037
|
+
console.log('[Farm.js] Server component - SPA router ready')
|
|
25038
|
+
},
|
|
25039
|
+
});
|
|
25040
|
+
} finally {
|
|
25041
|
+
if (pendingPageHydrationController === hydrationController) {
|
|
25042
|
+
pendingPageHydrationController = null;
|
|
25043
|
+
}
|
|
25044
|
+
}
|
|
23862
25045
|
} catch (error) {
|
|
23863
25046
|
console.error('[Farm.js] Hydration error:', error)
|
|
23864
25047
|
}
|