@@ -2,47 +2,53 @@ import { existsSync, readFileSync } from 'node:fs'
22import { join , isAbsolute , relative } from 'node:path'
33import { parse as dotEnvParse } from 'dotenv'
44import { expand as dotEnvExpand } from 'dotenv-expand'
5+ import { merge } from 'webpack-merge'
56
67import { encodeForDiff } from './encode-for-diff.js'
78
89export const ENV_VAR_PREFIX = 'QCLI_'
910export const validEnvKeyRE = / ^ [ a - z A - Z _ $ ] [ a - z A - Z 0 - 9 _ $ ] + /
1011
11- const readAppFileEnvCacheKey = 'readAppFileEnv'
12-
1312/**
1413 * Get the raw env definitions from the host project env files.
15- * Used for the Quasar config file.
1614 */
17- export function readQuasarConfFileEnv ( ctx ) {
18- return ctx . cacheProxy . getRuntime ( 'readQuasarConfFileEnv' , ( ) => {
19- const { rawFileEnv, usedEnvFiles } = getFileEnvResult ( {
20- appDir : ctx . appPaths . appDir ,
21- fileList : [ '.env' , '.env.local' ] ,
22- folderList : [ ctx . appPaths . appDir ]
23- } )
24-
15+ export function readEnvFiles ( ctx , env , isQuasarConfFile = false ) {
16+ if ( ! env ) {
2517 return {
26- envDefineList : parseEnv ( rawFileEnv , validEnvKeyRE ) ,
27- envBanner :
28- usedEnvFiles . length > 0
29- ? `(env files: ${ usedEnvFiles . join ( ' | ' ) } )`
30- : '(no env files used for it)'
18+ envDefineList : { } ,
19+ envBanner : ''
3120 }
32- } )
33- }
21+ }
3422
35- /**
36- * Get the raw env definitions from the host project env files.
37- * Used for the App content.
38- */
39- export function readAppFileEnv ( ctx , env , envPrefixRE ) {
23+ const cacheKey = isQuasarConfFile ? 'readQuasarConfEnvFiles' : 'readEnvFiles'
4024 const configHash = encodeForDiff ( env )
41- const cache = ctx . cacheProxy . getRuntime ( readAppFileEnvCacheKey , ( ) => ( { } ) )
25+ const cache = ctx . cacheProxy . getRuntime ( cacheKey , ( ) => ( { } ) )
4226
4327 if ( cache . configHash !== configHash ) {
44- const { modeName : quasarMode , dev } = ctx
45- const buildType = dev === true ? 'dev' : 'prod'
28+ const localEnv = merge (
29+ {
30+ prefix : ENV_VAR_PREFIX ,
31+ folder : ctx . appPaths . appDir ,
32+ files : [ ]
33+ // filter: (key, value) => true
34+ } ,
35+ env
36+ )
37+
38+ // we enforce a prefix (other than Quasar's own QUASAR_) for security reasons
39+ // and we also filter it if it's an array, to make sure that it only contains valid keys
40+
41+ let { prefix } = localEnv
42+ if ( ! prefix || prefix === 'QUASAR_' ) {
43+ prefix = ENV_VAR_PREFIX
44+ } else if ( Array . isArray ( prefix ) ) {
45+ prefix = prefix . filter ( p => validEnvKeyRE . test ( p ) && p !== 'QUASAR_' )
46+ if ( prefix . length === 0 ) prefix = ENV_VAR_PREFIX
47+ }
48+
49+ const envPrefix = Array . isArray ( prefix )
50+ ? new RegExp ( `^(${ prefix . join ( '|' ) } )[a-zA-Z_$][a-zA-Z0-9_$]+` )
51+ : new RegExp ( `^${ prefix } [a-zA-Z_$][a-zA-Z0-9_$]+` )
4652
4753 const fileList = [
4854 // .env
@@ -51,37 +57,48 @@ export function readAppFileEnv(ctx, env, envPrefixRE) {
5157
5258 // .env.local
5359 // loaded in all cases, ignored by git
54- '.env.local' ,
55-
56- // .env.[dev|prod]
57- // loaded for dev or prod only
58- `.env.${ buildType } ` ,
59-
60- // .env.local.[dev|prod]
61- // loaded for dev or prod only, ignored by git
62- `.env.local.${ buildType } ` ,
63-
64- // .env.[quasarMode]
65- // loaded for specific Quasar CLI mode only
66- `.env.${ quasarMode } ` ,
67-
68- // .env.local.[quasarMode]
69- // loaded for specific Quasar CLI mode only, ignored by git
70- `.env.local.${ quasarMode } ` ,
71-
72- // .env.[dev|prod].[quasarMode]
73- // loaded for specific Quasar CLI mode and dev|prod only
74- `.env.${ buildType } .${ quasarMode } ` ,
60+ '.env.local'
61+ ]
7562
76- // .env.local.[dev|prod].[quasarMode]
77- // loaded for specific Quasar CLI mode and dev|prod only, ignored by git
78- `.env.local.${ buildType } .${ quasarMode } ` ,
63+ // if it's not for the Quasar config file,
64+ // we also load mode and build-type specific env files
65+ if ( isQuasarConfFile === false ) {
66+ const { modeName : quasarMode , dev } = ctx
67+ const buildType = dev === true ? 'dev' : 'prod'
68+
69+ fileList . push (
70+ // .env.[dev|prod]
71+ // loaded for dev or prod only
72+ `.env.${ buildType } ` ,
73+
74+ // .env.local.[dev|prod]
75+ // loaded for dev or prod only, ignored by git
76+ `.env.local.${ buildType } ` ,
77+
78+ // .env.[quasarMode]
79+ // loaded for specific Quasar CLI mode only
80+ `.env.${ quasarMode } ` ,
81+
82+ // .env.local.[quasarMode]
83+ // loaded for specific Quasar CLI mode only, ignored by git
84+ `.env.local.${ quasarMode } ` ,
85+
86+ // .env.[dev|prod].[quasarMode]
87+ // loaded for specific Quasar CLI mode and dev|prod only
88+ `.env.${ buildType } .${ quasarMode } ` ,
89+
90+ // .env.local.[dev|prod].[quasarMode]
91+ // loaded for specific Quasar CLI mode and dev|prod only, ignored by git
92+ `.env.local.${ buildType } .${ quasarMode } `
93+ )
94+ }
7995
96+ if ( Array . isArray ( localEnv . files ) ) {
8097 // additional user-defined env files
81- ... ( env . files || [ ] )
82- ]
98+ fileList . push ( ... localEnv . files )
99+ }
83100
84- const folder = env . folder || ctx . appPaths . appDir
101+ const folder = localEnv . folder || ctx . appPaths . appDir
85102 const folderList = Array . isArray ( folder ) ? folder : [ folder ]
86103
87104 const { rawFileEnv, usedEnvFiles } = getFileEnvResult ( {
@@ -90,19 +107,24 @@ export function readAppFileEnv(ctx, env, envPrefixRE) {
90107 folderList
91108 } )
92109
110+ const prefixLabel = Array . isArray ( prefix ) ? prefix . join ( ' | ' ) : prefix
93111 const result = {
94- envDefineList : parseEnv ( rawFileEnv , envPrefixRE ) ,
112+ envDefineList : parseEnv ( rawFileEnv , envPrefix ) ,
95113 envBanner :
96- usedEnvFiles . length !== 0
97- ? `App .env files: ${ usedEnvFiles . join ( ' | ' ) } `
98- : null
114+ isQuasarConfFile === true
115+ ? usedEnvFiles . length > 0
116+ ? ` (env prefix: ${ prefixLabel } ; env files: ${ usedEnvFiles . join ( ' | ' ) } )`
117+ : ` (no env files used for it)`
118+ : usedEnvFiles . length !== 0
119+ ? `App .env prefix ${ prefixLabel } & .env files: ${ usedEnvFiles . join ( ' | ' ) } `
120+ : null
99121 }
100122
101- if ( typeof env . filter === 'function' ) {
102- result . envDefineList = env . filter ( result . envDefineList , 'client' ) || { }
123+ if ( typeof localEnv . filter === 'function' ) {
124+ result . envDefineList = localEnv . filter ( result . envDefineList ) || { }
103125 }
104126
105- ctx . cacheProxy . setRuntime ( readAppFileEnvCacheKey , {
127+ ctx . cacheProxy . setRuntime ( cacheKey , {
106128 configHash,
107129 result
108130 } )
0 commit comments