vercel 57.0.0 → 58.1.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/dist/chunks/{add-7M577U56.js → add-QKP6ZCHQ.js} +7 -7
- package/dist/chunks/{add-YRZTDNXX.js → add-WKV7KU4Y.js} +10 -8
- package/dist/chunks/build-ZXEK6YEA.js +240 -0
- package/dist/chunks/{chunk-4PGF367U.js → chunk-2D22CMQ7.js} +21 -3
- package/dist/chunks/{chunk-YA3WQFLY.js → chunk-32IPC6RB.js} +1 -1
- package/dist/chunks/{chunk-HD7B425F.js → chunk-3YARBN7P.js} +4 -4
- package/dist/chunks/{chunk-QZD5DKUR.js → chunk-4I7DTZAJ.js} +2 -2
- package/dist/chunks/{chunk-555WJSO5.js → chunk-4LSERVQQ.js} +4 -4
- package/dist/chunks/{chunk-2EDWKVNP.js → chunk-552YY6QY.js} +25 -11
- package/dist/chunks/{chunk-LMHT3QR3.js → chunk-5AG7MR7W.js} +3 -3
- package/dist/chunks/{chunk-A2TYQBX2.js → chunk-6QUKJKFX.js} +509 -242
- package/dist/chunks/{chunk-KCF6S3XF.js → chunk-75MDJ6TK.js} +10 -6
- package/dist/chunks/{chunk-FHEMFAHB.js → chunk-AX3N4MO2.js} +15 -9
- package/dist/chunks/{chunk-NRNMT43R.js → chunk-BAUVB2VF.js} +5 -11
- package/dist/chunks/{chunk-F7X55TOY.js → chunk-C267R2FA.js} +6 -5
- package/dist/chunks/{chunk-RAFH25WW.js → chunk-CSI7GEDD.js} +4 -4
- package/dist/chunks/{chunk-T4NODP6Y.js → chunk-CXICXWXJ.js} +3 -3
- package/dist/chunks/{chunk-TBR2Q37Y.js → chunk-DKS4XDVC.js} +248 -47
- package/dist/chunks/{chunk-DWMH5M4Q.js → chunk-E4LXCO7U.js} +1 -1
- package/dist/chunks/{chunk-ZVLPUREX.js → chunk-FBPCJV72.js} +2 -2
- package/dist/chunks/{chunk-VZSZBD4V.js → chunk-FR352QKR.js} +1 -1
- package/dist/chunks/{chunk-MAHINYBW.js → chunk-HXTQVMJZ.js} +2 -2
- package/dist/chunks/{chunk-NH43BFJ3.js → chunk-JA3QX2H6.js} +2 -2
- package/dist/chunks/{chunk-IOAZNR6Z.js → chunk-JNP3FQR3.js} +1 -1
- package/dist/chunks/{chunk-YOZCJHLZ.js → chunk-KLNWR2JI.js} +7 -7
- package/dist/chunks/{chunk-LHFNIZ2P.js → chunk-KY3ZOYJW.js} +4 -2
- package/dist/chunks/{chunk-NZRWTCRM.js → chunk-LA3BQQQK.js} +1 -1
- package/dist/chunks/{chunk-R5FOIIHT.js → chunk-LXA2GZ7U.js} +1 -1
- package/dist/chunks/{chunk-GIL3VAUR.js → chunk-NGYOR3MN.js} +5 -3
- package/dist/chunks/{chunk-3PKFXNJZ.js → chunk-NYURBHZJ.js} +7 -5
- package/dist/chunks/{chunk-F5PQWDOC.js → chunk-OG7DIS52.js} +1 -1
- package/dist/chunks/{chunk-3242RXCN.js → chunk-OVW5WUCR.js} +1 -1
- package/dist/chunks/{chunk-DMSLNAVH.js → chunk-P7IO46BQ.js} +2 -2
- package/dist/chunks/{chunk-MIFDRYTN.js → chunk-QCB22TQG.js} +2 -2
- package/dist/chunks/chunk-RBIFXFZX.js +52 -0
- package/dist/chunks/{chunk-SZXT3PDQ.js → chunk-RL7X7JGK.js} +1 -1
- package/dist/chunks/{chunk-UDWRZXIT.js → chunk-S7LXRKLD.js} +2 -1
- package/dist/chunks/{chunk-FYQPTH5C.js → chunk-TCBOCSWF.js} +7 -5
- package/dist/chunks/{chunk-OF2GNB42.js → chunk-TF627KEI.js} +1 -1
- package/dist/chunks/{chunk-4G6QZSBL.js → chunk-TPB4F5XN.js} +6 -4
- package/dist/chunks/{chunk-KSSNLCL4.js → chunk-U6PPDPR5.js} +2 -3
- package/dist/chunks/{chunk-3VS4DTAU.js → chunk-V6WHZAPP.js} +101 -11
- package/dist/chunks/{chunk-OGG6UBXK.js → chunk-VSMCQSGH.js} +1 -1
- package/dist/chunks/{chunk-3PGXYIKC.js → chunk-XAWGGWSG.js} +2 -2
- package/dist/chunks/{chunk-2MJROFVC.js → chunk-XTLNPNWY.js} +8 -5
- package/dist/chunks/{chunk-GP5VCTEU.js → chunk-XTQADJ6S.js} +207 -4
- package/dist/chunks/{chunk-RYO6FJFB.js → chunk-YITWM37U.js} +2 -2
- package/dist/chunks/{compile-vercel-config-3OHO3TJA.js → compile-vercel-config-AFGCQEYG.js} +4 -4
- package/dist/chunks/config-validator.mjs +1 -1
- package/dist/chunks/{delete-VOSJLNEA.js → delete-UGSJQBE7.js} +6 -6
- package/dist/chunks/{delete-3DZOCWCC.js → delete-Y5LNEZXI.js} +6 -6
- package/dist/chunks/{disable-LQDEVRQF.js → disable-IF3AHKJD.js} +6 -6
- package/dist/chunks/{discard-RGV4JKXQ.js → discard-Y6GZBIHJ.js} +6 -6
- package/dist/chunks/{edit-SFIEOQ24.js → edit-6TGJKUI5.js} +7 -7
- package/dist/chunks/{edit-UPZPI54L.js → edit-HNMKZ3YT.js} +6 -6
- package/dist/chunks/{enable-6UVH35WC.js → enable-SE4QM4X3.js} +6 -6
- package/dist/chunks/{export-6CEG3CK7.js → export-5AYL7HCJ.js} +6 -6
- package/dist/chunks/{image-CQRCD2OE.js → image-6BYNQVGW.js} +5 -5
- package/dist/chunks/{inspect-ZFRY3X3H.js → inspect-3KCFHDWA.js} +11 -11
- package/dist/chunks/{inspect-4ZAH3RFT.js → inspect-DPTRYDFH.js} +7 -7
- package/dist/chunks/{inspect-EXQBIAFF.js → inspect-FGYXO4K5.js} +10 -10
- package/dist/chunks/{inspect-K5ZMQG7X.js → inspect-LTHZUXA2.js} +10 -10
- package/dist/chunks/{inspect-UM3LDRPV.js → inspect-MA36GG73.js} +10 -10
- package/dist/chunks/{list-4DRVM7Q4.js → list-BTOXZBQK.js} +10 -10
- package/dist/chunks/{list-KCUHD4OA.js → list-OCW34SRV.js} +7 -7
- package/dist/chunks/{list-FJCBOCCA.js → list-VTQZSIIT.js} +5 -5
- package/dist/chunks/{login-DFGYNU3K.js → login-VSXLK5ZU.js} +18 -50
- package/dist/chunks/{ls-RHEQ6YQB.js → ls-3UA57DZZ.js} +10 -10
- package/dist/chunks/{ls-CG6A7UXF.js → ls-76YTWNKD.js} +11 -11
- package/dist/chunks/{ls-4QHHVXXD.js → ls-DRI2AOFB.js} +12 -12
- package/dist/chunks/{ls-34NCZKBE.js → ls-ZBLTJ5RE.js} +11 -11
- package/dist/chunks/{open-E3XADEMX.js → open-DVKAE5HP.js} +6 -6
- package/dist/chunks/{publish-Z3AQRUCS.js → publish-F5C4ZA7M.js} +6 -6
- package/dist/chunks/push-PKJFQTLO.js +180 -0
- package/dist/chunks/{query-3EV66DO3.js → query-GT5LCT45.js} +9 -9
- package/dist/chunks/{reorder-VA5E5ZJT.js → reorder-AQW4XFDS.js} +6 -6
- package/dist/chunks/{reply-SNSCNKAW.js → reply-FI7SADGU.js} +6 -6
- package/dist/chunks/{resolve-6ZX4RTXX.js → resolve-C5G7JJZJ.js} +6 -6
- package/dist/chunks/{restore-NEHI5B5P.js → restore-5TLSHQOS.js} +6 -6
- package/dist/chunks/{rm-22B22E47.js → rm-2EN66OYO.js} +8 -6
- package/dist/chunks/{rm-FR6KE744.js → rm-C37BHGQI.js} +7 -7
- package/dist/chunks/{rm-E5ZVLAKO.js → rm-L7OQPCIE.js} +10 -8
- package/dist/chunks/{rule-inspect-DMP2CKJQ.js → rule-inspect-V5DRHOTZ.js} +10 -10
- package/dist/chunks/{rules-EYGXEI2Z.js → rules-5XEMLN5G.js} +8 -8
- package/dist/chunks/{schema-2IIWOBSQ.js → schema-UEOZVBY5.js} +8 -8
- package/dist/chunks/{tags-ZDVYRHAY.js → tags-ZGANV4YD.js} +4 -4
- package/dist/chunks/{types-QKLIFDDP.js → types-IKWGLSDF.js} +4 -4
- package/dist/chunks/{update-QH4DQMZV.js → update-DHWSMSMS.js} +7 -7
- package/dist/commands/build/index.js +12 -16
- package/dist/commands/deploy/index.js +29 -24
- package/dist/commands/dev/index.js +25 -12
- package/dist/commands/env/index.js +28 -23
- package/dist/commands/link/index.js +21 -21
- package/dist/commands/list/index.js +13 -8
- package/dist/commands-bulk.js +3659 -2183
- package/dist/help.js +1 -1
- package/dist/index.js +24 -23
- package/dist/version.mjs +1 -1
- package/package.json +34 -92
- package/dist/chunks/chunk-6OMC3HOW.js +0 -73
|
@@ -20,13 +20,13 @@ import {
|
|
|
20
20
|
outputActionRequired,
|
|
21
21
|
outputAgentError,
|
|
22
22
|
shouldEmitNonInteractiveCommandError
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-S7LXRKLD.js";
|
|
24
24
|
import {
|
|
25
25
|
parseArguments,
|
|
26
26
|
printError,
|
|
27
27
|
require_string_width,
|
|
28
28
|
require_strip_ansi
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-RL7X7JGK.js";
|
|
30
30
|
import {
|
|
31
31
|
APIError,
|
|
32
32
|
CantParseJSONFile,
|
|
@@ -52,11 +52,12 @@ import {
|
|
|
52
52
|
getCommandNamePlain,
|
|
53
53
|
getFlagsSpecification,
|
|
54
54
|
isAPIError,
|
|
55
|
+
jsonOption,
|
|
55
56
|
packageName,
|
|
56
57
|
projectOption,
|
|
57
58
|
require_lib,
|
|
58
59
|
yesOption
|
|
59
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-U6PPDPR5.js";
|
|
60
61
|
import {
|
|
61
62
|
pkg_default
|
|
62
63
|
} from "./chunk-P4QNYOFB.js";
|
|
@@ -23280,7 +23281,7 @@ var require_utils3 = __commonJS({
|
|
|
23280
23281
|
};
|
|
23281
23282
|
}
|
|
23282
23283
|
}
|
|
23283
|
-
const hasVercelToml =
|
|
23284
|
+
const hasVercelToml = await fs5.hasPath("vercel.toml");
|
|
23284
23285
|
if (hasVercelToml) {
|
|
23285
23286
|
try {
|
|
23286
23287
|
const { parse: tomlParse3 } = await import("smol-toml");
|
|
@@ -29584,7 +29585,9 @@ var require_detect_builders = __commonJS({
|
|
|
29584
29585
|
detectApiExtensions: () => detectApiExtensions2,
|
|
29585
29586
|
detectBuilders: () => detectBuilders2,
|
|
29586
29587
|
detectOutputDirectory: () => detectOutputDirectory2,
|
|
29587
|
-
|
|
29588
|
+
getProxyBuilder: () => getProxyBuilder2,
|
|
29589
|
+
sortFiles: () => sortFiles,
|
|
29590
|
+
validateProxyConfig: () => validateProxyConfig3
|
|
29588
29591
|
});
|
|
29589
29592
|
module.exports = __toCommonJS2(detect_builders_exports);
|
|
29590
29593
|
var import_minimatch = __toESM2(require_minimatch());
|
|
@@ -29595,7 +29598,7 @@ var require_detect_builders = __commonJS({
|
|
|
29595
29598
|
var import_build_utils7 = __require("@vercel/build-utils");
|
|
29596
29599
|
var import_get_services_builders = require_get_services_builders();
|
|
29597
29600
|
var REGEX_MIDDLEWARE_FILES = "middleware.[jt]s";
|
|
29598
|
-
var
|
|
29601
|
+
var VERCEL_PLATFORM_FILES = [
|
|
29599
29602
|
"api/**",
|
|
29600
29603
|
"node_modules/**",
|
|
29601
29604
|
REGEX_MIDDLEWARE_FILES,
|
|
@@ -29607,8 +29610,18 @@ var require_detect_builders = __commonJS({
|
|
|
29607
29610
|
"bun.lockb",
|
|
29608
29611
|
".gitignore",
|
|
29609
29612
|
"README.md"
|
|
29610
|
-
]
|
|
29611
|
-
var
|
|
29613
|
+
];
|
|
29614
|
+
var REGEX_VERCEL_PLATFORM_FILES = VERCEL_PLATFORM_FILES.join(",");
|
|
29615
|
+
function escapeMinimatchPath(path3) {
|
|
29616
|
+
return path3.replace(/([\\,*?[\]{}()!+@])/g, "\\$1");
|
|
29617
|
+
}
|
|
29618
|
+
function getStaticFilesPattern(additionalExclusions = []) {
|
|
29619
|
+
return `!{${[
|
|
29620
|
+
...VERCEL_PLATFORM_FILES,
|
|
29621
|
+
...additionalExclusions.map(escapeMinimatchPath)
|
|
29622
|
+
].join(",")}}`;
|
|
29623
|
+
}
|
|
29624
|
+
var REGEX_NON_VERCEL_PLATFORM_FILES2 = getStaticFilesPattern();
|
|
29612
29625
|
var slugToFramework = new Map(
|
|
29613
29626
|
import_frameworks2.frameworkList.map((f) => [f.slug, f])
|
|
29614
29627
|
);
|
|
@@ -29664,6 +29677,18 @@ var require_detect_builders = __commonJS({
|
|
|
29664
29677
|
};
|
|
29665
29678
|
}
|
|
29666
29679
|
const { framework } = projectSettings;
|
|
29680
|
+
const proxyError = validateProxy(options, files, framework);
|
|
29681
|
+
if (proxyError) {
|
|
29682
|
+
return {
|
|
29683
|
+
builders: null,
|
|
29684
|
+
errors: [proxyError],
|
|
29685
|
+
warnings: [],
|
|
29686
|
+
defaultRoutes: null,
|
|
29687
|
+
redirectRoutes: null,
|
|
29688
|
+
rewriteRoutes: null,
|
|
29689
|
+
errorRoutes: null
|
|
29690
|
+
};
|
|
29691
|
+
}
|
|
29667
29692
|
const servicesConfig = services ?? experimentalServicesV2;
|
|
29668
29693
|
const configuredServices = servicesConfig ?? experimentalServicesV1;
|
|
29669
29694
|
const configuredServicesType = servicesConfig ? services ? "services" : "experimentalServicesV2" : "experimentalServices";
|
|
@@ -29680,6 +29705,12 @@ var require_detect_builders = __commonJS({
|
|
|
29680
29705
|
...(0, import_get_services_builders.warnIgnoredDirectories)(files, configuredServices)
|
|
29681
29706
|
);
|
|
29682
29707
|
}
|
|
29708
|
+
if (!result.errors && options.proxy) {
|
|
29709
|
+
result.builders = [
|
|
29710
|
+
getProxyBuilder2(options.proxy, options.tag, options.functions),
|
|
29711
|
+
...result.builders ?? []
|
|
29712
|
+
];
|
|
29713
|
+
}
|
|
29683
29714
|
return result;
|
|
29684
29715
|
}
|
|
29685
29716
|
const errors = [];
|
|
@@ -29730,6 +29761,9 @@ var require_detect_builders = __commonJS({
|
|
|
29730
29761
|
const apiRoutes = [];
|
|
29731
29762
|
const dynamicRoutes = [];
|
|
29732
29763
|
for (const fileName of sortedFiles) {
|
|
29764
|
+
if (fileName === options.proxy?.entrypoint) {
|
|
29765
|
+
continue;
|
|
29766
|
+
}
|
|
29733
29767
|
const apiBuilder = await maybeGetApiBuilder(fileName, apiMatches, options);
|
|
29734
29768
|
if (apiBuilder) {
|
|
29735
29769
|
const { routeError, apiRoute, isDynamic } = getApiRoute(
|
|
@@ -29772,6 +29806,15 @@ var require_detect_builders = __commonJS({
|
|
|
29772
29806
|
fallbackEntrypoint = fileName;
|
|
29773
29807
|
}
|
|
29774
29808
|
}
|
|
29809
|
+
if (options.proxy) {
|
|
29810
|
+
const proxyBuilder = getProxyBuilder2(
|
|
29811
|
+
options.proxy,
|
|
29812
|
+
options.tag,
|
|
29813
|
+
options.functions
|
|
29814
|
+
);
|
|
29815
|
+
addToUsedFunctions(proxyBuilder);
|
|
29816
|
+
apiBuilders.unshift(proxyBuilder);
|
|
29817
|
+
}
|
|
29775
29818
|
if (!makeFrontendStatic && (hasBuildScript(pkg) || buildCommand || framework)) {
|
|
29776
29819
|
frontendBuilder = detectFrontBuilder(
|
|
29777
29820
|
pkg,
|
|
@@ -29805,13 +29848,31 @@ var require_detect_builders = __commonJS({
|
|
|
29805
29848
|
} else if (apiBuilders.length && hasNoneApiFiles) {
|
|
29806
29849
|
frontendBuilder = {
|
|
29807
29850
|
use: "@vercel/static",
|
|
29808
|
-
src:
|
|
29851
|
+
src: getStaticFilesPattern(
|
|
29852
|
+
options.proxy ? [options.proxy.entrypoint] : []
|
|
29853
|
+
),
|
|
29809
29854
|
config: {
|
|
29810
29855
|
zeroConfig: true
|
|
29811
29856
|
}
|
|
29812
29857
|
};
|
|
29813
29858
|
}
|
|
29814
29859
|
}
|
|
29860
|
+
if (options.proxy && frontendBuilder && (0, import_is_official_runtime.isOfficialRuntime)("next", frontendBuilder.use)) {
|
|
29861
|
+
return {
|
|
29862
|
+
builders: null,
|
|
29863
|
+
errors: [
|
|
29864
|
+
{
|
|
29865
|
+
code: "proxy_framework_conflict",
|
|
29866
|
+
message: "The `proxy` property cannot be used with Next.js because the framework builds its own routing middleware."
|
|
29867
|
+
}
|
|
29868
|
+
],
|
|
29869
|
+
warnings,
|
|
29870
|
+
defaultRoutes: null,
|
|
29871
|
+
redirectRoutes: null,
|
|
29872
|
+
rewriteRoutes: null,
|
|
29873
|
+
errorRoutes: null
|
|
29874
|
+
};
|
|
29875
|
+
}
|
|
29815
29876
|
const unusedFunctionError = checkUnusedFunctions(
|
|
29816
29877
|
frontendBuilder,
|
|
29817
29878
|
usedFunctions,
|
|
@@ -29878,7 +29939,7 @@ var require_detect_builders = __commonJS({
|
|
|
29878
29939
|
};
|
|
29879
29940
|
}
|
|
29880
29941
|
async function maybeGetApiBuilder(fileName, apiMatches, options) {
|
|
29881
|
-
const middleware = fileName === "middleware.js" || fileName === "middleware.ts";
|
|
29942
|
+
const middleware = !options.proxy && (fileName === "middleware.js" || fileName === "middleware.ts");
|
|
29882
29943
|
if (middleware && options.projectSettings?.framework === "nextjs") {
|
|
29883
29944
|
return null;
|
|
29884
29945
|
}
|
|
@@ -29951,6 +30012,30 @@ var require_detect_builders = __commonJS({
|
|
|
29951
30012
|
const func = keys.find((key) => key === fileName || (0, import_minimatch.default)(fileName, key));
|
|
29952
30013
|
return func ? { fnPattern: func, func: functions[func] } : { fnPattern: null, func: null };
|
|
29953
30014
|
}
|
|
30015
|
+
function getProxyBuilder2(proxy, tag, functions = {}) {
|
|
30016
|
+
const { fnPattern, func } = getFunction(proxy.entrypoint, { functions });
|
|
30017
|
+
const runtime = func?.runtime;
|
|
30018
|
+
const config3 = {
|
|
30019
|
+
zeroConfig: true,
|
|
30020
|
+
middleware: true,
|
|
30021
|
+
...!runtime ? { middlewareRuntime: "nodejs" } : {},
|
|
30022
|
+
...proxy.matcher ? { middlewareMatcher: proxy.matcher } : {}
|
|
30023
|
+
};
|
|
30024
|
+
if (fnPattern && func) {
|
|
30025
|
+
config3.functions = { [fnPattern]: func };
|
|
30026
|
+
if (func.includeFiles) {
|
|
30027
|
+
config3.includeFiles = func.includeFiles;
|
|
30028
|
+
}
|
|
30029
|
+
if (func.excludeFiles) {
|
|
30030
|
+
config3.excludeFiles = func.excludeFiles;
|
|
30031
|
+
}
|
|
30032
|
+
}
|
|
30033
|
+
return {
|
|
30034
|
+
src: proxy.entrypoint,
|
|
30035
|
+
use: runtime || `@vercel/node${tag ? `@${tag}` : ""}`,
|
|
30036
|
+
config: config3
|
|
30037
|
+
};
|
|
30038
|
+
}
|
|
29954
30039
|
function getApiMatches() {
|
|
29955
30040
|
const config3 = { zeroConfig: true };
|
|
29956
30041
|
return [
|
|
@@ -29966,6 +30051,63 @@ var require_detect_builders = __commonJS({
|
|
|
29966
30051
|
{ src: "api/**/*.rs", use: `@vercel/rust`, config: config3 }
|
|
29967
30052
|
];
|
|
29968
30053
|
}
|
|
30054
|
+
function validateProxyConfig3(proxy) {
|
|
30055
|
+
if (typeof proxy !== "object" || typeof proxy.entrypoint !== "string" || !proxy.entrypoint) {
|
|
30056
|
+
return {
|
|
30057
|
+
code: "invalid_proxy",
|
|
30058
|
+
message: "The `proxy` property must contain an `entrypoint` string that references a `.js` or `.ts` file."
|
|
30059
|
+
};
|
|
30060
|
+
}
|
|
30061
|
+
const entrypoint = proxy.entrypoint;
|
|
30062
|
+
const segments = entrypoint.split("/");
|
|
30063
|
+
if (entrypoint.startsWith("/") || entrypoint.includes("\\") || segments.includes(".") || segments.includes("..") || /[?#\u0000-\u001f]/.test(entrypoint)) {
|
|
30064
|
+
return {
|
|
30065
|
+
code: "invalid_proxy_entrypoint",
|
|
30066
|
+
message: "The `proxy.entrypoint` path must be relative to the project root and cannot contain traversal, query, fragment, or control characters."
|
|
30067
|
+
};
|
|
30068
|
+
}
|
|
30069
|
+
if (!/\.(?:js|ts)$/.test(entrypoint) || entrypoint.endsWith(".d.ts")) {
|
|
30070
|
+
return {
|
|
30071
|
+
code: "invalid_proxy_entrypoint",
|
|
30072
|
+
message: "The `proxy.entrypoint` path must end in `.js` or `.ts` and reference an executable file."
|
|
30073
|
+
};
|
|
30074
|
+
}
|
|
30075
|
+
if (proxy.matcher !== void 0) {
|
|
30076
|
+
const matchers = Array.isArray(proxy.matcher) ? proxy.matcher : [proxy.matcher];
|
|
30077
|
+
if (matchers.length === 0 || matchers.some(
|
|
30078
|
+
(matcher) => typeof matcher !== "string" || !matcher.startsWith("/")
|
|
30079
|
+
)) {
|
|
30080
|
+
return {
|
|
30081
|
+
code: "invalid_proxy_matcher",
|
|
30082
|
+
message: "The `proxy.matcher` value must be a path matcher starting with `/`, or an array of path matchers starting with `/`."
|
|
30083
|
+
};
|
|
30084
|
+
}
|
|
30085
|
+
}
|
|
30086
|
+
return null;
|
|
30087
|
+
}
|
|
30088
|
+
function validateProxy(options, files, framework) {
|
|
30089
|
+
const { proxy } = options;
|
|
30090
|
+
if (!proxy) {
|
|
30091
|
+
return null;
|
|
30092
|
+
}
|
|
30093
|
+
const configError = validateProxyConfig3(proxy);
|
|
30094
|
+
if (configError) {
|
|
30095
|
+
return configError;
|
|
30096
|
+
}
|
|
30097
|
+
if (!files.includes(proxy.entrypoint)) {
|
|
30098
|
+
return {
|
|
30099
|
+
code: "proxy_entrypoint_not_found",
|
|
30100
|
+
message: `The proxy entrypoint \`${proxy.entrypoint}\` does not exist. Set \`proxy.entrypoint\` to an existing \`.js\` or \`.ts\` file.`
|
|
30101
|
+
};
|
|
30102
|
+
}
|
|
30103
|
+
if (framework === "nextjs" || framework === "astro") {
|
|
30104
|
+
return {
|
|
30105
|
+
code: "proxy_framework_conflict",
|
|
30106
|
+
message: `The \`proxy\` property cannot be used with ${framework === "nextjs" ? "Next.js" : "Astro"} because the framework builds its own routing middleware.`
|
|
30107
|
+
};
|
|
30108
|
+
}
|
|
30109
|
+
return null;
|
|
30110
|
+
}
|
|
29969
30111
|
function hasBuildScript(pkg) {
|
|
29970
30112
|
const { scripts = {} } = pkg || {};
|
|
29971
30113
|
return Boolean(scripts && scripts["build"]);
|
|
@@ -34924,6 +35066,7 @@ var require_dist6 = __commonJS({
|
|
|
34924
35066
|
getInternalServiceWorkerPath: () => import_utils4.getInternalServiceWorkerPath,
|
|
34925
35067
|
getInternalServiceWorkerPathPrefix: () => import_utils4.getInternalServiceWorkerPathPrefix,
|
|
34926
35068
|
getProjectPaths: () => import_get_project_paths.getProjectPaths,
|
|
35069
|
+
getProxyBuilder: () => import_detect_builders.getProxyBuilder,
|
|
34927
35070
|
getServicesBuilders: () => import_get_services_builders.getServicesBuilders,
|
|
34928
35071
|
getWorkspacePackagePaths: () => import_get_workspace_package_paths.getWorkspacePackagePaths,
|
|
34929
35072
|
getWorkspaces: () => import_get_workspaces.getWorkspaces,
|
|
@@ -34937,6 +35080,7 @@ var require_dist6 = __commonJS({
|
|
|
34937
35080
|
packageManagers: () => import_package_managers.packageManagers,
|
|
34938
35081
|
resolveAllConfiguredServicesV2: () => import_resolve_v2.resolveAllConfiguredServicesV2,
|
|
34939
35082
|
resolveConfiguredServiceV2: () => import_resolve_v2.resolveConfiguredServiceV2,
|
|
35083
|
+
validateProxyConfig: () => import_detect_builders.validateProxyConfig,
|
|
34940
35084
|
validateServiceConfigV2: () => import_resolve_v2.validateServiceConfigV2,
|
|
34941
35085
|
workspaceManagers: () => import_workspace_managers.workspaceManagers
|
|
34942
35086
|
});
|
|
@@ -38004,7 +38148,7 @@ var require_package = __commonJS({
|
|
|
38004
38148
|
"../client/package.json"(exports, module) {
|
|
38005
38149
|
module.exports = {
|
|
38006
38150
|
name: "@vercel/client",
|
|
38007
|
-
version: "18.
|
|
38151
|
+
version: "18.2.0",
|
|
38008
38152
|
main: "dist/index.js",
|
|
38009
38153
|
typings: "dist/index.d.ts",
|
|
38010
38154
|
homepage: "https://vercel.com",
|
|
@@ -56320,7 +56464,19 @@ async function performDeviceCodeFlow(client, options) {
|
|
|
56320
56464
|
);
|
|
56321
56465
|
const [deviceAuthorizationError, deviceAuthorization] = await processDeviceAuthorizationResponse(deviceAuthorizationResponse);
|
|
56322
56466
|
if (deviceAuthorizationError) {
|
|
56323
|
-
|
|
56467
|
+
if (options?.fallbackToLoginOnStepUpFailure && options.refreshToken && isOAuthError(deviceAuthorizationError) && (deviceAuthorizationError.code === "invalid_grant" || deviceAuthorizationError.code === "invalid_scope")) {
|
|
56468
|
+
output_manager_default.debug(
|
|
56469
|
+
`Step-up device authorization failed: ${deviceAuthorizationError.cause.message}`
|
|
56470
|
+
);
|
|
56471
|
+
output_manager_default.log("Couldn't refresh the saved login. Starting a new login.");
|
|
56472
|
+
return performDeviceCodeFlow(
|
|
56473
|
+
client,
|
|
56474
|
+
options.teamId ? { teamId: options.teamId } : void 0
|
|
56475
|
+
);
|
|
56476
|
+
}
|
|
56477
|
+
printError(
|
|
56478
|
+
isOAuthError(deviceAuthorizationError) ? deviceAuthorizationError.cause : deviceAuthorizationError
|
|
56479
|
+
);
|
|
56324
56480
|
return null;
|
|
56325
56481
|
}
|
|
56326
56482
|
const { device_code, user_code, verification_uri, expiresAt, interval } = deviceAuthorization;
|
|
@@ -56481,38 +56637,47 @@ async function wait(intervalMs) {
|
|
|
56481
56637
|
}
|
|
56482
56638
|
|
|
56483
56639
|
// src/util/env/challenge-recovery.ts
|
|
56640
|
+
var RECOVERABLE_CHALLENGE_CODES = /* @__PURE__ */ new Set([
|
|
56641
|
+
"challenge_required",
|
|
56642
|
+
"challenge_required_email_otp",
|
|
56643
|
+
"user_auth_required"
|
|
56644
|
+
]);
|
|
56484
56645
|
async function withEnvChallengeRecovery(client, fn) {
|
|
56646
|
+
const hadStoredSession = Boolean(
|
|
56647
|
+
client.authConfig.token || client.authConfig.refreshToken
|
|
56648
|
+
);
|
|
56485
56649
|
try {
|
|
56486
56650
|
return await fn();
|
|
56487
56651
|
} catch (error) {
|
|
56488
|
-
if (!isAPIError(error)
|
|
56652
|
+
if (!isAPIError(error)) {
|
|
56489
56653
|
throw error;
|
|
56490
56654
|
}
|
|
56491
|
-
const
|
|
56492
|
-
|
|
56655
|
+
const isRecoverableChallenge = RECOVERABLE_CHALLENGE_CODES.has(error.code);
|
|
56656
|
+
const isRejectedStoredSession = hadStoredSession && error.invalidToken === true;
|
|
56657
|
+
if (!isRecoverableChallenge && !isRejectedStoredSession) {
|
|
56658
|
+
throw error;
|
|
56659
|
+
}
|
|
56660
|
+
if (client.authConfig.tokenSource || !client.stdin.isTTY || client.nonInteractive) {
|
|
56493
56661
|
throw error;
|
|
56494
56662
|
}
|
|
56495
56663
|
output_manager_default.stopSpinner();
|
|
56496
56664
|
output_manager_default.log("Sensitive Environment Variables require fresh authentication.");
|
|
56665
|
+
const refreshToken = client.authConfig.refreshToken;
|
|
56497
56666
|
const acrValues = getAcrValuesFromWWWAuthenticate(error.wwwAuthenticate);
|
|
56498
|
-
|
|
56499
|
-
throw error;
|
|
56500
|
-
}
|
|
56501
|
-
const tokens = await performDeviceCodeFlow(client, {
|
|
56667
|
+
const tokens = isRecoverableChallenge && refreshToken && acrValues ? await performDeviceCodeFlow(client, {
|
|
56502
56668
|
refreshToken,
|
|
56503
|
-
acrValues
|
|
56504
|
-
|
|
56669
|
+
acrValues,
|
|
56670
|
+
fallbackToLoginOnStepUpFailure: true
|
|
56671
|
+
}) : await performDeviceCodeFlow(client);
|
|
56505
56672
|
if (!tokens) {
|
|
56506
56673
|
throw error;
|
|
56507
56674
|
}
|
|
56508
56675
|
client.updateAuthConfig({
|
|
56509
56676
|
token: tokens.access_token,
|
|
56510
56677
|
userId: void 0,
|
|
56511
|
-
expiresAt: Math.floor(Date.now() / 1e3) + tokens.expires_in
|
|
56678
|
+
expiresAt: Math.floor(Date.now() / 1e3) + tokens.expires_in,
|
|
56679
|
+
refreshToken: tokens.refresh_token
|
|
56512
56680
|
});
|
|
56513
|
-
if (tokens.refresh_token) {
|
|
56514
|
-
client.updateAuthConfig({ refreshToken: tokens.refresh_token });
|
|
56515
|
-
}
|
|
56516
56681
|
client.persistAuthConfig();
|
|
56517
56682
|
return await fn();
|
|
56518
56683
|
}
|
|
@@ -56804,6 +56969,7 @@ var listSubcommand = {
|
|
|
56804
56969
|
],
|
|
56805
56970
|
options: [
|
|
56806
56971
|
formatOption,
|
|
56972
|
+
jsonOption,
|
|
56807
56973
|
projectOption,
|
|
56808
56974
|
{
|
|
56809
56975
|
name: "guidance",
|
|
@@ -57215,13 +57381,6 @@ function getGlobalPathConfig2(argvSlice = process.argv.slice(2), cwd = process.c
|
|
|
57215
57381
|
// src/util/config/local-path.ts
|
|
57216
57382
|
import path2 from "path";
|
|
57217
57383
|
import { existsSync } from "fs";
|
|
57218
|
-
|
|
57219
|
-
// src/util/is-vercel-toml-enabled.ts
|
|
57220
|
-
function isVercelTomlEnabled() {
|
|
57221
|
-
return process.env.VERCEL_TOML_CONFIG_ENABLED === "1";
|
|
57222
|
-
}
|
|
57223
|
-
|
|
57224
|
-
// src/util/config/local-path.ts
|
|
57225
57384
|
function getLocalPathConfig(prefix) {
|
|
57226
57385
|
const argv = parseArguments(process.argv.slice(2), {}, { permissive: true });
|
|
57227
57386
|
const customPath = argv.flags["--local-config"];
|
|
@@ -57235,7 +57394,7 @@ function getLocalPathConfig(prefix) {
|
|
|
57235
57394
|
const vercelTomlPath = path2.join(prefix, "vercel.toml");
|
|
57236
57395
|
const nowConfigPath = path2.join(prefix, "now.json");
|
|
57237
57396
|
const vercelConfigExists = existsSync(vercelConfigPath);
|
|
57238
|
-
const vercelTomlExists =
|
|
57397
|
+
const vercelTomlExists = existsSync(vercelTomlPath);
|
|
57239
57398
|
const nowConfigExists = existsSync(nowConfigPath);
|
|
57240
57399
|
const foundConfigs = [];
|
|
57241
57400
|
if (vercelConfigExists)
|
|
@@ -57367,7 +57526,7 @@ function readLocalConfig(prefix = process.cwd()) {
|
|
|
57367
57526
|
} catch {
|
|
57368
57527
|
}
|
|
57369
57528
|
}
|
|
57370
|
-
if (!sourceFile
|
|
57529
|
+
if (!sourceFile) {
|
|
57371
57530
|
const tomlPath = join6(workPath, "vercel.toml");
|
|
57372
57531
|
try {
|
|
57373
57532
|
accessSync(tomlPath, constants.F_OK);
|
|
@@ -57998,7 +58157,7 @@ import { stat } from "fs/promises";
|
|
|
57998
58157
|
import { join as join9, dirname as dirname2 } from "path";
|
|
57999
58158
|
|
|
58000
58159
|
// src/util/projects/detect-services.ts
|
|
58001
|
-
var
|
|
58160
|
+
var import_fs_detectors3 = __toESM(require_dist6(), 1);
|
|
58002
58161
|
import { readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
|
|
58003
58162
|
import { basename as basename3, join as join8 } from "path";
|
|
58004
58163
|
import { parse as tomlParse, stringify as tomlStringify } from "smol-toml";
|
|
@@ -58030,6 +58189,7 @@ async function readFileSafe(file) {
|
|
|
58030
58189
|
// src/util/validate-config.ts
|
|
58031
58190
|
var import_routing_utils = __toESM(require_dist5(), 1);
|
|
58032
58191
|
var import_client2 = __toESM(require_dist7(), 1);
|
|
58192
|
+
var import_fs_detectors2 = __toESM(require_dist6(), 1);
|
|
58033
58193
|
import {
|
|
58034
58194
|
getFunctionsSchema,
|
|
58035
58195
|
buildsSchema,
|
|
@@ -58564,6 +58724,33 @@ var getServicesSchema = () => ({
|
|
|
58564
58724
|
},
|
|
58565
58725
|
additionalProperties: getServicesServiceConfigSchema()
|
|
58566
58726
|
});
|
|
58727
|
+
var proxySchema = {
|
|
58728
|
+
type: "object",
|
|
58729
|
+
additionalProperties: false,
|
|
58730
|
+
required: ["entrypoint"],
|
|
58731
|
+
properties: {
|
|
58732
|
+
entrypoint: {
|
|
58733
|
+
type: "string",
|
|
58734
|
+
minLength: 1
|
|
58735
|
+
},
|
|
58736
|
+
matcher: {
|
|
58737
|
+
oneOf: [
|
|
58738
|
+
{
|
|
58739
|
+
type: "string",
|
|
58740
|
+
minLength: 1
|
|
58741
|
+
},
|
|
58742
|
+
{
|
|
58743
|
+
type: "array",
|
|
58744
|
+
minItems: 1,
|
|
58745
|
+
items: {
|
|
58746
|
+
type: "string",
|
|
58747
|
+
minLength: 1
|
|
58748
|
+
}
|
|
58749
|
+
}
|
|
58750
|
+
]
|
|
58751
|
+
}
|
|
58752
|
+
}
|
|
58753
|
+
};
|
|
58567
58754
|
function buildVercelConfigSchema() {
|
|
58568
58755
|
return {
|
|
58569
58756
|
type: "object",
|
|
@@ -58582,6 +58769,7 @@ function buildVercelConfigSchema() {
|
|
|
58582
58769
|
images: imagesSchema,
|
|
58583
58770
|
crons: cronsSchema,
|
|
58584
58771
|
bunVersion: { type: "string" },
|
|
58772
|
+
proxy: proxySchema,
|
|
58585
58773
|
experimentalServices: getExperimentalServicesSchema(),
|
|
58586
58774
|
experimentalServiceGroups: experimentalServiceGroupsSchema,
|
|
58587
58775
|
services: getServicesSchema(),
|
|
@@ -58600,6 +58788,15 @@ function validateConfig(config3) {
|
|
|
58600
58788
|
return niceError;
|
|
58601
58789
|
}
|
|
58602
58790
|
}
|
|
58791
|
+
if (config3.proxy) {
|
|
58792
|
+
const proxyError = (0, import_fs_detectors2.validateProxyConfig)(config3.proxy);
|
|
58793
|
+
if (proxyError) {
|
|
58794
|
+
return new NowBuildError({
|
|
58795
|
+
code: proxyError.code.toUpperCase(),
|
|
58796
|
+
message: proxyError.message
|
|
58797
|
+
});
|
|
58798
|
+
}
|
|
58799
|
+
}
|
|
58603
58800
|
if (config3.functions && config3.builds) {
|
|
58604
58801
|
return new NowBuildError({
|
|
58605
58802
|
code: "FUNCTIONS_AND_BUILDS",
|
|
@@ -58607,6 +58804,12 @@ function validateConfig(config3) {
|
|
|
58607
58804
|
link: "https://vercel.link/functions-and-builds"
|
|
58608
58805
|
});
|
|
58609
58806
|
}
|
|
58807
|
+
if (config3.proxy && config3.builds) {
|
|
58808
|
+
return new NowBuildError({
|
|
58809
|
+
code: "PROXY_AND_BUILDS",
|
|
58810
|
+
message: "The `proxy` property cannot be used with the `builds` property. Remove `builds` to use an explicit proxy entrypoint."
|
|
58811
|
+
});
|
|
58812
|
+
}
|
|
58610
58813
|
const hasExperimentalServices = Boolean(config3.experimentalServices);
|
|
58611
58814
|
if (hasExperimentalServices && config3.builds) {
|
|
58612
58815
|
return new NowBuildError({
|
|
@@ -58754,8 +58957,8 @@ async function tryDetectServices(cwd) {
|
|
|
58754
58957
|
if (!isServicesEnabled) {
|
|
58755
58958
|
return null;
|
|
58756
58959
|
}
|
|
58757
|
-
const fs5 = new
|
|
58758
|
-
const result = await (0,
|
|
58960
|
+
const fs5 = new import_fs_detectors3.LocalFileSystemDetector(cwd);
|
|
58961
|
+
const result = await (0, import_fs_detectors3.detectServices)({
|
|
58759
58962
|
fs: fs5,
|
|
58760
58963
|
detectEntrypoint: createDetectEntrypoint(cwd)
|
|
58761
58964
|
});
|
|
@@ -58815,7 +59018,7 @@ function toProjectServicesConfigPatch(config3) {
|
|
|
58815
59018
|
async function prepareServicesConfigWrite(cwd, config3) {
|
|
58816
59019
|
const compileResult = await compileVercelConfig(cwd);
|
|
58817
59020
|
const configPath = join8(cwd, "vercel.json");
|
|
58818
|
-
if (
|
|
59021
|
+
if (compileResult.sourceFile === "vercel.toml") {
|
|
58819
59022
|
return prepareTomlServicesConfigWrite(join8(cwd, "vercel.toml"), config3);
|
|
58820
59023
|
}
|
|
58821
59024
|
if (compileResult.wasCompiled) {
|
|
@@ -58908,7 +59111,7 @@ async function findProjectRoot(startDir) {
|
|
|
58908
59111
|
}
|
|
58909
59112
|
const hasVercelDir = await (0, import_fs_extra7.pathExists)(join9(dir, ".vercel"));
|
|
58910
59113
|
const hasVercelJson = await (0, import_fs_extra7.pathExists)(join9(dir, "vercel.json"));
|
|
58911
|
-
const hasVercelToml =
|
|
59114
|
+
const hasVercelToml = await (0, import_fs_extra7.pathExists)(join9(dir, "vercel.toml"));
|
|
58912
59115
|
const hasGit = await (0, import_fs_extra7.pathExists)(join9(dir, ".git"));
|
|
58913
59116
|
if (hasVercelDir || hasVercelJson || hasVercelToml || hasGit) {
|
|
58914
59117
|
return dir;
|
|
@@ -59448,11 +59651,9 @@ async function findSourceVercelConfigFile(workPath) {
|
|
|
59448
59651
|
return basename4(configPath);
|
|
59449
59652
|
}
|
|
59450
59653
|
}
|
|
59451
|
-
|
|
59452
|
-
|
|
59453
|
-
|
|
59454
|
-
return "vercel.toml";
|
|
59455
|
-
}
|
|
59654
|
+
const tomlPath = join11(workPath, "vercel.toml");
|
|
59655
|
+
if (await fileExists(tomlPath)) {
|
|
59656
|
+
return "vercel.toml";
|
|
59456
59657
|
}
|
|
59457
59658
|
return null;
|
|
59458
59659
|
}
|
|
@@ -59496,7 +59697,7 @@ async function compileVercelConfig(workPath) {
|
|
|
59496
59697
|
const vercelTomlPath = join11(workPath, "vercel.toml");
|
|
59497
59698
|
const hasVercelJson = await fileExists(vercelJsonPath);
|
|
59498
59699
|
const hasNowJson = await fileExists(nowJsonPath);
|
|
59499
|
-
const hasVercelToml =
|
|
59700
|
+
const hasVercelToml = await fileExists(vercelTomlPath);
|
|
59500
59701
|
const vercelConfigPath = await findVercelConfigFile(workPath);
|
|
59501
59702
|
const vercelDir = join11(workPath, VERCEL_DIR);
|
|
59502
59703
|
const compiledConfigPath = join11(vercelDir, "vercel.json");
|
|
@@ -59675,7 +59876,7 @@ async function getVercelConfigPath(workPath) {
|
|
|
59675
59876
|
if (await fileExists(vercelJsonPath)) {
|
|
59676
59877
|
return vercelJsonPath;
|
|
59677
59878
|
}
|
|
59678
|
-
if (
|
|
59879
|
+
if (await fileExists(vercelTomlPath)) {
|
|
59679
59880
|
return vercelTomlPath;
|
|
59680
59881
|
}
|
|
59681
59882
|
if (await fileExists(compiledConfigPath)) {
|
|
@@ -59726,6 +59927,7 @@ export {
|
|
|
59726
59927
|
revocationRequest,
|
|
59727
59928
|
processRevocationResponse,
|
|
59728
59929
|
refreshTokenRequest,
|
|
59930
|
+
isOAuthError,
|
|
59729
59931
|
performDeviceCodeFlow,
|
|
59730
59932
|
login,
|
|
59731
59933
|
modify,
|
|
@@ -59789,7 +59991,6 @@ export {
|
|
|
59789
59991
|
pull,
|
|
59790
59992
|
envPullCommandLogic,
|
|
59791
59993
|
require_main,
|
|
59792
|
-
isVercelTomlEnabled,
|
|
59793
59994
|
normalizeConfig,
|
|
59794
59995
|
VERCEL_CONFIG_EXTENSIONS,
|
|
59795
59996
|
DEFAULT_VERCEL_CONFIG_FILENAME,
|
|
@@ -6,10 +6,10 @@ const __filename = __fileURLToPath(import.meta.url);
|
|
|
6
6
|
const __dirname = __dirname_(__filename);
|
|
7
7
|
import {
|
|
8
8
|
table
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LA3BQQQK.js";
|
|
10
10
|
import {
|
|
11
11
|
require_strip_ansi
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-RL7X7JGK.js";
|
|
13
13
|
import {
|
|
14
14
|
require_source
|
|
15
15
|
} from "./chunk-S7KYDPEM.js";
|
|
@@ -6,7 +6,7 @@ const __filename = __fileURLToPath(import.meta.url);
|
|
|
6
6
|
const __dirname = __dirname_(__filename);
|
|
7
7
|
import {
|
|
8
8
|
resolveAlertsScope
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-CXICXWXJ.js";
|
|
10
10
|
import {
|
|
11
11
|
handleValidationError,
|
|
12
12
|
outputError,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
AGENT_REASON,
|
|
17
17
|
buildCommandWithGlobalFlags,
|
|
18
18
|
outputAgentError
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-S7LXRKLD.js";
|
|
20
20
|
|
|
21
21
|
// src/commands/alerts/rules/parse-scope.ts
|
|
22
22
|
async function parseRulesFlagsAndScope(client, flags, jsonOutput, command = "alerts rules ls") {
|
|
@@ -6,12 +6,12 @@ const __filename = __fileURLToPath(import.meta.url);
|
|
|
6
6
|
const __dirname = __dirname_(__filename);
|
|
7
7
|
import {
|
|
8
8
|
getEnvTargetPlaceholder
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DKS4XDVC.js";
|
|
10
10
|
import {
|
|
11
11
|
packageName,
|
|
12
12
|
projectOption,
|
|
13
13
|
yesOption
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-U6PPDPR5.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/build/command.ts
|
|
17
17
|
var buildCommand = {
|