Skip to content

feat: add functions.generate util #6487

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 27, 2025
Merged

feat: add functions.generate util #6487

merged 10 commits into from
Jun 27, 2025

Conversation

eduardoboucas
Copy link
Member

@eduardoboucas eduardoboucas commented Jun 24, 2025

Summary

This PR implements support for build plugins to generate Netlify Functions that are automatically included in the build process without
requiring file copying. This introduces a new utils.functions.generate() method that allows plugins to register function files that they
manage directly.

Technical Implementation

  1. Plugin-side changes:

    • Added functions.generate(mainFile) method to the utils object available to plugins
    • The method accepts an absolute path to the function's main file
    • Generated functions are tracked in an array within the plugin execution context
  2. Build system changes:

    • Modified plugin step execution to capture return values containing generated functions
    • Updated the functions core plugin to include generated functions in the bundling process
    • Enhanced logging to report generated functions alongside user and internal functions
  3. Type safety:

    • Added comprehensive TypeScript definitions for the new generate method
    • Updated existing function utility types to include the new functionality

Copy link
Contributor

This pull request adds or modifies JavaScript (.js, .cjs, .mjs) files.
Consider converting them to TypeScript.

ndhoule
ndhoule previously approved these changes Jun 25, 2025
Copy link
Contributor

@ndhoule ndhoule left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes look good as they are, less missing tests. Let me know if you'd like a re-review once you add those.

I do wonder if exposing a method(s) for registering generated functions on the context (e.g. addGeneratedFunction and/or addGeneratedFunctions) might be a better API?

A method feels more consistent with the rest of the build hooks API, feels a little more intentional/easier to document, and is a more backward-compatible change. (Specifically, I'm wondering how many consumers are e.g. returning a promise from a build hook and counting on the current behavior of build resolving the promise but completely ignoring the return value.)

That said: I don't feel strongly about this, I don't understand if you have a particular reason for preferring a return value, and this is admittedly pretty edge casey. The likelihood that someone is returning a value with this property on it is low, but this would have higher potential for trouble as we expand the return-value API.

@@ -221,6 +235,10 @@ const hasFunctionsDirectories = async function ({
return await pathExists(frameworkFunctionsSrc)
}

const getGeneratedFunctions = (returnValues: Record<string, ReturnValue>) => {
return Object.values(returnValues).flatMap((returnValue) => returnValue.generatedFunctions || [])
Copy link
Contributor

@ndhoule ndhoule Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we defaulting returnValues to a non-nil value somewhere? I see on the type that we define this property as optional, but I don't see the code path where we're handling void returns from the build hook.

I'm probably just missing this somewhere in the prop drilling, but thought I'd point it out.

Copy link
Contributor

This pull request adds or modifies JavaScript (.js, .cjs, .mjs) files.
Consider converting them to TypeScript.

Copy link
Contributor

This pull request adds or modifies JavaScript (.js, .cjs, .mjs) files.
Consider converting them to TypeScript.

Copy link
Contributor

This pull request adds or modifies JavaScript (.js, .cjs, .mjs) files.
Consider converting them to TypeScript.

Copy link
Contributor

This pull request adds or modifies JavaScript (.js, .cjs, .mjs) files.
Consider converting them to TypeScript.

@eduardoboucas
Copy link
Member Author

I do wonder if exposing a method(s) for registering generated functions on the context (e.g. addGeneratedFunction and/or addGeneratedFunctions) might be a better API?

A method feels more consistent with the rest of the build hooks API, feels a little more intentional/easier to document, and is a more backward-compatible change. (Specifically, I'm wondering how many consumers are e.g. returning a promise from a build hook and counting on the current behavior of build resolving the promise but completely ignoring the return value.)

Yeah, I agree a method would be nicer, and this was my first choice. I ended up going for a return value because that felt simpler, as the communication mechanism between Netlify Build and the plugins is far from trivial, with parent/child process communicating over IPC messages.

At first I thought that a method call would need to be an out-of-band message as a separate event, but that's not really the case. In 480f66b I've added a new generate method to the existing functions utils, which simply pushes data to a generatedFunctions array that is then returned via the existing returnValue property.

Copy link
Contributor

This pull request adds or modifies JavaScript (.js, .cjs, .mjs) files.
Consider converting them to TypeScript.

Copy link
Contributor

This pull request adds or modifies JavaScript (.js, .cjs, .mjs) files.
Consider converting them to TypeScript.

Copy link
Contributor

This pull request adds or modifies JavaScript (.js, .cjs, .mjs) files.
Consider converting them to TypeScript.

@eduardoboucas eduardoboucas changed the title feat: support return values from plugin steps feat: add functions.generate util Jun 26, 2025
@eduardoboucas eduardoboucas marked this pull request as ready for review June 26, 2025 17:26
@eduardoboucas eduardoboucas requested a review from a team as a code owner June 26, 2025 17:26
@serhalp serhalp requested a review from ndhoule June 26, 2025 17:37
Copy link
Member

@serhalp serhalp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment on lines +242 to +243
for (const id in returnValues) {
if (returnValues[id].generatedFunctions && returnValues[id].generatedFunctions.length !== 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change
for (const id in returnValues) {
if (returnValues[id].generatedFunctions && returnValues[id].generatedFunctions.length !== 0) {
for (const {generatedFunctions} of Object.values(returnValues)) {
if (generatedFunctions?.length !== 0) {

Copy link
Contributor

This pull request adds or modifies JavaScript (.js, .cjs, .mjs) files.
Consider converting them to TypeScript.

@eduardoboucas eduardoboucas enabled auto-merge (squash) June 27, 2025 08:25
@eduardoboucas eduardoboucas merged commit dfb4a07 into main Jun 27, 2025
60 of 61 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants