Skip to content

Commit f719db8

Browse files
committed
feat(app-vite): support for env options on quasar.config file itself
1 parent f3d0264 commit f719db8

File tree

6 files changed

+99
-108
lines changed

6 files changed

+99
-108
lines changed

app-vite/lib/modes/electron/electron-builder.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export class QuasarModeBuilder extends AppBuilder {
5656
delete pkg.devDependencies
5757
delete pkg.browserslist
5858
delete pkg.scripts
59+
delete pkg.quasarCli
5960

6061
pkg.main = './electron-main.js'
6162

app-vite/lib/modes/ssr/ssr-builder.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ export class QuasarModeBuilder extends AppBuilder {
118118
express: cliPkg.dependencies.express
119119
}),
120120
engines: localAppPkg.engines,
121-
browserslist: localAppPkg.browserslist,
122-
quasar: { ssr: true }
121+
browserslist: localAppPkg.browserslist
123122
}
124123

125124
if (this.quasarConf.ssr.manualStoreSerialization !== true) {

app-vite/lib/quasar-config-file.js

Lines changed: 13 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@ import {
2121
import { findClosestOpenPort, localHostList } from './utils/net.js'
2222
import { isMinimalTerminal } from './utils/is-minimal-terminal.js'
2323
import { BASELINE_WIDELY_AVAILABLE_TARGET_STRING } from './utils/build-targets.js'
24-
import {
25-
readQuasarConfFileEnv,
26-
readAppFileEnv,
27-
ENV_VAR_PREFIX,
28-
validEnvKeyRE
29-
} from './utils/env.js'
24+
import { readEnvFiles } from './utils/env.js'
3025

3126
const urlRegex = /^http(s)?:\/\//i
3227
const defaultPortMapping = {
@@ -230,14 +225,21 @@ export class QuasarConfigFile {
230225
// if filename syntax gets changed, then also update the "clean" cmd
231226
this.#tempFile = `${appPaths.quasarConfigFilename}.temporary.compiled.${Date.now()}.js`
232227

233-
const { envDefineList, envBanner } = readQuasarConfFileEnv(this.#ctx)
228+
const { quasarCli } = JSON.parse(
229+
fse.readFileSync(appPaths.resolve.app('package.json'), 'utf-8')
230+
)
231+
const { envDefineList, envBanner } = readEnvFiles(
232+
this.#ctx,
233+
quasarCli?.quasarConfEnv,
234+
true /* isQuasarConfFile */
235+
)
234236
this.#rolldownConfigDefines = {
235237
...envDefineList,
236238
...quasarRolldownInjectReplacementsDefine
237239
}
238240

239241
log(
240-
`Using ${basename(appPaths.quasarConfigFilename)} in "${appPaths.quasarConfigInputFormat}" format ${envBanner}`
242+
`Using ${basename(appPaths.quasarConfigFilename)} in "${appPaths.quasarConfigInputFormat}" format${envBanner}`
241243
)
242244
}
243245

@@ -826,38 +828,10 @@ export class QuasarConfigFile {
826828
cfg.build
827829
)
828830

829-
if (cfg.build.env !== false) {
830-
cfg.build.env = merge(
831-
{
832-
prefix: ENV_VAR_PREFIX,
833-
folder: appPaths.appDir,
834-
files: []
835-
// filter: (key, value) => true
836-
},
837-
cfg.build.env
838-
)
839-
840-
// we enforce a prefix (other than Quasar's own QUASAR_) for security reasons
841-
// and we also filter it if it's an array, to make sure that it only contains valid keys
842-
843-
let { prefix } = cfg.build.env
844-
if (!prefix || prefix === 'QUASAR_') {
845-
prefix = ENV_VAR_PREFIX
846-
} else if (Array.isArray(prefix)) {
847-
prefix = prefix.filter(p => validEnvKeyRE.test(p) && p !== 'QUASAR_')
848-
if (prefix.length === 0) prefix = ENV_VAR_PREFIX
849-
}
850-
851-
cfg.build.env.prefix = prefix
852-
const envPrefix = Array.isArray(prefix)
853-
? new RegExp(`^(${prefix.join('|')})[a-zA-Z_$][a-zA-Z0-9_$]+`)
854-
: new RegExp(`^${prefix}[a-zA-Z_$][a-zA-Z0-9_$]+`)
855-
856-
// get the env variables from host project env files
857-
const { envDefineList, envBanner } = readAppFileEnv(
831+
if (cfg.build.env) {
832+
const { envDefineList, envBanner } = readEnvFiles(
858833
this.#ctx,
859-
cfg.build.env,
860-
envPrefix
834+
cfg.build.env
861835
)
862836

863837
cfg.metaConf.envDefineList = envDefineList

app-vite/lib/utils/env.js

Lines changed: 82 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,53 @@ import { existsSync, readFileSync } from 'node:fs'
22
import { join, isAbsolute, relative } from 'node:path'
33
import { parse as dotEnvParse } from 'dotenv'
44
import { expand as dotEnvExpand } from 'dotenv-expand'
5+
import { merge } from 'webpack-merge'
56

67
import { encodeForDiff } from './encode-for-diff.js'
78

89
export const ENV_VAR_PREFIX = 'QCLI_'
910
export const validEnvKeyRE = /^[a-zA-Z_$][a-zA-Z0-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
})

app-vite/lib/utils/get-fixed-deps.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ const urlRangePattern = /^[a-zA-Z]/
1313
* ```
1414
*/
1515
export function getFixedDeps(deps, rootDir) {
16-
if (!deps) {
17-
return {}
18-
}
16+
if (!deps) return {}
1917

2018
const appDeps = { ...deps }
2119

app-vite/types/configuration/build.d.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,7 @@ interface QuasarEnvConfig {
137137
* through the env files. This does not affects props
138138
* assigned directly to the quasar.config > build > define prop.
139139
*/
140-
filter?: (
141-
env: Record<string, string>,
142-
target: "client" | "server"
143-
) => Record<string, string>;
140+
filter?: (env: Record<string, string>) => Record<string, string>;
144141
}
145142

146143
interface QuasarStaticBuildConfiguration {

0 commit comments

Comments
 (0)