naro-cli 0.15.0 → 0.17.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 +70 -7
- package/dist/{chunk-6WJ3QQ5Y.js → chunk-PYRN5XR6.js} +288 -53
- package/dist/deploy.d.ts +4 -1
- package/dist/deploy.js +1 -1
- package/dist/index.js +592 -97
- package/dist/output.d.ts +5 -0
- package/dist/upload.d.ts +2 -0
- package/package.json +5 -5
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
|
|
6
6
|
// src/deploy.ts
|
|
7
7
|
import { existsSync as existsSync7 } from "fs";
|
|
8
|
-
import { cp as cp2, mkdtemp as mkdtemp2, readFile as readFile13, rm as
|
|
8
|
+
import { cp as cp2, mkdtemp as mkdtemp2, readFile as readFile13, rm as rm4 } from "fs/promises";
|
|
9
9
|
import { tmpdir as tmpdir2 } from "os";
|
|
10
|
-
import { basename as basename3, dirname as
|
|
10
|
+
import { basename as basename3, dirname as dirname5, join as join24, resolve as resolve10 } from "path";
|
|
11
11
|
import { fileURLToPath } from "url";
|
|
12
12
|
|
|
13
13
|
// ../../packages/build/src/artifact-upload.ts
|
|
@@ -26,6 +26,7 @@ function artifactUrlKey(kind, name) {
|
|
|
26
26
|
return `${kind}/${name}`;
|
|
27
27
|
}
|
|
28
28
|
var ARTIFACT_URL_BATCH_SIZE = 100;
|
|
29
|
+
var ARTIFACT_UPLOAD_CONCURRENCY = 8;
|
|
29
30
|
function parseArtifactPutUrls(payload) {
|
|
30
31
|
if (typeof payload !== "object" || payload === null) return null;
|
|
31
32
|
const { urls, disabled } = payload;
|
|
@@ -37,28 +38,55 @@ function parseArtifactPutUrls(payload) {
|
|
|
37
38
|
}
|
|
38
39
|
return resolved;
|
|
39
40
|
}
|
|
41
|
+
async function eachWithLimit(items, limit, work) {
|
|
42
|
+
let next = 0;
|
|
43
|
+
const lanes = Array.from(
|
|
44
|
+
{ length: Math.min(limit, items.length) },
|
|
45
|
+
async () => {
|
|
46
|
+
while (next < items.length) {
|
|
47
|
+
const item = items[next];
|
|
48
|
+
next += 1;
|
|
49
|
+
await work(item);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
await Promise.all(lanes);
|
|
54
|
+
}
|
|
40
55
|
async function uploadArtifactFiles(artifact, ports) {
|
|
41
56
|
const entries = artifactUploadEntries(artifact);
|
|
42
57
|
let proxied = 0;
|
|
43
58
|
for (let index = 0; index < entries.length; index += ARTIFACT_URL_BATCH_SIZE) {
|
|
44
59
|
const batch = entries.slice(index, index + ARTIFACT_URL_BATCH_SIZE);
|
|
45
60
|
const urls = await ports.resolvePutUrls(batch);
|
|
46
|
-
|
|
61
|
+
const viaProxy = [];
|
|
62
|
+
await eachWithLimit(batch, ARTIFACT_UPLOAD_CONCURRENCY, async (entry) => {
|
|
47
63
|
const url2 = urls?.get(artifactUrlKey(entry.kind, entry.file.name));
|
|
48
64
|
if (!url2) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
continue;
|
|
65
|
+
viaProxy.push(entry);
|
|
66
|
+
return;
|
|
52
67
|
}
|
|
53
68
|
try {
|
|
54
69
|
await ports.putSigned(url2, entry);
|
|
55
70
|
} catch {
|
|
56
|
-
|
|
57
|
-
await ports.putProxied(entry);
|
|
71
|
+
viaProxy.push(entry);
|
|
58
72
|
}
|
|
73
|
+
});
|
|
74
|
+
for (const entry of viaProxy) {
|
|
75
|
+
proxied += 1;
|
|
76
|
+
await ports.putProxied(entry);
|
|
59
77
|
}
|
|
60
78
|
}
|
|
61
|
-
|
|
79
|
+
const bytes = entries.reduce(
|
|
80
|
+
(total, entry) => total + entry.file.data.byteLength,
|
|
81
|
+
0
|
|
82
|
+
);
|
|
83
|
+
return { proxied, total: entries.length, bytes };
|
|
84
|
+
}
|
|
85
|
+
function artifactUploadSummary(report, elapsedMs) {
|
|
86
|
+
const kilobytes = Math.ceil(report.bytes / 1e3);
|
|
87
|
+
const size = kilobytes >= 1e3 ? `${(report.bytes / 1e6).toFixed(1)} MB` : `${String(kilobytes)} kB`;
|
|
88
|
+
const files = report.total === 1 ? "file" : "files";
|
|
89
|
+
return `Uploaded ${String(report.total)} artifact ${files} (${size}) in ${(elapsedMs / 1e3).toFixed(1)} s.`;
|
|
62
90
|
}
|
|
63
91
|
|
|
64
92
|
// ../../packages/build/src/cache.ts
|
|
@@ -74,7 +102,7 @@ var ERROR_CODE = {
|
|
|
74
102
|
deps: "INSTALL_FAILED",
|
|
75
103
|
next: "BUILD_FAILED"
|
|
76
104
|
};
|
|
77
|
-
async function computeDepsCacheKey(checkoutDir, packageManager) {
|
|
105
|
+
async function computeDepsCacheKey(checkoutDir, packageManager, extra = []) {
|
|
78
106
|
for (const name of LOCKFILES) {
|
|
79
107
|
let content;
|
|
80
108
|
try {
|
|
@@ -82,7 +110,10 @@ async function computeDepsCacheKey(checkoutDir, packageManager) {
|
|
|
82
110
|
} catch {
|
|
83
111
|
continue;
|
|
84
112
|
}
|
|
85
|
-
const
|
|
113
|
+
const hasher = createHash("sha256").update(name).update("\n").update(content);
|
|
114
|
+
if (extra.length > 0) hasher.update(`
|
|
115
|
+
${extra.join("\n")}`);
|
|
116
|
+
const hash2 = hasher.digest("hex");
|
|
86
117
|
return `${packageManager}-${hash2}`;
|
|
87
118
|
}
|
|
88
119
|
return null;
|
|
@@ -100,6 +131,7 @@ async function reportUnavailable(scope, ports, observer) {
|
|
|
100
131
|
"Build cache is unavailable - this build runs uncached and saves nothing for the next one."
|
|
101
132
|
);
|
|
102
133
|
}
|
|
134
|
+
var UNKNOWN_PAX_KEYWORD = /^tar: Ignoring unknown extended header keyword /;
|
|
103
135
|
async function restoreCache(args) {
|
|
104
136
|
const { scope, key, targetDir, ports, observer } = args;
|
|
105
137
|
const urls = await ports.transport.resolveUrls(scope, key);
|
|
@@ -132,7 +164,9 @@ async function restoreCache(args) {
|
|
|
132
164
|
stage: STAGE[scope],
|
|
133
165
|
errorCode: ERROR_CODE[scope]
|
|
134
166
|
},
|
|
135
|
-
|
|
167
|
+
{
|
|
168
|
+
onLog: (entry) => UNKNOWN_PAX_KEYWORD.test(entry.message) ? void 0 : observer.onLog(entry)
|
|
169
|
+
}
|
|
136
170
|
);
|
|
137
171
|
await log(observer, scope, "INFO", `Restored ${scope} cache (${key}).`);
|
|
138
172
|
return true;
|
|
@@ -160,7 +194,14 @@ async function saveCache(args) {
|
|
|
160
194
|
await ports.runCommand(
|
|
161
195
|
{
|
|
162
196
|
command: "tar",
|
|
163
|
-
|
|
197
|
+
// --no-xattrs: macOS bsdtar would store extended attributes that the
|
|
198
|
+
// build container's GNU tar warns about per file (UNKNOWN_PAX_KEYWORD).
|
|
199
|
+
// GNU tar 1.27+ and bsdtar 3.x both take it.
|
|
200
|
+
args: ["--no-xattrs", "--zstd", "-cf", archive, "-C", sourceDir, "."],
|
|
201
|
+
// macOS can also write the same metadata as AppleDouble `._name` files,
|
|
202
|
+
// which GNU tar restores as ordinary files (PR #114 review; not seen on
|
|
203
|
+
// bsdtar 3.5.3 here). GNU tar ignores the variable.
|
|
204
|
+
env: { COPYFILE_DISABLE: "1" },
|
|
164
205
|
cwd: sourceDir,
|
|
165
206
|
timeoutMs: 12e4,
|
|
166
207
|
stage: STAGE[scope],
|
|
@@ -224,9 +265,9 @@ function hashAsset(data, contentType2) {
|
|
|
224
265
|
}
|
|
225
266
|
|
|
226
267
|
// ../../packages/build/src/local-build-executor.ts
|
|
227
|
-
import { access as access8, mkdtemp, readFile as readFile12, rm as
|
|
268
|
+
import { access as access8, mkdtemp, readFile as readFile12, rm as rm3 } from "fs/promises";
|
|
228
269
|
import { tmpdir } from "os";
|
|
229
|
-
import { dirname as
|
|
270
|
+
import { dirname as dirname4, join as join17, resolve as resolve7 } from "path";
|
|
230
271
|
|
|
231
272
|
// ../../packages/core/src/route-patterns.ts
|
|
232
273
|
var ROUTE_PATTERN = /^\/[A-Za-z0-9\-._~%!$&()*+,;=:@/[\]]*$/;
|
|
@@ -257,6 +298,9 @@ var PHASES = [
|
|
|
257
298
|
];
|
|
258
299
|
var ACTIVE_STATUSES = new Set(PHASES);
|
|
259
300
|
|
|
301
|
+
// ../../packages/core/src/deployment-stall.ts
|
|
302
|
+
var STALL_WINDOW_MS = 10 * 6e4;
|
|
303
|
+
|
|
260
304
|
// ../../packages/core/src/deployment-strategy.ts
|
|
261
305
|
var MIN_SUPPORTED_NEXT_MAJOR = 15;
|
|
262
306
|
|
|
@@ -15254,13 +15298,18 @@ function cacheEnv(dir) {
|
|
|
15254
15298
|
return {
|
|
15255
15299
|
npm_config_store_dir: dir,
|
|
15256
15300
|
npm_config_cache: dir,
|
|
15257
|
-
YARN_CACHE_FOLDER: dir
|
|
15301
|
+
YARN_CACHE_FOLDER: dir,
|
|
15302
|
+
YARN_ENABLE_GLOBAL_CACHE: "0"
|
|
15258
15303
|
};
|
|
15259
15304
|
}
|
|
15260
15305
|
function withSharedCache(spec, dir) {
|
|
15261
15306
|
return {
|
|
15262
15307
|
...spec,
|
|
15263
|
-
addArgs: (specs) => [
|
|
15308
|
+
addArgs: (specs) => [
|
|
15309
|
+
...spec.addArgs(specs),
|
|
15310
|
+
...spec.sharedCacheAddArgs ?? [],
|
|
15311
|
+
...spec.cacheArgs(dir)
|
|
15312
|
+
],
|
|
15264
15313
|
addEnv: { ...spec.addEnv, ...cacheEnv(dir) }
|
|
15265
15314
|
};
|
|
15266
15315
|
}
|
|
@@ -15301,7 +15350,24 @@ async function detectPackageManager(root) {
|
|
|
15301
15350
|
install: ["npm", "ci"],
|
|
15302
15351
|
cacheArgs: (dir) => ["--cache", dir],
|
|
15303
15352
|
// --no-save keeps package.json and the lockfile untouched.
|
|
15304
|
-
addArgs: (specs) => ["npm", "install", "--no-save", ...specs]
|
|
15353
|
+
addArgs: (specs) => ["npm", "install", "--no-save", ...specs],
|
|
15354
|
+
// --prefer-offline takes package metadata from the restored cache instead
|
|
15355
|
+
// of asking the registry again for each of the toolchain's ~160 packages
|
|
15356
|
+
// (npm keeps metadata in the same cache, which the deps cache saves).
|
|
15357
|
+
// Measured on one vCPU like the build container: 8.8 s → 7.9 s locally,
|
|
15358
|
+
// and the live add took 17 s against 8.8 s here — the gap is registry
|
|
15359
|
+
// round trips.
|
|
15360
|
+
//
|
|
15361
|
+
// npm trusts cached metadata outright: a cached packument that lacks the
|
|
15362
|
+
// asked-for version fails with ETARGET instead of being fetched again
|
|
15363
|
+
// (pacote leaves that revalidation as a TODO). That cannot happen in the
|
|
15364
|
+
// build's own cache because its key carries the toolchain
|
|
15365
|
+
// (computeDepsCacheKey): a toolchain bump starts from an empty cache, and
|
|
15366
|
+
// the cache restored under a key was filled by this same add over the
|
|
15367
|
+
// same lockfile. A machine's default cache has no such key, so without
|
|
15368
|
+
// the build cache (no zstd, no transport — mostly the CLI) the add stays
|
|
15369
|
+
// online (PR #134 review).
|
|
15370
|
+
sharedCacheAddArgs: ["--prefer-offline"]
|
|
15305
15371
|
};
|
|
15306
15372
|
}
|
|
15307
15373
|
if (await exists(join2(root, "yarn.lock"))) {
|
|
@@ -15313,7 +15379,8 @@ async function detectPackageManager(root) {
|
|
|
15313
15379
|
"install",
|
|
15314
15380
|
modern ? "--immutable" : "--frozen-lockfile"
|
|
15315
15381
|
],
|
|
15316
|
-
// Berry takes no install-time cache flag;
|
|
15382
|
+
// Berry takes no install-time cache flag; cacheEnv covers it
|
|
15383
|
+
// (YARN_CACHE_FOLDER with the global cache switched off).
|
|
15317
15384
|
cacheArgs: (dir) => modern ? [] : ["--cache-folder", dir],
|
|
15318
15385
|
addArgs: (specs) => ["yarn", "add", ...specs]
|
|
15319
15386
|
};
|
|
@@ -15648,14 +15715,18 @@ async function pathExists(path) {
|
|
|
15648
15715
|
return false;
|
|
15649
15716
|
}
|
|
15650
15717
|
}
|
|
15718
|
+
var BUILD_NPMRC = [
|
|
15719
|
+
"# Host package-manager credentials are intentionally unavailable.",
|
|
15720
|
+
"audit=false",
|
|
15721
|
+
"fund=false",
|
|
15722
|
+
"update-notifier=false",
|
|
15723
|
+
""
|
|
15724
|
+
].join("\n");
|
|
15651
15725
|
async function createPackageManagerConfig(appRoot, writer = async (path, contents) => {
|
|
15652
15726
|
await writeFile3(path, contents, "utf8");
|
|
15653
15727
|
}) {
|
|
15654
15728
|
const packageManagerConfigPath = join5(appRoot, ".next-deploy-user.npmrc");
|
|
15655
|
-
await writer(
|
|
15656
|
-
packageManagerConfigPath,
|
|
15657
|
-
"# Host package-manager credentials are intentionally unavailable.\n"
|
|
15658
|
-
);
|
|
15729
|
+
await writer(packageManagerConfigPath, BUILD_NPMRC);
|
|
15659
15730
|
return packageManagerConfigPath;
|
|
15660
15731
|
}
|
|
15661
15732
|
async function createPlatformBuildConfig(appRoot, deploymentId, writer = async (path, contents) => {
|
|
@@ -17921,8 +17992,11 @@ function createVinextCloudflareStrategy(options) {
|
|
|
17921
17992
|
}
|
|
17922
17993
|
|
|
17923
17994
|
// ../../packages/build/src/strategy/workspace.ts
|
|
17924
|
-
import {
|
|
17925
|
-
import {
|
|
17995
|
+
import { execFile } from "child_process";
|
|
17996
|
+
import { cp, mkdir as mkdir2, readdir as readdir4, rm as rm2 } from "fs/promises";
|
|
17997
|
+
import { basename as basename2, dirname as dirname3, join as join16, relative as relative5, resolve as resolve6 } from "path";
|
|
17998
|
+
import { promisify } from "util";
|
|
17999
|
+
var execFileAsync = promisify(execFile);
|
|
17926
18000
|
var SKIPPED_ANYWHERE = /* @__PURE__ */ new Set(["node_modules"]);
|
|
17927
18001
|
function shouldCopy(path) {
|
|
17928
18002
|
const name = basename2(path);
|
|
@@ -17937,6 +18011,33 @@ async function copyCheckout(source, target2) {
|
|
|
17937
18011
|
filter: (path) => resolve6(path) === origin || shouldCopy(path)
|
|
17938
18012
|
});
|
|
17939
18013
|
}
|
|
18014
|
+
async function copyInstalledPackages(source, target2) {
|
|
18015
|
+
const origin = resolve6(source);
|
|
18016
|
+
const installs = [];
|
|
18017
|
+
const walk2 = async (dir) => {
|
|
18018
|
+
for (const entry of await readdir4(dir, { withFileTypes: true })) {
|
|
18019
|
+
if (!entry.isDirectory() || entry.name === ".git") continue;
|
|
18020
|
+
const path = join16(dir, entry.name);
|
|
18021
|
+
if (entry.name === "node_modules") installs.push(path);
|
|
18022
|
+
else await walk2(path);
|
|
18023
|
+
}
|
|
18024
|
+
};
|
|
18025
|
+
await walk2(origin);
|
|
18026
|
+
for (const install of installs)
|
|
18027
|
+
await copyTree(install, join16(target2, relative5(origin, install)));
|
|
18028
|
+
}
|
|
18029
|
+
async function copyTree(from, to) {
|
|
18030
|
+
await mkdir2(dirname3(to), { recursive: true });
|
|
18031
|
+
if (process.platform !== "win32") {
|
|
18032
|
+
try {
|
|
18033
|
+
await execFileAsync("cp", ["-a", from, to]);
|
|
18034
|
+
return;
|
|
18035
|
+
} catch {
|
|
18036
|
+
await rm2(to, { recursive: true, force: true });
|
|
18037
|
+
}
|
|
18038
|
+
}
|
|
18039
|
+
await cp(from, to, { recursive: true, verbatimSymlinks: true });
|
|
18040
|
+
}
|
|
17940
18041
|
function forkedAppRoot(checkout, appRoot, forkCheckout) {
|
|
17941
18042
|
return join16(forkCheckout, relative5(checkout, appRoot));
|
|
17942
18043
|
}
|
|
@@ -17961,7 +18062,7 @@ async function withRouteList(artifact, list, appRoot, observer) {
|
|
|
17961
18062
|
}
|
|
17962
18063
|
var defaultLocalBuildDependencies = {
|
|
17963
18064
|
createWorkspace: () => mkdtemp(join17(tmpdir(), "next-deploy-build-")),
|
|
17964
|
-
removeWorkspace: (path) =>
|
|
18065
|
+
removeWorkspace: (path) => rm3(path, { recursive: true, force: true }),
|
|
17965
18066
|
runCommand,
|
|
17966
18067
|
detectPackageManager,
|
|
17967
18068
|
resolveAppRoot,
|
|
@@ -17981,6 +18082,7 @@ var defaultLocalBuildDependencies = {
|
|
|
17981
18082
|
readVinextArtifact,
|
|
17982
18083
|
vinextCommand: "vinext",
|
|
17983
18084
|
forkWorkspace: copyCheckout,
|
|
18085
|
+
copyInstalledPackages,
|
|
17984
18086
|
collectProjectFacts,
|
|
17985
18087
|
listNextRoutes,
|
|
17986
18088
|
hashFingerprintInputs: hashStrategyInputs,
|
|
@@ -18002,7 +18104,7 @@ async function readInstalledNextVersion(appRoot, checkout) {
|
|
|
18002
18104
|
} catch {
|
|
18003
18105
|
}
|
|
18004
18106
|
if (dir === stop) return null;
|
|
18005
|
-
const parent =
|
|
18107
|
+
const parent = dirname4(dir);
|
|
18006
18108
|
if (parent === dir) return null;
|
|
18007
18109
|
dir = parent;
|
|
18008
18110
|
}
|
|
@@ -18220,7 +18322,11 @@ var LocalBuildExecutor = class {
|
|
|
18220
18322
|
let depsKey = null;
|
|
18221
18323
|
let depsRestored = false;
|
|
18222
18324
|
if (cachePorts) {
|
|
18223
|
-
depsKey = await computeDepsCacheKey(
|
|
18325
|
+
depsKey = await computeDepsCacheKey(
|
|
18326
|
+
checkout,
|
|
18327
|
+
packageManager.name,
|
|
18328
|
+
isNext ? VINEXT_TOOLCHAIN : []
|
|
18329
|
+
);
|
|
18224
18330
|
if (depsKey) {
|
|
18225
18331
|
depsRestored = await tryRestore(
|
|
18226
18332
|
"deps",
|
|
@@ -18305,6 +18411,7 @@ var LocalBuildExecutor = class {
|
|
|
18305
18411
|
const fork = this.dependencies.forkWorkspace ?? defaultFork;
|
|
18306
18412
|
await fork(checkout, pristine);
|
|
18307
18413
|
let forks = 0;
|
|
18414
|
+
const resolverConcurrency = this.dependencies.resolverConcurrency ?? 1;
|
|
18308
18415
|
const forkWorkspace = async (label2) => {
|
|
18309
18416
|
const target2 = join17(
|
|
18310
18417
|
workspace,
|
|
@@ -18312,7 +18419,9 @@ var LocalBuildExecutor = class {
|
|
|
18312
18419
|
`${String(forks++)}-${label2.replace(/[^a-z0-9-]/gi, "-")}`
|
|
18313
18420
|
);
|
|
18314
18421
|
await fork(pristine, target2);
|
|
18315
|
-
|
|
18422
|
+
if (packageManager.name === "npm" && resolverConcurrency === 1)
|
|
18423
|
+
await (this.dependencies.copyInstalledPackages ?? copyInstalledPackages)(checkout, target2);
|
|
18424
|
+
else await install(target2);
|
|
18316
18425
|
return {
|
|
18317
18426
|
checkout: target2,
|
|
18318
18427
|
appRoot: forkedAppRoot(checkout, appRoot, target2)
|
|
@@ -18355,7 +18464,7 @@ var LocalBuildExecutor = class {
|
|
|
18355
18464
|
{
|
|
18356
18465
|
pinned: input.strategy ?? null,
|
|
18357
18466
|
fingerprint: fingerprint.hash,
|
|
18358
|
-
concurrency:
|
|
18467
|
+
concurrency: resolverConcurrency,
|
|
18359
18468
|
...this.dependencies.now ? { now: this.dependencies.now } : {}
|
|
18360
18469
|
}
|
|
18361
18470
|
);
|
|
@@ -18446,22 +18555,31 @@ function createLogBatcher(options) {
|
|
|
18446
18555
|
let buffer = [];
|
|
18447
18556
|
let timer = null;
|
|
18448
18557
|
let pending = null;
|
|
18558
|
+
let sending = Promise.resolve();
|
|
18449
18559
|
function disarm() {
|
|
18450
18560
|
if (timer === null) return;
|
|
18451
18561
|
clearTimeout(timer);
|
|
18452
18562
|
timer = null;
|
|
18453
18563
|
}
|
|
18564
|
+
function surfacePending() {
|
|
18565
|
+
if (pending === null) return;
|
|
18566
|
+
const { error: error51 } = pending;
|
|
18567
|
+
pending = null;
|
|
18568
|
+
throw error51;
|
|
18569
|
+
}
|
|
18454
18570
|
async function flush() {
|
|
18455
18571
|
disarm();
|
|
18456
|
-
|
|
18457
|
-
|
|
18458
|
-
|
|
18459
|
-
|
|
18572
|
+
surfacePending();
|
|
18573
|
+
if (buffer.length === 0) {
|
|
18574
|
+
await sending;
|
|
18575
|
+
surfacePending();
|
|
18576
|
+
return;
|
|
18460
18577
|
}
|
|
18461
|
-
if (buffer.length === 0) return;
|
|
18462
18578
|
const batch = buffer;
|
|
18463
18579
|
buffer = [];
|
|
18464
|
-
|
|
18580
|
+
const send = sending.then(() => options.send(batch));
|
|
18581
|
+
sending = send.catch(() => void 0);
|
|
18582
|
+
await send;
|
|
18465
18583
|
}
|
|
18466
18584
|
function arm() {
|
|
18467
18585
|
if (timer !== null || !options.intervalMs) return;
|
|
@@ -19481,6 +19599,31 @@ var DomainsApi = class {
|
|
|
19481
19599
|
const match = await this.findByHostname(projectId, hostname3);
|
|
19482
19600
|
return this.verify(projectId, match.id, options);
|
|
19483
19601
|
}
|
|
19602
|
+
/**
|
|
19603
|
+
* Ownership checks the project opened for domains another project holds
|
|
19604
|
+
* (known-issues #156). Adding such a domain fails with
|
|
19605
|
+
* DOMAIN_VERIFICATION_REQUIRED and its check in `details.claim`.
|
|
19606
|
+
*/
|
|
19607
|
+
async listClaims(projectId) {
|
|
19608
|
+
const body = await this.client.request(
|
|
19609
|
+
`/api/projects/${encodeURIComponent(projectId)}/domain-claims`,
|
|
19610
|
+
{ context: "List ownership checks" }
|
|
19611
|
+
);
|
|
19612
|
+
return body.claims;
|
|
19613
|
+
}
|
|
19614
|
+
/** Reads the TXT record; when it matches, the domain moves to this project. */
|
|
19615
|
+
async verifyClaim(projectId, claimId) {
|
|
19616
|
+
return this.client.request(
|
|
19617
|
+
`/api/projects/${encodeURIComponent(projectId)}/domain-claims/${encodeURIComponent(claimId)}/verify`,
|
|
19618
|
+
{ method: "POST", body: {}, context: "Verify domain ownership" }
|
|
19619
|
+
);
|
|
19620
|
+
}
|
|
19621
|
+
async removeClaim(projectId, claimId) {
|
|
19622
|
+
await this.client.request(
|
|
19623
|
+
`/api/projects/${encodeURIComponent(projectId)}/domain-claims/${encodeURIComponent(claimId)}`,
|
|
19624
|
+
{ method: "DELETE", context: "Remove ownership check" }
|
|
19625
|
+
);
|
|
19626
|
+
}
|
|
19484
19627
|
async removeById(projectId, domainId) {
|
|
19485
19628
|
await this.client.request(
|
|
19486
19629
|
`/api/projects/${encodeURIComponent(projectId)}/domains/${encodeURIComponent(domainId)}`,
|
|
@@ -19950,6 +20093,14 @@ function bucketFields(fields, into = {}) {
|
|
|
19950
20093
|
if (fields[key] !== void 0) into[key] = fields[key];
|
|
19951
20094
|
return into;
|
|
19952
20095
|
}
|
|
20096
|
+
function listFields(options) {
|
|
20097
|
+
const body = {};
|
|
20098
|
+
if (options.prefix !== void 0) body.prefix = options.prefix;
|
|
20099
|
+
if (options.limit !== void 0) body.limit = options.limit;
|
|
20100
|
+
if (options.offset !== void 0) body.offset = options.offset;
|
|
20101
|
+
if (options.sortBy !== void 0) body.sortBy = options.sortBy;
|
|
20102
|
+
return body;
|
|
20103
|
+
}
|
|
19953
20104
|
var BackendApi = class {
|
|
19954
20105
|
constructor(client) {
|
|
19955
20106
|
this.client = client;
|
|
@@ -20474,6 +20625,60 @@ var StorageApi = class {
|
|
|
20474
20625
|
);
|
|
20475
20626
|
return { deleted: body.deleted, done: body.done };
|
|
20476
20627
|
}
|
|
20628
|
+
/**
|
|
20629
|
+
* What is directly below a folder of a bucket — its folders first, by
|
|
20630
|
+
* name, then its files — through the control plane's object proxy
|
|
20631
|
+
* (Storage 3-1e): the project's Naro worker lists it with the stored
|
|
20632
|
+
* service key, so every object is listed whatever the policies say. There
|
|
20633
|
+
* is no search. Needs `storage.manage`, Storage on and the backend on and
|
|
20634
|
+
* ready (`STORAGE_NOT_ENABLED`, `BACKEND_OFF`, `BACKEND_NOT_READY`, 409);
|
|
20635
|
+
* the worker's refusals — `BUCKET_NOT_FOUND`, `INVALID_REQUEST` with
|
|
20636
|
+
* `details.path` and `details.reason` — come through as they are.
|
|
20637
|
+
*/
|
|
20638
|
+
async listObjects(projectId, bucket, options = {}) {
|
|
20639
|
+
const body = await this.client.request(
|
|
20640
|
+
this.bucketPath(projectId, bucket, "/objects/list"),
|
|
20641
|
+
{ method: "POST", body: listFields(options), context: "List objects" }
|
|
20642
|
+
);
|
|
20643
|
+
return body.objects;
|
|
20644
|
+
}
|
|
20645
|
+
/**
|
|
20646
|
+
* A link that downloads one object without a key, for `expiresIn` seconds
|
|
20647
|
+
* (1–3600 through the control plane; `VALIDATION_FAILED` past it), on the
|
|
20648
|
+
* project's URL. Replacing or deleting the object ends it. The path is
|
|
20649
|
+
* held to the object name rules (`INVALID_PATH`); one not there is the
|
|
20650
|
+
* worker's `OBJECT_NOT_FOUND`.
|
|
20651
|
+
*/
|
|
20652
|
+
async signObject(projectId, bucket, path, options) {
|
|
20653
|
+
const body = await this.client.request(
|
|
20654
|
+
this.bucketPath(projectId, bucket, "/objects/sign"),
|
|
20655
|
+
{
|
|
20656
|
+
method: "POST",
|
|
20657
|
+
body: {
|
|
20658
|
+
path,
|
|
20659
|
+
expiresIn: options.expiresIn,
|
|
20660
|
+
// false is no download (supabase-js): left out, since the worker
|
|
20661
|
+
// answers it 400 INVALID_REQUEST — it is not a file name.
|
|
20662
|
+
...options.download === void 0 || options.download === false ? {} : { download: options.download }
|
|
20663
|
+
},
|
|
20664
|
+
context: "Sign an object URL"
|
|
20665
|
+
}
|
|
20666
|
+
);
|
|
20667
|
+
return { signedUrl: body.signedUrl };
|
|
20668
|
+
}
|
|
20669
|
+
/**
|
|
20670
|
+
* Deletes up to 1,000 objects by their full paths and answers the ones it
|
|
20671
|
+
* deleted, in the order asked: a path not there, or being written, is left
|
|
20672
|
+
* out — not an error (supabase-js's `remove`). A folder is not deleted by
|
|
20673
|
+
* its name; list it and delete what is in it.
|
|
20674
|
+
*/
|
|
20675
|
+
async removeObjects(projectId, bucket, prefixes) {
|
|
20676
|
+
const body = await this.client.request(
|
|
20677
|
+
this.bucketPath(projectId, bucket, "/objects"),
|
|
20678
|
+
{ method: "DELETE", body: { prefixes }, context: "Remove objects" }
|
|
20679
|
+
);
|
|
20680
|
+
return body.objects;
|
|
20681
|
+
}
|
|
20477
20682
|
};
|
|
20478
20683
|
|
|
20479
20684
|
// ../../packages/sdk/src/database.ts
|
|
@@ -21080,6 +21285,10 @@ var CATALOG = {
|
|
|
21080
21285
|
status: 404,
|
|
21081
21286
|
message: ({ bucket, path }) => `Object ${storageName(path)} was not found in bucket ${storageName(bucket)}.`
|
|
21082
21287
|
},
|
|
21288
|
+
UPLOAD_NOT_FOUND: {
|
|
21289
|
+
status: 404,
|
|
21290
|
+
message: ({ upload }) => `Upload ${storageName(upload)} was not found or has expired.`
|
|
21291
|
+
},
|
|
21083
21292
|
INVALID_CONTENT_TYPE: {
|
|
21084
21293
|
status: 400,
|
|
21085
21294
|
message: ({ type }) => `Content-Type ${storageName(type)} is not a media type like image/png.`
|
|
@@ -21094,7 +21303,7 @@ var CATALOG = {
|
|
|
21094
21303
|
},
|
|
21095
21304
|
OBJECT_TOO_LARGE: {
|
|
21096
21305
|
status: 413,
|
|
21097
|
-
message: (vars) => "single" in vars ? "Uploads over 50 MiB
|
|
21306
|
+
message: (vars) => "single" in vars ? "Uploads over 50 MiB go in parts: use the multipart upload." : `The object is ${String(vars.size)} bytes; bucket ${storageName(vars.bucket)} takes objects up to ${String(vars.max)} bytes.`
|
|
21098
21307
|
},
|
|
21099
21308
|
MIME_TYPE_NOT_ALLOWED: {
|
|
21100
21309
|
status: 415,
|
|
@@ -25840,7 +26049,7 @@ function claimUpload(i) {
|
|
|
25840
26049
|
const nonce = nonceOf(i.nonce);
|
|
25841
26050
|
return compose(
|
|
25842
26051
|
[
|
|
25843
|
-
`INSERT INTO ${STORAGE_OBJECTS_TABLE} (id, bucket_id, name, owner, owner_id, metadata, version, parent, size, status, lock_id, lock_expires_at) SELECT ?, ?, ?, ?, ?, ?, NULL, ?, ?, 'uploading', ?, ? WHERE CASE WHEN NOT EXISTS (SELECT 1 FROM ${STORAGE_BUCKETS_TABLE} WHERE id = ? AND ${LIVE_BUCKET}) THEN ${marker("bucket", nonce)} WHEN (`,
|
|
26052
|
+
`INSERT INTO ${STORAGE_OBJECTS_TABLE} (id, bucket_id, name, owner, owner_id, metadata, version, parent, size, status, lock_id, lock_expires_at, pending) SELECT ?, ?, ?, ?, ?, ?, NULL, ?, ?, 'uploading', ?, ?, ? WHERE CASE WHEN NOT EXISTS (SELECT 1 FROM ${STORAGE_BUCKETS_TABLE} WHERE id = ? AND ${LIVE_BUCKET}) THEN ${marker("bucket", nonce)} WHEN (`,
|
|
25844
26053
|
i.check,
|
|
25845
26054
|
`) <> 1 THEN 0 WHEN EXISTS (SELECT 1 FROM ${STORAGE_OBJECTS_TABLE} WHERE bucket_id = ? AND name = ? AND status = 'ready') THEN ${marker("exists", nonce)} WHEN EXISTS (SELECT 1 FROM ${STORAGE_OBJECTS_TABLE} WHERE bucket_id = ? AND name = ?) THEN ${marker("busy", nonce)} WHEN ${PROJECT_BYTES} + ? > ? THEN ${marker("quota", nonce)} ELSE 1 END RETURNING id`
|
|
25846
26055
|
],
|
|
@@ -25856,6 +26065,7 @@ function claimUpload(i) {
|
|
|
25856
26065
|
i.size,
|
|
25857
26066
|
i.lockId,
|
|
25858
26067
|
i.expiresAt,
|
|
26068
|
+
i.pending ?? null,
|
|
25859
26069
|
i.bucket
|
|
25860
26070
|
],
|
|
25861
26071
|
[i.bucket, i.name, i.bucket, i.name, i.size, i.limitBytes]
|
|
@@ -25879,6 +26089,13 @@ function overwriteCheckRow(i) {
|
|
|
25879
26089
|
}
|
|
25880
26090
|
function claimOverwrite(i) {
|
|
25881
26091
|
const nonce = nonceOf(i.nonce);
|
|
26092
|
+
const room = i.inParts ? {
|
|
26093
|
+
sql: `${PROJECT_BYTES} + ? > ?`,
|
|
26094
|
+
values: [i.size, i.limitBytes]
|
|
26095
|
+
} : {
|
|
26096
|
+
sql: `? > o.size AND ${PROJECT_BYTES} + ? - o.size > ?`,
|
|
26097
|
+
values: [i.size, i.size, i.limitBytes]
|
|
26098
|
+
};
|
|
25882
26099
|
return compose(
|
|
25883
26100
|
[
|
|
25884
26101
|
`UPDATE ${STORAGE_OBJECTS_TABLE} AS o SET lock_id = ?, lock_expires_at = ?, pending = ? WHERE o.bucket_id = ? AND o.name = ? AND CASE WHEN NOT (`,
|
|
@@ -25886,17 +26103,14 @@ function claimOverwrite(i) {
|
|
|
25886
26103
|
// The row's own bucket (`o.bucket_id`), so no value is bound for it.
|
|
25887
26104
|
`) THEN ${marker("hidden", nonce)} WHEN NOT EXISTS (SELECT 1 FROM ${STORAGE_BUCKETS_TABLE} AS b WHERE b.id = o.bucket_id AND b.${LIVE_BUCKET}) THEN ${marker("bucket", nonce)} WHEN o.status <> 'ready' OR o.lock_id IS NOT NULL THEN ${marker("busy", nonce)} WHEN NOT (`,
|
|
25888
26105
|
i.updateUsing,
|
|
25889
|
-
`) THEN ${marker("denied", nonce)} WHEN
|
|
26106
|
+
`) THEN ${marker("denied", nonce)} WHEN ${room.sql} THEN ${marker("quota", nonce)} ELSE (`,
|
|
25890
26107
|
i.check,
|
|
25891
26108
|
// RETURNING names the columns bare: it does not see the UPDATE's
|
|
25892
26109
|
// alias (SQLite 3.53: `no such column: o.id`), and the table is the
|
|
25893
26110
|
// only one there.
|
|
25894
26111
|
") END RETURNING id, version, size, owner, owner_id, created_at"
|
|
25895
26112
|
],
|
|
25896
|
-
[
|
|
25897
|
-
[i.lockId, i.expiresAt, i.pending, i.bucket, i.name],
|
|
25898
|
-
[i.size, i.size, i.limitBytes]
|
|
25899
|
-
]
|
|
26113
|
+
[[i.lockId, i.expiresAt, i.pending, i.bucket, i.name], room.values]
|
|
25900
26114
|
);
|
|
25901
26115
|
}
|
|
25902
26116
|
function claimDelete(i) {
|
|
@@ -27075,6 +27289,17 @@ function formatRedirectEntry(entry) {
|
|
|
27075
27289
|
return entry.path === "/" ? entry.origin : `${entry.origin}${entry.path}`;
|
|
27076
27290
|
}
|
|
27077
27291
|
|
|
27292
|
+
// ../../packages/data-core/src/storage-multipart.ts
|
|
27293
|
+
var MiB = 1024 * 1024;
|
|
27294
|
+
var MULTIPART_PART_SIZES = [16 * MiB, 32 * MiB, 64 * MiB];
|
|
27295
|
+
var MAX_MULTIPART_PARTS = 1e4;
|
|
27296
|
+
var MAX_MULTIPART_BYTES = 64 * MiB * MAX_MULTIPART_PARTS;
|
|
27297
|
+
var MULTIPART_LOCK_MS = 60 * 60 * 1e3;
|
|
27298
|
+
var MULTIPART_PART_EXTEND_BELOW_MS = 30 * 60 * 1e3;
|
|
27299
|
+
var MULTIPART_COMPLETE_LOCK_MS = 15 * 60 * 1e3;
|
|
27300
|
+
var UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
|
|
27301
|
+
var UPLOAD_ID = new RegExp(`^(${UUID})\\.(${UUID})$`);
|
|
27302
|
+
|
|
27078
27303
|
// ../../packages/data-core/src/system-sql.ts
|
|
27079
27304
|
async function convertLegacyPolicies(db, found) {
|
|
27080
27305
|
const rows = rowsOf(await db.prepare(POLICY_SQL.list).all());
|
|
@@ -28063,14 +28288,14 @@ async function promptForMissingEnv(ctx, keys) {
|
|
|
28063
28288
|
}
|
|
28064
28289
|
|
|
28065
28290
|
// src/git-info.ts
|
|
28066
|
-
import { execFile } from "child_process";
|
|
28291
|
+
import { execFile as execFile2 } from "child_process";
|
|
28067
28292
|
var SUPPORTED_REMOTE = [
|
|
28068
28293
|
/^https:\/\/[^\s]+$/,
|
|
28069
28294
|
/^ssh:\/\/[^\s]+$/,
|
|
28070
28295
|
/^git@[A-Za-z0-9.-]+:[A-Za-z0-9._/-]+(\.git)?$/
|
|
28071
28296
|
];
|
|
28072
28297
|
var defaultExec = (args, cwd) => new Promise((resolve11, reject) => {
|
|
28073
|
-
|
|
28298
|
+
execFile2("git", args, { cwd }, (error51, stdout) => {
|
|
28074
28299
|
if (error51) reject(error51);
|
|
28075
28300
|
else resolve11(stdout);
|
|
28076
28301
|
});
|
|
@@ -28203,7 +28428,9 @@ function manifest(artifact) {
|
|
|
28203
28428
|
};
|
|
28204
28429
|
}
|
|
28205
28430
|
async function uploadArtifact(artifact, opts) {
|
|
28206
|
-
|
|
28431
|
+
const started = Date.now();
|
|
28432
|
+
const report = await uploadArtifactFiles(artifact, uploadPorts(opts));
|
|
28433
|
+
const uploadSummary = artifactUploadSummary(report, Date.now() - started);
|
|
28207
28434
|
const response = await authed(opts, "/artifacts/complete", {
|
|
28208
28435
|
method: "POST",
|
|
28209
28436
|
headers: { "Content-Type": "application/json" },
|
|
@@ -28214,7 +28441,8 @@ async function uploadArtifact(artifact, opts) {
|
|
|
28214
28441
|
throw new Error("Control plane did not return an artifact key.");
|
|
28215
28442
|
return {
|
|
28216
28443
|
artifactKey: payload.artifactKey,
|
|
28217
|
-
previewUrl: typeof payload.previewUrl === "string" ? payload.previewUrl : null
|
|
28444
|
+
previewUrl: typeof payload.previewUrl === "string" ? payload.previewUrl : null,
|
|
28445
|
+
uploadSummary
|
|
28218
28446
|
};
|
|
28219
28447
|
}
|
|
28220
28448
|
|
|
@@ -28290,7 +28518,8 @@ function eventsObserver(cp3, deploymentId, token, fetchImpl = fetch, logIngestUr
|
|
|
28290
28518
|
await flushLogs();
|
|
28291
28519
|
await post({ type: "metadata", metadata: rest }).catch(() => {
|
|
28292
28520
|
});
|
|
28293
|
-
}
|
|
28521
|
+
},
|
|
28522
|
+
flush: flushLogs
|
|
28294
28523
|
};
|
|
28295
28524
|
}
|
|
28296
28525
|
function slugify2(value) {
|
|
@@ -28309,11 +28538,11 @@ async function projectName(sourceDir) {
|
|
|
28309
28538
|
}
|
|
28310
28539
|
var COPY_SKIP = /(^|[\\/])(node_modules|\.next|\.open-next|\.git|\.wrangler|\.turbo|\.naro)([\\/]|$)/;
|
|
28311
28540
|
function resolveBin(name) {
|
|
28312
|
-
let dir =
|
|
28541
|
+
let dir = dirname5(fileURLToPath(import.meta.url));
|
|
28313
28542
|
for (; ; ) {
|
|
28314
28543
|
const candidate = join24(dir, "node_modules", ".bin", name);
|
|
28315
28544
|
if (existsSync7(candidate)) return candidate;
|
|
28316
|
-
const parent =
|
|
28545
|
+
const parent = dirname5(dir);
|
|
28317
28546
|
if (parent === dir) return name;
|
|
28318
28547
|
dir = parent;
|
|
28319
28548
|
}
|
|
@@ -28339,7 +28568,7 @@ async function detectPackageManagerLenient(root) {
|
|
|
28339
28568
|
function localDependencies(sourceDir) {
|
|
28340
28569
|
return {
|
|
28341
28570
|
createWorkspace: () => mkdtemp2(join24(tmpdir2(), "naro-build-")),
|
|
28342
|
-
removeWorkspace: (path) =>
|
|
28571
|
+
removeWorkspace: (path) => rm4(path, { recursive: true, force: true }),
|
|
28343
28572
|
async runCommand(spec, observer) {
|
|
28344
28573
|
if (spec.command === "git" && spec.args[0] === "clone") {
|
|
28345
28574
|
const checkout = spec.args.at(-1);
|
|
@@ -28485,12 +28714,19 @@ async function deployDirectory(sourceDir, options, log2) {
|
|
|
28485
28714
|
{ details: { deploymentId: ctx.deploymentId }, cause: error51 }
|
|
28486
28715
|
);
|
|
28487
28716
|
}
|
|
28488
|
-
await uploadArtifact(artifact, {
|
|
28717
|
+
const { uploadSummary } = await uploadArtifact(artifact, {
|
|
28489
28718
|
controlPlaneUrl: cpUrl,
|
|
28490
28719
|
deploymentId: ctx.deploymentId,
|
|
28491
28720
|
callbackToken: ctx.callbackToken,
|
|
28492
28721
|
...options.fetch ? { fetch: options.fetch } : {}
|
|
28493
28722
|
});
|
|
28723
|
+
log2(`\u25B8 ${uploadSummary}`);
|
|
28724
|
+
await observer.onLog({
|
|
28725
|
+
level: "INFO",
|
|
28726
|
+
stage: "DEPLOYING",
|
|
28727
|
+
message: uploadSummary
|
|
28728
|
+
});
|
|
28729
|
+
await observer.flush();
|
|
28494
28730
|
log2("\u25B8 publishing worker");
|
|
28495
28731
|
const detail = await waitForFinish(client, ctx, log2);
|
|
28496
28732
|
const url2 = deploymentUrl(detail, ctx, production);
|
|
@@ -28568,7 +28804,6 @@ export {
|
|
|
28568
28804
|
parseCacheControl,
|
|
28569
28805
|
STORAGE_OBJECTS_TABLE,
|
|
28570
28806
|
systemTablePredicate,
|
|
28571
|
-
dataError,
|
|
28572
28807
|
SCHEMA_SQL,
|
|
28573
28808
|
tableNames,
|
|
28574
28809
|
snapshotFromRows,
|