netlify 27.10.2 → 27.11.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/commands/agents/agents-create.js +19 -33
- package/dist/commands/base-command.d.ts +1 -1
- package/dist/commands/base-command.js +8 -11
- package/dist/commands/clone/clone.js +5 -10
- package/dist/commands/completion/completion.js +5 -9
- package/dist/commands/create/create-action.js +16 -28
- package/dist/commands/database/db-init.js +17 -31
- package/dist/commands/database/db-migration-new.js +13 -23
- package/dist/commands/database/db-migration-pull.js +5 -9
- package/dist/commands/database/db-reset.js +5 -9
- package/dist/commands/deploy/deploy.js +23 -36
- package/dist/commands/env/env-list.js +5 -9
- package/dist/commands/functions/functions-create.js +35 -71
- package/dist/commands/functions/functions-invoke.js +5 -10
- package/dist/commands/init/init.js +12 -25
- package/dist/commands/link/link.js +26 -52
- package/dist/commands/logs/build.js +2 -4
- package/dist/commands/main.js +10 -17
- package/dist/commands/recipes/recipes.js +6 -16
- package/dist/commands/sites/sites-create.js +12 -22
- package/dist/commands/sites/sites-delete.js +3 -7
- package/dist/commands/switch/switch.js +5 -9
- package/dist/lib/edge-functions/editor-helper.js +3 -5
- package/dist/recipes/ai-context/index.js +9 -17
- package/dist/recipes/blobs-migrate/index.js +3 -7
- package/dist/recipes/vscode/index.js +6 -10
- package/dist/utils/build-info.js +3 -6
- package/dist/utils/deploy/deploy-site.js +21 -12
- package/dist/utils/deploy/upload-files.js +6 -2
- package/dist/utils/deploy/util.d.ts +1 -0
- package/dist/utils/deploy/util.js +1 -0
- package/dist/utils/exit-codes.d.ts +2 -0
- package/dist/utils/exit-codes.js +2 -0
- package/dist/utils/gh-auth.js +10 -22
- package/dist/utils/github-api.d.ts +22 -0
- package/dist/utils/github-api.js +47 -0
- package/dist/utils/init/config-github.js +29 -45
- package/dist/utils/init/config-manual.js +8 -28
- package/dist/utils/init/utils.js +14 -38
- package/dist/utils/prompts/confirm-prompt.js +4 -15
- package/dist/utils/proxy.js +7 -48
- package/dist/utils/redirects.js +3 -2
- package/dist/utils/rules-proxy.js +31 -29
- package/dist/utils/types.d.ts +2 -2
- package/package.json +7 -11
package/dist/utils/init/utils.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { writeFile } from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import cleanDeep from 'clean-deep';
|
|
4
|
-
import
|
|
4
|
+
import { confirm, input } from '@inquirer/prompts';
|
|
5
5
|
import { fileExistsAsync } from '../../lib/fs.js';
|
|
6
6
|
import { normalizeBackslash } from '../../lib/path.js';
|
|
7
7
|
import { detectBuildSettings } from '../build-info.js';
|
|
@@ -41,30 +41,6 @@ const normalizeSettings = (settings, config, command) => {
|
|
|
41
41
|
recommendedPlugins,
|
|
42
42
|
};
|
|
43
43
|
};
|
|
44
|
-
const getPromptInputs = ({ defaultBaseDir, defaultBuildCmd, defaultBuildDir, }) => {
|
|
45
|
-
const inputs = [
|
|
46
|
-
defaultBaseDir !== '' && {
|
|
47
|
-
type: 'input',
|
|
48
|
-
name: 'baseDir',
|
|
49
|
-
message: 'Base directory `(blank for current dir):',
|
|
50
|
-
default: defaultBaseDir,
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
type: 'input',
|
|
54
|
-
name: 'buildCmd',
|
|
55
|
-
message: 'Your build command (hugo build/yarn run build/etc):',
|
|
56
|
-
filter: (val) => (val === '' ? '# no build command' : val),
|
|
57
|
-
default: defaultBuildCmd,
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
type: 'input',
|
|
61
|
-
name: 'buildDir',
|
|
62
|
-
message: 'Directory to deploy (blank for current dir):',
|
|
63
|
-
default: defaultBuildDir,
|
|
64
|
-
},
|
|
65
|
-
].filter(Boolean);
|
|
66
|
-
return inputs.filter(Boolean);
|
|
67
|
-
};
|
|
68
44
|
export const getBuildSettings = async ({ command, config, }) => {
|
|
69
45
|
const settings = await detectBuildSettings(command);
|
|
70
46
|
const setting = settings.length > 0 ? settings[0] : {};
|
|
@@ -79,11 +55,15 @@ export const getBuildSettings = async ({ command, config, }) => {
|
|
|
79
55
|
log('For each setting, press Enter to accept the default or provide your own value.');
|
|
80
56
|
log();
|
|
81
57
|
}
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
58
|
+
const baseDir = defaultBaseDir === ''
|
|
59
|
+
? undefined
|
|
60
|
+
: await input({ message: 'Base directory `(blank for current dir):', default: defaultBaseDir });
|
|
61
|
+
const buildCmdInput = await input({
|
|
62
|
+
message: 'Your build command (hugo build/yarn run build/etc):',
|
|
63
|
+
default: defaultBuildCmd,
|
|
64
|
+
});
|
|
65
|
+
const buildCmd = buildCmdInput === '' ? '# no build command' : buildCmdInput;
|
|
66
|
+
const buildDir = await input({ message: 'Directory to deploy (blank for current dir):', default: defaultBuildDir });
|
|
87
67
|
const pluginsToInstall = recommendedPlugins.map((plugin) => ({ package: plugin }));
|
|
88
68
|
const normalizedBaseDir = baseDir ? normalizeBackslash(baseDir) : undefined;
|
|
89
69
|
return { baseDir: normalizedBaseDir, buildCmd, buildDir, functionsDir: defaultFunctionsDir, pluginsToInstall };
|
|
@@ -123,14 +103,10 @@ export const saveNetlifyToml = async ({ baseDir, buildCmd, buildDir, config, con
|
|
|
123
103
|
if (configPath === undefined && Object.keys(cleanDeep(config)).length !== 0) {
|
|
124
104
|
return;
|
|
125
105
|
}
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
message: 'No netlify.toml detected. Would you like to create one with these build settings?',
|
|
131
|
-
default: true,
|
|
132
|
-
},
|
|
133
|
-
]);
|
|
106
|
+
const makeNetlifyTOML = await confirm({
|
|
107
|
+
message: 'No netlify.toml detected. Would you like to create one with these build settings?',
|
|
108
|
+
default: true,
|
|
109
|
+
});
|
|
134
110
|
if (makeNetlifyTOML) {
|
|
135
111
|
try {
|
|
136
112
|
await writeFile(tomlPath, getNetlifyToml({ command: buildCmd, publish: buildDir, functions: functionsDir }), 'utf-8');
|
|
@@ -1,20 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { confirm } from '@inquirer/prompts';
|
|
2
2
|
import { log, exit } from '../command-helpers.js';
|
|
3
3
|
export const confirmPrompt = async (message) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
name: 'confirm',
|
|
8
|
-
message,
|
|
9
|
-
default: false,
|
|
10
|
-
});
|
|
11
|
-
log();
|
|
12
|
-
if (!confirm) {
|
|
13
|
-
exit();
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
catch (error) {
|
|
17
|
-
console.error(error);
|
|
4
|
+
const confirmed = await confirm({ message, default: false });
|
|
5
|
+
log();
|
|
6
|
+
if (!confirmed) {
|
|
18
7
|
exit();
|
|
19
8
|
}
|
|
20
9
|
};
|
package/dist/utils/proxy.js
CHANGED
|
@@ -16,13 +16,10 @@ import { ImageHandler } from '@netlify/images';
|
|
|
16
16
|
import { ServerHandler } from '@netlify/server-dev';
|
|
17
17
|
import { runBeforeProcessExit } from './shell.js';
|
|
18
18
|
import contentType from 'content-type';
|
|
19
|
-
import { parseCookie } from 'cookie';
|
|
20
|
-
import { getProperty } from 'dot-prop';
|
|
21
19
|
import generateETag from 'etag';
|
|
22
20
|
import getAvailablePort from 'get-port';
|
|
23
21
|
import httpProxy from 'http-proxy';
|
|
24
22
|
import { createProxyMiddleware } from 'http-proxy-middleware';
|
|
25
|
-
import { jwtDecode } from 'jwt-decode';
|
|
26
23
|
import { locatePath } from 'locate-path';
|
|
27
24
|
import { throttle } from './object-utilities.js';
|
|
28
25
|
import pFilter from 'p-filter';
|
|
@@ -126,7 +123,7 @@ const isEndpointExists = async function (endpoint, origin) {
|
|
|
126
123
|
}
|
|
127
124
|
};
|
|
128
125
|
const isExternal = function (match) {
|
|
129
|
-
return
|
|
126
|
+
return match.type === 'match' && /^https?:\/\//.exec(match.to) != null;
|
|
130
127
|
};
|
|
131
128
|
const stripOrigin = function ({ hash, pathname, search }) {
|
|
132
129
|
return `${pathname}${search}${hash}`;
|
|
@@ -193,7 +190,7 @@ const serveRedirect = async function ({ env, functionsRegistry, imageProxy, matc
|
|
|
193
190
|
return proxy.web(req, res, options);
|
|
194
191
|
options = options || req.proxyOptions || {};
|
|
195
192
|
options.match = null;
|
|
196
|
-
if (match.
|
|
193
|
+
if (match.type === 'forcedNotFound') {
|
|
197
194
|
res.writeHead(404);
|
|
198
195
|
res.end(await render404(options.publicFolder));
|
|
199
196
|
return;
|
|
@@ -203,8 +200,9 @@ const serveRedirect = async function ({ env, functionsRegistry, imageProxy, matc
|
|
|
203
200
|
req.headers[key] = value;
|
|
204
201
|
});
|
|
205
202
|
}
|
|
206
|
-
|
|
207
|
-
|
|
203
|
+
const signingSecretName = match.signer?.jwtSecret;
|
|
204
|
+
if (signingSecretName) {
|
|
205
|
+
const signingSecretVar = env[signingSecretName];
|
|
208
206
|
if (signingSecretVar) {
|
|
209
207
|
req.headers['x-nf-sign'] = signRedirect({
|
|
210
208
|
deployContext: 'dev',
|
|
@@ -214,7 +212,7 @@ const serveRedirect = async function ({ env, functionsRegistry, imageProxy, matc
|
|
|
214
212
|
});
|
|
215
213
|
}
|
|
216
214
|
else {
|
|
217
|
-
log(NETLIFYDEVWARN, `Could not sign redirect because environment variable ${chalk.yellow(
|
|
215
|
+
log(NETLIFYDEVWARN, `Could not sign redirect because environment variable ${chalk.yellow(signingSecretName)} is not set`);
|
|
218
216
|
}
|
|
219
217
|
}
|
|
220
218
|
if (isFunction(options.functionsPort, req.url)) {
|
|
@@ -226,44 +224,6 @@ const serveRedirect = async function ({ env, functionsRegistry, imageProxy, matc
|
|
|
226
224
|
return;
|
|
227
225
|
}
|
|
228
226
|
const originalURL = req.url;
|
|
229
|
-
if (match.exceptions && match.exceptions.JWT) {
|
|
230
|
-
// Some values of JWT can start with :, so, make sure to normalize them
|
|
231
|
-
const expectedRoles = new Set(match.exceptions.JWT.split(',').map((value) => (value.startsWith(':') ? value.slice(1) : value)));
|
|
232
|
-
const cookieValues = parseCookie(req.headers.cookie || '');
|
|
233
|
-
const token = cookieValues.nf_jwt;
|
|
234
|
-
// Serve not found by default
|
|
235
|
-
req.url = '/.netlify/non-existent-path';
|
|
236
|
-
if (token) {
|
|
237
|
-
let jwtValue = {};
|
|
238
|
-
try {
|
|
239
|
-
jwtValue = jwtDecode(token) || {};
|
|
240
|
-
}
|
|
241
|
-
catch (error) {
|
|
242
|
-
// @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
|
|
243
|
-
console.warn(NETLIFYDEVWARN, 'Error while decoding JWT provided in request', error.message);
|
|
244
|
-
res.writeHead(400);
|
|
245
|
-
res.end('Invalid JWT provided. Please see logs for more info.');
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
// @ts-expect-error TS(2339) FIXME: Property 'exp' does not exist on type '{}'.
|
|
249
|
-
if ((jwtValue.exp || 0) < Math.round(Date.now() / MILLISEC_TO_SEC)) {
|
|
250
|
-
console.warn(NETLIFYDEVWARN, 'Expired JWT provided in request', req.url);
|
|
251
|
-
}
|
|
252
|
-
else {
|
|
253
|
-
const presentedRoles = getProperty(jwtValue, options.jwtRolePath) || [];
|
|
254
|
-
if (!Array.isArray(presentedRoles)) {
|
|
255
|
-
console.warn(NETLIFYDEVWARN, `Invalid roles value provided in JWT ${options.jwtRolePath}`, presentedRoles);
|
|
256
|
-
res.writeHead(400);
|
|
257
|
-
res.end('Invalid JWT provided. Please see logs for more info.');
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
// Restore the URL if everything is correct
|
|
261
|
-
if (presentedRoles.some((pr) => expectedRoles.has(pr))) {
|
|
262
|
-
req.url = originalURL;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
227
|
const reqUrl = reqToURL(req, req.url);
|
|
268
228
|
const isHiddenProxy = match.proxyHeaders &&
|
|
269
229
|
Object.entries(match.proxyHeaders).some(([key, val]) => key.toLowerCase() === 'x-nf-hidden-proxy' && val === 'true');
|
|
@@ -363,7 +323,6 @@ const serveRedirect = async function ({ env, functionsRegistry, imageProxy, matc
|
|
|
363
323
|
const reqToURL = function (req, pathname) {
|
|
364
324
|
return new URL(pathname, `${req.protocol || (req.headers.scheme && `${req.headers.scheme}:`) || 'http:'}//${req.headers.host || req.hostname}`);
|
|
365
325
|
};
|
|
366
|
-
const MILLISEC_TO_SEC = 1e3;
|
|
367
326
|
const initializeProxy = async function ({ config, configPath, distDir, env, host, imageProxy, port, projectDir, siteInfo, }) {
|
|
368
327
|
const proxy = httpProxy.createProxyServer({
|
|
369
328
|
selfHandleResponse: true,
|
|
@@ -836,7 +795,7 @@ export const startProxy = async function ({ accountId, addonsUrls, aiGatewayCont
|
|
|
836
795
|
}
|
|
837
796
|
}
|
|
838
797
|
const match = await rewriter(req);
|
|
839
|
-
if (match &&
|
|
798
|
+
if (match && isExternal(match)) {
|
|
840
799
|
const reqUrl = reqToURL(req, req.url);
|
|
841
800
|
const dest = new URL(match.to, `${reqUrl.protocol}//${reqUrl.host}`);
|
|
842
801
|
const destURL = stripOrigin(dest);
|
package/dist/utils/redirects.js
CHANGED
|
@@ -26,10 +26,11 @@ const handleRedirectParsingErrors = function (errors) {
|
|
|
26
26
|
const getErrorMessage = function ({ message }) {
|
|
27
27
|
return message;
|
|
28
28
|
};
|
|
29
|
-
//
|
|
30
|
-
// - `from` is called `origin`
|
|
29
|
+
// `@netlify/redirect-matcher` reads a different rule shape from the backend's:
|
|
31
30
|
// - `query` is called `params`
|
|
32
31
|
// - `conditions.role|country|language` are capitalized
|
|
32
|
+
// - `signed` becomes `sign.jwt_secret`
|
|
33
|
+
// The matcher reads the source path from `path`; `origin` is ignored.
|
|
33
34
|
const normalizeRedirect = function ({
|
|
34
35
|
// @ts-expect-error TS(7031) FIXME: Binding element 'country' implicitly has an 'any' ... Remove this comment to see the full error message
|
|
35
36
|
conditions: { country, language, role, ...conditions },
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
+
import { createMatcher } from '@netlify/redirect-matcher';
|
|
2
3
|
import chokidar from 'chokidar';
|
|
3
4
|
import { parseCookie } from 'cookie';
|
|
4
|
-
import redirector from 'netlify-redirector';
|
|
5
5
|
import pFilter from 'p-filter';
|
|
6
6
|
import { fileExistsAsync } from '../lib/fs.js';
|
|
7
|
-
import { NETLIFYDEVLOG } from './command-helpers.js';
|
|
7
|
+
import { NETLIFYDEVERR, NETLIFYDEVLOG, log } from './command-helpers.js';
|
|
8
8
|
import { parseRedirects } from './redirects.js';
|
|
9
9
|
const watchers = [];
|
|
10
10
|
export const onChanges = function (files, listener) {
|
|
@@ -37,22 +37,35 @@ export const createRewriter = async function ({ config, configPath, distDir, geo
|
|
|
37
37
|
const existingRedirectsFiles = await pFilter(watchedRedirectFiles, fileExistsAsync);
|
|
38
38
|
console.log(`${NETLIFYDEVLOG} Reloading redirect rules from`, existingRedirectsFiles.map((redirectFile) => path.relative(projectDir, redirectFile)));
|
|
39
39
|
redirects = await parseRedirects({ config, redirectsFiles, configPath });
|
|
40
|
+
// Not closed: a request may still hold the previous matcher. The package
|
|
41
|
+
// frees it once it is garbage-collected.
|
|
40
42
|
matcher = null;
|
|
41
43
|
});
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return (matcher = await redirector.parseJSON(JSON.stringify(redirects), {
|
|
47
|
-
jwtSecret,
|
|
48
|
-
jwtRoleClaim,
|
|
49
|
-
}));
|
|
44
|
+
const buildMatcher = async () => {
|
|
45
|
+
// Without rules, skip compiling the matcher's WebAssembly module.
|
|
46
|
+
if (redirects.length === 0) {
|
|
47
|
+
return { match: () => null };
|
|
50
48
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
const built = await createMatcher(redirects, { jwtSecret, jwtRoleClaim });
|
|
50
|
+
if (built.parseErrors.length !== 0) {
|
|
51
|
+
log(NETLIFYDEVERR, `Redirects matcher errors:\n${built.parseErrors.map(({ message }) => message).join('\n\n')}`);
|
|
52
|
+
}
|
|
53
|
+
return built;
|
|
54
|
+
};
|
|
55
|
+
// The promise is cached, not the matcher, so concurrent requests share one
|
|
56
|
+
// build and a reload mid-build cannot cache a matcher of the old rules.
|
|
57
|
+
const getMatcher = () => {
|
|
58
|
+
if (!matcher) {
|
|
59
|
+
const build = buildMatcher();
|
|
60
|
+
matcher = build;
|
|
61
|
+
// A failed build is retried by the next request, unless a reload has
|
|
62
|
+
// already replaced it with a newer one.
|
|
63
|
+
build.catch(() => {
|
|
64
|
+
if (matcher === build)
|
|
65
|
+
matcher = null;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return matcher;
|
|
56
69
|
};
|
|
57
70
|
return async function rewriter(req) {
|
|
58
71
|
const matcherFunc = await getMatcher();
|
|
@@ -63,25 +76,14 @@ export const createRewriter = async function ({ config, configPath, distDir, geo
|
|
|
63
76
|
'x-country': cookieValues.nf_country || geoCountry || 'us',
|
|
64
77
|
...req.headers,
|
|
65
78
|
};
|
|
66
|
-
|
|
67
|
-
const matchReq = {
|
|
79
|
+
return matcherFunc.match({
|
|
68
80
|
scheme: reqUrl.protocol.replace(/:.*$/, ''),
|
|
69
81
|
host: reqUrl.hostname,
|
|
70
82
|
path: decodeURIComponent(reqUrl.pathname),
|
|
71
83
|
query: reqUrl.search.slice(1),
|
|
72
84
|
headers,
|
|
73
|
-
cookieValues,
|
|
74
|
-
|
|
75
|
-
const val = headers[name.toLowerCase()];
|
|
76
|
-
if (Array.isArray(val)) {
|
|
77
|
-
return val[0];
|
|
78
|
-
}
|
|
79
|
-
return val || '';
|
|
80
|
-
},
|
|
81
|
-
getCookie: (key) => cookieValues[key] || '',
|
|
82
|
-
};
|
|
83
|
-
const match = matcherFunc.match(matchReq);
|
|
84
|
-
return match;
|
|
85
|
+
cookies: cookieValues,
|
|
86
|
+
});
|
|
85
87
|
};
|
|
86
88
|
};
|
|
87
89
|
//# sourceMappingURL=rules-proxy.js.map
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Buffer } from 'buffer';
|
|
2
2
|
import type { IncomingMessage } from 'http';
|
|
3
3
|
import type { PollingStrategy } from '@netlify/build-info';
|
|
4
|
-
import type {
|
|
4
|
+
import type { MatchResult } from '@netlify/redirect-matcher';
|
|
5
5
|
export type { GlobalConfigStore } from '@netlify/dev-utils';
|
|
6
6
|
export type { LocalState } from '@netlify/dev-utils';
|
|
7
7
|
export type FrameworkNames = '#static' | '#auto' | '#custom' | string;
|
|
@@ -63,7 +63,7 @@ export interface Request extends IncomingMessage {
|
|
|
63
63
|
protocol?: string;
|
|
64
64
|
hostname?: string;
|
|
65
65
|
}
|
|
66
|
-
export type Rewriter = (req: Request) => Promise<
|
|
66
|
+
export type Rewriter = (req: Request) => Promise<MatchResult | null>;
|
|
67
67
|
export interface SiteInfo {
|
|
68
68
|
account_id?: string | undefined;
|
|
69
69
|
account_name: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.11.0",
|
|
4
4
|
"description": "Netlify command line tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -52,24 +52,25 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@fastify/static": "^10.0.0",
|
|
55
|
+
"@inquirer/prompts": "^8.7.2",
|
|
55
56
|
"@netlify/ai": "^1.0.1",
|
|
56
57
|
"@netlify/api": "^15.1.2",
|
|
57
|
-
"@netlify/blobs": "^11.1.
|
|
58
|
+
"@netlify/blobs": "^11.1.3",
|
|
58
59
|
"@netlify/build": "^37.3.3",
|
|
59
60
|
"@netlify/build-info": "^11.3.0",
|
|
60
61
|
"@netlify/config": "^25.2.6",
|
|
61
|
-
"@netlify/dev": "^5.1.
|
|
62
|
-
"@netlify/dev-utils": "^6.0.
|
|
62
|
+
"@netlify/dev": "^5.1.6",
|
|
63
|
+
"@netlify/dev-utils": "^6.0.3",
|
|
63
64
|
"@netlify/edge-bundler": "^16.1.1",
|
|
64
65
|
"@netlify/edge-functions": "^4.0.0",
|
|
65
66
|
"@netlify/edge-functions-bootstrap": "^3.2.0",
|
|
66
67
|
"@netlify/headers-parser": "^10.1.1",
|
|
67
68
|
"@netlify/images": "^2.0.1",
|
|
68
69
|
"@netlify/local-functions-proxy": "^2.0.3",
|
|
70
|
+
"@netlify/redirect-matcher": "^0.4.2",
|
|
69
71
|
"@netlify/redirect-parser": "^16.1.1",
|
|
70
72
|
"@netlify/server-dev": "^0.1.1",
|
|
71
73
|
"@netlify/zip-it-and-ship-it": "^16.2.3",
|
|
72
|
-
"@octokit/rest": "^22.0.0",
|
|
73
74
|
"@opentelemetry/api": "~1.9.0",
|
|
74
75
|
"@pnpm/tabtab": "^0.5.4",
|
|
75
76
|
"ansi-escapes": "^7.3.0",
|
|
@@ -88,7 +89,6 @@
|
|
|
88
89
|
"cron-parser": "^5.0.0",
|
|
89
90
|
"debug": "^4.4.3",
|
|
90
91
|
"decache": "^4.6.2",
|
|
91
|
-
"dot-prop": "^10.1.0",
|
|
92
92
|
"dotenv": "^17.3.1",
|
|
93
93
|
"env-paths": "^4.0.0",
|
|
94
94
|
"envinfo": "^7.21.0",
|
|
@@ -107,8 +107,6 @@
|
|
|
107
107
|
"http-proxy": "^1.18.1",
|
|
108
108
|
"http-proxy-middleware": "^3.0.5",
|
|
109
109
|
"https-proxy-agent": "^8.0.0",
|
|
110
|
-
"inquirer": "^8.2.7",
|
|
111
|
-
"inquirer-autocomplete-prompt": "^1.4.0",
|
|
112
110
|
"is-docker": "^4.0.0",
|
|
113
111
|
"is-stream": "^4.0.1",
|
|
114
112
|
"is-wsl": "^3.1.0",
|
|
@@ -123,7 +121,6 @@
|
|
|
123
121
|
"modern-tar": "^0.8.0",
|
|
124
122
|
"multiparty": "^4.2.3",
|
|
125
123
|
"nanospinner": "^1.2.2",
|
|
126
|
-
"netlify-redirector": "^0.5.0",
|
|
127
124
|
"node-fetch": "^3.3.2",
|
|
128
125
|
"normalize-package-data": "^7.0.1",
|
|
129
126
|
"open": "^11.0.0",
|
|
@@ -168,8 +165,6 @@
|
|
|
168
165
|
"@types/express": "^5.0.6",
|
|
169
166
|
"@types/folder-walker": "^3.2.5",
|
|
170
167
|
"@types/gitconfiglocal": "^2.0.3",
|
|
171
|
-
"@types/inquirer": "^9.0.9",
|
|
172
|
-
"@types/inquirer-autocomplete-prompt": "^3.0.3",
|
|
173
168
|
"@types/jsonwebtoken": "^9.0.10",
|
|
174
169
|
"@types/lodash.shuffle": "^4.2.9",
|
|
175
170
|
"@types/multiparty": "^4.2.1",
|
|
@@ -192,6 +187,7 @@
|
|
|
192
187
|
"c8": "^10.1.3",
|
|
193
188
|
"cheerio": "^1.1.2",
|
|
194
189
|
"dedent": "^1.7.2",
|
|
190
|
+
"dot-prop": "^10.1.0",
|
|
195
191
|
"eslint": "^9.36.0",
|
|
196
192
|
"eslint-config-prettier": "^10.1.8",
|
|
197
193
|
"eslint-plugin-n": "^17.23.1",
|