naro-cli 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -7
- package/dist/args.d.ts +2 -0
- package/dist/artifact-types.d.ts +1 -1
- package/dist/{chunk-UGJFIEH7.js → chunk-UJGDKNDM.js} +700 -903
- package/dist/deploy.d.ts +11 -2
- package/dist/deploy.js +7 -1
- package/dist/index.js +134 -9
- package/dist/user-adapter.d.ts +32 -0
- package/dist/working-tree.d.ts +1 -1
- package/package.json +5 -6
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
|
|
6
6
|
// src/deploy.ts
|
|
7
7
|
import { existsSync as existsSync10 } from "fs";
|
|
8
|
-
import { mkdtemp as mkdtemp2, readFile as
|
|
8
|
+
import { mkdtemp as mkdtemp2, readFile as readFile16, rm as rm6 } from "fs/promises";
|
|
9
9
|
import { tmpdir as tmpdir2 } from "os";
|
|
10
|
-
import { basename as
|
|
11
|
-
import { fileURLToPath as
|
|
10
|
+
import { basename as basename4, dirname as dirname9, join as join31, resolve as resolve15 } from "path";
|
|
11
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
12
12
|
|
|
13
13
|
// ../../packages/build/src/artifact-upload.ts
|
|
14
14
|
function artifactUploadEntries(artifact) {
|
|
@@ -41,7 +41,7 @@ function parseArtifactPutUrls(payload) {
|
|
|
41
41
|
}
|
|
42
42
|
async function eachWithinBudget(items, limit, budget, weigh, work) {
|
|
43
43
|
if (items.length === 0) return;
|
|
44
|
-
await new Promise((
|
|
44
|
+
await new Promise((resolve16, reject) => {
|
|
45
45
|
let next = 0;
|
|
46
46
|
let running = 0;
|
|
47
47
|
let weight = 0;
|
|
@@ -58,7 +58,7 @@ async function eachWithinBudget(items, limit, budget, weigh, work) {
|
|
|
58
58
|
running -= 1;
|
|
59
59
|
weight -= itemWeight;
|
|
60
60
|
finished += 1;
|
|
61
|
-
if (finished === items.length)
|
|
61
|
+
if (finished === items.length) resolve16();
|
|
62
62
|
else pump();
|
|
63
63
|
}, reject);
|
|
64
64
|
}
|
|
@@ -287,9 +287,9 @@ function hashAsset(data, contentType2) {
|
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
// ../../packages/build/src/local-build-executor.ts
|
|
290
|
-
import { access as
|
|
290
|
+
import { access as access6, mkdtemp, readFile as readFile14, rm as rm4 } from "fs/promises";
|
|
291
291
|
import { tmpdir } from "os";
|
|
292
|
-
import { dirname as
|
|
292
|
+
import { dirname as dirname3, join as join17, resolve as resolve7 } from "path";
|
|
293
293
|
|
|
294
294
|
// ../../packages/core/src/route-patterns.ts
|
|
295
295
|
var ROUTE_PATTERN = /^\/[A-Za-z0-9\-._~%!$&()*+,;=:@/[\]]*$/;
|
|
@@ -527,7 +527,10 @@ var CAPABILITIES = [
|
|
|
527
527
|
id: "team-usage",
|
|
528
528
|
domain: "teams",
|
|
529
529
|
title: "\uD300 \uC0AC\uC6A9\uB7C9",
|
|
530
|
-
routes: [
|
|
530
|
+
routes: [
|
|
531
|
+
"GET teams/[teamSlug]/usage",
|
|
532
|
+
"GET teams/[teamSlug]/usage/hosting"
|
|
533
|
+
],
|
|
531
534
|
ui: { kind: "built" },
|
|
532
535
|
cli: { kind: "built", commands: ["naro usage"] },
|
|
533
536
|
mcp: { kind: "built", tools: ["get_team_usage"] }
|
|
@@ -1873,6 +1876,19 @@ var CAPABILITIES = [
|
|
|
1873
1876
|
cli: { kind: "built", commands: ["naro backend"] },
|
|
1874
1877
|
mcp: { kind: "built", tools: ["get_backend"] }
|
|
1875
1878
|
},
|
|
1879
|
+
{
|
|
1880
|
+
id: "backend-usage",
|
|
1881
|
+
domain: "backend",
|
|
1882
|
+
title: "Backend \uAC1C\uC694\uC758 \uC0AC\uC6A9\uB7C9(DB \uC4F0\uAE30\xB7\uD06C\uAE30, Storage \uC6A9\uB7C9\xB7\uC4F0\uAE30, \uD568\uC218 \uD638\uCD9C, Realtime \uBA54\uC2DC\uC9C0)",
|
|
1883
|
+
routes: ["GET projects/[projectId]/backend/usage"],
|
|
1884
|
+
ui: { kind: "built" },
|
|
1885
|
+
// 같은 숫자를 섹션마다 이미 돌려준다: naro db info(오늘 쓴 행·한도), naro
|
|
1886
|
+
// storage(용량·오늘 쓰기), naro functions(함수별 오늘 호출), naro realtime
|
|
1887
|
+
// (이번 달 메시지). 이 라우트는 개요가 한 번에 읽으려고 모은 것이다.
|
|
1888
|
+
cli: { kind: "built" },
|
|
1889
|
+
// get_database·get_storage·list_functions·get_realtime이 같은 숫자를 준다.
|
|
1890
|
+
mcp: { kind: "built" }
|
|
1891
|
+
},
|
|
1876
1892
|
{
|
|
1877
1893
|
id: "backend-enable",
|
|
1878
1894
|
domain: "backend",
|
|
@@ -2248,7 +2264,7 @@ function parseDotenvDetailed(text3) {
|
|
|
2248
2264
|
var STALL_WINDOW_MS = 10 * 6e4;
|
|
2249
2265
|
|
|
2250
2266
|
// ../../packages/core/src/deployment-strategy.ts
|
|
2251
|
-
var MIN_SUPPORTED_NEXT_MAJOR =
|
|
2267
|
+
var MIN_SUPPORTED_NEXT_MAJOR = 16;
|
|
2252
2268
|
|
|
2253
2269
|
// ../../packages/core/src/environment-guidance.ts
|
|
2254
2270
|
var DATA_COMMANDS = /* @__PURE__ */ new Set([
|
|
@@ -17610,6 +17626,130 @@ var BUILDS = {
|
|
|
17610
17626
|
}
|
|
17611
17627
|
};
|
|
17612
17628
|
|
|
17629
|
+
// ../../packages/next-adapter/src/index.ts
|
|
17630
|
+
import { fileURLToPath } from "url";
|
|
17631
|
+
|
|
17632
|
+
// ../../packages/next-adapter/src/supported.ts
|
|
17633
|
+
var SUPPORTED_NEXT = [
|
|
17634
|
+
{ minor: "16.2", next: "16.2.12", routing: "@next/routing-16.2" },
|
|
17635
|
+
{ minor: "16.3", next: "16.3.8", routing: "@next/routing-16.3" },
|
|
17636
|
+
{ minor: "16.4", next: "16.4.5", routing: "@next/routing-16.4" }
|
|
17637
|
+
];
|
|
17638
|
+
var VERSION = /^(\d+)\.(\d+)\.(\d+)/;
|
|
17639
|
+
function judgeNextVersion(version3) {
|
|
17640
|
+
const match = VERSION.exec(version3.trim());
|
|
17641
|
+
if (!match) return null;
|
|
17642
|
+
const major = Number(match[1]);
|
|
17643
|
+
const minor = Number(match[2]);
|
|
17644
|
+
if (major < 16 || major === 16 && minor < 2) return { kind: "too-old" };
|
|
17645
|
+
const entry = SUPPORTED_NEXT.find(
|
|
17646
|
+
(candidate) => candidate.minor === `${String(major)}.${String(minor)}`
|
|
17647
|
+
);
|
|
17648
|
+
if (entry) return { kind: "supported", entry };
|
|
17649
|
+
const newest = SUPPORTED_NEXT[SUPPORTED_NEXT.length - 1];
|
|
17650
|
+
if (!newest) throw new Error("SUPPORTED_NEXT is empty.");
|
|
17651
|
+
return { kind: "newer", entry: newest };
|
|
17652
|
+
}
|
|
17653
|
+
function testedRange() {
|
|
17654
|
+
const first = SUPPORTED_NEXT[0];
|
|
17655
|
+
const last = SUPPORTED_NEXT[SUPPORTED_NEXT.length - 1];
|
|
17656
|
+
if (!first || !last) throw new Error("SUPPORTED_NEXT is empty.");
|
|
17657
|
+
return `${first.minor}\u2013${last.minor}`;
|
|
17658
|
+
}
|
|
17659
|
+
|
|
17660
|
+
// ../../packages/next-adapter/src/paths.ts
|
|
17661
|
+
var OUTPUT_DIR = ".naro";
|
|
17662
|
+
var BUILD_RECORD = ".naro/build.json";
|
|
17663
|
+
var WORKER_DIR = ".naro/worker";
|
|
17664
|
+
var ASSETS_DIR = ".naro/assets";
|
|
17665
|
+
var WRANGLER_CONFIG = ".naro/worker/wrangler.jsonc";
|
|
17666
|
+
|
|
17667
|
+
// ../../packages/next-adapter/src/bundle/wrangler.ts
|
|
17668
|
+
import { posix } from "path";
|
|
17669
|
+
|
|
17670
|
+
// ../../packages/next-adapter/src/config-wrapper.ts
|
|
17671
|
+
import { access, readFile as readFile2, rename, writeFile as writeFile2 } from "fs/promises";
|
|
17672
|
+
import { join as join2 } from "path";
|
|
17673
|
+
var PROJECT_CONFIG_BASENAME = "next.config.naro-user";
|
|
17674
|
+
var WRAPPABLE = {
|
|
17675
|
+
"next.config.js": {
|
|
17676
|
+
wrapper: "next.config.mjs",
|
|
17677
|
+
specifier: `./${PROJECT_CONFIG_BASENAME}.js`,
|
|
17678
|
+
typescript: false
|
|
17679
|
+
},
|
|
17680
|
+
"next.config.mjs": {
|
|
17681
|
+
wrapper: "next.config.mjs",
|
|
17682
|
+
specifier: `./${PROJECT_CONFIG_BASENAME}.mjs`,
|
|
17683
|
+
typescript: false
|
|
17684
|
+
},
|
|
17685
|
+
"next.config.ts": {
|
|
17686
|
+
wrapper: "next.config.ts",
|
|
17687
|
+
specifier: `./${PROJECT_CONFIG_BASENAME}`,
|
|
17688
|
+
typescript: true
|
|
17689
|
+
},
|
|
17690
|
+
"next.config.mts": {
|
|
17691
|
+
wrapper: "next.config.mts",
|
|
17692
|
+
specifier: `./${PROJECT_CONFIG_BASENAME}.mts`,
|
|
17693
|
+
typescript: true
|
|
17694
|
+
}
|
|
17695
|
+
};
|
|
17696
|
+
function nextConfigWrapperSource(projectSpecifier, typescript) {
|
|
17697
|
+
return `${typescript ? "// @ts-nocheck\n" : ""}// Written by Naro for this build only. The project's own next.config is
|
|
17698
|
+
// ${projectSpecifier}, unchanged; this wrapper swaps its Next.js adapter for
|
|
17699
|
+
// the Naro adapter (project setting "replace").
|
|
17700
|
+
import projectConfig from ${JSON.stringify(projectSpecifier)};
|
|
17701
|
+
|
|
17702
|
+
export default async function naroNextConfig(phase, context) {
|
|
17703
|
+
const config =
|
|
17704
|
+
typeof projectConfig === "function"
|
|
17705
|
+
? await projectConfig(phase, context)
|
|
17706
|
+
: await projectConfig;
|
|
17707
|
+
const rest = { ...(config ?? {}) };
|
|
17708
|
+
delete rest.adapterPath;
|
|
17709
|
+
if (rest.experimental && typeof rest.experimental === "object") {
|
|
17710
|
+
rest.experimental = { ...rest.experimental };
|
|
17711
|
+
delete rest.experimental.adapterPath;
|
|
17712
|
+
}
|
|
17713
|
+
return { ...rest, adapterPath: process.env.NEXT_ADAPTER_PATH };
|
|
17714
|
+
}
|
|
17715
|
+
`;
|
|
17716
|
+
}
|
|
17717
|
+
async function exists(path) {
|
|
17718
|
+
try {
|
|
17719
|
+
await access(path);
|
|
17720
|
+
return true;
|
|
17721
|
+
} catch {
|
|
17722
|
+
return false;
|
|
17723
|
+
}
|
|
17724
|
+
}
|
|
17725
|
+
async function wrapNextConfig(appRoot, file2) {
|
|
17726
|
+
const plan = WRAPPABLE[file2];
|
|
17727
|
+
if (!plan) return null;
|
|
17728
|
+
const ext = file2.slice("next.config.".length);
|
|
17729
|
+
const project2 = `${PROJECT_CONFIG_BASENAME}.${ext}`;
|
|
17730
|
+
if (await exists(join2(appRoot, project2)))
|
|
17731
|
+
throw new Error(
|
|
17732
|
+
`${project2} already exists in the project; Naro needs that name to replace the project's Next.js adapter.`
|
|
17733
|
+
);
|
|
17734
|
+
await readFile2(join2(appRoot, file2));
|
|
17735
|
+
await rename(join2(appRoot, file2), join2(appRoot, project2));
|
|
17736
|
+
await writeFile2(
|
|
17737
|
+
join2(appRoot, plan.wrapper),
|
|
17738
|
+
nextConfigWrapperSource(plan.specifier, plan.typescript)
|
|
17739
|
+
);
|
|
17740
|
+
return { wrapper: plan.wrapper, project: project2 };
|
|
17741
|
+
}
|
|
17742
|
+
|
|
17743
|
+
// ../../packages/next-adapter/src/index.ts
|
|
17744
|
+
function nextAdapterPath(base2 = import.meta.url) {
|
|
17745
|
+
if (!base2) return void 0;
|
|
17746
|
+
try {
|
|
17747
|
+
return fileURLToPath(new URL("../dist/adapter.cjs", base2));
|
|
17748
|
+
} catch {
|
|
17749
|
+
return void 0;
|
|
17750
|
+
}
|
|
17751
|
+
}
|
|
17752
|
+
|
|
17613
17753
|
// ../../packages/build/src/next-version.ts
|
|
17614
17754
|
var NEXT_RELEASE_DATES = {
|
|
17615
17755
|
16: "2025-10-21",
|
|
@@ -17619,7 +17759,6 @@ var NEXT_RELEASE_DATES = {
|
|
|
17619
17759
|
12: "2021-10-26"
|
|
17620
17760
|
};
|
|
17621
17761
|
var SUPPORT_WINDOW_YEARS = 2;
|
|
17622
|
-
var VERIFIED_15_FLOOR = { major: 15, minor: 5, patch: 21 };
|
|
17623
17762
|
var VERIFIED_16_FLOOR = { major: 16, minor: 2, patch: 11 };
|
|
17624
17763
|
function parseNextVersion(raw) {
|
|
17625
17764
|
const match = /^\s*(\d+)\.(\d+)\.(\d+)/.exec(raw);
|
|
@@ -17647,7 +17786,6 @@ function compare(a, b) {
|
|
|
17647
17786
|
return a.major - b.major || a.minor - b.minor || a.patch - b.patch;
|
|
17648
17787
|
}
|
|
17649
17788
|
function withinVerifiedRange(version3) {
|
|
17650
|
-
if (version3.major === 15) return compare(version3, VERIFIED_15_FLOOR) >= 0;
|
|
17651
17789
|
if (version3.major === 16) return compare(version3, VERIFIED_16_FLOOR) >= 0;
|
|
17652
17790
|
return version3.major > 16;
|
|
17653
17791
|
}
|
|
@@ -17663,34 +17801,34 @@ function classifyNextVersion(raw, now) {
|
|
|
17663
17801
|
reason: `Could not read a Next.js version from "${raw}".`
|
|
17664
17802
|
};
|
|
17665
17803
|
}
|
|
17666
|
-
|
|
17667
|
-
if (!windowEnd || version3.major < VERIFIED_15_FLOOR.major) {
|
|
17804
|
+
if (version3.major < MIN_SUPPORTED_NEXT_MAJOR) {
|
|
17668
17805
|
return {
|
|
17669
17806
|
status: "too-old",
|
|
17670
17807
|
version: version3,
|
|
17671
|
-
reason: `Next.js ${raw} is too old to deploy. Naro deploys Next.js
|
|
17808
|
+
reason: `Next.js ${raw} is too old to deploy. Naro deploys Next.js ${String(MIN_SUPPORTED_NEXT_MAJOR)} or newer. Upgrade to Next.js 16.`
|
|
17672
17809
|
};
|
|
17673
17810
|
}
|
|
17674
|
-
|
|
17811
|
+
const windowEnd = supportEndsAt(version3.major);
|
|
17812
|
+
if (windowEnd && now > windowEnd) {
|
|
17675
17813
|
return {
|
|
17676
|
-
status: "
|
|
17814
|
+
status: "past-support-window",
|
|
17677
17815
|
version: version3,
|
|
17678
|
-
reason: `Next.js ${version3.major} left its support window on ${formatDate(windowEnd)}. The build continues, but unsupported releases stop receiving security patches \u2014 upgrade
|
|
17816
|
+
reason: `Next.js ${version3.major} left its support window on ${formatDate(windowEnd)}. The build continues, but unsupported releases stop receiving security patches \u2014 upgrade Next.js. See https://nextjs.org/support-policy`
|
|
17679
17817
|
};
|
|
17680
17818
|
}
|
|
17681
17819
|
if (!withinVerifiedRange(version3)) {
|
|
17682
17820
|
return {
|
|
17683
|
-
status: "outside-
|
|
17821
|
+
status: "outside-verified-range",
|
|
17684
17822
|
version: version3,
|
|
17685
|
-
reason: `Next.js ${raw} is outside the range Naro verifies deploys on (>=
|
|
17823
|
+
reason: `Next.js ${raw} is outside the range Naro verifies deploys on (>=16.2.11). The build may fail in ways Naro cannot explain.`
|
|
17686
17824
|
};
|
|
17687
17825
|
}
|
|
17688
17826
|
return { status: "supported", version: version3, reason: "" };
|
|
17689
17827
|
}
|
|
17690
17828
|
|
|
17691
17829
|
// ../../packages/build/src/package-manager.ts
|
|
17692
|
-
import { access, readFile as
|
|
17693
|
-
import { join as
|
|
17830
|
+
import { access as access2, readFile as readFile3 } from "fs/promises";
|
|
17831
|
+
import { join as join3 } from "path";
|
|
17694
17832
|
function cacheEnv(dir, manager) {
|
|
17695
17833
|
return {
|
|
17696
17834
|
...manager === "pnpm" ? { npm_config_store_dir: dir } : {},
|
|
@@ -17710,9 +17848,9 @@ function withSharedCache(spec, dir) {
|
|
|
17710
17848
|
addEnv: { ...spec.addEnv, ...cacheEnv(dir, spec.name) }
|
|
17711
17849
|
};
|
|
17712
17850
|
}
|
|
17713
|
-
async function
|
|
17851
|
+
async function exists2(path) {
|
|
17714
17852
|
try {
|
|
17715
|
-
await
|
|
17853
|
+
await access2(path);
|
|
17716
17854
|
return true;
|
|
17717
17855
|
} catch {
|
|
17718
17856
|
return false;
|
|
@@ -17720,7 +17858,7 @@ async function exists(path) {
|
|
|
17720
17858
|
}
|
|
17721
17859
|
async function usesModernYarn(root) {
|
|
17722
17860
|
try {
|
|
17723
|
-
const raw = await
|
|
17861
|
+
const raw = await readFile3(join3(root, "package.json"), "utf8");
|
|
17724
17862
|
const packageJson = JSON.parse(raw);
|
|
17725
17863
|
if (typeof packageJson.packageManager !== "string") return false;
|
|
17726
17864
|
const version3 = /^yarn@(\d+)/.exec(packageJson.packageManager)?.[1];
|
|
@@ -17730,7 +17868,7 @@ async function usesModernYarn(root) {
|
|
|
17730
17868
|
}
|
|
17731
17869
|
}
|
|
17732
17870
|
async function detectPackageManager(root) {
|
|
17733
|
-
if (await
|
|
17871
|
+
if (await exists2(join3(root, "pnpm-lock.yaml"))) {
|
|
17734
17872
|
return {
|
|
17735
17873
|
name: "pnpm",
|
|
17736
17874
|
install: ["pnpm", "install", "--frozen-lockfile"],
|
|
@@ -17741,7 +17879,7 @@ async function detectPackageManager(root) {
|
|
|
17741
17879
|
addArgs: (specs) => ["pnpm", "add", ...specs]
|
|
17742
17880
|
};
|
|
17743
17881
|
}
|
|
17744
|
-
if (await
|
|
17882
|
+
if (await exists2(join3(root, "package-lock.json"))) {
|
|
17745
17883
|
return {
|
|
17746
17884
|
name: "npm",
|
|
17747
17885
|
install: ["npm", "ci"],
|
|
@@ -17767,7 +17905,7 @@ async function detectPackageManager(root) {
|
|
|
17767
17905
|
sharedCacheAddArgs: ["--prefer-offline"]
|
|
17768
17906
|
};
|
|
17769
17907
|
}
|
|
17770
|
-
if (await
|
|
17908
|
+
if (await exists2(join3(root, "yarn.lock"))) {
|
|
17771
17909
|
const modern = await usesModernYarn(root);
|
|
17772
17910
|
return {
|
|
17773
17911
|
name: "yarn",
|
|
@@ -17788,114 +17926,13 @@ async function detectPackageManager(root) {
|
|
|
17788
17926
|
);
|
|
17789
17927
|
}
|
|
17790
17928
|
|
|
17791
|
-
// ../../packages/build/src/proxy-to-middleware.ts
|
|
17792
|
-
import { access as access2, readFile as readFile3, rename, writeFile as writeFile2 } from "fs/promises";
|
|
17793
|
-
import { join as join3 } from "path";
|
|
17794
|
-
var EXTENSIONS = ["ts", "tsx", "js", "jsx"];
|
|
17795
|
-
var DIRECTORIES = ["", "src"];
|
|
17796
|
-
async function exists2(path) {
|
|
17797
|
-
try {
|
|
17798
|
-
await access2(path);
|
|
17799
|
-
return true;
|
|
17800
|
-
} catch {
|
|
17801
|
-
return false;
|
|
17802
|
-
}
|
|
17803
|
-
}
|
|
17804
|
-
function renameExport(source) {
|
|
17805
|
-
return source.replace(
|
|
17806
|
-
/(export\s+(?:default\s+)?(?:async\s+)?function\s+)proxy\b/g,
|
|
17807
|
-
"$1middleware"
|
|
17808
|
-
).replace(/(export\s+const\s+)proxy\b/g, "$1middleware");
|
|
17809
|
-
}
|
|
17810
|
-
async function convertProxyToMiddleware(appRoot) {
|
|
17811
|
-
for (const dir of DIRECTORIES) {
|
|
17812
|
-
for (const ext of EXTENSIONS) {
|
|
17813
|
-
const rel = join3(dir, `proxy.${ext}`);
|
|
17814
|
-
const proxyPath = join3(appRoot, rel);
|
|
17815
|
-
if (!await exists2(proxyPath)) continue;
|
|
17816
|
-
const middlewarePath = join3(appRoot, dir, `middleware.${ext}`);
|
|
17817
|
-
if (await exists2(middlewarePath)) return { converted: false };
|
|
17818
|
-
const source = await readFile3(proxyPath, "utf8");
|
|
17819
|
-
await writeFile2(middlewarePath, renameExport(source));
|
|
17820
|
-
await rename(proxyPath, `${proxyPath}.converted`);
|
|
17821
|
-
return { converted: true, file: rel };
|
|
17822
|
-
}
|
|
17823
|
-
}
|
|
17824
|
-
return { converted: false };
|
|
17825
|
-
}
|
|
17826
|
-
|
|
17827
17929
|
// ../../packages/build/src/vinext.ts
|
|
17828
|
-
import { access as
|
|
17829
|
-
import { join as join6, resolve
|
|
17930
|
+
import { access as access3, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
17931
|
+
import { join as join6, resolve } from "path";
|
|
17830
17932
|
|
|
17831
|
-
// ../../packages/build/src/
|
|
17832
|
-
import {
|
|
17833
|
-
import {
|
|
17834
|
-
basename,
|
|
17835
|
-
dirname,
|
|
17836
|
-
extname,
|
|
17837
|
-
isAbsolute,
|
|
17838
|
-
join as join4,
|
|
17839
|
-
relative,
|
|
17840
|
-
resolve,
|
|
17841
|
-
sep
|
|
17842
|
-
} from "path";
|
|
17843
|
-
function parseJsonc(source) {
|
|
17844
|
-
let output = "";
|
|
17845
|
-
let index = 0;
|
|
17846
|
-
let inString = false;
|
|
17847
|
-
let escaped = false;
|
|
17848
|
-
while (index < source.length) {
|
|
17849
|
-
const current = source[index] ?? "";
|
|
17850
|
-
const next = source[index + 1] ?? "";
|
|
17851
|
-
if (inString) {
|
|
17852
|
-
output += current;
|
|
17853
|
-
if (escaped) escaped = false;
|
|
17854
|
-
else if (current === "\\") escaped = true;
|
|
17855
|
-
else if (current === '"') inString = false;
|
|
17856
|
-
index += 1;
|
|
17857
|
-
continue;
|
|
17858
|
-
}
|
|
17859
|
-
if (current === '"') {
|
|
17860
|
-
inString = true;
|
|
17861
|
-
output += current;
|
|
17862
|
-
index += 1;
|
|
17863
|
-
continue;
|
|
17864
|
-
}
|
|
17865
|
-
if (current === "/" && next === "/") {
|
|
17866
|
-
index += 2;
|
|
17867
|
-
while (index < source.length && source[index] !== "\n") index += 1;
|
|
17868
|
-
continue;
|
|
17869
|
-
}
|
|
17870
|
-
if (current === "/" && next === "*") {
|
|
17871
|
-
index += 2;
|
|
17872
|
-
while (index < source.length && !(source[index] === "*" && source[index + 1] === "/"))
|
|
17873
|
-
index += 1;
|
|
17874
|
-
index += 2;
|
|
17875
|
-
continue;
|
|
17876
|
-
}
|
|
17877
|
-
output += current;
|
|
17878
|
-
index += 1;
|
|
17879
|
-
}
|
|
17880
|
-
return JSON.parse(output.replace(/,\s*([}\]])/g, "$1"));
|
|
17881
|
-
}
|
|
17882
|
-
function confinedPath(root, configuredPath, label2, base2 = root) {
|
|
17883
|
-
if (isAbsolute(configuredPath)) {
|
|
17884
|
-
throw new DeploymentError(
|
|
17885
|
-
"ARTIFACT_INVALID",
|
|
17886
|
-
`${label2} must be relative to the application root.`
|
|
17887
|
-
);
|
|
17888
|
-
}
|
|
17889
|
-
const resolved = resolve(base2, configuredPath);
|
|
17890
|
-
const relation = relative(root, resolved);
|
|
17891
|
-
if (relation === ".." || relation.startsWith(`..${sep}`) || isAbsolute(relation)) {
|
|
17892
|
-
throw new DeploymentError(
|
|
17893
|
-
"ARTIFACT_INVALID",
|
|
17894
|
-
`${label2} escapes the application root.`
|
|
17895
|
-
);
|
|
17896
|
-
}
|
|
17897
|
-
return resolved;
|
|
17898
|
-
}
|
|
17933
|
+
// ../../packages/build/src/artifact-files.ts
|
|
17934
|
+
import { readdir, readFile as readFile4, realpath } from "fs/promises";
|
|
17935
|
+
import { extname, isAbsolute, join as join4, relative, sep } from "path";
|
|
17899
17936
|
function contentType(path) {
|
|
17900
17937
|
switch (extname(path).toLowerCase()) {
|
|
17901
17938
|
case ".html":
|
|
@@ -17970,7 +18007,7 @@ async function assertInsideOnDisk(appRoot, directory, label2) {
|
|
|
17970
18007
|
);
|
|
17971
18008
|
}
|
|
17972
18009
|
}
|
|
17973
|
-
async function listArtifactFiles(root, label2 = "
|
|
18010
|
+
async function listArtifactFiles(root, label2 = "Build", appRoot) {
|
|
17974
18011
|
if (appRoot !== void 0) await assertInsideOnDisk(appRoot, root, label2);
|
|
17975
18012
|
const files = [];
|
|
17976
18013
|
async function visit(directory) {
|
|
@@ -17998,131 +18035,12 @@ async function listArtifactFiles(root, label2 = "OpenNext", appRoot) {
|
|
|
17998
18035
|
await visit(root);
|
|
17999
18036
|
return files;
|
|
18000
18037
|
}
|
|
18001
|
-
|
|
18002
|
-
|
|
18003
|
-
const resolved = isAbsolute(configuredPath) ? configuredPath : resolve(root, configuredPath);
|
|
18004
|
-
const relation = relative(root, resolved);
|
|
18005
|
-
if (relation === ".." || relation.startsWith(`..${sep}`) || isAbsolute(relation)) {
|
|
18006
|
-
throw new DeploymentError(
|
|
18007
|
-
"ARTIFACT_INVALID",
|
|
18008
|
-
"Wrangler config escapes the application root."
|
|
18009
|
-
);
|
|
18010
|
-
}
|
|
18011
|
-
await access3(resolved);
|
|
18012
|
-
return resolved;
|
|
18013
|
-
}
|
|
18014
|
-
for (const name of ["wrangler.jsonc", "wrangler.json"]) {
|
|
18015
|
-
const path = join4(root, name);
|
|
18016
|
-
try {
|
|
18017
|
-
await access3(path);
|
|
18018
|
-
return path;
|
|
18019
|
-
} catch {
|
|
18020
|
-
}
|
|
18021
|
-
}
|
|
18022
|
-
throw new DeploymentError(
|
|
18023
|
-
"ARTIFACT_INVALID",
|
|
18024
|
-
"A wrangler.jsonc or wrangler.json file is required."
|
|
18025
|
-
);
|
|
18026
|
-
}
|
|
18027
|
-
var OPEN_NEXT_LAYOUT = {
|
|
18028
|
-
outputRoot: ".open-next",
|
|
18029
|
-
bundleDir: ".open-next/worker-bundle"
|
|
18030
|
-
};
|
|
18031
|
-
async function readOpenNextArtifact(appRoot, identity, wranglerConfigPath) {
|
|
18032
|
-
const configPath = await findWranglerConfig(appRoot, wranglerConfigPath);
|
|
18033
|
-
return readWorkerArtifact(appRoot, identity, {
|
|
18034
|
-
wranglerConfigPath: configPath,
|
|
18035
|
-
...OPEN_NEXT_LAYOUT
|
|
18036
|
-
});
|
|
18037
|
-
}
|
|
18038
|
-
async function readWorkerArtifact(appRoot, identity, layout) {
|
|
18039
|
-
const listFiles = (root) => listArtifactFiles(root, "OpenNext", appRoot);
|
|
18040
|
-
try {
|
|
18041
|
-
const configPath = await findWranglerConfig(
|
|
18042
|
-
appRoot,
|
|
18043
|
-
layout.wranglerConfigPath
|
|
18044
|
-
);
|
|
18045
|
-
const metadata = parseJsonc(
|
|
18046
|
-
await readFile4(configPath, "utf8")
|
|
18047
|
-
);
|
|
18048
|
-
if (typeof metadata.main !== "string" || typeof metadata.compatibility_date !== "string") {
|
|
18049
|
-
throw new DeploymentError(
|
|
18050
|
-
"ARTIFACT_INVALID",
|
|
18051
|
-
"Wrangler metadata must declare main and compatibility_date."
|
|
18052
|
-
);
|
|
18053
|
-
}
|
|
18054
|
-
const configDir = dirname(configPath);
|
|
18055
|
-
const outputRoot = confinedPath(appRoot, layout.outputRoot, "Output root");
|
|
18056
|
-
const entrypointPath = confinedPath(
|
|
18057
|
-
appRoot,
|
|
18058
|
-
metadata.main,
|
|
18059
|
-
"Worker entrypoint",
|
|
18060
|
-
configDir
|
|
18061
|
-
);
|
|
18062
|
-
const entryRelation = relative(outputRoot, entrypointPath);
|
|
18063
|
-
if (entryRelation === ".." || entryRelation.startsWith(`..${sep}`) || isAbsolute(entryRelation)) {
|
|
18064
|
-
throw new DeploymentError(
|
|
18065
|
-
"ARTIFACT_INVALID",
|
|
18066
|
-
`Worker entrypoint must be inside ${layout.outputRoot}.`
|
|
18067
|
-
);
|
|
18068
|
-
}
|
|
18069
|
-
await access3(entrypointPath);
|
|
18070
|
-
const configuredAssets = typeof metadata.assets?.directory === "string" ? confinedPath(
|
|
18071
|
-
appRoot,
|
|
18072
|
-
metadata.assets.directory,
|
|
18073
|
-
"Assets directory",
|
|
18074
|
-
configDir
|
|
18075
|
-
) : join4(outputRoot, "assets");
|
|
18076
|
-
const assetsRelation = relative(outputRoot, configuredAssets);
|
|
18077
|
-
if (assetsRelation === ".." || assetsRelation.startsWith(`..${sep}`) || isAbsolute(assetsRelation)) {
|
|
18078
|
-
throw new DeploymentError(
|
|
18079
|
-
"ARTIFACT_INVALID",
|
|
18080
|
-
`Assets directory must be inside ${layout.outputRoot}.`
|
|
18081
|
-
);
|
|
18082
|
-
}
|
|
18083
|
-
const bundleRoot = confinedPath(appRoot, layout.bundleDir, "Bundle dir");
|
|
18084
|
-
let bundleExists = true;
|
|
18085
|
-
try {
|
|
18086
|
-
await access3(bundleRoot);
|
|
18087
|
-
} catch {
|
|
18088
|
-
bundleExists = false;
|
|
18089
|
-
}
|
|
18090
|
-
const bundleFiles = bundleExists ? await listFiles(bundleRoot) : null;
|
|
18091
|
-
const outputFiles = bundleFiles ?? await listFiles(outputRoot);
|
|
18092
|
-
const entrypointName = bundleFiles ? basename(entrypointPath) : relative(outputRoot, entrypointPath).split(sep).join("/");
|
|
18093
|
-
const assetsPrefix = `${relative(outputRoot, configuredAssets).split(sep).join("/")}/`;
|
|
18094
|
-
const entrypoint = outputFiles.find((file2) => file2.name === entrypointName);
|
|
18095
|
-
if (!entrypoint)
|
|
18096
|
-
throw new DeploymentError(
|
|
18097
|
-
"ARTIFACT_INVALID",
|
|
18098
|
-
"Worker entrypoint is missing from the build output."
|
|
18099
|
-
);
|
|
18100
|
-
return {
|
|
18101
|
-
...identity,
|
|
18102
|
-
entrypoint,
|
|
18103
|
-
modules: outputFiles.filter(
|
|
18104
|
-
(file2) => file2.name !== entrypointName && !file2.name.endsWith(".map") && file2.name !== "README.md" && (bundleFiles !== null || !file2.name.startsWith(assetsPrefix))
|
|
18105
|
-
),
|
|
18106
|
-
assets: (await listFiles(configuredAssets)).map((file2) => ({ ...file2 })),
|
|
18107
|
-
compatibilityDate: metadata.compatibility_date,
|
|
18108
|
-
compatibilityFlags: Array.isArray(metadata.compatibility_flags) ? metadata.compatibility_flags.filter(
|
|
18109
|
-
(flag) => typeof flag === "string"
|
|
18110
|
-
) : [],
|
|
18111
|
-
assetsBinding: typeof metadata.assets?.binding === "string" ? metadata.assets.binding : "ASSETS"
|
|
18112
|
-
};
|
|
18113
|
-
} catch (error51) {
|
|
18114
|
-
if (error51 instanceof DeploymentError) throw error51;
|
|
18115
|
-
throw new DeploymentError(
|
|
18116
|
-
"ARTIFACT_INVALID",
|
|
18117
|
-
"Could not read the Worker build output.",
|
|
18118
|
-
{ cause: error51 }
|
|
18119
|
-
);
|
|
18120
|
-
}
|
|
18121
|
-
}
|
|
18038
|
+
|
|
18039
|
+
// ../../packages/build/src/isr-cache-source.generated.ts
|
|
18040
|
+
var NARO_ISR_CACHE_SOURCE = '// Written by naro: vinext\'s data cache, shared across isolates and colos\n// through the dispatcher (spec 2026-11-06-isr-shared-cache \xA75).\n//\n// Layer 1 is this isolate\'s memory, with vinext\'s MemoryCacheHandler\n// semantics. Layer 2 is the store the dispatcher hands this request as\n// `ctx.props.NARO_CACHE` (an RPC stub, valid for this request only \u2014 never\n// kept). With no store (a build-time prerender, `vinext dev`, an older\n// dispatcher) this is a memory cache, as before.\n\nconst MEMORY_MAX_BYTES = 52_428_800;\nconst TAG_MEMO_TTL_MS = 5_000;\nconst TAG_MEMO_MAX = 10_000;\nconst ENTRY_MAX_CHARS = 2_097_152;\nconst ENTRY_MAX_TAGS = 256;\nconst TAG_MAX_CHARS = 1_024;\nconst TAG_LOOKUP_CHUNK = 256;\nconst SERIAL_VERSION = 1;\nconst WARN_INTERVAL_MS = 60_000;\nconst CONTEXT = Symbol.for("__cloudflare-context__");\n\n/** The store for the current request, or null. */\nexport function currentNaroCacheStore() {\n const context = globalThis[CONTEXT];\n return context?.ctx?.props?.NARO_CACHE ?? null;\n}\n\nfunction currentWaitUntil() {\n const ctx = globalThis[CONTEXT]?.ctx;\n return typeof ctx?.waitUntil === "function"\n ? (promise) => ctx.waitUntil(promise)\n : null;\n}\n\nconst isString = (value) => typeof value === "string";\n\nfunction unique(values) {\n return [...new Set(values)];\n}\n\nfunction readStringArray(ctx, field) {\n const value = ctx?.[field];\n return Array.isArray(value) ? value.filter(isString) : [];\n}\n\nfunction readPositiveNumber(ctx, field) {\n const value = ctx?.[field];\n return typeof value === "number" && value > 0 ? value : undefined;\n}\n\nfunction cacheControlOf(ctx) {\n const value = ctx?.cacheControl;\n return value !== null && typeof value === "object" ? value : undefined;\n}\n\nfunction readCacheControlNumber(ctx, field) {\n const value = cacheControlOf(ctx)?.[field] ?? ctx?.[field];\n return typeof value === "number" ? value : undefined;\n}\n\nfunction readCacheControlRevalidate(ctx) {\n const value = cacheControlOf(ctx)?.revalidate ?? ctx?.revalidate;\n return typeof value === "number" || value === false ? value : undefined;\n}\n\nfunction stringMapSize(map) {\n if (!map) return 0;\n let size = 0;\n for (const [key, value] of Object.entries(map)) {\n size += key.length;\n if (Array.isArray(value)) for (const item of value) size += item.length;\n else size += String(value).length;\n }\n return size;\n}\n\n/** vinext\'s estimate (shims/cache-handler.js), so the 50 MiB means the same. */\nfunction valueSize(value) {\n if (value === null || value === undefined) return 25;\n switch (value.kind) {\n case "FETCH":\n return JSON.stringify(value.data ?? "").length;\n case "PAGES":\n return (\n value.html.length +\n JSON.stringify(value.pageData ?? {}).length +\n stringMapSize(value.headers)\n );\n case "APP_PAGE":\n return (\n value.html.length +\n (value.rscData?.byteLength ?? 0) +\n (value.postponed?.length ?? 0) +\n stringMapSize(value.headers)\n );\n case "APP_ROUTE":\n return value.body.byteLength + stringMapSize(value.headers);\n case "REDIRECT":\n return JSON.stringify(value.props ?? {}).length;\n case "IMAGE":\n return (\n value.buffer.byteLength + value.extension.length + value.etag.length\n );\n default:\n return JSON.stringify(value).length;\n }\n}\n\nfunction entrySize(entry) {\n return (\n valueSize(entry.value) +\n entry.tags.reduce((sum, tag) => sum + tag.length, 0) +\n 64\n );\n}\n\nfunction toBase64(bytes) {\n let binary = "";\n for (let i = 0; i < bytes.length; i += 0x8000)\n binary += String.fromCharCode.apply(null, bytes.subarray(i, i + 0x8000));\n return btoa(binary);\n}\n\nfunction fromBase64(text) {\n const binary = atob(text);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return bytes;\n}\n\n/** One entry as the text layer 2 keeps. ArrayBuffers go as base64. */\nexport function serializeEntry(entry) {\n return JSON.stringify({ v: SERIAL_VERSION, ...entry }, (_key, value) => {\n if (value instanceof ArrayBuffer)\n return { __naroBytes: toBase64(new Uint8Array(value)) };\n if (ArrayBuffer.isView(value))\n return {\n __naroU8: toBase64(\n new Uint8Array(value.buffer, value.byteOffset, value.byteLength),\n ),\n };\n return value;\n });\n}\n\n/** The entry back, or null for another serial version. Throws on bad JSON. */\nexport function deserializeEntry(text) {\n const parsed = JSON.parse(text, (_key, value) => {\n if (value !== null && typeof value === "object") {\n if (isString(value.__naroBytes))\n return fromBase64(value.__naroBytes).buffer;\n if (isString(value.__naroU8)) return fromBase64(value.__naroU8);\n }\n return value;\n });\n if (\n parsed === null ||\n typeof parsed !== "object" ||\n parsed.v !== SERIAL_VERSION ||\n typeof parsed.lastModified !== "number" ||\n !Array.isArray(parsed.tags)\n )\n return null;\n return {\n value: parsed.value ?? null,\n tags: parsed.tags.filter(isString),\n lastModified: parsed.lastModified,\n revalidateAt:\n typeof parsed.revalidateAt === "number" ? parsed.revalidateAt : null,\n expireAt: typeof parsed.expireAt === "number" ? parsed.expireAt : null,\n cacheControl: parsed.cacheControl,\n };\n}\n\nfunction errorMessage(error) {\n return error instanceof Error && error.message\n ? error.message\n : String(error);\n}\n\nexport class NaroIsrCacheHandler {\n constructor({\n storeFor = currentNaroCacheStore,\n now = Date.now,\n waitUntilFor = currentWaitUntil,\n warn = (message) => console.warn(message),\n maxMemoryBytes = MEMORY_MAX_BYTES,\n tagMemoTtlMs = TAG_MEMO_TTL_MS,\n } = {}) {\n this.storeFor = storeFor;\n this.now = now;\n this.waitUntilFor = waitUntilFor;\n this.warn = warn;\n this.maxMemoryBytes = maxMemoryBytes;\n this.tagMemoTtlMs = tagMemoTtlMs;\n this.entries = new Map();\n this.memoryBytes = 0;\n this.tagMemo = new Map();\n this.lastWarnAt = -Infinity;\n }\n\n warnOnce(error) {\n const now = this.now();\n if (now - this.lastWarnAt < WARN_INTERVAL_MS) return;\n this.lastWarnAt = now;\n this.warn(`[naro-isr] shared cache unavailable: ${errorMessage(error)}`);\n }\n\n forget(key) {\n const existing = this.entries.get(key);\n if (!existing) return;\n this.memoryBytes -= existing.size;\n this.entries.delete(key);\n }\n\n remember(key, entry) {\n const size = entrySize(entry);\n this.forget(key);\n if (this.maxMemoryBytes <= 0 || size > this.maxMemoryBytes) return;\n this.entries.set(key, { ...entry, size });\n this.memoryBytes += size;\n while (this.memoryBytes > this.maxMemoryBytes) {\n const oldest = this.entries.keys().next().value;\n if (oldest === undefined) break;\n this.forget(oldest);\n }\n }\n\n setMemo(tag, time, fetchedAt) {\n this.tagMemo.delete(tag);\n this.tagMemo.set(tag, { time, fetchedAt });\n while (this.tagMemo.size > TAG_MEMO_MAX) {\n const oldest = this.tagMemo.keys().next().value;\n if (oldest === undefined) break;\n this.tagMemo.delete(oldest);\n }\n }\n\n /** Each tag\'s last revalidation as far as this isolate knows (ms, 0 = never). */\n async tagTimes(tags, store) {\n const now = this.now();\n const times = new Map();\n const missing = [];\n for (const tag of tags) {\n const memo = this.tagMemo.get(tag);\n // A tag over the cap never reaches layer 2 (set() does not write such\n // entries, the store ignores such tags): this isolate\'s own word only.\n if (\n memo &&\n (!store ||\n tag.length > TAG_MAX_CHARS ||\n now - memo.fetchedAt < this.tagMemoTtlMs)\n )\n times.set(tag, memo.time);\n else if (!store || tag.length > TAG_MAX_CHARS) times.set(tag, 0);\n else missing.push(tag);\n }\n if (missing.length === 0) return times;\n const chunks = [];\n for (let i = 0; i < missing.length; i += TAG_LOOKUP_CHUNK)\n chunks.push(missing.slice(i, i + TAG_LOOKUP_CHUNK));\n await Promise.all(\n chunks.map(async (chunk) => {\n let remote = null;\n try {\n remote = (await store.tagTimes(chunk)) ?? {};\n } catch (error) {\n this.warnOnce(error);\n }\n for (const tag of chunk) {\n const known = this.tagMemo.get(tag)?.time ?? 0;\n // A tag the store did not answer (failed read, or cut off by its\n // cap) keeps its old memo and fetch time, so the next get asks again.\n if (!remote || typeof remote[tag] !== "number") {\n times.set(tag, known);\n continue;\n }\n // Never forget a revalidation this isolate made: KV can answer an\n // older value for up to a minute after the write.\n const time = Math.max(known, remote[tag]);\n this.setMemo(tag, time, now);\n times.set(tag, time);\n }\n }),\n );\n return times;\n }\n\n /**\n * "valid", "own" (one of the entry\'s own tags was revalidated) or "soft"\n * (only a tag of the path asking was). vinext\'s MemoryCacheHandler evicts\n * only for an own tag: fetch entries are shared by several pages.\n */\n async validity(entry, softTags, store) {\n const tags = unique([...entry.tags, ...softTags]);\n if (tags.length === 0) return "valid";\n const times = await this.tagTimes(tags, store);\n const revalidated = (tag) => (times.get(tag) ?? 0) >= entry.lastModified;\n if (entry.tags.some(revalidated)) return "own";\n return softTags.some(revalidated) ? "soft" : "valid";\n }\n\n timing(entry, ctx) {\n const now = this.now();\n if (entry.expireAt !== null && now > entry.expireAt) return "expired";\n const requested = readPositiveNumber(ctx, "revalidate");\n const requestedAt =\n requested === undefined ? null : entry.lastModified + requested * 1000;\n if (\n (entry.revalidateAt !== null && now > entry.revalidateAt) ||\n (requestedAt !== null && now > requestedAt)\n )\n return "stale";\n return undefined;\n }\n\n answer(key, entry, cacheState) {\n // Most recently used goes last.\n const kept = this.entries.get(key);\n if (kept) {\n this.entries.delete(key);\n this.entries.set(key, kept);\n }\n return {\n lastModified: entry.lastModified,\n value: entry.value,\n ...(cacheState === undefined ? {} : { cacheState }),\n cacheControl: entry.cacheControl,\n };\n }\n\n async readRemote(store, key) {\n try {\n const found = await store.getEntry(key);\n if (!found || !isString(found.body)) return null;\n return deserializeEntry(found.body);\n } catch (error) {\n this.warnOnce(error);\n return null;\n }\n }\n\n async get(key, ctx) {\n const store = this.storeFor();\n const softTags = readStringArray(ctx, "softTags");\n const local = this.entries.get(key) ?? null;\n if (local) {\n const localValidity = await this.validity(local, softTags, store);\n if (localValidity === "valid") {\n const cacheState = this.timing(local, ctx);\n if (cacheState === undefined || !store)\n return this.answer(key, local, cacheState);\n // Stale here: another isolate may already have rendered a newer one.\n const remote = await this.readRemote(store, key);\n if (\n remote &&\n remote.lastModified > local.lastModified &&\n (await this.validity(remote, softTags, store)) === "valid"\n ) {\n this.remember(key, remote);\n return this.answer(key, remote, this.timing(remote, ctx));\n }\n return this.answer(key, local, cacheState);\n }\n // Only its own tags evict; a soft tag just makes this get a miss.\n if (localValidity === "own") this.forget(key);\n }\n if (!store) return null;\n const remote = await this.readRemote(store, key);\n if (!remote || (await this.validity(remote, softTags, store)) !== "valid")\n return null;\n this.remember(key, remote);\n return this.answer(key, remote, this.timing(remote, ctx));\n }\n\n async set(key, data, ctx) {\n const tags = unique([\n ...(data && Array.isArray(data.tags) ? data.tags.filter(isString) : []),\n ...readStringArray(ctx, "tags"),\n ]);\n let revalidate = readCacheControlRevalidate(ctx);\n const expire = readCacheControlNumber(ctx, "expire");\n const stale = readCacheControlNumber(ctx, "stale");\n if (data && typeof data.revalidate === "number")\n revalidate = data.revalidate;\n else if (data && data.revalidate === false) revalidate ??= false;\n if (revalidate === 0) return;\n const now = this.now();\n const entry = {\n value: data,\n tags,\n lastModified: now,\n revalidateAt:\n typeof revalidate === "number" && revalidate > 0\n ? now + revalidate * 1000\n : null,\n expireAt:\n typeof expire === "number" && expire > 0 ? now + expire * 1000 : null,\n cacheControl:\n typeof revalidate === "number" || revalidate === false\n ? {\n revalidate,\n ...(expire === undefined ? {} : { expire }),\n ...(stale === undefined ? {} : { stale }),\n }\n : undefined,\n };\n this.remember(key, entry);\n const store = this.storeFor();\n if (!store) return;\n if (\n tags.length > ENTRY_MAX_TAGS ||\n tags.some((tag) => tag.length > TAG_MAX_CHARS)\n )\n return;\n // The serialized text is never shorter than the size estimate (base64 is\n // 4/3 of the bytes, and the field names come on top), so an entry over the\n // limit by estimate is dropped without being serialized, which for a big\n // body would cost several times its size in memory.\n if (entrySize(entry) > ENTRY_MAX_CHARS) return;\n const body = serializeEntry(entry);\n if (body.length > ENTRY_MAX_CHARS) return;\n const write = Promise.resolve()\n .then(() => store.putEntry(key, body, { lastModified: now, tags }))\n .catch((error) => this.warnOnce(error));\n const waitUntil = this.waitUntilFor();\n if (waitUntil) waitUntil(write);\n else await write;\n }\n\n async revalidateTag(tags) {\n const list = unique((Array.isArray(tags) ? tags : [tags]).filter(isString));\n if (list.length === 0) return;\n const now = this.now();\n for (const tag of list)\n this.setMemo(tag, Math.max(this.tagMemo.get(tag)?.time ?? 0, now), now);\n const store = this.storeFor();\n if (!store) return;\n try {\n const recorded = await store.revalidateTags(list);\n if (typeof recorded === "number") {\n const fetchedAt = this.now();\n for (const tag of list)\n this.setMemo(\n tag,\n Math.max(this.tagMemo.get(tag)?.time ?? 0, recorded),\n fetchedAt,\n );\n }\n } catch (error) {\n this.warnOnce(error);\n }\n }\n\n resetRequestCache() {}\n}\n\n/** vinext calls this once per isolate with `{ env, options }`. */\nexport default function createNaroIsrCache({ options } = {}) {\n const ttl = options?.tagMemoTtlMs;\n return new NaroIsrCacheHandler(\n Number.isInteger(ttl) && ttl >= 0 && ttl <= 60_000\n ? { tagMemoTtlMs: ttl }\n : {},\n );\n}\n';
|
|
18122
18041
|
|
|
18123
18042
|
// ../../packages/build/src/platform-config.ts
|
|
18124
|
-
import {
|
|
18125
|
-
import { createRequire } from "module";
|
|
18043
|
+
import { writeFile as writeFile3 } from "fs/promises";
|
|
18126
18044
|
import { join as join5 } from "path";
|
|
18127
18045
|
var COMPATIBILITY_DATE = "2026-08-19";
|
|
18128
18046
|
var NEXT_CONFIG_FILES = [
|
|
@@ -18131,14 +18049,6 @@ var NEXT_CONFIG_FILES = [
|
|
|
18131
18049
|
"next.config.cjs",
|
|
18132
18050
|
"next.config.ts"
|
|
18133
18051
|
];
|
|
18134
|
-
async function pathExists(path) {
|
|
18135
|
-
try {
|
|
18136
|
-
await access4(path);
|
|
18137
|
-
return true;
|
|
18138
|
-
} catch {
|
|
18139
|
-
return false;
|
|
18140
|
-
}
|
|
18141
|
-
}
|
|
18142
18052
|
var BUILD_NPMRC = [
|
|
18143
18053
|
"# Host package-manager credentials are intentionally unavailable.",
|
|
18144
18054
|
"audit=false",
|
|
@@ -18153,61 +18063,40 @@ async function createPackageManagerConfig(appRoot, writer = async (path, content
|
|
|
18153
18063
|
await writer(packageManagerConfigPath, BUILD_NPMRC);
|
|
18154
18064
|
return packageManagerConfigPath;
|
|
18155
18065
|
}
|
|
18156
|
-
|
|
18157
|
-
|
|
18158
|
-
|
|
18159
|
-
"
|
|
18160
|
-
|
|
18161
|
-
|
|
18162
|
-
|
|
18163
|
-
|
|
18164
|
-
|
|
18165
|
-
|
|
18166
|
-
if (
|
|
18167
|
-
|
|
18168
|
-
|
|
18066
|
+
|
|
18067
|
+
// ../../packages/build/src/wrangler-output.ts
|
|
18068
|
+
function globToRegExp(glob) {
|
|
18069
|
+
let source = "";
|
|
18070
|
+
for (let index = 0; index < glob.length; index += 1) {
|
|
18071
|
+
const char = glob[index];
|
|
18072
|
+
if (char !== "*") {
|
|
18073
|
+
source += char?.replace(/[.+?^${}()|[\]\\]/g, String.raw`\$&`) ?? "";
|
|
18074
|
+
continue;
|
|
18075
|
+
}
|
|
18076
|
+
if (glob[index + 1] !== "*") {
|
|
18077
|
+
source += "[^/]*";
|
|
18078
|
+
continue;
|
|
18079
|
+
}
|
|
18080
|
+
if (glob[index + 2] === "/") {
|
|
18081
|
+
source += "(?:[^/]*/)*";
|
|
18082
|
+
index += 2;
|
|
18083
|
+
} else {
|
|
18084
|
+
source += ".*";
|
|
18085
|
+
index += 1;
|
|
18169
18086
|
}
|
|
18170
18087
|
}
|
|
18171
|
-
|
|
18172
|
-
|
|
18173
|
-
|
|
18174
|
-
|
|
18175
|
-
|
|
18176
|
-
|
|
18177
|
-
|
|
18178
|
-
|
|
18179
|
-
|
|
18180
|
-
|
|
18181
|
-
|
|
18182
|
-
|
|
18183
|
-
);
|
|
18184
|
-
await writer(
|
|
18185
|
-
wranglerConfigPath,
|
|
18186
|
-
`${JSON.stringify(
|
|
18187
|
-
{
|
|
18188
|
-
name: `next-deploy-${safeDeploymentId}`,
|
|
18189
|
-
main: ".open-next/worker.js",
|
|
18190
|
-
compatibility_date: COMPATIBILITY_DATE,
|
|
18191
|
-
compatibility_flags: ["nodejs_compat"],
|
|
18192
|
-
assets: {
|
|
18193
|
-
directory: ".open-next/assets",
|
|
18194
|
-
binding: "ASSETS"
|
|
18195
|
-
}
|
|
18196
|
-
},
|
|
18197
|
-
null,
|
|
18198
|
-
2
|
|
18199
|
-
)}
|
|
18200
|
-
`
|
|
18201
|
-
);
|
|
18202
|
-
const packageManagerConfigPath = await createPackageManagerConfig(
|
|
18203
|
-
appRoot,
|
|
18204
|
-
writer
|
|
18205
|
-
);
|
|
18206
|
-
return {
|
|
18207
|
-
openNextConfigPath,
|
|
18208
|
-
wranglerConfigPath,
|
|
18209
|
-
packageManagerConfigPath
|
|
18210
|
-
};
|
|
18088
|
+
return new RegExp(`^${source}$`);
|
|
18089
|
+
}
|
|
18090
|
+
function moduleRules(rules) {
|
|
18091
|
+
if (!Array.isArray(rules)) return [];
|
|
18092
|
+
return rules.flatMap((rule) => {
|
|
18093
|
+
const { type, globs } = rule;
|
|
18094
|
+
if (!Array.isArray(globs)) return [];
|
|
18095
|
+
return globs.filter((glob) => typeof glob === "string").map((glob) => ({
|
|
18096
|
+
type: typeof type === "string" ? type : "",
|
|
18097
|
+
test: globToRegExp(glob)
|
|
18098
|
+
}));
|
|
18099
|
+
});
|
|
18211
18100
|
}
|
|
18212
18101
|
|
|
18213
18102
|
// ../../packages/build/src/vinext.ts
|
|
@@ -18230,6 +18119,8 @@ var VITE_CONFIG_NAMES = [
|
|
|
18230
18119
|
];
|
|
18231
18120
|
var GENERATED_VITE_CONFIG = "vite.config.js";
|
|
18232
18121
|
var GENERATED_WORKER_ENTRY = "naro-worker.js";
|
|
18122
|
+
var GENERATED_ISR_CACHE = "naro-isr-cache.js";
|
|
18123
|
+
var ISR_SHARED_CACHE_OFF_NOTE = "ISR shared cache is off: the project builds with its own vite.config.";
|
|
18233
18124
|
var VINEXT_WORKER_ENTRY_SOURCE = `// Written by naro: vinext's Worker, with getCloudflareContext() given its env.
|
|
18234
18125
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
18235
18126
|
import handler from "vinext/server/fetch-handler";
|
|
@@ -18264,7 +18155,7 @@ function vinextWranglerConfigPath(appRoot) {
|
|
|
18264
18155
|
}
|
|
18265
18156
|
async function exists3(path) {
|
|
18266
18157
|
try {
|
|
18267
|
-
await
|
|
18158
|
+
await access3(path);
|
|
18268
18159
|
return true;
|
|
18269
18160
|
} catch {
|
|
18270
18161
|
return false;
|
|
@@ -18288,6 +18179,13 @@ async function createVinextBuildConfig(appRoot, deploymentId, writer = async (pa
|
|
|
18288
18179
|
`The project already has a ${GENERATED_WORKER_ENTRY}. Naro writes its vinext Worker entry under that name and will not overwrite a file of the project's.`
|
|
18289
18180
|
);
|
|
18290
18181
|
}
|
|
18182
|
+
const isrCachePath = join6(appRoot, GENERATED_ISR_CACHE);
|
|
18183
|
+
if (await exists3(isrCachePath)) {
|
|
18184
|
+
throw new DeploymentError(
|
|
18185
|
+
"ARTIFACT_INVALID",
|
|
18186
|
+
`The project already has a ${GENERATED_ISR_CACHE}. Naro writes its ISR cache handler under that name and will not overwrite a file of the project's.`
|
|
18187
|
+
);
|
|
18188
|
+
}
|
|
18291
18189
|
const safeDeploymentId = deploymentId.replace(/[^a-z0-9-]/gi, "-");
|
|
18292
18190
|
const viteConfigPath = join6(appRoot, GENERATED_VITE_CONFIG);
|
|
18293
18191
|
const wranglerConfigPath = join6(appRoot, "wrangler.jsonc");
|
|
@@ -18300,7 +18198,7 @@ async function createVinextBuildConfig(appRoot, deploymentId, writer = async (pa
|
|
|
18300
18198
|
"",
|
|
18301
18199
|
"export default defineConfig({",
|
|
18302
18200
|
" plugins: [",
|
|
18303
|
-
|
|
18201
|
+
` vinext({ cache: { data: { adapter: ${JSON.stringify(isrCachePath)} } } }),`,
|
|
18304
18202
|
' cloudflare({ viteEnvironment: { name: "rsc", childEnvironments: ["ssr"] } }),',
|
|
18305
18203
|
" ],",
|
|
18306
18204
|
"});",
|
|
@@ -18308,6 +18206,7 @@ async function createVinextBuildConfig(appRoot, deploymentId, writer = async (pa
|
|
|
18308
18206
|
].join("\n")
|
|
18309
18207
|
);
|
|
18310
18208
|
await writer(workerEntryPath, VINEXT_WORKER_ENTRY_SOURCE);
|
|
18209
|
+
await writer(isrCachePath, NARO_ISR_CACHE_SOURCE);
|
|
18311
18210
|
await writer(
|
|
18312
18211
|
wranglerConfigPath,
|
|
18313
18212
|
`${JSON.stringify(
|
|
@@ -18360,8 +18259,8 @@ function parseVinextCheckReport(output) {
|
|
|
18360
18259
|
function vinextRouteFromCheck(report) {
|
|
18361
18260
|
if (!report)
|
|
18362
18261
|
return {
|
|
18363
|
-
eligible:
|
|
18364
|
-
reason: "vinext check output could not be read;
|
|
18262
|
+
eligible: true,
|
|
18263
|
+
reason: "vinext check output could not be read; trying the build anyway. Expected if vinext changed its report format."
|
|
18365
18264
|
};
|
|
18366
18265
|
const autoFixed = report.issueLines.filter(
|
|
18367
18266
|
(line) => AUTO_FIXED_ISSUES.some((pattern) => pattern.test(line))
|
|
@@ -18373,7 +18272,7 @@ function vinextRouteFromCheck(report) {
|
|
|
18373
18272
|
if (blocking > 0)
|
|
18374
18273
|
return {
|
|
18375
18274
|
eligible: false,
|
|
18376
|
-
reason: `vinext check reported ${blocking} unsupported item(s) (${report.percent}% compatible)
|
|
18275
|
+
reason: `vinext check reported ${blocking} unsupported item(s) (${report.percent}% compatible).`
|
|
18377
18276
|
};
|
|
18378
18277
|
if (autoFixed.length > 0)
|
|
18379
18278
|
return {
|
|
@@ -18385,38 +18284,12 @@ function vinextRouteFromCheck(report) {
|
|
|
18385
18284
|
reason: report.partial > 0 ? `vinext check found no blocking issues (${report.partial} partially supported); attempting a vinext build.` : "vinext check found no issues; attempting a vinext build."
|
|
18386
18285
|
};
|
|
18387
18286
|
}
|
|
18388
|
-
function globToRegExp(glob) {
|
|
18389
|
-
let source = "";
|
|
18390
|
-
for (let index = 0; index < glob.length; index += 1) {
|
|
18391
|
-
const char = glob[index];
|
|
18392
|
-
if (char !== "*") {
|
|
18393
|
-
source += char?.replace(/[.+?^${}()|[\]\\]/g, String.raw`\$&`) ?? "";
|
|
18394
|
-
continue;
|
|
18395
|
-
}
|
|
18396
|
-
if (glob[index + 1] !== "*") {
|
|
18397
|
-
source += "[^/]*";
|
|
18398
|
-
continue;
|
|
18399
|
-
}
|
|
18400
|
-
if (glob[index + 2] === "/") {
|
|
18401
|
-
source += "(?:[^/]*/)*";
|
|
18402
|
-
index += 2;
|
|
18403
|
-
} else {
|
|
18404
|
-
source += ".*";
|
|
18405
|
-
index += 1;
|
|
18406
|
-
}
|
|
18407
|
-
}
|
|
18408
|
-
return new RegExp(`^${source}$`);
|
|
18409
|
-
}
|
|
18410
18287
|
function moduleMatchers(rules) {
|
|
18411
|
-
|
|
18412
|
-
return rules.flatMap((rule) => {
|
|
18413
|
-
const globs = rule.globs;
|
|
18414
|
-
return Array.isArray(globs) ? globs : [];
|
|
18415
|
-
}).filter((glob) => typeof glob === "string").map(globToRegExp);
|
|
18288
|
+
return moduleRules(rules).map((rule) => rule.test);
|
|
18416
18289
|
}
|
|
18417
18290
|
async function readVinextArtifact(appRoot, identity) {
|
|
18418
18291
|
try {
|
|
18419
|
-
const outputRoot =
|
|
18292
|
+
const outputRoot = resolve(appRoot, VINEXT_OUTPUT_DIR);
|
|
18420
18293
|
const serverRoot = join6(outputRoot, SERVER_DIR);
|
|
18421
18294
|
const clientRoot = join6(outputRoot, CLIENT_DIR);
|
|
18422
18295
|
const configPath = join6(serverRoot, WRANGLER_OUTPUT_NAME);
|
|
@@ -18477,7 +18350,7 @@ var FRAMEWORK_PRESETS = {
|
|
|
18477
18350
|
id: "next",
|
|
18478
18351
|
detectDependency: "next",
|
|
18479
18352
|
defaultBuildScript: "build",
|
|
18480
|
-
defaultOutputDirectory: "
|
|
18353
|
+
defaultOutputDirectory: "dist",
|
|
18481
18354
|
needsServerRuntime: true,
|
|
18482
18355
|
spaFallback: false,
|
|
18483
18356
|
cachePath: ".next/cache"
|
|
@@ -18815,9 +18688,85 @@ async function detectFramework(root, overrides = {}) {
|
|
|
18815
18688
|
};
|
|
18816
18689
|
}
|
|
18817
18690
|
|
|
18691
|
+
// ../../packages/build/src/naro-adapter-artifact.ts
|
|
18692
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
18693
|
+
import { join as join8 } from "path";
|
|
18694
|
+
var RULE_CONTENT_TYPES = {
|
|
18695
|
+
ESModule: "application/javascript+module",
|
|
18696
|
+
CommonJS: "application/javascript",
|
|
18697
|
+
Text: "text/plain",
|
|
18698
|
+
Data: "application/octet-stream",
|
|
18699
|
+
CompiledWasm: "application/wasm"
|
|
18700
|
+
};
|
|
18701
|
+
var CONFIG_NAME = "wrangler.jsonc";
|
|
18702
|
+
async function readNaroAdapterArtifact(appRoot, identity) {
|
|
18703
|
+
try {
|
|
18704
|
+
const workerRoot = join8(appRoot, WORKER_DIR);
|
|
18705
|
+
let metadata;
|
|
18706
|
+
try {
|
|
18707
|
+
metadata = JSON.parse(
|
|
18708
|
+
await readFile7(join8(workerRoot, CONFIG_NAME), "utf8")
|
|
18709
|
+
);
|
|
18710
|
+
} catch (error51) {
|
|
18711
|
+
throw new DeploymentError(
|
|
18712
|
+
"ARTIFACT_INVALID",
|
|
18713
|
+
`The Naro adapter produced no ${WORKER_DIR}/${CONFIG_NAME}.`,
|
|
18714
|
+
{ cause: error51 }
|
|
18715
|
+
);
|
|
18716
|
+
}
|
|
18717
|
+
if (typeof metadata.main !== "string" || typeof metadata.compatibility_date !== "string")
|
|
18718
|
+
throw new DeploymentError(
|
|
18719
|
+
"ARTIFACT_INVALID",
|
|
18720
|
+
"Naro adapter wrangler output must declare main and compatibility_date."
|
|
18721
|
+
);
|
|
18722
|
+
const rules = moduleRules(metadata.rules);
|
|
18723
|
+
const files = await listArtifactFiles(workerRoot, "naro-adapter", appRoot);
|
|
18724
|
+
const entry = files.find((file2) => file2.name === metadata.main);
|
|
18725
|
+
if (!entry)
|
|
18726
|
+
throw new DeploymentError(
|
|
18727
|
+
"ARTIFACT_INVALID",
|
|
18728
|
+
`Naro adapter worker entrypoint "${metadata.main}" is missing from the build output.`
|
|
18729
|
+
);
|
|
18730
|
+
const modules = files.filter(
|
|
18731
|
+
(file2) => file2.name !== metadata.main && file2.name !== CONFIG_NAME && !file2.name.endsWith(".map")
|
|
18732
|
+
).map((file2) => {
|
|
18733
|
+
const rule = rules.find((candidate) => candidate.test.test(file2.name));
|
|
18734
|
+
const contentType2 = rule ? RULE_CONTENT_TYPES[rule.type] : void 0;
|
|
18735
|
+
if (!contentType2)
|
|
18736
|
+
throw new DeploymentError(
|
|
18737
|
+
"ARTIFACT_INVALID",
|
|
18738
|
+
`Naro adapter output file "${file2.name}" matches no module rule.`
|
|
18739
|
+
);
|
|
18740
|
+
return { ...file2, contentType: contentType2 };
|
|
18741
|
+
});
|
|
18742
|
+
return {
|
|
18743
|
+
...identity,
|
|
18744
|
+
entrypoint: { ...entry, contentType: "application/javascript+module" },
|
|
18745
|
+
modules,
|
|
18746
|
+
assets: await listArtifactFiles(
|
|
18747
|
+
join8(appRoot, ASSETS_DIR),
|
|
18748
|
+
"naro-adapter",
|
|
18749
|
+
appRoot
|
|
18750
|
+
),
|
|
18751
|
+
compatibilityDate: metadata.compatibility_date,
|
|
18752
|
+
compatibilityFlags: Array.isArray(metadata.compatibility_flags) ? metadata.compatibility_flags.filter(
|
|
18753
|
+
(flag) => typeof flag === "string"
|
|
18754
|
+
) : [],
|
|
18755
|
+
assetsBinding: typeof metadata.assets?.binding === "string" ? metadata.assets.binding : "ASSETS"
|
|
18756
|
+
};
|
|
18757
|
+
} catch (error51) {
|
|
18758
|
+
if (error51 instanceof DeploymentError) throw error51;
|
|
18759
|
+
throw new DeploymentError(
|
|
18760
|
+
"ARTIFACT_INVALID",
|
|
18761
|
+
"Could not read the Naro adapter output.",
|
|
18762
|
+
{ cause: error51 }
|
|
18763
|
+
);
|
|
18764
|
+
}
|
|
18765
|
+
}
|
|
18766
|
+
|
|
18818
18767
|
// ../../packages/build/src/next-routes.ts
|
|
18819
18768
|
import { readdir as readdir2, stat as stat2 } from "fs/promises";
|
|
18820
|
-
import { join as
|
|
18769
|
+
import { join as join9 } from "path";
|
|
18821
18770
|
var APP_PAGE_FILE = /^page\.(?:js|jsx|ts|tsx|md|mdx)$/;
|
|
18822
18771
|
var PAGES_ROUTER_FILE = /^(.+)\.(?:js|jsx|ts|tsx)$/;
|
|
18823
18772
|
var DECLARATION_FILE = /\.d\.ts$/;
|
|
@@ -18831,7 +18780,7 @@ function errorCode(error51) {
|
|
|
18831
18780
|
}
|
|
18832
18781
|
async function firstDirectory(root, candidates) {
|
|
18833
18782
|
for (const candidate of candidates) {
|
|
18834
|
-
const path =
|
|
18783
|
+
const path = join9(root, candidate);
|
|
18835
18784
|
try {
|
|
18836
18785
|
if ((await stat2(path)).isDirectory()) return path;
|
|
18837
18786
|
} catch (error51) {
|
|
@@ -18861,7 +18810,7 @@ async function readAppRouter(dir, segments, routes) {
|
|
|
18861
18810
|
const name = entry.name;
|
|
18862
18811
|
if (name.startsWith("_") || INTERCEPTING.test(name)) continue;
|
|
18863
18812
|
const next = ROUTE_GROUP.test(name) || name.startsWith("@") ? segments : [...segments, urlSegment(name, "app")];
|
|
18864
|
-
await readAppRouter(
|
|
18813
|
+
await readAppRouter(join9(dir, name), next, routes);
|
|
18865
18814
|
}
|
|
18866
18815
|
}
|
|
18867
18816
|
async function readPagesRouter(dir, segments, routes) {
|
|
@@ -18870,7 +18819,7 @@ async function readPagesRouter(dir, segments, routes) {
|
|
|
18870
18819
|
if (entry.isDirectory()) {
|
|
18871
18820
|
if (segments.length === 0 && entry.name === "api") continue;
|
|
18872
18821
|
await readPagesRouter(
|
|
18873
|
-
|
|
18822
|
+
join9(dir, entry.name),
|
|
18874
18823
|
[...segments, urlSegment(entry.name, "pages")],
|
|
18875
18824
|
routes
|
|
18876
18825
|
);
|
|
@@ -18888,8 +18837,8 @@ async function readPagesRouter(dir, segments, routes) {
|
|
|
18888
18837
|
}
|
|
18889
18838
|
}
|
|
18890
18839
|
async function listNextRoutes(appRoot) {
|
|
18891
|
-
const app = await firstDirectory(appRoot, ["app",
|
|
18892
|
-
const pages = await firstDirectory(appRoot, ["pages",
|
|
18840
|
+
const app = await firstDirectory(appRoot, ["app", join9("src", "app")]);
|
|
18841
|
+
const pages = await firstDirectory(appRoot, ["pages", join9("src", "pages")]);
|
|
18893
18842
|
if (!app && !pages) return null;
|
|
18894
18843
|
const routes = /* @__PURE__ */ new Set();
|
|
18895
18844
|
if (app) await readAppRouter(app, [], routes);
|
|
@@ -19126,14 +19075,14 @@ async function runCommand(spec, observer) {
|
|
|
19126
19075
|
|
|
19127
19076
|
// ../../packages/build/src/repository.ts
|
|
19128
19077
|
import { realpath as realpath2 } from "fs/promises";
|
|
19129
|
-
import { isAbsolute as isAbsolute2, relative as relative2, resolve as
|
|
19078
|
+
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2, sep as sep2 } from "path";
|
|
19130
19079
|
function resolveAppRoot(checkout, configuredRoot) {
|
|
19131
|
-
const checkoutRoot =
|
|
19080
|
+
const checkoutRoot = resolve2(checkout);
|
|
19132
19081
|
if (!configuredRoot) return checkoutRoot;
|
|
19133
19082
|
if (isAbsolute2(configuredRoot)) {
|
|
19134
19083
|
throw new Error("Configured root directory escapes repository");
|
|
19135
19084
|
}
|
|
19136
|
-
const appRoot =
|
|
19085
|
+
const appRoot = resolve2(checkoutRoot, configuredRoot);
|
|
19137
19086
|
const relativeRoot = relative2(checkoutRoot, appRoot);
|
|
19138
19087
|
if (relativeRoot === ".." || relativeRoot.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute2(relativeRoot)) {
|
|
19139
19088
|
throw new Error("Configured root directory escapes repository");
|
|
@@ -19164,8 +19113,8 @@ async function assertAppRootInsideCheckout(checkout, appRoot) {
|
|
|
19164
19113
|
}
|
|
19165
19114
|
|
|
19166
19115
|
// ../../packages/build/src/static-artifact.ts
|
|
19167
|
-
import { readdir as readdir3, readFile as
|
|
19168
|
-
import { isAbsolute as isAbsolute3, join as
|
|
19116
|
+
import { readdir as readdir3, readFile as readFile8 } from "fs/promises";
|
|
19117
|
+
import { isAbsolute as isAbsolute3, join as join10, relative as relative3, resolve as resolve3, sep as sep3 } from "path";
|
|
19169
19118
|
var SHIM_WORKER_SOURCE = "export default { fetch: (request, env) => env.ASSETS.fetch(request) };\n";
|
|
19170
19119
|
var EXCLUDED_DIRECTORIES = /* @__PURE__ */ new Set(["node_modules"]);
|
|
19171
19120
|
var ALLOWED_DOTFILE = ".well-known";
|
|
@@ -19179,7 +19128,7 @@ async function readStaticArtifact(appRoot, outputDirectory, identity, options, o
|
|
|
19179
19128
|
"ARTIFACT_INVALID",
|
|
19180
19129
|
"Output directory must be relative to the application root."
|
|
19181
19130
|
);
|
|
19182
|
-
const outputRoot =
|
|
19131
|
+
const outputRoot = resolve3(appRoot, outputDirectory);
|
|
19183
19132
|
const relation = relative3(appRoot, outputRoot);
|
|
19184
19133
|
if (relation === ".." || relation.startsWith(`..${sep3}`) || isAbsolute3(relation))
|
|
19185
19134
|
throw new DeploymentError(
|
|
@@ -19198,7 +19147,7 @@ async function readStaticArtifact(appRoot, outputDirectory, identity, options, o
|
|
|
19198
19147
|
(left, right) => left.name.localeCompare(right.name)
|
|
19199
19148
|
)) {
|
|
19200
19149
|
if (excluded(entry.name)) continue;
|
|
19201
|
-
const path =
|
|
19150
|
+
const path = join10(directory, entry.name);
|
|
19202
19151
|
if (entry.isSymbolicLink())
|
|
19203
19152
|
throw new DeploymentError(
|
|
19204
19153
|
"ARTIFACT_INVALID",
|
|
@@ -19208,7 +19157,7 @@ async function readStaticArtifact(appRoot, outputDirectory, identity, options, o
|
|
|
19208
19157
|
else if (entry.isFile()) {
|
|
19209
19158
|
assets.push({
|
|
19210
19159
|
name: relative3(outputRoot, path).split(sep3).join("/"),
|
|
19211
|
-
data: await
|
|
19160
|
+
data: await readFile8(path),
|
|
19212
19161
|
contentType: contentType(path)
|
|
19213
19162
|
});
|
|
19214
19163
|
}
|
|
@@ -19254,8 +19203,8 @@ async function readStaticArtifact(appRoot, outputDirectory, identity, options, o
|
|
|
19254
19203
|
|
|
19255
19204
|
// ../../packages/build/src/strategy/fingerprint.ts
|
|
19256
19205
|
import { createHash as createHash3 } from "crypto";
|
|
19257
|
-
import { readFile as
|
|
19258
|
-
import { join as
|
|
19206
|
+
import { readFile as readFile9 } from "fs/promises";
|
|
19207
|
+
import { join as join11, relative as relative4, sep as sep4 } from "path";
|
|
19259
19208
|
var APP_ROOT_FILES = [
|
|
19260
19209
|
"package.json",
|
|
19261
19210
|
"next.config.js",
|
|
@@ -19292,18 +19241,18 @@ function sha256(data) {
|
|
|
19292
19241
|
}
|
|
19293
19242
|
async function hashFile(path) {
|
|
19294
19243
|
try {
|
|
19295
|
-
return sha256(await
|
|
19244
|
+
return sha256(await readFile9(path));
|
|
19296
19245
|
} catch {
|
|
19297
19246
|
return null;
|
|
19298
19247
|
}
|
|
19299
19248
|
}
|
|
19300
19249
|
async function hashStrategyInputs(checkout, appRoot) {
|
|
19301
19250
|
const candidates = /* @__PURE__ */ new Set();
|
|
19302
|
-
for (const name of CHECKOUT_FILES) candidates.add(
|
|
19303
|
-
for (const name of APP_ROOT_FILES) candidates.add(
|
|
19251
|
+
for (const name of CHECKOUT_FILES) candidates.add(join11(checkout, name));
|
|
19252
|
+
for (const name of APP_ROOT_FILES) candidates.add(join11(appRoot, name));
|
|
19304
19253
|
for (const base2 of SOURCE_FILES) {
|
|
19305
19254
|
for (const ext of SOURCE_EXTENSIONS) {
|
|
19306
|
-
candidates.add(
|
|
19255
|
+
candidates.add(join11(appRoot, `${base2}.${ext}`));
|
|
19307
19256
|
}
|
|
19308
19257
|
}
|
|
19309
19258
|
const entries = [];
|
|
@@ -19331,12 +19280,12 @@ async function computeStrategyFingerprint(input) {
|
|
|
19331
19280
|
}
|
|
19332
19281
|
|
|
19333
19282
|
// ../../packages/build/src/strategy/project-facts.ts
|
|
19334
|
-
import { access as
|
|
19335
|
-
import { join as
|
|
19283
|
+
import { access as access4, readFile as readFile11 } from "fs/promises";
|
|
19284
|
+
import { join as join13 } from "path";
|
|
19336
19285
|
|
|
19337
19286
|
// ../../packages/build/src/strategy/user-adapter.ts
|
|
19338
|
-
import { readFile as
|
|
19339
|
-
import { join as
|
|
19287
|
+
import { readFile as readFile10 } from "fs/promises";
|
|
19288
|
+
import { join as join12 } from "path";
|
|
19340
19289
|
var ADAPTER_PATH = /\badapterPath\b/;
|
|
19341
19290
|
var EXPERIMENTAL_ADAPTER_PATH = /\bexperimental\s*:\s*\{[^{}]*\badapterPath\b/;
|
|
19342
19291
|
function adapterKeyFromConfigSource(source) {
|
|
@@ -19368,8 +19317,8 @@ async function adapterInBuildOutput(appRoot, nextVersion) {
|
|
|
19368
19317
|
let manifest2;
|
|
19369
19318
|
try {
|
|
19370
19319
|
const parsed = JSON.parse(
|
|
19371
|
-
await
|
|
19372
|
-
|
|
19320
|
+
await readFile10(
|
|
19321
|
+
join12(appRoot, ".next", "required-server-files.json"),
|
|
19373
19322
|
"utf8"
|
|
19374
19323
|
)
|
|
19375
19324
|
);
|
|
@@ -19380,10 +19329,14 @@ async function adapterInBuildOutput(appRoot, nextVersion) {
|
|
|
19380
19329
|
}
|
|
19381
19330
|
const topLevel = manifest2.config?.adapterPath;
|
|
19382
19331
|
if (keys.includes("adapterPath") && typeof topLevel === "string" && topLevel)
|
|
19383
|
-
return { source: "build-output", key: "adapterPath" };
|
|
19332
|
+
return { source: "build-output", key: "adapterPath", path: topLevel };
|
|
19384
19333
|
const experimental = manifest2.config?.experimental?.adapterPath;
|
|
19385
19334
|
if (keys.includes("experimental.adapterPath") && typeof experimental === "string" && experimental)
|
|
19386
|
-
return {
|
|
19335
|
+
return {
|
|
19336
|
+
source: "build-output",
|
|
19337
|
+
key: "experimental.adapterPath",
|
|
19338
|
+
path: experimental
|
|
19339
|
+
};
|
|
19387
19340
|
return null;
|
|
19388
19341
|
}
|
|
19389
19342
|
function describeUserAdapter(adapter) {
|
|
@@ -19396,9 +19349,6 @@ function describeUserAdapter(adapter) {
|
|
|
19396
19349
|
return `${adapter.key} in the Next.js build output`;
|
|
19397
19350
|
}
|
|
19398
19351
|
}
|
|
19399
|
-
function openNextAdapterWarning(adapter) {
|
|
19400
|
-
return `P2 opennext-cloudflare: The project sets its own Next.js adapter (${describeUserAdapter(adapter)}); its modifyConfig and onBuildComplete also run in the OpenNext build.`;
|
|
19401
|
-
}
|
|
19402
19352
|
|
|
19403
19353
|
// ../../packages/build/src/strategy/project-facts.ts
|
|
19404
19354
|
var SOURCE_EXTENSIONS2 = ["ts", "tsx", "js", "jsx", "mjs", "mts"];
|
|
@@ -19411,17 +19361,17 @@ var VITE_CONFIGS = [
|
|
|
19411
19361
|
];
|
|
19412
19362
|
async function exists4(path) {
|
|
19413
19363
|
try {
|
|
19414
|
-
await
|
|
19364
|
+
await access4(path);
|
|
19415
19365
|
return true;
|
|
19416
19366
|
} catch {
|
|
19417
19367
|
return false;
|
|
19418
19368
|
}
|
|
19419
19369
|
}
|
|
19420
|
-
async function findSourceFile(appRoot,
|
|
19370
|
+
async function findSourceFile(appRoot, basename5) {
|
|
19421
19371
|
for (const dir of SOURCE_DIRECTORIES) {
|
|
19422
19372
|
for (const ext of SOURCE_EXTENSIONS2) {
|
|
19423
|
-
const rel = dir ? `${dir}/${
|
|
19424
|
-
if (await exists4(
|
|
19373
|
+
const rel = dir ? `${dir}/${basename5}.${ext}` : `${basename5}.${ext}`;
|
|
19374
|
+
if (await exists4(join13(appRoot, rel))) return rel;
|
|
19425
19375
|
}
|
|
19426
19376
|
}
|
|
19427
19377
|
return null;
|
|
@@ -19441,14 +19391,15 @@ function matcherRoutesFromSource(source) {
|
|
|
19441
19391
|
}
|
|
19442
19392
|
async function readIfExists(path) {
|
|
19443
19393
|
try {
|
|
19444
|
-
return await
|
|
19394
|
+
return await readFile11(path, "utf8");
|
|
19445
19395
|
} catch {
|
|
19446
19396
|
return null;
|
|
19447
19397
|
}
|
|
19448
19398
|
}
|
|
19449
19399
|
async function findAdapterConfig(appRoot) {
|
|
19450
19400
|
for (const file2 of NEXT_CONFIG_FILES) {
|
|
19451
|
-
|
|
19401
|
+
if (file2 === "next.config.cjs") continue;
|
|
19402
|
+
const source = await readIfExists(join13(appRoot, file2));
|
|
19452
19403
|
if (source === null) continue;
|
|
19453
19404
|
const key = adapterKeyFromConfigSource(source);
|
|
19454
19405
|
return key ? { file: file2, key } : null;
|
|
@@ -19459,10 +19410,10 @@ async function collectProjectFacts(appRoot) {
|
|
|
19459
19410
|
const proxyFile = await findSourceFile(appRoot, "proxy");
|
|
19460
19411
|
const middlewareFile = await findSourceFile(appRoot, "middleware");
|
|
19461
19412
|
const routeSourceFile = middlewareFile ?? proxyFile;
|
|
19462
|
-
const routeSource = routeSourceFile ? await readIfExists(
|
|
19413
|
+
const routeSource = routeSourceFile ? await readIfExists(join13(appRoot, routeSourceFile)) : null;
|
|
19463
19414
|
let usesVinext = false;
|
|
19464
19415
|
let nextSpec = null;
|
|
19465
|
-
const packageJsonSource = await readIfExists(
|
|
19416
|
+
const packageJsonSource = await readIfExists(join13(appRoot, "package.json"));
|
|
19466
19417
|
if (packageJsonSource) {
|
|
19467
19418
|
try {
|
|
19468
19419
|
const packageJson = JSON.parse(packageJsonSource);
|
|
@@ -19473,7 +19424,7 @@ async function collectProjectFacts(appRoot) {
|
|
|
19473
19424
|
nextSpec = dependency("next");
|
|
19474
19425
|
if (dependency("vinext") !== null) {
|
|
19475
19426
|
for (const name of VITE_CONFIGS) {
|
|
19476
|
-
const config2 = await readIfExists(
|
|
19427
|
+
const config2 = await readIfExists(join13(appRoot, name));
|
|
19477
19428
|
if (config2 && /\bvinext\s*\(/.test(config2) && /@cloudflare\/vite-plugin/.test(config2)) {
|
|
19478
19429
|
usesVinext = true;
|
|
19479
19430
|
break;
|
|
@@ -19742,7 +19693,8 @@ async function fetchStatus(fetchImpl, url2, timeoutMs) {
|
|
|
19742
19693
|
clearTimeout(timer);
|
|
19743
19694
|
}
|
|
19744
19695
|
}
|
|
19745
|
-
function probeOk(status) {
|
|
19696
|
+
function probeOk(status, expect) {
|
|
19697
|
+
if (expect === "found" && status === 404) return false;
|
|
19746
19698
|
return status < 500;
|
|
19747
19699
|
}
|
|
19748
19700
|
function createSmokeTester(options = {}) {
|
|
@@ -19829,7 +19781,11 @@ function createSmokeTester(options = {}) {
|
|
|
19829
19781
|
`${origin}${probe.path}`,
|
|
19830
19782
|
probeTimeoutMs
|
|
19831
19783
|
);
|
|
19832
|
-
const result = "status" in answer ? {
|
|
19784
|
+
const result = "status" in answer ? {
|
|
19785
|
+
...probe,
|
|
19786
|
+
status: answer.status,
|
|
19787
|
+
ok: probeOk(answer.status, probe.expect)
|
|
19788
|
+
} : { ...probe, status: null, ok: false, detail: answer.error };
|
|
19833
19789
|
probes2.push(result);
|
|
19834
19790
|
await observer.onLog({
|
|
19835
19791
|
level: result.ok ? "INFO" : "ERROR",
|
|
@@ -19874,13 +19830,40 @@ function defaultSmokeProbes(matcherRoutes) {
|
|
|
19874
19830
|
return probes2;
|
|
19875
19831
|
}
|
|
19876
19832
|
|
|
19877
|
-
// ../../packages/build/src/strategy/strategies/
|
|
19878
|
-
|
|
19879
|
-
|
|
19833
|
+
// ../../packages/build/src/strategy/strategies/unavailable.ts
|
|
19834
|
+
function createUnavailableStrategy(options) {
|
|
19835
|
+
return {
|
|
19836
|
+
id: options.id,
|
|
19837
|
+
priority: options.priority,
|
|
19838
|
+
target: options.target,
|
|
19839
|
+
supports: () => ({ supported: false, reason: options.reason }),
|
|
19840
|
+
evaluate: async () => ({ status: "skipped", reason: options.reason })
|
|
19841
|
+
};
|
|
19842
|
+
}
|
|
19843
|
+
function createSplitCloudflareStrategy() {
|
|
19844
|
+
return createUnavailableStrategy({
|
|
19845
|
+
id: "split-cloudflare",
|
|
19846
|
+
priority: 3,
|
|
19847
|
+
target: "cloudflare-split",
|
|
19848
|
+
reason: "Split Cloudflare deployment needs the dispatcher to chain a middleware Worker in front of the app Worker; the runtime plane routes one Worker per hostname today."
|
|
19849
|
+
});
|
|
19850
|
+
}
|
|
19851
|
+
function createAwsMiddlewareCloudflareAppStrategy() {
|
|
19852
|
+
return createUnavailableStrategy({
|
|
19853
|
+
id: "aws-middleware-cloudflare-app",
|
|
19854
|
+
priority: 4,
|
|
19855
|
+
target: "aws-hybrid",
|
|
19856
|
+
reason: "Hybrid AWS middleware + Cloudflare app needs an AWS deploy target and cross-cloud request chaining; neither exists on this control plane."
|
|
19857
|
+
});
|
|
19858
|
+
}
|
|
19859
|
+
|
|
19860
|
+
// ../../packages/build/src/strategy/strategies/naro-adapter-cloudflare.ts
|
|
19861
|
+
import { readFile as readFile13, rm as rm2 } from "fs/promises";
|
|
19862
|
+
import { join as join15, resolve as resolve5 } from "path";
|
|
19880
19863
|
|
|
19881
19864
|
// ../../packages/build/src/strategy/strategies/shared.ts
|
|
19882
|
-
import { access as
|
|
19883
|
-
import { dirname
|
|
19865
|
+
import { access as access5, readFile as readFile12, rm, writeFile as writeFile5 } from "fs/promises";
|
|
19866
|
+
import { dirname, join as join14, resolve as resolve4 } from "path";
|
|
19884
19867
|
function capturingObserver(observer) {
|
|
19885
19868
|
const lines = [];
|
|
19886
19869
|
return {
|
|
@@ -19916,31 +19899,28 @@ function describeFailure(step) {
|
|
|
19916
19899
|
function failed(stage, reason) {
|
|
19917
19900
|
return { status: "failed", stage, reason };
|
|
19918
19901
|
}
|
|
19919
|
-
function appBuildFailed(reason) {
|
|
19920
|
-
return { status: "failed", stage: "build", reason, appBuild: true };
|
|
19921
|
-
}
|
|
19922
19902
|
async function info(observer, message) {
|
|
19923
19903
|
await observer.onLog({ level: "INFO", stage: "BUILDING", message });
|
|
19924
19904
|
}
|
|
19925
19905
|
async function warn(observer, message) {
|
|
19926
19906
|
await observer.onLog({ level: "WARN", stage: "BUILDING", message });
|
|
19927
19907
|
}
|
|
19928
|
-
async function
|
|
19908
|
+
async function pathExists(path) {
|
|
19929
19909
|
try {
|
|
19930
|
-
await
|
|
19910
|
+
await access5(path);
|
|
19931
19911
|
return true;
|
|
19932
19912
|
} catch {
|
|
19933
19913
|
return false;
|
|
19934
19914
|
}
|
|
19935
19915
|
}
|
|
19936
19916
|
async function findProjectBin(appRoot, checkout, name) {
|
|
19937
|
-
let dir =
|
|
19938
|
-
const stop =
|
|
19917
|
+
let dir = resolve4(appRoot);
|
|
19918
|
+
const stop = resolve4(checkout);
|
|
19939
19919
|
for (; ; ) {
|
|
19940
|
-
const candidate =
|
|
19941
|
-
if (await
|
|
19920
|
+
const candidate = join14(dir, "node_modules", ".bin", name);
|
|
19921
|
+
if (await pathExists(candidate)) return candidate;
|
|
19942
19922
|
if (dir === stop) return null;
|
|
19943
|
-
const parent =
|
|
19923
|
+
const parent = dirname(dir);
|
|
19944
19924
|
if (parent === dir) return null;
|
|
19945
19925
|
dir = parent;
|
|
19946
19926
|
}
|
|
@@ -19951,7 +19931,7 @@ function dotenvQuote(value) {
|
|
|
19951
19931
|
return `"${value.replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r")}"`;
|
|
19952
19932
|
}
|
|
19953
19933
|
async function withDevVars(wranglerConfigPath, env, run) {
|
|
19954
|
-
const path =
|
|
19934
|
+
const path = join14(dirname(wranglerConfigPath), ".dev.vars");
|
|
19955
19935
|
const keys = Object.keys(env).filter(
|
|
19956
19936
|
(key) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(key)
|
|
19957
19937
|
);
|
|
@@ -19968,36 +19948,7 @@ async function withDevVars(wranglerConfigPath, env, run) {
|
|
|
19968
19948
|
await rm(path, { force: true });
|
|
19969
19949
|
}
|
|
19970
19950
|
}
|
|
19971
|
-
async function
|
|
19972
|
-
return runStep(
|
|
19973
|
-
context,
|
|
19974
|
-
{
|
|
19975
|
-
command: context.toolchain.wrangler,
|
|
19976
|
-
args: [
|
|
19977
|
-
"deploy",
|
|
19978
|
-
"--dry-run",
|
|
19979
|
-
"--config",
|
|
19980
|
-
layout.wranglerConfigPath,
|
|
19981
|
-
"--outdir",
|
|
19982
|
-
layout.bundleDir
|
|
19983
|
-
],
|
|
19984
|
-
cwd: layout.appRoot,
|
|
19985
|
-
env: {
|
|
19986
|
-
CI: "1",
|
|
19987
|
-
WRANGLER_LOG_PATH: join13(
|
|
19988
|
-
layout.appRoot,
|
|
19989
|
-
layout.outputRoot,
|
|
19990
|
-
"wrangler.log"
|
|
19991
|
-
)
|
|
19992
|
-
},
|
|
19993
|
-
timeoutMs: 5 * 6e4,
|
|
19994
|
-
stage: "BUILDING",
|
|
19995
|
-
errorCode: errorCode2
|
|
19996
|
-
},
|
|
19997
|
-
observer
|
|
19998
|
-
);
|
|
19999
|
-
}
|
|
20000
|
-
async function smokeWorker(context, layout, observer) {
|
|
19951
|
+
async function smokeWorker(context, layout, observer, extraProbes = []) {
|
|
20001
19952
|
return withDevVars(
|
|
20002
19953
|
layout.wranglerConfigPath,
|
|
20003
19954
|
context.env,
|
|
@@ -20017,19 +19968,22 @@ async function smokeWorker(context, layout, observer) {
|
|
|
20017
19968
|
"--show-interactive-dev-session=false",
|
|
20018
19969
|
"--log-level=warn",
|
|
20019
19970
|
"--persist-to",
|
|
20020
|
-
|
|
19971
|
+
join14(layout.appRoot, layout.outputRoot, ".naro-smoke-state")
|
|
20021
19972
|
],
|
|
20022
19973
|
cwd: layout.appRoot,
|
|
20023
19974
|
env: {
|
|
20024
19975
|
CI: "1",
|
|
20025
|
-
WRANGLER_LOG_PATH:
|
|
19976
|
+
WRANGLER_LOG_PATH: join14(
|
|
20026
19977
|
layout.appRoot,
|
|
20027
19978
|
layout.outputRoot,
|
|
20028
19979
|
"wrangler-dev.log"
|
|
20029
19980
|
)
|
|
20030
19981
|
}
|
|
20031
19982
|
}),
|
|
20032
|
-
probes:
|
|
19983
|
+
probes: [
|
|
19984
|
+
...defaultSmokeProbes(context.facts.matcherRoutes),
|
|
19985
|
+
...extraProbes
|
|
19986
|
+
],
|
|
20033
19987
|
stage: "BUILDING",
|
|
20034
19988
|
errorCode: "BUILD_FAILED"
|
|
20035
19989
|
},
|
|
@@ -20038,10 +19992,10 @@ async function smokeWorker(context, layout, observer) {
|
|
|
20038
19992
|
);
|
|
20039
19993
|
}
|
|
20040
19994
|
async function approvePnpmBuilds(checkout, packages) {
|
|
20041
|
-
const path =
|
|
19995
|
+
const path = join14(checkout, "pnpm-workspace.yaml");
|
|
20042
19996
|
let source = "";
|
|
20043
19997
|
try {
|
|
20044
|
-
source = await
|
|
19998
|
+
source = await readFile12(path, "utf8");
|
|
20045
19999
|
} catch {
|
|
20046
20000
|
}
|
|
20047
20001
|
let next = source;
|
|
@@ -20088,412 +20042,191 @@ ${listEntries}
|
|
|
20088
20042
|
}
|
|
20089
20043
|
}
|
|
20090
20044
|
|
|
20091
|
-
// ../../packages/build/src/strategy/strategies/
|
|
20092
|
-
var
|
|
20093
|
-
|
|
20094
|
-
|
|
20095
|
-
|
|
20096
|
-
|
|
20097
|
-
|
|
20098
|
-
|
|
20099
|
-
|
|
20100
|
-
|
|
20101
|
-
|
|
20102
|
-
|
|
20103
|
-
|
|
20104
|
-
|
|
20105
|
-
|
|
20106
|
-
|
|
20045
|
+
// ../../packages/build/src/strategy/strategies/naro-adapter-cloudflare.ts
|
|
20046
|
+
var NARO_ADAPTER_REASONS = {
|
|
20047
|
+
notInstalled: "The Naro adapter is not installed in this build environment.",
|
|
20048
|
+
unknownVersion: "The installed Next.js version could not be read; the Naro adapter needs Next.js 16.2 or newer.",
|
|
20049
|
+
missingOutput: "next build finished without the Naro adapter's output; another Next.js adapter may have run instead.",
|
|
20050
|
+
userAdapterRan: (key) => `next build ran the project's own Next.js adapter (${key} in the Next.js build output) instead of the Naro adapter. Naro replaces an adapter only when next.config sets adapterPath itself; this one is set somewhere Naro does not read before the build, such as an imported file.`
|
|
20051
|
+
};
|
|
20052
|
+
var REPLACE_TAIL = "Your repository is unchanged, and your adapter's modifyConfig and onBuildComplete do not run. To keep your adapter (vinext only), change the project's Next.js adapter setting.";
|
|
20053
|
+
function replaceWarning(adapter) {
|
|
20054
|
+
return adapter.source === "next-config" ? `${adapter.file} sets its own Next.js adapter (${adapter.key}); this build replaces it with the Naro adapter in a temporary copy. ${REPLACE_TAIL}` : `NEXT_ADAPTER_PATH sets its own Next.js adapter; this build replaces it with the Naro adapter. ${REPLACE_TAIL}`;
|
|
20055
|
+
}
|
|
20056
|
+
async function readRecord(appRoot) {
|
|
20057
|
+
try {
|
|
20058
|
+
const parsed = JSON.parse(
|
|
20059
|
+
await readFile13(join15(appRoot, BUILD_RECORD), "utf8")
|
|
20060
|
+
);
|
|
20061
|
+
if (typeof parsed.buildId !== "string" || typeof parsed.distDir !== "string")
|
|
20062
|
+
return null;
|
|
20063
|
+
const staticFiles = Array.isArray(parsed.outputs?.staticFiles) ? parsed.outputs.staticFiles : [];
|
|
20064
|
+
return {
|
|
20065
|
+
buildId: parsed.buildId,
|
|
20066
|
+
distDir: parsed.distDir,
|
|
20067
|
+
basePath: typeof parsed.config?.basePath === "string" ? parsed.config.basePath : "",
|
|
20068
|
+
staticPathnames: staticFiles.flatMap((file2) => {
|
|
20069
|
+
const pathname = file2?.pathname;
|
|
20070
|
+
return typeof pathname === "string" ? [pathname] : [];
|
|
20071
|
+
})
|
|
20072
|
+
};
|
|
20073
|
+
} catch {
|
|
20074
|
+
return null;
|
|
20075
|
+
}
|
|
20076
|
+
}
|
|
20077
|
+
function naroAdapterSmokeProbes(record3, assetNames) {
|
|
20078
|
+
const { basePath } = record3;
|
|
20079
|
+
const probes2 = [];
|
|
20080
|
+
const assetPrefix = `${basePath}/_next/static/`;
|
|
20081
|
+
const script = assetNames.find(
|
|
20082
|
+
(name) => `/${name}`.startsWith(assetPrefix) && name.endsWith(".js")
|
|
20083
|
+
);
|
|
20084
|
+
if (script)
|
|
20085
|
+
probes2.push({ path: `/${script}`, label: "static asset", expect: "found" });
|
|
20086
|
+
const notPages = new Set(
|
|
20087
|
+
["/404", "/500", "/index"].map((path) => `${basePath}${path}`)
|
|
20088
|
+
);
|
|
20089
|
+
const page2 = record3.staticPathnames.find(
|
|
20090
|
+
(pathname) => !pathname.startsWith(assetPrefix) && !pathname.endsWith(".rsc") && !notPages.has(pathname)
|
|
20091
|
+
);
|
|
20092
|
+
if (page2) probes2.push({ path: page2, label: "static page", expect: "found" });
|
|
20093
|
+
return probes2;
|
|
20094
|
+
}
|
|
20095
|
+
async function readBuildId(distDir) {
|
|
20096
|
+
try {
|
|
20097
|
+
return (await readFile13(join15(distDir, "BUILD_ID"), "utf8")).trim();
|
|
20098
|
+
} catch {
|
|
20099
|
+
return null;
|
|
20100
|
+
}
|
|
20107
20101
|
}
|
|
20108
|
-
function
|
|
20102
|
+
function createNaroAdapterCloudflareStrategy(options) {
|
|
20109
20103
|
return {
|
|
20110
|
-
id: "
|
|
20111
|
-
priority:
|
|
20112
|
-
target: "
|
|
20104
|
+
id: "naro-adapter-cloudflare",
|
|
20105
|
+
priority: 2,
|
|
20106
|
+
target: "cloudflare",
|
|
20113
20107
|
supports(context) {
|
|
20114
|
-
if (!context.
|
|
20108
|
+
if (!context.toolchain.nextAdapter)
|
|
20109
|
+
return { supported: false, reason: NARO_ADAPTER_REASONS.notInstalled };
|
|
20110
|
+
const verdict = judgeNextVersion(context.nextVersion);
|
|
20111
|
+
if (!verdict)
|
|
20115
20112
|
return {
|
|
20116
20113
|
supported: false,
|
|
20117
|
-
reason:
|
|
20114
|
+
reason: NARO_ADAPTER_REASONS.unknownVersion
|
|
20118
20115
|
};
|
|
20119
|
-
if (
|
|
20116
|
+
if (verdict.kind === "too-old")
|
|
20120
20117
|
return {
|
|
20121
20118
|
supported: false,
|
|
20122
|
-
reason:
|
|
20119
|
+
reason: `The Naro adapter needs Next.js 16.2 or newer; this project runs Next.js ${context.nextVersion}.`
|
|
20120
|
+
};
|
|
20121
|
+
const adapter = userAdapterOf(context);
|
|
20122
|
+
if (adapter && context.userAdapter === "keep")
|
|
20123
|
+
return {
|
|
20124
|
+
supported: false,
|
|
20125
|
+
reason: `The project keeps its own Next.js adapter (${describeUserAdapter(adapter)}) by its Next.js adapter setting, so the Naro adapter is skipped.`
|
|
20123
20126
|
};
|
|
20124
20127
|
return { supported: true };
|
|
20125
20128
|
},
|
|
20126
20129
|
async evaluate(context, observer) {
|
|
20127
|
-
|
|
20128
|
-
|
|
20129
|
-
|
|
20130
|
-
)
|
|
20130
|
+
const adapterPath = context.toolchain.nextAdapter;
|
|
20131
|
+
if (!adapterPath)
|
|
20132
|
+
return { status: "skipped", reason: NARO_ADAPTER_REASONS.notInstalled };
|
|
20133
|
+
if (judgeNextVersion(context.nextVersion)?.kind === "newer")
|
|
20134
|
+
await warn(
|
|
20135
|
+
observer,
|
|
20136
|
+
`Next.js ${context.nextVersion} is newer than the versions the Naro adapter is tested with (${testedRange()}); building anyway.`
|
|
20137
|
+
);
|
|
20131
20138
|
let fork;
|
|
20132
20139
|
try {
|
|
20133
|
-
fork = await context.workspace.fork("
|
|
20140
|
+
fork = await context.workspace.fork("naro-adapter");
|
|
20134
20141
|
} catch (error51) {
|
|
20135
20142
|
return failed("prepare", describeError(error51));
|
|
20136
20143
|
}
|
|
20137
|
-
|
|
20138
|
-
|
|
20139
|
-
|
|
20140
|
-
|
|
20141
|
-
|
|
20142
|
-
|
|
20143
|
-
|
|
20144
|
-
|
|
20145
|
-
|
|
20146
|
-
|
|
20147
|
-
|
|
20144
|
+
await rm2(join15(fork.appRoot, OUTPUT_DIR), {
|
|
20145
|
+
recursive: true,
|
|
20146
|
+
force: true
|
|
20147
|
+
});
|
|
20148
|
+
const userAdapter = userAdapterOf(context);
|
|
20149
|
+
if (userAdapter && userAdapter.source !== "build-output") {
|
|
20150
|
+
let replaced = true;
|
|
20151
|
+
if (userAdapter.source === "next-config") {
|
|
20152
|
+
try {
|
|
20153
|
+
replaced = await wrapNextConfig(fork.appRoot, userAdapter.file) !== null;
|
|
20154
|
+
} catch (error51) {
|
|
20155
|
+
return failed("prepare", describeError(error51));
|
|
20156
|
+
}
|
|
20157
|
+
}
|
|
20158
|
+
if (replaced) await warn(observer, replaceWarning(userAdapter));
|
|
20148
20159
|
}
|
|
20149
20160
|
const build = await runStep(
|
|
20150
20161
|
context,
|
|
20151
20162
|
{
|
|
20152
|
-
command: context.
|
|
20153
|
-
args: ["
|
|
20163
|
+
command: context.packageManager.name,
|
|
20164
|
+
args: ["run", context.buildScript],
|
|
20154
20165
|
cwd: fork.appRoot,
|
|
20155
20166
|
env: {
|
|
20156
20167
|
...context.env,
|
|
20157
|
-
|
|
20168
|
+
NEXT_ADAPTER_PATH: adapterPath,
|
|
20169
|
+
NPM_CONFIG_USERCONFIG: context.packageManagerConfigPath,
|
|
20170
|
+
CI: "1"
|
|
20158
20171
|
},
|
|
20159
|
-
timeoutMs:
|
|
20160
|
-
stage: "BUILDING",
|
|
20161
|
-
errorCode: "BUILD_FAILED"
|
|
20162
|
-
},
|
|
20163
|
-
observer
|
|
20164
|
-
);
|
|
20165
|
-
if (!build.ok) return failed("build", describeFailure(build));
|
|
20166
|
-
const serverFunction = join14(fork.appRoot, SERVER_FUNCTION);
|
|
20167
|
-
if (!await pathExists2(serverFunction))
|
|
20168
|
-
return failed("bundle", `OpenNext AWS produced no ${SERVER_FUNCTION}.`);
|
|
20169
|
-
const smoke = await context.ports.smoke.run(
|
|
20170
|
-
{
|
|
20171
|
-
boot: (port) => ({
|
|
20172
|
-
command: process.execPath,
|
|
20173
|
-
args: [serverFunction],
|
|
20174
|
-
cwd: fork.appRoot,
|
|
20175
|
-
env: { ...context.env, PORT: String(port), NODE_ENV: "production" }
|
|
20176
|
-
}),
|
|
20177
|
-
probes: defaultSmokeProbes(context.facts.matcherRoutes),
|
|
20172
|
+
timeoutMs: 15 * 6e4,
|
|
20178
20173
|
stage: "BUILDING",
|
|
20179
20174
|
errorCode: "BUILD_FAILED"
|
|
20180
20175
|
},
|
|
20181
20176
|
observer
|
|
20182
20177
|
);
|
|
20183
|
-
if (!
|
|
20184
|
-
|
|
20185
|
-
status: "success",
|
|
20186
|
-
artifact: {
|
|
20187
|
-
kind: "opennext-aws",
|
|
20188
|
-
outputRoot: join14(fork.appRoot, ".open-next"),
|
|
20189
|
-
serverFunction
|
|
20190
|
-
},
|
|
20191
|
-
notes: [
|
|
20192
|
-
"Verified with the Node wrapper; an AWS deploy needs a Lambda-wrapper build against provisioned resources."
|
|
20193
|
-
]
|
|
20194
|
-
};
|
|
20195
|
-
}
|
|
20196
|
-
};
|
|
20197
|
-
}
|
|
20198
|
-
|
|
20199
|
-
// ../../packages/build/src/strategy/strategies/opennext-cloudflare.ts
|
|
20200
|
-
import { readFile as readFile12 } from "fs/promises";
|
|
20201
|
-
import { join as join15 } from "path";
|
|
20202
|
-
var PROXY_TO_MIDDLEWARE_VARIANT = "proxy-to-middleware";
|
|
20203
|
-
var NODE_MIDDLEWARE_REFUSAL = /Node\.js middleware is not (?:currently )?supported/i;
|
|
20204
|
-
var NODE_MIDDLEWARE_EXPERIMENTAL = /Node\.js middleware support is experimental/i;
|
|
20205
|
-
var NODE_MIDDLEWARE_NOT_DEPLOYED = 'Node.js-runtime middleware (runtime: "nodejs") is only an experiment in OpenNext Cloudflare, and Naro does not deploy it. Remove runtime: "nodejs" to build it as Edge middleware';
|
|
20206
|
-
async function buildDeclaresNodeMiddleware(appRoot) {
|
|
20207
|
-
try {
|
|
20208
|
-
const manifest2 = JSON.parse(
|
|
20209
|
-
await readFile12(
|
|
20210
|
-
join15(appRoot, ".next", "server", "functions-config-manifest.json"),
|
|
20211
|
-
"utf8"
|
|
20212
|
-
)
|
|
20213
|
-
);
|
|
20214
|
-
return Boolean(manifest2.functions?.["/_middleware"]);
|
|
20215
|
-
} catch {
|
|
20216
|
-
return false;
|
|
20217
|
-
}
|
|
20218
|
-
}
|
|
20219
|
-
function createOpenNextCloudflareStrategy(options) {
|
|
20220
|
-
async function attempt(context, roots, observer, ownBuild, adapterNotice) {
|
|
20221
|
-
let platform;
|
|
20222
|
-
try {
|
|
20223
|
-
platform = await options.createPlatformBuildConfig(
|
|
20224
|
-
roots.appRoot,
|
|
20225
|
-
context.identity.deploymentId
|
|
20226
|
-
);
|
|
20227
|
-
} catch (error51) {
|
|
20228
|
-
return {
|
|
20229
|
-
ok: false,
|
|
20230
|
-
nodeMiddleware: null,
|
|
20231
|
-
outcome: failed("prepare", describeError(error51))
|
|
20232
|
-
};
|
|
20233
|
-
}
|
|
20234
|
-
const nextBuild = await runStep(
|
|
20235
|
-
context,
|
|
20236
|
-
{
|
|
20237
|
-
command: context.packageManager.name,
|
|
20238
|
-
args: ["run", context.buildScript],
|
|
20239
|
-
cwd: roots.appRoot,
|
|
20240
|
-
env: {
|
|
20241
|
-
...context.env,
|
|
20242
|
-
NEXT_PRIVATE_STANDALONE: "true",
|
|
20243
|
-
NPM_CONFIG_USERCONFIG: platform.packageManagerConfigPath
|
|
20244
|
-
},
|
|
20245
|
-
timeoutMs: 15 * 6e4,
|
|
20246
|
-
stage: "BUILDING",
|
|
20247
|
-
errorCode: "BUILD_FAILED"
|
|
20248
|
-
},
|
|
20249
|
-
observer
|
|
20250
|
-
);
|
|
20251
|
-
if (!nextBuild.ok) {
|
|
20252
|
-
return {
|
|
20253
|
-
ok: false,
|
|
20254
|
-
nodeMiddleware: null,
|
|
20255
|
-
outcome: ownBuild ? appBuildFailed(describeFailure(nextBuild)) : failed("build", describeFailure(nextBuild))
|
|
20256
|
-
};
|
|
20257
|
-
}
|
|
20258
|
-
if (!adapterNotice.warned) {
|
|
20259
|
-
const adapter = userAdapterOf(context) ?? await adapterInBuildOutput(roots.appRoot, context.nextVersion);
|
|
20260
|
-
if (adapter) {
|
|
20261
|
-
adapterNotice.warned = true;
|
|
20262
|
-
await warn(observer, openNextAdapterWarning(adapter));
|
|
20263
|
-
}
|
|
20264
|
-
}
|
|
20265
|
-
if (await buildDeclaresNodeMiddleware(roots.appRoot)) {
|
|
20266
|
-
return {
|
|
20267
|
-
ok: false,
|
|
20268
|
-
nodeMiddleware: "experimental",
|
|
20269
|
-
outcome: failed("build", NODE_MIDDLEWARE_NOT_DEPLOYED)
|
|
20270
|
-
};
|
|
20271
|
-
}
|
|
20272
|
-
const openNext = await runStep(
|
|
20273
|
-
context,
|
|
20274
|
-
{
|
|
20275
|
-
command: context.toolchain.openNextCloudflare,
|
|
20276
|
-
args: [
|
|
20277
|
-
"build",
|
|
20278
|
-
"--skip-next-build",
|
|
20279
|
-
"--openNextConfigPath",
|
|
20280
|
-
platform.openNextConfigPath,
|
|
20281
|
-
"--config",
|
|
20282
|
-
platform.wranglerConfigPath,
|
|
20283
|
-
...context.nextSupport.status === "needs-unsupported-flag" ? ["--dangerouslyUseUnsupportedNextVersion"] : []
|
|
20284
|
-
],
|
|
20285
|
-
cwd: roots.appRoot,
|
|
20286
|
-
timeoutMs: 15 * 6e4,
|
|
20287
|
-
stage: "BUILDING",
|
|
20288
|
-
errorCode: "OPENNEXT_FAILED"
|
|
20289
|
-
},
|
|
20290
|
-
observer
|
|
20291
|
-
);
|
|
20292
|
-
if (!openNext.ok) {
|
|
20293
|
-
const refused = openNext.output.some(
|
|
20294
|
-
(line) => NODE_MIDDLEWARE_REFUSAL.test(line)
|
|
20295
|
-
);
|
|
20296
|
-
return {
|
|
20297
|
-
ok: false,
|
|
20298
|
-
nodeMiddleware: refused ? "refused" : null,
|
|
20299
|
-
outcome: failed(
|
|
20300
|
-
"build",
|
|
20301
|
-
refused ? NODE_MIDDLEWARE_NOT_DEPLOYED : describeFailure(openNext)
|
|
20302
|
-
)
|
|
20303
|
-
};
|
|
20304
|
-
}
|
|
20305
|
-
if (openNext.output.some((line) => NODE_MIDDLEWARE_EXPERIMENTAL.test(line))) {
|
|
20306
|
-
return {
|
|
20307
|
-
ok: false,
|
|
20308
|
-
nodeMiddleware: "experimental",
|
|
20309
|
-
outcome: failed("build", NODE_MIDDLEWARE_NOT_DEPLOYED)
|
|
20310
|
-
};
|
|
20311
|
-
}
|
|
20312
|
-
const layout = {
|
|
20313
|
-
appRoot: roots.appRoot,
|
|
20314
|
-
wranglerConfigPath: platform.wranglerConfigPath,
|
|
20315
|
-
...OPEN_NEXT_LAYOUT
|
|
20316
|
-
};
|
|
20317
|
-
const bundle = await bundleWorker(
|
|
20318
|
-
context,
|
|
20319
|
-
layout,
|
|
20320
|
-
observer,
|
|
20321
|
-
"OPENNEXT_FAILED"
|
|
20322
|
-
);
|
|
20323
|
-
if (!bundle.ok) {
|
|
20324
|
-
return {
|
|
20325
|
-
ok: false,
|
|
20326
|
-
nodeMiddleware: null,
|
|
20327
|
-
outcome: failed("bundle", describeFailure(bundle))
|
|
20328
|
-
};
|
|
20329
|
-
}
|
|
20330
|
-
let artifact;
|
|
20331
|
-
try {
|
|
20332
|
-
artifact = await options.readOpenNextArtifact(
|
|
20333
|
-
roots.appRoot,
|
|
20334
|
-
context.identity,
|
|
20335
|
-
platform.wranglerConfigPath
|
|
20336
|
-
);
|
|
20337
|
-
} catch (error51) {
|
|
20338
|
-
return {
|
|
20339
|
-
ok: false,
|
|
20340
|
-
nodeMiddleware: null,
|
|
20341
|
-
outcome: failed("bundle", describeError(error51))
|
|
20342
|
-
};
|
|
20343
|
-
}
|
|
20344
|
-
const smoke = await smokeWorker(context, layout, observer);
|
|
20345
|
-
if (!smoke.ok) {
|
|
20346
|
-
return {
|
|
20347
|
-
ok: false,
|
|
20348
|
-
nodeMiddleware: null,
|
|
20349
|
-
outcome: failed("smoke", smoke.reason)
|
|
20350
|
-
};
|
|
20351
|
-
}
|
|
20352
|
-
return { ok: true, artifact };
|
|
20353
|
-
}
|
|
20354
|
-
return {
|
|
20355
|
-
id: "opennext-cloudflare",
|
|
20356
|
-
priority: 2,
|
|
20357
|
-
target: "cloudflare",
|
|
20358
|
-
supports: () => ({ supported: true }),
|
|
20359
|
-
async evaluate(context, observer) {
|
|
20360
|
-
const adapterNotice = { warned: false };
|
|
20361
|
-
const rememberedRewrite = context.pinnedVariant === PROXY_TO_MIDDLEWARE_VARIANT && context.facts.proxyFile !== null;
|
|
20362
|
-
if (rememberedRewrite) {
|
|
20363
|
-
await info(
|
|
20364
|
-
observer,
|
|
20365
|
-
`P2 opennext-cloudflare: the stored strategy already needed ${context.facts.proxyFile ?? "proxy"} rewritten to Edge middleware; building that way directly.`
|
|
20366
|
-
);
|
|
20367
|
-
} else {
|
|
20368
|
-
await info(
|
|
20369
|
-
observer,
|
|
20370
|
-
"P2 opennext-cloudflare: building the project as written."
|
|
20371
|
-
);
|
|
20372
|
-
const first = await attempt(
|
|
20373
|
-
context,
|
|
20374
|
-
context.workspace,
|
|
20375
|
-
observer,
|
|
20376
|
-
true,
|
|
20377
|
-
adapterNotice
|
|
20378
|
-
);
|
|
20379
|
-
if (first.ok) {
|
|
20178
|
+
if (!build.ok) {
|
|
20179
|
+
if (!await pathExists(join15(fork.appRoot, BUILD_RECORD)))
|
|
20380
20180
|
return {
|
|
20381
|
-
status: "
|
|
20382
|
-
|
|
20383
|
-
|
|
20181
|
+
status: "failed",
|
|
20182
|
+
stage: "build",
|
|
20183
|
+
reason: describeFailure(build),
|
|
20184
|
+
appBuild: true
|
|
20384
20185
|
};
|
|
20385
|
-
|
|
20386
|
-
|
|
20387
|
-
|
|
20388
|
-
|
|
20389
|
-
|
|
20390
|
-
|
|
20186
|
+
return failed("bundle", describeFailure(build));
|
|
20187
|
+
}
|
|
20188
|
+
const record3 = await readRecord(fork.appRoot);
|
|
20189
|
+
if (!record3 || await readBuildId(record3.distDir) !== record3.buildId) {
|
|
20190
|
+
const ran = await adapterInBuildOutput(
|
|
20191
|
+
fork.appRoot,
|
|
20192
|
+
context.nextVersion
|
|
20193
|
+
);
|
|
20194
|
+
return failed(
|
|
20195
|
+
"build",
|
|
20196
|
+
ran?.source === "build-output" && resolve5(fork.appRoot, ran.path) !== resolve5(adapterPath) ? NARO_ADAPTER_REASONS.userAdapterRan(ran.key) : NARO_ADAPTER_REASONS.missingOutput
|
|
20391
20197
|
);
|
|
20392
20198
|
}
|
|
20393
|
-
let
|
|
20199
|
+
let artifact;
|
|
20394
20200
|
try {
|
|
20395
|
-
|
|
20201
|
+
artifact = await options.readArtifact(fork.appRoot, context.identity);
|
|
20396
20202
|
} catch (error51) {
|
|
20397
|
-
return failed("
|
|
20398
|
-
}
|
|
20399
|
-
const conversion = await options.convertProxyToMiddleware(fork.appRoot);
|
|
20400
|
-
if (!conversion.converted) {
|
|
20401
|
-
return failed(
|
|
20402
|
-
"prepare",
|
|
20403
|
-
`Could not rewrite ${context.facts.proxyFile} to middleware (a middleware file already exists).`
|
|
20404
|
-
);
|
|
20203
|
+
return failed("bundle", describeError(error51));
|
|
20405
20204
|
}
|
|
20406
|
-
await
|
|
20407
|
-
observer,
|
|
20408
|
-
`Converted ${conversion.file ?? context.facts.proxyFile} to edge middleware for this build only. Next.js 16 proxy runs on the Node.js runtime, which Cloudflare does not support; middleware runs on the Edge runtime, so Node.js-only APIs are unavailable. Your repository is unchanged.`
|
|
20409
|
-
);
|
|
20410
|
-
const second = await attempt(
|
|
20205
|
+
const smoke = await smokeWorker(
|
|
20411
20206
|
context,
|
|
20412
|
-
|
|
20207
|
+
{
|
|
20208
|
+
appRoot: fork.appRoot,
|
|
20209
|
+
wranglerConfigPath: join15(fork.appRoot, WRANGLER_CONFIG),
|
|
20210
|
+
outputRoot: OUTPUT_DIR
|
|
20211
|
+
},
|
|
20413
20212
|
observer,
|
|
20414
|
-
|
|
20415
|
-
|
|
20213
|
+
naroAdapterSmokeProbes(
|
|
20214
|
+
record3,
|
|
20215
|
+
artifact.assets.map((asset) => asset.name)
|
|
20216
|
+
)
|
|
20416
20217
|
);
|
|
20417
|
-
if (!
|
|
20418
|
-
if (!rememberedRewrite || second.outcome.status !== "failed" || !second.outcome.appBuild)
|
|
20419
|
-
return second.outcome;
|
|
20420
|
-
await info(
|
|
20421
|
-
observer,
|
|
20422
|
-
`P2 opennext-cloudflare: the rewritten copy did not build; building the project as written once to tell the app's own error from the rewrite's.`
|
|
20423
|
-
);
|
|
20424
|
-
const asWritten = await attempt(
|
|
20425
|
-
context,
|
|
20426
|
-
context.workspace,
|
|
20427
|
-
observer,
|
|
20428
|
-
true,
|
|
20429
|
-
adapterNotice
|
|
20430
|
-
);
|
|
20431
|
-
if (asWritten.ok) {
|
|
20432
|
-
await info(
|
|
20433
|
-
observer,
|
|
20434
|
-
"P2 opennext-cloudflare: the project as written builds and ships as it is; the rewrite is no longer needed."
|
|
20435
|
-
);
|
|
20436
|
-
return {
|
|
20437
|
-
status: "success",
|
|
20438
|
-
artifact: {
|
|
20439
|
-
kind: "cloudflare-worker",
|
|
20440
|
-
artifact: asWritten.artifact
|
|
20441
|
-
},
|
|
20442
|
-
notes: []
|
|
20443
|
-
};
|
|
20444
|
-
}
|
|
20445
|
-
if (asWritten.outcome.status === "failed" && asWritten.outcome.appBuild) {
|
|
20446
|
-
await warn(
|
|
20447
|
-
observer,
|
|
20448
|
-
"P2 opennext-cloudflare: the project as written does not build either, so the error is the app's own."
|
|
20449
|
-
);
|
|
20450
|
-
return asWritten.outcome;
|
|
20451
|
-
}
|
|
20452
|
-
await warn(
|
|
20453
|
-
observer,
|
|
20454
|
-
"P2 opennext-cloudflare: the project as written builds, so the rewritten copy's error is the Edge rewrite's (a Node-only API reached from proxy.ts), not the app's code."
|
|
20455
|
-
);
|
|
20456
|
-
return failed("build", second.outcome.reason);
|
|
20457
|
-
}
|
|
20218
|
+
if (!smoke.ok) return failed("smoke", smoke.reason);
|
|
20458
20219
|
return {
|
|
20459
20220
|
status: "success",
|
|
20460
|
-
artifact: { kind: "cloudflare-worker", artifact
|
|
20461
|
-
variant: PROXY_TO_MIDDLEWARE_VARIANT,
|
|
20221
|
+
artifact: { kind: "cloudflare-worker", artifact },
|
|
20462
20222
|
notes: [
|
|
20463
|
-
|
|
20223
|
+
"Built with the Naro adapter (Next.js Adapter API) in a temporary workspace."
|
|
20464
20224
|
]
|
|
20465
20225
|
};
|
|
20466
20226
|
}
|
|
20467
20227
|
};
|
|
20468
20228
|
}
|
|
20469
20229
|
|
|
20470
|
-
// ../../packages/build/src/strategy/strategies/unavailable.ts
|
|
20471
|
-
function createUnavailableStrategy(options) {
|
|
20472
|
-
return {
|
|
20473
|
-
id: options.id,
|
|
20474
|
-
priority: options.priority,
|
|
20475
|
-
target: options.target,
|
|
20476
|
-
supports: () => ({ supported: false, reason: options.reason }),
|
|
20477
|
-
evaluate: async () => ({ status: "skipped", reason: options.reason })
|
|
20478
|
-
};
|
|
20479
|
-
}
|
|
20480
|
-
function createSplitCloudflareStrategy() {
|
|
20481
|
-
return createUnavailableStrategy({
|
|
20482
|
-
id: "split-cloudflare",
|
|
20483
|
-
priority: 3,
|
|
20484
|
-
target: "cloudflare-split",
|
|
20485
|
-
reason: "Split Cloudflare deployment needs the dispatcher to chain a middleware Worker in front of the app Worker; the runtime plane routes one Worker per hostname today."
|
|
20486
|
-
});
|
|
20487
|
-
}
|
|
20488
|
-
function createAwsMiddlewareCloudflareAppStrategy() {
|
|
20489
|
-
return createUnavailableStrategy({
|
|
20490
|
-
id: "aws-middleware-cloudflare-app",
|
|
20491
|
-
priority: 4,
|
|
20492
|
-
target: "aws-hybrid",
|
|
20493
|
-
reason: "Hybrid AWS middleware + Cloudflare app needs an AWS deploy target and cross-cloud request chaining; neither exists on this control plane."
|
|
20494
|
-
});
|
|
20495
|
-
}
|
|
20496
|
-
|
|
20497
20230
|
// ../../packages/build/src/strategy/strategies/vinext-cloudflare.ts
|
|
20498
20231
|
var VINEXT_MIN_NEXT_MAJOR = 16;
|
|
20499
20232
|
var VINEXT_BUILD_SCRIPTS = ["esbuild", "workerd"];
|
|
@@ -20568,6 +20301,7 @@ function createVinextCloudflareStrategy(options) {
|
|
|
20568
20301
|
observer,
|
|
20569
20302
|
"P1 vinext-cloudflare: the project already builds with vinext; using its own configuration."
|
|
20570
20303
|
);
|
|
20304
|
+
await info(observer, ISR_SHARED_CACHE_OFF_NOTE);
|
|
20571
20305
|
}
|
|
20572
20306
|
let fork;
|
|
20573
20307
|
try {
|
|
@@ -20665,13 +20399,13 @@ function createVinextCloudflareStrategy(options) {
|
|
|
20665
20399
|
|
|
20666
20400
|
// ../../packages/build/src/strategy/workspace.ts
|
|
20667
20401
|
import { execFile } from "child_process";
|
|
20668
|
-
import { cp, mkdir as mkdir2, readdir as readdir4, rm as
|
|
20669
|
-
import { basename
|
|
20402
|
+
import { cp, mkdir as mkdir2, readdir as readdir4, rm as rm3 } from "fs/promises";
|
|
20403
|
+
import { basename, dirname as dirname2, join as join16, relative as relative5, resolve as resolve6 } from "path";
|
|
20670
20404
|
import { promisify } from "util";
|
|
20671
20405
|
var execFileAsync = promisify(execFile);
|
|
20672
20406
|
var SKIPPED_ANYWHERE = /* @__PURE__ */ new Set(["node_modules"]);
|
|
20673
20407
|
function shouldCopy(path) {
|
|
20674
|
-
const name =
|
|
20408
|
+
const name = basename(path);
|
|
20675
20409
|
if (SKIPPED_ANYWHERE.has(name)) return false;
|
|
20676
20410
|
return !name.startsWith(".next-deploy-");
|
|
20677
20411
|
}
|
|
@@ -20699,13 +20433,13 @@ async function copyInstalledPackages(source, target2) {
|
|
|
20699
20433
|
await copyTree(install, join16(target2, relative5(origin, install)));
|
|
20700
20434
|
}
|
|
20701
20435
|
async function copyTree(from, to) {
|
|
20702
|
-
await mkdir2(
|
|
20436
|
+
await mkdir2(dirname2(to), { recursive: true });
|
|
20703
20437
|
if (process.platform !== "win32") {
|
|
20704
20438
|
try {
|
|
20705
20439
|
await execFileAsync("cp", ["-a", from, to]);
|
|
20706
20440
|
return;
|
|
20707
20441
|
} catch {
|
|
20708
|
-
await
|
|
20442
|
+
await rm3(to, { recursive: true, force: true });
|
|
20709
20443
|
}
|
|
20710
20444
|
}
|
|
20711
20445
|
await cp(from, to, { recursive: true, verbatimSymlinks: true });
|
|
@@ -20733,27 +20467,26 @@ async function withRouteList(artifact, list, appRoot, observer) {
|
|
|
20733
20467
|
return artifact;
|
|
20734
20468
|
}
|
|
20735
20469
|
}
|
|
20470
|
+
var NEXT_ADAPTER_PATH = nextAdapterPath();
|
|
20736
20471
|
var defaultLocalBuildDependencies = {
|
|
20737
20472
|
createWorkspace: () => mkdtemp(join17(tmpdir(), "next-deploy-build-")),
|
|
20738
|
-
removeWorkspace: (path) =>
|
|
20473
|
+
removeWorkspace: (path) => rm4(path, { recursive: true, force: true }),
|
|
20739
20474
|
runCommand,
|
|
20740
20475
|
detectPackageManager,
|
|
20741
20476
|
resolveAppRoot,
|
|
20742
20477
|
detectFramework,
|
|
20743
20478
|
readStaticArtifact,
|
|
20744
20479
|
createPackageManagerConfig,
|
|
20745
|
-
createPlatformBuildConfig,
|
|
20746
|
-
readOpenNextArtifact,
|
|
20747
|
-
openNextCommand: "opennextjs-cloudflare",
|
|
20748
20480
|
wranglerCommand: "wrangler",
|
|
20749
20481
|
cacheFetch: (input, init) => fetch(input, init),
|
|
20750
|
-
convertProxyToMiddleware,
|
|
20751
20482
|
commandAvailable: hasCommand,
|
|
20752
20483
|
readInstalledNextVersion,
|
|
20753
20484
|
now: () => /* @__PURE__ */ new Date(),
|
|
20754
20485
|
createVinextBuildConfig,
|
|
20755
20486
|
readVinextArtifact,
|
|
20756
20487
|
vinextCommand: "vinext",
|
|
20488
|
+
...NEXT_ADAPTER_PATH ? { nextAdapterPath: NEXT_ADAPTER_PATH } : {},
|
|
20489
|
+
readNaroAdapterArtifact,
|
|
20757
20490
|
forkWorkspace: copyCheckout,
|
|
20758
20491
|
copyInstalledPackages,
|
|
20759
20492
|
collectProjectFacts,
|
|
@@ -20768,7 +20501,7 @@ async function readInstalledNextVersion(appRoot, checkout) {
|
|
|
20768
20501
|
const stop = resolve7(checkout);
|
|
20769
20502
|
for (; ; ) {
|
|
20770
20503
|
try {
|
|
20771
|
-
const source = await
|
|
20504
|
+
const source = await readFile14(
|
|
20772
20505
|
join17(dir, "node_modules", "next", "package.json"),
|
|
20773
20506
|
"utf8"
|
|
20774
20507
|
);
|
|
@@ -20777,7 +20510,7 @@ async function readInstalledNextVersion(appRoot, checkout) {
|
|
|
20777
20510
|
} catch {
|
|
20778
20511
|
}
|
|
20779
20512
|
if (dir === stop) return null;
|
|
20780
|
-
const parent =
|
|
20513
|
+
const parent = dirname3(dir);
|
|
20781
20514
|
if (parent === dir) return null;
|
|
20782
20515
|
dir = parent;
|
|
20783
20516
|
}
|
|
@@ -20800,9 +20533,9 @@ async function hasCommand(command) {
|
|
|
20800
20533
|
return false;
|
|
20801
20534
|
}
|
|
20802
20535
|
}
|
|
20803
|
-
async function
|
|
20536
|
+
async function pathExists2(path) {
|
|
20804
20537
|
try {
|
|
20805
|
-
await
|
|
20538
|
+
await access6(path);
|
|
20806
20539
|
return true;
|
|
20807
20540
|
} catch {
|
|
20808
20541
|
return false;
|
|
@@ -20846,14 +20579,11 @@ function defaultStrategies(dependencies) {
|
|
|
20846
20579
|
createVinextBuildConfig: dependencies.createVinextBuildConfig ?? createVinextBuildConfig,
|
|
20847
20580
|
readVinextArtifact: dependencies.readVinextArtifact ?? readVinextArtifact
|
|
20848
20581
|
}),
|
|
20849
|
-
|
|
20850
|
-
|
|
20851
|
-
convertProxyToMiddleware: dependencies.convertProxyToMiddleware ?? convertProxyToMiddleware,
|
|
20852
|
-
readOpenNextArtifact: dependencies.readOpenNextArtifact
|
|
20582
|
+
createNaroAdapterCloudflareStrategy({
|
|
20583
|
+
readArtifact: dependencies.readNaroAdapterArtifact ?? readNaroAdapterArtifact
|
|
20853
20584
|
}),
|
|
20854
20585
|
createSplitCloudflareStrategy(),
|
|
20855
|
-
createAwsMiddlewareCloudflareAppStrategy()
|
|
20856
|
-
createOpenNextAwsStrategy()
|
|
20586
|
+
createAwsMiddlewareCloudflareAppStrategy()
|
|
20857
20587
|
];
|
|
20858
20588
|
}
|
|
20859
20589
|
var LocalBuildExecutor = class {
|
|
@@ -21132,7 +20862,7 @@ var LocalBuildExecutor = class {
|
|
|
21132
20862
|
"NEXT_VERSION_UNSUPPORTED",
|
|
21133
20863
|
nextSupport.reason
|
|
21134
20864
|
);
|
|
21135
|
-
if (nextSupport.status === "
|
|
20865
|
+
if (nextSupport.status === "past-support-window" || nextSupport.status === "outside-verified-range") {
|
|
21136
20866
|
await observer.onLog({
|
|
21137
20867
|
level: "WARN",
|
|
21138
20868
|
stage: "BUILDING",
|
|
@@ -21187,7 +20917,6 @@ var LocalBuildExecutor = class {
|
|
|
21187
20917
|
};
|
|
21188
20918
|
};
|
|
21189
20919
|
const vinextCommand = this.dependencies.vinextCommand;
|
|
21190
|
-
const openNextAwsCommand = this.dependencies.openNextAwsCommand;
|
|
21191
20920
|
const context = {
|
|
21192
20921
|
identity,
|
|
21193
20922
|
branch: input.branch,
|
|
@@ -21199,15 +20928,14 @@ var LocalBuildExecutor = class {
|
|
|
21199
20928
|
buildScript: resolved.buildScript,
|
|
21200
20929
|
nextVersion: nextVersion ? `${String(nextVersion.major)}.${String(nextVersion.minor)}.${String(nextVersion.patch)}` : "unknown",
|
|
21201
20930
|
nextMajor,
|
|
21202
|
-
nextSupport,
|
|
21203
20931
|
vinextEnabled: input.vinextEnabled !== false,
|
|
20932
|
+
userAdapter: input.userAdapter === "keep" ? "keep" : "replace",
|
|
21204
20933
|
facts,
|
|
21205
20934
|
workspace: { checkout, appRoot, fork: forkWorkspace },
|
|
21206
20935
|
toolchain: {
|
|
21207
|
-
openNextCloudflare: this.dependencies.openNextCommand,
|
|
21208
20936
|
wrangler: this.dependencies.wranglerCommand,
|
|
21209
20937
|
...vinextCommand && await commandAvailable(vinextCommand) ? { vinext: vinextCommand } : {},
|
|
21210
|
-
...
|
|
20938
|
+
...this.dependencies.nextAdapterPath && await pathExists2(this.dependencies.nextAdapterPath) ? { nextAdapter: this.dependencies.nextAdapterPath } : {}
|
|
21211
20939
|
},
|
|
21212
20940
|
targets: this.dependencies.targets ?? { cloudflare: true },
|
|
21213
20941
|
ports: {
|
|
@@ -21262,7 +20990,7 @@ var LocalBuildExecutor = class {
|
|
|
21262
20990
|
if (depsKey && !depsRestored) {
|
|
21263
20991
|
await trySave("deps", depsKey, pmCacheDir, cachePorts, observer);
|
|
21264
20992
|
}
|
|
21265
|
-
if (buildCacheDir && await
|
|
20993
|
+
if (buildCacheDir && await pathExists2(buildCacheDir)) {
|
|
21266
20994
|
await trySave(
|
|
21267
20995
|
"next",
|
|
21268
20996
|
buildCacheKey,
|
|
@@ -21662,8 +21390,8 @@ function sendPage(res, status, html) {
|
|
|
21662
21390
|
async function startCallbackServer() {
|
|
21663
21391
|
let resolveCode;
|
|
21664
21392
|
let rejectCode;
|
|
21665
|
-
const codePromise = new Promise((
|
|
21666
|
-
resolveCode =
|
|
21393
|
+
const codePromise = new Promise((resolve16, reject) => {
|
|
21394
|
+
resolveCode = resolve16;
|
|
21667
21395
|
rejectCode = reject;
|
|
21668
21396
|
});
|
|
21669
21397
|
const server = createServer2((req, res) => {
|
|
@@ -21692,7 +21420,7 @@ async function startCallbackServer() {
|
|
|
21692
21420
|
sendPage(res, 200, successPage());
|
|
21693
21421
|
resolveCode(code);
|
|
21694
21422
|
});
|
|
21695
|
-
await new Promise((
|
|
21423
|
+
await new Promise((resolve16) => server.listen(0, "127.0.0.1", resolve16));
|
|
21696
21424
|
const port = server.address().port;
|
|
21697
21425
|
return {
|
|
21698
21426
|
port,
|
|
@@ -22190,7 +21918,8 @@ function projectInfo(row) {
|
|
|
22190
21918
|
repositoryUrl: row.repository_url,
|
|
22191
21919
|
repositoryFullName: row.repository_full_name ?? null,
|
|
22192
21920
|
createdAt: row.created_at,
|
|
22193
|
-
updatedAt: row.updated_at
|
|
21921
|
+
updatedAt: row.updated_at,
|
|
21922
|
+
userAdapter: row.user_adapter ?? null
|
|
22194
21923
|
};
|
|
22195
21924
|
}
|
|
22196
21925
|
function deploymentInfo(row) {
|
|
@@ -22361,6 +22090,19 @@ var TeamsApi = class {
|
|
|
22361
22090
|
{ context: "Read team usage" }
|
|
22362
22091
|
);
|
|
22363
22092
|
}
|
|
22093
|
+
/**
|
|
22094
|
+
* The team's hosting compute (CPU) per project and environment for a UTC
|
|
22095
|
+
* month (spec 2026-11-06-hosting-cpu-usage §7). Observed, never billed.
|
|
22096
|
+
*/
|
|
22097
|
+
async usageHosting(teamSlug, query = {}) {
|
|
22098
|
+
const params = new URLSearchParams();
|
|
22099
|
+
if (query.month !== void 0) params.set("month", query.month);
|
|
22100
|
+
const text3 = params.toString();
|
|
22101
|
+
return this.client.request(
|
|
22102
|
+
`/api/teams/${encodeURIComponent(teamSlug)}/usage/hosting${text3 ? `?${text3}` : ""}`,
|
|
22103
|
+
{ context: "Read team hosting usage" }
|
|
22104
|
+
);
|
|
22105
|
+
}
|
|
22364
22106
|
path(teamSlug, suffix = "") {
|
|
22365
22107
|
return `/api/teams/${encodeURIComponent(teamSlug)}${suffix}`;
|
|
22366
22108
|
}
|
|
@@ -22736,7 +22478,7 @@ var DeploymentsApi = class {
|
|
|
22736
22478
|
async wait(deploymentId, options = {}) {
|
|
22737
22479
|
const intervalMs = options.intervalMs ?? 2500;
|
|
22738
22480
|
const timeoutMs = options.timeoutMs ?? 15 * 6e4;
|
|
22739
|
-
const sleep2 = options.sleep ?? ((ms) => new Promise((
|
|
22481
|
+
const sleep2 = options.sleep ?? ((ms) => new Promise((resolve16) => setTimeout(resolve16, ms)));
|
|
22740
22482
|
const startedAt = Date.now();
|
|
22741
22483
|
let lastStatus = null;
|
|
22742
22484
|
let lastSequence = -1;
|
|
@@ -23337,7 +23079,7 @@ var DbApi = class {
|
|
|
23337
23079
|
*/
|
|
23338
23080
|
async export(projectId, options = {}, wait = {}) {
|
|
23339
23081
|
const timeoutMs = wait.timeoutMs ?? EXPORT_TIMEOUT_MS;
|
|
23340
|
-
const sleep2 = wait.sleep ?? ((ms) => new Promise((
|
|
23082
|
+
const sleep2 = wait.sleep ?? ((ms) => new Promise((resolve16) => setTimeout(resolve16, ms)));
|
|
23341
23083
|
const given = wait.pollIntervalMs;
|
|
23342
23084
|
const firstPollMs = given !== void 0 && Number.isFinite(given) && given > 0 ? given : EXPORT_FIRST_POLL_MS;
|
|
23343
23085
|
const maxPollMs = Math.max(EXPORT_MAX_POLL_MS, firstPollMs);
|
|
@@ -26800,8 +26542,8 @@ function readAuth(state, start, allowBareJwt) {
|
|
|
26800
26542
|
stream.expectOperator("(");
|
|
26801
26543
|
stream.expectOperator(")");
|
|
26802
26544
|
if (fn !== "jwt") return { kind: "auth", fn };
|
|
26803
|
-
const
|
|
26804
|
-
if (
|
|
26545
|
+
const access7 = readJwtAccess(stream);
|
|
26546
|
+
if (access7) return access7;
|
|
26805
26547
|
if (allowBareJwt) return "jwt";
|
|
26806
26548
|
throw new PolicySyntaxError(
|
|
26807
26549
|
"auth.jwt() is read one claim at a time: auth.jwt() ->> 'email'",
|
|
@@ -26869,13 +26611,13 @@ function readPrimary(state) {
|
|
|
26869
26611
|
const inner2 = readAuth(state, auth, true);
|
|
26870
26612
|
stream.expectOperator(")");
|
|
26871
26613
|
if (inner2 !== "jwt") return inner2;
|
|
26872
|
-
const
|
|
26873
|
-
if (!
|
|
26614
|
+
const access7 = readJwtAccess(stream);
|
|
26615
|
+
if (!access7)
|
|
26874
26616
|
throw new PolicySyntaxError(
|
|
26875
26617
|
"auth.jwt() is read one claim at a time: (select auth.jwt()) ->> 'email'",
|
|
26876
26618
|
auth.position
|
|
26877
26619
|
);
|
|
26878
|
-
return
|
|
26620
|
+
return access7;
|
|
26879
26621
|
}
|
|
26880
26622
|
const inner = readOr(state);
|
|
26881
26623
|
stream.expectOperator(")");
|
|
@@ -34641,10 +34383,10 @@ var SUPPORTED_REMOTE = [
|
|
|
34641
34383
|
/^ssh:\/\/[^\s]+$/,
|
|
34642
34384
|
/^git@[A-Za-z0-9.-]+:[A-Za-z0-9._/-]+(\.git)?$/
|
|
34643
34385
|
];
|
|
34644
|
-
var defaultExec = (args, cwd) => new Promise((
|
|
34386
|
+
var defaultExec = (args, cwd) => new Promise((resolve16, reject) => {
|
|
34645
34387
|
execFile2("git", args, { cwd }, (error51, stdout) => {
|
|
34646
34388
|
if (error51) reject(error51);
|
|
34647
|
-
else
|
|
34389
|
+
else resolve16(stdout);
|
|
34648
34390
|
});
|
|
34649
34391
|
});
|
|
34650
34392
|
async function tryExec(exec, args, cwd) {
|
|
@@ -34793,15 +34535,52 @@ async function uploadArtifact(artifact, opts) {
|
|
|
34793
34535
|
};
|
|
34794
34536
|
}
|
|
34795
34537
|
|
|
34538
|
+
// src/user-adapter.ts
|
|
34539
|
+
import { resolve as resolve10 } from "path";
|
|
34540
|
+
async function detectUserAdapter(directory, rootDirectory) {
|
|
34541
|
+
return findAdapterConfig(
|
|
34542
|
+
rootDirectory ? resolve10(directory, rootDirectory) : directory
|
|
34543
|
+
);
|
|
34544
|
+
}
|
|
34545
|
+
function parseUserAdapter(value) {
|
|
34546
|
+
return value === "replace" || value === "keep" ? value : null;
|
|
34547
|
+
}
|
|
34548
|
+
var USER_ADAPTER_OPTIONS = [
|
|
34549
|
+
{
|
|
34550
|
+
value: "replace",
|
|
34551
|
+
label: "Replace it with the Naro adapter on Naro's builders (recommended) \u2014 your repository stays as it is"
|
|
34552
|
+
},
|
|
34553
|
+
{ value: "keep", label: "Keep my adapter \u2014 Naro builds with vinext only" }
|
|
34554
|
+
];
|
|
34555
|
+
function userAdapterQuestion(adapter) {
|
|
34556
|
+
return `${adapter.file} sets its own Next.js adapter (${adapter.key}). How should Naro build this project?`;
|
|
34557
|
+
}
|
|
34558
|
+
function userAdapterOutcome(choice) {
|
|
34559
|
+
return choice === "replace" ? "\u25B8 This local build uses vinext only; if vinext cannot build the app, build it on Naro with the Naro adapter: naro deployments create (needs a connected repository)." : "\u25B8 Naro keeps your adapter: builds use vinext only.";
|
|
34560
|
+
}
|
|
34561
|
+
function userAdapterStored(adapter, choice) {
|
|
34562
|
+
return choice === "replace" ? `\u25B8 ${adapter.file} sets its own Next.js adapter; this project replaces it with the Naro adapter on Naro's builders.` : `\u25B8 ${adapter.file} sets its own Next.js adapter; this project keeps it and builds with vinext only.`;
|
|
34563
|
+
}
|
|
34564
|
+
function userAdapterUnasked(adapter) {
|
|
34565
|
+
return `\u26A0 ${adapter.file} sets its own Next.js adapter (${adapter.key}). Naro's builders replace it with the Naro adapter unless you choose otherwise: naro deploy --user-adapter keep, or naro project set --user-adapter keep.`;
|
|
34566
|
+
}
|
|
34567
|
+
var CHOOSE_USER_ADAPTER = {
|
|
34568
|
+
cli: "naro project set --user-adapter replace|keep",
|
|
34569
|
+
mcp: "update_project with userAdapter replace|keep"
|
|
34570
|
+
};
|
|
34571
|
+
function userAdapterUnreadable(adapter, surface = "cli") {
|
|
34572
|
+
return `\u26A0 ${adapter.file} sets its own Next.js adapter (${adapter.key}), but the project's adapter setting could not be read, so nothing was asked. Choose with ${CHOOSE_USER_ADAPTER[surface]}.`;
|
|
34573
|
+
}
|
|
34574
|
+
|
|
34796
34575
|
// src/version.ts
|
|
34797
34576
|
import { readFileSync as readFileSync6 } from "fs";
|
|
34798
|
-
import { dirname as
|
|
34799
|
-
import { fileURLToPath } from "url";
|
|
34577
|
+
import { dirname as dirname4, join as join24 } from "path";
|
|
34578
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
34800
34579
|
function version2() {
|
|
34801
34580
|
try {
|
|
34802
34581
|
const pkg = JSON.parse(
|
|
34803
34582
|
readFileSync6(
|
|
34804
|
-
join24(
|
|
34583
|
+
join24(dirname4(fileURLToPath2(import.meta.url)), "..", "package.json"),
|
|
34805
34584
|
"utf8"
|
|
34806
34585
|
)
|
|
34807
34586
|
);
|
|
@@ -34817,22 +34596,22 @@ import {
|
|
|
34817
34596
|
cp as cp2,
|
|
34818
34597
|
lstat,
|
|
34819
34598
|
mkdir as mkdir3,
|
|
34820
|
-
readFile as
|
|
34599
|
+
readFile as readFile15,
|
|
34821
34600
|
readlink,
|
|
34822
34601
|
realpath as realpath3,
|
|
34823
|
-
rm as
|
|
34602
|
+
rm as rm5,
|
|
34824
34603
|
stat as stat3,
|
|
34825
34604
|
symlink,
|
|
34826
34605
|
unlink,
|
|
34827
|
-
writeFile as
|
|
34606
|
+
writeFile as writeFile6
|
|
34828
34607
|
} from "fs/promises";
|
|
34829
34608
|
import {
|
|
34830
|
-
basename as
|
|
34831
|
-
dirname as
|
|
34609
|
+
basename as basename2,
|
|
34610
|
+
dirname as dirname5,
|
|
34832
34611
|
isAbsolute as isAbsolute4,
|
|
34833
34612
|
join as join25,
|
|
34834
34613
|
relative as relative6,
|
|
34835
|
-
resolve as
|
|
34614
|
+
resolve as resolve11,
|
|
34836
34615
|
sep as sep5
|
|
34837
34616
|
} from "path";
|
|
34838
34617
|
var COPY_SKIP = /(^|[\\/])(node_modules|\.next|\.open-next|\.git|\.wrangler|\.turbo|\.naro)([\\/]|$)/;
|
|
@@ -34862,7 +34641,7 @@ async function committedEnvFiles(sourceDir) {
|
|
|
34862
34641
|
if (tab < 0) return [];
|
|
34863
34642
|
const [mode] = entry.slice(0, tab).split(" ");
|
|
34864
34643
|
const path = entry.slice(tab + 1);
|
|
34865
|
-
if (!ENV_FILE.test(
|
|
34644
|
+
if (!ENV_FILE.test(basename2(path)) || COPY_SKIP.test(path)) return [];
|
|
34866
34645
|
if (mode === "100644" || mode === "100755")
|
|
34867
34646
|
return [{ path, symlink: false }];
|
|
34868
34647
|
if (mode === "120000") return [{ path, symlink: true }];
|
|
@@ -34894,14 +34673,14 @@ async function keptOnly(items, keep, remove) {
|
|
|
34894
34673
|
async function readLocal(path) {
|
|
34895
34674
|
const found = await stat3(path).catch(() => null);
|
|
34896
34675
|
if (!found?.isFile()) return null;
|
|
34897
|
-
return
|
|
34676
|
+
return readFile15(path).catch(() => null);
|
|
34898
34677
|
}
|
|
34899
34678
|
async function realAncestor(dir) {
|
|
34900
|
-
for (let current = dir; ; current =
|
|
34679
|
+
for (let current = dir; ; current = dirname5(current)) {
|
|
34901
34680
|
try {
|
|
34902
34681
|
return await realpath3(current);
|
|
34903
34682
|
} catch {
|
|
34904
|
-
if (
|
|
34683
|
+
if (dirname5(current) === current)
|
|
34905
34684
|
throw new Error(`No ancestor of ${dir}`);
|
|
34906
34685
|
}
|
|
34907
34686
|
}
|
|
@@ -34920,7 +34699,7 @@ async function copyWorkingTree(source, checkout) {
|
|
|
34920
34699
|
recursive: true,
|
|
34921
34700
|
// Relative symlinks must stay relative: resolved, they would point
|
|
34922
34701
|
// back into the developer's real tree, and a strategy's temporary
|
|
34923
|
-
// rewrite (
|
|
34702
|
+
// rewrite (the vinext toolchain install) would land there.
|
|
34924
34703
|
verbatimSymlinks: true,
|
|
34925
34704
|
filter: async (src) => {
|
|
34926
34705
|
if (COPY_SKIP.test(src)) return false;
|
|
@@ -34928,7 +34707,7 @@ async function copyWorkingTree(source, checkout) {
|
|
|
34928
34707
|
const entry = await lstat(src);
|
|
34929
34708
|
if (entry.isFIFO() || entry.isSocket() || entry.isCharacterDevice() || entry.isBlockDevice())
|
|
34930
34709
|
return false;
|
|
34931
|
-
if (ENV_FILE.test(
|
|
34710
|
+
if (ENV_FILE.test(basename2(src)) && !entry.isDirectory()) {
|
|
34932
34711
|
inWorkingTree.push(relative6(sourceDir, src).split(sep5).join("/"));
|
|
34933
34712
|
return false;
|
|
34934
34713
|
}
|
|
@@ -34939,7 +34718,7 @@ async function copyWorkingTree(source, checkout) {
|
|
|
34939
34718
|
absoluteLinks.push(path);
|
|
34940
34719
|
return false;
|
|
34941
34720
|
}
|
|
34942
|
-
if (!inside(
|
|
34721
|
+
if (!inside(resolve11(dirname5(src), target2), sourceDir)) {
|
|
34943
34722
|
linksOutside.push(path);
|
|
34944
34723
|
return false;
|
|
34945
34724
|
}
|
|
@@ -34977,21 +34756,21 @@ async function copyWorkingTree(source, checkout) {
|
|
|
34977
34756
|
continue;
|
|
34978
34757
|
}
|
|
34979
34758
|
const target2 = join25(checkout, path);
|
|
34980
|
-
if (!inside(await realAncestor(
|
|
34759
|
+
if (!inside(await realAncestor(dirname5(target2)), root)) {
|
|
34981
34760
|
outsideProject.push(path);
|
|
34982
34761
|
continue;
|
|
34983
34762
|
}
|
|
34984
34763
|
try {
|
|
34985
|
-
await mkdir3(
|
|
34764
|
+
await mkdir3(dirname5(target2), { recursive: true });
|
|
34986
34765
|
} catch {
|
|
34987
34766
|
outsideProject.push(path);
|
|
34988
34767
|
continue;
|
|
34989
34768
|
}
|
|
34990
|
-
await
|
|
34769
|
+
await rm5(target2, { recursive: true, force: true });
|
|
34991
34770
|
const content = await git(sourceDir, ["show", `HEAD:./${path}`]);
|
|
34992
34771
|
if (isLink) {
|
|
34993
34772
|
const linkTarget = content.toString("utf8");
|
|
34994
|
-
const pointsAt =
|
|
34773
|
+
const pointsAt = resolve11(dirname5(target2), linkTarget);
|
|
34995
34774
|
if (isAbsolute4(linkTarget) || !inside(pointsAt, checkout)) {
|
|
34996
34775
|
outsideProject.push(path);
|
|
34997
34776
|
continue;
|
|
@@ -35000,7 +34779,7 @@ async function copyWorkingTree(source, checkout) {
|
|
|
35000
34779
|
envLinks.push(path);
|
|
35001
34780
|
continue;
|
|
35002
34781
|
}
|
|
35003
|
-
await
|
|
34782
|
+
await writeFile6(target2, content, { flag: "wx" });
|
|
35004
34783
|
const local = await readLocal(join25(sourceDir, path));
|
|
35005
34784
|
if (!local || !sameText(local, content)) committedVersion.push(path);
|
|
35006
34785
|
}
|
|
@@ -35095,7 +34874,7 @@ var TtyPrompter = class {
|
|
|
35095
34874
|
});
|
|
35096
34875
|
try {
|
|
35097
34876
|
return await new Promise(
|
|
35098
|
-
(
|
|
34877
|
+
(resolve16) => rl.question(question, resolve16)
|
|
35099
34878
|
);
|
|
35100
34879
|
} finally {
|
|
35101
34880
|
rl.close();
|
|
@@ -35116,7 +34895,7 @@ var TtyPrompter = class {
|
|
|
35116
34895
|
});
|
|
35117
34896
|
try {
|
|
35118
34897
|
const answer = new Promise(
|
|
35119
|
-
(
|
|
34898
|
+
(resolve16) => rl.question(question, resolve16)
|
|
35120
34899
|
);
|
|
35121
34900
|
muted = true;
|
|
35122
34901
|
const value = await answer;
|
|
@@ -35452,7 +35231,7 @@ async function runDbLint(context) {
|
|
|
35452
35231
|
}
|
|
35453
35232
|
|
|
35454
35233
|
// src/functions/deploy.ts
|
|
35455
|
-
import { relative as relative11, resolve as
|
|
35234
|
+
import { relative as relative11, resolve as resolve14, sep as sep10 } from "path";
|
|
35456
35235
|
|
|
35457
35236
|
// ../../packages/functions-bundler/src/errors.ts
|
|
35458
35237
|
var FunctionBundleError = class extends Error {
|
|
@@ -35509,7 +35288,7 @@ var BUNDLE_MESSAGES = {
|
|
|
35509
35288
|
|
|
35510
35289
|
// ../../packages/functions-bundler/src/discover.ts
|
|
35511
35290
|
import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync8, statSync as statSync2 } from "fs";
|
|
35512
|
-
import { join as join27, relative as relative8, resolve as
|
|
35291
|
+
import { join as join27, relative as relative8, resolve as resolve12, sep as sep6 } from "path";
|
|
35513
35292
|
|
|
35514
35293
|
// ../../packages/functions-bundler/src/limits.ts
|
|
35515
35294
|
var FUNCTION_BUNDLE_MAX_BYTES = 67108864;
|
|
@@ -35531,9 +35310,9 @@ function isEntrypoint(value) {
|
|
|
35531
35310
|
);
|
|
35532
35311
|
}
|
|
35533
35312
|
function functionsFolder(options) {
|
|
35534
|
-
const root =
|
|
35313
|
+
const root = resolve12(options.cwd, options.root ?? ".");
|
|
35535
35314
|
const explicit = options.dir !== void 0;
|
|
35536
|
-
const dir = explicit ?
|
|
35315
|
+
const dir = explicit ? resolve12(options.cwd, options.dir) : join27(root, "naro", "functions");
|
|
35537
35316
|
const label2 = relative8(options.cwd, dir).split(sep6).join("/") || ".";
|
|
35538
35317
|
return { dir, label: label2, root, explicit };
|
|
35539
35318
|
}
|
|
@@ -35652,7 +35431,7 @@ function closesNext(text3, from) {
|
|
|
35652
35431
|
while (i < text3.length && /\s/.test(text3[i] ?? "")) i += 1;
|
|
35653
35432
|
return text3[i] === "}" || text3[i] === "]";
|
|
35654
35433
|
}
|
|
35655
|
-
function
|
|
35434
|
+
function parseJsonc(text3) {
|
|
35656
35435
|
const uncommented = stripComments2(text3);
|
|
35657
35436
|
let out = "";
|
|
35658
35437
|
let inString = false;
|
|
@@ -35713,11 +35492,11 @@ function stripComments2(text3) {
|
|
|
35713
35492
|
}
|
|
35714
35493
|
|
|
35715
35494
|
// ../../packages/functions-bundler/src/node-compat.ts
|
|
35716
|
-
import { createRequire
|
|
35717
|
-
import { dirname as
|
|
35718
|
-
import { fileURLToPath as
|
|
35719
|
-
var require2 =
|
|
35720
|
-
var MODULE_DIR =
|
|
35495
|
+
import { createRequire } from "module";
|
|
35496
|
+
import { dirname as dirname6, resolve as resolvePath } from "path";
|
|
35497
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
35498
|
+
var require2 = createRequire(import.meta.url);
|
|
35499
|
+
var MODULE_DIR = dirname6(fileURLToPath3(import.meta.url));
|
|
35721
35500
|
var REQUIRED_NODE_BUILT_IN_NAMESPACE = "node-built-in-modules";
|
|
35722
35501
|
var REQUIRED_UNENV_ALIAS_NAMESPACE = "required-unenv-alias";
|
|
35723
35502
|
var SKIPPED_ALIASES = /* @__PURE__ */ new Set(["debug"]);
|
|
@@ -35847,12 +35626,12 @@ ${injects.map(
|
|
|
35847
35626
|
|
|
35848
35627
|
// ../../packages/functions-bundler/src/deno-imports.ts
|
|
35849
35628
|
import { existsSync as existsSync9, readFileSync as readFileSync10, realpathSync as realpathSync2 } from "fs";
|
|
35850
|
-
import { dirname as
|
|
35629
|
+
import { dirname as dirname8, isAbsolute as isAbsolute5, join as join29, relative as relative9, sep as sep8 } from "path";
|
|
35851
35630
|
|
|
35852
35631
|
// ../../packages/functions-bundler/src/import-map.ts
|
|
35853
35632
|
import { existsSync as existsSync8, readFileSync as readFileSync9, realpathSync } from "fs";
|
|
35854
|
-
import { basename as
|
|
35855
|
-
import { fileURLToPath as
|
|
35633
|
+
import { basename as basename3, dirname as dirname7, join as join28, resolve as resolve13, sep as sep7 } from "path";
|
|
35634
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
35856
35635
|
|
|
35857
35636
|
// ../../packages/functions-bundler/src/printable.ts
|
|
35858
35637
|
var UNPRINTABLE2 = /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/gu;
|
|
@@ -35885,7 +35664,7 @@ function expandBareKeys(imports) {
|
|
|
35885
35664
|
function load(file2, label2) {
|
|
35886
35665
|
let parsed;
|
|
35887
35666
|
try {
|
|
35888
|
-
parsed =
|
|
35667
|
+
parsed = parseJsonc(readFileSync9(file2, "utf8"));
|
|
35889
35668
|
} catch {
|
|
35890
35669
|
throw new FunctionBundleError(
|
|
35891
35670
|
"VALIDATION_FAILED",
|
|
@@ -35908,8 +35687,8 @@ function load(file2, label2) {
|
|
|
35908
35687
|
printable2(BUNDLE_MESSAGES.importMapPrefix(label2, key, value))
|
|
35909
35688
|
);
|
|
35910
35689
|
return {
|
|
35911
|
-
imports: DENO_CONFIGS.has(
|
|
35912
|
-
base:
|
|
35690
|
+
imports: DENO_CONFIGS.has(basename3(file2)) ? expandBareKeys(written) : written,
|
|
35691
|
+
base: dirname7(file2),
|
|
35913
35692
|
label: label2
|
|
35914
35693
|
};
|
|
35915
35694
|
}
|
|
@@ -35942,7 +35721,7 @@ var isPathLike = (text3) => text3.startsWith("./") || text3.startsWith("../") ||
|
|
|
35942
35721
|
function filePath(text3) {
|
|
35943
35722
|
if (!text3.startsWith("file:")) return null;
|
|
35944
35723
|
try {
|
|
35945
|
-
return
|
|
35724
|
+
return fileURLToPath4(text3);
|
|
35946
35725
|
} catch {
|
|
35947
35726
|
return null;
|
|
35948
35727
|
}
|
|
@@ -35960,7 +35739,7 @@ function keysOf(map2) {
|
|
|
35960
35739
|
for (const [key, target2] of Object.entries(map2.imports)) {
|
|
35961
35740
|
const trailing = key.endsWith("/");
|
|
35962
35741
|
const file2 = filePath(key);
|
|
35963
|
-
const name = file2 !== null ? realKey(file2, trailing) : isPathLike(key) ? realKey(
|
|
35742
|
+
const name = file2 !== null ? realKey(file2, trailing) : isPathLike(key) ? realKey(resolve13(base2, key), trailing) : key;
|
|
35964
35743
|
if (!keys.has(name)) keys.set(name, target2);
|
|
35965
35744
|
}
|
|
35966
35745
|
normalized.set(map2, keys);
|
|
@@ -35972,10 +35751,10 @@ function mapSpecifier(map2, specifier, importerDir) {
|
|
|
35972
35751
|
const file2 = filePath(specifier);
|
|
35973
35752
|
if (file2 !== null) lookup = realKey(file2, trailing);
|
|
35974
35753
|
else if (specifier.startsWith("/"))
|
|
35975
|
-
lookup = realKey(
|
|
35754
|
+
lookup = realKey(resolve13(specifier), trailing);
|
|
35976
35755
|
else if (isPathLike(specifier)) {
|
|
35977
35756
|
if (importerDir === void 0) return null;
|
|
35978
|
-
lookup = realKey(
|
|
35757
|
+
lookup = realKey(resolve13(importerDir, specifier), trailing);
|
|
35979
35758
|
}
|
|
35980
35759
|
const keys = keysOf(map2);
|
|
35981
35760
|
let target2 = keys.get(lookup);
|
|
@@ -35988,7 +35767,7 @@ function mapSpecifier(map2, specifier, importerDir) {
|
|
|
35988
35767
|
target2 = `${keys.get(prefix) ?? ""}${lookup.slice(prefix.length)}`;
|
|
35989
35768
|
}
|
|
35990
35769
|
if (target2.startsWith("./") || target2.startsWith("../"))
|
|
35991
|
-
return
|
|
35770
|
+
return resolve13(map2.base, target2);
|
|
35992
35771
|
return filePath(target2) ?? target2;
|
|
35993
35772
|
}
|
|
35994
35773
|
|
|
@@ -36068,7 +35847,7 @@ function packageDir(from, projectRoot) {
|
|
|
36068
35847
|
const inNodeModules = fromRoot(projectRoot, current).split("/").includes("node_modules");
|
|
36069
35848
|
if (!inNodeModules && existsSync9(join29(current, "package.json")))
|
|
36070
35849
|
return fromRoot(projectRoot, current) || ".";
|
|
36071
|
-
const up =
|
|
35850
|
+
const up = dirname8(current);
|
|
36072
35851
|
if (up === current) break;
|
|
36073
35852
|
current = up;
|
|
36074
35853
|
}
|
|
@@ -36079,14 +35858,14 @@ function isInstalled(from, pkg) {
|
|
|
36079
35858
|
let current = from;
|
|
36080
35859
|
for (; ; ) {
|
|
36081
35860
|
if (existsSync9(join29(current, "node_modules", pkg))) return true;
|
|
36082
|
-
const up =
|
|
35861
|
+
const up = dirname8(current);
|
|
36083
35862
|
if (up === current) return false;
|
|
36084
35863
|
current = up;
|
|
36085
35864
|
}
|
|
36086
35865
|
}
|
|
36087
35866
|
var NODE_MODULES = /[\\/]node_modules[\\/]/;
|
|
36088
35867
|
function installedVersion(resolved, pkg) {
|
|
36089
|
-
let current =
|
|
35868
|
+
let current = dirname8(resolved);
|
|
36090
35869
|
for (; ; ) {
|
|
36091
35870
|
const file2 = join29(current, "package.json");
|
|
36092
35871
|
if (existsSync9(file2)) {
|
|
@@ -36097,7 +35876,7 @@ function installedVersion(resolved, pkg) {
|
|
|
36097
35876
|
} catch {
|
|
36098
35877
|
}
|
|
36099
35878
|
}
|
|
36100
|
-
const up =
|
|
35879
|
+
const up = dirname8(current);
|
|
36101
35880
|
if (up === current) return null;
|
|
36102
35881
|
current = up;
|
|
36103
35882
|
}
|
|
@@ -36527,7 +36306,7 @@ var FUNCTION_BUSY_WAIT_MS = 5e3;
|
|
|
36527
36306
|
var FUNCTION_RATE_LIMIT_DEFAULT_SECONDS = 60;
|
|
36528
36307
|
var FUNCTION_RATE_LIMIT_MAX_SECONDS = 300;
|
|
36529
36308
|
function defaultSleep(ms) {
|
|
36530
|
-
return new Promise((
|
|
36309
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
36531
36310
|
}
|
|
36532
36311
|
function retryAfterSeconds(error51) {
|
|
36533
36312
|
const value = error51.details?.retryAfter;
|
|
@@ -36724,7 +36503,7 @@ async function deployOne(options, folder, name, importMap, secretNames, io, budg
|
|
|
36724
36503
|
}
|
|
36725
36504
|
function readFlagImportMap(options, folder) {
|
|
36726
36505
|
if (options.importMap === void 0) return void 0;
|
|
36727
|
-
const file2 =
|
|
36506
|
+
const file2 = resolve14(options.cwd, options.importMap);
|
|
36728
36507
|
try {
|
|
36729
36508
|
return readImportMapFile(
|
|
36730
36509
|
file2,
|
|
@@ -36842,7 +36621,7 @@ function eventsObserver(cp3, deploymentId, token, fetchImpl = fetch, logIngestUr
|
|
|
36842
36621
|
} catch (error51) {
|
|
36843
36622
|
lastError = error51;
|
|
36844
36623
|
await new Promise(
|
|
36845
|
-
(
|
|
36624
|
+
(resolve16) => setTimeout(resolve16, 500 * (attempt + 1))
|
|
36846
36625
|
);
|
|
36847
36626
|
}
|
|
36848
36627
|
}
|
|
@@ -36918,19 +36697,19 @@ function slugify2(value) {
|
|
|
36918
36697
|
async function projectName(sourceDir) {
|
|
36919
36698
|
try {
|
|
36920
36699
|
const pkg = JSON.parse(
|
|
36921
|
-
await
|
|
36700
|
+
await readFile16(join31(sourceDir, "package.json"), "utf8")
|
|
36922
36701
|
);
|
|
36923
36702
|
if (pkg.name) return pkg.name;
|
|
36924
36703
|
} catch {
|
|
36925
36704
|
}
|
|
36926
|
-
return
|
|
36705
|
+
return basename4(sourceDir);
|
|
36927
36706
|
}
|
|
36928
36707
|
function resolveBin(name) {
|
|
36929
|
-
let dir =
|
|
36708
|
+
let dir = dirname9(fileURLToPath5(import.meta.url));
|
|
36930
36709
|
for (; ; ) {
|
|
36931
36710
|
const candidate = join31(dir, "node_modules", ".bin", name);
|
|
36932
36711
|
if (existsSync10(candidate)) return candidate;
|
|
36933
|
-
const parent =
|
|
36712
|
+
const parent = dirname9(dir);
|
|
36934
36713
|
if (parent === dir) return name;
|
|
36935
36714
|
dir = parent;
|
|
36936
36715
|
}
|
|
@@ -36996,7 +36775,7 @@ function workingTreeNotices(copy) {
|
|
|
36996
36775
|
function localDependencies(sourceDir, say = () => void 0) {
|
|
36997
36776
|
return {
|
|
36998
36777
|
createWorkspace: () => mkdtemp2(join31(tmpdir2(), "naro-build-")),
|
|
36999
|
-
removeWorkspace: (path) =>
|
|
36778
|
+
removeWorkspace: (path) => rm6(path, { recursive: true, force: true }),
|
|
37000
36779
|
async runCommand(spec, observer) {
|
|
37001
36780
|
if (spec.command === "git" && spec.args[0] === "clone") {
|
|
37002
36781
|
const checkout = spec.args.at(-1);
|
|
@@ -37021,9 +36800,6 @@ function localDependencies(sourceDir, say = () => void 0) {
|
|
|
37021
36800
|
detectFramework,
|
|
37022
36801
|
readStaticArtifact,
|
|
37023
36802
|
createPackageManagerConfig,
|
|
37024
|
-
createPlatformBuildConfig,
|
|
37025
|
-
readOpenNextArtifact,
|
|
37026
|
-
openNextCommand: resolveBin("opennextjs-cloudflare"),
|
|
37027
36803
|
wranglerCommand: resolveBin("wrangler"),
|
|
37028
36804
|
// `vinext check` runs on the bare checkout, before the toolchain is added
|
|
37029
36805
|
// to the user's tree, so this binary has to come from the CLI's own deps.
|
|
@@ -37045,7 +36821,7 @@ async function deployDirectory(sourceDir, options, log2) {
|
|
|
37045
36821
|
"Pass production: true for production; preview is the default."
|
|
37046
36822
|
);
|
|
37047
36823
|
const surface = production ? "production" : environment ?? "preview";
|
|
37048
|
-
const appRoot = options.rootDirectory ?
|
|
36824
|
+
const appRoot = options.rootDirectory ? resolve15(sourceDir, options.rootDirectory) : sourceDir;
|
|
37049
36825
|
const framework = detectFramework2(appRoot);
|
|
37050
36826
|
if (!framework.deployable && !options.force) {
|
|
37051
36827
|
throw new NaroError(
|
|
@@ -37133,6 +36909,19 @@ async function deployDirectory(sourceDir, options, log2) {
|
|
|
37133
36909
|
});
|
|
37134
36910
|
if (ctx.envSkipped?.length)
|
|
37135
36911
|
log2(`\u26A0 skipped env: ${ctx.envSkipped.join(", ")}`);
|
|
36912
|
+
const storedAdapter = ctx.userAdapter ?? null;
|
|
36913
|
+
if (options.userAdapter && options.userAdapter !== storedAdapter) {
|
|
36914
|
+
try {
|
|
36915
|
+
await client.projects.update(ctx.projectId, {
|
|
36916
|
+
userAdapter: options.userAdapter
|
|
36917
|
+
});
|
|
36918
|
+
} catch (error51) {
|
|
36919
|
+
log2(
|
|
36920
|
+
`\u26A0 Could not save the Next.js adapter choice: ${error51 instanceof Error ? error51.message : String(error51)}`
|
|
36921
|
+
);
|
|
36922
|
+
}
|
|
36923
|
+
}
|
|
36924
|
+
if (options.userAdapter) log2(userAdapterOutcome(options.userAdapter));
|
|
37136
36925
|
const executor = options.executor ?? new LocalBuildExecutor(localDependencies(sourceDir, log2));
|
|
37137
36926
|
const observer = eventsObserver(
|
|
37138
36927
|
cpUrl,
|
|
@@ -37161,7 +36950,8 @@ async function deployDirectory(sourceDir, options, log2) {
|
|
|
37161
36950
|
// one, as before.
|
|
37162
36951
|
env: ctx.environment ? { ...envToSend, ...ctx.env } : { ...ctx.env, ...envToSend },
|
|
37163
36952
|
strategy: ctx.strategy ?? null,
|
|
37164
|
-
...ctx.vinextEnabled === void 0 ? {} : { vinextEnabled: ctx.vinextEnabled }
|
|
36953
|
+
...ctx.vinextEnabled === void 0 ? {} : { vinextEnabled: ctx.vinextEnabled },
|
|
36954
|
+
...options.userAdapter ?? storedAdapter ? { userAdapter: options.userAdapter ?? storedAdapter } : {}
|
|
37165
36955
|
},
|
|
37166
36956
|
observer,
|
|
37167
36957
|
createCacheTransport({
|
|
@@ -37343,6 +37133,13 @@ export {
|
|
|
37343
37133
|
promptForMissingEnv,
|
|
37344
37134
|
pullEnv,
|
|
37345
37135
|
detectGitInfo,
|
|
37136
|
+
detectUserAdapter,
|
|
37137
|
+
parseUserAdapter,
|
|
37138
|
+
USER_ADAPTER_OPTIONS,
|
|
37139
|
+
userAdapterQuestion,
|
|
37140
|
+
userAdapterStored,
|
|
37141
|
+
userAdapterUnasked,
|
|
37142
|
+
userAdapterUnreadable,
|
|
37346
37143
|
version2 as version,
|
|
37347
37144
|
DATA_ENV_MESSAGES,
|
|
37348
37145
|
dataEnvironment,
|
|
@@ -37372,7 +37169,7 @@ export {
|
|
|
37372
37169
|
runDbLint,
|
|
37373
37170
|
BUNDLE_MESSAGES,
|
|
37374
37171
|
functionsFolder,
|
|
37375
|
-
|
|
37172
|
+
parseJsonc,
|
|
37376
37173
|
defaultSleep,
|
|
37377
37174
|
retryAfterSeconds,
|
|
37378
37175
|
withFunctionRetries,
|