Skip to content

Commit

Permalink
fix: handle cors issue (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien-R44 committed Jun 2, 2024
1 parent 20bd446 commit 864659e
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 12 deletions.
10 changes: 10 additions & 0 deletions configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,21 @@ export async function configure(command: Configure) {
await codemods.makeUsingStub(stubsRoot, 'vite.config.stub', {})
await codemods.makeUsingStub(stubsRoot, 'js_entrypoint.stub', {})

/**
* Update RC file
*/
await codemods.updateRcFile((rcFile) => {
rcFile.addProvider('@adonisjs/vite/vite_provider')
rcFile.addMetaFile('public/**', false)
})

/**
* Add server middleware
*/
await codemods.registerMiddleware('server', [
{ path: '@adonisjs/vite/vite_middleware', position: 'after' },
])

/**
* Prompt when `install` or `--no-install` flags are
* not used
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
".": "./build/index.js",
"./vite_provider": "./build/providers/vite_provider.js",
"./plugins/edge": "./build/src/plugins/edge.js",
"./vite_middleware": "./build/src/vite_middleware.js",
"./build_hook": "./build/src/hooks/build_hook.js",
"./services/main": "./build/services/vite.js",
"./client": "./build/src/client/main.js",
Expand Down Expand Up @@ -52,13 +53,15 @@
"@japa/snapshot": "^2.0.4",
"@swc/core": "^1.4.2",
"@types/node": "^20.11.20",
"@types/supertest": "^6.0.2",
"c8": "^9.1.0",
"copyfiles": "^2.4.1",
"del-cli": "^5.1.0",
"edge.js": "^6.0.1",
"eslint": "^8.57.0",
"np": "^10.0.0",
"prettier": "^3.2.5",
"supertest": "^6.3.4",
"ts-node": "^10.9.2",
"tsup": "^8.0.2",
"typescript": "~5.3.3",
Expand Down Expand Up @@ -126,6 +129,7 @@
"entry": [
"./src/hooks/build_hook.ts",
"./providers/vite_provider.ts",
"./src/vite_middleware.ts",
"./src/plugins/edge.ts",
"./src/client/main.ts",
"./services/vite.ts",
Expand Down
11 changes: 3 additions & 8 deletions providers/vite_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { cspKeywords as ShieldCSPKeywords } from '@adonisjs/shield'

import { Vite } from '../src/vite.js'
import type { ViteOptions } from '../src/types.js'
import ViteMiddleware from '../src/middleware/vite_middleware.js'
import ViteMiddleware from '../src/vite_middleware.js'

declare module '@adonisjs/core/types' {
interface ContainerBindings {
Expand Down Expand Up @@ -80,7 +80,7 @@ export default class ViteProvider {

const vite = new Vite(this.#shouldRunVite, config)
this.app.container.bind('vite', () => vite)
this.app.container.bind(ViteMiddleware, () => new ViteMiddleware(vite))
this.app.container.singleton(ViteMiddleware, () => new ViteMiddleware(vite))
}

/**
Expand All @@ -92,13 +92,8 @@ export default class ViteProvider {

if (!this.#shouldRunVite) return

const [vite, server] = await Promise.all([
this.app.container.make('vite'),
this.app.container.make('server'),
])

const vite = await this.app.container.make('vite')
await vite.createDevServer()
server.use([() => import('../src/middleware/vite_middleware.js')])
}

/**
Expand Down
7 changes: 7 additions & 0 deletions src/client/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ export function configHook(
publicDir: userConfig.publicDir ?? false,
base: resolveBase(userConfig, options, command),

/**
* Disable the vite dev server cors handling. Otherwise, it will
* override the cors settings defined by @adonisjs/cors
* https://github.com/adonisjs/vite/issues/13
*/
server: { cors: userConfig.server?.cors ?? false },

build: {
assetsDir: '',
emptyOutDir: true,
Expand Down
14 changes: 12 additions & 2 deletions src/middleware/vite_middleware.ts → src/vite_middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { ViteDevServer } from 'vite'
import type { HttpContext } from '@adonisjs/core/http'
import type { NextFn } from '@adonisjs/core/types/http'

import type { Vite } from '../vite.js'
import type { Vite } from './vite.js'

/**
* Since Vite dev server is integrated within the AdonisJS process, this
Expand All @@ -29,7 +29,17 @@ export default class ViteMiddleware {
}

async handle({ request, response }: HttpContext, next: NextFn) {
return await new Promise((resolve) => {
if (!this.#devServer) return next()

/**
* @adonisjs/cors should handle the CORS instead of Vite
*/
if (this.#devServer.config.server.cors === false) response.relayHeaders()

/**
* Proxy the request to the vite dev server
*/
await new Promise((resolve) => {
this.#devServer.middlewares.handle(request.request, response.response, () => {
return resolve(next())
})
Expand Down
76 changes: 76 additions & 0 deletions tests/backend/middleware.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* @adonisjs/vite
*
* (c) AdonisJS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

import supertest from 'supertest'
import { test } from '@japa/runner'
import { createServer } from 'node:http'
import { RequestFactory, ResponseFactory, HttpContextFactory } from '@adonisjs/core/factories/http'

import { Vite } from '../../index.js'
import { createVite } from './helpers.js'
import adonisjs from '../../src/client/main.js'
import ViteMiddleware from '../../src/vite_middleware.js'

test.group('Vite Middleware', () => {
test('if route is handled by vite, relay cors headers', async ({ assert, fs }) => {
await fs.create('resources/js/app.ts', 'console.log("Hello world")')

const vite = await createVite(
{ buildDirectory: 'foo', manifestFile: 'bar.json' },
{ plugins: [adonisjs({ entrypoints: ['./resources/js/app.ts'] })] }
)

const server = createServer(async (req, res) => {
const middleware = new ViteMiddleware(vite)

const request = new RequestFactory().merge({ req, res }).create()
const response = new ResponseFactory().merge({ req, res }).create()
const ctx = new HttpContextFactory().merge({ request, response }).create()

response.header('access-control-allow-origin', 'http://test-origin.com')

await middleware.handle(ctx, () => {})

ctx.response.finish()
})

const res = await supertest(server).get('/resources/js/app.ts')
assert.equal(res.headers['access-control-allow-origin'], 'http://test-origin.com')

const resOptions = await supertest(server).options('/resources/js/app.ts')
assert.equal(resOptions.headers['access-control-allow-origin'], 'http://test-origin.com')
})

test('if vite dev server is not available, call next middleware', async ({ assert }) => {
class FakeVite extends Vite {
getDevServer() {
return undefined
}
}

const vite = new FakeVite(false, { buildDirectory: 'foo', manifestFile: 'bar.json' })

const server = createServer(async (req, res) => {
const middleware = new ViteMiddleware(vite)

const request = new RequestFactory().merge({ req, res }).create()
const response = new ResponseFactory().merge({ req, res }).create()
const ctx = new HttpContextFactory().merge({ request, response }).create()

await middleware.handle(ctx, () => {
ctx.response.status(200).send('handled by next middleware')
})

ctx.response.finish()
})

const res = await supertest(server).get('/resources/js/app.ts')
assert.equal(res.text, 'handled by next middleware')
})
})
2 changes: 1 addition & 1 deletion tests/backend/provider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { setTimeout } from 'node:timers/promises'
import { IgnitorFactory } from '@adonisjs/core/factories'

import { defineConfig } from '../../index.js'
import ViteMiddleware from '../../src/middleware/vite_middleware.js'
import ViteMiddleware from '../../src/vite_middleware.js'

const BASE_URL = new URL('./tmp/', import.meta.url)
const IMPORTER = (filePath: string) => {
Expand Down
10 changes: 10 additions & 0 deletions tests/client/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,14 @@ test.group('Vite plugin', () => {
const config = plugin!.config!({}, { command: 'build' })
assert.deepEqual(config.base, 'https://cdn.com/')
})

test('disable vite dev server cors handling', async ({ assert }) => {
const plugin = adonisjs({
entrypoints: ['./resources/js/app.ts'],
})[1] as Plugin

// @ts-ignore
const config = plugin!.config!({}, { command: 'serve' })
assert.deepEqual(config.server?.cors, false)
})
})
6 changes: 5 additions & 1 deletion tests/configure.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { BASE_URL } from './backend/helpers.js'
test.group('Configure', (group) => {
group.each.disableTimeout()

test('create config file and register provider', async ({ assert, fs }) => {
test('create config file and register provider and middleware', async ({ assert, fs }) => {
const ignitor = new IgnitorFactory()
.withCoreProviders()
.withCoreConfig()
Expand All @@ -33,6 +33,7 @@ test.group('Configure', (group) => {
await fs.create('.env', '')
await fs.createJson('tsconfig.json', {})
await fs.create('adonisrc.ts', `export default defineConfig({})`)
await fs.create('start/kernel.ts', `server.use([])`)

const app = ignitor.createApp('web')
await app.init()
Expand All @@ -51,6 +52,7 @@ test.group('Configure', (group) => {
await assert.fileContains('vite.config.ts', `import adonisjs from '@adonisjs/vite/client'`)
await assert.fileContains('adonisrc.ts', `pattern: 'public/**'`)
await assert.fileContains('adonisrc.ts', `reloadServer: false`)
await assert.fileContains('start/kernel.ts', '@adonisjs/vite/vite_middleware')
})

test('install package when --install flag is used', async ({ assert, fs }) => {
Expand All @@ -71,6 +73,7 @@ test.group('Configure', (group) => {
await fs.createJson('tsconfig.json', {})
await fs.createJson('package.json', {})
await fs.create('adonisrc.ts', `export default defineConfig({})`)
await fs.create('start/kernel.ts', `server.use([])`)

const app = ignitor.createApp('web')
await app.init()
Expand Down Expand Up @@ -101,6 +104,7 @@ test.group('Configure', (group) => {
await fs.createJson('tsconfig.json', {})
await fs.createJson('package.json', {})
await fs.create('adonisrc.ts', `export default defineConfig({})`)
await fs.create('start/kernel.ts', `server.use([])`)

const app = ignitor.createApp('web')
await app.init()
Expand Down

0 comments on commit 864659e

Please sign in to comment.