netlify-cli 27.11.2 → 27.12.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.
@@ -4,7 +4,7 @@ import type { $TSFixMe } from '../commands/types.js';
4
4
  import { type NormalizedCachedConfigConfig } from './command-helpers.js';
5
5
  import type { ServerSettings, SiteInfo } from './types.js';
6
6
  export declare const getProxyUrl: (settings: Pick<ServerSettings, 'https' | 'port'>) => string;
7
- export declare const startProxy: ({ accountId, addonsUrls, aiGatewayContext, api, blobsContext, command, config, configPath, debug, disableEdgeFunctions, env, functionsRegistry, geoCountry, geolocationMode, getUpdatedConfig, inspectSettings, offline, projectDir, repositoryRoot, settings, siteInfo, state, watchIgnore, deployEnvironment, }: {
7
+ export declare const startProxy: ({ accountId, aiGatewayContext, api, blobsContext, command, config, configPath, debug, disableEdgeFunctions, env, functionsRegistry, geoCountry, geolocationMode, getUpdatedConfig, inspectSettings, offline, projectDir, repositoryRoot, settings, siteInfo, state, watchIgnore, deployEnvironment, }: {
8
8
  command: BaseCommand;
9
9
  config: NormalizedCachedConfigConfig;
10
10
  settings: ServerSettings;
@@ -15,7 +15,7 @@ import { FileWatcher, fromWebResponse, mockLocation, renderFunctionErrorPage } f
15
15
  import { ImageHandler } from '@netlify/images';
16
16
  import { ServerHandler } from '@netlify/server-dev';
17
17
  import { runBeforeProcessExit } from './shell.js';
18
- import contentType from 'content-type';
18
+ import { parse as parseContentType } from 'content-type';
19
19
  import generateETag from 'etag';
20
20
  import getAvailablePort from 'get-port';
21
21
  import httpProxy from 'http-proxy';
@@ -99,18 +99,13 @@ function isInternal(url) {
99
99
  function isFunction(functionsPort, url) {
100
100
  return functionsPort && url.match(DEFAULT_FUNCTION_URL_EXPRESSION);
101
101
  }
102
- function getAddonUrl(addonsUrls, req) {
103
- const matches = req.url?.match(/^\/.netlify\/([^/]+)(\/.*)/);
104
- const addonUrl = matches && addonsUrls[matches[1]];
105
- return addonUrl ? `${addonUrl}${matches[2]}` : null;
106
- }
107
102
  const getStatic = async function (pathname, publicFolder) {
108
103
  const alternatives = [pathname, ...alternativePathsFor(pathname)].map((filePath) => path.resolve(publicFolder, filePath.slice(1)));
109
104
  const file = await locatePath(alternatives);
110
105
  if (file === undefined) {
111
106
  return false;
112
107
  }
113
- return `/${path.relative(publicFolder, file)}`;
108
+ return `/${path.relative(publicFolder, file).split(path.sep).join('/')}`;
114
109
  };
115
110
  const isEndpointExists = async function (endpoint, origin) {
116
111
  const url = new URL(endpoint, origin);
@@ -137,12 +132,6 @@ const proxyToExternalUrl = function ({ dest, destURL, req, res, }) {
137
132
  });
138
133
  void handler(req, res, () => { });
139
134
  };
140
- // @ts-expect-error TS(7031) FIXME: Binding element 'addonUrl' implicitly has an 'any'... Remove this comment to see the full error message
141
- const handleAddonUrl = function ({ addonUrl, req, res }) {
142
- const dest = new URL(addonUrl);
143
- const destURL = stripOrigin(dest);
144
- proxyToExternalUrl({ req, res, dest, destURL });
145
- };
146
135
  const isRedirect = function (match) {
147
136
  return 'status' in match && match.status != null && match.status >= 300 && match.status <= 400;
148
137
  };
@@ -218,11 +207,6 @@ const serveRedirect = async function ({ env, functionsRegistry, imageProxy, matc
218
207
  if (isFunction(options.functionsPort, req.url)) {
219
208
  return proxy.web(req, res, { target: options.functionsServer });
220
209
  }
221
- const urlForAddons = getAddonUrl(options.addonsUrls, req);
222
- if (urlForAddons) {
223
- handleAddonUrl({ req, res, addonUrl: urlForAddons });
224
- return;
225
- }
226
210
  const originalURL = req.url;
227
211
  const reqUrl = reqToURL(req, req.url);
228
212
  const isHiddenProxy = match.proxyHeaders &&
@@ -277,7 +261,7 @@ const serveRedirect = async function ({ env, functionsRegistry, imageProxy, matc
277
261
  res.end(`Redirecting to ${destURL}`);
278
262
  return;
279
263
  }
280
- const ct = req.headers['content-type'] ? contentType.parse(req).type : '';
264
+ const ct = parseContentType(req.headers['content-type'] ?? '').type;
281
265
  if (req.method === 'POST' &&
282
266
  !isInternal(req.url) &&
283
267
  !isInternal(destURL) &&
@@ -310,11 +294,6 @@ const serveRedirect = async function ({ env, functionsRegistry, imageProxy, matc
310
294
  if (isImageRequest(req)) {
311
295
  return imageProxy(req, res);
312
296
  }
313
- const addonUrl = getAddonUrl(options.addonsUrls, req);
314
- if (addonUrl) {
315
- handleAddonUrl({ req, res, addonUrl });
316
- return;
317
- }
318
297
  return proxy.web(req, res, { ...options, status: statusValue });
319
298
  }
320
299
  return proxy.web(req, res, options);
@@ -436,7 +415,7 @@ const initializeProxy = async function ({ config, configPath, distDir, env, host
436
415
  // The request has failed but we might still have a matching redirect
437
416
  // rule (without `force`) that should kick in. This is how we mimic the
438
417
  // file shadowing behavior from the CDN.
439
- if (options && options.match) {
418
+ if (options?.match) {
440
419
  return serveRedirect({
441
420
  // We don't want to match functions at this point because any redirects
442
421
  // to functions will have already been processed, so we don't supply a
@@ -568,7 +547,7 @@ const initializeProxy = async function ({ config, configPath, distDir, env, host
568
547
  };
569
548
  return handlers;
570
549
  };
571
- const onRequest = async ({ addonsUrls, api, edgeFunctionsProxy, env, functionsRegistry, functionsServer, imageProxy, proxy, rewriter, serverHandler, settings, siteInfo, }, req, res) => {
550
+ const onRequest = async ({ api, edgeFunctionsProxy, env, functionsRegistry, functionsServer, imageProxy, proxy, rewriter, serverHandler, settings, siteInfo, }, req, res) => {
572
551
  req.originalBody =
573
552
  req.method && ['GET', 'OPTIONS', 'HEAD'].includes(req.method) ? null : await createStreamPromise(req, BYTES_LIMIT);
574
553
  if (isImageRequest(req)) {
@@ -592,11 +571,6 @@ const onRequest = async ({ addonsUrls, api, edgeFunctionsProxy, env, functionsRe
592
571
  }
593
572
  return proxy.web(req, res, { headers, target: functionsServer });
594
573
  }
595
- const addonUrl = getAddonUrl(addonsUrls, req);
596
- if (addonUrl) {
597
- handleAddonUrl({ req, res, addonUrl });
598
- return;
599
- }
600
574
  if (serverHandler) {
601
575
  try {
602
576
  const requestURL = reqToURL(req, req.url);
@@ -634,7 +608,6 @@ const onRequest = async ({ addonsUrls, api, edgeFunctionsProxy, env, functionsRe
634
608
  const match = await rewriter(req);
635
609
  const options = {
636
610
  match,
637
- addonsUrls,
638
611
  target: `http://${settings.frameworkHost && isIPv6(settings.frameworkHost) ? `[${settings.frameworkHost}]` : settings.frameworkHost}:${settings.frameworkPort}`,
639
612
  detectTarget: settings.detectFrameworkHost,
640
613
  targetHostname: settings.frameworkHost,
@@ -668,7 +641,7 @@ const onRequest = async ({ addonsUrls, api, edgeFunctionsProxy, env, functionsRe
668
641
  // @ts-expect-error TS(7031) FIXME: Binding element 'statusCode' implicitly has an 'an... Remove this comment to see the full error message
669
642
  req[shouldGenerateETag] = ({ statusCode }) => statusCode >= 200 && statusCode < 300;
670
643
  const hasFormSubmissionHandler = functionsRegistry && getFormHandler({ functionsRegistry, logWarning: false });
671
- const ct = req.headers['content-type'] ? contentType.parse(req).type : '';
644
+ const ct = parseContentType(req.headers['content-type'] ?? '').type;
672
645
  if (hasFormSubmissionHandler &&
673
646
  functionsServer &&
674
647
  req.method === 'POST' &&
@@ -683,7 +656,7 @@ export const getProxyUrl = function (settings) {
683
656
  const scheme = settings.https ? 'https' : 'http';
684
657
  return `${scheme}://localhost:${settings.port}`;
685
658
  };
686
- export const startProxy = async function ({ accountId, addonsUrls, aiGatewayContext, api, blobsContext, command, config, configPath, debug, disableEdgeFunctions, env, functionsRegistry, geoCountry, geolocationMode, getUpdatedConfig, inspectSettings, offline, projectDir, repositoryRoot, settings, siteInfo, state, watchIgnore, deployEnvironment, }) {
659
+ export const startProxy = async function ({ accountId, aiGatewayContext, api, blobsContext, command, config, configPath, debug, disableEdgeFunctions, env, functionsRegistry, geoCountry, geolocationMode, getUpdatedConfig, inspectSettings, offline, projectDir, repositoryRoot, settings, siteInfo, state, watchIgnore, deployEnvironment, }) {
687
660
  const secondaryServerPort = settings.https ? await getAvailablePort() : null;
688
661
  const functionsServer = settings.functionsPort ? `http://127.0.0.1:${settings.functionsPort}` : null;
689
662
  let edgeFunctionsProxy;
@@ -767,7 +740,6 @@ export const startProxy = async function ({ accountId, addonsUrls, aiGatewayCont
767
740
  rewriter,
768
741
  serverHandler,
769
742
  settings,
770
- addonsUrls,
771
743
  functionsRegistry,
772
744
  functionsServer,
773
745
  edgeFunctionsProxy,
@@ -196,7 +196,7 @@ export type MinimalAccount = {
196
196
  members_count: number;
197
197
  };
198
198
  type EnvironmentVariableScope = 'builds' | 'functions' | 'runtime' | 'post_processing';
199
- export type EnvironmentVariableSource = 'account' | 'addons' | 'configFile' | 'general' | 'internal' | 'ui';
199
+ export type EnvironmentVariableSource = 'account' | 'configFile' | 'general' | 'internal' | 'ui';
200
200
  export type EnvironmentVariables = Record<string, {
201
201
  sources: EnvironmentVariableSource[];
202
202
  value: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "netlify-cli",
3
- "version": "27.11.2",
3
+ "version": "27.12.0",
4
4
  "description": "Netlify command line tool",
5
5
  "keywords": [
6
6
  "api",
@@ -63,14 +63,14 @@
63
63
  "@netlify/dev": "^5.1.6",
64
64
  "@netlify/dev-utils": "^6.0.3",
65
65
  "@netlify/edge-bundler": "^16.1.2",
66
- "@netlify/edge-functions": "^4.0.0",
66
+ "@netlify/edge-functions": "^4.0.2",
67
67
  "@netlify/edge-functions-bootstrap": "^3.2.0",
68
68
  "@netlify/headers-parser": "^10.1.1",
69
- "@netlify/images": "^2.0.1",
69
+ "@netlify/images": "^2.0.3",
70
70
  "@netlify/local-functions-proxy": "^2.0.3",
71
71
  "@netlify/redirect-matcher": "^0.4.2",
72
72
  "@netlify/redirect-parser": "^16.1.1",
73
- "@netlify/server-dev": "^0.1.1",
73
+ "@netlify/server-dev": "^0.1.3",
74
74
  "@netlify/zip-it-and-ship-it": "^16.3.0",
75
75
  "@opentelemetry/api": "~1.9.0",
76
76
  "@pnpm/tabtab": "^0.5.4",
@@ -85,7 +85,7 @@
85
85
  "clean-deep": "^3.4.0",
86
86
  "commander": "^12.1.0",
87
87
  "comment-json": "^5.0.0",
88
- "content-type": "^1.0.5",
88
+ "content-type": "^3.1.1",
89
89
  "cookie": "^2.0.0",
90
90
  "cron-parser": "^5.0.0",
91
91
  "debug": "^4.4.3",
@@ -153,12 +153,11 @@
153
153
  "@eslint/compat": "^1.4.1",
154
154
  "@eslint/js": "^9.36.0",
155
155
  "@netlify/functions": "^6.0.0",
156
- "@netlify/types": "^3.0.0",
156
+ "@netlify/types": "^3.2.0",
157
157
  "@sindresorhus/slugify": "^3.0.0",
158
158
  "@tsconfig/node22": "22.0.5",
159
159
  "@tsconfig/recommended": "^1.0.13",
160
160
  "@types/backoff": "^2.5.5",
161
- "@types/content-type": "^1.1.9",
162
161
  "@types/debug": "^4.1.12",
163
162
  "@types/envinfo": "^7.8.4",
164
163
  "@types/eslint-config-prettier": "^6.11.3",
@@ -183,7 +182,7 @@
183
182
  "@types/write-file-atomic": "^4.0.3",
184
183
  "@types/ws": "^8.18.1",
185
184
  "@types/yauzl": "^2.10.3",
186
- "@vitest/coverage-v8": "^3.2.4",
185
+ "@vitest/coverage-v8": "^4.1.11",
187
186
  "@vitest/eslint-plugin": "1.3.13",
188
187
  "c8": "^10.1.3",
189
188
  "cheerio": "^1.1.2",
@@ -197,7 +196,7 @@
197
196
  "memfs": "^4.56.10",
198
197
  "nock": "^14.0.10",
199
198
  "npm-run-all2": "^8.0.4",
200
- "oxfmt": "0.61.0",
199
+ "oxfmt": "0.72.0",
201
200
  "p-timeout": "^7.0.0",
202
201
  "picomatch": "^4.0.4",
203
202
  "pkg-pr-new": "^0.0.86",
@@ -211,7 +210,7 @@
211
210
  "typescript-eslint": "~8.65.0",
212
211
  "typescript-native": "npm:typescript@~7.0.2",
213
212
  "verdaccio": "^6.3.2",
214
- "vitest": "^3.2.4"
213
+ "vitest": "^4.1.11"
215
214
  },
216
215
  "engines": {
217
216
  "node": ">=22.13.0"
@@ -1,13 +0,0 @@
1
- export declare const getCurrentAddon: ({ addonName, addons }: {
2
- addonName: any;
3
- addons: any;
4
- }) => any;
5
- export declare const getSiteData: ({ api, siteId }: {
6
- api: any;
7
- siteId: any;
8
- }) => Promise<any>;
9
- export declare const getAddons: ({ api, siteId }: {
10
- api: any;
11
- siteId: any;
12
- }) => Promise<any>;
13
- //# sourceMappingURL=prepare.d.ts.map
@@ -1,26 +0,0 @@
1
- import { logAndThrowError } from '../command-helpers.js';
2
- // @ts-expect-error TS(7031) FIXME: Binding element 'addonName' implicitly has an 'any... Remove this comment to see the full error message
3
- export const getCurrentAddon = ({ addonName, addons }) => addons.find((addon) => addon.service_slug === addonName);
4
- // @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
5
- export const getSiteData = async ({ api, siteId }) => {
6
- let siteData;
7
- try {
8
- siteData = await api.getSite({ siteId });
9
- }
10
- catch (error_) {
11
- return logAndThrowError(`Failed getting list of project data: ${error_.message}`);
12
- }
13
- return siteData;
14
- };
15
- // @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message
16
- export const getAddons = async ({ api, siteId }) => {
17
- let addons;
18
- try {
19
- addons = await api.listServiceInstancesForSite({ siteId });
20
- }
21
- catch (error_) {
22
- return logAndThrowError(`Failed getting list of addons: ${error_.message}`);
23
- }
24
- return addons;
25
- };
26
- //# sourceMappingURL=prepare.js.map