netlify-cli 27.6.0 → 27.8.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/utils/login-url.js
CHANGED
|
@@ -2,7 +2,12 @@ import { getDrivingAgent } from './agent-detection.js';
|
|
|
2
2
|
// By contract these two hold only a non-sensitive agent name[@version]. Every other marker's value is a flag,
|
|
3
3
|
// a session or run id, or a path, none of which may reach a URL.
|
|
4
4
|
const SOURCES_WITH_ANNOUNCED_VALUE = new Set(['NETLIFY_AGENT', 'AI_AGENT']);
|
|
5
|
+
const LOGIN_SOURCES = new Set(['mcp']);
|
|
5
6
|
const sanitizeUtmTerm = (raw) => raw.replace(/[^A-Za-z0-9_.:@-]/g, '').slice(0, 64);
|
|
7
|
+
const getUtmSource = (env) => {
|
|
8
|
+
const source = env.NETLIFY_LOGIN_SOURCE;
|
|
9
|
+
return source !== undefined && LOGIN_SOURCES.has(source) ? source : 'cli';
|
|
10
|
+
};
|
|
6
11
|
const getUtmTerm = (source, env) => {
|
|
7
12
|
const value = SOURCES_WITH_ANNOUNCED_VALUE.has(source) ? env[source] : undefined;
|
|
8
13
|
return sanitizeUtmTerm(value ? `${source}:${value}` : source);
|
|
@@ -12,7 +17,7 @@ export const buildAuthorizeUrl = (ticketId, env = process.env) => {
|
|
|
12
17
|
const params = new URLSearchParams({
|
|
13
18
|
response_type: 'ticket',
|
|
14
19
|
ticket: ticketId,
|
|
15
|
-
utm_source:
|
|
20
|
+
utm_source: getUtmSource(env),
|
|
16
21
|
utm_campaign: 'integrations',
|
|
17
22
|
});
|
|
18
23
|
const agent = getDrivingAgent(env);
|
|
@@ -4,7 +4,7 @@ import type { $TSFixMe, NetlifyOptions } from '../commands/types.js';
|
|
|
4
4
|
import type { BlobsContextWithEdgeAccess } from '../lib/blobs/blobs.js';
|
|
5
5
|
import type { FunctionsRegistry } from '../lib/functions/registry.js';
|
|
6
6
|
import { type NormalizedCachedConfigConfig } from './command-helpers.js';
|
|
7
|
-
import type { LocalState } from './types.js';
|
|
7
|
+
import type { LocalState, SiteInfo } from './types.js';
|
|
8
8
|
import type { ServerSettings } from './types.js';
|
|
9
9
|
interface InspectSettings {
|
|
10
10
|
enabled: boolean;
|
|
@@ -31,7 +31,7 @@ export declare const startProxyServer: ({ accountId, addonsUrls, aiGatewayContex
|
|
|
31
31
|
settings: ServerSettings;
|
|
32
32
|
offline: boolean;
|
|
33
33
|
site: $TSFixMe;
|
|
34
|
-
siteInfo:
|
|
34
|
+
siteInfo: SiteInfo;
|
|
35
35
|
projectDir: string;
|
|
36
36
|
repositoryRoot?: string;
|
|
37
37
|
state: LocalState;
|
package/dist/utils/proxy.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { AIGatewayContext } from '@netlify/ai/bootstrap';
|
|
|
2
2
|
import type { BaseCommand } from '../commands/index.js';
|
|
3
3
|
import type { $TSFixMe } from '../commands/types.js';
|
|
4
4
|
import { type NormalizedCachedConfigConfig } from './command-helpers.js';
|
|
5
|
-
import type { ServerSettings } from './types.js';
|
|
5
|
+
import type { ServerSettings, SiteInfo } from './types.js';
|
|
6
6
|
export declare const getProxyUrl: (settings: Pick<ServerSettings, 'https' | 'port'>) => string;
|
|
7
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, }: {
|
|
8
8
|
command: BaseCommand;
|
|
@@ -11,6 +11,7 @@ export declare const startProxy: ({ accountId, addonsUrls, aiGatewayContext, api
|
|
|
11
11
|
disableEdgeFunctions: boolean;
|
|
12
12
|
getUpdatedConfig: () => Promise<NormalizedCachedConfigConfig>;
|
|
13
13
|
aiGatewayContext?: AIGatewayContext | null;
|
|
14
|
+
siteInfo?: SiteInfo;
|
|
14
15
|
watchIgnore: string[];
|
|
15
16
|
deployEnvironment: {
|
|
16
17
|
key: string;
|
package/dist/utils/proxy.js
CHANGED
|
@@ -11,8 +11,10 @@ import process from 'process';
|
|
|
11
11
|
import url from 'url';
|
|
12
12
|
import util from 'util';
|
|
13
13
|
import zlib from 'zlib';
|
|
14
|
-
import { renderFunctionErrorPage } from '@netlify/dev-utils';
|
|
14
|
+
import { FileWatcher, fromWebResponse, mockLocation, renderFunctionErrorPage } from '@netlify/dev-utils';
|
|
15
15
|
import { ImageHandler } from '@netlify/images';
|
|
16
|
+
import { ServerHandler } from '@netlify/server-dev';
|
|
17
|
+
import { runBeforeProcessExit } from './shell.js';
|
|
16
18
|
import contentType from 'content-type';
|
|
17
19
|
import { parseCookie } from 'cookie';
|
|
18
20
|
import { getProperty } from 'dot-prop';
|
|
@@ -607,7 +609,7 @@ const initializeProxy = async function ({ config, configPath, distDir, env, host
|
|
|
607
609
|
};
|
|
608
610
|
return handlers;
|
|
609
611
|
};
|
|
610
|
-
const onRequest = async ({ addonsUrls, api, edgeFunctionsProxy, env, functionsRegistry, functionsServer, imageProxy, proxy, rewriter, settings, siteInfo, }, req, res) => {
|
|
612
|
+
const onRequest = async ({ addonsUrls, api, edgeFunctionsProxy, env, functionsRegistry, functionsServer, imageProxy, proxy, rewriter, serverHandler, settings, siteInfo, }, req, res) => {
|
|
611
613
|
req.originalBody =
|
|
612
614
|
req.method && ['GET', 'OPTIONS', 'HEAD'].includes(req.method) ? null : await createStreamPromise(req, BYTES_LIMIT);
|
|
613
615
|
if (isImageRequest(req)) {
|
|
@@ -636,6 +638,40 @@ const onRequest = async ({ addonsUrls, api, edgeFunctionsProxy, env, functionsRe
|
|
|
636
638
|
handleAddonUrl({ req, res, addonUrl });
|
|
637
639
|
return;
|
|
638
640
|
}
|
|
641
|
+
if (serverHandler) {
|
|
642
|
+
try {
|
|
643
|
+
const requestURL = reqToURL(req, req.url);
|
|
644
|
+
const serverMatch = await serverHandler.match(new Request(requestURL));
|
|
645
|
+
if (serverMatch) {
|
|
646
|
+
const staticFile = await getStatic(decodeURIComponent(requestURL.pathname), settings.dist ?? '');
|
|
647
|
+
if (!staticFile) {
|
|
648
|
+
const headers = new Headers();
|
|
649
|
+
for (let index = 0; index < req.rawHeaders.length; index += 2) {
|
|
650
|
+
headers.append(req.rawHeaders[index], req.rawHeaders[index + 1]);
|
|
651
|
+
}
|
|
652
|
+
const response = await serverMatch.handle(new Request(requestURL, {
|
|
653
|
+
body: req.originalBody,
|
|
654
|
+
headers,
|
|
655
|
+
method: req.method,
|
|
656
|
+
}));
|
|
657
|
+
await fromWebResponse(response, res);
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
catch (error) {
|
|
663
|
+
// The response may have failed mid-stream, in which case the head is
|
|
664
|
+
// out and the only remaining option is dropping the connection.
|
|
665
|
+
if (res.headersSent) {
|
|
666
|
+
res.destroy();
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
669
|
+
res.writeHead(500);
|
|
670
|
+
res.end(error instanceof Error ? error.message : 'Failed to serve request from Netlify Server');
|
|
671
|
+
}
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
639
675
|
const match = await rewriter(req);
|
|
640
676
|
const options = {
|
|
641
677
|
match,
|
|
@@ -725,6 +761,24 @@ export const startProxy = async function ({ accountId, addonsUrls, aiGatewayCont
|
|
|
725
761
|
logger: { log, warn, error: logError },
|
|
726
762
|
imagesConfig: config.images,
|
|
727
763
|
});
|
|
764
|
+
const serverEntryEnabled = process.env.EXPERIMENTAL_NETLIFY_SERVER === 'true' || Boolean(siteInfo?.feature_flags?.netlify_build_server_entry);
|
|
765
|
+
let serverHandler;
|
|
766
|
+
if (serverEntryEnabled) {
|
|
767
|
+
const serverFileWatcher = new FileWatcher();
|
|
768
|
+
serverHandler = new ServerHandler({
|
|
769
|
+
accountID: siteInfo?.account_id,
|
|
770
|
+
fileWatcher: serverFileWatcher,
|
|
771
|
+
geolocation: mockLocation,
|
|
772
|
+
logger: { log, warn, error: logError },
|
|
773
|
+
projectRoot: projectDir,
|
|
774
|
+
siteID: siteInfo?.id,
|
|
775
|
+
});
|
|
776
|
+
const handlerToStop = serverHandler;
|
|
777
|
+
runBeforeProcessExit(async () => {
|
|
778
|
+
await handlerToStop.stop();
|
|
779
|
+
await serverFileWatcher.close();
|
|
780
|
+
});
|
|
781
|
+
}
|
|
728
782
|
const imageProxy = initializeImageProxy({
|
|
729
783
|
settings,
|
|
730
784
|
imageHandler,
|
|
@@ -752,6 +806,7 @@ export const startProxy = async function ({ accountId, addonsUrls, aiGatewayCont
|
|
|
752
806
|
const onRequestWithOptions = onRequest.bind(undefined, {
|
|
753
807
|
proxy,
|
|
754
808
|
rewriter,
|
|
809
|
+
serverHandler,
|
|
755
810
|
settings,
|
|
756
811
|
addonsUrls,
|
|
757
812
|
functionsRegistry,
|
|
@@ -766,6 +821,20 @@ export const startProxy = async function ({ accountId, addonsUrls, aiGatewayCont
|
|
|
766
821
|
? https.createServer({ cert: settings.https.cert, key: settings.https.key }, onRequestWithOptions)
|
|
767
822
|
: http.createServer(onRequestWithOptions);
|
|
768
823
|
const onUpgrade = async function onUpgrade(req, socket, head) {
|
|
824
|
+
if (serverHandler) {
|
|
825
|
+
let handled = false;
|
|
826
|
+
try {
|
|
827
|
+
handled = await serverHandler.handleUpgrade(req, socket, head);
|
|
828
|
+
}
|
|
829
|
+
catch (error) {
|
|
830
|
+
logError(`Failed to hand over upgrade request to server: ${error instanceof Error ? error.message : String(error)}`);
|
|
831
|
+
socket.destroy();
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
if (handled) {
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
769
838
|
const match = await rewriter(req);
|
|
770
839
|
if (match && !match.force404 && isExternal(match)) {
|
|
771
840
|
const reqUrl = reqToURL(req, req.url);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.8.0",
|
|
4
4
|
"description": "Netlify command line tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -55,11 +55,11 @@
|
|
|
55
55
|
"@fastify/static": "^10.0.0",
|
|
56
56
|
"@netlify/ai": "^1.0.1",
|
|
57
57
|
"@netlify/api": "^15.1.2",
|
|
58
|
-
"@netlify/blobs": "^11.0
|
|
59
|
-
"@netlify/build": "^
|
|
58
|
+
"@netlify/blobs": "^11.1.0",
|
|
59
|
+
"@netlify/build": "^37.0.0",
|
|
60
60
|
"@netlify/build-info": "^11.3.0",
|
|
61
61
|
"@netlify/config": "^25.2.5",
|
|
62
|
-
"@netlify/dev": "^5.
|
|
62
|
+
"@netlify/dev": "^5.1.2",
|
|
63
63
|
"@netlify/dev-utils": "^6.0.1",
|
|
64
64
|
"@netlify/edge-bundler": "^16.0.4",
|
|
65
65
|
"@netlify/edge-functions": "^4.0.0",
|
|
@@ -68,9 +68,10 @@
|
|
|
68
68
|
"@netlify/images": "^2.0.1",
|
|
69
69
|
"@netlify/local-functions-proxy": "^2.0.3",
|
|
70
70
|
"@netlify/redirect-parser": "^16.1.1",
|
|
71
|
-
"@netlify/
|
|
71
|
+
"@netlify/server-dev": "^0.1.1",
|
|
72
|
+
"@netlify/zip-it-and-ship-it": "^16.0.0",
|
|
72
73
|
"@octokit/rest": "^22.0.0",
|
|
73
|
-
"@opentelemetry/api": "
|
|
74
|
+
"@opentelemetry/api": "~1.9.0",
|
|
74
75
|
"@pnpm/tabtab": "^0.5.4",
|
|
75
76
|
"ansi-escapes": "^7.3.0",
|
|
76
77
|
"ansi-to-html": "^0.7.2",
|