@@ -3,6 +3,7 @@ import { createRequire } from 'module'
3
3
import { basename , extname , isAbsolute , join , resolve } from 'path'
4
4
import { env } from 'process'
5
5
6
+ import type { GeneratedFunction } from '@netlify/build'
6
7
import { type ListedFunction , listFunctions , type Manifest } from '@netlify/zip-it-and-ship-it'
7
8
import { type MemoizeCache , watchDebounced } from '@netlify/dev-utils'
8
9
import extractZip from 'extract-zip'
@@ -73,6 +74,7 @@ export class FunctionsRegistry {
73
74
private config : NormalizedCachedConfigConfig
74
75
private debug : boolean
75
76
private frameworksAPIPaths : ReturnType < typeof getFrameworksAPIPaths >
77
+ private generatedFunctions : GeneratedFunction [ ]
76
78
private isConnected : boolean
77
79
private logLambdaCompat : boolean
78
80
private manifest ?: Manifest
@@ -87,6 +89,7 @@ export class FunctionsRegistry {
87
89
config,
88
90
debug = false ,
89
91
frameworksAPIPaths,
92
+ generatedFunctions,
90
93
isConnected = false ,
91
94
logLambdaCompat,
92
95
manifest,
@@ -102,6 +105,7 @@ export class FunctionsRegistry {
102
105
config : NormalizedCachedConfigConfig
103
106
debug ?: boolean
104
107
frameworksAPIPaths : ReturnType < typeof getFrameworksAPIPaths >
108
+ generatedFunctions : GeneratedFunction [ ]
105
109
isConnected ?: boolean
106
110
logLambdaCompat : boolean
107
111
manifest ?: Manifest
@@ -114,6 +118,7 @@ export class FunctionsRegistry {
114
118
this . config = config
115
119
this . debug = debug
116
120
this . frameworksAPIPaths = frameworksAPIPaths
121
+ this . generatedFunctions = generatedFunctions ?? [ ]
117
122
this . isConnected = isConnected
118
123
this . projectRoot = projectRoot
119
124
this . timeouts = timeouts
@@ -464,14 +469,32 @@ export class FunctionsRegistry {
464
469
465
470
await Promise . all ( directories . map ( ( path ) => FunctionsRegistry . prepareDirectory ( path ) ) )
466
471
467
- const functions = await this . listFunctions ( directories , {
468
- featureFlags : {
469
- buildRustSource : env . NETLIFY_EXPERIMENTAL_BUILD_RUST_SOURCE === 'true' ,
472
+ const functions = await this . listFunctions (
473
+ {
474
+ generated : {
475
+ functions : this . generatedFunctions . map ( ( func ) => func . path ) ,
476
+ } ,
477
+ user : {
478
+ // In reality, `directories` contains both directories with user and
479
+ // generated functions. The registry currently lacks knowledge about
480
+ // the contents of each directory, so we put them in the same bag and
481
+ // rely on the order of the directories to get the priority right.
482
+ // But now that zip-it-and-ship-it accepts an object with mixed paths
483
+ // that lets us specify exactly which paths contain user functions or
484
+ // generated functions, we should refactor this call so it encodes
485
+ // that distinction.
486
+ directories,
487
+ } ,
470
488
} ,
471
- configFileDirectories : [ getPathInProject ( [ INTERNAL_FUNCTIONS_FOLDER ] ) ] ,
472
- // @ts -expect-error -- TODO(serhalp): Function config types do not match. Investigate and fix.
473
- config : this . config . functions ,
474
- } )
489
+ {
490
+ featureFlags : {
491
+ buildRustSource : env . NETLIFY_EXPERIMENTAL_BUILD_RUST_SOURCE === 'true' ,
492
+ } ,
493
+ configFileDirectories : [ getPathInProject ( [ INTERNAL_FUNCTIONS_FOLDER ] ) ] ,
494
+ // @ts -expect-error -- TODO(serhalp): Function config types do not match. Investigate and fix.
495
+ config : this . config . functions ,
496
+ } ,
497
+ )
475
498
476
499
// user-defined functions take precedence over internal functions,
477
500
// so we want to ignore any internal functions where there's a user-defined one with the same name
@@ -505,7 +528,7 @@ export class FunctionsRegistry {
505
528
// zip-it-and-ship-it returns an array sorted based on which extension should have precedence,
506
529
// where the last ones precede the previous ones. This is why
507
530
// we reverse the array so we get the right functions precedence in the CLI.
508
- functions . reverse ( ) . map ( async ( { displayName, mainFile, name, runtime : runtimeName } ) => {
531
+ functions . reverse ( ) . map ( async ( { displayName, mainFile, name, runtime : runtimeName , srcPath } ) => {
509
532
if ( ignoredFunctions . has ( name ) ) {
510
533
return
511
534
}
@@ -526,7 +549,6 @@ export class FunctionsRegistry {
526
549
const func = new NetlifyFunction ( {
527
550
blobsContext : this . blobsContext ,
528
551
config : this . config ,
529
- directory : directories . find ( ( directory ) => mainFile . startsWith ( directory ) ) ,
530
552
mainFile,
531
553
name,
532
554
displayName,
@@ -538,6 +560,7 @@ export class FunctionsRegistry {
538
560
timeoutBackground : this . timeouts . backgroundFunctions ,
539
561
timeoutSynchronous : this . timeouts . syncFunctions ,
540
562
settings : this . settings ,
563
+ srcPath,
541
564
} )
542
565
543
566
// If a function we're registering was also unregistered in this run,
0 commit comments