netlify-cli 17.10.2 → 17.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/npm-shrinkwrap.json +1083 -329
- package/package.json +2 -2
- package/src/commands/deploy/deploy.js +5 -8
- package/src/commands/serve/serve.js +3 -0
- package/src/lib/blobs/blobs.js +1 -1
- package/src/lib/edge-functions/proxy.js +2 -21
- package/src/lib/edge-functions/registry.js +42 -10
- package/src/lib/functions/netlify-function.js +3 -3
- package/src/lib/functions/registry.js +17 -27
- package/src/lib/functions/runtimes/index.js +0 -34
- package/src/lib/functions/server.js +1 -2
- package/src/utils/deploy/deploy-site.js +0 -6
- package/src/utils/detect-server-settings.js +3 -68
- package/src/utils/functions/functions.js +2 -9
- package/src/lib/edge-functions/internal.js +0 -46
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netlify-cli",
|
|
3
3
|
"description": "Netlify command line tool",
|
|
4
|
-
"version": "17.
|
|
4
|
+
"version": "17.11.0",
|
|
5
5
|
"author": "Netlify Inc.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@netlify/build": "29.31.0",
|
|
50
50
|
"@netlify/build-info": "7.11.3",
|
|
51
51
|
"@netlify/config": "20.10.0",
|
|
52
|
-
"@netlify/edge-bundler": "
|
|
52
|
+
"@netlify/edge-bundler": "11.0.0",
|
|
53
53
|
"@netlify/local-functions-proxy": "1.1.1",
|
|
54
54
|
"@netlify/zip-it-and-ship-it": "9.28.1",
|
|
55
55
|
"@octokit/rest": "19.0.13",
|
|
@@ -359,9 +359,7 @@ deployTimeout,
|
|
|
359
359
|
// @ts-expect-error TS(7031) FIXME: Binding element 'deployToProduction' implicitly ha... Remove this comment to see the full error message
|
|
360
360
|
deployToProduction,
|
|
361
361
|
// @ts-expect-error TS(7031) FIXME: Binding element 'functionsConfig' implicitly has a... Remove this comment to see the full error message
|
|
362
|
-
functionsConfig,
|
|
363
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'functionsFolder' implicitly has a... Remove this comment to see the full error message
|
|
364
|
-
functionsFolder,
|
|
362
|
+
functionsConfig, functionsFolder,
|
|
365
363
|
// @ts-expect-error TS(7031) FIXME: Binding element 'options' implicitly has an 'a... Remove this comment to see the full error message
|
|
366
364
|
options,
|
|
367
365
|
// @ts-expect-error TS(7031) FIXME: Binding element 'packagePath' implicitly has an 'a... Remove this comment to see the full error message
|
|
@@ -390,12 +388,11 @@ title, }) => {
|
|
|
390
388
|
const draft = !deployToProduction && !alias;
|
|
391
389
|
results = await api.createSiteDeploy({ siteId, title, body: { draft, branch: alias } });
|
|
392
390
|
deployId = results.id;
|
|
393
|
-
|
|
394
|
-
const internalFunctionsFolder = await getInternalFunctionsDir({ base: site.root, packagePath });
|
|
391
|
+
const internalFunctionsFolder = await getInternalFunctionsDir({ base: site.root, packagePath, ensureExists: true });
|
|
395
392
|
// The order of the directories matter: zip-it-and-ship-it will prioritize
|
|
396
393
|
// functions from the rightmost directories. In this case, we want user
|
|
397
394
|
// functions to take precedence over internal functions.
|
|
398
|
-
const functionDirectories = [internalFunctionsFolder, functionsFolder].filter(Boolean);
|
|
395
|
+
const functionDirectories = [internalFunctionsFolder, functionsFolder].filter((folder) => Boolean(folder));
|
|
399
396
|
const manifestPath = skipFunctionsCache ? null : await getFunctionsManifestPath({ base: site.root, packagePath });
|
|
400
397
|
const redirectsPath = `${deployFolder}/_redirects`;
|
|
401
398
|
const headersPath = `${deployFolder}/_headers`;
|
|
@@ -414,11 +411,10 @@ title, }) => {
|
|
|
414
411
|
config.headers = headers;
|
|
415
412
|
uploadDeployBlobs({ deployId, siteId, silent, options, cachedConfig: command.netlify.cachedConfig });
|
|
416
413
|
results = await deploySite(api, siteId, deployFolder, {
|
|
414
|
+
// @ts-expect-error FIXME
|
|
417
415
|
config,
|
|
418
|
-
// @ts-expect-error TS(2322) FIXME: Type 'any[]' is not assignable to type 'never[]'.
|
|
419
416
|
fnDir: functionDirectories,
|
|
420
417
|
functionsConfig,
|
|
421
|
-
// @ts-expect-error TS(2322) FIXME: Type '(event: any) => void' is not assignable to t... Remove this comment to see the full error message
|
|
422
418
|
statusCb: silent ? () => { } : deployProgressCb(),
|
|
423
419
|
deployTimeout,
|
|
424
420
|
syncFileLimit: SYNC_FILE_LIMIT,
|
|
@@ -640,6 +636,7 @@ workingDir, }) => {
|
|
|
640
636
|
siteEnv,
|
|
641
637
|
});
|
|
642
638
|
const results = await runDeploy({
|
|
639
|
+
// @ts-expect-error FIXME
|
|
643
640
|
alias,
|
|
644
641
|
api,
|
|
645
642
|
command,
|
|
@@ -40,6 +40,9 @@ export const serve = async (options, command) => {
|
|
|
40
40
|
site,
|
|
41
41
|
siteInfo,
|
|
42
42
|
});
|
|
43
|
+
if (!site.root) {
|
|
44
|
+
throw new Error('Site root not found');
|
|
45
|
+
}
|
|
43
46
|
// Ensure the internal functions directory exists so that the functions
|
|
44
47
|
// server and registry are initialized, and any functions created by
|
|
45
48
|
// Netlify Build are loaded.
|
package/src/lib/blobs/blobs.js
CHANGED
|
@@ -12,7 +12,7 @@ const printLocalBlobsNotice = () => {
|
|
|
12
12
|
log(`${NETLIFYDEVLOG} Netlify Blobs running in sandbox mode for local development. Refer to https://ntl.fyi/local-blobs for more information.`);
|
|
13
13
|
};
|
|
14
14
|
const startBlobsServer = async (debug, projectRoot, token) => {
|
|
15
|
-
const directory = path.resolve(projectRoot, getPathInProject(['blobs-
|
|
15
|
+
const directory = path.resolve(projectRoot, getPathInProject(['blobs-serve']));
|
|
16
16
|
const server = new BlobsServer({
|
|
17
17
|
debug,
|
|
18
18
|
directory,
|
|
@@ -10,7 +10,6 @@ import { startSpinner, stopSpinner } from '../spinner.js';
|
|
|
10
10
|
import { getBootstrapURL } from './bootstrap.js';
|
|
11
11
|
import { DIST_IMPORT_MAP_PATH, EDGE_FUNCTIONS_SERVE_FOLDER } from './consts.js';
|
|
12
12
|
import { headers, getFeatureFlagsHeader, getInvocationMetadataHeader } from './headers.js';
|
|
13
|
-
import { getInternalFunctions } from './internal.js';
|
|
14
13
|
import { EdgeFunctionsRegistry } from './registry.js';
|
|
15
14
|
const headersSymbol = Symbol('Edge Functions Headers');
|
|
16
15
|
const LOCAL_HOST = '127.0.0.1';
|
|
@@ -111,9 +110,6 @@ settings,
|
|
|
111
110
|
siteInfo,
|
|
112
111
|
// @ts-expect-error TS(7031) FIXME: Binding element 'state' implicitly has an 'any' ty... Remove this comment to see the full error message
|
|
113
112
|
state, }) => {
|
|
114
|
-
const { functions: internalFunctions,
|
|
115
|
-
// @ts-expect-error TS(2339) FIXME: Property 'importMap' does not exist on type '{ fun... Remove this comment to see the full error message
|
|
116
|
-
importMap, path: internalFunctionsPath, } = await getInternalFunctions(projectDir);
|
|
117
113
|
const userFunctionsPath = config.build.edge_functions;
|
|
118
114
|
const isolatePort = await getAvailablePort();
|
|
119
115
|
const buildFeatureFlags = {
|
|
@@ -132,18 +128,13 @@ state, }) => {
|
|
|
132
128
|
env: configEnv,
|
|
133
129
|
featureFlags: buildFeatureFlags,
|
|
134
130
|
getUpdatedConfig,
|
|
135
|
-
importMaps: [importMap].filter(Boolean),
|
|
136
131
|
inspectSettings,
|
|
137
|
-
internalDirectory: internalFunctionsPath,
|
|
138
|
-
internalFunctions,
|
|
139
132
|
port: isolatePort,
|
|
140
133
|
projectDir,
|
|
141
134
|
repositoryRoot,
|
|
142
135
|
});
|
|
143
|
-
const hasEdgeFunctions = userFunctionsPath !== undefined || internalFunctionsPath;
|
|
144
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'req' implicitly has an 'any' type.
|
|
145
136
|
return async (req) => {
|
|
146
|
-
if (req.headers[headers.Passthrough] !== undefined
|
|
137
|
+
if (req.headers[headers.Passthrough] !== undefined) {
|
|
147
138
|
return;
|
|
148
139
|
}
|
|
149
140
|
const [geoLocation, registry] = await Promise.all([
|
|
@@ -199,22 +190,14 @@ env: configEnv,
|
|
|
199
190
|
featureFlags,
|
|
200
191
|
// @ts-expect-error TS(7031) FIXME: Binding element 'getUpdatedConfig' implicitly has ... Remove this comment to see the full error message
|
|
201
192
|
getUpdatedConfig,
|
|
202
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'importMaps' implicitly has an 'an... Remove this comment to see the full error message
|
|
203
|
-
importMaps,
|
|
204
193
|
// @ts-expect-error TS(7031) FIXME: Binding element 'inspectSettings' implicitly has a... Remove this comment to see the full error message
|
|
205
194
|
inspectSettings,
|
|
206
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'internalDirectory' implicitly has... Remove this comment to see the full error message
|
|
207
|
-
internalDirectory,
|
|
208
|
-
// @ts-expect-error TS(7031) FIXME: Binding element 'internalFunctions' implicitly has... Remove this comment to see the full error message
|
|
209
|
-
internalFunctions,
|
|
210
195
|
// @ts-expect-error TS(7031) FIXME: Binding element 'port' implicitly has an 'any' typ... Remove this comment to see the full error message
|
|
211
196
|
port,
|
|
212
197
|
// @ts-expect-error TS(7031) FIXME: Binding element 'projectDir' implicitly has an 'an... Remove this comment to see the full error message
|
|
213
198
|
projectDir,
|
|
214
199
|
// @ts-expect-error TS(7031) FIXME: Binding element 'repositoryRoot' implicitly has an... Remove this comment to see the full error message
|
|
215
200
|
repositoryRoot, }) => {
|
|
216
|
-
// Merging internal with user-defined import maps.
|
|
217
|
-
const importMapPaths = [...importMaps, config.functions['*'].deno_import_map];
|
|
218
201
|
try {
|
|
219
202
|
const distImportMapPath = getPathInProject([DIST_IMPORT_MAP_PATH]);
|
|
220
203
|
const servePath = resolve(projectDir, getPathInProject([EDGE_FUNCTIONS_SERVE_FOLDER]));
|
|
@@ -228,7 +211,6 @@ repositoryRoot, }) => {
|
|
|
228
211
|
featureFlags,
|
|
229
212
|
formatExportTypeError: (name) => `${NETLIFYDEVERR} ${chalk.red('Failed')} to load Edge Function ${chalk.yellow(name)}. The file does not seem to have a function as the default export.`,
|
|
230
213
|
formatImportError: (name) => `${NETLIFYDEVERR} ${chalk.red('Failed')} to run Edge Function ${chalk.yellow(name)}:`,
|
|
231
|
-
importMapPaths,
|
|
232
214
|
inspectSettings,
|
|
233
215
|
port,
|
|
234
216
|
rootPath: repositoryRoot,
|
|
@@ -242,8 +224,7 @@ repositoryRoot, }) => {
|
|
|
242
224
|
directories: [directory].filter(Boolean),
|
|
243
225
|
env: configEnv,
|
|
244
226
|
getUpdatedConfig,
|
|
245
|
-
|
|
246
|
-
internalFunctions,
|
|
227
|
+
importMapFromTOML: config.functions['*'].deno_import_map,
|
|
247
228
|
projectDir,
|
|
248
229
|
runIsolate,
|
|
249
230
|
servePath,
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
1
3
|
import { fileURLToPath } from 'url';
|
|
2
4
|
import { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, nonNullable, chalk, log, warn, watchDebounced, isNodeError, } from '../../utils/command-helpers.js';
|
|
5
|
+
import { getPathInProject } from '../settings.js';
|
|
6
|
+
import { INTERNAL_EDGE_FUNCTIONS_FOLDER } from './consts.js';
|
|
3
7
|
const featureFlags = { edge_functions_correct_order: true };
|
|
4
8
|
export class EdgeFunctionsRegistry {
|
|
5
|
-
constructor({ bundler, config, configPath, directories, env, getUpdatedConfig,
|
|
9
|
+
constructor({ bundler, config, configPath, directories, env, getUpdatedConfig, importMapFromTOML, projectDir, runIsolate, servePath, }) {
|
|
6
10
|
this.buildError = null;
|
|
11
|
+
this.declarationsFromDeployConfig = [];
|
|
7
12
|
this.dependencyPaths = new Map();
|
|
8
13
|
this.directoryWatchers = new Map();
|
|
9
14
|
this.functionPaths = new Map();
|
|
@@ -14,11 +19,11 @@ export class EdgeFunctionsRegistry {
|
|
|
14
19
|
this.bundler = bundler;
|
|
15
20
|
this.configPath = configPath;
|
|
16
21
|
this.directories = directories;
|
|
17
|
-
this.internalDirectories = internalDirectories;
|
|
18
22
|
this.getUpdatedConfig = getUpdatedConfig;
|
|
19
23
|
this.runIsolate = runIsolate;
|
|
20
24
|
this.servePath = servePath;
|
|
21
|
-
this.
|
|
25
|
+
this.projectDir = projectDir;
|
|
26
|
+
this.importMapFromTOML = importMapFromTOML;
|
|
22
27
|
this.declarationsFromTOML = EdgeFunctionsRegistry.getDeclarationsFromTOML(config);
|
|
23
28
|
this.env = EdgeFunctionsRegistry.getEnvironmentVariables(env);
|
|
24
29
|
this.buildError = null;
|
|
@@ -28,7 +33,7 @@ export class EdgeFunctionsRegistry {
|
|
|
28
33
|
this.userFunctions = [];
|
|
29
34
|
this.internalFunctions = [];
|
|
30
35
|
this.initialScan = this.doInitialScan();
|
|
31
|
-
this.setupWatchers(
|
|
36
|
+
this.setupWatchers();
|
|
32
37
|
}
|
|
33
38
|
async doInitialScan() {
|
|
34
39
|
await this.scanForFunctions();
|
|
@@ -306,13 +311,40 @@ export class EdgeFunctionsRegistry {
|
|
|
306
311
|
}
|
|
307
312
|
const { functionsConfig, graph, npmSpecifiersWithExtraneousFiles, success } = await this.runIsolate(this.functions, this.env, {
|
|
308
313
|
getFunctionsConfig: true,
|
|
314
|
+
importMapPaths: [this.importMapFromTOML, this.importMapFromDeployConfig].filter(nonNullable),
|
|
309
315
|
});
|
|
310
316
|
return { functionsConfig, graph, npmSpecifiersWithExtraneousFiles, success };
|
|
311
317
|
}
|
|
318
|
+
get internalDirectory() {
|
|
319
|
+
return join(this.projectDir, getPathInProject([INTERNAL_EDGE_FUNCTIONS_FOLDER]));
|
|
320
|
+
}
|
|
321
|
+
async readDeployConfig() {
|
|
322
|
+
const manifestPath = join(this.internalDirectory, 'manifest.json');
|
|
323
|
+
try {
|
|
324
|
+
const contents = await readFile(manifestPath, 'utf8');
|
|
325
|
+
const manifest = JSON.parse(contents);
|
|
326
|
+
return manifest;
|
|
327
|
+
}
|
|
328
|
+
catch { }
|
|
329
|
+
}
|
|
330
|
+
async scanForDeployConfig() {
|
|
331
|
+
const deployConfig = await this.readDeployConfig();
|
|
332
|
+
if (!deployConfig) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
if (deployConfig.version !== 1) {
|
|
336
|
+
throw new Error('Unsupported manifest format');
|
|
337
|
+
}
|
|
338
|
+
this.declarationsFromDeployConfig = deployConfig.functions;
|
|
339
|
+
this.importMapFromDeployConfig = deployConfig.import_map
|
|
340
|
+
? join(this.internalDirectory, deployConfig.import_map)
|
|
341
|
+
: undefined;
|
|
342
|
+
}
|
|
312
343
|
async scanForFunctions() {
|
|
313
344
|
const [internalFunctions, userFunctions] = await Promise.all([
|
|
314
|
-
this.bundler.find(this.
|
|
345
|
+
this.bundler.find([this.internalDirectory]),
|
|
315
346
|
this.bundler.find(this.directories),
|
|
347
|
+
this.scanForDeployConfig(),
|
|
316
348
|
]);
|
|
317
349
|
const functions = [...internalFunctions, ...userFunctions];
|
|
318
350
|
const newFunctions = functions.filter((func) => {
|
|
@@ -327,7 +359,7 @@ export class EdgeFunctionsRegistry {
|
|
|
327
359
|
this.userFunctions = userFunctions;
|
|
328
360
|
return { all: functions, new: newFunctions, deleted: deletedFunctions };
|
|
329
361
|
}
|
|
330
|
-
async setupWatchers(
|
|
362
|
+
async setupWatchers() {
|
|
331
363
|
if (!this.configPath) {
|
|
332
364
|
return;
|
|
333
365
|
}
|
|
@@ -344,16 +376,16 @@ export class EdgeFunctionsRegistry {
|
|
|
344
376
|
// directories, they might be importing files that are located in
|
|
345
377
|
// parent directories. So we watch the entire project directory for
|
|
346
378
|
// changes.
|
|
347
|
-
await this.setupWatcherForDirectory(
|
|
379
|
+
await this.setupWatcherForDirectory();
|
|
348
380
|
}
|
|
349
|
-
async setupWatcherForDirectory(
|
|
381
|
+
async setupWatcherForDirectory() {
|
|
350
382
|
const ignored = [`${this.servePath}/**`];
|
|
351
|
-
const watcher = await watchDebounced(
|
|
383
|
+
const watcher = await watchDebounced(this.projectDir, {
|
|
352
384
|
ignored,
|
|
353
385
|
onAdd: () => this.checkForAddedOrDeletedFunctions(),
|
|
354
386
|
onChange: (paths) => this.handleFileChange(paths),
|
|
355
387
|
onUnlink: () => this.checkForAddedOrDeletedFunctions(),
|
|
356
388
|
});
|
|
357
|
-
this.directoryWatchers.set(
|
|
389
|
+
this.directoryWatchers.set(this.projectDir, watcher);
|
|
358
390
|
}
|
|
359
391
|
}
|
|
@@ -51,7 +51,6 @@ export default class NetlifyFunction {
|
|
|
51
51
|
this.name = name;
|
|
52
52
|
this.displayName = displayName ?? name;
|
|
53
53
|
this.projectRoot = projectRoot;
|
|
54
|
-
// @ts-expect-error TS(2339) FIXME: Property 'runtime' does not exist on type 'Netlify... Remove this comment to see the full error message
|
|
55
54
|
this.runtime = runtime;
|
|
56
55
|
this.timeoutBackground = timeoutBackground;
|
|
57
56
|
this.timeoutSynchronous = timeoutSynchronous;
|
|
@@ -142,7 +141,9 @@ export default class NetlifyFunction {
|
|
|
142
141
|
return { includedFiles, srcFilesDiff };
|
|
143
142
|
}
|
|
144
143
|
catch (error) {
|
|
145
|
-
|
|
144
|
+
if (error instanceof Error) {
|
|
145
|
+
this.buildError = error;
|
|
146
|
+
}
|
|
146
147
|
return { error };
|
|
147
148
|
}
|
|
148
149
|
}
|
|
@@ -164,7 +165,6 @@ export default class NetlifyFunction {
|
|
|
164
165
|
async invoke(event = {}, context = {}) {
|
|
165
166
|
await this.buildQueue;
|
|
166
167
|
if (this.buildError) {
|
|
167
|
-
// @ts-expect-error TS(2339) FIXME: Property 'buildError' does not exist on type 'Netl... Remove this comment to see the full error message
|
|
168
168
|
return { result: null, error: { errorMessage: this.buildError.message } };
|
|
169
169
|
}
|
|
170
170
|
const timeout = this.isBackground ? this.timeoutBackground : this.timeoutSynchronous;
|
|
@@ -13,6 +13,7 @@ import runtimes from './runtimes/index.js';
|
|
|
13
13
|
export const DEFAULT_FUNCTION_URL_EXPRESSION = /^\/.netlify\/(functions|builders)\/([^/]+).*/;
|
|
14
14
|
const TYPES_PACKAGE = '@netlify/functions';
|
|
15
15
|
const ZIP_EXTENSION = '.zip';
|
|
16
|
+
const isInternalFunction = (func) => func.mainFile.includes(getPathInProject([INTERNAL_FUNCTIONS_FOLDER]));
|
|
16
17
|
/**
|
|
17
18
|
* @typedef {"buildError" | "extracted" | "loaded" | "missing-types-package" | "reloaded" | "reloading" | "removed"} FunctionEvent
|
|
18
19
|
*/
|
|
@@ -149,7 +150,6 @@ export class FunctionsRegistry {
|
|
|
149
150
|
? `rename the function file to ${chalk.underline(newFilename)}. Refer to https://ntl.fyi/functions-runtime for more information`
|
|
150
151
|
: `refer to https://ntl.fyi/functions-runtime`;
|
|
151
152
|
const warning = `The function is using the legacy CommonJS format. To start using ES modules, ${action}.`;
|
|
152
|
-
// @ts-expect-error TS(2322) FIXME: Type 'string' is not assignable to type 'never'.
|
|
153
153
|
FunctionsRegistry.logEvent(event, { func, warnings: [warning] });
|
|
154
154
|
}
|
|
155
155
|
else {
|
|
@@ -230,14 +230,7 @@ export class FunctionsRegistry {
|
|
|
230
230
|
}
|
|
231
231
|
/**
|
|
232
232
|
* Logs an event associated with functions.
|
|
233
|
-
*
|
|
234
|
-
* @param {FunctionEvent} event
|
|
235
|
-
* @param {object} data
|
|
236
|
-
* @param {NetlifyFunction} [data.func]
|
|
237
|
-
* @param {string[]} [data.warnings]
|
|
238
|
-
* @returns
|
|
239
233
|
*/
|
|
240
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'event' implicitly has an 'any' type.
|
|
241
234
|
static logEvent(event, { func, warnings = [] }) {
|
|
242
235
|
let warningsText = '';
|
|
243
236
|
if (warnings.length !== 0) {
|
|
@@ -280,18 +273,13 @@ export class FunctionsRegistry {
|
|
|
280
273
|
}
|
|
281
274
|
/**
|
|
282
275
|
* Adds a function to the registry
|
|
283
|
-
*
|
|
284
|
-
* @param {string} name
|
|
285
|
-
* @param {NetlifyFunction} funcBeforeHook
|
|
286
|
-
* @param {boolean} [isReload]
|
|
287
|
-
* @returns
|
|
288
276
|
*/
|
|
289
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
|
|
290
277
|
async registerFunction(name, funcBeforeHook, isReload = false) {
|
|
291
278
|
const { runtime } = funcBeforeHook;
|
|
292
279
|
// The `onRegister` hook allows runtimes to modify the function before it's
|
|
293
280
|
// registered, or to prevent it from being registered altogether if the
|
|
294
281
|
// hook returns `null`.
|
|
282
|
+
// @ts-expect-error FIXME
|
|
295
283
|
const func = typeof runtime.onRegister === 'function' ? runtime.onRegister(funcBeforeHook) : funcBeforeHook;
|
|
296
284
|
if (func === null) {
|
|
297
285
|
return;
|
|
@@ -339,31 +327,24 @@ export class FunctionsRegistry {
|
|
|
339
327
|
/**
|
|
340
328
|
* A proxy to zip-it-and-ship-it's `listFunctions` method. It exists just so
|
|
341
329
|
* that we can mock it in tests.
|
|
342
|
-
* @param {Parameters<listFunctions>} args
|
|
343
|
-
* @returns
|
|
344
330
|
*/
|
|
345
|
-
// @ts-expect-error TS(7019) FIXME: Rest parameter 'args' implicitly has an 'any[]' ty... Remove this comment to see the full error message
|
|
346
331
|
// eslint-disable-next-line class-methods-use-this
|
|
347
332
|
async listFunctions(...args) {
|
|
348
|
-
// @ts-expect-error TS(2556) FIXME: A spread argument must either have a tuple type or... Remove this comment to see the full error message
|
|
349
333
|
return await listFunctions(...args);
|
|
350
334
|
}
|
|
351
335
|
/**
|
|
352
336
|
* Takes a list of directories and scans for functions. It keeps tracks of
|
|
353
337
|
* any functions in those directories that we've previously seen, and takes
|
|
354
338
|
* care of registering and unregistering functions as they come and go.
|
|
355
|
-
*
|
|
356
|
-
* @param {string[]} relativeDirs
|
|
357
339
|
*/
|
|
358
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'relativeDirs' implicitly has an 'any' t... Remove this comment to see the full error message
|
|
359
340
|
async scan(relativeDirs) {
|
|
360
|
-
|
|
361
|
-
|
|
341
|
+
const directories = relativeDirs
|
|
342
|
+
.filter((dir) => Boolean(dir))
|
|
343
|
+
.map((dir) => (isAbsolute(dir) ? dir : join(this.projectRoot, dir)));
|
|
362
344
|
// check after filtering to filter out [undefined] for example
|
|
363
345
|
if (directories.length === 0) {
|
|
364
346
|
return;
|
|
365
347
|
}
|
|
366
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'path' implicitly has an 'any' type.
|
|
367
348
|
await Promise.all(directories.map((path) => FunctionsRegistry.prepareDirectoryScan(path)));
|
|
368
349
|
const functions = await this.listFunctions(directories, {
|
|
369
350
|
featureFlags: {
|
|
@@ -373,10 +354,18 @@ export class FunctionsRegistry {
|
|
|
373
354
|
// @ts-expect-error TS(2339) FIXME: Property 'config' does not exist on type 'Function... Remove this comment to see the full error message
|
|
374
355
|
config: this.config.functions,
|
|
375
356
|
});
|
|
357
|
+
// user-defined functions take precedence over internal functions,
|
|
358
|
+
// so we want to ignore any internal functions where there's a user-defined one with the same name
|
|
359
|
+
const ignoredFunctions = new Set(functions
|
|
360
|
+
.filter((func) => isInternalFunction(func) &&
|
|
361
|
+
this.functions.has(func.name) &&
|
|
362
|
+
!isInternalFunction(this.functions.get(func.name)))
|
|
363
|
+
.map((func) => func.name));
|
|
376
364
|
// Before registering any functions, we look for any functions that were on
|
|
377
365
|
// the previous list but are missing from the new one. We unregister them.
|
|
378
366
|
const deletedFunctions = [...this.functions.values()].filter((oldFunc) => {
|
|
379
|
-
const isFound = functions.some((newFunc) => newFunc.name
|
|
367
|
+
const isFound = functions.some((newFunc) => ignoredFunctions.has(newFunc.name) ||
|
|
368
|
+
(newFunc.name === oldFunc.name && newFunc.mainFile === oldFunc.mainFile));
|
|
380
369
|
return !isFound;
|
|
381
370
|
});
|
|
382
371
|
await Promise.all(deletedFunctions.map((func) => this.unregisterFunction(func)));
|
|
@@ -386,6 +375,9 @@ export class FunctionsRegistry {
|
|
|
386
375
|
// where the last ones precede the previous ones. This is why
|
|
387
376
|
// we reverse the array so we get the right functions precedence in the CLI.
|
|
388
377
|
functions.reverse().map(async ({ displayName, mainFile, name, runtime: runtimeName }) => {
|
|
378
|
+
if (ignoredFunctions.has(name)) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
389
381
|
const runtime = runtimes[runtimeName];
|
|
390
382
|
// If there is no matching runtime, it means this function is not yet
|
|
391
383
|
// supported in Netlify Dev.
|
|
@@ -400,7 +392,6 @@ export class FunctionsRegistry {
|
|
|
400
392
|
blobsContext: this.blobsContext,
|
|
401
393
|
// @ts-expect-error TS(2339) FIXME: Property 'config' does not exist on type 'Function... Remove this comment to see the full error message
|
|
402
394
|
config: this.config,
|
|
403
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'directory' implicitly has an 'any' type... Remove this comment to see the full error message
|
|
404
395
|
directory: directories.find((directory) => mainFile.startsWith(directory)),
|
|
405
396
|
mainFile,
|
|
406
397
|
name,
|
|
@@ -430,7 +421,6 @@ export class FunctionsRegistry {
|
|
|
430
421
|
}
|
|
431
422
|
FunctionsRegistry.logEvent('removed', { func });
|
|
432
423
|
});
|
|
433
|
-
// @ts-expect-error TS(7006) FIXME: Parameter 'path' implicitly has an 'any' type.
|
|
434
424
|
await Promise.all(directories.map((path) => this.setupDirectoryWatcher(path)));
|
|
435
425
|
}
|
|
436
426
|
/**
|
|
@@ -1,40 +1,6 @@
|
|
|
1
1
|
import * as go from './go/index.js';
|
|
2
2
|
import * as js from './js/index.js';
|
|
3
3
|
import * as rust from './rust/index.js';
|
|
4
|
-
/* eslint-enable import/no-namespace */
|
|
5
|
-
/**
|
|
6
|
-
* @callback BuildFunction
|
|
7
|
-
* @param {object} func
|
|
8
|
-
* @returns {Promise<{srcFiles: string[], buildPath?: string}>}
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* @callback GetBuildFunction
|
|
12
|
-
* @param {{ config: object, context: object, errorExit: function, func: object, functionsDirectory: string, projectRoot: string }} params
|
|
13
|
-
* @returns {Promise<BuildFunction>}
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* @callback InvokeFunction
|
|
17
|
-
* @param {{ context: object, event: object, func: object, timeout: number }} params
|
|
18
|
-
* @returns {Promise<{ body: object, statusCode: number }>}
|
|
19
|
-
*/
|
|
20
|
-
/**
|
|
21
|
-
* @callback OnDirectoryScanFunction
|
|
22
|
-
* @param {{ directory: string }} params
|
|
23
|
-
* @returns {Promise<undefined>}
|
|
24
|
-
*/
|
|
25
|
-
/**
|
|
26
|
-
* @callback OnRegisterFunction
|
|
27
|
-
* @param {object} func
|
|
28
|
-
* @returns {object|null}
|
|
29
|
-
*/
|
|
30
|
-
/**
|
|
31
|
-
* @typedef {object} Runtime
|
|
32
|
-
* @property {GetBuildFunction} getBuildFunction
|
|
33
|
-
* @property {InvokeFunction} invokeFunction
|
|
34
|
-
* @property {OnDirectoryScanFunction} [onDirectoryScan]
|
|
35
|
-
* @property {OnRegisterFunction} [onRegister]
|
|
36
|
-
* @property {string} name
|
|
37
|
-
*/
|
|
38
4
|
const runtimes = {
|
|
39
5
|
[go.name]: go,
|
|
40
6
|
[js.name]: js,
|
|
@@ -125,7 +125,7 @@ export const createHandler = function (options) {
|
|
|
125
125
|
'client-ip': [remoteAddress],
|
|
126
126
|
'x-nf-client-connection-ip': [remoteAddress],
|
|
127
127
|
'x-nf-account-id': [options.accountId],
|
|
128
|
-
'x-nf-site-id': [options?.siteInfo?.id
|
|
128
|
+
'x-nf-site-id': [options?.siteInfo?.id ?? 'unlinked'],
|
|
129
129
|
[efHeaders.Geo]: Buffer.from(JSON.stringify(geoLocation)).toString('base64'),
|
|
130
130
|
}).reduce((prev, [key, value]) => ({ ...prev, [key]: Array.isArray(value) ? value : [value] }), {});
|
|
131
131
|
const rawQuery = new URLSearchParams(requestQuery).toString();
|
|
@@ -228,7 +228,6 @@ const getFunctionsServer = (options) => {
|
|
|
228
228
|
// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
|
|
229
229
|
export const startFunctionsServer = async (options) => {
|
|
230
230
|
const { blobsContext, capabilities, command, config, debug, loadDistFunctions, settings, site, siteInfo, siteUrl, timeouts, } = options;
|
|
231
|
-
// @ts-expect-error TS(2345) FIXME: Argument of type '{ base: any; }' is not assignabl... Remove this comment to see the full error message
|
|
232
231
|
const internalFunctionsDir = await getInternalFunctionsDir({ base: site.root });
|
|
233
232
|
const functionsDirectories = [];
|
|
234
233
|
let manifest;
|
|
@@ -42,7 +42,6 @@ skipFunctionsCache, statusCb = () => {
|
|
|
42
42
|
}, syncFileLimit = DEFAULT_SYNC_LIMIT, tmpDir = temporaryDirectory(),
|
|
43
43
|
// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message
|
|
44
44
|
workingDir, } = {}) => {
|
|
45
|
-
// @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1.
|
|
46
45
|
statusCb({
|
|
47
46
|
type: 'hashing',
|
|
48
47
|
msg: `Hashing files...`,
|
|
@@ -85,7 +84,6 @@ workingDir, } = {}) => {
|
|
|
85
84
|
functionsCount > 0 && `${functionsCount} functions`,
|
|
86
85
|
edgeFunctionsCount > 0 && 'edge functions',
|
|
87
86
|
]);
|
|
88
|
-
// @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1.
|
|
89
87
|
statusCb({
|
|
90
88
|
type: 'hashing',
|
|
91
89
|
msg: `Finished hashing ${stats}`,
|
|
@@ -108,7 +106,6 @@ instead of manual deployment.
|
|
|
108
106
|
|
|
109
107
|
For more information, visit https://ntl.fyi/cli-native-modules.`);
|
|
110
108
|
}
|
|
111
|
-
// @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1.
|
|
112
109
|
statusCb({
|
|
113
110
|
type: 'create-deploy',
|
|
114
111
|
msg: 'CDN diffing files...',
|
|
@@ -132,7 +129,6 @@ For more information, visit https://ntl.fyi/cli-native-modules.`);
|
|
|
132
129
|
if (deployParams.body.async)
|
|
133
130
|
deploy = await waitForDiff(api, deploy.id, siteId, deployTimeout);
|
|
134
131
|
const { required: requiredFiles, required_functions: requiredFns } = deploy;
|
|
135
|
-
// @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1.
|
|
136
132
|
statusCb({
|
|
137
133
|
type: 'create-deploy',
|
|
138
134
|
msg: `CDN requesting ${requiredFiles.length} files${Array.isArray(requiredFns) ? ` and ${requiredFns.length} functions` : ''}`,
|
|
@@ -142,14 +138,12 @@ For more information, visit https://ntl.fyi/cli-native-modules.`);
|
|
|
142
138
|
const functionsUploadList = getUploadList(requiredFns, fnShaMap);
|
|
143
139
|
const uploadList = [...filesUploadList, ...functionsUploadList];
|
|
144
140
|
await uploadFiles(api, deployId, uploadList, { concurrentUpload, statusCb, maxRetry });
|
|
145
|
-
// @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1.
|
|
146
141
|
statusCb({
|
|
147
142
|
type: 'wait-for-deploy',
|
|
148
143
|
msg: 'Waiting for deploy to go live...',
|
|
149
144
|
phase: 'start',
|
|
150
145
|
});
|
|
151
146
|
deploy = await waitForDeploy(api, deployId, siteId, deployTimeout);
|
|
152
|
-
// @ts-expect-error TS(2554) FIXME: Expected 0 arguments, but got 1.
|
|
153
147
|
statusCb({
|
|
154
148
|
type: 'wait-for-deploy',
|
|
155
149
|
msg: draft ? 'Draft deploy is live!' : 'Deploy is live!',
|