Skip to content

Commit 536630e

Browse files
feat: expose generatedFunctions to consumers (#6525)
* feat: expose `generatedFunctions` to consumers * fix: add guard --------- Co-authored-by: Philippe Serhal <[email protected]>
1 parent 9d10c78 commit 536630e

File tree

10 files changed

+107
-52
lines changed

10 files changed

+107
-52
lines changed

packages/build/src/core/build.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ const tExecBuild = async function ({
166166
timers: timersB,
167167
configMutations,
168168
metrics,
169+
returnValues,
169170
} = await runAndReportBuild({
170171
pluginsOptions,
171172
netlifyConfig,
@@ -222,6 +223,7 @@ const tExecBuild = async function ({
222223
timers: timersB,
223224
configMutations,
224225
metrics,
226+
returnValues,
225227
}
226228
}
227229

@@ -285,6 +287,7 @@ export const runAndReportBuild = async function ({
285287
timers: timersA,
286288
configMutations,
287289
metrics,
290+
returnValues,
288291
} = await initAndRunBuild({
289292
pluginsOptions,
290293
netlifyConfig,
@@ -370,6 +373,7 @@ export const runAndReportBuild = async function ({
370373
timers: timersA,
371374
configMutations,
372375
metrics,
376+
returnValues,
373377
}
374378
} catch (error) {
375379
const [{ statuses }] = getErrorInfo(error)
@@ -502,6 +506,7 @@ const initAndRunBuild = async function ({
502506
timers: timersC,
503507
configMutations,
504508
metrics,
509+
returnValues,
505510
} = await runBuild({
506511
childProcesses,
507512
pluginsOptions: pluginsOptionsA,
@@ -560,6 +565,7 @@ const initAndRunBuild = async function ({
560565
timers: timersC,
561566
configMutations,
562567
metrics,
568+
returnValues,
563569
}
564570
} finally {
565571
// Terminate the child processes of plugins so that they don't linger after
@@ -651,6 +657,7 @@ const runBuild = async function ({
651657
timers: timersB,
652658
configMutations,
653659
metrics,
660+
returnValues,
654661
} = await runSteps({
655662
steps,
656663
buildbotServerSocket,
@@ -698,5 +705,6 @@ const runBuild = async function ({
698705
timers: timersB,
699706
configMutations,
700707
metrics,
708+
returnValues,
701709
}
702710
}

packages/build/src/core/dev.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { handleBuildError } from '../error/handle.js'
2+
import { getGeneratedFunctions } from '../steps/return_values.js'
23

34
import { execBuild, startBuild } from './build.js'
45
import { getSeverity } from './severity.js'
@@ -8,7 +9,11 @@ export const startDev = async (devCommand, flags = {}) => {
89
const errorParams = { errorMonitor, mode, logs, debug, testOpts }
910

1011
try {
11-
const { netlifyConfig: netlifyConfigA, configMutations } = await execBuild({
12+
const {
13+
netlifyConfig: netlifyConfigA,
14+
configMutations,
15+
returnValues,
16+
} = await execBuild({
1217
...normalizedFlags,
1318
errorMonitor,
1419
errorParams,
@@ -21,7 +26,14 @@ export const startDev = async (devCommand, flags = {}) => {
2126
})
2227
const { success, severityCode } = getSeverity('success')
2328

24-
return { success, severityCode, netlifyConfig: netlifyConfigA, logs, configMutations }
29+
return {
30+
success,
31+
severityCode,
32+
netlifyConfig: netlifyConfigA,
33+
logs,
34+
configMutations,
35+
generatedFunctions: getGeneratedFunctions(returnValues),
36+
}
2537
} catch (error) {
2638
const { severity, message, stack } = await handleBuildError(error, errorParams)
2739
const { success, severityCode } = getSeverity(severity)

packages/build/src/core/main.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { reportError } from '../error/report.js'
66
import { getSystemLogger } from '../log/logger.js'
77
import type { BufferedLogs } from '../log/logger.js'
88
import { logTimer, logBuildSuccess } from '../log/messages/core.js'
9+
import { getGeneratedFunctions } from '../steps/return_values.js'
910
import { trackBuildComplete } from '../telemetry/main.js'
1011
import { reportTimers } from '../time/report.js'
1112
import { RootExecutionAttributes } from '../tracing/main.js'
@@ -72,6 +73,7 @@ export async function buildSite(flags: Partial<BuildFlags> = {}): Promise<{
7273
durationNs,
7374
configMutations,
7475
metrics,
76+
returnValues,
7577
} = await execBuild({
7678
...flagsA,
7779
buildId,
@@ -117,7 +119,14 @@ export async function buildSite(flags: Partial<BuildFlags> = {}): Promise<{
117119
testOpts,
118120
errorParams,
119121
})
120-
return { success, severityCode, netlifyConfig: netlifyConfigA, logs, configMutations }
122+
return {
123+
success,
124+
severityCode,
125+
netlifyConfig: netlifyConfigA,
126+
logs,
127+
configMutations,
128+
generatedFunctions: getGeneratedFunctions(returnValues),
129+
}
121130
} catch (error) {
122131
const { severity } = await handleBuildError(error, errorParams as any)
123132
const { pluginsOptions, siteInfo, userNodeVersion }: any = errorParams

packages/build/src/log/messages/core_steps.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,22 @@ export const logFunctionsToBundle = function ({
7272
}) {
7373
let needsSpace = false
7474

75-
if (generatedFunctions.length !== 0) {
76-
for (const id in generatedFunctions) {
77-
const { displayName, generatorType, functionNames } = generatedFunctions[id]
75+
for (const id in generatedFunctions) {
76+
if (generatedFunctions[id].length === 0) {
77+
continue
78+
}
7879

79-
if (needsSpace) log(logs, '')
80+
// Getting the generator block from the first function, since it will be
81+
// the same for all of them.
82+
const { generator } = generatedFunctions[id][0]
83+
const functionNames = generatedFunctions[id].map((func) => path.basename(func.path))
8084

81-
log(logs, `Packaging ${type} generated by ${THEME.highlightWords(displayName)} ${generatorType}:`)
82-
logArray(logs, functionNames, { indent: false })
85+
if (needsSpace) log(logs, '')
8386

84-
needsSpace = true
85-
}
87+
log(logs, `Packaging ${type} generated by ${THEME.highlightWords(generator.displayName)} ${generator.type}:`)
88+
logArray(logs, functionNames, { indent: false })
89+
90+
needsSpace = true
8691
}
8792

8893
if (internalFunctions.length !== 0) {

packages/build/src/plugins_core/edge_functions/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ const logFunctions = async ({
206206
internalFunctionsSrc: internalSrcDirectory,
207207
frameworkFunctions: frameworkFunctions.map(({ name }) => name),
208208
type: 'Edge Functions',
209-
generatedFunctions: [],
209+
generatedFunctions: {},
210210
})
211211
}
212212

packages/build/src/plugins_core/functions/index.ts

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { basename, resolve } from 'path'
1+
import { resolve } from 'path'
22

33
import { type NodeBundlerName, RUNTIME, zipFunctions, type FunctionResult } from '@netlify/zip-it-and-ship-it'
44
import { pathExists } from 'path-exists'
55

66
import { addErrorInfo } from '../../error/info.js'
77
import { log } from '../../log/logger.js'
8-
import type { ReturnValue } from '../../types/step.js'
8+
import { type GeneratedFunction, getGeneratedFunctions } from '../../steps/return_values.js'
99
import { logBundleResults, logFunctionsNonExistingDir, logFunctionsToBundle } from '../../log/messages/core_steps.js'
1010
import { FRAMEWORKS_API_FUNCTIONS_ENDPOINT } from '../../utils/frameworks_api.js'
1111

@@ -168,7 +168,7 @@ const coreStep = async function ({
168168
}
169169
}
170170

171-
const generatedFunctions = getGeneratedFunctionPaths(returnValues)
171+
const generatedFunctions = getGeneratedFunctions(returnValues)
172172

173173
logFunctionsToBundle({
174174
logs,
@@ -178,7 +178,7 @@ const coreStep = async function ({
178178
internalFunctions,
179179
internalFunctionsSrc: relativeInternalFunctionsSrc,
180180
frameworkFunctions,
181-
generatedFunctions: getGeneratedFunctionsByGenerator(returnValues),
181+
generatedFunctions: getGeneratedFunctionsByGenerator(generatedFunctions),
182182
})
183183

184184
if (
@@ -205,7 +205,7 @@ const coreStep = async function ({
205205
repositoryRoot,
206206
userNodeVersion,
207207
systemLog,
208-
generatedFunctions,
208+
generatedFunctions: generatedFunctions.map((func) => func.path),
209209
})
210210

211211
const metrics = getMetrics(internalFunctions, userFunctions)
@@ -257,31 +257,17 @@ const hasFunctionsDirectories = async function ({
257257
return false
258258
}
259259

260-
// Takes a list of return values and produces an array with the paths of all
261-
// generated functions.
262-
const getGeneratedFunctionPaths = (returnValues: Record<string, ReturnValue>) => {
263-
return Object.values(returnValues).flatMap(
264-
(returnValue) => returnValue.generatedFunctions?.map((func) => func.path) || [],
265-
)
266-
}
267-
268260
// Takes a list of return values and produces an object with the names of the
269261
// generated functions for each generator. This is used for printing logs only.
270-
const getGeneratedFunctionsByGenerator = (returnValues: Record<string, ReturnValue>) => {
271-
const result: Record<string, { displayName: string; generatorType: string; functionNames: string[] }> = {}
272-
273-
for (const id in returnValues) {
274-
const { displayName, generatedFunctions, generatorType } = returnValues[id]
275-
276-
if (!generatedFunctions || generatedFunctions.length === 0) {
277-
continue
278-
}
279-
280-
result[id] = {
281-
displayName,
282-
generatorType,
283-
functionNames: generatedFunctions.map((func) => basename(func.path)),
284-
}
262+
const getGeneratedFunctionsByGenerator = (
263+
generatedFunctions: GeneratedFunction[],
264+
): Record<string, GeneratedFunction[]> => {
265+
const result: Record<string, GeneratedFunction[]> = {}
266+
267+
for (const func of generatedFunctions) {
268+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
269+
result[func.generator.name] = result[func.generator.name] || []
270+
result[func.generator.name].push(func)
285271
}
286272

287273
return result
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
type GeneratorType = 'build plugin' | 'extension'
2+
3+
export interface GeneratedFunction {
4+
generator: {
5+
displayName: string
6+
name: string
7+
type: GeneratorType
8+
}
9+
path: string
10+
}
11+
12+
export interface ReturnValue {
13+
displayName?: string
14+
generatedFunctions?: { path: string }[]
15+
generatorType: GeneratorType
16+
}
17+
18+
export const getGeneratedFunctions = (returnValues?: Record<string, ReturnValue>): GeneratedFunction[] => {
19+
return Object.entries(returnValues ?? {}).flatMap(([name, returnValue]) => {
20+
const generator = {
21+
displayName: returnValue.displayName ?? name,
22+
name,
23+
type: returnValue.generatorType,
24+
}
25+
26+
return (
27+
returnValue.generatedFunctions?.map((func) => ({
28+
generator,
29+
path: func.path,
30+
})) ?? []
31+
)
32+
})
33+
}

packages/build/src/steps/run_steps.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ export const runSteps = async function ({
164164

165165
const statusesA = addStatus({ newStatus, statuses, event, packageName, pluginPackageJson })
166166

167-
/** @type import('../types/step.js').ReturnValue */
167+
/** @type import('../steps/return_values.js').ReturnValue */
168168
const augmentedReturnValue = returnValue
169169
? {
170170
...returnValue,

packages/build/src/types/step.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

packages/build/tests/core/tests.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,15 +460,18 @@ test.serial('Passes the right properties to zip-it-and-ship-it', async (t) => {
460460
})
461461

462462
test.serial('Passes functions generated by build plugins to zip-it-and-ship-it', async (t) => {
463-
const mockZipFunctions = sinon.stub().resolves()
463+
const mockZipFunctions = sinon.stub().resolves([])
464464
const stub = sinon.stub(zipItAndShipIt, 'zipFunctions').get(() => mockZipFunctions)
465465
const fixtureName = 'functions_generated_from_steps'
466466
const fixtureDir = join(FIXTURES_DIR, fixtureName)
467467

468-
await new Fixture(`./fixtures/${fixtureName}`).withFlags({ mode: 'buildbot' }).runWithBuild()
468+
const { success, generatedFunctions } = await new Fixture(`./fixtures/${fixtureName}`)
469+
.withFlags({ mode: 'buildbot' })
470+
.runWithBuildAndIntrospect()
469471

470472
stub.restore()
471473

474+
t.true(success)
472475
t.is(mockZipFunctions.callCount, 1)
473476

474477
const { generated, user } = mockZipFunctions.firstCall.args[0]
@@ -487,6 +490,14 @@ test.serial('Passes functions generated by build plugins to zip-it-and-ship-it',
487490
t.is(user.directories.length, 1)
488491
t.true(user.directories.includes(resolve(fixtureDir, 'netlify/functions')))
489492
t.is(user.functions, undefined)
493+
494+
t.is(generatedFunctions.length, 1)
495+
t.deepEqual(generatedFunctions[0].generator, {
496+
displayName: './.netlify/plugins/node_modules/plugin/plugin.mjs',
497+
name: './.netlify/plugins/node_modules/plugin/plugin.mjs',
498+
type: 'build plugin',
499+
})
500+
t.is(generatedFunctions[0].path, join(fixtureDir, '.netlify/plugins/node_modules/plugin/functions/plugin-func1.mjs'))
490501
})
491502

492503
test.serial('Passes the right feature flags to zip-it-and-ship-it', async (t) => {

0 commit comments

Comments
 (0)