Skip to content

Commit f2084b8

Browse files
orinokaiMarcL
andauthoredFeb 22, 2024
feat: check for root publish dir (#292)
* feat: check for root publish dir * test: add test to catch root publish dir * fix: error message clarity Co-authored-by: Marc Littlemore <MarcL@users.noreply.github.com> * fix: error message consistency Co-authored-by: Marc Littlemore <MarcL@users.noreply.github.com> --------- Co-authored-by: Marc Littlemore <MarcL@users.noreply.github.com>
1 parent 01e9450 commit f2084b8

File tree

4 files changed

+33
-19
lines changed

4 files changed

+33
-19
lines changed
 

‎src/build/plugin-context.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { join } from 'node:path'
22

33
import { NetlifyPluginOptions } from '@netlify/build'
4-
import { test, expect, vi } from 'vitest'
4+
import { expect, test, vi } from 'vitest'
55

66
import { mockFileSystem } from '../../tests/index.js'
77

@@ -66,7 +66,7 @@ test('next app with deep custom distDir', () => {
6666
expect(ctx.standaloneDir).toBe(join(cwd, 'out/dir/standalone/out'))
6767
expect(ctx.standaloneRootDir).toBe(join(cwd, 'out/dir/standalone'))
6868
expect(ctx.distDir).toBe('out/dir')
69-
expect(ctx.distFolder).toBe('out')
69+
expect(ctx.distDirParent).toBe('out')
7070
expect(ctx.nextDistDir).toBe('dir')
7171
expect(ctx.relPublishDir).toBe('out/dir')
7272
expect(ctx.publishDir).toBe(join(cwd, 'out/dir'))
@@ -103,7 +103,7 @@ test('monorepo with package path', () => {
103103
expect(ctx.standaloneRootDir).toBe(join(cwd, 'apps/my-app/.next/standalone'))
104104
expect(ctx.staticDir).toBe(join(cwd, 'apps/my-app/.netlify/static'))
105105
expect(ctx.distDir).toBe('apps/my-app/.next')
106-
expect(ctx.distFolder).toBe('apps/my-app')
106+
expect(ctx.distDirParent).toBe('apps/my-app')
107107
expect(ctx.nextDistDir).toBe('.next')
108108
expect(ctx.relPublishDir).toBe('apps/my-app/.next')
109109
expect(ctx.publishDir).toBe(join(cwd, 'apps/my-app/.next'))
@@ -142,7 +142,7 @@ test('nx monorepo with package path and different distDir', () => {
142142
expect(ctx.standaloneRootDir).toBe(join(cwd, 'dist/apps/my-app/.next/standalone'))
143143
expect(ctx.staticDir).toBe(join(cwd, 'apps/my-app/.netlify/static'))
144144
expect(ctx.distDir).toBe('dist/apps/my-app/.next')
145-
expect(ctx.distFolder).toBe('dist/apps/my-app')
145+
expect(ctx.distDirParent).toBe('dist/apps/my-app')
146146
expect(ctx.nextDistDir).toBe('.next')
147147
expect(ctx.relPublishDir).toBe('dist/apps/my-app/.next')
148148
expect(ctx.publishDir).toBe(join(cwd, 'dist/apps/my-app/.next'))

‎src/build/plugin-context.ts

+20-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { readFileSync } from 'node:fs'
1+
import { existsSync, readFileSync } from 'node:fs'
22
import { readFile } from 'node:fs/promises'
33
// Here we need to actually import `resolve` from node:path as we want to resolve the paths
44
// eslint-disable-next-line no-restricted-imports
@@ -62,7 +62,7 @@ export class PluginContext {
6262
* The working directory inside the lambda that is used for monorepos to execute the serverless function
6363
*/
6464
get lambdaWorkingDirectory(): string {
65-
return join('/var/task', this.distFolder)
65+
return join('/var/task', this.distDirParent)
6666
}
6767

6868
/**
@@ -83,16 +83,16 @@ export class PluginContext {
8383
return relative(process.cwd(), resolve(this.packagePath, dir))
8484
}
8585

86-
/** The dist folder represents the parent directory of the .next folder or custom distDir */
87-
get distFolder(): string {
86+
/** Represents the parent directory of the .next folder or custom distDir */
87+
get distDirParent(): string {
8888
// the .. is omitting the last part of the dist dir like `.next` but as it can be any custom folder
8989
// let's just move one directory up with that
9090
return join(this.distDir, '..')
9191
}
9292

9393
/** The `.next` folder or what the custom dist dir is set to */
9494
get nextDistDir(): string {
95-
return relative(this.distFolder, this.distDir)
95+
return relative(this.distDirParent, this.distDir)
9696
}
9797

9898
/** Retrieves the `.next/standalone/` directory monorepo aware */
@@ -102,7 +102,7 @@ export class PluginContext {
102102
// if the publish directory is .next the standalone directory will be `.next/standalone`
103103
// for nx workspaces where the publish directory is on the root of the repository
104104
// like `dist/apps/my-app/.next` the standalone directory will be `.next/standalone/dist/apps/my-app`
105-
return join(this.standaloneRootDir, this.distFolder)
105+
return join(this.standaloneRootDir, this.distDirParent)
106106
}
107107

108108
/**
@@ -139,7 +139,7 @@ export class PluginContext {
139139
if (this.packagePath.length === 0) {
140140
return this.serverHandlerRootDir
141141
}
142-
return join(this.serverHandlerRootDir, this.distFolder)
142+
return join(this.serverHandlerRootDir, this.distDirParent)
143143
}
144144

145145
get nextServerHandler(): string {
@@ -213,4 +213,17 @@ export class PluginContext {
213213
failBuild(message: string, error?: unknown): never {
214214
return this.utils.build.failBuild(message, error instanceof Error ? { error } : undefined)
215215
}
216+
217+
verifyPublishDir() {
218+
if (!existsSync(this.publishDir)) {
219+
this.failBuild(
220+
`Your publish directory was not found at: ${this.publishDir}, please check your build settings`,
221+
)
222+
}
223+
if (this.publishDir === this.resolve(this.packagePath)) {
224+
this.failBuild(
225+
`Your publish directory cannot be the same as the base directory of your site, please check your build settings`,
226+
)
227+
}
228+
}
216229
}

‎src/index.ts

+2-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { existsSync } from 'node:fs'
2-
31
import type { NetlifyPluginOptions } from '@netlify/build'
42

53
import { restoreBuildCache, saveBuildCache } from './build/cache.js'
@@ -25,12 +23,7 @@ export const onPreBuild = async (options: NetlifyPluginOptions) => {
2523

2624
export const onBuild = async (options: NetlifyPluginOptions) => {
2725
const ctx = new PluginContext(options)
28-
if (!existsSync(ctx.publishDir)) {
29-
ctx.failBuild(
30-
`Publish directory not found under: ${ctx.publishDir}, please check your netlify.toml`,
31-
)
32-
}
33-
await setImageConfig(ctx)
26+
ctx.verifyPublishDir()
3427

3528
// only save the build cache if not run via the CLI
3629
if (!options.constants.IS_LOCAL) {
@@ -43,6 +36,7 @@ export const onBuild = async (options: NetlifyPluginOptions) => {
4336
copyPrerenderedContent(ctx),
4437
createServerHandler(ctx),
4538
createEdgeHandlers(ctx),
39+
setImageConfig(ctx),
4640
])
4741
}
4842

‎tests/integration/simple-app.test.ts

+7
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ test<FixtureTestContext>('Test that the simple next app is working', async (ctx)
6363
expect(load(notFound.body)('h1').text()).toBe('404')
6464
})
6565

66+
test<FixtureTestContext>('Should warn if publish dir is root', async (ctx) => {
67+
await createFixture('simple-next-app', ctx)
68+
expect(() => runPlugin(ctx, { PUBLISH_DIR: '.' })).rejects.toThrowError(
69+
'check your build settings',
70+
)
71+
})
72+
6673
test<FixtureTestContext>('Should add cache-tags to prerendered app pages', async (ctx) => {
6774
await createFixture('simple-next-app', ctx)
6875
await runPlugin(ctx)

0 commit comments

Comments
 (0)
Please sign in to comment.