1
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-11 15:43:32 +08:00
parent f19e482c8f
commit 0981d6ee1b
78 changed files with 1102 additions and 8510 deletions

View File

@@ -131,14 +131,39 @@ function resolveDefaultProjectRoot() {
: cwd;
}
function readMergedEnv(projectRoot: string, processEnv: NodeJS.ProcessEnv) {
function readMergedEnv(
exampleEnv: Record<string, string>,
localEnv: Record<string, string>,
processEnv: NodeJS.ProcessEnv,
) {
return {
...readEnvFile(path.join(projectRoot, '.env.example')),
...readEnvFile(path.join(projectRoot, '.env.local')),
...exampleEnv,
...localEnv,
...processEnv,
};
}
function hasOwnEnvKey(
env: Record<string, string | undefined>,
key: string,
) {
return Object.prototype.hasOwnProperty.call(env, key);
}
function readBooleanOverride(
env: Record<string, string | undefined>,
overrideSources: Array<Record<string, string | undefined>>,
key: string,
fallback: boolean,
) {
const hasOverride = overrideSources.some((source) => hasOwnEnvKey(source, key));
if (!hasOverride) {
return fallback;
}
return readBoolean(env, key, fallback);
}
function readString(
env: Record<string, string | undefined>,
key: string,
@@ -199,33 +224,51 @@ function readBoolean(
export function loadConfig(options: LoadConfigOptions = {}): AppConfig {
const projectRoot = options.projectRoot ?? resolveDefaultProjectRoot();
const env = readMergedEnv(projectRoot, options.env ?? process.env);
const exampleEnv = readEnvFile(path.join(projectRoot, '.env.example'));
const localEnv = readEnvFile(path.join(projectRoot, '.env.local'));
const processEnv = options.env ?? process.env;
const env = readMergedEnv(exampleEnv, localEnv, processEnv);
const logsDir = path.join(projectRoot, 'server-node', 'logs');
const dataDir = path.join(projectRoot, 'server-node', 'data');
const defaultEditorApiEnabled = readString(env, 'NODE_ENV', 'development') !== 'production';
const nodeEnv = readString(env, 'NODE_ENV', 'development');
const defaultEditorApiEnabled = nodeEnv !== 'production';
const editorApiEnabled = readBoolean(
env,
'EDITOR_API_ENABLED',
defaultEditorApiEnabled,
);
const smsProvider = readString(
const smsProviderFromEnv = readString(
env,
'SMS_AUTH_PROVIDER',
readString(env, 'NODE_ENV', 'development') === 'test' ? 'mock' : 'aliyun',
nodeEnv === 'test' ? 'mock' : 'aliyun',
) as AppConfig['smsAuth']['provider'];
const smsAccessKeyId = readString(env, 'ALIYUN_SMS_ACCESS_KEY_ID', '');
const smsAccessKeySecret = readString(env, 'ALIYUN_SMS_ACCESS_KEY_SECRET', '');
const smsProvider = smsProviderFromEnv;
const defaultSmsEnabled =
smsProvider === 'mock' || Boolean(smsAccessKeyId && smsAccessKeySecret);
smsProvider === 'mock' ||
Boolean(smsAccessKeyId && smsAccessKeySecret);
const smsEnabled = readBooleanOverride(
env,
[localEnv, processEnv],
'SMS_AUTH_ENABLED',
defaultSmsEnabled,
);
const wechatProvider = readString(
env,
'WECHAT_AUTH_PROVIDER',
readString(env, 'NODE_ENV', 'development') === 'test' ? 'mock' : 'wechat',
nodeEnv === 'test' ? 'mock' : 'wechat',
) as AppConfig['wechatAuth']['provider'];
const wechatAppId = readString(env, 'WECHAT_APP_ID', '');
const wechatAppSecret = readString(env, 'WECHAT_APP_SECRET', '');
const defaultWechatEnabled =
wechatProvider === 'mock' || Boolean(wechatAppId && wechatAppSecret);
const wechatEnabled = readBooleanOverride(
env,
[localEnv, processEnv],
'WECHAT_AUTH_ENABLED',
defaultWechatEnabled,
);
const refreshSameSite = readString(
env,
'AUTH_REFRESH_COOKIE_SAME_SITE',
@@ -233,7 +276,7 @@ export function loadConfig(options: LoadConfigOptions = {}): AppConfig {
);
return {
nodeEnv: readString(env, 'NODE_ENV', 'development'),
nodeEnv,
projectRoot,
publicDir: path.join(projectRoot, 'public'),
logsDir,
@@ -295,7 +338,7 @@ export function loadConfig(options: LoadConfigOptions = {}): AppConfig {
),
},
smsAuth: {
enabled: readBoolean(env, 'SMS_AUTH_ENABLED', defaultSmsEnabled),
enabled: smsEnabled,
provider: smsProvider,
endpoint: readString(
env,
@@ -410,7 +453,7 @@ export function loadConfig(options: LoadConfigOptions = {}): AppConfig {
),
},
wechatAuth: {
enabled: readBoolean(env, 'WECHAT_AUTH_ENABLED', defaultWechatEnabled),
enabled: wechatEnabled,
provider: wechatProvider,
appId: wechatAppId,
appSecret: wechatAppSecret,