@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/server.cjs
CHANGED
|
@@ -652,26 +652,26 @@ async function prepareFarmWorkflowsForNitro(config) {
|
|
|
652
652
|
const root = config.root || process.cwd();
|
|
653
653
|
const distDir = config.distDir || ".farm";
|
|
654
654
|
const fs9 = await import("fs/promises");
|
|
655
|
-
const
|
|
656
|
-
const generatedDir =
|
|
655
|
+
const path27 = await import("path");
|
|
656
|
+
const generatedDir = path27.join(root, distDir, ".nitro", "farm-workflows");
|
|
657
657
|
await fs9.mkdir(generatedDir, { recursive: true });
|
|
658
658
|
const tasks = {};
|
|
659
659
|
const scheduledTasks = createScheduledTasks(workflows);
|
|
660
660
|
for (const workflow of workflows) {
|
|
661
|
-
const wrapperPath =
|
|
661
|
+
const wrapperPath = path27.join(generatedDir, `${safeFileName(workflow.id)}.mjs`);
|
|
662
662
|
await fs9.writeFile(wrapperPath, createNitroTaskWrapper(workflow), "utf8");
|
|
663
663
|
tasks[workflow.id] = {
|
|
664
664
|
handler: wrapperPath,
|
|
665
665
|
description: workflow.description || `Farm workflow ${workflow.id}`
|
|
666
666
|
};
|
|
667
667
|
}
|
|
668
|
-
const handlerPath =
|
|
668
|
+
const handlerPath = path27.join(generatedDir, "http-handler.mjs");
|
|
669
669
|
await fs9.writeFile(
|
|
670
670
|
handlerPath,
|
|
671
671
|
createNitroWorkflowHTTPHandler(workflowConfig, workflows),
|
|
672
672
|
"utf8"
|
|
673
673
|
);
|
|
674
|
-
const manifestPath =
|
|
674
|
+
const manifestPath = path27.join(generatedDir, "manifest.json");
|
|
675
675
|
await fs9.writeFile(
|
|
676
676
|
manifestPath,
|
|
677
677
|
JSON.stringify(
|
|
@@ -754,10 +754,10 @@ function resolveWorkflowDefinition(module2) {
|
|
|
754
754
|
}
|
|
755
755
|
async function findWorkflowFiles(root, dirs) {
|
|
756
756
|
const fs9 = await import("fs/promises");
|
|
757
|
-
const
|
|
757
|
+
const path27 = await import("path");
|
|
758
758
|
const files = [];
|
|
759
759
|
for (const dir of dirs) {
|
|
760
|
-
const absoluteDir =
|
|
760
|
+
const absoluteDir = path27.isAbsolute(dir) ? dir : path27.join(root, dir);
|
|
761
761
|
if (!await pathExists(absoluteDir)) continue;
|
|
762
762
|
await walkWorkflowDir(absoluteDir, files);
|
|
763
763
|
}
|
|
@@ -765,10 +765,10 @@ async function findWorkflowFiles(root, dirs) {
|
|
|
765
765
|
}
|
|
766
766
|
async function walkWorkflowDir(dir, files) {
|
|
767
767
|
const fs9 = await import("fs/promises");
|
|
768
|
-
const
|
|
768
|
+
const path27 = await import("path");
|
|
769
769
|
const entries = await fs9.readdir(dir, { withFileTypes: true });
|
|
770
770
|
for (const entry of entries) {
|
|
771
|
-
const filePath =
|
|
771
|
+
const filePath = path27.join(dir, entry.name);
|
|
772
772
|
if (entry.isDirectory()) {
|
|
773
773
|
if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
|
|
774
774
|
await walkWorkflowDir(filePath, files);
|
|
@@ -788,12 +788,12 @@ function isWorkflowFile(fileName) {
|
|
|
788
788
|
}
|
|
789
789
|
async function loadWorkflowModule(filePath, root) {
|
|
790
790
|
const fs9 = await import("fs/promises");
|
|
791
|
-
const
|
|
791
|
+
const path27 = await import("path");
|
|
792
792
|
const { pathToFileURL: pathToFileURL5 } = await import("url");
|
|
793
793
|
const { build } = await import("esbuild");
|
|
794
|
-
const outDir =
|
|
794
|
+
const outDir = path27.join(root, ".farm", ".workflow-loader");
|
|
795
795
|
await fs9.mkdir(outDir, { recursive: true });
|
|
796
|
-
const outfile =
|
|
796
|
+
const outfile = path27.join(
|
|
797
797
|
outDir,
|
|
798
798
|
`workflow-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`
|
|
799
799
|
);
|
|
@@ -1076,7 +1076,7 @@ function normalizeCronJob(name, job) {
|
|
|
1076
1076
|
if (!job || typeof job !== "object" || Array.isArray(job)) {
|
|
1077
1077
|
throw new TypeError(`Farm cron ${JSON.stringify(name)} must be a configuration object.`);
|
|
1078
1078
|
}
|
|
1079
|
-
const
|
|
1079
|
+
const path27 = normalizeCronPath(name, job.path);
|
|
1080
1080
|
const rawSchedule = Array.isArray(job.schedule) ? job.schedule : [job.schedule];
|
|
1081
1081
|
const schedule = [...new Set(rawSchedule.map((value) => normalizeCronExpression(name, value)))];
|
|
1082
1082
|
if (schedule.length === 0) {
|
|
@@ -1085,7 +1085,7 @@ function normalizeCronJob(name, job) {
|
|
|
1085
1085
|
return {
|
|
1086
1086
|
name,
|
|
1087
1087
|
schedule,
|
|
1088
|
-
path:
|
|
1088
|
+
path: path27,
|
|
1089
1089
|
description: job.description?.trim() || void 0
|
|
1090
1090
|
};
|
|
1091
1091
|
}
|
|
@@ -1093,13 +1093,13 @@ function normalizeCronPath(name, value) {
|
|
|
1093
1093
|
if (typeof value !== "string" || !value.trim().startsWith("/")) {
|
|
1094
1094
|
throw new TypeError(`Farm cron ${JSON.stringify(name)} path must start with "/".`);
|
|
1095
1095
|
}
|
|
1096
|
-
const
|
|
1097
|
-
if (
|
|
1096
|
+
const path27 = value.trim();
|
|
1097
|
+
if (path27.startsWith("//") || path27.includes("?") || path27.includes("#")) {
|
|
1098
1098
|
throw new TypeError(
|
|
1099
1099
|
`Farm cron ${JSON.stringify(name)} path must be an application pathname without a host, query, or hash.`
|
|
1100
1100
|
);
|
|
1101
1101
|
}
|
|
1102
|
-
return
|
|
1102
|
+
return path27.length > 1 ? path27.replace(/\/+$/, "") : path27;
|
|
1103
1103
|
}
|
|
1104
1104
|
function normalizeCronExpression(name, value) {
|
|
1105
1105
|
if (typeof value !== "string") {
|
|
@@ -2364,7 +2364,7 @@ var init_server_action_security = __esm({
|
|
|
2364
2364
|
|
|
2365
2365
|
// src/image-config.ts
|
|
2366
2366
|
function resolveFarmImageConfig(config) {
|
|
2367
|
-
const
|
|
2367
|
+
const path27 = normalizeImagePath(config?.path ?? DEFAULT_FARM_IMAGE_PATH);
|
|
2368
2368
|
const deviceSizes = normalizeIntegerList(
|
|
2369
2369
|
config?.deviceSizes ?? DEFAULT_FARM_IMAGE_DEVICE_SIZES,
|
|
2370
2370
|
"images.deviceSizes"
|
|
@@ -2392,7 +2392,7 @@ function resolveFarmImageConfig(config) {
|
|
|
2392
2392
|
);
|
|
2393
2393
|
return Object.freeze({
|
|
2394
2394
|
provider: config?.provider ?? "auto",
|
|
2395
|
-
path:
|
|
2395
|
+
path: path27,
|
|
2396
2396
|
domains: Object.freeze([
|
|
2397
2397
|
...new Set(
|
|
2398
2398
|
(config?.domains ?? []).map((domain) => domain.trim().toLowerCase()).filter(Boolean)
|
|
@@ -2431,11 +2431,11 @@ function getPublicFarmImageConfig(config) {
|
|
|
2431
2431
|
};
|
|
2432
2432
|
}
|
|
2433
2433
|
function normalizeImagePath(value) {
|
|
2434
|
-
const
|
|
2435
|
-
if (!
|
|
2434
|
+
const path27 = value.trim().replace(/\/+$/, "") || "/";
|
|
2435
|
+
if (!path27.startsWith("/") || path27.includes("?") || path27.includes("#")) {
|
|
2436
2436
|
throw new TypeError("images.path must be an absolute pathname without a query or hash");
|
|
2437
2437
|
}
|
|
2438
|
-
return
|
|
2438
|
+
return path27;
|
|
2439
2439
|
}
|
|
2440
2440
|
function normalizeIntegerList(values, name, max) {
|
|
2441
2441
|
if (values.length === 0) {
|
|
@@ -3274,9 +3274,9 @@ var init_integration_orm = __esm({
|
|
|
3274
3274
|
});
|
|
3275
3275
|
|
|
3276
3276
|
// src/integrations.ts
|
|
3277
|
-
function defineTypedIntegrationRoute(method,
|
|
3277
|
+
function defineTypedIntegrationRoute(method, path27, input) {
|
|
3278
3278
|
return {
|
|
3279
|
-
path:
|
|
3279
|
+
path: path27,
|
|
3280
3280
|
method,
|
|
3281
3281
|
middleware: input.middleware,
|
|
3282
3282
|
before: input.before,
|
|
@@ -3286,7 +3286,7 @@ function defineTypedIntegrationRoute(method, path25, input) {
|
|
|
3286
3286
|
input: normalizeIntegrationRouteInputSchemas(input),
|
|
3287
3287
|
handler: input.handler,
|
|
3288
3288
|
__operation: defineIntegrationAPIOperation({
|
|
3289
|
-
path:
|
|
3289
|
+
path: path27,
|
|
3290
3290
|
method,
|
|
3291
3291
|
bodyFormat: input.bodyFormat,
|
|
3292
3292
|
responseFormat: input.responseFormat,
|
|
@@ -3298,52 +3298,52 @@ function defineTypedIntegrationRoute(method, path25, input) {
|
|
|
3298
3298
|
}
|
|
3299
3299
|
function createIntegrationRouteFactory() {
|
|
3300
3300
|
return {
|
|
3301
|
-
get(
|
|
3301
|
+
get(path27, input) {
|
|
3302
3302
|
return defineTypedIntegrationRoute(
|
|
3303
3303
|
"GET",
|
|
3304
|
-
|
|
3304
|
+
path27,
|
|
3305
3305
|
input
|
|
3306
3306
|
);
|
|
3307
3307
|
},
|
|
3308
|
-
post(
|
|
3308
|
+
post(path27, input) {
|
|
3309
3309
|
return defineTypedIntegrationRoute(
|
|
3310
3310
|
"POST",
|
|
3311
|
-
|
|
3311
|
+
path27,
|
|
3312
3312
|
{
|
|
3313
3313
|
bodyFormat: "json",
|
|
3314
3314
|
...input
|
|
3315
3315
|
}
|
|
3316
3316
|
);
|
|
3317
3317
|
},
|
|
3318
|
-
put(
|
|
3318
|
+
put(path27, input) {
|
|
3319
3319
|
return defineTypedIntegrationRoute(
|
|
3320
3320
|
"PUT",
|
|
3321
|
-
|
|
3321
|
+
path27,
|
|
3322
3322
|
{
|
|
3323
3323
|
bodyFormat: "json",
|
|
3324
3324
|
...input
|
|
3325
3325
|
}
|
|
3326
3326
|
);
|
|
3327
3327
|
},
|
|
3328
|
-
patch(
|
|
3329
|
-
return defineTypedIntegrationRoute("PATCH",
|
|
3328
|
+
patch(path27, input) {
|
|
3329
|
+
return defineTypedIntegrationRoute("PATCH", path27, {
|
|
3330
3330
|
bodyFormat: "json",
|
|
3331
3331
|
...input
|
|
3332
3332
|
});
|
|
3333
3333
|
},
|
|
3334
|
-
delete(
|
|
3335
|
-
return defineTypedIntegrationRoute("DELETE",
|
|
3334
|
+
delete(path27, input) {
|
|
3335
|
+
return defineTypedIntegrationRoute("DELETE", path27, {
|
|
3336
3336
|
bodyFormat: "json",
|
|
3337
3337
|
...input
|
|
3338
3338
|
});
|
|
3339
3339
|
},
|
|
3340
|
-
options(
|
|
3341
|
-
return defineTypedIntegrationRoute("OPTIONS",
|
|
3340
|
+
options(path27, input) {
|
|
3341
|
+
return defineTypedIntegrationRoute("OPTIONS", path27, input);
|
|
3342
3342
|
},
|
|
3343
|
-
head(
|
|
3343
|
+
head(path27, input) {
|
|
3344
3344
|
return defineTypedIntegrationRoute(
|
|
3345
3345
|
"HEAD",
|
|
3346
|
-
|
|
3346
|
+
path27,
|
|
3347
3347
|
input
|
|
3348
3348
|
);
|
|
3349
3349
|
}
|
|
@@ -3560,8 +3560,8 @@ async function parseIntegrationConfigSchema(integration, schema, value) {
|
|
|
3560
3560
|
function createIntegrationConfigValidationError(integration, error) {
|
|
3561
3561
|
const issues = Array.isArray(error.issues) && error.issues.length > 0 ? error.issues.map((issue) => {
|
|
3562
3562
|
const normalizedPath = normalizeIntegrationValidationPath(issue.path);
|
|
3563
|
-
const
|
|
3564
|
-
return `${
|
|
3563
|
+
const path27 = normalizedPath.length ? `${normalizedPath.join(".")}: ` : "";
|
|
3564
|
+
return `${path27}${issue.message || "Invalid config"}`;
|
|
3565
3565
|
}).join("; ") : error.message || "Invalid config";
|
|
3566
3566
|
return new Error(`Integration "${integration.type}" config validation failed: ${issues}`);
|
|
3567
3567
|
}
|
|
@@ -4246,8 +4246,8 @@ function normalizeIntegrationValidationIssues(source, error) {
|
|
|
4246
4246
|
}
|
|
4247
4247
|
];
|
|
4248
4248
|
}
|
|
4249
|
-
function normalizeIntegrationValidationPath(
|
|
4250
|
-
return (
|
|
4249
|
+
function normalizeIntegrationValidationPath(path27) {
|
|
4250
|
+
return (path27 || []).map((segment) => {
|
|
4251
4251
|
const key = typeof segment === "object" && segment !== null && "key" in segment ? segment.key : segment;
|
|
4252
4252
|
return typeof key === "symbol" ? key.description || key.toString() : key;
|
|
4253
4253
|
});
|
|
@@ -5040,8 +5040,8 @@ function createFarmDeploymentMismatchResponse(mismatch) {
|
|
|
5040
5040
|
}
|
|
5041
5041
|
);
|
|
5042
5042
|
}
|
|
5043
|
-
function createFarmDeploymentCookie(deploymentId,
|
|
5044
|
-
const normalizedPath =
|
|
5043
|
+
function createFarmDeploymentCookie(deploymentId, path27 = "/", secure = false) {
|
|
5044
|
+
const normalizedPath = path27.startsWith("/") ? path27 : `/${path27}`;
|
|
5045
5045
|
return [
|
|
5046
5046
|
`${FARM_DEPLOYMENT_COOKIE}=${encodeURIComponent(deploymentId)}`,
|
|
5047
5047
|
`Path=${normalizedPath}`,
|
|
@@ -5325,6 +5325,33 @@ var init_auth_config = __esm({
|
|
|
5325
5325
|
}
|
|
5326
5326
|
});
|
|
5327
5327
|
|
|
5328
|
+
// src/preload.ts
|
|
5329
|
+
function resolveFarmPerformanceConfig(config) {
|
|
5330
|
+
return {
|
|
5331
|
+
preload: {
|
|
5332
|
+
mode: config?.preload?.mode === "warn" ? "warn" : "enforce",
|
|
5333
|
+
maxImages: normalizeBudget(config?.preload?.maxImages, DEFAULT_PRELOAD_CONFIG.maxImages),
|
|
5334
|
+
maxFonts: normalizeBudget(config?.preload?.maxFonts, DEFAULT_PRELOAD_CONFIG.maxFonts)
|
|
5335
|
+
}
|
|
5336
|
+
};
|
|
5337
|
+
}
|
|
5338
|
+
function normalizeBudget(value, fallback) {
|
|
5339
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : fallback;
|
|
5340
|
+
}
|
|
5341
|
+
var DEFAULT_PRELOAD_CONFIG;
|
|
5342
|
+
var init_preload = __esm({
|
|
5343
|
+
"src/preload.ts"() {
|
|
5344
|
+
"use strict";
|
|
5345
|
+
DEFAULT_PRELOAD_CONFIG = {
|
|
5346
|
+
mode: "enforce",
|
|
5347
|
+
maxImages: 1,
|
|
5348
|
+
maxFonts: 2
|
|
5349
|
+
};
|
|
5350
|
+
__name(resolveFarmPerformanceConfig, "resolveFarmPerformanceConfig");
|
|
5351
|
+
__name(normalizeBudget, "normalizeBudget");
|
|
5352
|
+
}
|
|
5353
|
+
});
|
|
5354
|
+
|
|
5328
5355
|
// src/write-file-if-changed.ts
|
|
5329
5356
|
function writeFileIfChanged(filePath, content) {
|
|
5330
5357
|
try {
|
|
@@ -5444,11 +5471,11 @@ var init_type_generator = __esm({
|
|
|
5444
5471
|
routeGroups.get(key).push(route);
|
|
5445
5472
|
}
|
|
5446
5473
|
const nestedStructure = {};
|
|
5447
|
-
for (const [
|
|
5474
|
+
for (const [path27, routeList] of routeGroups) {
|
|
5448
5475
|
const route = routeList[0];
|
|
5449
5476
|
const importPath = this.getRouteImportPath(route, options.outFile);
|
|
5450
5477
|
const routeName = this.pathToRouteName(route.path);
|
|
5451
|
-
const cleanPath =
|
|
5478
|
+
const cleanPath = path27 === "/api" ? "" : path27.replace(/^\/api\//, "");
|
|
5452
5479
|
const parts = cleanPath ? cleanPath.split("/") : [];
|
|
5453
5480
|
const allMethods = routeList.flatMap((r) => r.methods);
|
|
5454
5481
|
for (const method of allMethods) {
|
|
@@ -5507,8 +5534,8 @@ ${typeExports}
|
|
|
5507
5534
|
const relativeImport = (0, import_path7.relative)((0, import_path7.dirname)(outFile), route.filePath).replace(/\\/g, "/").replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
5508
5535
|
return relativeImport.startsWith(".") ? relativeImport : `./${relativeImport}`;
|
|
5509
5536
|
}
|
|
5510
|
-
pathToRouteName(
|
|
5511
|
-
return (
|
|
5537
|
+
pathToRouteName(path27) {
|
|
5538
|
+
return (path27 === "/api" ? "root" : path27.replace(/^\/api\//, "")).replace(/\//g, "_").replace(/[^a-zA-Z0-9_]/g, "");
|
|
5512
5539
|
}
|
|
5513
5540
|
structureToTypeString(obj, indent) {
|
|
5514
5541
|
const spaces = " ".repeat(indent);
|
|
@@ -5528,15 +5555,15 @@ ${typeExports}
|
|
|
5528
5555
|
toTypePropertyKey(key) {
|
|
5529
5556
|
return /^[$A-Z_][0-9A-Z_$]*$/i.test(key) ? key : JSON.stringify(key);
|
|
5530
5557
|
}
|
|
5531
|
-
getBaseExportName(
|
|
5532
|
-
const cleanPath =
|
|
5558
|
+
getBaseExportName(path27) {
|
|
5559
|
+
const cleanPath = path27.replace(/^\/api\//, "");
|
|
5533
5560
|
if (cleanPath === "") {
|
|
5534
5561
|
return "api";
|
|
5535
5562
|
}
|
|
5536
5563
|
return cleanPath;
|
|
5537
5564
|
}
|
|
5538
|
-
getExportName(
|
|
5539
|
-
const cleanPath =
|
|
5565
|
+
getExportName(path27, method) {
|
|
5566
|
+
const cleanPath = path27.replace(/^\/api\//, "");
|
|
5540
5567
|
if (cleanPath === "") {
|
|
5541
5568
|
return method.toLowerCase();
|
|
5542
5569
|
}
|
|
@@ -5978,28 +6005,71 @@ var init_image_server = __esm({
|
|
|
5978
6005
|
}
|
|
5979
6006
|
});
|
|
5980
6007
|
|
|
6008
|
+
// src/docs/fonts.ts
|
|
6009
|
+
function resolveFarmDocsFontAssets(root) {
|
|
6010
|
+
return FARM_DOCS_FONT_SOURCES.flatMap(({ family, packagePath }) => {
|
|
6011
|
+
const sourcePath = import_node_path10.default.join(root, "node_modules", packagePath);
|
|
6012
|
+
if (!(0, import_node_fs6.existsSync)(sourcePath)) return [];
|
|
6013
|
+
const source = (0, import_node_fs6.readFileSync)(sourcePath);
|
|
6014
|
+
const fingerprint = (0, import_node_crypto3.createHash)("sha256").update(source).digest("hex").slice(0, 12);
|
|
6015
|
+
const extension = import_node_path10.default.extname(packagePath);
|
|
6016
|
+
const baseName = import_node_path10.default.basename(packagePath, extension);
|
|
6017
|
+
return [
|
|
6018
|
+
{
|
|
6019
|
+
family,
|
|
6020
|
+
sourcePath,
|
|
6021
|
+
url: `/assets/fonts/${baseName}-h${fingerprint}${extension}`
|
|
6022
|
+
}
|
|
6023
|
+
];
|
|
6024
|
+
});
|
|
6025
|
+
}
|
|
6026
|
+
function toFarmDocsPublicFontAssets(assets) {
|
|
6027
|
+
return assets.map(({ family, url }) => ({ family, url }));
|
|
6028
|
+
}
|
|
6029
|
+
var import_node_crypto3, import_node_fs6, import_node_path10, FARM_DOCS_FONT_SOURCES;
|
|
6030
|
+
var init_fonts = __esm({
|
|
6031
|
+
"src/docs/fonts.ts"() {
|
|
6032
|
+
"use strict";
|
|
6033
|
+
import_node_crypto3 = require("crypto");
|
|
6034
|
+
import_node_fs6 = require("fs");
|
|
6035
|
+
import_node_path10 = __toESM(require("path"));
|
|
6036
|
+
FARM_DOCS_FONT_SOURCES = [
|
|
6037
|
+
{
|
|
6038
|
+
family: "Geist Sans",
|
|
6039
|
+
packagePath: "geist/dist/fonts/geist-sans/Geist-Variable.woff2"
|
|
6040
|
+
},
|
|
6041
|
+
{
|
|
6042
|
+
family: "Geist Mono",
|
|
6043
|
+
packagePath: "geist/dist/fonts/geist-mono/GeistMono-Variable.woff2"
|
|
6044
|
+
}
|
|
6045
|
+
];
|
|
6046
|
+
__name(resolveFarmDocsFontAssets, "resolveFarmDocsFontAssets");
|
|
6047
|
+
__name(toFarmDocsPublicFontAssets, "toFarmDocsPublicFontAssets");
|
|
6048
|
+
}
|
|
6049
|
+
});
|
|
6050
|
+
|
|
5981
6051
|
// src/docs/last-modified.ts
|
|
5982
6052
|
function normalizeRelativePath(value) {
|
|
5983
6053
|
return value.replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
5984
6054
|
}
|
|
5985
6055
|
function resolveExistingPath(filePath) {
|
|
5986
6056
|
try {
|
|
5987
|
-
return (0,
|
|
6057
|
+
return (0, import_node_fs7.realpathSync)(filePath);
|
|
5988
6058
|
} catch {
|
|
5989
|
-
return
|
|
6059
|
+
return import_node_path11.default.resolve(filePath);
|
|
5990
6060
|
}
|
|
5991
6061
|
}
|
|
5992
6062
|
function isDocsSourceFile(filePath) {
|
|
5993
|
-
return DOCS_FILE_EXTENSIONS.has(
|
|
6063
|
+
return DOCS_FILE_EXTENSIONS.has(import_node_path11.default.extname(filePath).toLowerCase());
|
|
5994
6064
|
}
|
|
5995
6065
|
function discoverDocsSourceFiles(contentDir) {
|
|
5996
6066
|
const files = [];
|
|
5997
6067
|
const visit = /* @__PURE__ */ __name((dir) => {
|
|
5998
|
-
for (const entry of (0,
|
|
6068
|
+
for (const entry of (0, import_node_fs7.readdirSync)(dir, { withFileTypes: true }).sort(
|
|
5999
6069
|
(a, b) => a.name.localeCompare(b.name)
|
|
6000
6070
|
)) {
|
|
6001
6071
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
6002
|
-
const absolutePath =
|
|
6072
|
+
const absolutePath = import_node_path11.default.join(dir, entry.name);
|
|
6003
6073
|
if (entry.isDirectory()) {
|
|
6004
6074
|
visit(absolutePath);
|
|
6005
6075
|
} else if (entry.isFile() && isDocsSourceFile(absolutePath)) {
|
|
@@ -6007,7 +6077,7 @@ function discoverDocsSourceFiles(contentDir) {
|
|
|
6007
6077
|
}
|
|
6008
6078
|
}
|
|
6009
6079
|
}, "visit");
|
|
6010
|
-
if ((0,
|
|
6080
|
+
if ((0, import_node_fs7.existsSync)(contentDir)) visit(contentDir);
|
|
6011
6081
|
return files;
|
|
6012
6082
|
}
|
|
6013
6083
|
function getGitLastModifiedDates(contentDir) {
|
|
@@ -6017,7 +6087,7 @@ function getGitLastModifiedDates(contentDir) {
|
|
|
6017
6087
|
stdio: ["ignore", "pipe", "ignore"]
|
|
6018
6088
|
}).trim();
|
|
6019
6089
|
if (!gitRoot) return {};
|
|
6020
|
-
const contentPathspec = normalizeRelativePath(
|
|
6090
|
+
const contentPathspec = normalizeRelativePath(import_node_path11.default.relative(gitRoot, contentDir)) || ".";
|
|
6021
6091
|
const contentPrefix = contentPathspec === "." ? "" : `${contentPathspec}/`;
|
|
6022
6092
|
const history = (0, import_node_child_process.execFileSync)(
|
|
6023
6093
|
"git",
|
|
@@ -6059,11 +6129,11 @@ function getGitLastModifiedDates(contentDir) {
|
|
|
6059
6129
|
}
|
|
6060
6130
|
}
|
|
6061
6131
|
function readManifest(contentDir) {
|
|
6062
|
-
const manifestPath =
|
|
6063
|
-
if (!(0,
|
|
6132
|
+
const manifestPath = import_node_path11.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
|
|
6133
|
+
if (!(0, import_node_fs7.existsSync)(manifestPath)) return null;
|
|
6064
6134
|
try {
|
|
6065
6135
|
const parsed = JSON.parse(
|
|
6066
|
-
(0,
|
|
6136
|
+
(0, import_node_fs7.readFileSync)(manifestPath, "utf8")
|
|
6067
6137
|
);
|
|
6068
6138
|
if (parsed.version !== 1 || !parsed.pages || typeof parsed.pages !== "object") return null;
|
|
6069
6139
|
const pages = Object.fromEntries(
|
|
@@ -6082,15 +6152,15 @@ function createFarmDocsLastModifiedManifest(contentDir, options = {}) {
|
|
|
6082
6152
|
const fallbackDate = (options.now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
6083
6153
|
const pages = {};
|
|
6084
6154
|
for (const sourcePath of discoverDocsSourceFiles(resolvedContentDir)) {
|
|
6085
|
-
const relativePath2 = normalizeRelativePath(
|
|
6086
|
-
pages[relativePath2] = gitDates[relativePath2] || (options.fallback === "now" ? fallbackDate : (0,
|
|
6155
|
+
const relativePath2 = normalizeRelativePath(import_node_path11.default.relative(resolvedContentDir, sourcePath));
|
|
6156
|
+
pages[relativePath2] = gitDates[relativePath2] || (options.fallback === "now" ? fallbackDate : (0, import_node_fs7.statSync)(sourcePath).mtime.toISOString());
|
|
6087
6157
|
}
|
|
6088
6158
|
return { version: 1, pages };
|
|
6089
6159
|
}
|
|
6090
6160
|
function getLastModifiedManifest(contentDir) {
|
|
6091
6161
|
const resolvedContentDir = resolveExistingPath(contentDir);
|
|
6092
|
-
const manifestPath =
|
|
6093
|
-
const manifestStat = (0,
|
|
6162
|
+
const manifestPath = import_node_path11.default.join(resolvedContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
|
|
6163
|
+
const manifestStat = (0, import_node_fs7.existsSync)(manifestPath) ? (0, import_node_fs7.statSync)(manifestPath) : null;
|
|
6094
6164
|
const signature = manifestStat ? `file:${manifestStat.mtimeMs}:${manifestStat.size}` : "generated";
|
|
6095
6165
|
const cached = manifestCache.get(resolvedContentDir);
|
|
6096
6166
|
if (cached?.signature === signature) return cached.manifest;
|
|
@@ -6103,21 +6173,21 @@ function resolveFarmDocsPageLastModified(contentDir, sourcePath, frontmatter) {
|
|
|
6103
6173
|
if (configured) return configured;
|
|
6104
6174
|
const resolvedContentDir = resolveExistingPath(contentDir);
|
|
6105
6175
|
const resolvedSourcePath = resolveExistingPath(sourcePath);
|
|
6106
|
-
const relativePath2 = normalizeRelativePath(
|
|
6107
|
-
const isInsideContentDir = relativePath2 !== ".." && !relativePath2.startsWith("../") && !
|
|
6176
|
+
const relativePath2 = normalizeRelativePath(import_node_path11.default.relative(resolvedContentDir, resolvedSourcePath));
|
|
6177
|
+
const isInsideContentDir = relativePath2 !== ".." && !relativePath2.startsWith("../") && !import_node_path11.default.isAbsolute(relativePath2);
|
|
6108
6178
|
if (isInsideContentDir) {
|
|
6109
6179
|
const generated = getLastModifiedManifest(resolvedContentDir).pages[relativePath2];
|
|
6110
6180
|
if (generated) return generated;
|
|
6111
6181
|
}
|
|
6112
|
-
return (0,
|
|
6182
|
+
return (0, import_node_fs7.statSync)(resolvedSourcePath).mtime.toISOString();
|
|
6113
6183
|
}
|
|
6114
|
-
var import_node_child_process,
|
|
6184
|
+
var import_node_child_process, import_node_fs7, import_node_path11, FARM_DOCS_LAST_MODIFIED_MANIFEST, COMMIT_MARKER, DOCS_FILE_EXTENSIONS, manifestCache;
|
|
6115
6185
|
var init_last_modified = __esm({
|
|
6116
6186
|
"src/docs/last-modified.ts"() {
|
|
6117
6187
|
"use strict";
|
|
6118
6188
|
import_node_child_process = require("child_process");
|
|
6119
|
-
|
|
6120
|
-
|
|
6189
|
+
import_node_fs7 = require("fs");
|
|
6190
|
+
import_node_path11 = __toESM(require("path"));
|
|
6121
6191
|
FARM_DOCS_LAST_MODIFIED_MANIFEST = ".farm-docs-last-modified.json";
|
|
6122
6192
|
COMMIT_MARKER = "__FARM_DOCS_COMMIT__";
|
|
6123
6193
|
DOCS_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".mdx"]);
|
|
@@ -6179,8 +6249,8 @@ var init_pixel_border_css = __esm({
|
|
|
6179
6249
|
--scrollbar-thumb-hover: var(--color-fd-ring);
|
|
6180
6250
|
--scrollbar-track: transparent;
|
|
6181
6251
|
--radius: 0px;
|
|
6182
|
-
--font-geist-sans:
|
|
6183
|
-
--font-geist-mono:
|
|
6252
|
+
--font-geist-sans: ui-sans-serif, system-ui, sans-serif;
|
|
6253
|
+
--font-geist-mono: ui-monospace, monospace;
|
|
6184
6254
|
}
|
|
6185
6255
|
|
|
6186
6256
|
.dark {
|
|
@@ -6193,28 +6263,6 @@ body,
|
|
|
6193
6263
|
background-color: var(--color-fd-background) !important;
|
|
6194
6264
|
}
|
|
6195
6265
|
|
|
6196
|
-
@font-face {
|
|
6197
|
-
font-family: "Geist Sans";
|
|
6198
|
-
font-display: block;
|
|
6199
|
-
font-style: normal;
|
|
6200
|
-
font-weight: 100 900;
|
|
6201
|
-
src:
|
|
6202
|
-
local("Geist Sans"),
|
|
6203
|
-
url("/assets/Geist-Variable-CrgPqtmy.woff2") format("woff2"),
|
|
6204
|
-
url("/node_modules/geist/dist/fonts/geist-sans/Geist-Variable.woff2") format("woff2");
|
|
6205
|
-
}
|
|
6206
|
-
|
|
6207
|
-
@font-face {
|
|
6208
|
-
font-family: "Geist Mono";
|
|
6209
|
-
font-display: block;
|
|
6210
|
-
font-style: normal;
|
|
6211
|
-
font-weight: 100 900;
|
|
6212
|
-
src:
|
|
6213
|
-
local("Geist Mono"),
|
|
6214
|
-
url("/assets/GeistMono-Variable-BNLlm6Cd.woff2") format("woff2"),
|
|
6215
|
-
url("/node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2") format("woff2");
|
|
6216
|
-
}
|
|
6217
|
-
|
|
6218
6266
|
* {
|
|
6219
6267
|
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
|
|
6220
6268
|
scrollbar-width: thin;
|
|
@@ -7421,10 +7469,10 @@ function isFarmDocsSearchEnabled(docs) {
|
|
|
7421
7469
|
}
|
|
7422
7470
|
function resolveFarmDocsSearchClientModule(root) {
|
|
7423
7471
|
try {
|
|
7424
|
-
const requireFromApp = (0, import_node_module4.createRequire)(
|
|
7472
|
+
const requireFromApp = (0, import_node_module4.createRequire)(import_node_path12.default.join(import_node_path12.default.resolve(root), "package.json"));
|
|
7425
7473
|
const themeEntry = requireFromApp.resolve("@farming-labs/theme");
|
|
7426
|
-
const commandSearchModule =
|
|
7427
|
-
if ((0,
|
|
7474
|
+
const commandSearchModule = import_node_path12.default.join(import_node_path12.default.dirname(themeEntry), "docs-command-search.mjs");
|
|
7475
|
+
if ((0, import_node_fs8.existsSync)(commandSearchModule)) return commandSearchModule;
|
|
7428
7476
|
} catch {
|
|
7429
7477
|
}
|
|
7430
7478
|
return void 0;
|
|
@@ -7563,13 +7611,13 @@ async function mountFarmDocsSearch() {
|
|
|
7563
7611
|
window.__FARM_MOUNT_DOCS_SEARCH__ = mountFarmDocsSearch;
|
|
7564
7612
|
`;
|
|
7565
7613
|
}
|
|
7566
|
-
var
|
|
7614
|
+
var import_node_fs8, import_node_module4, import_node_path12;
|
|
7567
7615
|
var init_search_client = __esm({
|
|
7568
7616
|
"src/docs/search-client.ts"() {
|
|
7569
7617
|
"use strict";
|
|
7570
|
-
|
|
7618
|
+
import_node_fs8 = require("fs");
|
|
7571
7619
|
import_node_module4 = require("module");
|
|
7572
|
-
|
|
7620
|
+
import_node_path12 = __toESM(require("path"));
|
|
7573
7621
|
__name(isFarmDocsSearchEnabled, "isFarmDocsSearchEnabled");
|
|
7574
7622
|
__name(resolveFarmDocsSearchClientModule, "resolveFarmDocsSearchClientModule");
|
|
7575
7623
|
__name(generateFarmDocsSearchBootstrapRuntime, "generateFarmDocsSearchBootstrapRuntime");
|
|
@@ -7577,11 +7625,418 @@ var init_search_client = __esm({
|
|
|
7577
7625
|
}
|
|
7578
7626
|
});
|
|
7579
7627
|
|
|
7628
|
+
// src/docs/social-image.ts
|
|
7629
|
+
function normalizeEntry(entry) {
|
|
7630
|
+
if (!entry || entry === "/") return "";
|
|
7631
|
+
return `/${entry.replace(/^\/+|\/+$/g, "")}`;
|
|
7632
|
+
}
|
|
7633
|
+
function encodeSlugPath(slug) {
|
|
7634
|
+
return slug.split("/").filter(Boolean).map((segment) => encodeURIComponent(segment)).join("/");
|
|
7635
|
+
}
|
|
7636
|
+
function getSocialImageConfig(docs) {
|
|
7637
|
+
return typeof docs.config.socialImage === "object" && docs.config.socialImage ? docs.config.socialImage : void 0;
|
|
7638
|
+
}
|
|
7639
|
+
function getNavTitle(docs) {
|
|
7640
|
+
if (typeof docs.config.nav !== "object" || !docs.config.nav || !("title" in docs.config.nav)) {
|
|
7641
|
+
return "Farm.js";
|
|
7642
|
+
}
|
|
7643
|
+
return String(docs.config.nav.title || "Farm.js");
|
|
7644
|
+
}
|
|
7645
|
+
function isFalse(value) {
|
|
7646
|
+
return value ? /^(false|no|none|off|disabled)$/i.test(value.trim()) : false;
|
|
7647
|
+
}
|
|
7648
|
+
function isExternalOrRootPath(value) {
|
|
7649
|
+
return /^(https?:)?\/\//i.test(value) || value.startsWith("/");
|
|
7650
|
+
}
|
|
7651
|
+
function isFarmDocsSocialImageEnabled(page2, docs) {
|
|
7652
|
+
if (docs.config.socialImage === false || getSocialImageConfig(docs)?.enabled === false) {
|
|
7653
|
+
return false;
|
|
7654
|
+
}
|
|
7655
|
+
return !isFalse(page2.frontmatter.socialImage);
|
|
7656
|
+
}
|
|
7657
|
+
function getFarmDocsCustomSocialImage(page2) {
|
|
7658
|
+
const value = page2.frontmatter.socialImage || page2.frontmatter.openGraphImage || page2.frontmatter.ogImage;
|
|
7659
|
+
return value && !isFalse(value) && isExternalOrRootPath(value) ? value : void 0;
|
|
7660
|
+
}
|
|
7661
|
+
function resolveIllustration(page2) {
|
|
7662
|
+
const explicit = page2.frontmatter.socialIllustration?.toLowerCase();
|
|
7663
|
+
if (explicit === "auth" || explicit === "cache" || explicit === "cli" || explicit === "integrations" || explicit === "project" || explicit === "routing" || explicit === "runtime") {
|
|
7664
|
+
return explicit;
|
|
7665
|
+
}
|
|
7666
|
+
const source = `${page2.slug} ${page2.title} ${page2.section || ""}`.toLowerCase();
|
|
7667
|
+
if (/auth|session|security|csrf/.test(source)) return "auth";
|
|
7668
|
+
if (/cache|ppr|render|static|revalid|stream/.test(source)) return "cache";
|
|
7669
|
+
if (/integration|stripe|prisma|better.auth|email|job|workflow/.test(source)) {
|
|
7670
|
+
return "integrations";
|
|
7671
|
+
}
|
|
7672
|
+
if (/cli|test|deploy|preview|upgrade|migration|install/.test(source)) return "cli";
|
|
7673
|
+
if (/project|structure|config|environment|markdown|docs.engine/.test(source)) {
|
|
7674
|
+
return "project";
|
|
7675
|
+
}
|
|
7676
|
+
if (/rout|endpoint|middleware|navigation|server.function|server.action|api/.test(source)) {
|
|
7677
|
+
return "routing";
|
|
7678
|
+
}
|
|
7679
|
+
return "runtime";
|
|
7680
|
+
}
|
|
7681
|
+
function createHashValue(value) {
|
|
7682
|
+
return (0, import_node_crypto4.createHash)("sha256").update(JSON.stringify(value)).digest("hex").slice(0, 16);
|
|
7683
|
+
}
|
|
7684
|
+
function resolveBaseUrl(requestUrl, config) {
|
|
7685
|
+
return config?.baseUrl ? new URL(config.baseUrl) : new URL(requestUrl.origin);
|
|
7686
|
+
}
|
|
7687
|
+
function createFarmDocsSocialImageDescriptor(page2, docs, requestUrl) {
|
|
7688
|
+
const config = getSocialImageConfig(docs);
|
|
7689
|
+
const siteName = config?.siteName || getNavTitle(docs);
|
|
7690
|
+
const brand = config?.brand || siteName;
|
|
7691
|
+
const title = page2.frontmatter.socialTitle || page2.title;
|
|
7692
|
+
const description = page2.frontmatter.socialDescription || page2.description || docs.config.metadata?.description || `Documentation for ${siteName}`;
|
|
7693
|
+
const section = page2.frontmatter.section || page2.section || "Documentation";
|
|
7694
|
+
const illustration = resolveIllustration(page2);
|
|
7695
|
+
const entry = normalizeEntry(docs.entry);
|
|
7696
|
+
const slugPath = encodeSlugPath(page2.slug) || "index";
|
|
7697
|
+
const imagePath = `${entry}/_social/${slugPath}/opengraph-image.svg`;
|
|
7698
|
+
const baseUrl = resolveBaseUrl(requestUrl, config);
|
|
7699
|
+
const pageUrl = new URL(page2.href, baseUrl).href;
|
|
7700
|
+
const imageAlt = `${title} \u2014 ${siteName} documentation`;
|
|
7701
|
+
const hash = createHashValue({
|
|
7702
|
+
version: FARM_DOCS_SOCIAL_IMAGE_VERSION,
|
|
7703
|
+
title,
|
|
7704
|
+
description,
|
|
7705
|
+
section,
|
|
7706
|
+
siteName,
|
|
7707
|
+
brand,
|
|
7708
|
+
pageHref: page2.href,
|
|
7709
|
+
illustration,
|
|
7710
|
+
fonts: config?.fonts
|
|
7711
|
+
});
|
|
7712
|
+
return {
|
|
7713
|
+
title,
|
|
7714
|
+
description,
|
|
7715
|
+
section,
|
|
7716
|
+
siteName,
|
|
7717
|
+
brand,
|
|
7718
|
+
pageHref: page2.href,
|
|
7719
|
+
pageUrl,
|
|
7720
|
+
imagePath,
|
|
7721
|
+
imageUrl: new URL(`${imagePath}?v=${hash}`, baseUrl).href,
|
|
7722
|
+
imageAlt,
|
|
7723
|
+
illustration,
|
|
7724
|
+
fonts: config?.fonts,
|
|
7725
|
+
hash
|
|
7726
|
+
};
|
|
7727
|
+
}
|
|
7728
|
+
function getFarmDocsSocialImageSlug(docs, requestUrl) {
|
|
7729
|
+
const entry = normalizeEntry(docs.entry);
|
|
7730
|
+
const prefix = `${entry}/_social/`;
|
|
7731
|
+
const suffix = "/opengraph-image.svg";
|
|
7732
|
+
if (!requestUrl.pathname.startsWith(prefix) || !requestUrl.pathname.endsWith(suffix)) {
|
|
7733
|
+
return null;
|
|
7734
|
+
}
|
|
7735
|
+
const rawSlug = requestUrl.pathname.slice(prefix.length, -suffix.length);
|
|
7736
|
+
if (!rawSlug) return null;
|
|
7737
|
+
try {
|
|
7738
|
+
const slug = rawSlug.split("/").map((segment) => decodeURIComponent(segment)).join("/");
|
|
7739
|
+
if (slug.split("/").some((segment) => !segment || segment === ".." || segment === ".")) {
|
|
7740
|
+
return null;
|
|
7741
|
+
}
|
|
7742
|
+
return slug === "index" ? "" : slug;
|
|
7743
|
+
} catch {
|
|
7744
|
+
return null;
|
|
7745
|
+
}
|
|
7746
|
+
}
|
|
7747
|
+
function escapeXml(value) {
|
|
7748
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
7749
|
+
}
|
|
7750
|
+
function truncate(value, length) {
|
|
7751
|
+
if (value.length <= length) return value;
|
|
7752
|
+
return `${value.slice(0, Math.max(0, length - 1)).trimEnd()}\u2026`;
|
|
7753
|
+
}
|
|
7754
|
+
function wrapText(value, maxCharacters, maxLines) {
|
|
7755
|
+
const words = value.trim().split(/\s+/).filter(Boolean);
|
|
7756
|
+
const lines = [];
|
|
7757
|
+
let current = "";
|
|
7758
|
+
let consumedWords = 0;
|
|
7759
|
+
for (const word of words) {
|
|
7760
|
+
const candidate = current ? `${current} ${word}` : word;
|
|
7761
|
+
if (candidate.length <= maxCharacters || !current) {
|
|
7762
|
+
current = candidate;
|
|
7763
|
+
consumedWords += 1;
|
|
7764
|
+
continue;
|
|
7765
|
+
}
|
|
7766
|
+
lines.push(current);
|
|
7767
|
+
if (lines.length === maxLines) break;
|
|
7768
|
+
current = word;
|
|
7769
|
+
consumedWords += 1;
|
|
7770
|
+
}
|
|
7771
|
+
if (current && lines.length < maxLines) lines.push(current);
|
|
7772
|
+
if (consumedWords < words.length && lines.length) {
|
|
7773
|
+
lines[lines.length - 1] = truncate(`${lines[lines.length - 1]}\u2026`, maxCharacters);
|
|
7774
|
+
}
|
|
7775
|
+
return lines;
|
|
7776
|
+
}
|
|
7777
|
+
function renderTextLines(lines, x, y, lineHeight, attributes) {
|
|
7778
|
+
return lines.map(
|
|
7779
|
+
(line, index) => `<text x="${x}" y="${y + index * lineHeight}" ${attributes}>${escapeXml(line)}</text>`
|
|
7780
|
+
).join("");
|
|
7781
|
+
}
|
|
7782
|
+
function renderEmbeddedFont(name, source, weight) {
|
|
7783
|
+
if (!source) return "";
|
|
7784
|
+
return `@font-face{font-family:"${name}";src:url("${escapeXml(source)}") format("woff2");font-style:normal;font-weight:${weight};font-display:block;}`;
|
|
7785
|
+
}
|
|
7786
|
+
function renderArrow(x1, y, x2, color = "#8b8b8b") {
|
|
7787
|
+
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}"/>`;
|
|
7788
|
+
}
|
|
7789
|
+
function renderPanelHeader(label, status) {
|
|
7790
|
+
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>`;
|
|
7791
|
+
}
|
|
7792
|
+
function renderRoutingIllustration() {
|
|
7793
|
+
return `${renderPanelHeader("ROUTE BLUEPRINT", "TYPED")}
|
|
7794
|
+
<rect x="819" y="296" width="92" height="54" fill="#a3a3a3"/>
|
|
7795
|
+
<text x="832" y="327" class="diagram-title ink">src/app</text>
|
|
7796
|
+
<path d="M911 323h41M952 232v181M952 232h44M952 323h44M952 413h44" fill="none" stroke="#696969"/>
|
|
7797
|
+
<rect x="996" y="205" width="138" height="54" fill="#0a0a0a" stroke="#414141"/>
|
|
7798
|
+
<text x="1010" y="228" class="diagram-title">/</text><text x="1010" y="246" class="micro">STATIC</text>
|
|
7799
|
+
<rect x="996" y="296" width="138" height="54" fill="#0a0a0a" stroke="#414141"/>
|
|
7800
|
+
<text x="1010" y="319" class="diagram-title">/blog/:slug</text><text x="1010" y="337" class="micro">DYNAMIC</text>
|
|
7801
|
+
<rect x="996" y="386" width="138" height="55" fill="#f0f0f0"/>
|
|
7802
|
+
<text x="1010" y="410" class="diagram-title ink">/docs/:path*</text><text x="1010" y="428" class="micro ink-muted">CATCH-ALL</text>
|
|
7803
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
7804
|
+
<text x="819" y="475" class="label bright">FILE ROUTES</text><text x="1134" y="475" class="label" text-anchor="end">TYPES INCLUDED</text>`;
|
|
7805
|
+
}
|
|
7806
|
+
function renderAuthIllustration() {
|
|
7807
|
+
return `${renderPanelHeader("REQUEST GUARD", "SERVER VERIFIED")}
|
|
7808
|
+
<rect x="819" y="269" width="86" height="54" fill="#0a0a0a" stroke="#454545"/>
|
|
7809
|
+
<text x="837" y="292" class="micro bright">REQUEST</text><text x="837" y="310" class="diagram-title">GET /app</text>
|
|
7810
|
+
${renderArrow(905, 296, 943)}
|
|
7811
|
+
<rect x="943" y="224" width="104" height="118" fill="#f0f0f0"/>
|
|
7812
|
+
<path d="M974 271v-12a21 21 0 0 1 42 0v12M968 271h54v45h-54z" fill="#050505"/>
|
|
7813
|
+
<circle cx="995" cy="292" r="4" fill="#f0f0f0"/><path d="M995 296v8" stroke="#f0f0f0" stroke-width="3"/>
|
|
7814
|
+
<text x="995" y="332" class="micro ink" text-anchor="middle">auth()</text>
|
|
7815
|
+
${renderArrow(1047, 296, 1071)}
|
|
7816
|
+
<rect x="1071" y="269" width="63" height="54" fill="#0a0a0a" stroke="#454545"/>
|
|
7817
|
+
<text x="1082" y="292" class="micro bright">ALLOW</text><text x="1082" y="310" class="micro">/app</text>
|
|
7818
|
+
<rect x="819" y="372" width="315" height="38" fill="#090909" stroke="#3d3d3d"/>
|
|
7819
|
+
<rect x="832" y="385" width="11" height="11" fill="#a3a3a3"/>
|
|
7820
|
+
<text x="856" y="395" class="code">session.user / verified</text>
|
|
7821
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
7822
|
+
<text x="819" y="475" class="label bright">SESSION TYPED</text><text x="1134" y="475" class="label" text-anchor="end">CSRF PROTECTED</text>`;
|
|
7823
|
+
}
|
|
7824
|
+
function renderCacheIllustration() {
|
|
7825
|
+
return `${renderPanelHeader("PAGE / PRODUCT", "CACHE + PPR")}
|
|
7826
|
+
<rect x="819" y="204" width="315" height="54" fill="#f0f0f0"/>
|
|
7827
|
+
<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>
|
|
7828
|
+
<rect x="819" y="271" width="198" height="76" fill="#a3a3a3"/>
|
|
7829
|
+
<text x="836" y="301" class="diagram-title ink">CACHED DATA</text><text x="836" y="326" class="micro ink-muted">tag: products</text>
|
|
7830
|
+
<rect x="1029" y="271" width="105" height="76" fill="#0a0a0a" stroke="#555"/>
|
|
7831
|
+
<text x="1045" y="301" class="diagram-title">LIVE</text><text x="1045" y="326" class="micro">stream</text>
|
|
7832
|
+
<path d="M1081 347v43m-8-9 8 9 8-9" fill="none" stroke="#d4d4d4"/>
|
|
7833
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
7834
|
+
<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>`;
|
|
7835
|
+
}
|
|
7836
|
+
function renderIntegrationsIllustration() {
|
|
7837
|
+
return `${renderPanelHeader("INTEGRATION GRAPH", "ONE PRODUCT")}
|
|
7838
|
+
<path d="M976 309H879V247M976 309H879v87M1030 309h93V247M1030 309h93v87" fill="none" stroke="#4a4a4a"/>
|
|
7839
|
+
<rect x="819" y="214" width="120" height="57" fill="#0a0a0a" stroke="#4b4b4b"/><text x="839" y="247" class="diagram-title">BETTER AUTH</text>
|
|
7840
|
+
<rect x="819" y="368" width="120" height="57" fill="#0a0a0a" stroke="#4b4b4b"/><text x="851" y="401" class="diagram-title">PRISMA</text>
|
|
7841
|
+
<rect x="1061" y="214" width="73" height="57" fill="#0a0a0a" stroke="#4b4b4b"/><text x="1077" y="247" class="diagram-title">STRIPE</text>
|
|
7842
|
+
<rect x="1061" y="368" width="73" height="57" fill="#a3a3a3"/><text x="1075" y="401" class="diagram-title ink">VERCEL</text>
|
|
7843
|
+
<rect x="976" y="277" width="94" height="64" fill="#f0f0f0"/>
|
|
7844
|
+
<text x="994" y="304" class="diagram-title ink">FARM.JS</text><text x="994" y="324" class="micro ink-muted">CORE</text>
|
|
7845
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
7846
|
+
<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>`;
|
|
7847
|
+
}
|
|
7848
|
+
function renderCliIllustration() {
|
|
7849
|
+
return `${renderPanelHeader("TERMINAL", "PRODUCTION OUTPUT")}
|
|
7850
|
+
<rect x="819" y="203" width="315" height="213" fill="#050505" stroke="#555"/>
|
|
7851
|
+
<line x1="819" y1="236" x2="1134" y2="236" stroke="#555"/>
|
|
7852
|
+
<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"/>
|
|
7853
|
+
<text x="837" y="273" class="code bright"><tspan fill="#7a7a7a">$</tspan> farm build</text>
|
|
7854
|
+
<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"/>
|
|
7855
|
+
<text x="861" y="303" class="code">64 routes discovered</text>
|
|
7856
|
+
<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"/>
|
|
7857
|
+
<text x="861" y="330" class="code">client + server bundles</text>
|
|
7858
|
+
<rect x="837" y="355" width="126" height="30" fill="#f0f0f0"/><text x="853" y="374" class="micro ink">BUILD COMPLETE</text>
|
|
7859
|
+
<text x="1115" y="374" class="micro" text-anchor="end">/dist</text>
|
|
7860
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
7861
|
+
<text x="819" y="475" class="label bright">REAL COMMANDS</text><text x="1134" y="475" class="label" text-anchor="end">842MS</text>`;
|
|
7862
|
+
}
|
|
7863
|
+
function renderProjectIllustration() {
|
|
7864
|
+
return `${renderPanelHeader("PROJECT MAP", "CONVENTION TYPED")}
|
|
7865
|
+
<rect x="819" y="202" width="315" height="216" fill="#050505" stroke="#555"/>
|
|
7866
|
+
<text x="837" y="227" class="diagram-title bright">my-app/</text>
|
|
7867
|
+
<path d="M847 243v143M847 259h23M847 293h23M847 327h23M847 361h23" fill="none" stroke="#666"/>
|
|
7868
|
+
<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>
|
|
7869
|
+
<rect x="870" y="277" width="246" height="33" fill="#f0f0f0"/><text x="886" y="298" class="code ink">src/app/page.tsx</text>
|
|
7870
|
+
<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>
|
|
7871
|
+
<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>
|
|
7872
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
7873
|
+
<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>`;
|
|
7874
|
+
}
|
|
7875
|
+
function renderRuntimeIllustration() {
|
|
7876
|
+
return `${renderPanelHeader("PRODUCT ARCHITECTURE", "FULL STACK")}
|
|
7877
|
+
<rect x="819" y="211" width="315" height="55" fill="#f0f0f0"/>
|
|
7878
|
+
<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>
|
|
7879
|
+
<path d="M976 266v20m0 61v20" stroke="#727272"/>
|
|
7880
|
+
<rect x="855" y="286" width="242" height="61" fill="#a3a3a3"/>
|
|
7881
|
+
<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>
|
|
7882
|
+
<rect x="819" y="367" width="315" height="55" fill="#4c4c4c"/>
|
|
7883
|
+
<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>
|
|
7884
|
+
<line x1="819" y1="450" x2="1134" y2="450" stroke="#343434"/>
|
|
7885
|
+
<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>`;
|
|
7886
|
+
}
|
|
7887
|
+
function renderIllustration(type) {
|
|
7888
|
+
switch (type) {
|
|
7889
|
+
case "auth":
|
|
7890
|
+
return renderAuthIllustration();
|
|
7891
|
+
case "cache":
|
|
7892
|
+
return renderCacheIllustration();
|
|
7893
|
+
case "cli":
|
|
7894
|
+
return renderCliIllustration();
|
|
7895
|
+
case "integrations":
|
|
7896
|
+
return renderIntegrationsIllustration();
|
|
7897
|
+
case "project":
|
|
7898
|
+
return renderProjectIllustration();
|
|
7899
|
+
case "routing":
|
|
7900
|
+
return renderRoutingIllustration();
|
|
7901
|
+
default:
|
|
7902
|
+
return renderRuntimeIllustration();
|
|
7903
|
+
}
|
|
7904
|
+
}
|
|
7905
|
+
function renderFarmDocsSocialImageSvg(descriptor) {
|
|
7906
|
+
const titleLines = wrapText(descriptor.title, 22, 2);
|
|
7907
|
+
const longestTitleLine = Math.max(...titleLines.map((line) => line.length));
|
|
7908
|
+
const titleSize = titleLines.length === 1 ? longestTitleLine > 17 ? 62 : 74 : 56;
|
|
7909
|
+
const titleLineHeight = Math.round(titleSize * 0.98);
|
|
7910
|
+
const titleY = titleLines.length === 1 ? 294 : 266;
|
|
7911
|
+
const descriptionY = titleY + (titleLines.length - 1) * titleLineHeight + 59;
|
|
7912
|
+
const descriptionLines = wrapText(descriptor.description, 68, 2);
|
|
7913
|
+
const routeY = Math.max(418, descriptionY + descriptionLines.length * 29 + 24);
|
|
7914
|
+
const section = truncate(descriptor.section.toUpperCase(), 27);
|
|
7915
|
+
const route = truncate(descriptor.pageHref, 42);
|
|
7916
|
+
const footerUrl = truncate(descriptor.pageUrl.replace(/^https?:\/\//, ""), 70);
|
|
7917
|
+
const brand = truncate(descriptor.brand.toUpperCase(), 25);
|
|
7918
|
+
const titleId = `farm-docs-og-${descriptor.hash}`;
|
|
7919
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
7920
|
+
<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">
|
|
7921
|
+
<title id="${titleId}-title">${escapeXml(descriptor.imageAlt)}</title>
|
|
7922
|
+
<desc id="${titleId}-description">${escapeXml(descriptor.description)}</desc>
|
|
7923
|
+
<metadata>${escapeXml(JSON.stringify({ generator: "Farm.js docs", page: descriptor.pageUrl, illustration: descriptor.illustration }))}</metadata>
|
|
7924
|
+
<style type="text/css">
|
|
7925
|
+
${renderEmbeddedFont("Farm Sans", descriptor.fonts?.sans, "100 900")}
|
|
7926
|
+
${renderEmbeddedFont("Farm Mono", descriptor.fonts?.mono, "100 900")}
|
|
7927
|
+
${renderEmbeddedFont("Farm Pixel", descriptor.fonts?.display, "400 700")}
|
|
7928
|
+
.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}
|
|
7929
|
+
</style>
|
|
7930
|
+
<defs>
|
|
7931
|
+
<pattern id="canvas-grid" width="40" height="40" patternUnits="userSpaceOnUse"><path d="M40 0H0V40" fill="none" stroke="#151515"/></pattern>
|
|
7932
|
+
<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>
|
|
7933
|
+
<clipPath id="frame-clip"><rect x="28" y="28" width="1144" height="574"/></clipPath>
|
|
7934
|
+
</defs>
|
|
7935
|
+
<rect width="1200" height="630" fill="#050505"/>
|
|
7936
|
+
<rect width="1200" height="630" fill="url(#canvas-grid)"/>
|
|
7937
|
+
<g clip-path="url(#frame-clip)">
|
|
7938
|
+
<rect x="28" y="28" width="1144" height="574" fill="#020202"/>
|
|
7939
|
+
<rect x="782" y="114" width="390" height="411" fill="url(#diagonal)"/>
|
|
7940
|
+
</g>
|
|
7941
|
+
<rect x="28.5" y="28.5" width="1143" height="573" fill="none" stroke="#323232"/>
|
|
7942
|
+
<path d="M28 114.5h1144M28 525.5h1144M781.5 114v411" fill="none" stroke="#303030"/>
|
|
7943
|
+
|
|
7944
|
+
<g transform="translate(71 51)">
|
|
7945
|
+
<rect width="11" height="11" rx="1" fill="#f5f5f4"/><rect x="15" width="28" height="11" rx="1" fill="#f5f5f4"/>
|
|
7946
|
+
<rect y="15" width="11" height="11" rx="1" fill="#9b9b9b"/><rect x="15" y="15" width="28" height="11" rx="1" fill="#9b9b9b"/>
|
|
7947
|
+
<rect y="30" width="11" height="11" rx="1" fill="#5f5f5f"/><rect x="15" y="30" width="20" height="11" rx="1" fill="#5f5f5f"/>
|
|
7948
|
+
<text x="61" y="24" class="mono bright" font-size="24" font-weight="550">FARM<tspan fill="#777">.JS</tspan></text>
|
|
7949
|
+
<text x="61" y="43" class="label">BY FARMING LABS</text>
|
|
7950
|
+
</g>
|
|
7951
|
+
<text x="1134" y="72" class="label" text-anchor="end">${escapeXml(brand)} \xB7 DOCUMENTATION</text>
|
|
7952
|
+
|
|
7953
|
+
<text x="71" y="198" class="mono bright" font-size="13" font-weight="650">DOCS</text>
|
|
7954
|
+
<line x1="117" y1="193" x2="155" y2="193" stroke="#696969"/>
|
|
7955
|
+
<text x="166" y="198" class="mono" fill="#9b9b9b" font-size="13">${escapeXml(section)}</text>
|
|
7956
|
+
${renderTextLines(titleLines, 71, titleY, titleLineHeight, `class="pixel bright" font-size="${titleSize}" font-weight="500" letter-spacing="-2.4"`)}
|
|
7957
|
+
${renderTextLines(descriptionLines, 71, descriptionY, 29, 'class="sans" fill="#a3a3a3" font-size="20" font-weight="430" letter-spacing="-.3"')}
|
|
7958
|
+
<rect x="71" y="${routeY}" width="${Math.min(390, 56 + route.length * 8)}" height="36" fill="#050505" stroke="#3c3c3c"/>
|
|
7959
|
+
<text x="85" y="${routeY + 23}" class="mono bright" font-size="11" font-weight="600">GET</text>
|
|
7960
|
+
<text x="119" y="${routeY + 23}" class="mono" fill="#898989" font-size="11">${escapeXml(route)}</text>
|
|
7961
|
+
|
|
7962
|
+
${renderIllustration(descriptor.illustration)}
|
|
7963
|
+
|
|
7964
|
+
<text x="71" y="570" class="mono bright" font-size="13" font-weight="550">${escapeXml(footerUrl)}</text>
|
|
7965
|
+
<text x="1134" y="570" class="mono" fill="#9b9b9b" font-size="12" text-anchor="end">FARM.JS DOCUMENTATION</text>
|
|
7966
|
+
<path d="M20 20h10M20 20v10M1180 20h-10M1180 20v10M20 610h10M20 610v-10M1180 610h-10M1180 610v-10" fill="none" stroke="#9b9b9b"/>
|
|
7967
|
+
</svg>`;
|
|
7968
|
+
}
|
|
7969
|
+
function renderFarmDocsSocialMetadata(descriptor, customImage) {
|
|
7970
|
+
const imageUrl = customImage ? new URL(customImage, descriptor.pageUrl).href : descriptor.imageUrl;
|
|
7971
|
+
const customExtension = customImage?.toLowerCase().split(/[?#]/, 1)[0];
|
|
7972
|
+
const imageType = customExtension?.endsWith(".webp") ? "image/webp" : customExtension?.endsWith(".png") ? "image/png" : customExtension?.match(/\.jpe?g$/) ? "image/jpeg" : "image/svg+xml";
|
|
7973
|
+
const tag = /* @__PURE__ */ __name((property, content, name = false) => `<meta ${name ? "name" : "property"}="${property}" content="${escapeXml(content)}">`, "tag");
|
|
7974
|
+
return [
|
|
7975
|
+
tag("og:type", "article"),
|
|
7976
|
+
tag("og:site_name", descriptor.siteName),
|
|
7977
|
+
tag("og:title", descriptor.title),
|
|
7978
|
+
tag("og:description", descriptor.description),
|
|
7979
|
+
tag("og:url", descriptor.pageUrl),
|
|
7980
|
+
tag("og:image", imageUrl),
|
|
7981
|
+
tag("og:image:type", imageType),
|
|
7982
|
+
...customImage ? [] : [
|
|
7983
|
+
tag("og:image:width", String(FARM_DOCS_SOCIAL_IMAGE_WIDTH)),
|
|
7984
|
+
tag("og:image:height", String(FARM_DOCS_SOCIAL_IMAGE_HEIGHT))
|
|
7985
|
+
],
|
|
7986
|
+
tag("og:image:alt", descriptor.imageAlt),
|
|
7987
|
+
tag("twitter:card", "summary_large_image", true),
|
|
7988
|
+
tag("twitter:title", descriptor.title, true),
|
|
7989
|
+
tag("twitter:description", descriptor.description, true),
|
|
7990
|
+
tag("twitter:image", imageUrl, true),
|
|
7991
|
+
tag("twitter:image:alt", descriptor.imageAlt, true)
|
|
7992
|
+
].join("\n ");
|
|
7993
|
+
}
|
|
7994
|
+
var import_node_crypto4, FARM_DOCS_SOCIAL_IMAGE_WIDTH, FARM_DOCS_SOCIAL_IMAGE_HEIGHT, FARM_DOCS_SOCIAL_IMAGE_VERSION;
|
|
7995
|
+
var init_social_image = __esm({
|
|
7996
|
+
"src/docs/social-image.ts"() {
|
|
7997
|
+
"use strict";
|
|
7998
|
+
import_node_crypto4 = require("crypto");
|
|
7999
|
+
FARM_DOCS_SOCIAL_IMAGE_WIDTH = 1200;
|
|
8000
|
+
FARM_DOCS_SOCIAL_IMAGE_HEIGHT = 630;
|
|
8001
|
+
FARM_DOCS_SOCIAL_IMAGE_VERSION = 3;
|
|
8002
|
+
__name(normalizeEntry, "normalizeEntry");
|
|
8003
|
+
__name(encodeSlugPath, "encodeSlugPath");
|
|
8004
|
+
__name(getSocialImageConfig, "getSocialImageConfig");
|
|
8005
|
+
__name(getNavTitle, "getNavTitle");
|
|
8006
|
+
__name(isFalse, "isFalse");
|
|
8007
|
+
__name(isExternalOrRootPath, "isExternalOrRootPath");
|
|
8008
|
+
__name(isFarmDocsSocialImageEnabled, "isFarmDocsSocialImageEnabled");
|
|
8009
|
+
__name(getFarmDocsCustomSocialImage, "getFarmDocsCustomSocialImage");
|
|
8010
|
+
__name(resolveIllustration, "resolveIllustration");
|
|
8011
|
+
__name(createHashValue, "createHashValue");
|
|
8012
|
+
__name(resolveBaseUrl, "resolveBaseUrl");
|
|
8013
|
+
__name(createFarmDocsSocialImageDescriptor, "createFarmDocsSocialImageDescriptor");
|
|
8014
|
+
__name(getFarmDocsSocialImageSlug, "getFarmDocsSocialImageSlug");
|
|
8015
|
+
__name(escapeXml, "escapeXml");
|
|
8016
|
+
__name(truncate, "truncate");
|
|
8017
|
+
__name(wrapText, "wrapText");
|
|
8018
|
+
__name(renderTextLines, "renderTextLines");
|
|
8019
|
+
__name(renderEmbeddedFont, "renderEmbeddedFont");
|
|
8020
|
+
__name(renderArrow, "renderArrow");
|
|
8021
|
+
__name(renderPanelHeader, "renderPanelHeader");
|
|
8022
|
+
__name(renderRoutingIllustration, "renderRoutingIllustration");
|
|
8023
|
+
__name(renderAuthIllustration, "renderAuthIllustration");
|
|
8024
|
+
__name(renderCacheIllustration, "renderCacheIllustration");
|
|
8025
|
+
__name(renderIntegrationsIllustration, "renderIntegrationsIllustration");
|
|
8026
|
+
__name(renderCliIllustration, "renderCliIllustration");
|
|
8027
|
+
__name(renderProjectIllustration, "renderProjectIllustration");
|
|
8028
|
+
__name(renderRuntimeIllustration, "renderRuntimeIllustration");
|
|
8029
|
+
__name(renderIllustration, "renderIllustration");
|
|
8030
|
+
__name(renderFarmDocsSocialImageSvg, "renderFarmDocsSocialImageSvg");
|
|
8031
|
+
__name(renderFarmDocsSocialMetadata, "renderFarmDocsSocialMetadata");
|
|
8032
|
+
}
|
|
8033
|
+
});
|
|
8034
|
+
|
|
7580
8035
|
// src/docs/handler.ts
|
|
7581
8036
|
function trimSlashes2(value) {
|
|
7582
8037
|
return value.replace(/^\/+|\/+$/g, "");
|
|
7583
8038
|
}
|
|
7584
|
-
function
|
|
8039
|
+
function normalizeEntry2(entry) {
|
|
7585
8040
|
if (!entry || entry === "/") return "/";
|
|
7586
8041
|
return `/${trimSlashes2(entry)}`;
|
|
7587
8042
|
}
|
|
@@ -7593,10 +8048,10 @@ function resolveFarmDocsFavicon(docs, options) {
|
|
|
7593
8048
|
if (typeof configuredFavicon === "string" && configuredFavicon.trim()) {
|
|
7594
8049
|
return configuredFavicon.trim();
|
|
7595
8050
|
}
|
|
7596
|
-
const publicDir =
|
|
8051
|
+
const publicDir = import_node_path13.default.join(import_node_path13.default.resolve(options.root), "public");
|
|
7597
8052
|
for (const fileName of FARM_DOCS_FAVICON_FILES) {
|
|
7598
|
-
const faviconPath =
|
|
7599
|
-
if ((0,
|
|
8053
|
+
const faviconPath = import_node_path13.default.join(publicDir, fileName);
|
|
8054
|
+
if ((0, import_node_fs9.existsSync)(faviconPath) && (0, import_node_fs9.statSync)(faviconPath).isFile()) {
|
|
7600
8055
|
return `/${fileName}`;
|
|
7601
8056
|
}
|
|
7602
8057
|
}
|
|
@@ -7630,10 +8085,10 @@ function isSafeSegment(segment) {
|
|
|
7630
8085
|
return segment !== ".." && !segment.includes("/") && !segment.includes("\\");
|
|
7631
8086
|
}
|
|
7632
8087
|
function resolveInside(root, target) {
|
|
7633
|
-
const resolvedRoot =
|
|
7634
|
-
const resolvedTarget =
|
|
7635
|
-
const relative4 =
|
|
7636
|
-
if (relative4 === "" || !relative4.startsWith("..") && !
|
|
8088
|
+
const resolvedRoot = import_node_path13.default.resolve(root);
|
|
8089
|
+
const resolvedTarget = import_node_path13.default.resolve(target);
|
|
8090
|
+
const relative4 = import_node_path13.default.relative(resolvedRoot, resolvedTarget);
|
|
8091
|
+
if (relative4 === "" || !relative4.startsWith("..") && !import_node_path13.default.isAbsolute(relative4)) {
|
|
7637
8092
|
return resolvedTarget;
|
|
7638
8093
|
}
|
|
7639
8094
|
return null;
|
|
@@ -7642,36 +8097,36 @@ function isFarmDocsRequest(docs, request) {
|
|
|
7642
8097
|
if (!docs?.enabled) return false;
|
|
7643
8098
|
if (request.method !== "GET" && request.method !== "HEAD") return false;
|
|
7644
8099
|
const pathname = new URL(request.url).pathname;
|
|
7645
|
-
const entry =
|
|
8100
|
+
const entry = normalizeEntry2(docs.entry);
|
|
7646
8101
|
if (entry === "/") return true;
|
|
7647
8102
|
return pathname === entry || pathname === `${entry}.md` || pathname.startsWith(`${entry}/`);
|
|
7648
8103
|
}
|
|
7649
8104
|
function resolveFarmDocsContentDir(docs, options) {
|
|
7650
|
-
const root =
|
|
8105
|
+
const root = import_node_path13.default.resolve(options.root);
|
|
7651
8106
|
const srcDir = options.srcDir || "src";
|
|
7652
8107
|
const configuredContentDir = docs.contentDir || docs.config.contentDir;
|
|
7653
8108
|
if (configuredContentDir) {
|
|
7654
|
-
return
|
|
8109
|
+
return import_node_path13.default.isAbsolute(configuredContentDir) ? configuredContentDir : import_node_path13.default.join(root, configuredContentDir);
|
|
7655
8110
|
}
|
|
7656
8111
|
const entryDir = docs.config.entry || trimSlashes2(docs.entry) || "docs";
|
|
7657
|
-
const appDocsDir =
|
|
7658
|
-
if ((0,
|
|
7659
|
-
return
|
|
8112
|
+
const appDocsDir = import_node_path13.default.join(root, srcDir, "app", entryDir);
|
|
8113
|
+
if ((0, import_node_fs9.existsSync)(appDocsDir)) return appDocsDir;
|
|
8114
|
+
return import_node_path13.default.join(root, entryDir);
|
|
7660
8115
|
}
|
|
7661
8116
|
function getFarmDocsRouteTypeEntries(docs) {
|
|
7662
8117
|
if (!docs?.enabled) return [];
|
|
7663
|
-
const entry =
|
|
8118
|
+
const entry = normalizeEntry2(docs.entry);
|
|
7664
8119
|
if (entry === "/") return ["/", "/[...docs]"];
|
|
7665
8120
|
return [entry, `${entry}/[...docs]`];
|
|
7666
8121
|
}
|
|
7667
8122
|
function getFarmDocsDocumentNavigationMatchers(docs) {
|
|
7668
8123
|
if (!docs?.enabled) return [];
|
|
7669
|
-
const entry =
|
|
8124
|
+
const entry = normalizeEntry2(docs.entry);
|
|
7670
8125
|
return [entry === "/" ? "/(.*)" : `${entry}(.*)`];
|
|
7671
8126
|
}
|
|
7672
8127
|
function getRequestSlug(docs, request) {
|
|
7673
8128
|
const pathname = new URL(request.url).pathname;
|
|
7674
|
-
const entry =
|
|
8129
|
+
const entry = normalizeEntry2(docs.entry);
|
|
7675
8130
|
if (entry === "/") return normalizeSlug(pathname);
|
|
7676
8131
|
if (pathname === entry || pathname === `${entry}.md`) return "";
|
|
7677
8132
|
return normalizeSlug(pathname.slice(entry.length));
|
|
@@ -7679,14 +8134,14 @@ function getRequestSlug(docs, request) {
|
|
|
7679
8134
|
function findDocsPageFile(contentDir, slug) {
|
|
7680
8135
|
const segments = slug ? slug.split("/").filter(Boolean) : [];
|
|
7681
8136
|
if (!segments.every(isSafeSegment)) return null;
|
|
7682
|
-
const slugDir =
|
|
7683
|
-
const candidates = segments.length === 0 ? DOCS_FILE_NAMES.map((filename) =>
|
|
7684
|
-
...DOCS_FILE_NAMES.map((filename) =>
|
|
7685
|
-
...DOCS_FILE_EXTENSIONS2.map((extension) =>
|
|
8137
|
+
const slugDir = import_node_path13.default.join(contentDir, ...segments);
|
|
8138
|
+
const candidates = segments.length === 0 ? DOCS_FILE_NAMES.map((filename) => import_node_path13.default.join(contentDir, filename)) : [
|
|
8139
|
+
...DOCS_FILE_NAMES.map((filename) => import_node_path13.default.join(slugDir, filename)),
|
|
8140
|
+
...DOCS_FILE_EXTENSIONS2.map((extension) => import_node_path13.default.join(contentDir, `${slug}${extension}`))
|
|
7686
8141
|
];
|
|
7687
8142
|
for (const candidate of candidates) {
|
|
7688
8143
|
const safePath = resolveInside(contentDir, candidate);
|
|
7689
|
-
if (safePath && (0,
|
|
8144
|
+
if (safePath && (0, import_node_fs9.existsSync)(safePath) && (0, import_node_fs9.statSync)(safePath).isFile()) {
|
|
7690
8145
|
return safePath;
|
|
7691
8146
|
}
|
|
7692
8147
|
}
|
|
@@ -7721,7 +8176,7 @@ function titleFromMarkdown2(body, fallback) {
|
|
|
7721
8176
|
function loadFarmDocsPage(contentDir, docs, slug) {
|
|
7722
8177
|
const sourcePath = findDocsPageFile(contentDir, slug);
|
|
7723
8178
|
if (!sourcePath) return null;
|
|
7724
|
-
const source = (0,
|
|
8179
|
+
const source = (0, import_node_fs9.readFileSync)(sourcePath, "utf8");
|
|
7725
8180
|
const { frontmatter, body } = parseFrontmatter(source);
|
|
7726
8181
|
const title = frontmatter.title || titleFromMarkdown2(body, titleFromSlug(slug));
|
|
7727
8182
|
const href = createDocsHref(docs.entry, slug);
|
|
@@ -7729,6 +8184,7 @@ function loadFarmDocsPage(contentDir, docs, slug) {
|
|
|
7729
8184
|
slug,
|
|
7730
8185
|
title,
|
|
7731
8186
|
description: frontmatter.description,
|
|
8187
|
+
section: frontmatter.section,
|
|
7732
8188
|
href,
|
|
7733
8189
|
sourcePath,
|
|
7734
8190
|
lastModified: resolveFarmDocsPageLastModified(contentDir, sourcePath, frontmatter),
|
|
@@ -7737,15 +8193,15 @@ function loadFarmDocsPage(contentDir, docs, slug) {
|
|
|
7737
8193
|
};
|
|
7738
8194
|
}
|
|
7739
8195
|
function createDocsHref(entry, slug) {
|
|
7740
|
-
const normalizedEntry =
|
|
8196
|
+
const normalizedEntry = normalizeEntry2(entry);
|
|
7741
8197
|
const normalizedSlug = trimSlashes2(slug);
|
|
7742
8198
|
if (normalizedEntry === "/") return normalizedSlug ? `/${normalizedSlug}` : "/";
|
|
7743
8199
|
return normalizedSlug ? `${normalizedEntry}/${normalizedSlug}` : normalizedEntry;
|
|
7744
8200
|
}
|
|
7745
8201
|
function pathToSlug(contentDir, filePath) {
|
|
7746
|
-
const relative4 =
|
|
8202
|
+
const relative4 = import_node_path13.default.relative(contentDir, filePath).replace(/\\/g, "/");
|
|
7747
8203
|
if (relative4.startsWith("..")) return null;
|
|
7748
|
-
const extension =
|
|
8204
|
+
const extension = import_node_path13.default.extname(relative4);
|
|
7749
8205
|
if (!DOCS_FILE_EXTENSIONS2.includes(extension)) return null;
|
|
7750
8206
|
const withoutExtension = relative4.slice(0, -extension.length);
|
|
7751
8207
|
if (withoutExtension === "page" || withoutExtension === "index") return "";
|
|
@@ -7758,12 +8214,12 @@ function loadPage(contentDir, docs, request) {
|
|
|
7758
8214
|
return loadFarmDocsPage(contentDir, docs, getRequestSlug(docs, request));
|
|
7759
8215
|
}
|
|
7760
8216
|
function discoverFarmDocsPages(contentDir, docs) {
|
|
7761
|
-
if (!(0,
|
|
8217
|
+
if (!(0, import_node_fs9.existsSync)(contentDir)) return [];
|
|
7762
8218
|
const pages = [];
|
|
7763
8219
|
const visit = /* @__PURE__ */ __name((dir) => {
|
|
7764
|
-
for (const entry of (0,
|
|
8220
|
+
for (const entry of (0, import_node_fs9.readdirSync)(dir, { withFileTypes: true })) {
|
|
7765
8221
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
7766
|
-
const absolutePath =
|
|
8222
|
+
const absolutePath = import_node_path13.default.join(dir, entry.name);
|
|
7767
8223
|
if (entry.isDirectory()) {
|
|
7768
8224
|
visit(absolutePath);
|
|
7769
8225
|
continue;
|
|
@@ -7771,7 +8227,7 @@ function discoverFarmDocsPages(contentDir, docs) {
|
|
|
7771
8227
|
if (!entry.isFile()) continue;
|
|
7772
8228
|
const slug = pathToSlug(contentDir, absolutePath);
|
|
7773
8229
|
if (slug === null) continue;
|
|
7774
|
-
const source = (0,
|
|
8230
|
+
const source = (0, import_node_fs9.readFileSync)(absolutePath, "utf8");
|
|
7775
8231
|
const { frontmatter, body } = parseFrontmatter(source);
|
|
7776
8232
|
pages.push({
|
|
7777
8233
|
slug,
|
|
@@ -8549,7 +9005,7 @@ function renderPixelBreadcrumb(page2, docs) {
|
|
|
8549
9005
|
const parentSegments = segments.slice(0, -1);
|
|
8550
9006
|
const parentSegment = parentSegments[parentSegments.length - 1];
|
|
8551
9007
|
const currentSegment = segments[segments.length - 1];
|
|
8552
|
-
const entry =
|
|
9008
|
+
const entry = normalizeEntry2(docs.entry);
|
|
8553
9009
|
const parentPath = parentSegments.join("/");
|
|
8554
9010
|
const parentHref = entry === "/" ? `/${parentPath}` : `${entry}/${parentPath}`;
|
|
8555
9011
|
return `<nav class="fd-breadcrumb" aria-label="Breadcrumb">
|
|
@@ -8587,7 +9043,7 @@ ${items.map(
|
|
|
8587
9043
|
</div>`;
|
|
8588
9044
|
}
|
|
8589
9045
|
function renderDocsRuntimeScript(docs) {
|
|
8590
|
-
const docsEntry = JSON.stringify(
|
|
9046
|
+
const docsEntry = JSON.stringify(normalizeEntry2(docs.entry));
|
|
8591
9047
|
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>`;
|
|
8592
9048
|
}
|
|
8593
9049
|
function renderDocsPageActionsRuntimeScript() {
|
|
@@ -8602,13 +9058,13 @@ ${renderDocsHashRuntimeScript()}
|
|
|
8602
9058
|
${renderDocsPageActionsRuntimeScript()}`;
|
|
8603
9059
|
}
|
|
8604
9060
|
function readCssWithImports(filePath, seen = /* @__PURE__ */ new Set()) {
|
|
8605
|
-
const resolved =
|
|
9061
|
+
const resolved = import_node_path13.default.resolve(filePath);
|
|
8606
9062
|
if (seen.has(resolved)) return "";
|
|
8607
9063
|
seen.add(resolved);
|
|
8608
|
-
const source = (0,
|
|
9064
|
+
const source = (0, import_node_fs9.readFileSync)(resolved, "utf8");
|
|
8609
9065
|
return source.replace(/@import\s+["']([^"']+)["'];?/g, (_match, importPath) => {
|
|
8610
9066
|
try {
|
|
8611
|
-
const importedPath = importPath.startsWith(".") ?
|
|
9067
|
+
const importedPath = importPath.startsWith(".") ? import_node_path13.default.resolve(import_node_path13.default.dirname(resolved), importPath) : (0, import_node_module5.createRequire)(resolved).resolve(importPath);
|
|
8612
9068
|
return readCssWithImports(importedPath, seen);
|
|
8613
9069
|
} catch {
|
|
8614
9070
|
return "";
|
|
@@ -8616,11 +9072,11 @@ function readCssWithImports(filePath, seen = /* @__PURE__ */ new Set()) {
|
|
|
8616
9072
|
});
|
|
8617
9073
|
}
|
|
8618
9074
|
function resolvePixelBorderThemeCss(options) {
|
|
8619
|
-
const cacheKey =
|
|
9075
|
+
const cacheKey = import_node_path13.default.resolve(options.root);
|
|
8620
9076
|
const cached = themeCssCache.get(cacheKey);
|
|
8621
9077
|
if (cached !== void 0) return cached;
|
|
8622
9078
|
try {
|
|
8623
|
-
const requireFromApp = (0, import_node_module5.createRequire)(
|
|
9079
|
+
const requireFromApp = (0, import_node_module5.createRequire)(import_node_path13.default.join(cacheKey, "package.json"));
|
|
8624
9080
|
const themeCssPath = requireFromApp.resolve("@farming-labs/theme/pixel-border/css");
|
|
8625
9081
|
const requireFromTheme = (0, import_node_module5.createRequire)(themeCssPath);
|
|
8626
9082
|
const fumadocsCssPath = requireFromTheme.resolve("fumadocs-ui/style.css");
|
|
@@ -8633,17 +9089,28 @@ ${readCssWithImports(themeCssPath)}`;
|
|
|
8633
9089
|
return "";
|
|
8634
9090
|
}
|
|
8635
9091
|
}
|
|
8636
|
-
function renderFarmDocsBridgeCss(docs) {
|
|
9092
|
+
function renderFarmDocsBridgeCss(docs, fontAssets, layoutFonts) {
|
|
8637
9093
|
const sidebarWidth = getThemeLayoutValue(docs, "sidebarWidth", 320);
|
|
8638
9094
|
const contentWidth = getThemeLayoutValue(docs, "contentWidth", 860);
|
|
9095
|
+
const fontFaces = fontAssets.map(
|
|
9096
|
+
({ family, url }) => `@font-face { font-family: "${family}"; src: url("${url}") format("woff2"); font-style: normal; font-weight: 100 900; font-display: block; }`
|
|
9097
|
+
).join("\n");
|
|
9098
|
+
const fontVariables = [
|
|
9099
|
+
fontAssets.some(({ family }) => family === "Geist Sans") ? '--font-geist-sans: "Geist Sans", ui-sans-serif, system-ui, sans-serif;' : "",
|
|
9100
|
+
fontAssets.some(({ family }) => family === "Geist Mono") ? '--font-geist-mono: "Geist Mono", ui-monospace, monospace;' : ""
|
|
9101
|
+
].filter(Boolean).join(" ");
|
|
9102
|
+
const fontCss = fontFaces ? `${fontFaces}
|
|
9103
|
+
:root { ${fontVariables} }` : "";
|
|
9104
|
+
const layoutFontVariables = [
|
|
9105
|
+
renderFarmDocsLayoutFontVariable("--fd-layout-font-body", layoutFonts?.body),
|
|
9106
|
+
renderFarmDocsLayoutFontVariable("--fd-layout-font-code", layoutFonts?.code)
|
|
9107
|
+
].filter(Boolean).join(" ");
|
|
8639
9108
|
return `
|
|
8640
|
-
|
|
8641
|
-
@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; }
|
|
8642
|
-
: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); }
|
|
9109
|
+
: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); }
|
|
8643
9110
|
* { box-sizing: border-box; }
|
|
8644
9111
|
html { background: var(--color-fd-background, hsl(0 0% 2%)); scroll-padding-top: calc(var(--fd-nav-height, 44px) + 24px); }
|
|
8645
9112
|
html[data-farm-docs-sidebar="open"], html[data-farm-docs-sidebar="open"] body { overflow: hidden; }
|
|
8646
|
-
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; }
|
|
9113
|
+
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; }
|
|
8647
9114
|
::selection { background: var(--color-fd-foreground, #fff); color: var(--color-fd-background, #000); }
|
|
8648
9115
|
a { color: inherit; }
|
|
8649
9116
|
#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%)); }
|
|
@@ -8823,14 +9290,45 @@ function renderFarmDocsBridgeCss(docs) {
|
|
|
8823
9290
|
.sh__line { min-height: 1.6em; }
|
|
8824
9291
|
}
|
|
8825
9292
|
${farmDocsPixelBorderCss}
|
|
9293
|
+
${fontCss}
|
|
8826
9294
|
`;
|
|
8827
9295
|
}
|
|
8828
|
-
function
|
|
9296
|
+
function renderFarmDocsLayoutFontVariable(name, font) {
|
|
9297
|
+
const family = font?.style.fontFamily;
|
|
9298
|
+
if (!family || /[;{}<>]/.test(family)) return "";
|
|
9299
|
+
return `${name}: ${family};`;
|
|
9300
|
+
}
|
|
9301
|
+
function renderFarmDocsFontPreloads(fontAssets) {
|
|
9302
|
+
return fontAssets.map(
|
|
9303
|
+
({ url }) => `<link rel="preload" href="${escapeAttribute2(url)}" as="font" type="font/woff2" crossorigin>`
|
|
9304
|
+
).join("\n ");
|
|
9305
|
+
}
|
|
9306
|
+
function renderFarmDocsFontPreloadHeader(fontAssets) {
|
|
9307
|
+
return fontAssets.map(({ url }) => `<${url}>; rel=preload; as=font; type=font/woff2; crossorigin`).join(", ");
|
|
9308
|
+
}
|
|
9309
|
+
function getFarmLayoutFontPreloads(layoutFonts) {
|
|
9310
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9311
|
+
return [layoutFonts?.body, layoutFonts?.code].flatMap(
|
|
9312
|
+
(font) => (font?.preloads || []).filter(({ href }) => {
|
|
9313
|
+
if (seen.has(href)) return false;
|
|
9314
|
+
seen.add(href);
|
|
9315
|
+
return true;
|
|
9316
|
+
})
|
|
9317
|
+
);
|
|
9318
|
+
}
|
|
9319
|
+
function renderFarmLayoutFontPreloadHeader(layoutFonts) {
|
|
9320
|
+
return getFarmLayoutFontPreloads(layoutFonts).map(({ href, type }) => `<${href}>; rel=preload; as=font; type=${type}; crossorigin`).join(", ");
|
|
9321
|
+
}
|
|
9322
|
+
function renderPixelDocsHtml(page2, pages, docs, themeCss, clientEntry, faviconHref, requestUrl, fontAssets, layoutFonts, fontStylesheetHref) {
|
|
8829
9323
|
const navTitle = typeof docs.config.nav === "object" && docs.config.nav && "title" in docs.config.nav ? String(docs.config.nav.title || "Docs") : "Docs";
|
|
8830
9324
|
const description = page2.description || docs.config.metadata?.description || "";
|
|
8831
9325
|
const tocItems = extractTocItems(page2.body, getThemeTocDepth(docs));
|
|
8832
9326
|
const themeName = getThemeName(docs);
|
|
8833
9327
|
const searchEnabled = isFarmDocsSearchEnabled(docs);
|
|
9328
|
+
const socialMetadata = isFarmDocsSocialImageEnabled(page2, docs) ? renderFarmDocsSocialMetadata(
|
|
9329
|
+
createFarmDocsSocialImageDescriptor(page2, docs, requestUrl),
|
|
9330
|
+
getFarmDocsCustomSocialImage(page2)
|
|
9331
|
+
) : "";
|
|
8834
9332
|
return `<!DOCTYPE html>
|
|
8835
9333
|
<html class="dark" lang="en" data-docs-theme="${escapeAttribute2(themeName)}">
|
|
8836
9334
|
<head>
|
|
@@ -8839,11 +9337,12 @@ function renderPixelDocsHtml(page2, pages, docs, themeCss, clientEntry, faviconH
|
|
|
8839
9337
|
<meta name="generator" content="@farming-labs/docs via Farm.js">
|
|
8840
9338
|
<title>${escapeHtml(page2.title)}</title>
|
|
8841
9339
|
${renderFarmDocsFaviconLink(faviconHref)}
|
|
8842
|
-
|
|
8843
|
-
|
|
9340
|
+
${renderFarmDocsFontPreloads(fontAssets)}
|
|
9341
|
+
${fontStylesheetHref ? `<link rel="stylesheet" href="${escapeAttribute2(fontStylesheetHref)}">` : ""}
|
|
8844
9342
|
${description ? `<meta name="description" content="${escapeHtml(description)}">` : ""}
|
|
9343
|
+
${socialMetadata}
|
|
8845
9344
|
<style>${themeCss}
|
|
8846
|
-
${renderFarmDocsBridgeCss(docs)}</style>
|
|
9345
|
+
${renderFarmDocsBridgeCss(docs, fontAssets, layoutFonts)}</style>
|
|
8847
9346
|
${searchEnabled ? renderDocsSearchBootstrapScript() : ""}
|
|
8848
9347
|
</head>
|
|
8849
9348
|
<body>
|
|
@@ -8895,9 +9394,34 @@ ${renderMarkdownHtmlWithTitleMeta(page2, docs)}
|
|
|
8895
9394
|
}
|
|
8896
9395
|
function createFarmDocsHandler(docs, options) {
|
|
8897
9396
|
const faviconHref = resolveFarmDocsFavicon(docs, options);
|
|
9397
|
+
const fontAssets = options.fontAssets ?? toFarmDocsPublicFontAssets(resolveFarmDocsFontAssets(options.root));
|
|
9398
|
+
const fallbackFontPreloadHeader = renderFarmDocsFontPreloadHeader(fontAssets);
|
|
8898
9399
|
return /* @__PURE__ */ __name(async function handleFarmDocsRequest(request) {
|
|
8899
9400
|
if (!docs?.enabled || request.method !== "GET" && request.method !== "HEAD") return null;
|
|
8900
9401
|
const contentDir = resolveFarmDocsContentDir(docs, options);
|
|
9402
|
+
const requestUrl = new URL(request.url);
|
|
9403
|
+
const socialImageSlug = getFarmDocsSocialImageSlug(docs, requestUrl);
|
|
9404
|
+
if (socialImageSlug !== null) {
|
|
9405
|
+
const socialImagePage = loadFarmDocsPage(contentDir, docs, socialImageSlug);
|
|
9406
|
+
if (!socialImagePage || !isFarmDocsSocialImageEnabled(socialImagePage, docs) || getFarmDocsCustomSocialImage(socialImagePage)) {
|
|
9407
|
+
return null;
|
|
9408
|
+
}
|
|
9409
|
+
const descriptor = createFarmDocsSocialImageDescriptor(socialImagePage, docs, requestUrl);
|
|
9410
|
+
if (requestUrl.pathname !== descriptor.imagePath) return null;
|
|
9411
|
+
const etag = `"${descriptor.hash}"`;
|
|
9412
|
+
const immutable = requestUrl.searchParams.get("v") === descriptor.hash;
|
|
9413
|
+
const headers = new Headers({
|
|
9414
|
+
"Content-Type": "image/svg+xml; charset=utf-8",
|
|
9415
|
+
"Cache-Control": immutable ? "public, max-age=31536000, immutable" : "public, max-age=0, must-revalidate",
|
|
9416
|
+
ETag: etag,
|
|
9417
|
+
"X-Content-Type-Options": "nosniff"
|
|
9418
|
+
});
|
|
9419
|
+
if (request.headers.get("if-none-match") === etag) {
|
|
9420
|
+
return new Response(null, { status: 304, headers });
|
|
9421
|
+
}
|
|
9422
|
+
if (request.method === "HEAD") return new Response(null, { status: 200, headers });
|
|
9423
|
+
return new Response(renderFarmDocsSocialImageSvg(descriptor), { status: 200, headers });
|
|
9424
|
+
}
|
|
8901
9425
|
const publicResponse = createFarmDocsPublicResponse(contentDir, docs, request);
|
|
8902
9426
|
if (publicResponse) return publicResponse;
|
|
8903
9427
|
if (!isFarmDocsRequest(docs, request)) return null;
|
|
@@ -8920,6 +9444,11 @@ function createFarmDocsHandler(docs, options) {
|
|
|
8920
9444
|
}
|
|
8921
9445
|
);
|
|
8922
9446
|
}
|
|
9447
|
+
const pathname = new URL(request.url).pathname;
|
|
9448
|
+
const layoutFonts = await options.resolveLayoutFonts?.(pathname);
|
|
9449
|
+
const usesLayoutFonts = Boolean(layoutFonts?.body || layoutFonts?.code);
|
|
9450
|
+
const activeFontAssets = usesLayoutFonts ? [] : fontAssets;
|
|
9451
|
+
const fontPreloadHeader = usesLayoutFonts ? renderFarmLayoutFontPreloadHeader(layoutFonts) : fallbackFontPreloadHeader;
|
|
8923
9452
|
return new Response(
|
|
8924
9453
|
renderPixelDocsHtml(
|
|
8925
9454
|
page2,
|
|
@@ -8927,39 +9456,44 @@ function createFarmDocsHandler(docs, options) {
|
|
|
8927
9456
|
docs,
|
|
8928
9457
|
resolvePixelBorderThemeCss(options),
|
|
8929
9458
|
options.clientEntry || "/farm-client.js",
|
|
8930
|
-
faviconHref
|
|
9459
|
+
faviconHref,
|
|
9460
|
+
requestUrl,
|
|
9461
|
+
activeFontAssets,
|
|
9462
|
+
layoutFonts,
|
|
9463
|
+
usesLayoutFonts ? options.fontStylesheetHref : void 0
|
|
8931
9464
|
),
|
|
8932
9465
|
{
|
|
8933
9466
|
status: 200,
|
|
8934
9467
|
headers: {
|
|
8935
9468
|
"Content-Type": "text/html; charset=utf-8",
|
|
8936
|
-
"Cache-Control": "public, s-maxage=60, stale-while-revalidate=300"
|
|
9469
|
+
"Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
|
|
9470
|
+
...fontPreloadHeader ? { Link: fontPreloadHeader } : {}
|
|
8937
9471
|
}
|
|
8938
9472
|
}
|
|
8939
9473
|
);
|
|
8940
9474
|
}, "handleFarmDocsRequest");
|
|
8941
9475
|
}
|
|
8942
|
-
var
|
|
9476
|
+
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;
|
|
8943
9477
|
var init_handler = __esm({
|
|
8944
9478
|
"src/docs/handler.ts"() {
|
|
8945
9479
|
"use strict";
|
|
8946
|
-
|
|
9480
|
+
import_node_fs9 = require("fs");
|
|
8947
9481
|
import_node_module5 = require("module");
|
|
8948
|
-
|
|
9482
|
+
import_node_path13 = __toESM(require("path"));
|
|
8949
9483
|
import_docs = require("@farming-labs/docs");
|
|
8950
9484
|
import_marked = require("marked");
|
|
8951
9485
|
import_sugar_high = require("sugar-high");
|
|
9486
|
+
init_fonts();
|
|
8952
9487
|
init_last_modified();
|
|
8953
9488
|
init_pixel_border_css();
|
|
8954
9489
|
init_search_client();
|
|
9490
|
+
init_social_image();
|
|
8955
9491
|
DOCS_FILE_NAMES = ["page.mdx", "page.md", "index.mdx", "index.md"];
|
|
8956
9492
|
DOCS_FILE_EXTENSIONS2 = [".mdx", ".md"];
|
|
8957
9493
|
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";
|
|
8958
9494
|
FARM_DOCS_FAVICON_FILES = ["favicon.svg", "favicon.ico", "favicon.png"];
|
|
8959
|
-
GEIST_SANS_FONT_URL = "/assets/Geist-Variable-CrgPqtmy.woff2";
|
|
8960
|
-
GEIST_MONO_FONT_URL = "/assets/GeistMono-Variable-BNLlm6Cd.woff2";
|
|
8961
9495
|
__name(trimSlashes2, "trimSlashes");
|
|
8962
|
-
__name(
|
|
9496
|
+
__name(normalizeEntry2, "normalizeEntry");
|
|
8963
9497
|
__name(normalizeSlug, "normalizeSlug");
|
|
8964
9498
|
__name(resolveFarmDocsFavicon, "resolveFarmDocsFavicon");
|
|
8965
9499
|
__name(renderFarmDocsFaviconLink, "renderFarmDocsFaviconLink");
|
|
@@ -9149,6 +9683,11 @@ var init_handler = __esm({
|
|
|
9149
9683
|
__name(readCssWithImports, "readCssWithImports");
|
|
9150
9684
|
__name(resolvePixelBorderThemeCss, "resolvePixelBorderThemeCss");
|
|
9151
9685
|
__name(renderFarmDocsBridgeCss, "renderFarmDocsBridgeCss");
|
|
9686
|
+
__name(renderFarmDocsLayoutFontVariable, "renderFarmDocsLayoutFontVariable");
|
|
9687
|
+
__name(renderFarmDocsFontPreloads, "renderFarmDocsFontPreloads");
|
|
9688
|
+
__name(renderFarmDocsFontPreloadHeader, "renderFarmDocsFontPreloadHeader");
|
|
9689
|
+
__name(getFarmLayoutFontPreloads, "getFarmLayoutFontPreloads");
|
|
9690
|
+
__name(renderFarmLayoutFontPreloadHeader, "renderFarmLayoutFontPreloadHeader");
|
|
9152
9691
|
__name(renderPixelDocsHtml, "renderPixelDocsHtml");
|
|
9153
9692
|
__name(createFarmDocsHandler, "createFarmDocsHandler");
|
|
9154
9693
|
}
|
|
@@ -9430,18 +9969,18 @@ function sanitizeDocsConfig(config) {
|
|
|
9430
9969
|
return cloneSerializable(config) || {};
|
|
9431
9970
|
}
|
|
9432
9971
|
async function findDocsConfigPath(rootDir, configPath) {
|
|
9433
|
-
const { existsSync:
|
|
9972
|
+
const { existsSync: existsSync16 } = await import("fs");
|
|
9434
9973
|
const root = import_path9.default.resolve(rootDir || process.cwd());
|
|
9435
9974
|
if (configPath) {
|
|
9436
9975
|
const resolvedPath = import_path9.default.isAbsolute(configPath) ? configPath : import_path9.default.join(root, configPath);
|
|
9437
|
-
if (!
|
|
9976
|
+
if (!existsSync16(resolvedPath)) {
|
|
9438
9977
|
throw new Error(`Could not find docs config at ${configPath}.`);
|
|
9439
9978
|
}
|
|
9440
9979
|
return import_path9.default.resolve(resolvedPath);
|
|
9441
9980
|
}
|
|
9442
9981
|
for (const filename of DOCS_CONFIG_FILENAMES) {
|
|
9443
9982
|
const resolvedPath = import_path9.default.join(root, filename);
|
|
9444
|
-
if (
|
|
9983
|
+
if (existsSync16(resolvedPath)) {
|
|
9445
9984
|
return resolvedPath;
|
|
9446
9985
|
}
|
|
9447
9986
|
}
|
|
@@ -9629,6 +10168,7 @@ async function resolveConfig(userConfig, mode) {
|
|
|
9629
10168
|
headers: /* @__PURE__ */ __name(() => [...headers, ...routeRuleHeaders], "headers"),
|
|
9630
10169
|
routeRules,
|
|
9631
10170
|
images: resolveFarmImageConfig(userConfig.images),
|
|
10171
|
+
performance: resolveFarmPerformanceConfig(userConfig.performance),
|
|
9632
10172
|
publicDir: userConfig.publicDir || "public",
|
|
9633
10173
|
i18n: resolveFarmI18nConfig(userConfig.i18n, { root, mode }),
|
|
9634
10174
|
openapi: {
|
|
@@ -9667,7 +10207,7 @@ async function resolveConfig(userConfig, mode) {
|
|
|
9667
10207
|
return resolved;
|
|
9668
10208
|
}
|
|
9669
10209
|
async function loadConfig(rootDir, configPath, mode = process.env.NODE_ENV === "production" ? "production" : "development", loadEnvironment) {
|
|
9670
|
-
const { existsSync:
|
|
10210
|
+
const { existsSync: existsSync16 } = await import("fs");
|
|
9671
10211
|
const loadEnv = loadEnvironment || (await import("vite")).loadEnv;
|
|
9672
10212
|
const root = rootDir || process.cwd();
|
|
9673
10213
|
const loadedEnv = loadEnv(mode, root, "");
|
|
@@ -9691,7 +10231,7 @@ async function loadConfig(rootDir, configPath, mode = process.env.NODE_ENV === "
|
|
|
9691
10231
|
try {
|
|
9692
10232
|
const absolutePath = relativePath2.startsWith("/") ? relativePath2 : import_path9.default.join(root, relativePath2);
|
|
9693
10233
|
const normalizedPath = import_path9.default.resolve(absolutePath);
|
|
9694
|
-
if (!
|
|
10234
|
+
if (!existsSync16(normalizedPath)) {
|
|
9695
10235
|
continue;
|
|
9696
10236
|
}
|
|
9697
10237
|
const loadedConfig = await loadFarmConfigFile(normalizedPath, { root });
|
|
@@ -9722,6 +10262,7 @@ var init_config2 = __esm({
|
|
|
9722
10262
|
init_image_config();
|
|
9723
10263
|
init_config();
|
|
9724
10264
|
init_auth_config();
|
|
10265
|
+
init_preload();
|
|
9725
10266
|
init_config_entry();
|
|
9726
10267
|
FARM_RESOLVED_CUSTOM_CONTEXT = /* @__PURE__ */ Symbol.for("farm.resolvedCustomContext");
|
|
9727
10268
|
__name(normalizeDeployTarget, "normalizeDeployTarget");
|
|
@@ -10518,8 +11059,8 @@ var init_generator = __esm({
|
|
|
10518
11059
|
}
|
|
10519
11060
|
routeGroups.get(key).push(route);
|
|
10520
11061
|
}
|
|
10521
|
-
for (const [
|
|
10522
|
-
const openAPIPath = this.convertToOpenAPIPath(
|
|
11062
|
+
for (const [path27, routeList] of routeGroups) {
|
|
11063
|
+
const openAPIPath = this.convertToOpenAPIPath(path27);
|
|
10523
11064
|
spec.paths[openAPIPath] = {};
|
|
10524
11065
|
for (const route of routeList) {
|
|
10525
11066
|
for (const method of route.methods) {
|
|
@@ -10533,8 +11074,8 @@ var init_generator = __esm({
|
|
|
10533
11074
|
/**
|
|
10534
11075
|
* Convert Farm.js API path to OpenAPI path format
|
|
10535
11076
|
*/
|
|
10536
|
-
convertToOpenAPIPath(
|
|
10537
|
-
return
|
|
11077
|
+
convertToOpenAPIPath(path27) {
|
|
11078
|
+
return path27.replace(/^\/api/, "");
|
|
10538
11079
|
}
|
|
10539
11080
|
/**
|
|
10540
11081
|
* Extract request body schema from endpoint
|
|
@@ -10696,8 +11237,8 @@ var init_generator = __esm({
|
|
|
10696
11237
|
/**
|
|
10697
11238
|
* Generate operation summary
|
|
10698
11239
|
*/
|
|
10699
|
-
generateSummary(
|
|
10700
|
-
const cleanPath =
|
|
11240
|
+
generateSummary(path27, method) {
|
|
11241
|
+
const cleanPath = path27.replace(/^\/api\//, "");
|
|
10701
11242
|
const pathParts = cleanPath.split("/");
|
|
10702
11243
|
const lastPart = pathParts[pathParts.length - 1];
|
|
10703
11244
|
const action = method === "GET" ? "Get" : method === "POST" ? "Create" : method === "PUT" ? "Update" : method === "DELETE" ? "Delete" : method === "PATCH" ? "Update" : method;
|
|
@@ -10706,22 +11247,22 @@ var init_generator = __esm({
|
|
|
10706
11247
|
/**
|
|
10707
11248
|
* Generate operation description
|
|
10708
11249
|
*/
|
|
10709
|
-
generateDescription(
|
|
10710
|
-
const cleanPath =
|
|
11250
|
+
generateDescription(path27, method) {
|
|
11251
|
+
const cleanPath = path27.replace(/^\/api\//, "");
|
|
10711
11252
|
return `${method} ${cleanPath} endpoint`;
|
|
10712
11253
|
}
|
|
10713
11254
|
/**
|
|
10714
11255
|
* Generate operation ID
|
|
10715
11256
|
*/
|
|
10716
|
-
generateOperationId(
|
|
10717
|
-
const cleanPath =
|
|
11257
|
+
generateOperationId(path27, method) {
|
|
11258
|
+
const cleanPath = path27.replace(/^\/api\//, "").replace(/\//g, "_");
|
|
10718
11259
|
return `${method.toLowerCase()}_${cleanPath}`;
|
|
10719
11260
|
}
|
|
10720
11261
|
/**
|
|
10721
11262
|
* Generate tags for grouping operations
|
|
10722
11263
|
*/
|
|
10723
|
-
generateTags(
|
|
10724
|
-
const cleanPath =
|
|
11264
|
+
generateTags(path27) {
|
|
11265
|
+
const cleanPath = path27.replace(/^\/api\//, "");
|
|
10725
11266
|
const pathParts = cleanPath.split("/");
|
|
10726
11267
|
if (pathParts.length > 1) {
|
|
10727
11268
|
return [pathParts[0]];
|
|
@@ -10734,8 +11275,8 @@ var init_generator = __esm({
|
|
|
10734
11275
|
async generateSpecFile(routes, outputPath) {
|
|
10735
11276
|
const spec = await this.generateSpec(routes);
|
|
10736
11277
|
const fs9 = require("fs");
|
|
10737
|
-
const
|
|
10738
|
-
const dir =
|
|
11278
|
+
const path27 = require("path");
|
|
11279
|
+
const dir = path27.dirname(outputPath);
|
|
10739
11280
|
if (!fs9.existsSync(dir)) {
|
|
10740
11281
|
fs9.mkdirSync(dir, { recursive: true });
|
|
10741
11282
|
}
|
|
@@ -11155,7 +11696,7 @@ async function createFarmDevtoolsSnapshot(input) {
|
|
|
11155
11696
|
generatedAt: (input.now?.() || /* @__PURE__ */ new Date()).toISOString(),
|
|
11156
11697
|
health: resolveHealth(diagnostics),
|
|
11157
11698
|
project: {
|
|
11158
|
-
name:
|
|
11699
|
+
name: import_node_path14.default.basename(import_node_path14.default.resolve(input.root)),
|
|
11159
11700
|
root: input.root,
|
|
11160
11701
|
srcDir: input.srcDir,
|
|
11161
11702
|
basePath: config.basePath || "/",
|
|
@@ -11204,11 +11745,11 @@ async function createFarmDevtoolsSnapshot(input) {
|
|
|
11204
11745
|
diagnostics
|
|
11205
11746
|
};
|
|
11206
11747
|
}
|
|
11207
|
-
var
|
|
11748
|
+
var import_node_path14;
|
|
11208
11749
|
var init_devtools = __esm({
|
|
11209
11750
|
"src/devtools.ts"() {
|
|
11210
11751
|
"use strict";
|
|
11211
|
-
|
|
11752
|
+
import_node_path14 = __toESM(require("path"));
|
|
11212
11753
|
init_config2();
|
|
11213
11754
|
init_cron();
|
|
11214
11755
|
init_route_runtime();
|
|
@@ -13279,6 +13820,22 @@ var import_promises3 = require("fs/promises");
|
|
|
13279
13820
|
var OPTIONAL_CATCH_ALL_SEGMENT = /^\[\[\.\.\.([^\]]+)\]\]$/;
|
|
13280
13821
|
var REQUIRED_CATCH_ALL_SEGMENT = /^\[\.\.\.([^\]]+)\]$/;
|
|
13281
13822
|
var REQUIRED_DYNAMIC_SEGMENT = /^\[([^\]]+)\]$/;
|
|
13823
|
+
var REQUEST_API_LABELS = /* @__PURE__ */ new Map([
|
|
13824
|
+
["cookies", "request cookies"],
|
|
13825
|
+
["headers", "request headers"],
|
|
13826
|
+
["getCurrentRequest", "the current Request"],
|
|
13827
|
+
["useSearchParams", "URL search parameters"],
|
|
13828
|
+
["auth", "request authentication"],
|
|
13829
|
+
["getServerSession", "request authentication"],
|
|
13830
|
+
["getSession", "request authentication"],
|
|
13831
|
+
["currentUser", "request authentication"]
|
|
13832
|
+
]);
|
|
13833
|
+
var ROUTE_PROP_LABELS = /* @__PURE__ */ new Map([
|
|
13834
|
+
["searchParams", "URL search parameters"],
|
|
13835
|
+
["middleware", "middleware request data"],
|
|
13836
|
+
["middlewareData", "middleware request data"],
|
|
13837
|
+
["context", "request context"]
|
|
13838
|
+
]);
|
|
13282
13839
|
function resolveRouteRenderingConfig(mod, source) {
|
|
13283
13840
|
const directiveConfig = parseRouteRenderingDirective(source);
|
|
13284
13841
|
let ssg = directiveConfig?.ssg ?? false;
|
|
@@ -13331,6 +13888,221 @@ async function resolveRouteRenderingConfigFromFile(mod, filePath) {
|
|
|
13331
13888
|
return resolveRouteRenderingConfig(mod, source);
|
|
13332
13889
|
}
|
|
13333
13890
|
__name(resolveRouteRenderingConfigFromFile, "resolveRouteRenderingConfigFromFile");
|
|
13891
|
+
function analyzeStaticRouteCandidate(mod, source, options = {}) {
|
|
13892
|
+
const blockers = [];
|
|
13893
|
+
if (!source) {
|
|
13894
|
+
blockers.push("route source is unavailable");
|
|
13895
|
+
}
|
|
13896
|
+
if (options.isDynamic) {
|
|
13897
|
+
blockers.push("the route has dynamic path segments");
|
|
13898
|
+
}
|
|
13899
|
+
if (hasExplicitRenderingConfig(mod, source)) {
|
|
13900
|
+
blockers.push("the route already has explicit rendering config");
|
|
13901
|
+
}
|
|
13902
|
+
if (source) {
|
|
13903
|
+
blockers.push(...findRequestBoundSourceBlockers(source));
|
|
13904
|
+
}
|
|
13905
|
+
return {
|
|
13906
|
+
candidate: blockers.length === 0,
|
|
13907
|
+
blockers
|
|
13908
|
+
};
|
|
13909
|
+
}
|
|
13910
|
+
__name(analyzeStaticRouteCandidate, "analyzeStaticRouteCandidate");
|
|
13911
|
+
function findRequestBoundSourceBlockers(source) {
|
|
13912
|
+
const blockers = /* @__PURE__ */ new Set();
|
|
13913
|
+
const code = stripCommentsAndLiteralContents(source);
|
|
13914
|
+
const sourceWithoutComments = stripComments(source);
|
|
13915
|
+
for (const binding of readRequestApiImportBindings(sourceWithoutComments)) {
|
|
13916
|
+
if (new RegExp(`\\b${escapeRegExp2(binding.local)}\\s*(?:\\?\\.\\s*)?\\(`).test(code)) {
|
|
13917
|
+
blockers.add(`the route reads ${binding.label}`);
|
|
13918
|
+
}
|
|
13919
|
+
}
|
|
13920
|
+
for (const namespace of readNamespaceImportBindings(sourceWithoutComments)) {
|
|
13921
|
+
for (const [name, label] of REQUEST_API_LABELS) {
|
|
13922
|
+
if (new RegExp(
|
|
13923
|
+
`\\b${escapeRegExp2(namespace)}\\s*(?:\\?\\.\\s*|\\.\\s*)${name}\\s*(?:\\?\\.\\s*)?\\(`
|
|
13924
|
+
).test(code)) {
|
|
13925
|
+
blockers.add(`the route reads ${label}`);
|
|
13926
|
+
}
|
|
13927
|
+
}
|
|
13928
|
+
}
|
|
13929
|
+
const params = readDefaultRouteParameters(code);
|
|
13930
|
+
if (params) {
|
|
13931
|
+
for (const [name, label] of ROUTE_PROP_LABELS) {
|
|
13932
|
+
if (new RegExp(`\\b${name}\\b`).test(params)) {
|
|
13933
|
+
blockers.add(`the route reads ${label}`);
|
|
13934
|
+
}
|
|
13935
|
+
}
|
|
13936
|
+
const propsName = params.match(/^\s*([A-Za-z_$][\w$]*)\s*(?::|,|$)/)?.[1];
|
|
13937
|
+
if (propsName) {
|
|
13938
|
+
for (const [name, label] of ROUTE_PROP_LABELS) {
|
|
13939
|
+
if (new RegExp(`\\b${escapeRegExp2(propsName)}\\s*\\.\\s*${name}\\b`).test(code)) {
|
|
13940
|
+
blockers.add(`the route reads ${label}`);
|
|
13941
|
+
}
|
|
13942
|
+
if (new RegExp(`\\{[^}]*\\b${name}\\b[^}]*\\}\\s*=\\s*${escapeRegExp2(propsName)}\\b`).test(
|
|
13943
|
+
code
|
|
13944
|
+
)) {
|
|
13945
|
+
blockers.add(`the route reads ${label}`);
|
|
13946
|
+
}
|
|
13947
|
+
}
|
|
13948
|
+
}
|
|
13949
|
+
}
|
|
13950
|
+
return [...blockers];
|
|
13951
|
+
}
|
|
13952
|
+
__name(findRequestBoundSourceBlockers, "findRequestBoundSourceBlockers");
|
|
13953
|
+
function readRequestApiImportBindings(source) {
|
|
13954
|
+
const bindings = [];
|
|
13955
|
+
for (const clause of readStaticImportClauses(source)) {
|
|
13956
|
+
const namedGroup = clause.match(/\{([\s\S]*?)\}/)?.[1];
|
|
13957
|
+
for (const rawSpecifier of (namedGroup ?? "").split(",")) {
|
|
13958
|
+
const specifier = rawSpecifier.trim().replace(/^type\s+/, "");
|
|
13959
|
+
const imported = specifier.match(/^([A-Za-z_$][\w$]*)(?:\s+as\s+([A-Za-z_$][\w$]*))?$/);
|
|
13960
|
+
if (!imported?.[1]) continue;
|
|
13961
|
+
const label = REQUEST_API_LABELS.get(imported[1]);
|
|
13962
|
+
if (label) bindings.push({ local: imported[2] ?? imported[1], label });
|
|
13963
|
+
}
|
|
13964
|
+
const local = clause.match(/^\s*([A-Za-z_$][\w$]*)\s*(?:,|$)/)?.[1];
|
|
13965
|
+
if (local) {
|
|
13966
|
+
const label = REQUEST_API_LABELS.get(local);
|
|
13967
|
+
if (label) bindings.push({ local, label });
|
|
13968
|
+
}
|
|
13969
|
+
}
|
|
13970
|
+
return bindings;
|
|
13971
|
+
}
|
|
13972
|
+
__name(readRequestApiImportBindings, "readRequestApiImportBindings");
|
|
13973
|
+
function readNamespaceImportBindings(source) {
|
|
13974
|
+
return readStaticImportClauses(source).map((clause) => clause.match(/\*\s*as\s*([A-Za-z_$][\w$]*)/)?.[1]).filter((binding) => Boolean(binding));
|
|
13975
|
+
}
|
|
13976
|
+
__name(readNamespaceImportBindings, "readNamespaceImportBindings");
|
|
13977
|
+
function readStaticImportClauses(source) {
|
|
13978
|
+
return [...source.matchAll(/\bimport\s+(?!\()([\s\S]*?)\s+from\s*["'][^"']+["']/g)].map((match) => match[1]).filter((clause) => Boolean(clause));
|
|
13979
|
+
}
|
|
13980
|
+
__name(readStaticImportClauses, "readStaticImportClauses");
|
|
13981
|
+
function readDefaultRouteParameters(code) {
|
|
13982
|
+
const inlineParams = code.match(/\bexport\s+default\s+(?:async\s+)?function\b[^(]*\(([^)]*)\)/)?.[1] ?? code.match(/\bexport\s+default\s+(?:async\s+)?\(([^)]*)\)\s*=>/)?.[1];
|
|
13983
|
+
if (inlineParams !== void 0) return inlineParams;
|
|
13984
|
+
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];
|
|
13985
|
+
if (!binding) return void 0;
|
|
13986
|
+
const escapedBinding = escapeRegExp2(binding);
|
|
13987
|
+
return code.match(new RegExp(`\\bfunction\\s+${escapedBinding}\\s*\\(([^)]*)\\)`))?.[1] ?? code.match(
|
|
13988
|
+
new RegExp(
|
|
13989
|
+
`\\b(?:const|let|var)\\s+${escapedBinding}\\s*=\\s*(?:async\\s+)?\\(([^)]*)\\)\\s*=>`
|
|
13990
|
+
)
|
|
13991
|
+
)?.[1] ?? code.match(
|
|
13992
|
+
new RegExp(`\\b(?:const|let|var)\\s+${escapedBinding}\\s*=\\s*function\\s*\\(([^)]*)\\)`)
|
|
13993
|
+
)?.[1];
|
|
13994
|
+
}
|
|
13995
|
+
__name(readDefaultRouteParameters, "readDefaultRouteParameters");
|
|
13996
|
+
function stripCommentsAndLiteralContents(source) {
|
|
13997
|
+
return sanitizeSource(source, true);
|
|
13998
|
+
}
|
|
13999
|
+
__name(stripCommentsAndLiteralContents, "stripCommentsAndLiteralContents");
|
|
14000
|
+
function stripComments(source) {
|
|
14001
|
+
return sanitizeSource(source, false);
|
|
14002
|
+
}
|
|
14003
|
+
__name(stripComments, "stripComments");
|
|
14004
|
+
function sanitizeSource(source, maskLiterals) {
|
|
14005
|
+
const output = [...source];
|
|
14006
|
+
const mask = /* @__PURE__ */ __name((index) => {
|
|
14007
|
+
if (output[index] !== "\n" && output[index] !== "\r") output[index] = " ";
|
|
14008
|
+
}, "mask");
|
|
14009
|
+
const scanQuoted = /* @__PURE__ */ __name((start, quote) => {
|
|
14010
|
+
let index = start;
|
|
14011
|
+
if (maskLiterals) mask(index);
|
|
14012
|
+
index += 1;
|
|
14013
|
+
while (index < source.length) {
|
|
14014
|
+
if (source[index] === "\\") {
|
|
14015
|
+
if (maskLiterals) mask(index);
|
|
14016
|
+
if (index + 1 < source.length && maskLiterals) mask(index + 1);
|
|
14017
|
+
index += 2;
|
|
14018
|
+
continue;
|
|
14019
|
+
}
|
|
14020
|
+
const character = source[index];
|
|
14021
|
+
if (maskLiterals) mask(index);
|
|
14022
|
+
index += 1;
|
|
14023
|
+
if (character === quote) break;
|
|
14024
|
+
}
|
|
14025
|
+
return index;
|
|
14026
|
+
}, "scanQuoted");
|
|
14027
|
+
const scanCode = /* @__PURE__ */ __name((start, stopAtTemplateBrace) => {
|
|
14028
|
+
let index = start;
|
|
14029
|
+
let braceDepth = 0;
|
|
14030
|
+
while (index < source.length) {
|
|
14031
|
+
const character = source[index];
|
|
14032
|
+
const next = source[index + 1];
|
|
14033
|
+
if (character === "/" && next === "/") {
|
|
14034
|
+
while (index < source.length && source[index] !== "\n" && source[index] !== "\r") {
|
|
14035
|
+
mask(index++);
|
|
14036
|
+
}
|
|
14037
|
+
continue;
|
|
14038
|
+
}
|
|
14039
|
+
if (character === "/" && next === "*") {
|
|
14040
|
+
mask(index++);
|
|
14041
|
+
mask(index++);
|
|
14042
|
+
while (index < source.length) {
|
|
14043
|
+
const closesComment = source[index] === "*" && source[index + 1] === "/";
|
|
14044
|
+
mask(index++);
|
|
14045
|
+
if (closesComment) {
|
|
14046
|
+
mask(index++);
|
|
14047
|
+
break;
|
|
14048
|
+
}
|
|
14049
|
+
}
|
|
14050
|
+
continue;
|
|
14051
|
+
}
|
|
14052
|
+
if (character === "'" || character === '"') {
|
|
14053
|
+
index = scanQuoted(index, character);
|
|
14054
|
+
continue;
|
|
14055
|
+
}
|
|
14056
|
+
if (character === "`") {
|
|
14057
|
+
if (maskLiterals) mask(index);
|
|
14058
|
+
index += 1;
|
|
14059
|
+
while (index < source.length) {
|
|
14060
|
+
if (source[index] === "\\") {
|
|
14061
|
+
if (maskLiterals) mask(index);
|
|
14062
|
+
if (index + 1 < source.length && maskLiterals) mask(index + 1);
|
|
14063
|
+
index += 2;
|
|
14064
|
+
} else if (source[index] === "`") {
|
|
14065
|
+
if (maskLiterals) mask(index);
|
|
14066
|
+
index += 1;
|
|
14067
|
+
break;
|
|
14068
|
+
} else if (source[index] === "$" && source[index + 1] === "{") {
|
|
14069
|
+
if (maskLiterals) {
|
|
14070
|
+
mask(index);
|
|
14071
|
+
mask(index + 1);
|
|
14072
|
+
}
|
|
14073
|
+
index = scanCode(index + 2, true);
|
|
14074
|
+
} else {
|
|
14075
|
+
if (maskLiterals) mask(index);
|
|
14076
|
+
index += 1;
|
|
14077
|
+
}
|
|
14078
|
+
}
|
|
14079
|
+
continue;
|
|
14080
|
+
}
|
|
14081
|
+
if (character === "{") {
|
|
14082
|
+
braceDepth += 1;
|
|
14083
|
+
} else if (character === "}") {
|
|
14084
|
+
if (stopAtTemplateBrace && braceDepth === 0) {
|
|
14085
|
+
if (maskLiterals) mask(index);
|
|
14086
|
+
return index + 1;
|
|
14087
|
+
}
|
|
14088
|
+
braceDepth = Math.max(0, braceDepth - 1);
|
|
14089
|
+
}
|
|
14090
|
+
index += 1;
|
|
14091
|
+
}
|
|
14092
|
+
return index;
|
|
14093
|
+
}, "scanCode");
|
|
14094
|
+
scanCode(0, false);
|
|
14095
|
+
return output.join("");
|
|
14096
|
+
}
|
|
14097
|
+
__name(sanitizeSource, "sanitizeSource");
|
|
14098
|
+
function escapeRegExp2(value) {
|
|
14099
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14100
|
+
}
|
|
14101
|
+
__name(escapeRegExp2, "escapeRegExp");
|
|
14102
|
+
function hasExplicitRenderingConfig(mod, source) {
|
|
14103
|
+
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";
|
|
14104
|
+
}
|
|
14105
|
+
__name(hasExplicitRenderingConfig, "hasExplicitRenderingConfig");
|
|
13334
14106
|
function parseRouteRenderingDirective(source) {
|
|
13335
14107
|
if (!source) {
|
|
13336
14108
|
return void 0;
|
|
@@ -13462,9 +14234,10 @@ function skipHorizontalWhitespace(source, start) {
|
|
|
13462
14234
|
return index;
|
|
13463
14235
|
}
|
|
13464
14236
|
__name(skipHorizontalWhitespace, "skipHorizontalWhitespace");
|
|
13465
|
-
async function collectSSGPages(routes, loadModule2) {
|
|
14237
|
+
async function collectSSGPages(routes, loadModule2, options = {}) {
|
|
13466
14238
|
const ssgPages = [];
|
|
13467
14239
|
const ssrRoutes = [];
|
|
14240
|
+
const staticCandidateRoutes = [];
|
|
13468
14241
|
for (const route of routes) {
|
|
13469
14242
|
try {
|
|
13470
14243
|
const mod = await loadModule2(route.filePath);
|
|
@@ -13472,7 +14245,8 @@ async function collectSSGPages(routes, loadModule2) {
|
|
|
13472
14245
|
ssrRoutes.push(route.path);
|
|
13473
14246
|
continue;
|
|
13474
14247
|
}
|
|
13475
|
-
const
|
|
14248
|
+
const source = await (0, import_promises3.readFile)(route.filePath, "utf8").catch(() => void 0);
|
|
14249
|
+
const rendering = resolveRouteRenderingConfig(mod, source);
|
|
13476
14250
|
if (rendering.ssg) {
|
|
13477
14251
|
if (route.isDynamic) {
|
|
13478
14252
|
const getStaticPaths = mod.getStaticPaths || mod.generateStaticParams;
|
|
@@ -13499,12 +14273,26 @@ async function collectSSGPages(routes, loadModule2) {
|
|
|
13499
14273
|
}
|
|
13500
14274
|
} else {
|
|
13501
14275
|
ssrRoutes.push(route.path);
|
|
14276
|
+
if (options.suggestStaticRendering !== false && analyzeStaticRouteCandidate(mod, source, { isDynamic: route.isDynamic }).candidate) {
|
|
14277
|
+
staticCandidateRoutes.push(route.path);
|
|
14278
|
+
}
|
|
13502
14279
|
}
|
|
13503
14280
|
} catch (error) {
|
|
13504
14281
|
console.error(`Error processing route ${route.path}:`, error);
|
|
13505
14282
|
ssrRoutes.push(route.path);
|
|
13506
14283
|
}
|
|
13507
14284
|
}
|
|
14285
|
+
if (staticCandidateRoutes.length > 0) {
|
|
14286
|
+
const visibleRoutes = staticCandidateRoutes.slice(0, 10);
|
|
14287
|
+
const remainingCount = staticCandidateRoutes.length - visibleRoutes.length;
|
|
14288
|
+
const remainingSuffix = remainingCount > 0 ? `
|
|
14289
|
+
\u2026and ${remainingCount} more` : "";
|
|
14290
|
+
console.warn(
|
|
14291
|
+
`[Farm.js] ${staticCandidateRoutes.length} route${staticCandidateRoutes.length === 1 ? " appears" : "s appear"} eligible for static rendering:
|
|
14292
|
+
${visibleRoutes.join("\n ")}${remainingSuffix}
|
|
14293
|
+
Add \`export const dynamic = "force-static";\` after verifying that imported code does not read cookies, headers, authentication, or other request data.`
|
|
14294
|
+
);
|
|
14295
|
+
}
|
|
13508
14296
|
return { ssg: ssgPages, ssr: ssrRoutes };
|
|
13509
14297
|
}
|
|
13510
14298
|
__name(collectSSGPages, "collectSSGPages");
|
|
@@ -14419,25 +15207,25 @@ function defineRoutes(input) {
|
|
|
14419
15207
|
}
|
|
14420
15208
|
__name(defineRoutes, "defineRoutes");
|
|
14421
15209
|
var routesBuilder = {
|
|
14422
|
-
page(
|
|
15210
|
+
page(path27, options) {
|
|
14423
15211
|
return normalizeProgrammaticRoute({
|
|
14424
15212
|
kind: "page",
|
|
14425
|
-
path:
|
|
15213
|
+
path: path27,
|
|
14426
15214
|
...options
|
|
14427
15215
|
});
|
|
14428
15216
|
},
|
|
14429
|
-
layout(
|
|
15217
|
+
layout(path27, options) {
|
|
14430
15218
|
return normalizeProgrammaticRoute({
|
|
14431
15219
|
kind: "layout",
|
|
14432
|
-
path:
|
|
15220
|
+
path: path27,
|
|
14433
15221
|
...options
|
|
14434
15222
|
});
|
|
14435
15223
|
},
|
|
14436
|
-
api(
|
|
15224
|
+
api(path27, options) {
|
|
14437
15225
|
const { render, runtime, regions, maxDuration, ...methods } = options;
|
|
14438
15226
|
return normalizeProgrammaticRoute({
|
|
14439
15227
|
kind: "api",
|
|
14440
|
-
path:
|
|
15228
|
+
path: path27,
|
|
14441
15229
|
render,
|
|
14442
15230
|
runtime,
|
|
14443
15231
|
regions,
|
|
@@ -14473,7 +15261,7 @@ function getProgrammaticRouteSearchClientOptions(search) {
|
|
|
14473
15261
|
return Object.keys(options).length > 0 ? options : void 0;
|
|
14474
15262
|
}
|
|
14475
15263
|
__name(getProgrammaticRouteSearchClientOptions, "getProgrammaticRouteSearchClientOptions");
|
|
14476
|
-
function resolveProgrammaticRouteSearch(searchConfig, rawSearch,
|
|
15264
|
+
function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path27, routePath) {
|
|
14477
15265
|
const schema = getProgrammaticRouteSearchSchema(searchConfig);
|
|
14478
15266
|
const search = parseProgrammaticSchema(schema, rawSearch, "search", routePath);
|
|
14479
15267
|
const options = getProgrammaticRouteSearchOptions(searchConfig);
|
|
@@ -14482,7 +15270,7 @@ function resolveProgrammaticRouteSearch(searchConfig, rawSearch, path25, routePa
|
|
|
14482
15270
|
schema,
|
|
14483
15271
|
rawSearch,
|
|
14484
15272
|
parsedSearch: search,
|
|
14485
|
-
path:
|
|
15273
|
+
path: path27
|
|
14486
15274
|
});
|
|
14487
15275
|
return { search, canonicalPath };
|
|
14488
15276
|
}
|
|
@@ -14665,7 +15453,7 @@ function createRouteModuleFromProgrammaticPage(route) {
|
|
|
14665
15453
|
mod.__farmRouteData = route.data;
|
|
14666
15454
|
mod.__farmRouteParsesProps = true;
|
|
14667
15455
|
mod.__farmResolveRouteProps = (props) => resolveProgrammaticRouteProps(route, props);
|
|
14668
|
-
mod.__farmResolveRouteCanonicalPath = (rawSearch,
|
|
15456
|
+
mod.__farmResolveRouteCanonicalPath = (rawSearch, path27) => resolveProgrammaticRouteSearch(route.search, rawSearch, path27, route.path).canonicalPath;
|
|
14669
15457
|
}
|
|
14670
15458
|
if (route.pending || route.error || route.notFound) {
|
|
14671
15459
|
mod.__farmRouteComponents = {
|
|
@@ -15141,6 +15929,15 @@ var import_path5 = __toESM(require("path"));
|
|
|
15141
15929
|
var import_fs2 = __toESM(require("fs"));
|
|
15142
15930
|
var import_path4 = __toESM(require("path"));
|
|
15143
15931
|
var import_url2 = require("url");
|
|
15932
|
+
|
|
15933
|
+
// src/island.ts
|
|
15934
|
+
var FARM_ISLAND_STRATEGIES = ["load", "interaction", "visible", "idle"];
|
|
15935
|
+
function isFarmIslandStrategy(value) {
|
|
15936
|
+
return FARM_ISLAND_STRATEGIES.includes(value);
|
|
15937
|
+
}
|
|
15938
|
+
__name(isFarmIslandStrategy, "isFarmIslandStrategy");
|
|
15939
|
+
|
|
15940
|
+
// src/utils/client-component.ts
|
|
15144
15941
|
function readIfExists(filePath) {
|
|
15145
15942
|
try {
|
|
15146
15943
|
if (!filePath || !import_fs2.default.existsSync(filePath)) {
|
|
@@ -15211,56 +16008,186 @@ function hasHydrateExport(content) {
|
|
|
15211
16008
|
return /\bexport\s+const\s+hydrate\s*=\s*true\b/.test(content) || /\bexport\s*\{\s*hydrate\s*\}\b/.test(content);
|
|
15212
16009
|
}
|
|
15213
16010
|
__name(hasHydrateExport, "hasHydrateExport");
|
|
16011
|
+
function tokenizeModuleSource(content) {
|
|
16012
|
+
const tokens = [];
|
|
16013
|
+
let index = 0;
|
|
16014
|
+
let line = 1;
|
|
16015
|
+
while (index < content.length) {
|
|
16016
|
+
const character = content[index];
|
|
16017
|
+
if (/\s/.test(character)) {
|
|
16018
|
+
if (character === "\n") line++;
|
|
16019
|
+
index++;
|
|
16020
|
+
continue;
|
|
16021
|
+
}
|
|
16022
|
+
if (character === "/" && content[index + 1] === "/") {
|
|
16023
|
+
index += 2;
|
|
16024
|
+
while (index < content.length && content[index] !== "\n") index++;
|
|
16025
|
+
continue;
|
|
16026
|
+
}
|
|
16027
|
+
if (character === "/" && content[index + 1] === "*") {
|
|
16028
|
+
index += 2;
|
|
16029
|
+
while (index < content.length) {
|
|
16030
|
+
if (content[index] === "\n") line++;
|
|
16031
|
+
if (content[index] === "*" && content[index + 1] === "/") {
|
|
16032
|
+
index += 2;
|
|
16033
|
+
break;
|
|
16034
|
+
}
|
|
16035
|
+
index++;
|
|
16036
|
+
}
|
|
16037
|
+
continue;
|
|
16038
|
+
}
|
|
16039
|
+
if (character === '"' || character === "'") {
|
|
16040
|
+
const quote = character;
|
|
16041
|
+
const tokenLine = line;
|
|
16042
|
+
let value = "";
|
|
16043
|
+
index++;
|
|
16044
|
+
while (index < content.length) {
|
|
16045
|
+
const next = content[index];
|
|
16046
|
+
if (next === "\\") {
|
|
16047
|
+
value += next;
|
|
16048
|
+
if (index + 1 < content.length) value += content[index + 1];
|
|
16049
|
+
index += 2;
|
|
16050
|
+
continue;
|
|
16051
|
+
}
|
|
16052
|
+
if (next === quote) {
|
|
16053
|
+
index++;
|
|
16054
|
+
break;
|
|
16055
|
+
}
|
|
16056
|
+
if (next === "\n") line++;
|
|
16057
|
+
value += next;
|
|
16058
|
+
index++;
|
|
16059
|
+
}
|
|
16060
|
+
tokens.push({ kind: "string", value, line: tokenLine });
|
|
16061
|
+
continue;
|
|
16062
|
+
}
|
|
16063
|
+
if (character === "`") {
|
|
16064
|
+
index++;
|
|
16065
|
+
while (index < content.length) {
|
|
16066
|
+
const next = content[index];
|
|
16067
|
+
if (next === "\\") {
|
|
16068
|
+
index += 2;
|
|
16069
|
+
continue;
|
|
16070
|
+
}
|
|
16071
|
+
if (next === "`") {
|
|
16072
|
+
index++;
|
|
16073
|
+
break;
|
|
16074
|
+
}
|
|
16075
|
+
if (next === "\n") line++;
|
|
16076
|
+
index++;
|
|
16077
|
+
}
|
|
16078
|
+
continue;
|
|
16079
|
+
}
|
|
16080
|
+
if (/[A-Za-z_$]/.test(character)) {
|
|
16081
|
+
const start = index++;
|
|
16082
|
+
while (index < content.length && /[\w$]/.test(content[index])) index++;
|
|
16083
|
+
tokens.push({ kind: "identifier", value: content.slice(start, index), line });
|
|
16084
|
+
continue;
|
|
16085
|
+
}
|
|
16086
|
+
tokens.push({ kind: "punctuation", value: character, line });
|
|
16087
|
+
index++;
|
|
16088
|
+
}
|
|
16089
|
+
return tokens;
|
|
16090
|
+
}
|
|
16091
|
+
__name(tokenizeModuleSource, "tokenizeModuleSource");
|
|
16092
|
+
function isIslandExportStart(tokens, index) {
|
|
16093
|
+
const token = tokens[index];
|
|
16094
|
+
const previous = tokens[index - 1];
|
|
16095
|
+
const startsStatement = !previous || previous.value === ";" || previous.value === "{" || previous.value === "}" || token.line > previous.line;
|
|
16096
|
+
return startsStatement && token.value === "export" && tokens[index + 1]?.value === "const" && tokens[index + 2]?.value === "island";
|
|
16097
|
+
}
|
|
16098
|
+
__name(isIslandExportStart, "isIslandExportStart");
|
|
16099
|
+
function getIslandStrategyExport(content) {
|
|
16100
|
+
if (!content) return null;
|
|
16101
|
+
const tokens = tokenizeModuleSource(content);
|
|
16102
|
+
for (let index = 0; index < tokens.length - 2; index++) {
|
|
16103
|
+
if (!isIslandExportStart(tokens, index)) continue;
|
|
16104
|
+
let valueIndex = index + 3;
|
|
16105
|
+
if (tokens[valueIndex]?.value === ":") {
|
|
16106
|
+
while (valueIndex < tokens.length && tokens[valueIndex].value !== "=") valueIndex++;
|
|
16107
|
+
}
|
|
16108
|
+
if (tokens[valueIndex]?.value !== "=") break;
|
|
16109
|
+
valueIndex++;
|
|
16110
|
+
const literal = tokens[valueIndex];
|
|
16111
|
+
if (!literal || literal.kind !== "string" || !isFarmIslandStrategy(literal.value)) break;
|
|
16112
|
+
let trailingIndex = valueIndex + 1;
|
|
16113
|
+
if (tokens[trailingIndex]?.value === "as" && tokens[trailingIndex + 1]?.value === "const") {
|
|
16114
|
+
trailingIndex += 2;
|
|
16115
|
+
}
|
|
16116
|
+
const trailing = tokens[trailingIndex];
|
|
16117
|
+
if (trailing && trailing.value !== ";" && trailing.line === literal.line) break;
|
|
16118
|
+
return literal.value;
|
|
16119
|
+
}
|
|
16120
|
+
if (tokens.some((_token, index) => isIslandExportStart(tokens, index))) {
|
|
16121
|
+
throw new Error(
|
|
16122
|
+
'Farm island configuration must be a static "load", "interaction", "visible", or "idle" string literal.'
|
|
16123
|
+
);
|
|
16124
|
+
}
|
|
16125
|
+
return null;
|
|
16126
|
+
}
|
|
16127
|
+
__name(getIslandStrategyExport, "getIslandStrategyExport");
|
|
15214
16128
|
function stripUseClientDirective(content) {
|
|
15215
16129
|
return content.replace(/^\s*(["'])use client\1\s*;?\s*/, "");
|
|
15216
16130
|
}
|
|
15217
16131
|
__name(stripUseClientDirective, "stripUseClientDirective");
|
|
15218
|
-
function parseClientModuleMetadata(content) {
|
|
16132
|
+
function parseClientModuleMetadata(content, inspectIslandExport) {
|
|
15219
16133
|
if (!content) {
|
|
15220
16134
|
return {
|
|
15221
16135
|
isClientComponent: false,
|
|
15222
|
-
hasHydrateExport: false
|
|
16136
|
+
hasHydrateExport: false,
|
|
16137
|
+
islandStrategy: null
|
|
15223
16138
|
};
|
|
15224
16139
|
}
|
|
16140
|
+
const isClientComponent = hasUseClientDirective(content);
|
|
16141
|
+
const hasHydrate = hasHydrateExport(content);
|
|
15225
16142
|
return {
|
|
15226
|
-
isClientComponent
|
|
15227
|
-
hasHydrateExport:
|
|
16143
|
+
isClientComponent,
|
|
16144
|
+
hasHydrateExport: hasHydrate,
|
|
16145
|
+
islandStrategy: inspectIslandExport || isClientComponent || hasHydrate ? getIslandStrategyExport(content) : null
|
|
15228
16146
|
};
|
|
15229
16147
|
}
|
|
15230
16148
|
__name(parseClientModuleMetadata, "parseClientModuleMetadata");
|
|
15231
16149
|
function getClientModuleMetadata(modulePath, root) {
|
|
15232
16150
|
const resolvedPath = resolveModuleSourcePath(modulePath, root);
|
|
15233
|
-
return inspectClientModuleMetadata(resolvedPath, root, /* @__PURE__ */ new Set());
|
|
16151
|
+
return inspectClientModuleMetadata(resolvedPath, root, /* @__PURE__ */ new Set(), true);
|
|
15234
16152
|
}
|
|
15235
16153
|
__name(getClientModuleMetadata, "getClientModuleMetadata");
|
|
15236
|
-
function inspectClientModuleMetadata(resolvedPath, root, visited) {
|
|
16154
|
+
function inspectClientModuleMetadata(resolvedPath, root, visited, inspectIslandExport) {
|
|
15237
16155
|
if (!resolvedPath || visited.has(resolvedPath)) {
|
|
15238
16156
|
return {
|
|
15239
16157
|
isClientComponent: false,
|
|
15240
|
-
shouldHydrate: false
|
|
16158
|
+
shouldHydrate: false,
|
|
16159
|
+
islandStrategy: null
|
|
15241
16160
|
};
|
|
15242
16161
|
}
|
|
15243
16162
|
visited.add(resolvedPath);
|
|
15244
16163
|
const content = readIfExists(resolvedPath);
|
|
15245
|
-
const parsed = parseClientModuleMetadata(content);
|
|
16164
|
+
const parsed = parseClientModuleMetadata(content, inspectIslandExport);
|
|
15246
16165
|
if (parsed.isClientComponent) {
|
|
15247
16166
|
return {
|
|
15248
16167
|
isClientComponent: true,
|
|
15249
|
-
shouldHydrate: true
|
|
16168
|
+
shouldHydrate: true,
|
|
16169
|
+
islandStrategy: parsed.islandStrategy ?? "load"
|
|
15250
16170
|
};
|
|
15251
16171
|
}
|
|
15252
16172
|
let importsClientBoundary = false;
|
|
16173
|
+
let importedIslandStrategy = null;
|
|
15253
16174
|
for (const specifier of getRelativeImportSpecifiers(content)) {
|
|
15254
16175
|
const importedPath = resolveImportedModuleSourcePath(resolvedPath, specifier, root);
|
|
15255
|
-
const importedMetadata = inspectClientModuleMetadata(importedPath, root, visited);
|
|
16176
|
+
const importedMetadata = inspectClientModuleMetadata(importedPath, root, visited, false);
|
|
15256
16177
|
if (importedMetadata.isClientComponent || importedMetadata.shouldHydrate) {
|
|
15257
16178
|
importsClientBoundary = true;
|
|
15258
|
-
|
|
16179
|
+
if (importedIslandStrategy === null) {
|
|
16180
|
+
importedIslandStrategy = importedMetadata.islandStrategy;
|
|
16181
|
+
} else if (importedIslandStrategy !== importedMetadata.islandStrategy) {
|
|
16182
|
+
importedIslandStrategy = "load";
|
|
16183
|
+
}
|
|
15259
16184
|
}
|
|
15260
16185
|
}
|
|
16186
|
+
const shouldHydrate = parsed.hasHydrateExport || importsClientBoundary;
|
|
15261
16187
|
return {
|
|
15262
16188
|
isClientComponent: false,
|
|
15263
|
-
shouldHydrate
|
|
16189
|
+
shouldHydrate,
|
|
16190
|
+
islandStrategy: shouldHydrate ? parsed.islandStrategy ?? importedIslandStrategy ?? "load" : null
|
|
15264
16191
|
};
|
|
15265
16192
|
}
|
|
15266
16193
|
__name(inspectClientModuleMetadata, "inspectClientModuleMetadata");
|
|
@@ -15516,6 +16443,10 @@ function parseInterceptionMarker(segment) {
|
|
|
15516
16443
|
__name(parseInterceptionMarker, "parseInterceptionMarker");
|
|
15517
16444
|
|
|
15518
16445
|
// src/routing/route-manager.ts
|
|
16446
|
+
function shouldSuggestStaticRenderingForI18n(i18n) {
|
|
16447
|
+
return !i18n || i18n.routing === "prefix-always" || i18n.routing === "prefix-except-default" && i18n.detection.every((signal) => signal === "url");
|
|
16448
|
+
}
|
|
16449
|
+
__name(shouldSuggestStaticRenderingForI18n, "shouldSuggestStaticRenderingForI18n");
|
|
15519
16450
|
function routeSpecificity(entry) {
|
|
15520
16451
|
return entry.route.segments.reduce((score, segment) => {
|
|
15521
16452
|
if (!segment.isDynamic) return score + 100;
|
|
@@ -15759,6 +16690,7 @@ var _RouteManager = class _RouteManager {
|
|
|
15759
16690
|
modulePath: toUrlPath(entry.modulePath),
|
|
15760
16691
|
shouldHydrate: metadata.shouldHydrate,
|
|
15761
16692
|
isClientComponent: metadata.isClientComponent,
|
|
16693
|
+
islandStrategy: metadata.islandStrategy,
|
|
15762
16694
|
search: getProgrammaticRouteSearchClientOptions(programmaticPage?.search),
|
|
15763
16695
|
segments: entry.route.segments.map((seg) => ({
|
|
15764
16696
|
segment: seg.segment,
|
|
@@ -16221,8 +17153,10 @@ var _RouteManager = class _RouteManager {
|
|
|
16221
17153
|
isDynamic: entry.route.segments.some((seg) => seg.isDynamic),
|
|
16222
17154
|
pattern: entry.pattern
|
|
16223
17155
|
}));
|
|
16224
|
-
const result = await collectSSGPages(routes, (filePath) => this.loadRouteModule(filePath));
|
|
16225
17156
|
const i18n = this.getI18nConfig();
|
|
17157
|
+
const result = await collectSSGPages(routes, (filePath) => this.loadRouteModule(filePath), {
|
|
17158
|
+
suggestStaticRendering: shouldSuggestStaticRenderingForI18n(i18n)
|
|
17159
|
+
});
|
|
16226
17160
|
if (!i18n) {
|
|
16227
17161
|
return result;
|
|
16228
17162
|
}
|
|
@@ -16353,8 +17287,8 @@ async function safeGlobFiles(pattern, cwd) {
|
|
|
16353
17287
|
__name(safeGlobFiles, "safeGlobFiles");
|
|
16354
17288
|
|
|
16355
17289
|
// src/server/renderer.ts
|
|
16356
|
-
var
|
|
16357
|
-
var
|
|
17290
|
+
var import_react5 = __toESM(require("react"));
|
|
17291
|
+
var import_server2 = require("react-dom/server");
|
|
16358
17292
|
var fs2 = __toESM(require("fs"));
|
|
16359
17293
|
var path9 = __toESM(require("path"));
|
|
16360
17294
|
var import_stream = require("stream");
|
|
@@ -17644,7 +18578,8 @@ __name(transformFarmFontCalls, "transformFarmFontCalls");
|
|
|
17644
18578
|
function renderFarmFontDevHead(root) {
|
|
17645
18579
|
const registry = registries.get(normalizeRoot(root));
|
|
17646
18580
|
if (!registry || registry.production || registry.size === 0) return "";
|
|
17647
|
-
return registry.renderPreloadTags(false)
|
|
18581
|
+
return `${registry.renderPreloadTags(false)}
|
|
18582
|
+
<link rel="stylesheet" href="/@farm/fonts.css">`;
|
|
17648
18583
|
}
|
|
17649
18584
|
__name(renderFarmFontDevHead, "renderFarmFontDevHead");
|
|
17650
18585
|
var _FarmFontRegistry = class _FarmFontRegistry {
|
|
@@ -17826,6 +18761,10 @@ ${FONT_SECTION_END}
|
|
|
17826
18761
|
fallback,
|
|
17827
18762
|
display,
|
|
17828
18763
|
preload: raw.preload !== false,
|
|
18764
|
+
preloadResources: raw.preload === false ? [] : normalizedSources.map(({ resource }) => ({
|
|
18765
|
+
href: resourceUrl(resource, production, this.basePath),
|
|
18766
|
+
type: fontContentType(resource.extension)
|
|
18767
|
+
})),
|
|
17829
18768
|
weight: defaultWeight,
|
|
17830
18769
|
style: raw.style === void 0 ? void 0 : defaultStyle,
|
|
17831
18770
|
sources: normalizedSources
|
|
@@ -17922,7 +18861,7 @@ ${FONT_SECTION_END}
|
|
|
17922
18861
|
const normalizedExtension = extension.toLowerCase();
|
|
17923
18862
|
const hash = (0, import_node_crypto2.createHash)("sha256").update(bytes).digest("hex").slice(0, 12);
|
|
17924
18863
|
const baseName = sanitizeFileName(import_node_path4.default.basename(fileName, extension)) || "font";
|
|
17925
|
-
const outputFileName = `assets/fonts/${baseName}
|
|
18864
|
+
const outputFileName = `assets/fonts/${baseName}-h${hash}${normalizedExtension}`;
|
|
17926
18865
|
const key = `${hash}${normalizedExtension}`;
|
|
17927
18866
|
const existing = this.resources.get(key);
|
|
17928
18867
|
if (existing) return existing;
|
|
@@ -18192,7 +19131,8 @@ function serializeFontResult(font) {
|
|
|
18192
19131
|
fontFamily: stack,
|
|
18193
19132
|
...font.style ? { fontStyle: font.style } : {},
|
|
18194
19133
|
...font.weight !== void 0 && !String(font.weight).includes(" ") ? { fontWeight: font.weight } : {}
|
|
18195
|
-
}
|
|
19134
|
+
},
|
|
19135
|
+
preloads: font.preloadResources
|
|
18196
19136
|
});
|
|
18197
19137
|
}
|
|
18198
19138
|
__name(serializeFontResult, "serializeFontResult");
|
|
@@ -18535,6 +19475,166 @@ function fontError(id, message) {
|
|
|
18535
19475
|
}
|
|
18536
19476
|
__name(fontError, "fontError");
|
|
18537
19477
|
|
|
19478
|
+
// src/metadata-image.ts
|
|
19479
|
+
var import_react4 = __toESM(require("react"));
|
|
19480
|
+
var import_server = require("react-dom/server");
|
|
19481
|
+
var REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref");
|
|
19482
|
+
var REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo");
|
|
19483
|
+
var REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy");
|
|
19484
|
+
function isResponse(value) {
|
|
19485
|
+
return typeof Response !== "undefined" && (value instanceof Response || Boolean(
|
|
19486
|
+
value && typeof value === "object" && typeof value.arrayBuffer === "function" && value.headers
|
|
19487
|
+
));
|
|
19488
|
+
}
|
|
19489
|
+
__name(isResponse, "isResponse");
|
|
19490
|
+
function isThenable(value) {
|
|
19491
|
+
return Boolean(
|
|
19492
|
+
value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function"
|
|
19493
|
+
);
|
|
19494
|
+
}
|
|
19495
|
+
__name(isThenable, "isThenable");
|
|
19496
|
+
async function prepareMetadataImageNode(node) {
|
|
19497
|
+
if (isThenable(node)) {
|
|
19498
|
+
return prepareMetadataImageNode(await node);
|
|
19499
|
+
}
|
|
19500
|
+
if (Array.isArray(node)) {
|
|
19501
|
+
return Promise.all(node.map((child) => prepareMetadataImageNode(child)));
|
|
19502
|
+
}
|
|
19503
|
+
if (!import_react4.default.isValidElement(node)) {
|
|
19504
|
+
return node;
|
|
19505
|
+
}
|
|
19506
|
+
const element = node;
|
|
19507
|
+
const type = element.type;
|
|
19508
|
+
const props = element.props || {};
|
|
19509
|
+
if (typeof type === "function") {
|
|
19510
|
+
if (type.prototype?.isReactComponent) {
|
|
19511
|
+
throw new Error(
|
|
19512
|
+
"Metadata image components must be stateless function components; React class components are not supported."
|
|
19513
|
+
);
|
|
19514
|
+
}
|
|
19515
|
+
return prepareMetadataImageNode(await type(props));
|
|
19516
|
+
}
|
|
19517
|
+
if (type && typeof type === "object") {
|
|
19518
|
+
if (type.$$typeof === REACT_MEMO_TYPE) {
|
|
19519
|
+
return prepareMetadataImageNode(import_react4.default.createElement(type.type, props));
|
|
19520
|
+
}
|
|
19521
|
+
if (type.$$typeof === REACT_FORWARD_REF_TYPE) {
|
|
19522
|
+
return prepareMetadataImageNode(await type.render(props, null));
|
|
19523
|
+
}
|
|
19524
|
+
if (type.$$typeof === REACT_LAZY_TYPE) {
|
|
19525
|
+
return prepareMetadataImageNode(import_react4.default.createElement(type._init(type._payload), props));
|
|
19526
|
+
}
|
|
19527
|
+
}
|
|
19528
|
+
const preparedChildren = await prepareMetadataImageNode(props.children);
|
|
19529
|
+
const preparedProps = { ...props };
|
|
19530
|
+
if (typeof preparedProps.className === "string") {
|
|
19531
|
+
preparedProps.tw = [preparedProps.tw, preparedProps.className].filter(Boolean).join(" ");
|
|
19532
|
+
delete preparedProps.className;
|
|
19533
|
+
}
|
|
19534
|
+
delete preparedProps.children;
|
|
19535
|
+
return import_react4.default.createElement(type, {
|
|
19536
|
+
...preparedProps,
|
|
19537
|
+
key: element.key,
|
|
19538
|
+
children: preparedChildren
|
|
19539
|
+
});
|
|
19540
|
+
}
|
|
19541
|
+
__name(prepareMetadataImageNode, "prepareMetadataImageNode");
|
|
19542
|
+
async function normalizeFonts(fonts) {
|
|
19543
|
+
if (!fonts?.length) return void 0;
|
|
19544
|
+
return Promise.all(
|
|
19545
|
+
fonts.map(async (font) => {
|
|
19546
|
+
const data = await font.data;
|
|
19547
|
+
const arrayBuffer = ArrayBuffer.isView(data) ? toArrayBuffer(data) : data;
|
|
19548
|
+
return { ...font, data: arrayBuffer };
|
|
19549
|
+
})
|
|
19550
|
+
);
|
|
19551
|
+
}
|
|
19552
|
+
__name(normalizeFonts, "normalizeFonts");
|
|
19553
|
+
function resolveCacheControl(revalidate) {
|
|
19554
|
+
if (revalidate === false) {
|
|
19555
|
+
return "public, max-age=31536000, immutable";
|
|
19556
|
+
}
|
|
19557
|
+
if (typeof revalidate === "number" && Number.isFinite(revalidate) && revalidate > 0) {
|
|
19558
|
+
return `public, s-maxage=${Math.floor(revalidate)}, stale-while-revalidate=300`;
|
|
19559
|
+
}
|
|
19560
|
+
return "public, max-age=0, must-revalidate";
|
|
19561
|
+
}
|
|
19562
|
+
__name(resolveCacheControl, "resolveCacheControl");
|
|
19563
|
+
function toArrayBuffer(value) {
|
|
19564
|
+
if (value instanceof ArrayBuffer) return value;
|
|
19565
|
+
const bytes = new Uint8Array(value.byteLength);
|
|
19566
|
+
bytes.set(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
|
|
19567
|
+
return bytes.buffer;
|
|
19568
|
+
}
|
|
19569
|
+
__name(toArrayBuffer, "toArrayBuffer");
|
|
19570
|
+
async function createEntityTag(body) {
|
|
19571
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", body);
|
|
19572
|
+
const hash = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, 32);
|
|
19573
|
+
return `"${hash}"`;
|
|
19574
|
+
}
|
|
19575
|
+
__name(createEntityTag, "createEntityTag");
|
|
19576
|
+
async function finalizeMetadataImageResponse(body, headers, options) {
|
|
19577
|
+
const responseHeaders = new Headers(headers);
|
|
19578
|
+
const etag = await createEntityTag(body);
|
|
19579
|
+
responseHeaders.set("ETag", etag);
|
|
19580
|
+
responseHeaders.set("Content-Length", String(body.byteLength));
|
|
19581
|
+
responseHeaders.set("X-Content-Type-Options", "nosniff");
|
|
19582
|
+
const matchesEntityTag = options.ifNoneMatch?.trim() === "*" || options.ifNoneMatch?.split(",").some((candidate) => candidate.trim().replace(/^W\//, "") === etag);
|
|
19583
|
+
if (matchesEntityTag) {
|
|
19584
|
+
return new Response(null, { status: 304, headers: responseHeaders });
|
|
19585
|
+
}
|
|
19586
|
+
return new Response(options.method?.toUpperCase() === "HEAD" ? null : body, {
|
|
19587
|
+
status: 200,
|
|
19588
|
+
headers: responseHeaders
|
|
19589
|
+
});
|
|
19590
|
+
}
|
|
19591
|
+
__name(finalizeMetadataImageResponse, "finalizeMetadataImageResponse");
|
|
19592
|
+
async function createFarmMetadataImageResponse(value, imageModule, options = {}) {
|
|
19593
|
+
const method = (options.method || "GET").toUpperCase();
|
|
19594
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
19595
|
+
return new Response(null, { status: 405, headers: { Allow: "GET, HEAD" } });
|
|
19596
|
+
}
|
|
19597
|
+
if (isResponse(value)) {
|
|
19598
|
+
return method === "HEAD" ? new Response(null, { status: value.status, headers: value.headers }) : value;
|
|
19599
|
+
}
|
|
19600
|
+
const cacheControl = resolveCacheControl(imageModule.revalidate);
|
|
19601
|
+
const explicitContentType = imageModule.contentType?.split(";", 1)[0]?.trim().toLowerCase();
|
|
19602
|
+
if (import_react4.default.isValidElement(value) && explicitContentType !== "image/svg+xml") {
|
|
19603
|
+
const { ImageResponse } = await import("@vercel/og");
|
|
19604
|
+
const element = await prepareMetadataImageNode(value);
|
|
19605
|
+
const response = new ImageResponse(element, {
|
|
19606
|
+
width: imageModule.size?.width || 1200,
|
|
19607
|
+
height: imageModule.size?.height || 630,
|
|
19608
|
+
fonts: await normalizeFonts(imageModule.fonts),
|
|
19609
|
+
emoji: imageModule.emoji,
|
|
19610
|
+
debug: imageModule.debug,
|
|
19611
|
+
headers: { "cache-control": cacheControl }
|
|
19612
|
+
});
|
|
19613
|
+
const headers = new Headers(response.headers);
|
|
19614
|
+
headers.set("Cache-Control", cacheControl);
|
|
19615
|
+
return finalizeMetadataImageResponse(await response.arrayBuffer(), headers, options);
|
|
19616
|
+
}
|
|
19617
|
+
let body;
|
|
19618
|
+
if (typeof value === "string") {
|
|
19619
|
+
body = toArrayBuffer(new TextEncoder().encode(value));
|
|
19620
|
+
} else if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {
|
|
19621
|
+
body = toArrayBuffer(value);
|
|
19622
|
+
} else if (import_react4.default.isValidElement(value)) {
|
|
19623
|
+
body = toArrayBuffer(new TextEncoder().encode((0, import_server.renderToStaticMarkup)(value)));
|
|
19624
|
+
} else {
|
|
19625
|
+
throw new Error("Metadata image must return a Response, string, bytes, or React element");
|
|
19626
|
+
}
|
|
19627
|
+
return finalizeMetadataImageResponse(
|
|
19628
|
+
body,
|
|
19629
|
+
{
|
|
19630
|
+
"Content-Type": imageModule.contentType || "image/svg+xml; charset=utf-8",
|
|
19631
|
+
"Cache-Control": cacheControl
|
|
19632
|
+
},
|
|
19633
|
+
options
|
|
19634
|
+
);
|
|
19635
|
+
}
|
|
19636
|
+
__name(createFarmMetadataImageResponse, "createFarmMetadataImageResponse");
|
|
19637
|
+
|
|
18538
19638
|
// src/server/renderer.ts
|
|
18539
19639
|
var cachedClerkProvider = null;
|
|
18540
19640
|
var importRuntimeModule = new Function("specifier", "return import(specifier);");
|
|
@@ -18608,7 +19708,7 @@ function createPPRRefreshScript() {
|
|
|
18608
19708
|
}
|
|
18609
19709
|
__name(createPPRRefreshScript, "createPPRRefreshScript");
|
|
18610
19710
|
function createPreHydrationClickQueueScript() {
|
|
18611
|
-
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>`;
|
|
19711
|
+
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>`;
|
|
18612
19712
|
}
|
|
18613
19713
|
__name(createPreHydrationClickQueueScript, "createPreHydrationClickQueueScript");
|
|
18614
19714
|
function searchParamsToObject(searchParams) {
|
|
@@ -18659,7 +19759,7 @@ function isWebResponse(value) {
|
|
|
18659
19759
|
return typeof Response !== "undefined" && value instanceof Response && typeof value.arrayBuffer === "function";
|
|
18660
19760
|
}
|
|
18661
19761
|
__name(isWebResponse, "isWebResponse");
|
|
18662
|
-
var _FarmRouteErrorBoundary = class _FarmRouteErrorBoundary extends
|
|
19762
|
+
var _FarmRouteErrorBoundary = class _FarmRouteErrorBoundary extends import_react5.default.Component {
|
|
18663
19763
|
constructor(props) {
|
|
18664
19764
|
super(props);
|
|
18665
19765
|
this.state = { hasError: false, error: null };
|
|
@@ -18670,7 +19770,7 @@ var _FarmRouteErrorBoundary = class _FarmRouteErrorBoundary extends import_react
|
|
|
18670
19770
|
render() {
|
|
18671
19771
|
if (this.state.hasError) {
|
|
18672
19772
|
const Fallback = this.props.Fallback;
|
|
18673
|
-
return
|
|
19773
|
+
return import_react5.default.createElement(Fallback, {
|
|
18674
19774
|
...this.props.fallbackProps,
|
|
18675
19775
|
error: this.state.error,
|
|
18676
19776
|
reset: /* @__PURE__ */ __name(() => this.setState({ hasError: false, error: null }), "reset")
|
|
@@ -18886,14 +19986,14 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
18886
19986
|
searchParams: Promise.resolve({}),
|
|
18887
19987
|
path: page2.urlPath
|
|
18888
19988
|
};
|
|
18889
|
-
let pageElement =
|
|
19989
|
+
let pageElement = import_react5.default.createElement(
|
|
18890
19990
|
PageComponent,
|
|
18891
19991
|
pageProps
|
|
18892
19992
|
);
|
|
18893
19993
|
for (let i = layoutModules.length - 1; i >= 0; i--) {
|
|
18894
19994
|
const layoutModule = layoutModules[i];
|
|
18895
19995
|
const LayoutComponent = layoutModule.default;
|
|
18896
|
-
pageElement =
|
|
19996
|
+
pageElement = import_react5.default.createElement(
|
|
18897
19997
|
LayoutComponent,
|
|
18898
19998
|
{
|
|
18899
19999
|
children: pageElement,
|
|
@@ -19219,6 +20319,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19219
20319
|
req.__FARM_ROUTE__ = pathname;
|
|
19220
20320
|
req.__FARM_IS_CLIENT_COMPONENT__ = isClientComponent;
|
|
19221
20321
|
req.__FARM_SHOULD_HYDRATE__ = shouldHydrate;
|
|
20322
|
+
req.__FARM_ISLAND_STRATEGY__ = moduleMetadata.islandStrategy;
|
|
19222
20323
|
req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ = hasHydratableRouteSlots;
|
|
19223
20324
|
req.__FARM_LOADING_MODULE_PATH__ = loadingBoundaryEntry?.modulePath ? loadingBoundaryEntry.modulePath.substring(
|
|
19224
20325
|
loadingBoundaryEntry.modulePath.indexOf("/src/app/")
|
|
@@ -19271,12 +20372,12 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19271
20372
|
await _runWithMiddlewareData(middlewareDataForContext, async () => {
|
|
19272
20373
|
await _runWithMiddlewareContext(middlewareContext, async () => {
|
|
19273
20374
|
await _runWithCurrentRequest(currentRequest, async () => {
|
|
19274
|
-
let pageElement =
|
|
20375
|
+
let pageElement = import_react5.default.createElement(
|
|
19275
20376
|
PageComponent,
|
|
19276
20377
|
pageProps
|
|
19277
20378
|
);
|
|
19278
20379
|
if (LoadingFallbackComponent) {
|
|
19279
|
-
const loadingFallback =
|
|
20380
|
+
const loadingFallback = import_react5.default.createElement(LoadingFallbackComponent, {
|
|
19280
20381
|
...createRouteStateProps({
|
|
19281
20382
|
params,
|
|
19282
20383
|
searchParamsObject,
|
|
@@ -19285,16 +20386,21 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19285
20386
|
pluginExposedContext
|
|
19286
20387
|
})
|
|
19287
20388
|
});
|
|
19288
|
-
pageElement =
|
|
19289
|
-
|
|
20389
|
+
pageElement = import_react5.default.createElement(
|
|
20390
|
+
import_react5.default.Suspense,
|
|
19290
20391
|
{ fallback: loadingFallback },
|
|
19291
20392
|
pageElement
|
|
19292
20393
|
);
|
|
19293
20394
|
}
|
|
19294
20395
|
if (isClientComponent || shouldHydrate) {
|
|
19295
|
-
pageElement =
|
|
20396
|
+
pageElement = import_react5.default.createElement(
|
|
19296
20397
|
"div",
|
|
19297
|
-
{
|
|
20398
|
+
{
|
|
20399
|
+
id: "__farm_page__",
|
|
20400
|
+
"data-farm-client": "true",
|
|
20401
|
+
"data-farm-island": "page",
|
|
20402
|
+
"data-farm-island-strategy": moduleMetadata.islandStrategy ?? "load"
|
|
20403
|
+
},
|
|
19298
20404
|
pageElement
|
|
19299
20405
|
);
|
|
19300
20406
|
}
|
|
@@ -19306,11 +20412,11 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19306
20412
|
const slotProps = {};
|
|
19307
20413
|
for (const slot of renderedRouteSlots) {
|
|
19308
20414
|
if (slot.ownerPattern !== layoutEntry.pattern) continue;
|
|
19309
|
-
let slotElement =
|
|
20415
|
+
let slotElement = import_react5.default.createElement(
|
|
19310
20416
|
slot.module.default,
|
|
19311
20417
|
slot.props
|
|
19312
20418
|
);
|
|
19313
|
-
slotElement =
|
|
20419
|
+
slotElement = import_react5.default.createElement(
|
|
19314
20420
|
"div",
|
|
19315
20421
|
{
|
|
19316
20422
|
id: slot.containerId,
|
|
@@ -19321,7 +20427,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19321
20427
|
);
|
|
19322
20428
|
slotProps[slot.name] = slotElement;
|
|
19323
20429
|
}
|
|
19324
|
-
wrappedElement =
|
|
20430
|
+
wrappedElement = import_react5.default.createElement(
|
|
19325
20431
|
LayoutComponent,
|
|
19326
20432
|
{
|
|
19327
20433
|
children: wrappedElement,
|
|
@@ -19331,7 +20437,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19331
20437
|
);
|
|
19332
20438
|
}
|
|
19333
20439
|
if (ErrorFallbackComponent) {
|
|
19334
|
-
wrappedElement =
|
|
20440
|
+
wrappedElement = import_react5.default.createElement(
|
|
19335
20441
|
FarmRouteErrorBoundary,
|
|
19336
20442
|
{
|
|
19337
20443
|
Fallback: ErrorFallbackComponent,
|
|
@@ -19464,7 +20570,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19464
20570
|
if (!cachedClerkProvider) {
|
|
19465
20571
|
cachedClerkProvider = await importRuntimeModule("@clerk/react");
|
|
19466
20572
|
}
|
|
19467
|
-
wrapped =
|
|
20573
|
+
wrapped = import_react5.default.createElement(
|
|
19468
20574
|
cachedClerkProvider.ClerkProvider,
|
|
19469
20575
|
provider.props || {},
|
|
19470
20576
|
wrapped
|
|
@@ -19539,6 +20645,13 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19539
20645
|
return reference;
|
|
19540
20646
|
}
|
|
19541
20647
|
async renderMetadataImage(req, res, options) {
|
|
20648
|
+
const method = (req.method || "GET").toUpperCase();
|
|
20649
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
20650
|
+
res.statusCode = 405;
|
|
20651
|
+
res.setHeader("Allow", "GET, HEAD");
|
|
20652
|
+
res.end();
|
|
20653
|
+
return;
|
|
20654
|
+
}
|
|
19542
20655
|
if (options.image.sourceType === "static") {
|
|
19543
20656
|
if (!options.image.staticInfo) {
|
|
19544
20657
|
throw new Error(`Static metadata image ${options.image.modulePath} is missing file info`);
|
|
@@ -19564,42 +20677,12 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19564
20677
|
await this.writeMetadataImageResponse(req, res, handlerResult, imageModule);
|
|
19565
20678
|
}
|
|
19566
20679
|
async writeMetadataImageResponse(req, res, value, imageModule) {
|
|
19567
|
-
|
|
19568
|
-
|
|
19569
|
-
|
|
19570
|
-
|
|
19571
|
-
|
|
19572
|
-
|
|
19573
|
-
res.end();
|
|
19574
|
-
return;
|
|
19575
|
-
}
|
|
19576
|
-
const body2 = Buffer.from(await value.arrayBuffer());
|
|
19577
|
-
res.write(body2);
|
|
19578
|
-
res.end();
|
|
19579
|
-
return;
|
|
19580
|
-
}
|
|
19581
|
-
const contentType = imageModule.contentType || "image/svg+xml; charset=utf-8";
|
|
19582
|
-
let body;
|
|
19583
|
-
if (typeof value === "string") {
|
|
19584
|
-
body = value;
|
|
19585
|
-
} else if (value instanceof ArrayBuffer) {
|
|
19586
|
-
body = Buffer.from(value);
|
|
19587
|
-
} else if (ArrayBuffer.isView(value)) {
|
|
19588
|
-
body = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
19589
|
-
} else if (import_react4.default.isValidElement(value)) {
|
|
19590
|
-
body = (0, import_server.renderToStaticMarkup)(value);
|
|
19591
|
-
} else {
|
|
19592
|
-
throw new Error("Metadata image must return a Response, string, bytes, or React element");
|
|
19593
|
-
}
|
|
19594
|
-
res.statusCode = res.statusCode || 200;
|
|
19595
|
-
res.setHeader("Content-Type", contentType);
|
|
19596
|
-
res.setHeader("Cache-Control", "public, max-age=0, must-revalidate");
|
|
19597
|
-
if (req.method === "HEAD") {
|
|
19598
|
-
res.end();
|
|
19599
|
-
return;
|
|
19600
|
-
}
|
|
19601
|
-
res.write(body);
|
|
19602
|
-
res.end();
|
|
20680
|
+
const ifNoneMatch = req.headers["if-none-match"];
|
|
20681
|
+
const response = await createFarmMetadataImageResponse(value, imageModule, {
|
|
20682
|
+
method: req.method,
|
|
20683
|
+
ifNoneMatch: Array.isArray(ifNoneMatch) ? ifNoneMatch[0] : ifNoneMatch
|
|
20684
|
+
});
|
|
20685
|
+
await sendWebResponse(res, response);
|
|
19603
20686
|
}
|
|
19604
20687
|
async writeStaticMetadataImageResponse(req, res, image) {
|
|
19605
20688
|
const method = (req.method || "GET").toUpperCase();
|
|
@@ -19646,7 +20729,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19646
20729
|
return false;
|
|
19647
20730
|
}
|
|
19648
20731
|
const ErrorComponent = errorModule.default;
|
|
19649
|
-
const errorElement =
|
|
20732
|
+
const errorElement = import_react5.default.createElement(ErrorComponent, {
|
|
19650
20733
|
...createRouteStateProps({
|
|
19651
20734
|
params: options.params,
|
|
19652
20735
|
searchParamsObject: options.searchParamsObject,
|
|
@@ -19664,7 +20747,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19664
20747
|
);
|
|
19665
20748
|
for (let i = layoutModules.length - 1; i >= 0; i--) {
|
|
19666
20749
|
const LayoutComponent = layoutModules[i].default;
|
|
19667
|
-
wrapped =
|
|
20750
|
+
wrapped = import_react5.default.createElement(
|
|
19668
20751
|
LayoutComponent,
|
|
19669
20752
|
{
|
|
19670
20753
|
children: wrapped,
|
|
@@ -19729,6 +20812,7 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
19729
20812
|
search: routeEntry.search,
|
|
19730
20813
|
isClientComponent: routeEntry.isClientComponent,
|
|
19731
20814
|
shouldHydrate: routeEntry.shouldHydrate,
|
|
20815
|
+
islandStrategy: routeEntry.islandStrategy,
|
|
19732
20816
|
preloads: [routeEntry.modulePath],
|
|
19733
20817
|
assets: []
|
|
19734
20818
|
};
|
|
@@ -19765,6 +20849,7 @@ window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(deploymentId)};
|
|
|
19765
20849
|
window.__FARM_PATH__ = ${JSON.stringify(req.__FARM_ROUTE__ || req.url || "/")};
|
|
19766
20850
|
window.__FARM_IS_CLIENT__ = ${JSON.stringify(isClientComponent)};
|
|
19767
20851
|
window.__FARM_SHOULD_HYDRATE__ = ${JSON.stringify(req.__FARM_SHOULD_HYDRATE__ === true)};
|
|
20852
|
+
window.__FARM_ISLAND_STRATEGY__ = ${JSON.stringify(req.__FARM_ISLAND_STRATEGY__ || "load")};
|
|
19768
20853
|
window.__FARM_PAGE_MODULE__ = ${JSON.stringify(relativePath2)};
|
|
19769
20854
|
window.__FARM_LOADING_MODULE__ = ${JSON.stringify(
|
|
19770
20855
|
req.__FARM_LOADING_MODULE_PATH__ || null
|
|
@@ -19782,8 +20867,8 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
19782
20867
|
const i18nSnapshot = getFarmI18nClientSnapshot();
|
|
19783
20868
|
const i18nAlternateTags = i18nSnapshot ? renderI18nAlternateLinks(req.__FARM_ROUTE__ || req.url || "/", i18nSnapshot) : "";
|
|
19784
20869
|
const fontHead = renderFarmFontDevHead(this.config.root || process.cwd());
|
|
19785
|
-
const streamRoot =
|
|
19786
|
-
const { pipe, abort } = (0,
|
|
20870
|
+
const streamRoot = import_react5.default.createElement("div", { style: { display: "contents" } }, element);
|
|
20871
|
+
const { pipe, abort } = (0, import_server2.renderToPipeableStream)(streamRoot, {
|
|
19787
20872
|
onShellReady() {
|
|
19788
20873
|
const shellReadyMs = Date.now() - streamStartTime;
|
|
19789
20874
|
emitFarmEvent({
|
|
@@ -19941,12 +21026,12 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
|
|
|
19941
21026
|
break;
|
|
19942
21027
|
}
|
|
19943
21028
|
}
|
|
19944
|
-
let element =
|
|
21029
|
+
let element = import_react5.default.createElement(
|
|
19945
21030
|
NotFoundComponent,
|
|
19946
21031
|
{ pathname }
|
|
19947
21032
|
);
|
|
19948
21033
|
if (LayoutComponent) {
|
|
19949
|
-
element =
|
|
21034
|
+
element = import_react5.default.createElement(
|
|
19950
21035
|
LayoutComponent,
|
|
19951
21036
|
{ children: element }
|
|
19952
21037
|
);
|
|
@@ -20060,6 +21145,7 @@ var import_path6 = __toESM(require("path"));
|
|
|
20060
21145
|
init_devtools_config();
|
|
20061
21146
|
init_config();
|
|
20062
21147
|
init_auth_config();
|
|
21148
|
+
init_preload();
|
|
20063
21149
|
var defaultDocsConfig = {
|
|
20064
21150
|
enabled: false,
|
|
20065
21151
|
entry: "/docs",
|
|
@@ -20128,6 +21214,7 @@ var _FarmApp = class _FarmApp {
|
|
|
20128
21214
|
context: config.context || (() => void 0),
|
|
20129
21215
|
serverActions: resolveServerActionsConfig(config.serverActions),
|
|
20130
21216
|
images: resolveFarmImageConfig(config.images),
|
|
21217
|
+
performance: resolveFarmPerformanceConfig(config.performance),
|
|
20131
21218
|
i18n: isResolvedI18nConfig(config.i18n) ? config.i18n : resolveFarmI18nConfig(config.i18n, {
|
|
20132
21219
|
root,
|
|
20133
21220
|
mode: process.env.NODE_ENV === "production" ? "production" : "development"
|
|
@@ -22364,7 +23451,7 @@ init_response();
|
|
|
22364
23451
|
init_integrations();
|
|
22365
23452
|
init_devtools_config();
|
|
22366
23453
|
var fs7 = __toESM(require("fs"));
|
|
22367
|
-
var
|
|
23454
|
+
var path25 = __toESM(require("path"));
|
|
22368
23455
|
init_layers();
|
|
22369
23456
|
|
|
22370
23457
|
// src/environment-vite.ts
|
|
@@ -22711,7 +23798,7 @@ function transformError(id, message) {
|
|
|
22711
23798
|
__name(transformError, "transformError");
|
|
22712
23799
|
|
|
22713
23800
|
// package.json
|
|
22714
|
-
var version = "0.1.0-beta.
|
|
23801
|
+
var version = "0.1.0-beta.13";
|
|
22715
23802
|
|
|
22716
23803
|
// src/version.ts
|
|
22717
23804
|
var FARM_VERSION = version;
|
|
@@ -22981,8 +24068,116 @@ async function createBlurDataURL(bytes) {
|
|
|
22981
24068
|
}
|
|
22982
24069
|
__name(createBlurDataURL, "createBlurDataURL");
|
|
22983
24070
|
|
|
24071
|
+
// src/font.ts
|
|
24072
|
+
function resolveFarmLayoutFonts(layouts) {
|
|
24073
|
+
let resolved;
|
|
24074
|
+
for (const layout2 of layouts) {
|
|
24075
|
+
if (!layout2.fonts) continue;
|
|
24076
|
+
resolved = { ...resolved, ...layout2.fonts };
|
|
24077
|
+
}
|
|
24078
|
+
return resolved;
|
|
24079
|
+
}
|
|
24080
|
+
__name(resolveFarmLayoutFonts, "resolveFarmLayoutFonts");
|
|
24081
|
+
|
|
22984
24082
|
// src/vite.ts
|
|
22985
24083
|
init_image_server();
|
|
24084
|
+
|
|
24085
|
+
// src/server/vite-config.ts
|
|
24086
|
+
var import_node_path9 = __toESM(require("path"));
|
|
24087
|
+
var FARM_CLIENT_ENTRY_PATTERN = "**/{page,layout,loading,error,not-found,default}.{js,jsx,ts,tsx}";
|
|
24088
|
+
var FARM_CLIENT_OPTIMIZE_DEPS_INCLUDE = [
|
|
24089
|
+
"react",
|
|
24090
|
+
"react-dom",
|
|
24091
|
+
"react-dom/client",
|
|
24092
|
+
"react/jsx-runtime",
|
|
24093
|
+
"react/jsx-dev-runtime",
|
|
24094
|
+
"@farm.js/core/client",
|
|
24095
|
+
"@farm.js/core/plugin/client",
|
|
24096
|
+
"@farm.js/core/deferred",
|
|
24097
|
+
"@farm.js/core/deployment",
|
|
24098
|
+
"@farm.js/core/i18n/client",
|
|
24099
|
+
"@farm.js/core/query/client",
|
|
24100
|
+
"@farm.js/core/server-fn/client",
|
|
24101
|
+
"@farm.js/core/server-query/client"
|
|
24102
|
+
];
|
|
24103
|
+
function createFarmClientOptimizeDepsEntries(projectRoot, appDirectories) {
|
|
24104
|
+
const resolvedProjectRoot = import_node_path9.default.resolve(projectRoot);
|
|
24105
|
+
return appDirectories.map((appDirectory) => {
|
|
24106
|
+
const relativeAppDirectory = import_node_path9.default.relative(resolvedProjectRoot, import_node_path9.default.resolve(appDirectory)).replace(/\\/g, "/");
|
|
24107
|
+
const prefix = relativeAppDirectory || ".";
|
|
24108
|
+
return `${prefix}/${FARM_CLIENT_ENTRY_PATTERN}`;
|
|
24109
|
+
});
|
|
24110
|
+
}
|
|
24111
|
+
__name(createFarmClientOptimizeDepsEntries, "createFarmClientOptimizeDepsEntries");
|
|
24112
|
+
function createFarmClientOptimizeDepsConfig(entries) {
|
|
24113
|
+
return {
|
|
24114
|
+
// Keep normal application dependency discovery for CJS-only packages, but
|
|
24115
|
+
// seed every Farm browser runtime so React is present in the first crawl.
|
|
24116
|
+
noDiscovery: false,
|
|
24117
|
+
// Waiting for the crawl avoids serving a partial optimizer generation and
|
|
24118
|
+
// then changing browser hashes while hydration is already in progress.
|
|
24119
|
+
holdUntilCrawlEnd: true,
|
|
24120
|
+
include: [...FARM_CLIENT_OPTIMIZE_DEPS_INCLUDE],
|
|
24121
|
+
// Farm's HTML boots through a virtual module and imports route UI lazily.
|
|
24122
|
+
// Explicit entries let Vite finish that crawl before a navigation can
|
|
24123
|
+
// rotate the optimizer hash underneath a hydrated React runtime.
|
|
24124
|
+
...entries?.length ? { entries: [...entries] } : {}
|
|
24125
|
+
};
|
|
24126
|
+
}
|
|
24127
|
+
__name(createFarmClientOptimizeDepsConfig, "createFarmClientOptimizeDepsConfig");
|
|
24128
|
+
function mergeNoExternal(farmValue, userValue) {
|
|
24129
|
+
if (farmValue === true || userValue === true) return true;
|
|
24130
|
+
const normalize = /* @__PURE__ */ __name((value) => value == null || value === true ? [] : Array.isArray(value) ? value : [value], "normalize");
|
|
24131
|
+
return Array.from(/* @__PURE__ */ new Set([...normalize(farmValue), ...normalize(userValue)]));
|
|
24132
|
+
}
|
|
24133
|
+
__name(mergeNoExternal, "mergeNoExternal");
|
|
24134
|
+
function mergeFarmViteConfig(farmConfig, userConfig = {}) {
|
|
24135
|
+
const noDiscovery = userConfig.optimizeDeps?.noDiscovery ?? farmConfig.optimizeDeps?.noDiscovery;
|
|
24136
|
+
const holdUntilCrawlEnd = userConfig.optimizeDeps?.holdUntilCrawlEnd ?? (userConfig.optimizeDeps?.noDiscovery === true ? false : farmConfig.optimizeDeps?.holdUntilCrawlEnd);
|
|
24137
|
+
return {
|
|
24138
|
+
...farmConfig,
|
|
24139
|
+
...userConfig,
|
|
24140
|
+
plugins: [...farmConfig.plugins || [], ...userConfig.plugins || []],
|
|
24141
|
+
server: {
|
|
24142
|
+
...farmConfig.server,
|
|
24143
|
+
...userConfig.server
|
|
24144
|
+
},
|
|
24145
|
+
resolve: {
|
|
24146
|
+
...farmConfig.resolve,
|
|
24147
|
+
...userConfig.resolve,
|
|
24148
|
+
dedupe: Array.from(
|
|
24149
|
+
/* @__PURE__ */ new Set([...farmConfig.resolve?.dedupe || [], ...userConfig.resolve?.dedupe || []])
|
|
24150
|
+
)
|
|
24151
|
+
},
|
|
24152
|
+
optimizeDeps: {
|
|
24153
|
+
...farmConfig.optimizeDeps,
|
|
24154
|
+
...userConfig.optimizeDeps,
|
|
24155
|
+
noDiscovery,
|
|
24156
|
+
holdUntilCrawlEnd,
|
|
24157
|
+
include: Array.from(
|
|
24158
|
+
/* @__PURE__ */ new Set([
|
|
24159
|
+
...farmConfig.optimizeDeps?.include || [],
|
|
24160
|
+
...userConfig.optimizeDeps?.include || []
|
|
24161
|
+
])
|
|
24162
|
+
),
|
|
24163
|
+
exclude: Array.from(
|
|
24164
|
+
/* @__PURE__ */ new Set([
|
|
24165
|
+
...farmConfig.optimizeDeps?.exclude || [],
|
|
24166
|
+
...userConfig.optimizeDeps?.exclude || []
|
|
24167
|
+
])
|
|
24168
|
+
)
|
|
24169
|
+
},
|
|
24170
|
+
ssr: {
|
|
24171
|
+
...farmConfig.ssr,
|
|
24172
|
+
...userConfig.ssr,
|
|
24173
|
+
noExternal: mergeNoExternal(farmConfig.ssr?.noExternal, userConfig.ssr?.noExternal)
|
|
24174
|
+
}
|
|
24175
|
+
};
|
|
24176
|
+
}
|
|
24177
|
+
__name(mergeFarmViteConfig, "mergeFarmViteConfig");
|
|
24178
|
+
|
|
24179
|
+
// src/vite.ts
|
|
24180
|
+
init_fonts();
|
|
22986
24181
|
var ALL_TYPE_ARTIFACTS = {
|
|
22987
24182
|
routes: true,
|
|
22988
24183
|
api: true,
|
|
@@ -23203,7 +24398,7 @@ function fileContainsProgrammaticPageRoute(file) {
|
|
|
23203
24398
|
__name(fileContainsProgrammaticPageRoute, "fileContainsProgrammaticPageRoute");
|
|
23204
24399
|
function rewriteEarlySsrRelativeImports(options) {
|
|
23205
24400
|
const cleanId = options.id.split("?", 1)[0];
|
|
23206
|
-
if (!
|
|
24401
|
+
if (!path25.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
|
|
23207
24402
|
return null;
|
|
23208
24403
|
}
|
|
23209
24404
|
const replacements = [];
|
|
@@ -23223,7 +24418,7 @@ function rewriteEarlySsrRelativeImports(options) {
|
|
|
23223
24418
|
const suffixIndex = source.value.search(/[?#]/);
|
|
23224
24419
|
const sourcePath = suffixIndex === -1 ? source.value : source.value.slice(0, suffixIndex);
|
|
23225
24420
|
const suffix = suffixIndex === -1 ? "" : source.value.slice(suffixIndex);
|
|
23226
|
-
const resolvedPath =
|
|
24421
|
+
const resolvedPath = path25.resolve(path25.dirname(cleanId), sourcePath);
|
|
23227
24422
|
replacements.push({
|
|
23228
24423
|
start: source.start,
|
|
23229
24424
|
end: source.end,
|
|
@@ -23308,7 +24503,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
23308
24503
|
...layerRoots.length ? {
|
|
23309
24504
|
server: {
|
|
23310
24505
|
fs: {
|
|
23311
|
-
allow: [
|
|
24506
|
+
allow: [path25.resolve(options.root || process.cwd()), ...layerRoots]
|
|
23312
24507
|
}
|
|
23313
24508
|
}
|
|
23314
24509
|
} : {}
|
|
@@ -23339,9 +24534,9 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
23339
24534
|
},
|
|
23340
24535
|
server
|
|
23341
24536
|
);
|
|
23342
|
-
const globalsCSSPath =
|
|
24537
|
+
const globalsCSSPath = path25.join(server.config.root, "src/app/globals.css");
|
|
23343
24538
|
if (!fs7.existsSync(globalsCSSPath)) {
|
|
23344
|
-
const appDir =
|
|
24539
|
+
const appDir = path25.join(server.config.root, "src/app");
|
|
23345
24540
|
if (!fs7.existsSync(appDir)) {
|
|
23346
24541
|
fs7.mkdirSync(appDir, { recursive: true });
|
|
23347
24542
|
}
|
|
@@ -23363,10 +24558,10 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
23363
24558
|
});
|
|
23364
24559
|
}
|
|
23365
24560
|
const sourceRoots = getFarmSourceRoots(farmConfig);
|
|
23366
|
-
server.watcher.add(sourceRoots.map((source) =>
|
|
24561
|
+
server.watcher.add(sourceRoots.map((source) => path25.join(source.root, source.srcDir)));
|
|
23367
24562
|
if (farmConfig.i18n.enabled) {
|
|
23368
24563
|
server.watcher.add(
|
|
23369
|
-
farmConfig.i18n.messages.includes("{locale}") ?
|
|
24564
|
+
farmConfig.i18n.messages.includes("{locale}") ? path25.dirname(farmConfig.i18n.messages) : farmConfig.i18n.messages
|
|
23370
24565
|
);
|
|
23371
24566
|
}
|
|
23372
24567
|
const workflowConfig = farmConfig.workflows;
|
|
@@ -23376,7 +24571,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
23376
24571
|
...farmDocsDevRuntime?.getFarmDocsRouteTypeEntries(farmConfig.docs) ?? []
|
|
23377
24572
|
], "getExtraRouteTypes");
|
|
23378
24573
|
const appDirSlugs = sourceRoots.map(
|
|
23379
|
-
(source) =>
|
|
24574
|
+
(source) => path25.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
|
|
23380
24575
|
);
|
|
23381
24576
|
const generateTypeArtifacts = /* @__PURE__ */ __name(async (reason, selection = ALL_TYPE_ARTIFACTS, log = false) => {
|
|
23382
24577
|
try {
|
|
@@ -23416,7 +24611,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
23416
24611
|
}, "generateTypeArtifacts");
|
|
23417
24612
|
await generateTypeArtifacts("startup");
|
|
23418
24613
|
const srcDirSlugs = sourceRoots.map(
|
|
23419
|
-
(source) =>
|
|
24614
|
+
(source) => path25.join(source.root, source.srcDir).replace(/\\/g, "/")
|
|
23420
24615
|
);
|
|
23421
24616
|
const layerConfigFiles = new Set(
|
|
23422
24617
|
farmConfig.layers.map((layer) => layer.configFile?.replace(/\\/g, "/")).filter((file) => Boolean(file))
|
|
@@ -23534,7 +24729,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
23534
24729
|
await apiRouteManager.discoverRoutes();
|
|
23535
24730
|
let discoveredWorkflows = [];
|
|
23536
24731
|
const hasWorkflowDirectory = workflowConfig.enabled && workflowConfig.dirs.some(
|
|
23537
|
-
(dir) => fs7.existsSync(
|
|
24732
|
+
(dir) => fs7.existsSync(path25.isAbsolute(dir) ? dir : path25.join(farmConfig.root, dir))
|
|
23538
24733
|
);
|
|
23539
24734
|
if (hasWorkflowDirectory) {
|
|
23540
24735
|
const { createFarmWorkflowRequestHandler: createFarmWorkflowRequestHandler2, discoverFarmWorkflows: discoverFarmWorkflows2 } = await loadFarmWorkflowsDevRuntime();
|
|
@@ -23598,10 +24793,20 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
23598
24793
|
logger.info(`Refreshed routes: ${reason}`);
|
|
23599
24794
|
}
|
|
23600
24795
|
}, "refreshRouteDiscovery");
|
|
24796
|
+
const farmDocsFontAssetList = farmDocsDevRuntime ? resolveFarmDocsFontAssets(farmConfig.root) : [];
|
|
23601
24797
|
const farmDocsHandler = farmDocsDevRuntime ? farmDocsDevRuntime.createFarmDocsHandler(farmConfig.docs, {
|
|
23602
24798
|
root: farmConfig.root,
|
|
23603
24799
|
srcDir: farmConfig.srcDir,
|
|
23604
|
-
clientEntry: "/@farm/client.js"
|
|
24800
|
+
clientEntry: "/@farm/client.js",
|
|
24801
|
+
fontAssets: toFarmDocsPublicFontAssets(farmDocsFontAssetList),
|
|
24802
|
+
resolveLayoutFonts: /* @__PURE__ */ __name(async (pathname) => {
|
|
24803
|
+
const layouts = routeManager.matchRoute(pathname).layouts;
|
|
24804
|
+
const layoutModules = await Promise.all(
|
|
24805
|
+
layouts.map((layout2) => routeManager.loadLayoutModule(layout2.modulePath))
|
|
24806
|
+
);
|
|
24807
|
+
return resolveFarmLayoutFonts(layoutModules);
|
|
24808
|
+
}, "resolveLayoutFonts"),
|
|
24809
|
+
fontStylesheetHref: "/@farm/fonts.css"
|
|
23605
24810
|
}) : null;
|
|
23606
24811
|
const farmDocsAPIHandler = farmDocsDevRuntime ? farmDocsDevRuntime.createFarmDocsAPIHandler({
|
|
23607
24812
|
rootDir: farmConfig.root,
|
|
@@ -23609,22 +24814,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
23609
24814
|
docs: farmConfig.docs
|
|
23610
24815
|
}) : null;
|
|
23611
24816
|
const farmDocsFontAssets = new Map(
|
|
23612
|
-
|
|
23613
|
-
[
|
|
23614
|
-
"/assets/Geist-Variable-CrgPqtmy.woff2",
|
|
23615
|
-
path23.join(
|
|
23616
|
-
farmConfig.root,
|
|
23617
|
-
"node_modules/geist/dist/fonts/geist-sans/Geist-Variable.woff2"
|
|
23618
|
-
)
|
|
23619
|
-
],
|
|
23620
|
-
[
|
|
23621
|
-
"/assets/GeistMono-Variable-BNLlm6Cd.woff2",
|
|
23622
|
-
path23.join(
|
|
23623
|
-
farmConfig.root,
|
|
23624
|
-
"node_modules/geist/dist/fonts/geist-mono/GeistMono-Variable.woff2"
|
|
23625
|
-
)
|
|
23626
|
-
]
|
|
23627
|
-
] : []
|
|
24817
|
+
farmDocsFontAssetList.map(({ url, sourcePath }) => [url, sourcePath])
|
|
23628
24818
|
);
|
|
23629
24819
|
const logRequest = /* @__PURE__ */ __name((method, urlPath, tag) => {
|
|
23630
24820
|
try {
|
|
@@ -23688,11 +24878,12 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
23688
24878
|
}
|
|
23689
24879
|
}
|
|
23690
24880
|
const farmDocsFontPath = farmDocsFontAssets.get(requestPathname);
|
|
23691
|
-
if (farmDocsFontPath && fs7.existsSync(farmDocsFontPath)) {
|
|
24881
|
+
if ((requestMethod === "GET" || requestMethod === "HEAD") && farmDocsFontPath && fs7.existsSync(farmDocsFontPath)) {
|
|
23692
24882
|
res.statusCode = 200;
|
|
23693
24883
|
res.setHeader("Content-Type", "font/woff2");
|
|
23694
24884
|
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
|
23695
|
-
|
|
24885
|
+
if (requestMethod === "HEAD") res.end();
|
|
24886
|
+
else fs7.createReadStream(farmDocsFontPath).pipe(res);
|
|
23696
24887
|
return;
|
|
23697
24888
|
}
|
|
23698
24889
|
if (requestMethod === "GET" && (requestPathname === FARM_DEVTOOLS_PATH || requestPathname === `${FARM_DEVTOOLS_PATH}.json`)) {
|
|
@@ -24298,6 +25489,7 @@ function farmPlugin(options = {}, initialPluginManager) {
|
|
|
24298
25489
|
modulePath: toUrlPath(route.modulePath),
|
|
24299
25490
|
isClientComponent: routeSlots.length > 0 ? false : isClientComponent,
|
|
24300
25491
|
shouldHydrate: shouldHydrate || routeSlots.some((slot) => slot.isClientComponent || slot.shouldHydrate),
|
|
25492
|
+
islandStrategy: moduleMetadata.islandStrategy,
|
|
24301
25493
|
metadata: {
|
|
24302
25494
|
title: mergedMetadata.title,
|
|
24303
25495
|
description: mergedMetadata.description
|
|
@@ -24682,6 +25874,7 @@ export const getManifest = () => ({
|
|
|
24682
25874
|
search: route.search,
|
|
24683
25875
|
isClientComponent: moduleMetadata.isClientComponent,
|
|
24684
25876
|
shouldHydrate: moduleMetadata.shouldHydrate,
|
|
25877
|
+
islandStrategy: moduleMetadata.islandStrategy,
|
|
24685
25878
|
preloads: [route.modulePath],
|
|
24686
25879
|
// In dev, preload is just the module
|
|
24687
25880
|
assets: []
|
|
@@ -24808,8 +26001,8 @@ if (import.meta.hot) {
|
|
|
24808
26001
|
}
|
|
24809
26002
|
logger.info(`Found ${ssgPages.length} SSG pages, ${ssrRoutes.length} SSR routes`);
|
|
24810
26003
|
logger.info("Pre-rendering SSG pages...");
|
|
24811
|
-
const outDir =
|
|
24812
|
-
const clientDir =
|
|
26004
|
+
const outDir = path25.join(server?.config.root || process.cwd(), options.outDir || "dist");
|
|
26005
|
+
const clientDir = path25.join(outDir, "client");
|
|
24813
26006
|
for (const page2 of ssgPages) {
|
|
24814
26007
|
try {
|
|
24815
26008
|
const staticRequest = new Request(new URL(page2.urlPath, "http://farm.static"));
|
|
@@ -24820,7 +26013,7 @@ if (import.meta.hot) {
|
|
|
24820
26013
|
const layoutModules = await Promise.all(
|
|
24821
26014
|
layouts.map((l) => routeManager.loadLayoutModule(l.modulePath))
|
|
24822
26015
|
);
|
|
24823
|
-
const
|
|
26016
|
+
const React4 = await import("react");
|
|
24824
26017
|
const { renderToString } = await import("react-dom/server");
|
|
24825
26018
|
const PageComponent = mod.default;
|
|
24826
26019
|
const pageProps = {
|
|
@@ -24828,14 +26021,14 @@ if (import.meta.hot) {
|
|
|
24828
26021
|
searchParams: Promise.resolve({}),
|
|
24829
26022
|
path: page2.urlPath
|
|
24830
26023
|
};
|
|
24831
|
-
let pageElement =
|
|
26024
|
+
let pageElement = React4.createElement(
|
|
24832
26025
|
PageComponent,
|
|
24833
26026
|
pageProps
|
|
24834
26027
|
);
|
|
24835
26028
|
for (let i = layoutModules.length - 1; i >= 0; i--) {
|
|
24836
26029
|
const layoutModule = layoutModules[i];
|
|
24837
26030
|
const LayoutComponent = layoutModule.default;
|
|
24838
|
-
pageElement =
|
|
26031
|
+
pageElement = React4.createElement(
|
|
24839
26032
|
LayoutComponent,
|
|
24840
26033
|
{
|
|
24841
26034
|
children: pageElement,
|
|
@@ -24861,8 +26054,8 @@ if (import.meta.hot) {
|
|
|
24861
26054
|
<script type="module" src="/assets/client.js"></script>
|
|
24862
26055
|
</body>
|
|
24863
26056
|
</html>`;
|
|
24864
|
-
const outputPath = page2.urlPath === "/" ?
|
|
24865
|
-
fs7.mkdirSync(
|
|
26057
|
+
const outputPath = page2.urlPath === "/" ? path25.join(clientDir, "index.html") : path25.join(clientDir, page2.urlPath + ".html");
|
|
26058
|
+
fs7.mkdirSync(path25.dirname(outputPath), { recursive: true });
|
|
24866
26059
|
fs7.writeFileSync(outputPath, fullHtml);
|
|
24867
26060
|
const revalidateInfo = page2.revalidate ? ` (revalidate: ${page2.revalidate}s)` : "";
|
|
24868
26061
|
logger.success(` \u2713 ${page2.urlPath}${revalidateInfo}`);
|
|
@@ -24871,7 +26064,7 @@ if (import.meta.hot) {
|
|
|
24871
26064
|
logger.error(` \u2717 ${page2.urlPath}: ${error}`);
|
|
24872
26065
|
}
|
|
24873
26066
|
}
|
|
24874
|
-
const manifestPath =
|
|
26067
|
+
const manifestPath = path25.join(outDir, "__ssg_manifest.json");
|
|
24875
26068
|
fs7.writeFileSync(
|
|
24876
26069
|
manifestPath,
|
|
24877
26070
|
JSON.stringify(
|
|
@@ -24907,9 +26100,9 @@ if (import.meta.hot) {
|
|
|
24907
26100
|
}
|
|
24908
26101
|
const currentFarmConfig = farmApp?.getConfig();
|
|
24909
26102
|
const normalizedFile = file.replace(/\\/g, "/");
|
|
24910
|
-
const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) =>
|
|
26103
|
+
const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path25.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
|
|
24911
26104
|
if (currentSrcRoot && normalizedFile.startsWith(`${currentSrcRoot}/`) && isProgrammaticRoutesFileName(normalizedFile)) {
|
|
24912
|
-
logUpdate("PAGE", `updated ${
|
|
26105
|
+
logUpdate("PAGE", `updated ${path25.basename(file)}`);
|
|
24913
26106
|
for (const mod of modules) {
|
|
24914
26107
|
server2.moduleGraph.invalidateModule(mod);
|
|
24915
26108
|
}
|
|
@@ -25306,6 +26499,7 @@ import React from 'react'
|
|
|
25306
26499
|
import { hydrateRoot, createRoot } from 'react-dom/client'
|
|
25307
26500
|
import { installChunkErrorRecovery, SPARouter } from '@farm.js/core/client'
|
|
25308
26501
|
import { createClientPluginManager } from '@farm.js/core/plugin/client'
|
|
26502
|
+
import { scheduleFarmIslandHydration } from '@farm.js/core/internal/client-runtime'
|
|
25309
26503
|
import { reviveDeferredData } from '@farm.js/core/deferred'
|
|
25310
26504
|
import {
|
|
25311
26505
|
createFarmDeploymentMismatchError,
|
|
@@ -25558,6 +26752,7 @@ class LegacyManifestSPARouter {
|
|
|
25558
26752
|
|
|
25559
26753
|
// Only prefetch routes that will hydrate on the client.
|
|
25560
26754
|
if (!match.route.isClientComponent && !match.route.shouldHydrate) return;
|
|
26755
|
+
if (match.route.islandStrategy && match.route.islandStrategy !== 'load') return;
|
|
25561
26756
|
|
|
25562
26757
|
const modulePath = match.route.modulePath;
|
|
25563
26758
|
if (this.moduleCache.has(modulePath)) return;
|
|
@@ -25702,6 +26897,12 @@ let hasClientTakenOver = false;
|
|
|
25702
26897
|
const routeSlotRoots = new Map();
|
|
25703
26898
|
const routeSlotDefinitions = new Map();
|
|
25704
26899
|
let activeRouteInterception = null;
|
|
26900
|
+
let pendingPageHydrationController = null;
|
|
26901
|
+
|
|
26902
|
+
function cancelPendingPageHydration() {
|
|
26903
|
+
pendingPageHydrationController?.abort();
|
|
26904
|
+
pendingPageHydrationController = null;
|
|
26905
|
+
}
|
|
25705
26906
|
|
|
25706
26907
|
function normalizeServerProps(rawProps) {
|
|
25707
26908
|
const props = rawProps && typeof rawProps === 'object' ? { ...rawProps } : {};
|
|
@@ -25770,7 +26971,11 @@ async function hydrateInitialRouteSlots() {
|
|
|
25770
26971
|
routeSlotDefinitions.set(getRouteSlotKey(slot), slot);
|
|
25771
26972
|
if (!slot.isClientComponent && !slot.shouldHydrate) continue;
|
|
25772
26973
|
try {
|
|
25773
|
-
|
|
26974
|
+
const slotHydrated = await renderRouteSlot(slot, 'hydrate');
|
|
26975
|
+
hydrated = slotHydrated || hydrated;
|
|
26976
|
+
if (slotHydrated) {
|
|
26977
|
+
replayPreHydrationClicks(document.getElementById(slot.containerId));
|
|
26978
|
+
}
|
|
25774
26979
|
} catch (error) {
|
|
25775
26980
|
console.warn('[Farm.js] Could not hydrate route slot:', slot.name, error);
|
|
25776
26981
|
}
|
|
@@ -25841,16 +27046,29 @@ function applyCanonicalPathFromProps(props) {
|
|
|
25841
27046
|
window.history.replaceState({ ...(window.history.state || {}), path: canonicalPath }, '', canonicalPath);
|
|
25842
27047
|
}
|
|
25843
27048
|
|
|
25844
|
-
function replayPreHydrationClicks() {
|
|
25845
|
-
|
|
25846
|
-
|
|
27049
|
+
function replayPreHydrationClicks(container = null) {
|
|
27050
|
+
if (!container) {
|
|
27051
|
+
markFarmHydrated();
|
|
27052
|
+
} else {
|
|
27053
|
+
container.dataset.farmIslandHydrated = 'true';
|
|
27054
|
+
}
|
|
25847
27055
|
|
|
25848
27056
|
const queue = Array.isArray(window.__FARM_PREHYDRATION_CLICK_QUEUE__)
|
|
25849
27057
|
? window.__FARM_PREHYDRATION_CLICK_QUEUE__
|
|
25850
27058
|
: [];
|
|
25851
27059
|
if (queue.length === 0) return;
|
|
25852
27060
|
|
|
25853
|
-
const queuedClicks =
|
|
27061
|
+
const queuedClicks = [];
|
|
27062
|
+
const remainingClicks = [];
|
|
27063
|
+
for (const queuedClick of queue) {
|
|
27064
|
+
const target = queuedClick?.target;
|
|
27065
|
+
if (!container || (target instanceof Node && container.contains(target))) {
|
|
27066
|
+
queuedClicks.push(queuedClick);
|
|
27067
|
+
} else {
|
|
27068
|
+
remainingClicks.push(queuedClick);
|
|
27069
|
+
}
|
|
27070
|
+
}
|
|
27071
|
+
queue.splice(0, queue.length, ...remainingClicks);
|
|
25854
27072
|
for (const queuedClick of queuedClicks) {
|
|
25855
27073
|
const target = queuedClick?.target;
|
|
25856
27074
|
if (!target || typeof target.click !== 'function') continue;
|
|
@@ -25859,6 +27077,11 @@ function replayPreHydrationClicks() {
|
|
|
25859
27077
|
}
|
|
25860
27078
|
}
|
|
25861
27079
|
|
|
27080
|
+
function markFarmHydrated() {
|
|
27081
|
+
window.__FARM_HYDRATED__ = true;
|
|
27082
|
+
document.documentElement.dataset.farmHydrated = 'true';
|
|
27083
|
+
}
|
|
27084
|
+
|
|
25862
27085
|
async function buildClientHydrationElement(PageComponent, pageProps) {
|
|
25863
27086
|
let element = React.createElement(PageComponent, pageProps);
|
|
25864
27087
|
const loadingModulePath = window.__FARM_LOADING_MODULE__;
|
|
@@ -26001,9 +27224,10 @@ async function tryHydrateImportedPage(
|
|
|
26001
27224
|
layouts,
|
|
26002
27225
|
useHydrate = false,
|
|
26003
27226
|
existingProps = null,
|
|
27227
|
+
signal = null,
|
|
26004
27228
|
) {
|
|
26005
27229
|
const modulePath = route?.modulePath;
|
|
26006
|
-
if (!modulePath) {
|
|
27230
|
+
if (!modulePath || signal?.aborted) {
|
|
26007
27231
|
return false;
|
|
26008
27232
|
}
|
|
26009
27233
|
|
|
@@ -26012,6 +27236,7 @@ async function tryHydrateImportedPage(
|
|
|
26012
27236
|
pageModule = await import(/* @vite-ignore */ modulePath);
|
|
26013
27237
|
pageModuleCache.set(modulePath, pageModule);
|
|
26014
27238
|
}
|
|
27239
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
26015
27240
|
|
|
26016
27241
|
const PageComponent = pageModule?.default;
|
|
26017
27242
|
if (!PageComponent) {
|
|
@@ -26026,6 +27251,7 @@ async function tryHydrateImportedPage(
|
|
|
26026
27251
|
window.location.pathname,
|
|
26027
27252
|
existingProps,
|
|
26028
27253
|
);
|
|
27254
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
26029
27255
|
|
|
26030
27256
|
const wrappedElement = useHydrate && container?.id === '__farm_page__'
|
|
26031
27257
|
? wrapWithIntegrationProviders(
|
|
@@ -26036,6 +27262,7 @@ async function tryHydrateImportedPage(
|
|
|
26036
27262
|
currentPageProps,
|
|
26037
27263
|
layouts,
|
|
26038
27264
|
);
|
|
27265
|
+
if (signal?.aborted || !container?.isConnected) return false;
|
|
26039
27266
|
|
|
26040
27267
|
if (useHydrate) {
|
|
26041
27268
|
try {
|
|
@@ -26066,6 +27293,7 @@ async function tryHydrateImportedPage(
|
|
|
26066
27293
|
async function renderPage(pageData) {
|
|
26067
27294
|
const container = document.getElementById('root');
|
|
26068
27295
|
if (!container) return;
|
|
27296
|
+
cancelPendingPageHydration();
|
|
26069
27297
|
const destination = window.location.pathname + window.location.search;
|
|
26070
27298
|
|
|
26071
27299
|
if (pageData.interception) {
|
|
@@ -26082,6 +27310,7 @@ async function renderPage(pageData) {
|
|
|
26082
27310
|
modulePath: pageData.modulePath,
|
|
26083
27311
|
isClientComponent: pageData.isClientComponent === true,
|
|
26084
27312
|
shouldHydrate: pageData.shouldHydrate === true,
|
|
27313
|
+
islandStrategy: pageData.islandStrategy || 'load',
|
|
26085
27314
|
};
|
|
26086
27315
|
const params = pageData.props?.params || {};
|
|
26087
27316
|
const layouts = (pageData.layoutModules || []).map((modulePath, index) => ({
|
|
@@ -26281,14 +27510,6 @@ async function hydrate() {
|
|
|
26281
27510
|
}
|
|
26282
27511
|
|
|
26283
27512
|
try {
|
|
26284
|
-
// Pre-load layout for SPA navigation
|
|
26285
|
-
try {
|
|
26286
|
-
const layoutModule = await import(/* @vite-ignore */ '/src/app/layout.tsx');
|
|
26287
|
-
LayoutComponent = layoutModule.default;
|
|
26288
|
-
} catch (e) {
|
|
26289
|
-
console.warn('[Farm.js] Could not preload layout:', e);
|
|
26290
|
-
}
|
|
26291
|
-
|
|
26292
27513
|
// Check if this is a client component (set by SSR)
|
|
26293
27514
|
const isClientComponent = window.__FARM_IS_CLIENT__ === true;
|
|
26294
27515
|
const modulePath = window.__FARM_PAGE_MODULE__;
|
|
@@ -26336,34 +27557,88 @@ async function hydrate() {
|
|
|
26336
27557
|
return
|
|
26337
27558
|
}
|
|
26338
27559
|
|
|
26339
|
-
const
|
|
26340
|
-
|
|
26341
|
-
|
|
26342
|
-
|
|
27560
|
+
const currentRoute = findRoute(window.location.pathname)?.route;
|
|
27561
|
+
const islandStrategy = window.__FARM_ISLAND_STRATEGY__ || currentRoute?.islandStrategy || 'load';
|
|
27562
|
+
pageContainer.dataset.farmIsland = 'page';
|
|
27563
|
+
pageContainer.dataset.farmIslandStrategy = islandStrategy;
|
|
26343
27564
|
|
|
26344
|
-
|
|
27565
|
+
const hydrationPathname = window.location.pathname;
|
|
27566
|
+
const hydrationController = new AbortController();
|
|
27567
|
+
pendingPageHydrationController = hydrationController;
|
|
26345
27568
|
try {
|
|
26346
|
-
|
|
26347
|
-
pageContainer,
|
|
26348
|
-
|
|
26349
|
-
|
|
26350
|
-
|
|
26351
|
-
|
|
26352
|
-
|
|
26353
|
-
|
|
26354
|
-
|
|
26355
|
-
|
|
26356
|
-
|
|
26357
|
-
|
|
26358
|
-
}
|
|
27569
|
+
await scheduleFarmIslandHydration({
|
|
27570
|
+
container: pageContainer,
|
|
27571
|
+
strategy: islandStrategy,
|
|
27572
|
+
signal: hydrationController.signal,
|
|
27573
|
+
hydrate: async () => {
|
|
27574
|
+
if (
|
|
27575
|
+
hydrationController.signal.aborted ||
|
|
27576
|
+
!pageContainer.isConnected ||
|
|
27577
|
+
window.location.pathname !== hydrationPathname
|
|
27578
|
+
) {
|
|
27579
|
+
return;
|
|
27580
|
+
}
|
|
26359
27581
|
|
|
26360
|
-
|
|
26361
|
-
|
|
26362
|
-
|
|
26363
|
-
|
|
26364
|
-
|
|
27582
|
+
// Layout code is only needed when this route boundary actually hydrates.
|
|
27583
|
+
try {
|
|
27584
|
+
const layoutModule = await import(/* @vite-ignore */ '/src/app/layout.tsx');
|
|
27585
|
+
LayoutComponent = layoutModule.default;
|
|
27586
|
+
} catch (e) {
|
|
27587
|
+
console.warn('[Farm.js] Could not preload layout:', e);
|
|
27588
|
+
}
|
|
27589
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) return;
|
|
27590
|
+
|
|
27591
|
+
const hydrationSession = await farmClientRuntime.beginHydration({
|
|
27592
|
+
container: pageContainer,
|
|
27593
|
+
mode: shouldHydrate ? 'hydrate' : 'render',
|
|
27594
|
+
});
|
|
27595
|
+
|
|
27596
|
+
let hydrated = false;
|
|
27597
|
+
try {
|
|
27598
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) {
|
|
27599
|
+
await farmClientRuntime.failHydration(
|
|
27600
|
+
hydrationSession,
|
|
27601
|
+
new DOMException('Route hydration was cancelled', 'AbortError'),
|
|
27602
|
+
);
|
|
27603
|
+
return;
|
|
27604
|
+
}
|
|
27605
|
+
hydrated = await tryHydrateImportedPage(
|
|
27606
|
+
pageContainer,
|
|
27607
|
+
{ modulePath },
|
|
27608
|
+
currentPageProps.params || {},
|
|
27609
|
+
layouts,
|
|
27610
|
+
shouldHydrate,
|
|
27611
|
+
currentPageProps,
|
|
27612
|
+
hydrationController.signal,
|
|
27613
|
+
);
|
|
27614
|
+
if (hydrationController.signal.aborted || !pageContainer.isConnected) {
|
|
27615
|
+
await farmClientRuntime.failHydration(
|
|
27616
|
+
hydrationSession,
|
|
27617
|
+
new DOMException('Route hydration was cancelled', 'AbortError'),
|
|
27618
|
+
);
|
|
27619
|
+
return;
|
|
27620
|
+
}
|
|
27621
|
+
await farmClientRuntime.completeHydration(hydrationSession);
|
|
27622
|
+
} catch (error) {
|
|
27623
|
+
await farmClientRuntime.failHydration(hydrationSession, error);
|
|
27624
|
+
throw error;
|
|
27625
|
+
}
|
|
27626
|
+
|
|
27627
|
+
if (hydrated) {
|
|
27628
|
+
// The scheduler owns queue draining and exactly-once click replay.
|
|
27629
|
+
markFarmHydrated();
|
|
27630
|
+
console.log('[Farm.js] \u2705 Hydrated:', modulePath, '(' + islandStrategy + ')');
|
|
27631
|
+
return;
|
|
27632
|
+
}
|
|
26365
27633
|
|
|
26366
|
-
|
|
27634
|
+
console.log('[Farm.js] Server component - SPA router ready')
|
|
27635
|
+
},
|
|
27636
|
+
});
|
|
27637
|
+
} finally {
|
|
27638
|
+
if (pendingPageHydrationController === hydrationController) {
|
|
27639
|
+
pendingPageHydrationController = null;
|
|
27640
|
+
}
|
|
27641
|
+
}
|
|
26367
27642
|
} catch (error) {
|
|
26368
27643
|
console.error('[Farm.js] Hydration error:', error)
|
|
26369
27644
|
}
|
|
@@ -26469,7 +27744,7 @@ function generateClientManifest(bundle) {
|
|
|
26469
27744
|
__name(generateClientManifest, "generateClientManifest");
|
|
26470
27745
|
async function defineConfig2(config = {}) {
|
|
26471
27746
|
const tailwindcss = (await import("@tailwindcss/vite")).default;
|
|
26472
|
-
const appRoot =
|
|
27747
|
+
const appRoot = path25.resolve(config.root || process.cwd());
|
|
26473
27748
|
if (config.extends?.length) {
|
|
26474
27749
|
const { config: layeredConfig } = await Promise.resolve().then(() => (init_layers(), layers_exports)).then(
|
|
26475
27750
|
({ resolveFarmLayers: resolveFarmLayers2 }) => resolveFarmLayers2(config, {
|
|
@@ -26614,13 +27889,16 @@ async function defineConfig2(config = {}) {
|
|
|
26614
27889
|
customLogger: farmLogger,
|
|
26615
27890
|
clearScreen: false,
|
|
26616
27891
|
optimizeDeps: {
|
|
26617
|
-
|
|
26618
|
-
|
|
26619
|
-
|
|
26620
|
-
|
|
26621
|
-
|
|
26622
|
-
|
|
26623
|
-
|
|
27892
|
+
...createFarmClientOptimizeDepsConfig(
|
|
27893
|
+
createFarmClientOptimizeDepsEntries(
|
|
27894
|
+
appRoot,
|
|
27895
|
+
getFarmAppDirectories({ ...config, root: appRoot })
|
|
27896
|
+
)
|
|
27897
|
+
),
|
|
27898
|
+
// Pre-bundle every framework client-runtime entry with React. Without
|
|
27899
|
+
// this, Vite can discover a linked Farm entry after the page has loaded,
|
|
27900
|
+
// regenerate the optimizer browser hash, and leave React DOM holding a
|
|
27901
|
+
// different React module instance from a client component.
|
|
26624
27902
|
// Exclude server-side packages from browser bundling
|
|
26625
27903
|
exclude: [
|
|
26626
27904
|
"@farm.js/core/server",
|
|
@@ -26655,7 +27933,7 @@ async function defineConfig2(config = {}) {
|
|
|
26655
27933
|
// Stub out problematic server-only modules during dev mode
|
|
26656
27934
|
alias: {
|
|
26657
27935
|
...getFarmLayerAliases(config.layers),
|
|
26658
|
-
"@":
|
|
27936
|
+
"@": path25.resolve(appRoot, "src"),
|
|
26659
27937
|
// Nitro internals that should not be resolved in browser
|
|
26660
27938
|
"supports-color": "data:text/javascript,export default false; export const supportsColor = false; export const stdout = false; export const stderr = false;",
|
|
26661
27939
|
"@poppinss/dumper": "data:text/javascript,export default {};",
|
|
@@ -27750,55 +29028,8 @@ function createLoggerPlugin({
|
|
|
27750
29028
|
}
|
|
27751
29029
|
__name(createLoggerPlugin, "createLoggerPlugin");
|
|
27752
29030
|
|
|
27753
|
-
// src/server/vite-config.ts
|
|
27754
|
-
function mergeNoExternal(farmValue, userValue) {
|
|
27755
|
-
if (farmValue === true || userValue === true) return true;
|
|
27756
|
-
const normalize = /* @__PURE__ */ __name((value) => value == null || value === true ? [] : Array.isArray(value) ? value : [value], "normalize");
|
|
27757
|
-
return Array.from(/* @__PURE__ */ new Set([...normalize(farmValue), ...normalize(userValue)]));
|
|
27758
|
-
}
|
|
27759
|
-
__name(mergeNoExternal, "mergeNoExternal");
|
|
27760
|
-
function mergeFarmViteConfig(farmConfig, userConfig = {}) {
|
|
27761
|
-
return {
|
|
27762
|
-
...farmConfig,
|
|
27763
|
-
...userConfig,
|
|
27764
|
-
plugins: [...farmConfig.plugins || [], ...userConfig.plugins || []],
|
|
27765
|
-
server: {
|
|
27766
|
-
...farmConfig.server,
|
|
27767
|
-
...userConfig.server
|
|
27768
|
-
},
|
|
27769
|
-
resolve: {
|
|
27770
|
-
...farmConfig.resolve,
|
|
27771
|
-
...userConfig.resolve,
|
|
27772
|
-
dedupe: Array.from(
|
|
27773
|
-
/* @__PURE__ */ new Set([...farmConfig.resolve?.dedupe || [], ...userConfig.resolve?.dedupe || []])
|
|
27774
|
-
)
|
|
27775
|
-
},
|
|
27776
|
-
optimizeDeps: {
|
|
27777
|
-
...farmConfig.optimizeDeps,
|
|
27778
|
-
...userConfig.optimizeDeps,
|
|
27779
|
-
include: Array.from(
|
|
27780
|
-
/* @__PURE__ */ new Set([
|
|
27781
|
-
...farmConfig.optimizeDeps?.include || [],
|
|
27782
|
-
...userConfig.optimizeDeps?.include || []
|
|
27783
|
-
])
|
|
27784
|
-
),
|
|
27785
|
-
exclude: Array.from(
|
|
27786
|
-
/* @__PURE__ */ new Set([
|
|
27787
|
-
...farmConfig.optimizeDeps?.exclude || [],
|
|
27788
|
-
...userConfig.optimizeDeps?.exclude || []
|
|
27789
|
-
])
|
|
27790
|
-
)
|
|
27791
|
-
},
|
|
27792
|
-
ssr: {
|
|
27793
|
-
...farmConfig.ssr,
|
|
27794
|
-
...userConfig.ssr,
|
|
27795
|
-
noExternal: mergeNoExternal(farmConfig.ssr?.noExternal, userConfig.ssr?.noExternal)
|
|
27796
|
-
}
|
|
27797
|
-
};
|
|
27798
|
-
}
|
|
27799
|
-
__name(mergeFarmViteConfig, "mergeFarmViteConfig");
|
|
27800
|
-
|
|
27801
29031
|
// src/server/create-server.ts
|
|
29032
|
+
init_layers();
|
|
27802
29033
|
var DEFAULT_FARM_DEV_SERVER_PORT = 3e3;
|
|
27803
29034
|
function createBrandingPlugin() {
|
|
27804
29035
|
let serverStarted = false;
|
|
@@ -27970,15 +29201,9 @@ async function createServer(config = {}) {
|
|
|
27970
29201
|
dedupe: ["react", "react-dom"]
|
|
27971
29202
|
},
|
|
27972
29203
|
optimizeDeps: {
|
|
27973
|
-
|
|
27974
|
-
|
|
27975
|
-
|
|
27976
|
-
"react",
|
|
27977
|
-
"react-dom",
|
|
27978
|
-
"react-dom/client",
|
|
27979
|
-
"react/jsx-runtime",
|
|
27980
|
-
"react/jsx-dev-runtime"
|
|
27981
|
-
],
|
|
29204
|
+
...createFarmClientOptimizeDepsConfig(
|
|
29205
|
+
createFarmClientOptimizeDepsEntries(projectRoot, getFarmAppDirectories(finalConfig))
|
|
29206
|
+
),
|
|
27982
29207
|
exclude: [
|
|
27983
29208
|
"@farm.js/core/server",
|
|
27984
29209
|
"@farm.js/core/api",
|