@vercel/client 18.2.2 → 18.2.5

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/types.d.ts CHANGED
@@ -196,6 +196,11 @@ export interface GitMetadata {
196
196
  commitSha?: string | undefined;
197
197
  dirty?: boolean | undefined;
198
198
  remoteUrl?: string;
199
+ /**
200
+ * Path of the deployed directory relative to the detected git repository
201
+ * root. Empty string when deploying from the repository root.
202
+ */
203
+ rootDirectory?: string;
199
204
  }
200
205
  /**
201
206
  * Options that will be sent to the API.
@@ -35,7 +35,17 @@ export interface PreparedFile {
35
35
  sha?: string;
36
36
  size?: number;
37
37
  mode: number;
38
+ data?: string;
39
+ encoding?: 'base64';
38
40
  }
41
+ /**
42
+ * Small all-static file sets are sent inline in the deployment creation
43
+ * request instead of as SHA references. This lets the API take its instant
44
+ * static fast path (deployment is READY in the create response, no build) —
45
+ * eligibility is decided entirely server-side, and ineligible deployments
46
+ * fall back to the regular build flow with no behavior change.
47
+ */
48
+ export declare function shouldInlineStaticFiles(files: FilesMap): boolean;
39
49
  export declare const prepareFiles: (files: FilesMap, clientOptions: VercelClientOptions) => PreparedFile[];
40
50
  export declare function createDebug(debug?: boolean): (...logs: string[]) => void;
41
51
  export type Debug = ReturnType<typeof createDebug>;
@@ -36,7 +36,8 @@ __export(utils_exports, {
36
36
  getApiDeploymentsUrl: () => getApiDeploymentsUrl,
37
37
  getVercelIgnore: () => getVercelIgnore,
38
38
  parseVercelConfig: () => parseVercelConfig,
39
- prepareFiles: () => prepareFiles
39
+ prepareFiles: () => prepareFiles,
40
+ shouldInlineStaticFiles: () => shouldInlineStaticFiles
40
41
  });
41
42
  module.exports = __toCommonJS(utils_exports);
42
43
  var import_path = require("path");
@@ -101,6 +102,24 @@ const maybeRead = async function(path, default_) {
101
102
  return default_;
102
103
  }
103
104
  };
105
+ async function getUserIgnore(cwd) {
106
+ const [vercelignore, nowignore] = await Promise.all([
107
+ maybeRead((0, import_path.join)(cwd, ".vercelignore"), ""),
108
+ maybeRead((0, import_path.join)(cwd, ".nowignore"), "")
109
+ ]);
110
+ if (vercelignore && nowignore) {
111
+ throw new import_build_utils.NowBuildError({
112
+ code: "CONFLICTING_IGNORE_FILES",
113
+ message: "Cannot use both a `.vercelignore` and `.nowignore` file. Please delete the `.nowignore` file.",
114
+ link: "https://vercel.link/combining-old-and-new-config"
115
+ });
116
+ }
117
+ const ignoreFile = vercelignore || nowignore;
118
+ if (!ignoreFile) {
119
+ return null;
120
+ }
121
+ return (0, import_ignore.default)().add(clearRelative(ignoreFile));
122
+ }
104
123
  async function buildFileTree(path, {
105
124
  isDirectory,
106
125
  prebuilt,
@@ -129,6 +148,7 @@ async function buildFileTree(path, {
129
148
  const vcConfigFilePaths = fileList.filter(
130
149
  (file) => (0, import_path.basename)(file) === ".vc-config.json"
131
150
  );
151
+ const userIg = await getUserIgnore(path);
132
152
  await Promise.all(
133
153
  vcConfigFilePaths.map(async (p) => {
134
154
  const configJson = await (0, import_fs_extra.readFile)(p, "utf8");
@@ -136,7 +156,21 @@ async function buildFileTree(path, {
136
156
  if (!config.filePathMap)
137
157
  return;
138
158
  for (const v of Object.values(config.filePathMap)) {
139
- refs.add((0, import_path.join)(path, v));
159
+ const absPath = (0, import_path.join)(path, v);
160
+ const rel = (0, import_path.relative)(path, absPath);
161
+ if (rel.startsWith("..") || (0, import_path.isAbsolute)(rel)) {
162
+ debug(
163
+ `Ignoring "filePathMap" entry "${v}": resolves outside the deployment root`
164
+ );
165
+ continue;
166
+ }
167
+ if (userIg && userIg.ignores(rel)) {
168
+ debug(
169
+ `Ignoring "filePathMap" entry "${v}": matched by a rule in .vercelignore/.nowignore`
170
+ );
171
+ continue;
172
+ }
173
+ refs.add(absPath);
140
174
  }
141
175
  })
142
176
  );
@@ -338,8 +372,33 @@ const fetchApi = async (url, token, opts = {}, debugEnabled) => {
338
372
  }
339
373
  };
340
374
  const isWin = process.platform.includes("win");
375
+ const INLINE_STATIC_EXTENSIONS = [".html", ".htm", ".md"];
376
+ const MAX_INLINE_FILES = 10;
377
+ const MAX_INLINE_TOTAL_BYTES = 5 * 1024 * 1024;
378
+ const S_IFREG = 32768;
379
+ const S_IFMT = 61440;
380
+ function shouldInlineStaticFiles(files) {
381
+ let count = 0;
382
+ let totalBytes = 0;
383
+ for (const file of files.values()) {
384
+ if ((file.mode & S_IFMT) !== S_IFREG)
385
+ return false;
386
+ if (!file.data)
387
+ return false;
388
+ for (const name of file.names) {
389
+ const lower = name.toLowerCase();
390
+ if (!INLINE_STATIC_EXTENSIONS.some((ext) => lower.endsWith(ext))) {
391
+ return false;
392
+ }
393
+ count += 1;
394
+ totalBytes += file.data.byteLength;
395
+ }
396
+ }
397
+ return count > 0 && count <= MAX_INLINE_FILES && totalBytes <= MAX_INLINE_TOTAL_BYTES;
398
+ }
341
399
  const prepareFiles = (files, clientOptions) => {
342
400
  const preparedFiles = [];
401
+ const inlineStaticFiles = shouldInlineStaticFiles(files);
343
402
  for (const [sha, file] of files) {
344
403
  for (const name of file.names) {
345
404
  let fileName;
@@ -349,8 +408,18 @@ const prepareFiles = (files, clientOptions) => {
349
408
  const segments = name.split(import_path.sep);
350
409
  fileName = segments[segments.length - 1];
351
410
  }
411
+ const normalizedName = isWin ? fileName.replace(/\\/g, "/") : fileName;
412
+ if (inlineStaticFiles && file.data) {
413
+ preparedFiles.push({
414
+ file: normalizedName,
415
+ data: file.data.toString("base64"),
416
+ encoding: "base64",
417
+ mode: file.mode
418
+ });
419
+ continue;
420
+ }
352
421
  preparedFiles.push({
353
- file: isWin ? fileName.replace(/\\/g, "/") : fileName,
422
+ file: normalizedName,
354
423
  size: file.data?.byteLength ?? file.size,
355
424
  mode: file.mode,
356
425
  sha: sha || void 0
@@ -380,5 +449,6 @@ function createDebug(debug) {
380
449
  getApiDeploymentsUrl,
381
450
  getVercelIgnore,
382
451
  parseVercelConfig,
383
- prepareFiles
452
+ prepareFiles,
453
+ shouldInlineStaticFiles
384
454
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/client",
3
- "version": "18.2.2",
3
+ "version": "18.2.5",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
6
6
  "homepage": "https://vercel.com",
@@ -37,9 +37,9 @@
37
37
  "querystring": "^0.2.0",
38
38
  "sleep-promise": "8.0.1",
39
39
  "tar-fs": "1.16.3",
40
- "@vercel/build-utils": "13.36.2",
41
- "@vercel/error-utils": "2.2.0",
42
- "@vercel/routing-utils": "6.4.0"
40
+ "@vercel/build-utils": "14.0.1",
41
+ "@vercel/error-utils": "2.2.1",
42
+ "@vercel/routing-utils": "6.4.1"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "node ../../utils/build.mjs",