netlify-cli 17.5.0 → 17.5.2

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.
@@ -1,538 +1,357 @@
1
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
- if (kind === "m") throw new TypeError("Private method is not writable");
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
- };
7
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
- };
12
- var _EdgeFunctionsRegistry_instances, _a, _EdgeFunctionsRegistry_bundler, _EdgeFunctionsRegistry_configPath, _EdgeFunctionsRegistry_debug, _EdgeFunctionsRegistry_directories, _EdgeFunctionsRegistry_internalDirectories, _EdgeFunctionsRegistry_getUpdatedConfig, _EdgeFunctionsRegistry_runIsolate, _EdgeFunctionsRegistry_buildError, _EdgeFunctionsRegistry_declarationsFromDeployConfig, _EdgeFunctionsRegistry_declarationsFromTOML, _EdgeFunctionsRegistry_env, _EdgeFunctionsRegistry_directoryWatchers, _EdgeFunctionsRegistry_dependencyPaths, _EdgeFunctionsRegistry_functionPaths, _EdgeFunctionsRegistry_manifest, _EdgeFunctionsRegistry_userFunctions, _EdgeFunctionsRegistry_internalFunctions, _EdgeFunctionsRegistry_initialScan, _EdgeFunctionsRegistry_routes, _EdgeFunctionsRegistry_servePath, _EdgeFunctionsRegistry_doInitialScan, _EdgeFunctionsRegistry_functions_get, _EdgeFunctionsRegistry_build, _EdgeFunctionsRegistry_buildRoutes, _EdgeFunctionsRegistry_checkForAddedOrDeletedFunctions, _EdgeFunctionsRegistry_getDeclarationsFromTOML, _EdgeFunctionsRegistry_getEnvironmentVariables, _EdgeFunctionsRegistry_handleFileChange, _EdgeFunctionsRegistry_logEvent, _EdgeFunctionsRegistry_processGraph, _EdgeFunctionsRegistry_runBuild, _EdgeFunctionsRegistry_scanForFunctions, _EdgeFunctionsRegistry_setupWatchers, _EdgeFunctionsRegistry_setupWatcherForDirectory, _EdgeFunctionsRegistry_getDisplayName;
13
1
  import { fileURLToPath } from 'url';
14
- import { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, log, warn, watchDebounced, } from '../../utils/command-helpers.mjs';
15
- /** @typedef {import('@netlify/edge-bundler').Declaration} Declaration */
16
- /** @typedef {import('@netlify/edge-bundler').EdgeFunction} EdgeFunction */
17
- /**
18
- * @typedef {"buildError" | "loaded" | "reloaded" | "reloading" | "removed"} EdgeFunctionEvent
19
- */
20
- /** @typedef {import('@netlify/edge-bundler').FunctionConfig} FunctionConfig */
21
- /** @typedef {import('@netlify/edge-bundler').Manifest} Manifest */
22
- /** @typedef {import('@netlify/edge-bundler').ModuleGraph} ModuleGraph */
23
- /** @typedef {Awaited<ReturnType<typeof import('@netlify/edge-bundler').serve>>} RunIsolate */
24
- /** @typedef {Omit<Manifest["routes"][0], "pattern"> & { pattern: RegExp }} Route */
2
+ import { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, nonNullable, chalk, log, warn, watchDebounced, isNodeError, } from '../../utils/command-helpers.mjs';
25
3
  const featureFlags = { edge_functions_correct_order: true };
26
4
  export class EdgeFunctionsRegistry {
5
+ constructor({ bundler, config, configPath, directories, env, getUpdatedConfig, internalDirectories, internalFunctions, projectDir, runIsolate, servePath, }) {
6
+ this.buildError = null;
7
+ this.dependencyPaths = new Map();
8
+ this.directoryWatchers = new Map();
9
+ this.functionPaths = new Map();
10
+ this.internalFunctions = [];
11
+ this.manifest = null;
12
+ this.routes = [];
13
+ this.userFunctions = [];
14
+ this.bundler = bundler;
15
+ this.configPath = configPath;
16
+ this.directories = directories;
17
+ this.internalDirectories = internalDirectories;
18
+ this.getUpdatedConfig = getUpdatedConfig;
19
+ this.runIsolate = runIsolate;
20
+ this.servePath = servePath;
21
+ this.declarationsFromDeployConfig = internalFunctions;
22
+ this.declarationsFromTOML = EdgeFunctionsRegistry.getDeclarationsFromTOML(config);
23
+ this.env = EdgeFunctionsRegistry.getEnvironmentVariables(env);
24
+ this.buildError = null;
25
+ this.directoryWatchers = new Map();
26
+ this.dependencyPaths = new Map();
27
+ this.functionPaths = new Map();
28
+ this.userFunctions = [];
29
+ this.internalFunctions = [];
30
+ this.initialScan = this.doInitialScan();
31
+ this.setupWatchers(projectDir);
32
+ }
33
+ async doInitialScan() {
34
+ await this.scanForFunctions();
35
+ try {
36
+ const { warnings } = await this.build();
37
+ this.functions.forEach((func) => {
38
+ this.logEvent('loaded', { functionName: func.name, warnings: warnings[func.name] });
39
+ });
40
+ }
41
+ catch {
42
+ // no-op
43
+ }
44
+ }
45
+ get functions() {
46
+ return [...this.internalFunctions, ...this.userFunctions];
47
+ }
48
+ async build() {
49
+ const warnings = {};
50
+ try {
51
+ const { functionsConfig, graph, npmSpecifiersWithExtraneousFiles, success } = await this.runBuild();
52
+ if (!success) {
53
+ throw new Error('Build error');
54
+ }
55
+ this.buildError = null;
56
+ // We use one index to loop over both internal and user function, because we know that this.#functions has internalFunctions first.
57
+ // functionsConfig therefore contains first all internal functionConfigs and then user functionConfigs
58
+ let index = 0;
59
+ const internalFunctionConfigs = this.internalFunctions.reduce(
60
+ // eslint-disable-next-line no-plusplus
61
+ (acc, func) => ({ ...acc, [func.name]: functionsConfig[index++] }), {});
62
+ const userFunctionConfigs = this.userFunctions.reduce(
63
+ // eslint-disable-next-line no-plusplus
64
+ (acc, func) => ({ ...acc, [func.name]: functionsConfig[index++] }), {});
65
+ const { manifest, routes, unroutedFunctions } = this.buildRoutes(internalFunctionConfigs, userFunctionConfigs);
66
+ this.manifest = manifest;
67
+ this.routes = routes;
68
+ unroutedFunctions.forEach((name) => {
69
+ warnings[name] = warnings[name] || [];
70
+ warnings[name].push(`Edge function is not accessible because it does not have a path configured. Learn more at https://ntl.fyi/edge-create.`);
71
+ });
72
+ for (const functionName in userFunctionConfigs) {
73
+ if ('paths' in userFunctionConfigs[functionName]) {
74
+ warnings[functionName] = warnings[functionName] || [];
75
+ warnings[functionName].push(`Unknown 'paths' configuration property. Did you mean 'path'?`);
76
+ }
77
+ }
78
+ this.processGraph(graph);
79
+ if (npmSpecifiersWithExtraneousFiles.length !== 0) {
80
+ const modules = npmSpecifiersWithExtraneousFiles.map((name) => chalk.yellow(name)).join(', ');
81
+ log(`${NETLIFYDEVWARN} The following npm modules, which are directly or indirectly imported by an edge function, may not be supported: ${modules}. For more information, visit https://ntl.fyi/edge-functions-npm.`);
82
+ }
83
+ return { warnings };
84
+ }
85
+ catch (error) {
86
+ if (error instanceof Error) {
87
+ this.buildError = error;
88
+ }
89
+ throw error;
90
+ }
91
+ }
27
92
  /**
28
- * @param {Object} opts
29
- * @param {import('@netlify/edge-bundler')} opts.bundler
30
- * @param {object} opts.config
31
- * @param {string} opts.configPath
32
- * @param {boolean} opts.debug
33
- * @param {string[]} opts.directories
34
- * @param {Record<string, { sources: string[], value: string}>} opts.env
35
- * @param {() => Promise<object>} opts.getUpdatedConfig
36
- * @param {string[]} opts.internalDirectories
37
- * @param {Declaration[]} opts.internalFunctions
38
- * @param {string} opts.projectDir
39
- * @param {RunIsolate} opts.runIsolate
40
- * @param {string} opts.servePath
93
+ * Builds a manifest and corresponding routes for the functions in the
94
+ * registry, taking into account the declarations from the TOML, from
95
+ * the deploy configuration API, and from the in-source configuration
96
+ * found in both internal and user functions.
41
97
  */
42
- constructor({
43
- // @ts-expect-error TS(7031) FIXME: Binding element 'bundler' implicitly has an 'any' ... Remove this comment to see the full error message
44
- bundler,
45
- // @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message
46
- config,
47
- // @ts-expect-error TS(7031) FIXME: Binding element 'configPath' implicitly has an 'an... Remove this comment to see the full error message
48
- configPath,
49
- // @ts-expect-error TS(7031) FIXME: Binding element 'debug' implicitly has an 'any' ty... Remove this comment to see the full error message
50
- debug,
51
- // @ts-expect-error TS(7031) FIXME: Binding element 'directories' implicitly has an 'a... Remove this comment to see the full error message
52
- directories,
53
- // @ts-expect-error TS(7031) FIXME: Binding element 'env' implicitly has an 'any' type... Remove this comment to see the full error message
54
- env,
55
- // @ts-expect-error TS(7031) FIXME: Binding element 'getUpdatedConfig' implicitly has ... Remove this comment to see the full error message
56
- getUpdatedConfig,
57
- // @ts-expect-error TS(7031) FIXME: Binding element 'internalDirectories' implicitly h... Remove this comment to see the full error message
58
- internalDirectories,
59
- // @ts-expect-error TS(7031) FIXME: Binding element 'internalFunctions' implicitly has... Remove this comment to see the full error message
60
- internalFunctions,
61
- // @ts-expect-error TS(7031) FIXME: Binding element 'projectDir' implicitly has an 'an... Remove this comment to see the full error message
62
- projectDir,
63
- // @ts-expect-error TS(7031) FIXME: Binding element 'runIsolate' implicitly has an 'an... Remove this comment to see the full error message
64
- runIsolate,
65
- // @ts-expect-error TS(7031) FIXME: Binding element 'servePath' implicitly has an 'any... Remove this comment to see the full error message
66
- servePath, }) {
67
- _EdgeFunctionsRegistry_instances.add(this);
68
- /** @type {import('@netlify/edge-bundler')} */
69
- _EdgeFunctionsRegistry_bundler.set(this, void 0);
70
- /** @type {string} */
71
- _EdgeFunctionsRegistry_configPath.set(this, void 0);
72
- /** @type {boolean} */
73
- _EdgeFunctionsRegistry_debug.set(this, void 0);
74
- /** @type {string[]} */
75
- _EdgeFunctionsRegistry_directories.set(this, void 0);
76
- /** @type {string[]} */
77
- _EdgeFunctionsRegistry_internalDirectories.set(this, void 0);
78
- /** @type {() => Promise<object>} */
79
- _EdgeFunctionsRegistry_getUpdatedConfig.set(this, void 0);
80
- /** @type {RunIsolate} */
81
- _EdgeFunctionsRegistry_runIsolate.set(this, void 0);
82
- /** @type {Error | null} */
83
- _EdgeFunctionsRegistry_buildError.set(this, null
84
- /** @type {Declaration[]} */
85
- );
86
- /** @type {Declaration[]} */
87
- _EdgeFunctionsRegistry_declarationsFromDeployConfig.set(this, void 0);
88
- /** @type {Declaration[]} */
89
- _EdgeFunctionsRegistry_declarationsFromTOML.set(this, void 0);
90
- /** @type {Record<string, string>} */
91
- _EdgeFunctionsRegistry_env.set(this, void 0);
92
- /** @type {Map<string, import('chokidar').FSWatcher>} */
93
- _EdgeFunctionsRegistry_directoryWatchers.set(this, new Map()
94
- /** @type {Map<string, string[]>} */
95
- );
96
- /** @type {Map<string, string[]>} */
97
- _EdgeFunctionsRegistry_dependencyPaths.set(this, new Map()
98
- /** @type {Map<string, string>} */
99
- );
100
- /** @type {Map<string, string>} */
101
- _EdgeFunctionsRegistry_functionPaths.set(this, new Map()
102
- /** @type {Manifest | null} */
103
- );
104
- /** @type {Manifest | null} */
105
- _EdgeFunctionsRegistry_manifest.set(this, null
106
- /** @type {EdgeFunction[]} */
107
- );
108
- /** @type {EdgeFunction[]} */
109
- _EdgeFunctionsRegistry_userFunctions.set(this, []
110
- /** @type {EdgeFunction[]} */
111
- );
112
- /** @type {EdgeFunction[]} */
113
- _EdgeFunctionsRegistry_internalFunctions.set(this, []
114
- /** @type {Promise<void>} */
115
- );
116
- /** @type {Promise<void>} */
117
- _EdgeFunctionsRegistry_initialScan.set(this, void 0);
118
- /** @type {Route[]} */
119
- _EdgeFunctionsRegistry_routes.set(this, []
120
- /** @type {string} */
121
- );
122
- /** @type {string} */
123
- _EdgeFunctionsRegistry_servePath.set(this, void 0);
124
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_bundler, bundler, "f");
125
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_configPath, configPath, "f");
126
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_debug, debug, "f");
127
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_directories, directories, "f");
128
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_internalDirectories, internalDirectories, "f");
129
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_getUpdatedConfig, getUpdatedConfig, "f");
130
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_runIsolate, runIsolate, "f");
131
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_servePath, servePath, "f");
132
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_declarationsFromDeployConfig, internalFunctions, "f");
133
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_declarationsFromTOML, __classPrivateFieldGet(EdgeFunctionsRegistry, _a, "m", _EdgeFunctionsRegistry_getDeclarationsFromTOML).call(EdgeFunctionsRegistry, config), "f");
134
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_env, __classPrivateFieldGet(EdgeFunctionsRegistry, _a, "m", _EdgeFunctionsRegistry_getEnvironmentVariables).call(EdgeFunctionsRegistry, env), "f");
135
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_buildError, null, "f");
136
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_directoryWatchers, new Map(), "f");
137
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_dependencyPaths, new Map(), "f");
138
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_functionPaths, new Map(), "f");
139
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_userFunctions, [], "f");
140
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_internalFunctions, [], "f");
141
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_initialScan, __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_doInitialScan).call(this), "f");
142
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_setupWatchers).call(this, projectDir);
98
+ buildRoutes(internalFunctionConfigs, userFunctionConfigs) {
99
+ const declarations = this.bundler.mergeDeclarations(this.declarationsFromTOML, userFunctionConfigs, internalFunctionConfigs, this.declarationsFromDeployConfig, featureFlags);
100
+ const { declarationsWithoutFunction, manifest, unroutedFunctions } = this.bundler.generateManifest({
101
+ declarations,
102
+ userFunctionConfig: userFunctionConfigs,
103
+ internalFunctionConfig: internalFunctionConfigs,
104
+ functions: this.functions,
105
+ featureFlags,
106
+ });
107
+ const routes = [...manifest.routes, ...manifest.post_cache_routes].map((route) => ({
108
+ ...route,
109
+ pattern: new RegExp(route.pattern),
110
+ }));
111
+ return { declarationsWithoutFunction, manifest, routes, unroutedFunctions };
112
+ }
113
+ async checkForAddedOrDeletedFunctions() {
114
+ const { deleted: deletedFunctions, new: newFunctions } = await this.scanForFunctions();
115
+ if (newFunctions.length === 0 && deletedFunctions.length === 0) {
116
+ return;
117
+ }
118
+ try {
119
+ const { warnings } = await this.build();
120
+ deletedFunctions.forEach((func) => {
121
+ this.logEvent('removed', { functionName: func.name, warnings: warnings[func.name] });
122
+ });
123
+ newFunctions.forEach((func) => {
124
+ this.logEvent('loaded', { functionName: func.name, warnings: warnings[func.name] });
125
+ });
126
+ }
127
+ catch {
128
+ // no-op
129
+ }
130
+ }
131
+ static getDeclarationsFromTOML(config) {
132
+ const { edge_functions: edgeFunctions = [] } = config;
133
+ return edgeFunctions;
134
+ }
135
+ getDisplayName(func) {
136
+ const declarations = [...this.declarationsFromTOML, ...this.declarationsFromDeployConfig];
137
+ return declarations.find((declaration) => declaration.function === func)?.name ?? func;
138
+ }
139
+ static getEnvironmentVariables(envConfig) {
140
+ const env = Object.create(null);
141
+ Object.entries(envConfig).forEach(([key, variable]) => {
142
+ if (variable.sources.includes('ui') ||
143
+ variable.sources.includes('account') ||
144
+ variable.sources.includes('addons') ||
145
+ variable.sources.includes('internal') ||
146
+ variable.sources.some((source) => source.startsWith('.env'))) {
147
+ env[key] = variable.value;
148
+ }
149
+ });
150
+ env.DENO_REGION = 'local';
151
+ return env;
152
+ }
153
+ async handleFileChange(paths) {
154
+ const matchingFunctions = new Set([
155
+ ...paths.map((path) => this.functionPaths.get(path)),
156
+ ...paths.flatMap((path) => this.dependencyPaths.get(path)),
157
+ ].filter(nonNullable));
158
+ // If the file is not associated with any function, there's no point in
159
+ // building. However, it might be that the path is in fact associated with
160
+ // a function but we just haven't registered it due to a build error. So if
161
+ // there was a build error, let's always build.
162
+ if (matchingFunctions.size === 0 && this.buildError === null) {
163
+ return;
164
+ }
165
+ this.logEvent('reloading', {});
166
+ try {
167
+ const { warnings } = await this.build();
168
+ const functionNames = [...matchingFunctions];
169
+ if (functionNames.length === 0) {
170
+ this.logEvent('reloaded', {});
171
+ }
172
+ else {
173
+ functionNames.forEach((functionName) => {
174
+ this.logEvent('reloaded', { functionName, warnings: warnings[functionName] });
175
+ });
176
+ }
177
+ }
178
+ catch (error) {
179
+ if (isNodeError(error)) {
180
+ this.logEvent('buildError', { buildError: error });
181
+ }
182
+ }
183
+ }
184
+ async initialize() {
185
+ return await this.initialScan;
143
186
  }
144
187
  /**
145
- * @return {Promise<void>}
188
+ * Logs an event associated with functions.
146
189
  */
147
- async initialize() {
148
- return await __classPrivateFieldGet(this, _EdgeFunctionsRegistry_initialScan, "f");
190
+ logEvent(event, { buildError, functionName, warnings = [] }) {
191
+ const subject = functionName ? `edge function ${chalk.yellow(this.getDisplayName(functionName))}` : 'edge functions';
192
+ const warningsText = warnings.length === 0 ? '' : ` with warnings:\n${warnings.map((warning) => ` - ${warning}`).join('\n')}`;
193
+ if (event === 'buildError') {
194
+ log(`${NETLIFYDEVERR} ${chalk.red('Failed to load')} ${subject}: ${buildError}`);
195
+ return;
196
+ }
197
+ if (event === 'loaded') {
198
+ const icon = warningsText ? NETLIFYDEVWARN : NETLIFYDEVLOG;
199
+ const color = warningsText ? chalk.yellow : chalk.green;
200
+ log(`${icon} ${color('Loaded')} ${subject}${warningsText}`);
201
+ return;
202
+ }
203
+ if (event === 'reloaded') {
204
+ const icon = warningsText ? NETLIFYDEVWARN : NETLIFYDEVLOG;
205
+ const color = warningsText ? chalk.yellow : chalk.green;
206
+ log(`${icon} ${color('Reloaded')} ${subject}${warningsText}`);
207
+ return;
208
+ }
209
+ if (event === 'reloading') {
210
+ log(`${NETLIFYDEVLOG} ${chalk.magenta('Reloading')} ${subject}...`);
211
+ return;
212
+ }
213
+ if (event === 'removed') {
214
+ log(`${NETLIFYDEVLOG} ${chalk.magenta('Removed')} ${subject}`);
215
+ }
149
216
  }
150
217
  /**
151
218
  * Returns the functions in the registry that should run for a given URL path
152
219
  * and HTTP method, based on the routes registered for each function.
153
- *
154
- * @param {string} urlPath
155
- * @param {string} method
156
220
  */
157
- // @ts-expect-error TS(7006) FIXME: Parameter 'urlPath' implicitly has an 'any' type.
158
221
  matchURLPath(urlPath, method) {
159
- /** @type string[] */
160
- // @ts-expect-error TS(7034) FIXME: Variable 'functionNames' implicitly has type 'any[... Remove this comment to see the full error message
161
222
  const functionNames = [];
162
- /** @type number[] */
163
- // @ts-expect-error TS(7034) FIXME: Variable 'routeIndexes' implicitly has type 'any[]... Remove this comment to see the full error message
164
223
  const routeIndexes = [];
165
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_routes, "f").forEach((route, index) => {
166
- // @ts-expect-error TS(2339) FIXME: Property 'methods' does not exist on type 'never'.
224
+ this.routes.forEach((route, index) => {
167
225
  if (route.methods && route.methods.length !== 0 && !route.methods.includes(method)) {
168
226
  return;
169
227
  }
170
- // @ts-expect-error TS(2339) FIXME: Property 'pattern' does not exist on type 'never'.
171
228
  if (!route.pattern.test(urlPath)) {
172
229
  return;
173
230
  }
174
- // @ts-expect-error TS(2339) FIXME: Property 'function_config' does not exist on type ... Remove this comment to see the full error message
175
- const isExcluded = __classPrivateFieldGet(this, _EdgeFunctionsRegistry_manifest, "f")?.function_config[route.function]?.excluded_patterns?.some((pattern) => new RegExp(pattern).test(urlPath));
231
+ const isExcluded = this.manifest?.function_config[route.function]?.excluded_patterns?.some((pattern) => new RegExp(pattern).test(urlPath));
176
232
  if (isExcluded) {
177
233
  return;
178
234
  }
179
- // @ts-expect-error TS(2339) FIXME: Property 'function' does not exist on type 'never'... Remove this comment to see the full error message
180
235
  functionNames.push(route.function);
181
236
  routeIndexes.push(index);
182
237
  });
238
+ const routes = [...(this.manifest?.routes || []), ...(this.manifest?.post_cache_routes || [])].map((route) => ({
239
+ function: route.function,
240
+ path: route.path,
241
+ pattern: route.pattern,
242
+ }));
183
243
  const invocationMetadata = {
184
- // @ts-expect-error TS(2339) FIXME: Property 'function_config' does not exist on type ... Remove this comment to see the full error message
185
- function_config: __classPrivateFieldGet(this, _EdgeFunctionsRegistry_manifest, "f")?.function_config,
186
- // @ts-expect-error TS(7005) FIXME: Variable 'routeIndexes' implicitly has an 'any[]' ... Remove this comment to see the full error message
244
+ function_config: this.manifest?.function_config,
187
245
  req_routes: routeIndexes,
188
- // @ts-expect-error TS(2339) FIXME: Property 'routes' does not exist on type 'never'.
189
- routes: __classPrivateFieldGet(this, _EdgeFunctionsRegistry_manifest, "f")?.routes.map((route) => ({
190
- function: route.function,
191
- path: route.path,
192
- pattern: route.pattern,
193
- })),
246
+ routes,
194
247
  };
195
- // @ts-expect-error TS(7005) FIXME: Variable 'functionNames' implicitly has an 'any[]'... Remove this comment to see the full error message
196
248
  return { functionNames, invocationMetadata };
197
249
  }
198
- }
199
- _a = EdgeFunctionsRegistry, _EdgeFunctionsRegistry_bundler = new WeakMap(), _EdgeFunctionsRegistry_configPath = new WeakMap(), _EdgeFunctionsRegistry_debug = new WeakMap(), _EdgeFunctionsRegistry_directories = new WeakMap(), _EdgeFunctionsRegistry_internalDirectories = new WeakMap(), _EdgeFunctionsRegistry_getUpdatedConfig = new WeakMap(), _EdgeFunctionsRegistry_runIsolate = new WeakMap(), _EdgeFunctionsRegistry_buildError = new WeakMap(), _EdgeFunctionsRegistry_declarationsFromDeployConfig = new WeakMap(), _EdgeFunctionsRegistry_declarationsFromTOML = new WeakMap(), _EdgeFunctionsRegistry_env = new WeakMap(), _EdgeFunctionsRegistry_directoryWatchers = new WeakMap(), _EdgeFunctionsRegistry_dependencyPaths = new WeakMap(), _EdgeFunctionsRegistry_functionPaths = new WeakMap(), _EdgeFunctionsRegistry_manifest = new WeakMap(), _EdgeFunctionsRegistry_userFunctions = new WeakMap(), _EdgeFunctionsRegistry_internalFunctions = new WeakMap(), _EdgeFunctionsRegistry_initialScan = new WeakMap(), _EdgeFunctionsRegistry_routes = new WeakMap(), _EdgeFunctionsRegistry_servePath = new WeakMap(), _EdgeFunctionsRegistry_instances = new WeakSet(), _EdgeFunctionsRegistry_doInitialScan =
200
- /**
201
- * @returns {Promise<void>}
202
- */
203
- async function _EdgeFunctionsRegistry_doInitialScan() {
204
- await __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_scanForFunctions).call(this);
205
- try {
206
- const { warnings } = await __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_build).call(this);
207
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "a", _EdgeFunctionsRegistry_functions_get).forEach((func) => {
208
- // @ts-expect-error TS(2345) FIXME: Argument of type '{ functionName: any; warnings: a... Remove this comment to see the full error message
209
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_logEvent).call(this, 'loaded', { functionName: func.name, warnings: warnings[func.name] });
250
+ /**
251
+ * Takes the module graph returned from the server and tracks dependencies of
252
+ * each function.
253
+ */
254
+ processGraph(graph) {
255
+ if (!graph) {
256
+ warn('Could not process edge functions dependency graph. Live reload will not be available.');
257
+ return;
258
+ }
259
+ // Creating a Map from `this.functions` that maps function paths to function
260
+ // names. This allows us to match modules against functions in O(1) time as
261
+ // opposed to O(n).
262
+ // eslint-disable-next-line unicorn/prefer-spread
263
+ const functionPaths = new Map(Array.from(this.functions, (func) => [func.path, func.name]));
264
+ // Mapping file URLs to names of functions that use them as dependencies.
265
+ const dependencyPaths = new Map();
266
+ const { modules } = graph;
267
+ modules.forEach(({ dependencies = [], specifier }) => {
268
+ if (!specifier.startsWith('file://')) {
269
+ return;
270
+ }
271
+ const path = fileURLToPath(specifier);
272
+ const functionMatch = functionPaths.get(path);
273
+ if (!functionMatch) {
274
+ return;
275
+ }
276
+ dependencies.forEach((dependency) => {
277
+ // We're interested in tracking local dependencies, so we only look at
278
+ // specifiers with the `file:` protocol.
279
+ if (dependency.code === undefined ||
280
+ typeof dependency.code.specifier !== 'string' ||
281
+ !dependency.code.specifier.startsWith('file://')) {
282
+ return;
283
+ }
284
+ const { specifier: dependencyURL } = dependency.code;
285
+ const dependencyPath = fileURLToPath(dependencyURL);
286
+ const functions = dependencyPaths.get(dependencyPath) || [];
287
+ dependencyPaths.set(dependencyPath, [...functions, functionMatch]);
288
+ });
210
289
  });
290
+ this.dependencyPaths = dependencyPaths;
291
+ this.functionPaths = functionPaths;
211
292
  }
212
- catch {
213
- // no-op
214
- }
215
- }, _EdgeFunctionsRegistry_functions_get = function _EdgeFunctionsRegistry_functions_get() {
216
- return [...__classPrivateFieldGet(this, _EdgeFunctionsRegistry_internalFunctions, "f"), ...__classPrivateFieldGet(this, _EdgeFunctionsRegistry_userFunctions, "f")];
217
- }, _EdgeFunctionsRegistry_build =
218
- /**
219
- * @return {Promise<{warnings: Record<string, string[]>}>}
220
- */
221
- async function _EdgeFunctionsRegistry_build() {
222
293
  /**
223
- * @type Record<string, string[]>
294
+ * Thin wrapper for `#runIsolate` that skips running a build and returns an
295
+ * empty response if there are no functions in the registry.
224
296
  */
225
- const warnings = {};
226
- try {
227
- const { functionsConfig, graph, npmSpecifiersWithExtraneousFiles, success } = await __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_runBuild).call(this);
228
- if (!success) {
229
- throw new Error('Build error');
297
+ async runBuild() {
298
+ if (this.functions.length === 0) {
299
+ return {
300
+ functionsConfig: [],
301
+ npmSpecifiersWithExtraneousFiles: [],
302
+ success: true,
303
+ };
230
304
  }
231
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_buildError, null, "f");
232
- // We use one index to loop over both internal and user function, because we know that this.#functions has internalFunctions first.
233
- // functionsConfig therefore contains first all internal functionConfigs and then user functionConfigs
234
- let index = 0;
235
- /** @type {Record<string, FunctionConfig>} */
236
- const internalFunctionConfigs = __classPrivateFieldGet(this, _EdgeFunctionsRegistry_internalFunctions, "f").reduce(
237
- // @ts-expect-error TS(2339) FIXME: Property 'name' does not exist on type 'never'.
238
- // eslint-disable-next-line no-plusplus
239
- (acc, func) => ({ ...acc, [func.name]: functionsConfig[index++] }), {});
240
- /** @type {Record<string, FunctionConfig>} */
241
- const userFunctionConfigs = __classPrivateFieldGet(this, _EdgeFunctionsRegistry_userFunctions, "f").reduce(
242
- // @ts-expect-error TS(2339) FIXME: Property 'name' does not exist on type 'never'.
243
- // eslint-disable-next-line no-plusplus
244
- (acc, func) => ({ ...acc, [func.name]: functionsConfig[index++] }), {});
245
- const { manifest, routes, unroutedFunctions } = __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_buildRoutes).call(this, internalFunctionConfigs, userFunctionConfigs);
246
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_manifest, manifest, "f");
247
- // @ts-expect-error TS(2322) FIXME: Type 'any[]' is not assignable to type 'never[]'.
248
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_routes, routes, "f");
249
- // @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
250
- unroutedFunctions.forEach((name) => {
251
- // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
252
- warnings[name] = warnings[name] || [];
253
- // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
254
- warnings[name].push(`Edge function is not accessible because it does not have a path configured. Learn more at https://ntl.fyi/edge-create.`);
305
+ const { functionsConfig, graph, npmSpecifiersWithExtraneousFiles, success } = await this.runIsolate(this.functions, this.env, {
306
+ getFunctionsConfig: true,
255
307
  });
256
- for (const functionName in userFunctionConfigs) {
257
- // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
258
- if ('paths' in userFunctionConfigs[functionName]) {
259
- // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
260
- warnings[functionName] = warnings[functionName] || [];
261
- // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
262
- warnings[functionName].push(`Unknown 'paths' configuration property. Did you mean 'path'?`);
263
- }
264
- }
265
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_processGraph).call(this, graph);
266
- if (npmSpecifiersWithExtraneousFiles.length !== 0) {
267
- // @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type.
268
- const modules = npmSpecifiersWithExtraneousFiles.map((name) => chalk.yellow(name)).join(', ');
269
- log(`${NETLIFYDEVWARN} The following npm modules, which are directly or indirectly imported by an edge function, may not be supported: ${modules}. For more information, visit https://ntl.fyi/edge-functions-npm.`);
270
- }
271
- return { warnings };
308
+ return { functionsConfig, graph, npmSpecifiersWithExtraneousFiles, success };
272
309
  }
273
- catch (error) {
274
- // @ts-expect-error TS(2322) FIXME: Type 'unknown' is not assignable to type 'null'.
275
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_buildError, error, "f");
276
- throw error;
277
- }
278
- }, _EdgeFunctionsRegistry_buildRoutes = function _EdgeFunctionsRegistry_buildRoutes(internalFunctionConfigs, userFunctionConfigs) {
279
- const declarations = __classPrivateFieldGet(this, _EdgeFunctionsRegistry_bundler, "f").mergeDeclarations(__classPrivateFieldGet(this, _EdgeFunctionsRegistry_declarationsFromTOML, "f"), userFunctionConfigs, internalFunctionConfigs, __classPrivateFieldGet(this, _EdgeFunctionsRegistry_declarationsFromDeployConfig, "f"), featureFlags);
280
- const { declarationsWithoutFunction, manifest, unroutedFunctions } = __classPrivateFieldGet(this, _EdgeFunctionsRegistry_bundler, "f").generateManifest({
281
- declarations,
282
- userFunctionConfig: userFunctionConfigs,
283
- internalFunctionConfig: internalFunctionConfigs,
284
- functions: __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "a", _EdgeFunctionsRegistry_functions_get),
285
- featureFlags,
286
- });
287
- const routes = [...manifest.routes, ...manifest.post_cache_routes].map((route) => ({
288
- ...route,
289
- pattern: new RegExp(route.pattern),
290
- }));
291
- return { declarationsWithoutFunction, manifest, routes, unroutedFunctions };
292
- }, _EdgeFunctionsRegistry_checkForAddedOrDeletedFunctions =
293
- /**
294
- * @returns {Promise<void>}
295
- */
296
- async function _EdgeFunctionsRegistry_checkForAddedOrDeletedFunctions() {
297
- const { deleted: deletedFunctions, new: newFunctions } = await __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_scanForFunctions).call(this);
298
- if (newFunctions.length === 0 && deletedFunctions.length === 0) {
299
- return;
300
- }
301
- try {
302
- const { warnings } = await __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_build).call(this);
303
- deletedFunctions.forEach((func) => {
304
- // @ts-expect-error TS(2345) FIXME: Argument of type '{ functionName: any; warnings: a... Remove this comment to see the full error message
305
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_logEvent).call(this, 'removed', { functionName: func.name, warnings: warnings[func.name] });
310
+ async scanForFunctions() {
311
+ const [internalFunctions, userFunctions] = await Promise.all([
312
+ this.bundler.find(this.internalDirectories),
313
+ this.bundler.find(this.directories),
314
+ ]);
315
+ const functions = [...internalFunctions, ...userFunctions];
316
+ const newFunctions = functions.filter((func) => {
317
+ const functionExists = this.functions.some((existingFunc) => func.name === existingFunc.name && func.path === existingFunc.path);
318
+ return !functionExists;
306
319
  });
307
- newFunctions.forEach((func) => {
308
- // @ts-expect-error TS(2345) FIXME: Argument of type '{ functionName: any; warnings: a... Remove this comment to see the full error message
309
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_logEvent).call(this, 'loaded', { functionName: func.name, warnings: warnings[func.name] });
320
+ const deletedFunctions = this.functions.filter((existingFunc) => {
321
+ const functionExists = functions.some((func) => func.name === existingFunc.name && func.path === existingFunc.path);
322
+ return !functionExists;
310
323
  });
324
+ this.internalFunctions = internalFunctions;
325
+ this.userFunctions = userFunctions;
326
+ return { all: functions, new: newFunctions, deleted: deletedFunctions };
311
327
  }
312
- catch {
313
- // no-op
314
- }
315
- }, _EdgeFunctionsRegistry_getDeclarationsFromTOML = function _EdgeFunctionsRegistry_getDeclarationsFromTOML(config) {
316
- const { edge_functions: edgeFunctions = [] } = config;
317
- return edgeFunctions;
318
- }, _EdgeFunctionsRegistry_getEnvironmentVariables = function _EdgeFunctionsRegistry_getEnvironmentVariables(envConfig) {
319
- const env = Object.create(null);
320
- Object.entries(envConfig).forEach(([key, variable]) => {
321
- if (
322
- // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
323
- variable.sources.includes('ui') ||
324
- // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
325
- variable.sources.includes('account') ||
326
- // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
327
- variable.sources.includes('addons') ||
328
- // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
329
- variable.sources.includes('internal') ||
330
- // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
331
- variable.sources.some((source) => source.startsWith('.env'))) {
332
- // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'.
333
- env[key] = variable.value;
334
- }
335
- });
336
- env.DENO_REGION = 'local';
337
- return env;
338
- }, _EdgeFunctionsRegistry_handleFileChange =
339
- /**
340
- * @param {string[]} paths
341
- * @returns {Promise<void>}
342
- */
343
- // @ts-expect-error TS(7006) FIXME: Parameter 'paths' implicitly has an 'any' type.
344
- async function _EdgeFunctionsRegistry_handleFileChange(paths) {
345
- const matchingFunctions = new Set([
346
- // @ts-expect-error TS(7006) FIXME: Parameter 'path' implicitly has an 'any' type.
347
- ...paths.map((path) => __classPrivateFieldGet(this, _EdgeFunctionsRegistry_functionPaths, "f").get(path)),
348
- // @ts-expect-error TS(7006) FIXME: Parameter 'path' implicitly has an 'any' type.
349
- ...paths.flatMap((path) => __classPrivateFieldGet(this, _EdgeFunctionsRegistry_dependencyPaths, "f").get(path)),
350
- ].filter(Boolean));
351
- // If the file is not associated with any function, there's no point in
352
- // building. However, it might be that the path is in fact associated with
353
- // a function but we just haven't registered it due to a build error. So if
354
- // there was a build error, let's always build.
355
- if (matchingFunctions.size === 0 && __classPrivateFieldGet(this, _EdgeFunctionsRegistry_buildError, "f") === null) {
356
- return;
357
- }
358
- // @ts-expect-error TS(2345) FIXME: Argument of type '{}' is not assignable to paramet... Remove this comment to see the full error message
359
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_logEvent).call(this, 'reloading', {});
360
- try {
361
- const { warnings } = await __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_build).call(this);
362
- const functionNames = [...matchingFunctions];
363
- if (functionNames.length === 0) {
364
- // @ts-expect-error TS(2345) FIXME: Argument of type '{}' is not assignable to paramet... Remove this comment to see the full error message
365
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_logEvent).call(this, 'reloaded', {});
366
- }
367
- else {
368
- functionNames.forEach((functionName) => {
369
- // @ts-expect-error TS(2345) FIXME: Argument of type '{ functionName: any; warnings: a... Remove this comment to see the full error message
370
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_logEvent).call(this, 'reloaded', { functionName, warnings: warnings[functionName] });
371
- });
372
- }
373
- }
374
- catch (error) {
375
- // @ts-expect-error TS(2345) FIXME: Argument of type '{ buildError: any; }' is not ass... Remove this comment to see the full error message
376
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_logEvent).call(this, 'buildError', { buildError: error?.message });
377
- }
378
- }, _EdgeFunctionsRegistry_logEvent = function _EdgeFunctionsRegistry_logEvent(event, { buildError, functionName, warnings = [] }) {
379
- const subject = functionName
380
- ? `edge function ${chalk.yellow(__classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_getDisplayName).call(this, functionName))}`
381
- : 'edge functions';
382
- const warningsText = warnings.length === 0 ? '' : ` with warnings:\n${warnings.map((warning) => ` - ${warning}`).join('\n')}`;
383
- if (event === 'buildError') {
384
- log(`${NETLIFYDEVERR} ${chalk.red('Failed to load')} ${subject}: ${buildError}`);
385
- return;
386
- }
387
- if (event === 'loaded') {
388
- const icon = warningsText ? NETLIFYDEVWARN : NETLIFYDEVLOG;
389
- const color = warningsText ? chalk.yellow : chalk.green;
390
- log(`${icon} ${color('Loaded')} ${subject}${warningsText}`);
391
- return;
392
- }
393
- if (event === 'reloaded') {
394
- const icon = warningsText ? NETLIFYDEVWARN : NETLIFYDEVLOG;
395
- const color = warningsText ? chalk.yellow : chalk.green;
396
- log(`${icon} ${color('Reloaded')} ${subject}${warningsText}`);
397
- return;
398
- }
399
- if (event === 'reloading') {
400
- log(`${NETLIFYDEVLOG} ${chalk.magenta('Reloading')} ${subject}...`);
401
- return;
402
- }
403
- if (event === 'removed') {
404
- log(`${NETLIFYDEVLOG} ${chalk.magenta('Removed')} ${subject}`);
405
- }
406
- }, _EdgeFunctionsRegistry_processGraph = function _EdgeFunctionsRegistry_processGraph(graph) {
407
- if (!graph) {
408
- warn('Could not process edge functions dependency graph. Live reload will not be available.');
409
- return;
410
- }
411
- // Creating a Map from `this.#functions` that map function paths to function
412
- // names. This allows us to match modules against functions in O(1) time as
413
- // opposed to O(n).
414
- // @ts-expect-error TS(2339) FIXME: Property 'path' does not exist on type 'never'.
415
- // eslint-disable-next-line unicorn/prefer-spread
416
- const functionPaths = new Map(Array.from(__classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "a", _EdgeFunctionsRegistry_functions_get), (func) => [func.path, func.name]));
417
- // Mapping file URLs to names of functions that use them as dependencies.
418
- const dependencyPaths = new Map();
419
- // @ts-expect-error TS(7031) FIXME: Binding element 'specifier' implicitly has an 'any... Remove this comment to see the full error message
420
- graph.modules.forEach(({ dependencies = [], specifier }) => {
421
- if (!specifier.startsWith('file://')) {
328
+ async setupWatchers(projectDir) {
329
+ if (!this.configPath) {
422
330
  return;
423
331
  }
424
- const path = fileURLToPath(specifier);
425
- const functionMatch = functionPaths.get(path);
426
- if (!functionMatch) {
427
- return;
428
- }
429
- dependencies.forEach((dependency) => {
430
- // We're interested in tracking local dependencies, so we only look at
431
- // specifiers with the `file:` protocol.
432
- if (
433
- // @ts-expect-error TS(2339) FIXME: Property 'code' does not exist on type 'never'.
434
- dependency.code === undefined ||
435
- // @ts-expect-error TS(2339) FIXME: Property 'code' does not exist on type 'never'.
436
- typeof dependency.code.specifier !== 'string' ||
437
- // @ts-expect-error TS(2339) FIXME: Property 'code' does not exist on type 'never'.
438
- !dependency.code.specifier.startsWith('file://')) {
439
- return;
440
- }
441
- // @ts-expect-error TS(2339) FIXME: Property 'code' does not exist on type 'never'.
442
- const { specifier: dependencyURL } = dependency.code;
443
- const dependencyPath = fileURLToPath(dependencyURL);
444
- const functions = dependencyPaths.get(dependencyPath) || [];
445
- dependencyPaths.set(dependencyPath, [...functions, functionMatch]);
446
- });
447
- });
448
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_dependencyPaths, dependencyPaths, "f");
449
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_functionPaths, functionPaths, "f");
450
- }, _EdgeFunctionsRegistry_runBuild =
451
- /**
452
- * Thin wrapper for `#runIsolate` that skips running a build and returns an
453
- * empty response if there are no functions in the registry.
454
- */
455
- async function _EdgeFunctionsRegistry_runBuild() {
456
- if (__classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "a", _EdgeFunctionsRegistry_functions_get).length === 0) {
457
- return {
458
- functionsConfig: [],
459
- graph: {
460
- modules: [],
461
- },
462
- npmSpecifiersWithExtraneousFiles: [],
463
- success: true,
464
- };
465
- }
466
- const { functionsConfig, graph, npmSpecifiersWithExtraneousFiles, success } = await __classPrivateFieldGet(this, _EdgeFunctionsRegistry_runIsolate, "f").call(this, __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "a", _EdgeFunctionsRegistry_functions_get), __classPrivateFieldGet(this, _EdgeFunctionsRegistry_env, "f"), {
467
- getFunctionsConfig: true,
468
- });
469
- return { functionsConfig, graph, npmSpecifiersWithExtraneousFiles, success };
470
- }, _EdgeFunctionsRegistry_scanForFunctions =
471
- /**
472
- * @returns {Promise<{all: EdgeFunction[], new: EdgeFunction[], deleted: EdgeFunction[]}>}
473
- */
474
- async function _EdgeFunctionsRegistry_scanForFunctions() {
475
- const [internalFunctions, userFunctions] = await Promise.all([
476
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_bundler, "f").find(__classPrivateFieldGet(this, _EdgeFunctionsRegistry_internalDirectories, "f")),
477
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_bundler, "f").find(__classPrivateFieldGet(this, _EdgeFunctionsRegistry_directories, "f")),
478
- ]);
479
- const functions = [...internalFunctions, ...userFunctions];
480
- const newFunctions = functions.filter((func) => {
481
- const functionExists = __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "a", _EdgeFunctionsRegistry_functions_get).some(
482
- // @ts-expect-error TS(2339) FIXME: Property 'name' does not exist on type 'never'.
483
- (existingFunc) => func.name === existingFunc.name && func.path === existingFunc.path);
484
- return !functionExists;
485
- });
486
- const deletedFunctions = __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "a", _EdgeFunctionsRegistry_functions_get).filter((existingFunc) => {
487
- const functionExists = functions.some(
488
- // @ts-expect-error TS(2339) FIXME: Property 'name' does not exist on type 'never'.
489
- (func) => func.name === existingFunc.name && func.path === existingFunc.path);
490
- return !functionExists;
491
- });
492
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_internalFunctions, internalFunctions, "f");
493
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_userFunctions, userFunctions, "f");
494
- return { all: functions, new: newFunctions, deleted: deletedFunctions };
495
- }, _EdgeFunctionsRegistry_setupWatchers =
496
- /**
497
- * @param {string} projectDir
498
- */
499
- // @ts-expect-error TS(7006) FIXME: Parameter 'projectDir' implicitly has an 'any' typ... Remove this comment to see the full error message
500
- async function _EdgeFunctionsRegistry_setupWatchers(projectDir) {
501
- if (__classPrivateFieldGet(this, _EdgeFunctionsRegistry_configPath, "f")) {
502
332
  // Creating a watcher for the config file. When it changes, we update the
503
333
  // declarations and see if we need to register or unregister any functions.
504
- // @ts-expect-error TS(2345) FIXME: Argument of type '{ onChange: () => Promise<void>;... Remove this comment to see the full error message
505
- await watchDebounced(__classPrivateFieldGet(this, _EdgeFunctionsRegistry_configPath, "f"), {
334
+ await watchDebounced(this.configPath, {
506
335
  onChange: async () => {
507
- const newConfig = await __classPrivateFieldGet(this, _EdgeFunctionsRegistry_getUpdatedConfig, "f").call(this);
508
- __classPrivateFieldSet(this, _EdgeFunctionsRegistry_declarationsFromTOML, __classPrivateFieldGet(EdgeFunctionsRegistry, _a, "m", _EdgeFunctionsRegistry_getDeclarationsFromTOML).call(EdgeFunctionsRegistry, newConfig), "f");
509
- await __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_checkForAddedOrDeletedFunctions).call(this);
336
+ const newConfig = await this.getUpdatedConfig();
337
+ this.declarationsFromTOML = EdgeFunctionsRegistry.getDeclarationsFromTOML(newConfig);
338
+ await this.checkForAddedOrDeletedFunctions();
510
339
  },
511
340
  });
341
+ // While functions are guaranteed to be inside one of the configured
342
+ // directories, they might be importing files that are located in
343
+ // parent directories. So we watch the entire project directory for
344
+ // changes.
345
+ await this.setupWatcherForDirectory(projectDir);
512
346
  }
513
- // While functions are guaranteed to be inside one of the configured
514
- // directories, they might be importing files that are located in
515
- // parent directories. So we watch the entire project directory for
516
- // changes.
517
- await __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_setupWatcherForDirectory).call(this, projectDir);
518
- }, _EdgeFunctionsRegistry_setupWatcherForDirectory =
519
- /**
520
- * @param {string} directory
521
- * @returns {Promise<void>}
522
- */
523
- // @ts-expect-error TS(7006) FIXME: Parameter 'directory' implicitly has an 'any' type... Remove this comment to see the full error message
524
- async function _EdgeFunctionsRegistry_setupWatcherForDirectory(directory) {
525
- const ignored = [`${__classPrivateFieldGet(this, _EdgeFunctionsRegistry_servePath, "f")}/**`];
526
- const watcher = await watchDebounced(directory, {
527
- // @ts-expect-error TS(2322) FIXME: Type 'string[]' is not assignable to type 'never[]... Remove this comment to see the full error message
528
- ignored,
529
- onAdd: () => __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_checkForAddedOrDeletedFunctions).call(this),
530
- // @ts-expect-error TS(2322) FIXME: Type '(paths: any) => Promise<void>' is not assign... Remove this comment to see the full error message
531
- onChange: (paths) => __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_handleFileChange).call(this, paths),
532
- onUnlink: () => __classPrivateFieldGet(this, _EdgeFunctionsRegistry_instances, "m", _EdgeFunctionsRegistry_checkForAddedOrDeletedFunctions).call(this),
533
- });
534
- __classPrivateFieldGet(this, _EdgeFunctionsRegistry_directoryWatchers, "f").set(directory, watcher);
535
- }, _EdgeFunctionsRegistry_getDisplayName = function _EdgeFunctionsRegistry_getDisplayName(func) {
536
- const declarations = [...__classPrivateFieldGet(this, _EdgeFunctionsRegistry_declarationsFromTOML, "f"), ...__classPrivateFieldGet(this, _EdgeFunctionsRegistry_declarationsFromDeployConfig, "f")];
537
- return declarations.find((declaration) => declaration.function === func)?.name ?? func;
538
- };
347
+ async setupWatcherForDirectory(directory) {
348
+ const ignored = [`${this.servePath}/**`];
349
+ const watcher = await watchDebounced(directory, {
350
+ ignored,
351
+ onAdd: () => this.checkForAddedOrDeletedFunctions(),
352
+ onChange: (paths) => this.handleFileChange(paths),
353
+ onUnlink: () => this.checkForAddedOrDeletedFunctions(),
354
+ });
355
+ this.directoryWatchers.set(directory, watcher);
356
+ }
357
+ }