@vercel/client 17.6.4 → 18.0.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/check-deployment-status.js +1 -2
- package/dist/continue.d.ts +2 -3
- package/dist/continue.js +5 -5
- package/dist/deploy.js +1 -1
- package/dist/types.d.ts +9 -2
- package/dist/upload.d.ts +2 -3
- package/dist/upload.js +27 -33
- package/dist/utils/index.d.ts +6 -3
- package/dist/utils/index.js +5 -2
- package/package.json +4 -6
|
@@ -146,8 +146,7 @@ async function* checkDeploymentStatus(deployment, clientOptions) {
|
|
|
146
146
|
{
|
|
147
147
|
apiUrl,
|
|
148
148
|
userAgent,
|
|
149
|
-
|
|
150
|
-
// node-fetch's bundled AbortSignal type predates the native one.
|
|
149
|
+
dispatcher: clientOptions.dispatcher,
|
|
151
150
|
signal: aliasAssignedSignal
|
|
152
151
|
}
|
|
153
152
|
);
|
package/dist/continue.d.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ArchiveFormat, DeploymentEventType } from './types';
|
|
1
|
+
import type { ArchiveFormat, DeploymentEventType, FetchDispatcher } from './types';
|
|
3
2
|
/**
|
|
4
3
|
* Continues a manual deployment by uploading build outputs and calling the
|
|
5
4
|
* continue endpoint. Waits for READY state unless the caller stops consuming
|
|
6
5
|
* events early.
|
|
7
6
|
*/
|
|
8
7
|
export declare function continueDeployment(options: {
|
|
9
|
-
|
|
8
|
+
dispatcher?: FetchDispatcher;
|
|
10
9
|
apiUrl?: string;
|
|
11
10
|
debug?: boolean;
|
|
12
11
|
deploymentId: string;
|
package/dist/continue.js
CHANGED
|
@@ -84,7 +84,7 @@ async function* continueDeployment(options) {
|
|
|
84
84
|
teamId: options.teamId,
|
|
85
85
|
apiUrl: options.apiUrl,
|
|
86
86
|
userAgent: options.userAgent,
|
|
87
|
-
|
|
87
|
+
dispatcher: options.dispatcher,
|
|
88
88
|
debug: options.debug
|
|
89
89
|
});
|
|
90
90
|
if (result.type === "missing_files") {
|
|
@@ -97,7 +97,7 @@ async function* continueDeployment(options) {
|
|
|
97
97
|
payload: { total: files, missing: result.missing, uploads }
|
|
98
98
|
};
|
|
99
99
|
for await (const event of (0, import_upload.uploadFiles)({
|
|
100
|
-
|
|
100
|
+
dispatcher: options.dispatcher,
|
|
101
101
|
apiUrl: options.apiUrl,
|
|
102
102
|
debug: options.debug,
|
|
103
103
|
teamId: options.teamId,
|
|
@@ -122,7 +122,7 @@ async function* continueDeployment(options) {
|
|
|
122
122
|
teamId: options.teamId,
|
|
123
123
|
apiUrl: options.apiUrl,
|
|
124
124
|
userAgent: options.userAgent,
|
|
125
|
-
|
|
125
|
+
dispatcher: options.dispatcher,
|
|
126
126
|
debug: options.debug
|
|
127
127
|
});
|
|
128
128
|
if (result.type === "missing_files") {
|
|
@@ -157,7 +157,7 @@ async function* continueDeployment(options) {
|
|
|
157
157
|
return yield { type: "alias-assigned", payload: deployment };
|
|
158
158
|
}
|
|
159
159
|
yield* (0, import_check_deployment_status.checkDeploymentStatus)(deployment, {
|
|
160
|
-
|
|
160
|
+
dispatcher: options.dispatcher,
|
|
161
161
|
apiUrl: options.apiUrl,
|
|
162
162
|
debug: options.debug,
|
|
163
163
|
path: options.path,
|
|
@@ -187,7 +187,7 @@ async function postContinue(options) {
|
|
|
187
187
|
}),
|
|
188
188
|
apiUrl: options.apiUrl,
|
|
189
189
|
userAgent: options.userAgent,
|
|
190
|
-
|
|
190
|
+
dispatcher: options.dispatcher
|
|
191
191
|
}
|
|
192
192
|
);
|
|
193
193
|
let result;
|
package/dist/deploy.js
CHANGED
|
@@ -56,7 +56,7 @@ async function* postDeployment(files, clientOptions, deploymentOptions) {
|
|
|
56
56
|
}),
|
|
57
57
|
apiUrl: clientOptions.apiUrl,
|
|
58
58
|
userAgent: clientOptions.userAgent,
|
|
59
|
-
|
|
59
|
+
dispatcher: clientOptions.dispatcher
|
|
60
60
|
}
|
|
61
61
|
);
|
|
62
62
|
let deployment = void 0;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import type { Agent } from 'http';
|
|
2
1
|
import type { Builder, BuilderFunctions, Images, ProjectSettings, Cron, ExperimentalServices, ExperimentalServiceGroups, ExperimentalServicesV2, Services } from '@vercel/build-utils';
|
|
3
2
|
import type { Header, Route, Redirect, Rewrite } from '@vercel/routing-utils';
|
|
4
3
|
export { DeploymentEventType } from './utils';
|
|
4
|
+
/**
|
|
5
|
+
* Minimal interface of an undici `Dispatcher` (e.g. `undici.ProxyAgent`),
|
|
6
|
+
* passed to `fetch` as the non-standard `dispatcher` init option to customize
|
|
7
|
+
* connection handling, such as routing requests through an HTTP(S) proxy.
|
|
8
|
+
*/
|
|
9
|
+
export interface FetchDispatcher {
|
|
10
|
+
dispatch(options: unknown, handler: unknown): boolean;
|
|
11
|
+
}
|
|
5
12
|
export interface Dictionary<T> {
|
|
6
13
|
[key: string]: T;
|
|
7
14
|
}
|
|
@@ -39,7 +46,7 @@ export interface VercelClientOptions {
|
|
|
39
46
|
isDirectory?: boolean;
|
|
40
47
|
skipAutoDetectionConfirmation?: boolean;
|
|
41
48
|
archive?: ArchiveFormat;
|
|
42
|
-
|
|
49
|
+
dispatcher?: FetchDispatcher;
|
|
43
50
|
projectName?: string;
|
|
44
51
|
/**
|
|
45
52
|
* Path to a file containing bulk redirects (relative to the project root).
|
package/dist/upload.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
2
|
import { DeploymentFile, FilesMap } from './utils/hashes';
|
|
3
|
-
import type {
|
|
4
|
-
import type { VercelClientOptions, DeploymentOptions, DeploymentEventType } from './types';
|
|
3
|
+
import type { FetchDispatcher, VercelClientOptions, DeploymentOptions, DeploymentEventType } from './types';
|
|
5
4
|
export declare function upload(files: FilesMap, clientOptions: VercelClientOptions, deploymentOptions: DeploymentOptions): AsyncIterableIterator<any>;
|
|
6
5
|
/**
|
|
7
6
|
* Uploads files to the /v2/files endpoint with retry and fault tolerance.
|
|
8
7
|
*/
|
|
9
8
|
export declare function uploadFiles(options: {
|
|
10
|
-
|
|
9
|
+
dispatcher?: FetchDispatcher;
|
|
11
10
|
apiUrl?: string;
|
|
12
11
|
debug?: boolean;
|
|
13
12
|
files: FilesMap;
|
package/dist/upload.js
CHANGED
|
@@ -33,8 +33,6 @@ __export(upload_exports, {
|
|
|
33
33
|
uploadFiles: () => uploadFiles
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(upload_exports);
|
|
36
|
-
var import_http = __toESM(require("http"));
|
|
37
|
-
var import_https = __toESM(require("https"));
|
|
38
36
|
var import_fs = require("fs");
|
|
39
37
|
var import_stream = require("stream");
|
|
40
38
|
var import_node_events = require("node:events");
|
|
@@ -44,10 +42,16 @@ var import_utils = require("./utils");
|
|
|
44
42
|
var import_errors = require("./errors");
|
|
45
43
|
var import_deploy = require("./deploy");
|
|
46
44
|
const isClientNetworkError = (err) => {
|
|
45
|
+
if (!(err instanceof Error)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
47
48
|
if (err.message) {
|
|
48
|
-
|
|
49
|
+
const matches = err.message.includes("ETIMEDOUT") || err.message.includes("ECONNREFUSED") || err.message.includes("ENOTFOUND") || err.message.includes("ECONNRESET") || err.message.includes("EAI_FAIL") || err.message.includes("socket hang up") || err.message.includes("network socket disconnected");
|
|
50
|
+
if (matches) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
49
53
|
}
|
|
50
|
-
return
|
|
54
|
+
return isClientNetworkError(err.cause);
|
|
51
55
|
};
|
|
52
56
|
async function* upload(files, clientOptions, deploymentOptions) {
|
|
53
57
|
const debug = (0, import_utils.createDebug)(clientOptions.debug);
|
|
@@ -83,7 +87,7 @@ async function* upload(files, clientOptions, deploymentOptions) {
|
|
|
83
87
|
payload: { total: files, missing: shas, uploads }
|
|
84
88
|
};
|
|
85
89
|
const uploadGenerator = uploadFiles({
|
|
86
|
-
|
|
90
|
+
dispatcher: clientOptions.dispatcher,
|
|
87
91
|
apiUrl: clientOptions.apiUrl,
|
|
88
92
|
debug: clientOptions.debug,
|
|
89
93
|
teamId: clientOptions.teamId,
|
|
@@ -121,7 +125,6 @@ async function* uploadFiles(options) {
|
|
|
121
125
|
const uploadList = {};
|
|
122
126
|
debug("Building an upload list...");
|
|
123
127
|
const semaphore = new import_async_sema.Sema(50, { capacity: 50 });
|
|
124
|
-
const defaultAgent = options.apiUrl?.startsWith("https://") ? new import_https.default.Agent({ keepAlive: true }) : new import_http.default.Agent({ keepAlive: true });
|
|
125
128
|
const abortControllers = /* @__PURE__ */ new Set();
|
|
126
129
|
let aborted = false;
|
|
127
130
|
options.shas.forEach((sha, index) => {
|
|
@@ -142,35 +145,27 @@ async function* uploadFiles(options) {
|
|
|
142
145
|
uploadProgress.bytesUploaded = 0;
|
|
143
146
|
let body;
|
|
144
147
|
let contentLength;
|
|
148
|
+
const counter = new import_stream.Transform({
|
|
149
|
+
transform(chunk, _encoding, callback) {
|
|
150
|
+
uploadProgress.bytesUploaded += chunk.length;
|
|
151
|
+
uploadProgress.emit("progress");
|
|
152
|
+
callback(null, chunk);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
145
155
|
if (typeof data !== "undefined") {
|
|
146
156
|
contentLength = data.length;
|
|
147
|
-
const buffered = new import_stream.Readable();
|
|
148
|
-
const originalRead = buffered.read.bind(buffered);
|
|
149
|
-
buffered.read = function(...args) {
|
|
150
|
-
const chunk = originalRead(...args);
|
|
151
|
-
if (chunk) {
|
|
152
|
-
uploadProgress.bytesUploaded += chunk.length;
|
|
153
|
-
uploadProgress.emit("progress");
|
|
154
|
-
}
|
|
155
|
-
return chunk;
|
|
156
|
-
};
|
|
157
157
|
const chunkSize = 16384;
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
function* chunks() {
|
|
159
|
+
for (let i = 0; i < data.length; i += chunkSize) {
|
|
160
|
+
yield data.slice(i, i + chunkSize);
|
|
161
|
+
}
|
|
161
162
|
}
|
|
162
|
-
buffered.
|
|
163
|
-
|
|
163
|
+
const buffered = import_stream.Readable.from(chunks());
|
|
164
|
+
buffered.on("error", (err2) => counter.destroy(err2));
|
|
165
|
+
body = buffered.pipe(counter);
|
|
164
166
|
} else if (typeof size === "number") {
|
|
165
167
|
contentLength = size;
|
|
166
168
|
const fileStream = (0, import_fs.createReadStream)(names[0]);
|
|
167
|
-
const counter = new import_stream.Transform({
|
|
168
|
-
transform(chunk, _encoding, callback) {
|
|
169
|
-
uploadProgress.bytesUploaded += chunk.length;
|
|
170
|
-
uploadProgress.emit("progress");
|
|
171
|
-
callback(null, chunk);
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
169
|
fileStream.on("error", (err2) => counter.destroy(err2));
|
|
175
170
|
counter.on("close", () => fileStream.destroy());
|
|
176
171
|
body = fileStream.pipe(counter);
|
|
@@ -187,19 +182,18 @@ async function* uploadFiles(options) {
|
|
|
187
182
|
import_utils.API_FILES,
|
|
188
183
|
options.token,
|
|
189
184
|
{
|
|
190
|
-
|
|
185
|
+
dispatcher: options.dispatcher,
|
|
191
186
|
method: "POST",
|
|
192
187
|
headers: {
|
|
193
188
|
"Content-Type": "application/octet-stream",
|
|
194
|
-
"Content-Length": contentLength,
|
|
189
|
+
"Content-Length": String(contentLength),
|
|
195
190
|
"x-now-digest": sha,
|
|
196
|
-
"x-now-size": contentLength
|
|
191
|
+
"x-now-size": String(contentLength)
|
|
197
192
|
},
|
|
198
193
|
body,
|
|
199
194
|
teamId: options.teamId,
|
|
200
195
|
apiUrl: options.apiUrl,
|
|
201
196
|
userAgent: options.userAgent,
|
|
202
|
-
// @ts-expect-error: typescript is getting confused with the signal types from node (web & server) and node-fetch (server only)
|
|
203
197
|
signal: abortController.signal
|
|
204
198
|
},
|
|
205
199
|
options.debug
|
|
@@ -226,7 +220,7 @@ async function* uploadFiles(options) {
|
|
|
226
220
|
} catch (e) {
|
|
227
221
|
debug(`An unexpected error occurred in upload promise:
|
|
228
222
|
${e}`);
|
|
229
|
-
err = new Error(e);
|
|
223
|
+
err = e instanceof Error ? e : new Error(String(e));
|
|
230
224
|
}
|
|
231
225
|
semaphore.release();
|
|
232
226
|
if (err) {
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FilesMap } from './hashes';
|
|
2
|
-
import {
|
|
2
|
+
import { Readable } from 'stream';
|
|
3
3
|
import ignore from 'ignore';
|
|
4
|
-
import { VercelClientOptions, VercelConfig } from '../types';
|
|
4
|
+
import { FetchDispatcher, VercelClientOptions, VercelConfig } from '../types';
|
|
5
5
|
type Ignore = ReturnType<typeof ignore>;
|
|
6
6
|
export declare const API_FILES = "/v2/files";
|
|
7
7
|
declare const EVENTS_ARRAY: readonly ["hashes-calculated", "file-count", "file-uploaded", "all-files-uploaded", "created", "building", "ready", "alias-assigned", "warning", "error", "notice", "tip", "canceled", "checks-registered", "checks-completed", "checks-running", "checks-conclusion-succeeded", "checks-conclusion-failed", "checks-conclusion-skipped", "checks-conclusion-canceled", "checks-v2-failed"];
|
|
@@ -17,7 +17,8 @@ export declare function getVercelIgnore(cwd: string | string[], prebuilt?: boole
|
|
|
17
17
|
ig: Ignore;
|
|
18
18
|
ignores: string[];
|
|
19
19
|
}>;
|
|
20
|
-
|
|
20
|
+
type NativeRequestInit = NonNullable<Parameters<typeof globalThis.fetch>[1]>;
|
|
21
|
+
interface FetchOpts extends Omit<NativeRequestInit, 'body' | 'headers' | 'dispatcher'> {
|
|
21
22
|
apiUrl?: string;
|
|
22
23
|
method?: string;
|
|
23
24
|
teamId?: string;
|
|
@@ -25,6 +26,8 @@ interface FetchOpts extends RequestInit {
|
|
|
25
26
|
[key: string]: any;
|
|
26
27
|
};
|
|
27
28
|
userAgent?: string;
|
|
29
|
+
body?: NonNullable<NativeRequestInit['body']> | Buffer | Readable;
|
|
30
|
+
dispatcher?: FetchDispatcher;
|
|
28
31
|
}
|
|
29
32
|
export declare const fetchApi: (url: string, token: string, opts?: FetchOpts, debugEnabled?: boolean) => Promise<any>;
|
|
30
33
|
export interface PreparedFile {
|
package/dist/utils/index.js
CHANGED
|
@@ -39,8 +39,8 @@ __export(utils_exports, {
|
|
|
39
39
|
prepareFiles: () => prepareFiles
|
|
40
40
|
});
|
|
41
41
|
module.exports = __toCommonJS(utils_exports);
|
|
42
|
-
var import_node_fetch = __toESM(require("node-fetch"));
|
|
43
42
|
var import_path = require("path");
|
|
43
|
+
var import_stream = require("stream");
|
|
44
44
|
var import_url = require("url");
|
|
45
45
|
var import_ignore = __toESM(require("ignore"));
|
|
46
46
|
var import_pkg = require("../pkg");
|
|
@@ -320,10 +320,13 @@ const fetchApi = async (url, token, opts = {}, debugEnabled) => {
|
|
|
320
320
|
accept: "application/json",
|
|
321
321
|
"user-agent": userAgent
|
|
322
322
|
};
|
|
323
|
+
if (opts.body instanceof import_stream.Readable) {
|
|
324
|
+
opts.duplex = "half";
|
|
325
|
+
}
|
|
323
326
|
debug(`${opts.method || "GET"} ${url}`);
|
|
324
327
|
time = Date.now();
|
|
325
328
|
try {
|
|
326
|
-
const res = await (
|
|
329
|
+
const res = await fetch(url, opts);
|
|
327
330
|
debug(`DONE in ${Date.now() - time}ms: ${opts.method || "GET"} ${url}`);
|
|
328
331
|
return res;
|
|
329
332
|
} finally {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/client",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "18.0.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"typings": "dist/index.d.ts",
|
|
6
6
|
"homepage": "https://vercel.com",
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
"@types/minimatch": "3.0.5",
|
|
23
23
|
"@types/ms": "0.7.30",
|
|
24
24
|
"@types/node": "20.11.0",
|
|
25
|
-
"@types/node-fetch": "2.5.4",
|
|
26
25
|
"@types/recursive-readdir": "2.2.0",
|
|
27
26
|
"@types/tar-fs": "1.16.1",
|
|
28
27
|
"vitest": "2.0.1"
|
|
@@ -35,13 +34,12 @@
|
|
|
35
34
|
"ignore": "4.0.6",
|
|
36
35
|
"minimatch": "5.0.1",
|
|
37
36
|
"ms": "2.1.2",
|
|
38
|
-
"node-fetch": "2.6.7",
|
|
39
37
|
"querystring": "^0.2.0",
|
|
40
38
|
"sleep-promise": "8.0.1",
|
|
41
39
|
"tar-fs": "1.16.3",
|
|
42
|
-
"@vercel/
|
|
43
|
-
"@vercel/
|
|
44
|
-
"@vercel/
|
|
40
|
+
"@vercel/error-utils": "2.2.0",
|
|
41
|
+
"@vercel/build-utils": "13.33.1",
|
|
42
|
+
"@vercel/routing-utils": "6.4.0"
|
|
45
43
|
},
|
|
46
44
|
"scripts": {
|
|
47
45
|
"build": "node ../../utils/build.mjs",
|