Skip to content

Commit 6720e16

Browse files
committed
feat: support for custom config file path
close #22
1 parent a6ae092 commit 6720e16

File tree

5 files changed

+132
-49
lines changed

5 files changed

+132
-49
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,22 @@ export default defineConfig({
191191
})
192192
```
193193

194+
### Custom config file path
195+
196+
By default, the plugin is looking for a file named `env.ts` at the root of your project. If you want to use a different file, you can specify the path to your file in the plugin options.
197+
198+
```ts
199+
// vite.config.ts
200+
import { defineConfig } from 'vite'
201+
import { ValidateEnv } from "@julr/vite-plugin-validate-env";
202+
203+
export default defineConfig({
204+
plugins: [ValidateEnv({ envFile: 'config/env' })],
205+
})
206+
```
207+
208+
This will look for a file named `env.ts` in the `config` folder at the root of your project. Make sure to not include the file extension in the path as the plugin will automatically search for `.js`, `.ts` and other valid file extensions.
209+
194210
## Transforming variables
195211
In addition to the validation of your variables, there is also a parsing that is done. This means that you can modify the value of an environment variable before it is injected.
196212

src/index.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,28 @@ import type { FullPluginOptions, PluginOptions, Schema } from './types.js'
1111
/**
1212
* Load schema defined in `env.ts` file using unconfig
1313
*/
14-
async function loadConfig(rootDir: string) {
14+
async function loadOptions(rootDir: string, inlineConfig?: PluginOptions) {
15+
let source = 'env'
16+
17+
/**
18+
* If configFile is defined in the inlineConfig, use it as the source
19+
*/
20+
if (inlineConfig && 'configFile' in inlineConfig && inlineConfig.configFile) {
21+
source = inlineConfig.configFile
22+
}
23+
1524
const loader = createLoader<PluginOptions>({
16-
sources: [{ files: 'env', extensions: ['ts', 'cts', 'mts', 'js', 'cjs', 'mjs'] }],
25+
sources: [{ files: source, extensions: ['ts', 'cts', 'mts', 'js', 'cjs', 'mjs'] }],
1726
cwd: rootDir,
27+
defaults: inlineConfig,
1828
})
1929

2030
const result = await loader.load()
21-
return result.config
31+
const config = result.config
32+
33+
if (!config) throw new Error('Missing configuration for vite-plugin-validate-env')
34+
35+
return config
2236
}
2337

2438
/**
@@ -61,7 +75,7 @@ async function validateEnv(
6175
ui: UI,
6276
userConfig: UserConfig,
6377
envConfig: ConfigEnv,
64-
options?: PluginOptions,
78+
inlineOptions?: PluginOptions,
6579
) {
6680
const rootDir = userConfig.root || cwd()
6781

@@ -75,15 +89,7 @@ async function validateEnv(
7589

7690
const env = loadEnv(envConfig.mode, envDir, userConfig.envPrefix)
7791

78-
const isInlineConfig = options !== undefined
79-
if (!isInlineConfig) {
80-
options = await loadConfig(rootDir)
81-
}
82-
83-
if (!options) {
84-
throw new Error('Missing configuration for vite-plugin-validate-env')
85-
}
86-
92+
const options = await loadOptions(rootDir, inlineOptions)
8793
const variables = await validateAndLog(ui, env, options)
8894

8995
return {

src/types.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ export type RecordViteKeys<T> = Record<`${string}_${string}`, T>
1212
*/
1313
export type PluginOptions = Schema | FullPluginOptions
1414

15-
export type FullPluginOptions =
16-
| { validator: 'builtin'; schema: PoppinsSchema; debug?: boolean }
17-
| { validator: 'zod'; schema: ZodSchema; debug?: boolean }
15+
export type FullPluginOptions = (
16+
| { validator: 'builtin'; schema: PoppinsSchema }
17+
| { validator: 'zod'; schema: ZodSchema }
18+
) & { debug?: boolean; configFile?: string }
1819

1920
/**
2021
* Contract for schema definition for poppins validator

tests/common.spec.ts

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -81,39 +81,6 @@ test.group('vite-plugin-validate-env', () => {
8181
assert.deepEqual(define['import.meta.env.VITE_URL_TRAILING'], '"test.com/"')
8282
})
8383

84-
test('Dedicated config file', async ({ assert, fs }) => {
85-
assert.plan(1)
86-
87-
const plugin = ValidateEnv()
88-
89-
await fs.create(`.env.development`, `VITE_MY_VAR=true`)
90-
await fs.create(
91-
`env.ts`,
92-
`export default {
93-
VITE_TEST: () => {
94-
throw new Error('Error validating')
95-
}
96-
}`,
97-
)
98-
99-
try {
100-
// @ts-ignore
101-
await plugin.config({ root: fs.basePath }, viteEnvConfig)
102-
} catch (error: any) {
103-
assert.include(error.message, 'Error validating')
104-
}
105-
})
106-
107-
test('Should fail if no schema is found', async ({ assert, fs }) => {
108-
const plugin = ValidateEnv()
109-
110-
await fs.create(`.env.development`, `VITE_MY_VAR=true`)
111-
112-
// @ts-expect-error - `config` is the handler
113-
const fn = plugin.config!.bind(plugin, { root: fs.basePath }, viteEnvConfig)
114-
await assert.rejects(fn, 'Missing configuration for vite-plugin-validate-env')
115-
})
116-
11784
test('Should pick up var with custom prefix', async ({ assert, fs }) => {
11885
assert.plan(1)
11986

tests/config.spec.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { test } from '@japa/runner'
2+
3+
import type { UI } from '../src/ui.js'
4+
import { ValidateEnv as CoreTypedValidateEnv, Schema } from '../src/index.js'
5+
6+
const viteEnvConfig = { mode: 'development', command: 'serve' } as const
7+
8+
const ValidateEnv = CoreTypedValidateEnv as (
9+
...args: Parameters<typeof CoreTypedValidateEnv>
10+
) => ReturnType<typeof CoreTypedValidateEnv> & { ui: UI }
11+
12+
test.group('Config loading', () => {
13+
test('Dedicated config file', async ({ fs }) => {
14+
const plugin = ValidateEnv()
15+
16+
await fs.create(`.env.development`, `VITE_MY_VAR=true`)
17+
await fs.create(
18+
`env.ts`,
19+
`export default {
20+
VITE_TEST: () => {
21+
throw new Error('Error validating')
22+
}
23+
}`,
24+
)
25+
26+
// @ts-ignore
27+
await plugin.config({ root: fs.basePath }, viteEnvConfig)
28+
}).throws(/Error validating/)
29+
30+
test('dedicated config file custom path', async ({ fs }) => {
31+
const plugin = ValidateEnv({ configFile: 'import_env' })
32+
33+
await fs.create(`.env.development`, `VITE_MY_VAR=true`)
34+
await fs.create(
35+
`import_env.ts`,
36+
`export default {
37+
VITE_TEST: () => {
38+
throw new Error('Error validating')
39+
}
40+
}`,
41+
)
42+
43+
// @ts-ignore
44+
await plugin.config({ root: fs.basePath }, viteEnvConfig)
45+
}).throws(/Error validating/)
46+
47+
test('Should fail if no schema is found', async ({ assert, fs }) => {
48+
const plugin = ValidateEnv()
49+
50+
await fs.create(`.env.development`, `VITE_MY_VAR=true`)
51+
52+
// @ts-expect-error - `config` is the handler
53+
const fn = plugin.config!.bind(plugin, { root: fs.basePath }, viteEnvConfig)
54+
await assert.rejects(fn, 'Missing configuration for vite-plugin-validate-env')
55+
})
56+
57+
test('if inline config is also specified, it should be merged with the dedicated config file', async ({
58+
fs,
59+
assert,
60+
}) => {
61+
const plugin = ValidateEnv({ VITE_VAR: Schema.number() })
62+
63+
await fs.create(`.env.development`, `VITE_TEST=true\nVITE_VAR=34`)
64+
await fs.create(
65+
`env.ts`,
66+
`export default {
67+
VITE_TEST: () => 42
68+
}`,
69+
)
70+
71+
// @ts-ignore
72+
const { define } = await plugin.config({ root: fs.basePath }, viteEnvConfig)
73+
74+
assert.deepEqual(define['import.meta.env.VITE_VAR'], '34')
75+
assert.deepEqual(define['import.meta.env.VITE_TEST'], '42')
76+
})
77+
78+
test('dedicated config file in another folder', async ({ fs }) => {
79+
const plugin = ValidateEnv({ configFile: 'config/env' })
80+
81+
await fs.create(
82+
`config/env.ts`,
83+
`export default {
84+
VITE_TEST: (key, value) => {
85+
throw new Error('Error validating')
86+
}
87+
}`,
88+
)
89+
90+
// @ts-ignore
91+
await plugin.config({ root: fs.basePath }, viteEnvConfig)
92+
}).throws(/Error validating/)
93+
})

0 commit comments

Comments
 (0)