Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d879ac2

Browse files
committed
fix: don't delete functions generated by other build plugins
1 parent 4345795 commit d879ac2

File tree

2 files changed

+84
-9
lines changed

2 files changed

+84
-9
lines changed

‎src/build/functions/edge.ts

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'
2-
import { dirname, join } from 'node:path'
1+
import { cp, mkdir, readdir,readFile, rm, writeFile } from 'node:fs/promises'
2+
import { dirname, join,parseasparsePath } from 'node:path'
33

44
import type { Manifest, ManifestFunction } from '@netlify/edge-functions'
55
import { glob } from 'fast-glob'
@@ -8,9 +8,21 @@ import { pathToRegexp } from 'path-to-regexp'
88

99
import { EDGE_HANDLER_NAME, PluginContext } from '../plugin-context.js'
1010

11+
type ManifestFunctionWithGenerator = ManifestFunction & { generator?: string }
12+
13+
const getEdgeManifestPath = (ctx: PluginContext) => join(ctx.edgeFunctionsDir, 'manifest.json')
14+
1115
const writeEdgeManifest = async (ctx: PluginContext, manifest: Manifest) => {
1216
await mkdir(ctx.edgeFunctionsDir, { recursive: true })
13-
await writeFile(join(ctx.edgeFunctionsDir, 'manifest.json'), JSON.stringify(manifest, null, 2))
17+
await writeFile(getEdgeManifestPath(ctx), JSON.stringify(manifest, null, 2))
18+
}
19+
20+
const readEdgeManifest = async (ctx: PluginContext) => {
21+
try {
22+
return JSON.parse(await readFile(getEdgeManifestPath(ctx), 'utf-8')) as Manifest
23+
} catch {
24+
return null
25+
}
1426
}
1527

1628
const copyRuntime = async (ctx: PluginContext, handlerDirectory: string): Promise<void> => {
@@ -145,7 +157,7 @@ const getHandlerName = ({ name }: Pick<NextDefinition, 'name'>): string =>
145157
const buildHandlerDefinition = (
146158
ctx: PluginContext,
147159
{ name, matchers, page }: NextDefinition,
148-
): Array<ManifestFunction> => {
160+
): Array<ManifestFunctionWithGenerator> => {
149161
const fun = getHandlerName({ name })
150162
const funName = name.endsWith('middleware')
151163
? 'Next.js Middleware Handler'
@@ -162,8 +174,35 @@ const buildHandlerDefinition = (
162174
}))
163175
}
164176

177+
const clearStaleEdgeHandlers = async (ctx: PluginContext) => {
178+
const previousManifest = await readEdgeManifest(ctx)
179+
if (!previousManifest) {
180+
return []
181+
}
182+
183+
const uniqueNextRuntimeFunctions = new Set<string>()
184+
const nonNextRuntimeFunctions: ManifestFunctionWithGenerator[] = []
185+
186+
for (const fn of previousManifest.functions as ManifestFunctionWithGenerator[]) {
187+
if (fn?.generator?.startsWith(ctx.pluginName)) {
188+
uniqueNextRuntimeFunctions.add(fn.function)
189+
} else {
190+
nonNextRuntimeFunctions.push(fn)
191+
}
192+
}
193+
194+
for (const fileOrDir of await readdir(ctx.edgeFunctionsDir, { withFileTypes: true })) {
195+
const nameWithoutExtension = parsePath(fileOrDir.name).name
196+
197+
if (uniqueNextRuntimeFunctions.has(nameWithoutExtension)) {
198+
await rm(join(ctx.edgeFunctionsDir, fileOrDir.name), { recursive: true, force: true })
199+
}
200+
}
201+
return nonNextRuntimeFunctions
202+
}
203+
165204
export const createEdgeHandlers = async (ctx: PluginContext) => {
166-
awaitrm(ctx.edgeFunctionsDir,{recursive: true,force: true})
205+
constnonNextRuntimeFunctions=awaitclearStaleEdgeHandlers(ctx)
167206

168207
const nextManifest = await ctx.getMiddlewareManifest()
169208
const nextDefinitions = [
@@ -175,7 +214,7 @@ export const createEdgeHandlers = async (ctx: PluginContext) => {
175214
const netlifyDefinitions = nextDefinitions.flatMap((def) => buildHandlerDefinition(ctx, def))
176215
const netlifyManifest: Manifest = {
177216
version: 1,
178-
functions: netlifyDefinitions,
217+
functions: [...nonNextRuntimeFunctions, ...netlifyDefinitions],
179218
}
180219
await writeEdgeManifest(ctx, netlifyManifest)
181220
}

‎src/build/functions/server.ts

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'
2-
import { join, relative } from 'node:path'
1+
import { cp, mkdir, readdir,readFile, rm, writeFile } from 'node:fs/promises'
2+
import { join, parseasparsePath,relative } from 'node:path'
33
import { join as posixJoin } from 'node:path/posix'
44

55
import { trace } from '@opentelemetry/api'
@@ -127,12 +127,48 @@ const writeHandlerFile = async (ctx: PluginContext) => {
127127
await writeFile(join(ctx.serverHandlerRootDir, `${SERVER_HANDLER_NAME}.mjs`), handler)
128128
}
129129

130+
const clearStaleServerHandlers = async (ctx: PluginContext) => {
131+
const potentialServerlessFunctionConfigFiles = await glob('**/*.json', {
132+
deep: 2,
133+
cwd: ctx.serverFunctionsDir,
134+
})
135+
136+
const toRemove = new Set<string>()
137+
138+
for (const potentialServerlessFunctionConfigFile of potentialServerlessFunctionConfigFiles) {
139+
try {
140+
const functionConfig = JSON.parse(
141+
await readFile(
142+
join(ctx.serverFunctionsDir, potentialServerlessFunctionConfigFile),
143+
'utf-8',
144+
),
145+
)
146+
147+
if (functionConfig?.config?.generator?.startsWith(ctx.pluginName)) {
148+
const parsedPath = parsePath(potentialServerlessFunctionConfigFile)
149+
150+
toRemove.add(parsedPath.dir || parsedPath.name)
151+
}
152+
} catch {
153+
// this might be malformatted json or json that doesn't represent function configuration
154+
// so we just skip it in case of errors
155+
}
156+
}
157+
158+
for (const fileOrDir of await readdir(ctx.serverFunctionsDir, { withFileTypes: true })) {
159+
const nameWithoutExtension = parsePath(fileOrDir.name).name
160+
161+
if (toRemove.has(nameWithoutExtension)) {
162+
await rm(join(ctx.serverFunctionsDir, fileOrDir.name), { recursive: true, force: true })
163+
}
164+
}
165+
}
130166
/**
131167
* Create a Netlify function to run the Next.js server
132168
*/
133169
export const createServerHandler = async (ctx: PluginContext) => {
134170
await tracer.withActiveSpan('createServerHandler', async () => {
135-
await rm(ctx.serverFunctionsDir,{recursive: true,force: true})
171+
await clearStaleServerHandlers(ctx)
136172
await mkdir(join(ctx.serverHandlerDir, '.netlify'), { recursive: true })
137173

138174
await copyNextServerCode(ctx)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /