Skip to content

Commit d991bfd

Browse files
authored
fix(vite): support new cors rules in Vite 6 (#890)
1 parent dec5c2f commit d991bfd

File tree

5 files changed

+113
-13
lines changed

5 files changed

+113
-13
lines changed

bun.lockb

2.54 KB
Binary file not shown.

package.json

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"private": true,
3-
"workspaces": ["packages/*"],
3+
"workspaces": [
4+
"packages/*"
5+
],
46
"scripts": {
57
"qa": "bun lint:fix && bun run test run && bun run build",
68
"lint": "eslint packages",
@@ -10,13 +12,13 @@
1012
"test": "vitest"
1113
},
1214
"devDependencies": {
13-
"@innocenzi/eslint-config": "^0.22.4",
15+
"@innocenzi/eslint-config": "^0.22.6",
1416
"@types/bun": "latest",
15-
"bumpp": "^9.9.0",
16-
"eslint": "^9.16.0",
17-
"typescript": "^5.7.2",
18-
"unbuild": "^2.0.0",
17+
"bumpp": "^10.0.1",
18+
"eslint": "^9.19.0",
19+
"typescript": "^5.7.3",
20+
"unbuild": "^3.3.1",
1921
"vite-plugin-tempest": "workspace:*",
20-
"vitest": "^2.1.8"
22+
"vitest": "^3.0.4"
2123
}
2224
}

packages/vite-plugin-tempest/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vite-plugin-tempest",
33
"type": "module",
4-
"version": "0.0.1",
4+
"version": "0.0.2",
55
"author": "Enzo Innocenzi",
66
"license": "MIT",
77
"sideEffects": false,

packages/vite-plugin-tempest/src/plugin.test.ts

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
import { afterEach, describe, expect, it, vi } from 'vitest'
1+
import fs from 'node:fs'
2+
import path from 'node:path'
3+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
24
import tempest from './plugin'
35
import { mockTempestConfiguration } from './test-utils'
46

57
describe('tempest', () => {
8+
beforeEach(() => {
9+
process.env.TEMPEST_BYPASS_ENV_CHECK = 'true'
10+
})
11+
612
afterEach(() => {
713
vi.restoreAllMocks()
814
})
@@ -34,4 +40,83 @@ describe('tempest', () => {
3440
'src/main.ts',
3541
] })
3642
})
43+
44+
it("respects the user's server.cors config", async () => {
45+
mockTempestConfiguration()
46+
47+
const plugin = tempest()
48+
49+
// @ts-expect-error typing
50+
const resolvedConfig = await plugin.config({
51+
server: {
52+
cors: true,
53+
},
54+
}, {
55+
mode: '',
56+
command: 'serve',
57+
})
58+
59+
expect(resolvedConfig.server.cors).toBe(true)
60+
})
61+
62+
it('configures default cors.origin values', async () => {
63+
mockTempestConfiguration()
64+
65+
const test = (pattern: RegExp | string, value: string) => pattern instanceof RegExp ? pattern.test(value) : pattern === value
66+
fs.writeFileSync(path.join(__dirname, '.env'), 'APP_URL=http://example.com')
67+
68+
const plugin = tempest()
69+
70+
// @ts-expect-error typing
71+
const resolvedConfig = await plugin.config({ envDir: __dirname }, {
72+
mode: '',
73+
command: 'serve',
74+
})
75+
76+
// Allowed origins...
77+
expect([
78+
// localhost
79+
'http://localhost',
80+
'https://localhost',
81+
'http://localhost:8080',
82+
'https://localhost:8080',
83+
// 127.0.0.1
84+
'http://127.0.0.1',
85+
'https://127.0.0.1',
86+
'http://127.0.0.1:8000',
87+
'https://127.0.0.1:8000',
88+
// *.test
89+
'http://tempest.test',
90+
'https://tempest.test',
91+
'http://tempest.test:8000',
92+
'https://tempest.test:8000',
93+
'http://my-app.test',
94+
'https://my-app.test',
95+
'http://my-app.test:8000',
96+
'https://my-app.test:8000',
97+
'https://my-app.test:8',
98+
// APP_URL
99+
'http://example.com',
100+
'https://subdomain.my-app.test',
101+
].some((url) => resolvedConfig.server.cors.origin.some((regex: RegExp) => test(regex, url)))).toBe(true)
102+
103+
// Disallowed origins...
104+
expect([
105+
'http://tempest.com',
106+
'https://tempest.com',
107+
'http://tempest.com:8000',
108+
'https://tempest.com:8000',
109+
'http://128.0.0.1',
110+
'https://128.0.0.1',
111+
'http://128.0.0.1:8000',
112+
'https://128.0.0.1:8000',
113+
'https://example.com',
114+
'http://example.com:8000',
115+
'https://example.com:8000',
116+
'http://exampletest',
117+
'http://example.test:',
118+
].some((url) => resolvedConfig.server.cors.origin.some((regex: RegExp) => test(regex, url)))).toBe(false)
119+
120+
fs.rmSync(path.join(__dirname, '.env'))
121+
})
37122
})

packages/vite-plugin-tempest/src/plugin.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type { DevelopmentServerUrl, TempestViteConfiguration } from './types'
1111
import { loadTempestConfiguration } from './config'
1212
import { isIpv6 } from './utils'
1313

14-
const TEMPEST_ORIGIN_PLACEHOLDER = '__tempest_placeholder__'
14+
const TEMPEST_ORIGIN_PLACEHOLDER = 'http://__tempest_placeholder__.test'
1515

1616
let exitHandlersBound = false
1717

@@ -55,6 +55,13 @@ export default function tempest(): Plugin {
5555
},
5656
server: {
5757
origin: userConfig.server?.origin ?? TEMPEST_ORIGIN_PLACEHOLDER,
58+
cors: userConfig.server?.cors ?? {
59+
origin: userConfig.server?.origin ?? [
60+
env.BASE_URI,
61+
/^https?:\/\/(?:(?:[^:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/,
62+
/^https?:\/\/.*\.test(:\d+)?$/,
63+
].filter(Boolean),
64+
},
5865
...(serverConfig
5966
? {
6067
host: userConfig.server?.host ?? serverConfig.host,
@@ -94,7 +101,7 @@ export default function tempest(): Plugin {
94101
},
95102
configureServer(server) {
96103
const envDir = resolvedConfig.envDir || process.cwd()
97-
const appUrl = loadEnv(resolvedConfig.mode, envDir, 'BASE_URI').BASE_URI ?? 'undefined'
104+
const appUrl = loadEnv(resolvedConfig.mode, envDir, 'BASE_URI').BASE_URI
98105

99106
server.httpServer?.once('listening', () => {
100107
const address = server.httpServer?.address()
@@ -113,7 +120,12 @@ export default function tempest(): Plugin {
113120
setTimeout(() => {
114121
server.config.logger.info(`\n ${colors.magenta(`${colors.bold('TEMPEST')} ${tempestVersion()}`)} ${colors.dim('plugin')} ${colors.bold(`v${pluginVersion()}`)}`)
115122
server.config.logger.info('')
116-
server.config.logger.info(` ${colors.green('➜')} ${colors.bold('URL')}: ${colors.cyan(appUrl.replace(/:(\d+)/, (_, port) => `:${colors.bold(port)}`))}`)
123+
124+
if (appUrl) {
125+
server.config.logger.info(` ${colors.green('➜')} ${colors.bold('URL')}: ${colors.cyan(appUrl.replace(/:(\d+)/, (_, port) => `:${colors.bold(port)}`))}`)
126+
} else {
127+
server.config.logger.info(` ${colors.magenta('➜')} ${colors.yellow(`No ${colors.bold('BASE_URI')} specified in ${colors.bold('.env')}`)}.`)
128+
}
117129

118130
if (typeof resolvedConfig.server.https === 'object' && typeof resolvedConfig.server.https.key === 'string') {
119131
if (resolvedConfig.server.https.key.startsWith(herdMacConfigPath()) || resolvedConfig.server.https.key.startsWith(herdWindowsConfigPath())) {
@@ -310,7 +322,8 @@ function resolveDevelopmentEnvironmentServerConfig(): {
310322
? 'Ensure you have secured the site via the Herd UI.'
311323
: `Ensure you have secured the site by running \`valet secure ${host}\`.`
312324

313-
throw new TypeError(`Unable to find certificate files for your host [${host}] in the [${configPath}/Certificates] directory. ${tip}`)
325+
console.warn(`Unable to find certificate files for your host [${host}] in the [${configPath}/Certificates] directory. ${tip}`)
326+
return
314327
}
315328

316329
return {

0 commit comments

Comments
 (0)