From 0bf85b14d9ee9939f31833865e03f30ea7488aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Thu, 10 Jul 2025 16:04:39 +0100 Subject: [PATCH 1/5] feat: add `srcDir` to output of `listFunctions` --- packages/zip-it-and-ship-it/src/main.ts | 3 +++ .../__snapshots__/list_functions.test.ts.snap | 26 +++++++++++++++++++ .../zip-it-and-ship-it/tests/helpers/main.ts | 2 ++ 3 files changed, 31 insertions(+) diff --git a/packages/zip-it-and-ship-it/src/main.ts b/packages/zip-it-and-ship-it/src/main.ts index c3c12e75af..bb2fc03bc1 100644 --- a/packages/zip-it-and-ship-it/src/main.ts +++ b/packages/zip-it-and-ship-it/src/main.ts @@ -38,6 +38,7 @@ export interface ListedFunction { inputModuleFormat?: ModuleFormat excludedRoutes?: Route[] routes?: ExtendedRoute[] + srcDir?: string } type ListedFunctionFile = ListedFunction & { @@ -152,6 +153,7 @@ const getListedFunction = function ({ mainFile, name, runtime, + srcDir, }: AugmentedFunctionSource): ListedFunction { return { displayName: config.name, @@ -166,6 +168,7 @@ const getListedFunction = function ({ runtimeAPIVersion: staticAnalysisResult ? (staticAnalysisResult?.runtimeAPIVersion ?? 1) : undefined, schedule: staticAnalysisResult?.config?.schedule ?? config.schedule, inputModuleFormat: staticAnalysisResult?.inputModuleFormat, + srcDir, } } diff --git a/packages/zip-it-and-ship-it/tests/__snapshots__/list_functions.test.ts.snap b/packages/zip-it-and-ship-it/tests/__snapshots__/list_functions.test.ts.snap index bb5d774e64..6c414e1a6e 100644 --- a/packages/zip-it-and-ship-it/tests/__snapshots__/list_functions.test.ts.snap +++ b/packages/zip-it-and-ship-it/tests/__snapshots__/list_functions.test.ts.snap @@ -25,6 +25,7 @@ exports[`listFunctions > V2 API > listFunctions includes routes when parseISC is "runtime": "js", "runtimeAPIVersion": 2, "schedule": undefined, + "srcDir": "", "srcFile": undefined, "timeout": undefined, } @@ -43,6 +44,7 @@ exports[`listFunctions > V2 API > listFunctions includes runtimeAPIVersion when "runtime": "js", "runtimeAPIVersion": 2, "schedule": undefined, + "srcDir": "", "srcFile": undefined, "timeout": undefined, } @@ -62,6 +64,7 @@ exports[`listFunctions > v1 > Can list function main files from multiple source "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": undefined, "timeout": undefined, }, @@ -77,6 +80,7 @@ exports[`listFunctions > v1 > Can list function main files from multiple source "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": undefined, "timeout": undefined, }, @@ -92,6 +96,7 @@ exports[`listFunctions > v1 > Can list function main files from multiple source "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": undefined, "timeout": undefined, }, @@ -107,6 +112,7 @@ exports[`listFunctions > v1 > Can list function main files from multiple source "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": undefined, "timeout": undefined, }, @@ -127,6 +133,7 @@ exports[`listFunctions > v1 > Can list function main files with listFunctions() "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -142,6 +149,7 @@ exports[`listFunctions > v1 > Can list function main files with listFunctions() "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -157,6 +165,7 @@ exports[`listFunctions > v1 > Can list function main files with listFunctions() "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "five", "srcFile": undefined, "timeout": undefined, }, @@ -172,6 +181,7 @@ exports[`listFunctions > v1 > Can list function main files with listFunctions() "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "four.js", "srcFile": undefined, "timeout": undefined, }, @@ -187,6 +197,7 @@ exports[`listFunctions > v1 > Can list function main files with listFunctions() "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "one", "srcFile": undefined, "timeout": undefined, }, @@ -202,6 +213,7 @@ exports[`listFunctions > v1 > Can list function main files with listFunctions() "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "two", "srcFile": undefined, "timeout": undefined, }, @@ -217,6 +229,7 @@ exports[`listFunctions > v1 > Can list function main files with listFunctions() "runtime": "go", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -237,6 +250,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -252,6 +266,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -267,6 +282,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -282,6 +298,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -297,6 +314,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -312,6 +330,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -327,6 +346,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -342,6 +362,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -357,6 +378,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -372,6 +394,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -387,6 +410,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -402,6 +426,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, @@ -417,6 +442,7 @@ exports[`listFunctions > v1 > listFunctions includes in-source config declaratio "runtime": "js", "runtimeAPIVersion": 1, "schedule": "@daily", + "srcDir": "", "srcFile": undefined, "timeout": undefined, }, diff --git a/packages/zip-it-and-ship-it/tests/helpers/main.ts b/packages/zip-it-and-ship-it/tests/helpers/main.ts index 54618da238..f5c2a01c07 100644 --- a/packages/zip-it-and-ship-it/tests/helpers/main.ts +++ b/packages/zip-it-and-ship-it/tests/helpers/main.ts @@ -209,6 +209,7 @@ export const normalizeFiles = function ( fixtureDir: string, { mainFile, + srcDir, srcFile, ...rest }: ListedFunction & { @@ -218,6 +219,7 @@ export const normalizeFiles = function ( return { ...rest, mainFile: normalizedRelative(fixtureDir, mainFile), + srcDir: srcDir ? normalizedRelative(fixtureDir, srcDir) : undefined, srcFile: srcFile ? normalizedRelative(fixtureDir, srcFile) : undefined, } } From 0d62c1271fcb80ae384359e1484bc966d150449b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Thu, 10 Jul 2025 16:25:42 +0100 Subject: [PATCH 2/5] chore: update snapshot --- .../list_functions_files.test.ts.snap | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/packages/zip-it-and-ship-it/tests/__snapshots__/list_functions_files.test.ts.snap b/packages/zip-it-and-ship-it/tests/__snapshots__/list_functions_files.test.ts.snap index 255963e598..3b236863b8 100644 --- a/packages/zip-it-and-ship-it/tests/__snapshots__/list_functions_files.test.ts.snap +++ b/packages/zip-it-and-ship-it/tests/__snapshots__/list_functions_files.test.ts.snap @@ -14,6 +14,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function.js", "timeout": undefined, }, @@ -29,6 +30,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -44,6 +46,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -59,6 +62,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function_internal.js", "timeout": undefined, }, @@ -74,6 +78,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -89,6 +94,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -104,6 +110,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function.js", "timeout": undefined, }, @@ -119,6 +126,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -134,6 +142,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -149,6 +158,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function_user.js", "timeout": undefined, }, @@ -164,6 +174,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -179,6 +190,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -199,6 +211,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function.js", "timeout": undefined, }, @@ -214,6 +227,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -229,6 +243,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -244,6 +259,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function_internal.js", "timeout": undefined, }, @@ -259,6 +275,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -274,6 +291,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -289,6 +307,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function.js", "timeout": undefined, }, @@ -304,6 +323,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -319,6 +339,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -334,6 +355,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function_user.js", "timeout": undefined, }, @@ -349,6 +371,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -364,6 +387,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -384,6 +408,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function.js", "timeout": undefined, }, @@ -399,6 +424,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function_internal.js", "timeout": undefined, }, @@ -414,6 +440,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function.js", "timeout": undefined, }, @@ -429,6 +456,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function_user.js", "timeout": undefined, }, @@ -449,6 +477,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function.js", "timeout": undefined, }, @@ -464,6 +493,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function_internal.js", "timeout": undefined, }, @@ -479,6 +509,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function.js", "timeout": undefined, }, @@ -494,6 +525,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function_user.js", "timeout": undefined, }, @@ -514,6 +546,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function.js", "timeout": undefined, }, @@ -529,6 +562,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -544,6 +578,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -559,6 +594,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function_internal.js", "timeout": undefined, }, @@ -574,6 +610,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -589,6 +626,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -604,6 +642,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function.js", "timeout": undefined, }, @@ -619,6 +658,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -634,6 +674,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -649,6 +690,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function_user.js", "timeout": undefined, }, @@ -664,6 +706,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/index.js", "timeout": undefined, }, @@ -679,6 +722,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "node_modules/test/package.json", "timeout": undefined, }, @@ -699,6 +743,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function.js", "timeout": undefined, }, @@ -714,6 +759,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": ".netlify/internal-functions", "srcFile": ".netlify/internal-functions/function_internal.js", "timeout": undefined, }, @@ -729,6 +775,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function.js", "timeout": undefined, }, @@ -744,6 +791,7 @@ exports[`listFunctionsFiles > Can list all function files from multiple source d "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "netlify/functions", "srcFile": "netlify/functions/function_user.js", "timeout": undefined, }, @@ -764,6 +812,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.zip", "timeout": undefined, }, @@ -779,6 +828,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.js", "timeout": undefined, }, @@ -794,6 +844,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "five", "srcFile": "five/index.ts", "timeout": undefined, }, @@ -809,6 +860,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "four.js", "srcFile": "four.js/four.js.js", "timeout": undefined, }, @@ -824,6 +876,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "one", "srcFile": "one/index.js", "timeout": undefined, }, @@ -839,6 +892,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "two", "srcFile": "two/three.json", "timeout": undefined, }, @@ -854,6 +908,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "two", "srcFile": "two/two.js", "timeout": undefined, }, @@ -869,6 +924,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "go", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test", "timeout": undefined, }, @@ -889,6 +945,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.zip", "timeout": undefined, }, @@ -904,6 +961,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.js", "timeout": undefined, }, @@ -919,6 +977,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "five", "srcFile": "five/index.ts", "timeout": undefined, }, @@ -934,6 +993,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "four.js", "srcFile": "four.js/four.js.js", "timeout": undefined, }, @@ -949,6 +1009,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "one", "srcFile": "one/index.js", "timeout": undefined, }, @@ -964,6 +1025,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "two", "srcFile": "two/two.js", "timeout": undefined, }, @@ -979,6 +1041,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "two", "srcFile": "two/three.json", "timeout": undefined, }, @@ -994,6 +1057,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "go", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test", "timeout": undefined, }, @@ -1014,6 +1078,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.zip", "timeout": undefined, }, @@ -1029,6 +1094,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.js", "timeout": undefined, }, @@ -1044,6 +1110,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "five", "srcFile": "five/index.ts", "timeout": undefined, }, @@ -1059,6 +1126,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "four.js", "srcFile": "four.js/four.js.js", "timeout": undefined, }, @@ -1074,6 +1142,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "one", "srcFile": "one/index.js", "timeout": undefined, }, @@ -1089,6 +1158,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "two", "srcFile": "two/two.js", "timeout": undefined, }, @@ -1104,6 +1174,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "go", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test", "timeout": undefined, }, @@ -1124,6 +1195,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.zip", "timeout": undefined, }, @@ -1139,6 +1211,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.js", "timeout": undefined, }, @@ -1154,6 +1227,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "five", "srcFile": "five/index.ts", "timeout": undefined, }, @@ -1169,6 +1243,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "four.js", "srcFile": "four.js/four.js.js", "timeout": undefined, }, @@ -1184,6 +1259,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "one", "srcFile": "one/index.js", "timeout": undefined, }, @@ -1199,6 +1275,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "two", "srcFile": "two/two.js", "timeout": undefined, }, @@ -1214,6 +1291,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "go", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test", "timeout": undefined, }, @@ -1234,6 +1312,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.zip", "timeout": undefined, }, @@ -1249,6 +1328,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.js", "timeout": undefined, }, @@ -1264,6 +1344,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "five", "srcFile": "five/index.ts", "timeout": undefined, }, @@ -1279,6 +1360,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "five", "srcFile": "five/util.ts", "timeout": undefined, }, @@ -1294,6 +1376,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "four.js", "srcFile": "four.js/four.js.js", "timeout": undefined, }, @@ -1309,6 +1392,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "one", "srcFile": "one/index.js", "timeout": undefined, }, @@ -1324,6 +1408,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "two", "srcFile": "two/two.js", "timeout": undefined, }, @@ -1339,6 +1424,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "two", "srcFile": "two/three.json", "timeout": undefined, }, @@ -1354,6 +1440,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "go", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test", "timeout": undefined, }, @@ -1374,6 +1461,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.zip", "timeout": undefined, }, @@ -1389,6 +1477,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test.js", "timeout": undefined, }, @@ -1404,6 +1493,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "five", "srcFile": "five/index.ts", "timeout": undefined, }, @@ -1419,6 +1509,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "four.js", "srcFile": "four.js/four.js.js", "timeout": undefined, }, @@ -1434,6 +1525,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "one", "srcFile": "one/index.js", "timeout": undefined, }, @@ -1449,6 +1541,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "js", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "two", "srcFile": "two/two.js", "timeout": undefined, }, @@ -1464,6 +1557,7 @@ exports[`listFunctionsFiles > Can list all function files with listFunctionsFile "runtime": "go", "runtimeAPIVersion": undefined, "schedule": undefined, + "srcDir": "", "srcFile": "test", "timeout": undefined, }, From ebc0fdd8f686f988e9ea0984aaff5a174cd36aa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Thu, 10 Jul 2025 17:26:29 +0100 Subject: [PATCH 3/5] chore: fix tests --- .../__snapshots__/list_function.test.ts.snap | 1 + .../tests/list_function.test.ts | 41 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/zip-it-and-ship-it/tests/__snapshots__/list_function.test.ts.snap b/packages/zip-it-and-ship-it/tests/__snapshots__/list_function.test.ts.snap index fe0a4f65f3..1b53ea49f2 100644 --- a/packages/zip-it-and-ship-it/tests/__snapshots__/list_function.test.ts.snap +++ b/packages/zip-it-and-ship-it/tests/__snapshots__/list_function.test.ts.snap @@ -13,6 +13,7 @@ exports[`listFunction > V2 API > listFunction includes metadata properties when "runtime": "js", "runtimeAPIVersion": 2, "schedule": undefined, + "srcDir": "v2-api-esm-ts-aliases", "srcFile": undefined, "timeout": undefined, } diff --git a/packages/zip-it-and-ship-it/tests/list_function.test.ts b/packages/zip-it-and-ship-it/tests/list_function.test.ts index e7b1d21480..d4df1fc030 100644 --- a/packages/zip-it-and-ship-it/tests/list_function.test.ts +++ b/packages/zip-it-and-ship-it/tests/list_function.test.ts @@ -1,4 +1,4 @@ -import { join, resolve } from 'path' +import { join, normalize, resolve } from 'path' import { describe, expect, test } from 'vitest' @@ -27,38 +27,37 @@ describe('listFunction', () => { }) test('listFunction includes in-source config declarations', async () => { - const mainFile = join(FIXTURES_DIR, 'in-source-config/functions/cron_cjs.js') + const dir = join(FIXTURES_DIR, 'in-source-config/functions') + const mainFile = join(dir, 'cron_cjs.js') const func = await listFunction(mainFile, { parseISC: true, }) - expect(func).toEqual({ - extension: '.js', - inputModuleFormat: 'cjs', - mainFile, - name: 'cron_cjs', - runtime: 'js', - runtimeAPIVersion: 1, - schedule: '@daily', - }) + expect(func?.extension).toBe('.js') + expect(func?.inputModuleFormat).toBe('cjs') + expect(func?.mainFile).toBe(mainFile) + expect(func?.name).toBe('cron_cjs') + expect(func?.runtime).toBe('js') + expect(func?.runtimeAPIVersion).toBe(1) + expect(func?.schedule).toBe('@daily') + expect(normalize(func!.srcDir!)).toBe(normalize(dir)) }) test('listFunction includes json configured functions with configured properties', async () => { - const dir = join(FIXTURES_DIR, 'json-config/.netlify/functions-internal/') + const dir = join(FIXTURES_DIR, 'json-config/.netlify/functions-internal') const mainFile = join(dir, 'simple.js') const func = await listFunction(mainFile, { configFileDirectories: [dir], }) - expect(func).toEqual({ - displayName: 'A Display Name', - extension: '.js', - generator: '@netlify/mock-plugin@1.0.0', - mainFile, - name: 'simple', - runtime: 'js', - runtimeAPIVersion: undefined, - }) + expect(func?.displayName).toBe('A Display Name') + expect(func?.extension).toBe('.js') + expect(func?.generator).toBe('@netlify/mock-plugin@1.0.0') + expect(func?.mainFile).toBe(mainFile) + expect(func?.name).toBe('simple') + expect(func?.runtime).toBe('js') + expect(func?.runtimeAPIVersion).toBeUndefined() + expect(normalize(func!.srcDir!)).toBe(normalize(dir)) }) }) describe('V2 API', () => { From f22c280051942c4d61bf1a10a876f44b84539351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Thu, 10 Jul 2025 18:24:12 +0100 Subject: [PATCH 4/5] chore: fix test --- packages/functions-utils/tests/main.test.ts | 70 ++++++++++++++++----- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/packages/functions-utils/tests/main.test.ts b/packages/functions-utils/tests/main.test.ts index 4ad80e2396..692b0b0ae9 100644 --- a/packages/functions-utils/tests/main.test.ts +++ b/packages/functions-utils/tests/main.test.ts @@ -1,5 +1,5 @@ import { readFile, rm } from 'fs/promises' -import { normalize } from 'path' +import { normalize, resolve } from 'path' import { fileURLToPath } from 'url' import cpy from 'cpy' @@ -107,10 +107,11 @@ test('Should allow "fail" option to customize failures', async () => { expect(fail).toHaveBeenCalledWith('No function source directory was specified') }) -const normalizeFiles = function (fixtureDir, { name, mainFile, runtime, extension, srcFile, schedule }) { +const normalizeFiles = function (fixtureDir, { name, mainFile, runtime, extension, srcDir, srcFile, schedule }) { const mainFileA = normalize(`${fixtureDir}/${mainFile}`) const srcFileA = srcFile === undefined ? {} : { srcFile: normalize(`${fixtureDir}/${srcFile}`) } - return { name, mainFile: mainFileA, runtime, extension, schedule, ...srcFileA } + const srcDirA = srcDir ? { srcDir: resolve(fixtureDir, srcDir) } : {} + return { name, mainFile: mainFileA, runtime, extension, schedule, ...srcFileA, ...srcDirA } } test('Can list function main files with list()', async () => { @@ -118,12 +119,18 @@ test('Can list function main files with list()', async () => { const functions = await list(fixtureDir) expect(sortOn(functions, ['mainFile', 'extension'])).toEqual( [ - { name: 'four', mainFile: 'four.js/four.js.js', runtime: 'js', extension: '.js' }, - { name: 'one', mainFile: 'one/index.js', runtime: 'js', extension: '.js' }, - { name: 'test', mainFile: 'test', runtime: 'go', extension: '' }, - { name: 'test', mainFile: 'test.js', runtime: 'js', extension: '.js' }, - { name: 'test', mainFile: 'test.zip', runtime: 'js', extension: '.zip' }, - { name: 'two', mainFile: 'two/two.js', runtime: 'js', extension: '.js' }, + { name: 'four', mainFile: 'four.js/four.js.js', runtime: 'js', extension: '.js', srcDir: 'four.js' }, + { + name: 'one', + mainFile: 'one/index.js', + runtime: 'js', + extension: '.js', + srcDir: 'one', + }, + { name: 'test', mainFile: 'test', runtime: 'go', extension: '', srcDir: '.' }, + { name: 'test', mainFile: 'test.js', runtime: 'js', extension: '.js', srcDir: '.' }, + { name: 'test', mainFile: 'test.zip', runtime: 'js', extension: '.zip', srcDir: '.' }, + { name: 'two', mainFile: 'two/two.js', runtime: 'js', extension: '.js', srcDir: 'two' }, ].map(normalizeFiles.bind(null, fixtureDir)), ) }) @@ -139,6 +146,7 @@ test('Can list all function files with listAll()', async () => { runtime: 'js', extension: '.js', srcFile: 'four.js/four.js.js', + srcDir: 'four.js', }, { name: 'four', @@ -146,33 +154,65 @@ test('Can list all function files with listAll()', async () => { runtime: 'js', extension: '.json', srcFile: '../../../package.json', + srcDir: 'four.js', + }, + { + name: 'one', + mainFile: 'one/index.js', + runtime: 'js', + extension: '.js', + srcFile: 'one/index.js', + srcDir: 'one', }, - { name: 'one', mainFile: 'one/index.js', runtime: 'js', extension: '.js', srcFile: 'one/index.js' }, { name: 'one', mainFile: 'one/index.js', runtime: 'js', extension: '.json', srcFile: '../../../package.json', + srcDir: 'one', + }, + { + name: 'test', + mainFile: 'test', + runtime: 'go', + extension: '', + srcFile: 'test', + srcDir: '.', + }, + { + name: 'test', + mainFile: 'test.js', + runtime: 'js', + extension: '.js', + srcFile: 'test.js', + srcDir: '.', }, - { name: 'test', mainFile: 'test', runtime: 'go', extension: '', srcFile: 'test' }, - { name: 'test', mainFile: 'test.js', runtime: 'js', extension: '.js', srcFile: 'test.js' }, { name: 'test', mainFile: 'test.js', runtime: 'js', extension: '.json', srcFile: '../../../package.json', + srcDir: '.', + }, + { + name: 'test', + mainFile: 'test.zip', + runtime: 'js', + extension: '.zip', + srcFile: 'test.zip', + srcDir: '.', }, - { name: 'test', mainFile: 'test.zip', runtime: 'js', extension: '.zip', srcFile: 'test.zip' }, - { name: 'two', mainFile: 'two/two.js', runtime: 'js', extension: '.js', srcFile: 'two/two.js' }, - { name: 'two', mainFile: 'two/two.js', runtime: 'js', extension: '.js', srcFile: 'two/three.js' }, + { name: 'two', mainFile: 'two/two.js', runtime: 'js', extension: '.js', srcFile: 'two/two.js', srcDir: 'two' }, + { name: 'two', mainFile: 'two/two.js', runtime: 'js', extension: '.js', srcFile: 'two/three.js', srcDir: 'two' }, { name: 'two', mainFile: 'two/two.js', runtime: 'js', extension: '.json', srcFile: '../../../package.json', + srcDir: 'two', }, ].map(normalizeFiles.bind(null, fixtureDir)), ) From 56608c930c2457d25af50d8dd565f27e8f97eab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Thu, 10 Jul 2025 18:53:02 +0100 Subject: [PATCH 5/5] chore: update snapshot --- .../build/tests/plugins/snapshots/tests.js.md | 6 ++++-- .../tests/plugins/snapshots/tests.js.snap | Bin 5836 -> 5849 bytes 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/build/tests/plugins/snapshots/tests.js.md b/packages/build/tests/plugins/snapshots/tests.js.md index 1e7a15a797..3f379e986b 100644 --- a/packages/build/tests/plugins/snapshots/tests.js.md +++ b/packages/build/tests/plugins/snapshots/tests.js.md @@ -1928,13 +1928,15 @@ Generated by [AVA](https://avajs.dev). "extension": ".js",␊ "mainFile": "packages/build/tests/plugins/fixtures/functions_list/.netlify/functions-internal/internal_1.js",␊ "name": "internal_1",␊ - "runtime": "js"␊ + "runtime": "js",␊ + "srcDir": "packages/build/tests/plugins/fixtures/functions_list/.netlify/functions-internal"␊ },␊ {␊ "extension": ".js",␊ "mainFile": "packages/build/tests/plugins/fixtures/functions_list/netlify/functions/user_1.js",␊ "name": "user_1",␊ - "runtime": "js"␊ + "runtime": "js",␊ + "srcDir": "packages/build/tests/plugins/fixtures/functions_list/netlify/functions"␊ }␊ ]␊ ␊ diff --git a/packages/build/tests/plugins/snapshots/tests.js.snap b/packages/build/tests/plugins/snapshots/tests.js.snap index 2aa6b351551a2d02ecb51d99bf5ef16aab89e596..9421635161b1a516791f6ecf6f0e6dc9270978b1 100644 GIT binary patch delta 5267 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