Skip to content

Commit

Permalink
Sfs 1755 generate middleware in build time (#2540)
Browse files Browse the repository at this point in the history
## What's the purpose of this pull request?

This task will allow enabling the redirects middleware within
**@faststore/core** during the build process based on a flag.

The idea is to enable this functionality only for projects that have the
flag `ENABLE_REDIRECTS_MIDDLEWARE` saved in the env vars and which are
hosted by homebrew. In the future, we intend to have control of this
feature through webops.

Next steps: 

- Set this flag in a pipeline env var.
- Implements dynamoDB client (Reference:
#2517)

## How it works?

The key is the name of the file: **middleware__DISABLED.ts**

This middleware is disabled by default. Only stores that are in
**homebrew** and want this functionality will be able to enable it via a
feature flag. When the flag is active, the CLI at build time will check
whether the **ENABLE_REDIRECTS_MIDDLEWARE** flag is set or not, if so,
the file name will be changed to **middleware.ts** and nextjs will know
how to automatically deal with it.

## How to test it?
I created a [PR](vtex-sites/starter.store#599)
with the flag enabled, clone the branch and then:

- Run `yarn build`
- check if the **middleware.ts** was created inside **.faststore/src**

### References


https://docs.google.com/document/d/1iC1fLwJbypnvDyp_JilKBfQfaHjFDHYrjS1kC722sB4/edit?tab=t.0#heading=h.tglo77yl0lf5
  • Loading branch information
pedromtec authored Nov 12, 2024
1 parent 5d3b33b commit 6bbe1b1
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
35 changes: 35 additions & 0 deletions packages/cli/src/utils/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,40 @@ function validateAndInstallMissingDependencies(basePath: string) {
})
}

// TODO: Read the value from an environment variable
const ENABLE_REDIRECTS_MIDDLEWARE = false

// Enable redirects middleware by renaming the file from middleware__DISABLED.ts to middleware.tsß
function enableRedirectsMiddleware(basePath: string) {
if (!ENABLE_REDIRECTS_MIDDLEWARE) {
return
}

try {
const { tmpDir } = withBasePath(basePath)

const disabledMiddlewarePath = path.join(
tmpDir,
'src',
'middleware__DISABLED.ts'
)

/* Rename the file to enable middleware functionality and then remove the disabled middleware file */
if (existsSync(disabledMiddlewarePath)) {
const enabledMiddlewarePath = path.join(tmpDir, 'src', 'middleware.ts')
copyFileSync(disabledMiddlewarePath, enabledMiddlewarePath)
removeSync(disabledMiddlewarePath)

logger.log(
`${chalk.green('success')} Redirects middleware has been enabled`
)
}
} catch (error) {
logger.error(error)
throw error
}
}

export async function generate(options: GenerateOptions) {
const { basePath, setup = false } = options

Expand All @@ -461,5 +495,6 @@ export async function generate(options: GenerateOptions) {
copyTheme(basePath),
createCmsWebhookUrlsJsonFile(basePath),
updateNextConfig(basePath),
enableRedirectsMiddleware(basePath),
])
}
65 changes: 65 additions & 0 deletions packages/core/src/middleware__DISABLED.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* This middleware is disabled by default. Only stores that are in
* homebrew and want this functionality will be able to enable it via
* a feature flag. When the flag is active, the CLI at build time will
* check whether the ENABLE_REDIRECTS_MIDDLEWARE flag is set or not,
* if so, the file name will be changed to middleware.ts and nextjs
* will know how to automatically deal with it.
*/

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import storeConfig from 'discovery.config'

type Redirect = {
from: string
to: string
type: 'permanent' | 'temporary'
}
interface RedirectsClient {
get(from: string): Promise<Redirect | null>
}

class DynamoRedirectsClient implements RedirectsClient {
async get(from: string): Promise<Redirect | null> {
// TODO: Implement DynamoDB client. Ensure that the cluster has access to DynamoDB first.
return null
}
}

const redirectsClient = new DynamoRedirectsClient()

export async function middleware(request: NextRequest) {
const { pathname } = request.nextUrl

const redirect = await redirectsClient.get(pathname)

if (redirect) {
const redirectUrl = new URL(redirect.to, storeConfig.storeUrl)
const redirectStatusCode = redirect.type === 'permanent' ? 301 : 302

const response = NextResponse.redirect(redirectUrl, redirectStatusCode)

response.headers.set(
'Cache-Control',
'public, max-age=300, stale-while-revalidate=31536000'
)

return response
}

return NextResponse.next()
}

export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
*/
'/((?!api|_next/static|_next/image|favicon.ico).*)',
],
}

0 comments on commit 6bbe1b1

Please sign in to comment.