sa2kit 3.2.2 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-5H2FICSO.js +418 -0
- package/dist/chunk-5H2FICSO.js.map +1 -0
- package/dist/chunk-LGVPFYPR.mjs +401 -0
- package/dist/chunk-LGVPFYPR.mjs.map +1 -0
- package/dist/common/auth/server/index.d.mts +9 -36
- package/dist/common/auth/server/index.d.ts +9 -36
- package/dist/common/auth/server/index.js +26 -56
- package/dist/common/auth/server/index.js.map +1 -1
- package/dist/common/auth/server/index.mjs +17 -53
- package/dist/common/auth/server/index.mjs.map +1 -1
- package/dist/common/config/bootstrap/index.d.mts +124 -0
- package/dist/common/config/bootstrap/index.d.ts +124 -0
- package/dist/common/config/bootstrap/index.js +65 -0
- package/dist/common/config/bootstrap/index.js.map +1 -0
- package/dist/common/config/bootstrap/index.mjs +4 -0
- package/dist/common/config/bootstrap/index.mjs.map +1 -0
- package/dist/common/config/server/index.d.mts +3 -0
- package/dist/common/config/server/index.d.ts +3 -0
- package/dist/common/config/server/index.js +53 -0
- package/dist/common/config/server/index.js.map +1 -1
- package/dist/common/config/server/index.mjs +1 -0
- package/dist/common/config/server/index.mjs.map +1 -1
- package/dist/types-272dN1B6.d.mts +36 -0
- package/dist/types-272dN1B6.d.ts +36 -0
- package/package.json +8 -1
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var zod = require('zod');
|
|
4
|
+
var fs = require('fs');
|
|
5
|
+
var path = require('path');
|
|
6
|
+
var yaml = require('yaml');
|
|
7
|
+
|
|
8
|
+
// src/common/config/bootstrap/schema.ts
|
|
9
|
+
var aliyunSmsSchema = zod.z.object({
|
|
10
|
+
accessKeyId: zod.z.string().optional(),
|
|
11
|
+
accessKeySecret: zod.z.string().optional(),
|
|
12
|
+
signName: zod.z.string().optional(),
|
|
13
|
+
templateCode: zod.z.string().optional(),
|
|
14
|
+
countryCode: zod.z.string().optional(),
|
|
15
|
+
codeValidMinutes: zod.z.coerce.number().int().positive().optional(),
|
|
16
|
+
endpoint: zod.z.string().url().optional()
|
|
17
|
+
});
|
|
18
|
+
var authSchema = zod.z.object({
|
|
19
|
+
secret: zod.z.string().min(32, "auth.secret \u81F3\u5C11 32 \u5B57\u7B26"),
|
|
20
|
+
url: zod.z.string().url("auth.url \u987B\u4E3A\u5408\u6CD5 URL"),
|
|
21
|
+
publicUrl: zod.z.string().url("auth.publicUrl \u987B\u4E3A\u5408\u6CD5 URL"),
|
|
22
|
+
trustedOrigins: zod.z.array(zod.z.string().url()).optional(),
|
|
23
|
+
logOtpInDev: zod.z.boolean().optional(),
|
|
24
|
+
sms: zod.z.object({
|
|
25
|
+
provider: zod.z.enum(["console", "aliyun-pnvs", "none"]).optional(),
|
|
26
|
+
aliyun: aliyunSmsSchema.optional()
|
|
27
|
+
}).optional(),
|
|
28
|
+
email: zod.z.object({
|
|
29
|
+
provider: zod.z.string().optional()
|
|
30
|
+
}).optional()
|
|
31
|
+
});
|
|
32
|
+
var databaseSchema = zod.z.object({
|
|
33
|
+
url: zod.z.string().min(1, "database.url \u4E0D\u80FD\u4E3A\u7A7A"),
|
|
34
|
+
poolSize: zod.z.coerce.number().int().positive().max(100).optional(),
|
|
35
|
+
timeout: zod.z.coerce.number().int().positive().max(3e4).optional(),
|
|
36
|
+
sslMode: zod.z.enum(["disable", "prefer", "require"]).optional()
|
|
37
|
+
});
|
|
38
|
+
var aliyunOssSchema = zod.z.object({
|
|
39
|
+
enabled: zod.z.boolean().optional(),
|
|
40
|
+
region: zod.z.string().optional(),
|
|
41
|
+
bucket: zod.z.string().optional(),
|
|
42
|
+
accessKeyId: zod.z.string().optional(),
|
|
43
|
+
accessKeySecret: zod.z.string().optional(),
|
|
44
|
+
customDomain: zod.z.string().optional(),
|
|
45
|
+
secure: zod.z.boolean().optional(),
|
|
46
|
+
internal: zod.z.boolean().optional()
|
|
47
|
+
});
|
|
48
|
+
var aliyunCdnSchema = zod.z.object({
|
|
49
|
+
enabled: zod.z.boolean().optional(),
|
|
50
|
+
domain: zod.z.string().optional(),
|
|
51
|
+
accessKeyId: zod.z.string().optional(),
|
|
52
|
+
accessKeySecret: zod.z.string().optional()
|
|
53
|
+
});
|
|
54
|
+
var appConfigSchema = zod.z.object({
|
|
55
|
+
app: zod.z.object({
|
|
56
|
+
name: zod.z.string().min(1),
|
|
57
|
+
env: zod.z.enum(["development", "production", "test"]).optional()
|
|
58
|
+
}),
|
|
59
|
+
database: databaseSchema,
|
|
60
|
+
auth: authSchema,
|
|
61
|
+
storage: zod.z.object({
|
|
62
|
+
aliyunOss: aliyunOssSchema.optional(),
|
|
63
|
+
aliyunCdn: aliyunCdnSchema.optional()
|
|
64
|
+
}).optional()
|
|
65
|
+
});
|
|
66
|
+
var FILE_BY_ENV = {
|
|
67
|
+
local: "config/app.config.local.yaml",
|
|
68
|
+
production: "config/app.config.production.yaml",
|
|
69
|
+
test: "config/app.config.test.yaml"
|
|
70
|
+
};
|
|
71
|
+
var SOPS_ENCRYPTED_PATH = "config/production.enc.yaml";
|
|
72
|
+
function resolveAppConfigEnv() {
|
|
73
|
+
const fromEnv = process.env.APP_CONFIG_ENV?.trim();
|
|
74
|
+
if (fromEnv === "local" || fromEnv === "production" || fromEnv === "test") {
|
|
75
|
+
return fromEnv;
|
|
76
|
+
}
|
|
77
|
+
if (process.env.NODE_ENV === "production") return "production";
|
|
78
|
+
if (process.env.NODE_ENV === "test") return "test";
|
|
79
|
+
return "local";
|
|
80
|
+
}
|
|
81
|
+
function isNextBuildPhaseWithoutRuntimeEnv() {
|
|
82
|
+
return process.env.NEXT_PHASE === "phase-production-build" || process.env.NEXT_PHASE === "phase-export";
|
|
83
|
+
}
|
|
84
|
+
function resolveAppConfigPath(options = {}) {
|
|
85
|
+
const cwd = options.cwd ?? process.cwd();
|
|
86
|
+
if (options.explicitPath) {
|
|
87
|
+
return path.resolve(cwd, options.explicitPath);
|
|
88
|
+
}
|
|
89
|
+
const fromEnv = process.env.APP_CONFIG_PATH?.trim();
|
|
90
|
+
if (fromEnv) {
|
|
91
|
+
return path.resolve(cwd, fromEnv);
|
|
92
|
+
}
|
|
93
|
+
const envName = options.env ?? resolveAppConfigEnv();
|
|
94
|
+
const candidate = path.resolve(cwd, FILE_BY_ENV[envName]);
|
|
95
|
+
if (fs.existsSync(candidate)) {
|
|
96
|
+
return candidate;
|
|
97
|
+
}
|
|
98
|
+
const examplePath = path.resolve(cwd, "config/app.config.example.yaml");
|
|
99
|
+
if (isNextBuildPhaseWithoutRuntimeEnv() && fs.existsSync(examplePath)) {
|
|
100
|
+
return examplePath;
|
|
101
|
+
}
|
|
102
|
+
if (envName === "local") {
|
|
103
|
+
const productionFallback = path.resolve(cwd, FILE_BY_ENV.production);
|
|
104
|
+
if (fs.existsSync(productionFallback)) {
|
|
105
|
+
return productionFallback;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return candidate;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/common/config/bootstrap/apply-to-process-env.ts
|
|
112
|
+
function applyAppConfigToProcessEnv(config) {
|
|
113
|
+
const set = (key, value) => {
|
|
114
|
+
if (!value || process.env[key] && process.env[key].length > 0) return;
|
|
115
|
+
process.env[key] = value;
|
|
116
|
+
};
|
|
117
|
+
set("DATABASE_URL", config.database.url);
|
|
118
|
+
if (config.database.poolSize !== void 0) {
|
|
119
|
+
set("DATABASE_POOL_SIZE", String(config.database.poolSize));
|
|
120
|
+
}
|
|
121
|
+
if (config.database.timeout !== void 0) {
|
|
122
|
+
set("DATABASE_TIMEOUT", String(config.database.timeout));
|
|
123
|
+
}
|
|
124
|
+
if (config.database.sslMode) {
|
|
125
|
+
set("DATABASE_SSL_MODE", config.database.sslMode);
|
|
126
|
+
}
|
|
127
|
+
set("BETTER_AUTH_SECRET", config.auth.secret);
|
|
128
|
+
set("BETTER_AUTH_URL", config.auth.url);
|
|
129
|
+
set("NEXT_PUBLIC_APP_URL", config.auth.publicUrl);
|
|
130
|
+
if (config.auth.trustedOrigins?.length) {
|
|
131
|
+
set("BETTER_AUTH_TRUSTED_ORIGINS", config.auth.trustedOrigins.join(","));
|
|
132
|
+
}
|
|
133
|
+
const smsProvider = config.auth.sms?.provider;
|
|
134
|
+
if (smsProvider) {
|
|
135
|
+
set("SA2KIT_SMS_PROVIDER", smsProvider);
|
|
136
|
+
}
|
|
137
|
+
const aliyunSms = config.auth.sms?.aliyun;
|
|
138
|
+
if (aliyunSms) {
|
|
139
|
+
set("ALIYUN_SMS_ACCESS_KEY_ID", aliyunSms.accessKeyId);
|
|
140
|
+
set("ALIYUN_SMS_ACCESS_KEY_SECRET", aliyunSms.accessKeySecret);
|
|
141
|
+
set("ALIYUN_SMS_SIGN_NAME", aliyunSms.signName);
|
|
142
|
+
set("ALIYUN_SMS_TEMPLATE_CODE", aliyunSms.templateCode);
|
|
143
|
+
set("ALIYUN_SMS_COUNTRY_CODE", aliyunSms.countryCode);
|
|
144
|
+
if (aliyunSms.codeValidMinutes !== void 0) {
|
|
145
|
+
set("ALIYUN_SMS_CODE_VALID_MINUTES", String(aliyunSms.codeValidMinutes));
|
|
146
|
+
}
|
|
147
|
+
set("ALIYUN_SMS_ENDPOINT", aliyunSms.endpoint);
|
|
148
|
+
}
|
|
149
|
+
if (config.auth.email?.provider) {
|
|
150
|
+
set("SA2KIT_EMAIL_PROVIDER", config.auth.email.provider);
|
|
151
|
+
}
|
|
152
|
+
if (config.auth.logOtpInDev !== void 0) {
|
|
153
|
+
set("SA2KIT_AUTH_LOG_OTP", config.auth.logOtpInDev ? "1" : "0");
|
|
154
|
+
}
|
|
155
|
+
const oss = config.storage?.aliyunOss;
|
|
156
|
+
if (oss) {
|
|
157
|
+
if (oss.region) set("ALIYUN_OSS_REGION", oss.region);
|
|
158
|
+
if (oss.bucket) set("ALIYUN_OSS_BUCKET", oss.bucket);
|
|
159
|
+
if (oss.accessKeyId) set("ALIYUN_OSS_ACCESS_KEY_ID", oss.accessKeyId);
|
|
160
|
+
if (oss.accessKeySecret) set("ALIYUN_OSS_ACCESS_KEY_SECRET", oss.accessKeySecret);
|
|
161
|
+
if (oss.customDomain) set("ALIYUN_OSS_CUSTOM_DOMAIN", oss.customDomain);
|
|
162
|
+
if (oss.secure !== void 0) set("ALIYUN_OSS_SECURE", oss.secure ? "true" : "false");
|
|
163
|
+
if (oss.internal !== void 0) set("ALIYUN_OSS_INTERNAL", oss.internal ? "true" : "false");
|
|
164
|
+
}
|
|
165
|
+
const cdn = config.storage?.aliyunCdn;
|
|
166
|
+
if (cdn) {
|
|
167
|
+
if (cdn.domain) set("ALIYUN_CDN_DOMAIN", cdn.domain);
|
|
168
|
+
if (cdn.accessKeyId) set("ALIYUN_CDN_ACCESS_KEY_ID", cdn.accessKeyId);
|
|
169
|
+
if (cdn.accessKeySecret) set("ALIYUN_CDN_ACCESS_KEY_SECRET", cdn.accessKeySecret);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/common/config/bootstrap/doctor.ts
|
|
174
|
+
function isSet(value) {
|
|
175
|
+
return Boolean(value && value.trim().length > 0);
|
|
176
|
+
}
|
|
177
|
+
function diagnoseAppConfig(config) {
|
|
178
|
+
const issues = [];
|
|
179
|
+
const enabledFeatures = ["app", "database", "auth-core"];
|
|
180
|
+
const env = config.app.env ?? process.env.NODE_ENV ?? "development";
|
|
181
|
+
const isProd = env === "production";
|
|
182
|
+
const smsProvider = config.auth.sms?.provider ?? (isProd ? void 0 : "console");
|
|
183
|
+
if (smsProvider === "aliyun-pnvs") {
|
|
184
|
+
const aliyun = config.auth.sms?.aliyun;
|
|
185
|
+
const missing = [
|
|
186
|
+
!isSet(aliyun?.accessKeyId) && "auth.sms.aliyun.accessKeyId",
|
|
187
|
+
!isSet(aliyun?.accessKeySecret) && "auth.sms.aliyun.accessKeySecret",
|
|
188
|
+
!isSet(aliyun?.signName) && "auth.sms.aliyun.signName",
|
|
189
|
+
!isSet(aliyun?.templateCode) && "auth.sms.aliyun.templateCode"
|
|
190
|
+
].filter(Boolean);
|
|
191
|
+
if (missing.length === 0) {
|
|
192
|
+
enabledFeatures.push("auth-sms");
|
|
193
|
+
} else {
|
|
194
|
+
issues.push({
|
|
195
|
+
level: "error",
|
|
196
|
+
featureId: "auth-sms",
|
|
197
|
+
featureName: "\u624B\u673A\u77ED\u4FE1 OTP",
|
|
198
|
+
message: `sms.provider=aliyun-pnvs \u4F46\u7F3A\u5C11\uFF1A${missing.join(", ")}`
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
} else if (smsProvider === "console") {
|
|
202
|
+
enabledFeatures.push("auth-sms");
|
|
203
|
+
if (isProd) {
|
|
204
|
+
issues.push({
|
|
205
|
+
level: "warning",
|
|
206
|
+
featureId: "auth-sms",
|
|
207
|
+
featureName: "\u624B\u673A\u77ED\u4FE1 OTP",
|
|
208
|
+
message: "\u751F\u4EA7\u73AF\u5883\u4F7F\u7528 console SMS\uFF0C\u9A8C\u8BC1\u7801\u4EC5\u8F93\u51FA\u5230\u65E5\u5FD7\u3002",
|
|
209
|
+
hints: ["\u751F\u4EA7\u8BF7\u6539\u4E3A aliyun-pnvs \u5E76\u586B\u5199 auth.sms.aliyun.*"]
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
} else {
|
|
213
|
+
issues.push({
|
|
214
|
+
level: isProd ? "warning" : "info",
|
|
215
|
+
featureId: "auth-sms",
|
|
216
|
+
featureName: "\u624B\u673A\u77ED\u4FE1 OTP",
|
|
217
|
+
message: isProd ? "\u672A\u914D\u7F6E\u77ED\u4FE1 provider\uFF0C\u7528\u6237\u6536\u4E0D\u5230\u9A8C\u8BC1\u7801\u3002" : "\u672A\u914D\u7F6E\u77ED\u4FE1\uFF1B\u5F00\u53D1\u53EF\u8BBE auth.sms.provider: console",
|
|
218
|
+
hints: ["\u5F00\u53D1\uFF1Aauth.sms.provider: console", "\u751F\u4EA7\uFF1Aauth.sms.provider: aliyun-pnvs"]
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
const oss = config.storage?.aliyunOss;
|
|
222
|
+
const ossComplete = oss?.enabled !== false && isSet(oss?.region) && isSet(oss?.bucket) && isSet(oss?.accessKeyId) && isSet(oss?.accessKeySecret);
|
|
223
|
+
if (ossComplete) {
|
|
224
|
+
enabledFeatures.push("storage-oss");
|
|
225
|
+
} else if (oss?.enabled === true) {
|
|
226
|
+
issues.push({
|
|
227
|
+
level: "error",
|
|
228
|
+
featureId: "storage-oss",
|
|
229
|
+
featureName: "\u963F\u91CC\u4E91 OSS",
|
|
230
|
+
message: "storage.aliyunOss.enabled \u4E3A true \u4F46\u914D\u7F6E\u4E0D\u5B8C\u6574\u3002"
|
|
231
|
+
});
|
|
232
|
+
} else {
|
|
233
|
+
issues.push({
|
|
234
|
+
level: "info",
|
|
235
|
+
featureId: "storage-oss",
|
|
236
|
+
featureName: "\u963F\u91CC\u4E91 OSS",
|
|
237
|
+
message: "\u672A\u542F\u7528\u5B8C\u6574 OSS \u914D\u7F6E\uFF0C\u6587\u4EF6\u4E0A\u4F20\u5C06\u56DE\u9000\u672C\u5730\u5B58\u50A8\uFF08\u82E5\u6A21\u5757\u5141\u8BB8\uFF09\u3002"
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
const ok = !issues.some((i) => i.level === "error");
|
|
241
|
+
return { ok, issues, enabledFeatures };
|
|
242
|
+
}
|
|
243
|
+
var loggedOnce = false;
|
|
244
|
+
function logConfigDoctorReport(report, options) {
|
|
245
|
+
if (loggedOnce && !options?.force) return;
|
|
246
|
+
loggedOnce = true;
|
|
247
|
+
const lines = ["[sa2kit/config] \u914D\u7F6E\u68C0\u67E5"];
|
|
248
|
+
for (const issue of report.issues) {
|
|
249
|
+
const prefix = issue.level === "error" ? "\u2717" : issue.level === "warning" ? "\u26A0" : "\u25CB";
|
|
250
|
+
lines.push(`${prefix} ${issue.featureName}: ${issue.message}`);
|
|
251
|
+
for (const hint of issue.hints ?? []) {
|
|
252
|
+
lines.push(` \u2192 ${hint}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (report.issues.length === 0) {
|
|
256
|
+
lines.push("\u2713 \u914D\u7F6E\u9879\u68C0\u67E5\u901A\u8FC7");
|
|
257
|
+
}
|
|
258
|
+
lines.push(` \u5DF2\u542F\u7528: ${report.enabledFeatures.join(", ")}`);
|
|
259
|
+
console.info(lines.join("\n"));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// src/common/config/bootstrap/load-app-config.ts
|
|
263
|
+
var cachedConfig;
|
|
264
|
+
var cachedPath;
|
|
265
|
+
function readAppConfigFile(filePath) {
|
|
266
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
267
|
+
const parsed = yaml.parse(raw);
|
|
268
|
+
const result = appConfigSchema.safeParse(parsed);
|
|
269
|
+
if (!result.success) {
|
|
270
|
+
const details = result.error.issues.map((issue) => ` - ${issue.path.join(".")}: ${issue.message}`).join("\n");
|
|
271
|
+
throw new Error(`AppConfig \u6821\u9A8C\u5931\u8D25 (${filePath}):
|
|
272
|
+
${details}`);
|
|
273
|
+
}
|
|
274
|
+
return result.data;
|
|
275
|
+
}
|
|
276
|
+
function loadAppConfig(options = {}) {
|
|
277
|
+
const filePath = resolveAppConfigPath(options);
|
|
278
|
+
if (cachedConfig && cachedPath === filePath) {
|
|
279
|
+
return cachedConfig;
|
|
280
|
+
}
|
|
281
|
+
const config = readAppConfigFile(filePath);
|
|
282
|
+
cachedPath = filePath;
|
|
283
|
+
cachedConfig = config;
|
|
284
|
+
if (options.applyToProcessEnv !== false) {
|
|
285
|
+
applyAppConfigToProcessEnv(config);
|
|
286
|
+
}
|
|
287
|
+
if (options.logDoctor !== false) {
|
|
288
|
+
logConfigDoctorReport(diagnoseAppConfig(config));
|
|
289
|
+
}
|
|
290
|
+
return config;
|
|
291
|
+
}
|
|
292
|
+
function getAppConfig() {
|
|
293
|
+
if (!cachedConfig) {
|
|
294
|
+
return loadAppConfig();
|
|
295
|
+
}
|
|
296
|
+
return cachedConfig;
|
|
297
|
+
}
|
|
298
|
+
function resetAppConfigCache() {
|
|
299
|
+
cachedConfig = void 0;
|
|
300
|
+
cachedPath = void 0;
|
|
301
|
+
}
|
|
302
|
+
function checkAppConfigFromFile(filePath) {
|
|
303
|
+
const config = readAppConfigFile(filePath);
|
|
304
|
+
return { config, report: diagnoseAppConfig(config) };
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/common/auth/server/sms/providers/aliyun-pnvs.ts
|
|
308
|
+
async function loadPopCore() {
|
|
309
|
+
try {
|
|
310
|
+
const mod = await import('@alicloud/pop-core');
|
|
311
|
+
return mod.default ?? mod;
|
|
312
|
+
} catch {
|
|
313
|
+
throw new Error(
|
|
314
|
+
"\u542F\u7528 SA2KIT_SMS_PROVIDER=aliyun-pnvs \u9700\u8981\u5B89\u88C5 @alicloud/pop-core\uFF1Apnpm add @alicloud/pop-core"
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function createAliyunPnvsSmsProvider(config) {
|
|
319
|
+
return {
|
|
320
|
+
async sendOTP(phoneNumber, code) {
|
|
321
|
+
const Core = await loadPopCore();
|
|
322
|
+
const client = new Core({
|
|
323
|
+
accessKeyId: config.accessKeyId,
|
|
324
|
+
accessKeySecret: config.accessKeySecret,
|
|
325
|
+
endpoint: config.endpoint ?? "https://dypnsapi.aliyuncs.com",
|
|
326
|
+
apiVersion: "2017-05-25"
|
|
327
|
+
});
|
|
328
|
+
const minutes = String(config.codeValidMinutes ?? 5);
|
|
329
|
+
const result = await client.request(
|
|
330
|
+
"SendSmsVerifyCode",
|
|
331
|
+
{
|
|
332
|
+
PhoneNumber: phoneNumber,
|
|
333
|
+
CountryCode: config.countryCode ?? "86",
|
|
334
|
+
SignName: config.signName,
|
|
335
|
+
TemplateCode: config.templateCode,
|
|
336
|
+
TemplateParam: JSON.stringify({ code, min: minutes })
|
|
337
|
+
},
|
|
338
|
+
{ method: "POST" }
|
|
339
|
+
);
|
|
340
|
+
if (result.Code !== "OK" && result.Success !== true) {
|
|
341
|
+
throw new Error(
|
|
342
|
+
`\u963F\u91CC\u4E91\u77ED\u4FE1\u8BA4\u8BC1\u53D1\u9001\u5931\u8D25: ${result.Message ?? result.Code ?? "unknown error"}`
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// src/common/auth/server/sms/providers/console.ts
|
|
350
|
+
function createConsoleSmsProvider() {
|
|
351
|
+
return {
|
|
352
|
+
async sendOTP(phoneNumber, code) {
|
|
353
|
+
console.info(`[sa2kit/auth][sms][console] ${phoneNumber} => ${code}`);
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// src/common/config/bootstrap/resolve-auth-from-config.ts
|
|
359
|
+
function parseTrustedOrigins(config) {
|
|
360
|
+
const baseURL = config.auth.url;
|
|
361
|
+
const defaults = [baseURL, "http://localhost:3000", "http://127.0.0.1:3000"];
|
|
362
|
+
const extra = config.auth.trustedOrigins ?? [];
|
|
363
|
+
return [...defaults, ...extra].filter((origin, index, list) => list.indexOf(origin) === index);
|
|
364
|
+
}
|
|
365
|
+
function resolveAuthConfigFromAppConfig(config, overrides) {
|
|
366
|
+
const smsProvider = config.auth.sms?.provider ?? "console";
|
|
367
|
+
let sms = overrides.sms;
|
|
368
|
+
if (!sms && smsProvider === "console") {
|
|
369
|
+
const consoleProvider = createConsoleSmsProvider();
|
|
370
|
+
sms = { sendOTP: consoleProvider.sendOTP.bind(consoleProvider) };
|
|
371
|
+
}
|
|
372
|
+
if (!sms && smsProvider === "aliyun-pnvs") {
|
|
373
|
+
const aliyun = config.auth.sms?.aliyun;
|
|
374
|
+
if (aliyun?.accessKeyId && aliyun.accessKeySecret && aliyun.signName && aliyun.templateCode) {
|
|
375
|
+
const provider = createAliyunPnvsSmsProvider({
|
|
376
|
+
accessKeyId: aliyun.accessKeyId,
|
|
377
|
+
accessKeySecret: aliyun.accessKeySecret,
|
|
378
|
+
signName: aliyun.signName,
|
|
379
|
+
templateCode: aliyun.templateCode,
|
|
380
|
+
countryCode: aliyun.countryCode ?? "86",
|
|
381
|
+
codeValidMinutes: aliyun.codeValidMinutes ?? 5,
|
|
382
|
+
endpoint: aliyun.endpoint
|
|
383
|
+
});
|
|
384
|
+
sms = { sendOTP: provider.sendOTP.bind(provider) };
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
const isProd = (config.app.env ?? process.env.NODE_ENV) === "production";
|
|
388
|
+
return {
|
|
389
|
+
db: overrides.db,
|
|
390
|
+
baseURL: overrides.baseURL ?? config.auth.url,
|
|
391
|
+
secret: overrides.secret ?? config.auth.secret,
|
|
392
|
+
trustedOrigins: overrides.trustedOrigins ?? parseTrustedOrigins(config),
|
|
393
|
+
basePath: overrides.basePath,
|
|
394
|
+
sms: overrides.sms ?? sms,
|
|
395
|
+
email: overrides.email,
|
|
396
|
+
phoneNumberValidator: overrides.phoneNumberValidator,
|
|
397
|
+
logOtpInDev: overrides.logOtpInDev ?? config.auth.logOtpInDev ?? (!isProd || process.env.SA2KIT_AUTH_LOG_OTP === "1")
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
exports.SOPS_ENCRYPTED_PATH = SOPS_ENCRYPTED_PATH;
|
|
402
|
+
exports.appConfigSchema = appConfigSchema;
|
|
403
|
+
exports.applyAppConfigToProcessEnv = applyAppConfigToProcessEnv;
|
|
404
|
+
exports.checkAppConfigFromFile = checkAppConfigFromFile;
|
|
405
|
+
exports.createAliyunPnvsSmsProvider = createAliyunPnvsSmsProvider;
|
|
406
|
+
exports.createConsoleSmsProvider = createConsoleSmsProvider;
|
|
407
|
+
exports.diagnoseAppConfig = diagnoseAppConfig;
|
|
408
|
+
exports.getAppConfig = getAppConfig;
|
|
409
|
+
exports.isNextBuildPhaseWithoutRuntimeEnv = isNextBuildPhaseWithoutRuntimeEnv;
|
|
410
|
+
exports.loadAppConfig = loadAppConfig;
|
|
411
|
+
exports.logConfigDoctorReport = logConfigDoctorReport;
|
|
412
|
+
exports.readAppConfigFile = readAppConfigFile;
|
|
413
|
+
exports.resetAppConfigCache = resetAppConfigCache;
|
|
414
|
+
exports.resolveAppConfigEnv = resolveAppConfigEnv;
|
|
415
|
+
exports.resolveAppConfigPath = resolveAppConfigPath;
|
|
416
|
+
exports.resolveAuthConfigFromAppConfig = resolveAuthConfigFromAppConfig;
|
|
417
|
+
//# sourceMappingURL=chunk-5H2FICSO.js.map
|
|
418
|
+
//# sourceMappingURL=chunk-5H2FICSO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/common/config/bootstrap/schema.ts","../src/common/config/bootstrap/paths.ts","../src/common/config/bootstrap/apply-to-process-env.ts","../src/common/config/bootstrap/doctor.ts","../src/common/config/bootstrap/load-app-config.ts","../src/common/auth/server/sms/providers/aliyun-pnvs.ts","../src/common/auth/server/sms/providers/console.ts","../src/common/config/bootstrap/resolve-auth-from-config.ts"],"names":["z","resolve","existsSync","readFileSync","parseYaml"],"mappings":"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","file":"chunk-5H2FICSO.js","sourcesContent":["import { z } from 'zod';\n\nconst aliyunSmsSchema = z.object({\n accessKeyId: z.string().optional(),\n accessKeySecret: z.string().optional(),\n signName: z.string().optional(),\n templateCode: z.string().optional(),\n countryCode: z.string().optional(),\n codeValidMinutes: z.coerce.number().int().positive().optional(),\n endpoint: z.string().url().optional(),\n});\n\nconst authSchema = z.object({\n secret: z.string().min(32, 'auth.secret 至少 32 字符'),\n url: z.string().url('auth.url 须为合法 URL'),\n publicUrl: z.string().url('auth.publicUrl 须为合法 URL'),\n trustedOrigins: z.array(z.string().url()).optional(),\n logOtpInDev: z.boolean().optional(),\n sms: z\n .object({\n provider: z.enum(['console', 'aliyun-pnvs', 'none']).optional(),\n aliyun: aliyunSmsSchema.optional(),\n })\n .optional(),\n email: z\n .object({\n provider: z.string().optional(),\n })\n .optional(),\n});\n\nconst databaseSchema = z.object({\n url: z.string().min(1, 'database.url 不能为空'),\n poolSize: z.coerce.number().int().positive().max(100).optional(),\n timeout: z.coerce.number().int().positive().max(30000).optional(),\n sslMode: z.enum(['disable', 'prefer', 'require']).optional(),\n});\n\nconst aliyunOssSchema = z.object({\n enabled: z.boolean().optional(),\n region: z.string().optional(),\n bucket: z.string().optional(),\n accessKeyId: z.string().optional(),\n accessKeySecret: z.string().optional(),\n customDomain: z.string().optional(),\n secure: z.boolean().optional(),\n internal: z.boolean().optional(),\n});\n\nconst aliyunCdnSchema = z.object({\n enabled: z.boolean().optional(),\n domain: z.string().optional(),\n accessKeyId: z.string().optional(),\n accessKeySecret: z.string().optional(),\n});\n\nexport const appConfigSchema = z.object({\n app: z.object({\n name: z.string().min(1),\n env: z.enum(['development', 'production', 'test']).optional(),\n }),\n database: databaseSchema,\n auth: authSchema,\n storage: z\n .object({\n aliyunOss: aliyunOssSchema.optional(),\n aliyunCdn: aliyunCdnSchema.optional(),\n })\n .optional(),\n});\n\nexport type AppConfig = z.infer<typeof appConfigSchema>;\nexport type AppConfigInput = z.input<typeof appConfigSchema>;\n","import { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nexport type AppConfigEnvName = 'local' | 'production' | 'test';\n\nexport type ResolveAppConfigPathOptions = {\n cwd?: string;\n env?: AppConfigEnvName;\n explicitPath?: string;\n};\n\nconst FILE_BY_ENV: Record<AppConfigEnvName, string> = {\n local: 'config/app.config.local.yaml',\n production: 'config/app.config.production.yaml',\n test: 'config/app.config.test.yaml',\n};\n\n/** SOPS 密文默认路径(解密前由运维/脚本处理,应用运行时读明文 production.yaml) */\nexport const SOPS_ENCRYPTED_PATH = 'config/production.enc.yaml';\n\nexport function resolveAppConfigEnv(): AppConfigEnvName {\n const fromEnv = process.env.APP_CONFIG_ENV?.trim();\n if (fromEnv === 'local' || fromEnv === 'production' || fromEnv === 'test') {\n return fromEnv;\n }\n if (process.env.NODE_ENV === 'production') return 'production';\n if (process.env.NODE_ENV === 'test') return 'test';\n return 'local';\n}\n\nexport function isNextBuildPhaseWithoutRuntimeEnv(): boolean {\n return (\n process.env.NEXT_PHASE === 'phase-production-build' ||\n process.env.NEXT_PHASE === 'phase-export'\n );\n}\n\nexport function resolveAppConfigPath(options: ResolveAppConfigPathOptions = {}): string {\n const cwd = options.cwd ?? process.cwd();\n\n if (options.explicitPath) {\n return resolve(cwd, options.explicitPath);\n }\n\n const fromEnv = process.env.APP_CONFIG_PATH?.trim();\n if (fromEnv) {\n return resolve(cwd, fromEnv);\n }\n\n const envName = options.env ?? resolveAppConfigEnv();\n const candidate = resolve(cwd, FILE_BY_ENV[envName]);\n\n if (existsSync(candidate)) {\n return candidate;\n }\n\n const examplePath = resolve(cwd, 'config/app.config.example.yaml');\n if (isNextBuildPhaseWithoutRuntimeEnv() && existsSync(examplePath)) {\n return examplePath;\n }\n\n // 开发回退:local 不存在时尝试 production(CI / 解密后路径)\n if (envName === 'local') {\n const productionFallback = resolve(cwd, FILE_BY_ENV.production);\n if (existsSync(productionFallback)) {\n return productionFallback;\n }\n }\n\n return candidate;\n}\n","import type { AppConfig } from './schema';\n\n/**\n * 将 AppConfig 同步到 process.env,兼容仍读取扁平 env 的 sa2kit 模块(ossFile、legacy 脚本)。\n * 仅在进程内调用一次;已有非空 env 不被覆盖。\n */\nexport function applyAppConfigToProcessEnv(config: AppConfig): void {\n const set = (key: string, value: string | undefined) => {\n if (!value || (process.env[key] && process.env[key]!.length > 0)) return;\n process.env[key] = value;\n };\n\n set('DATABASE_URL', config.database.url);\n if (config.database.poolSize !== undefined) {\n set('DATABASE_POOL_SIZE', String(config.database.poolSize));\n }\n if (config.database.timeout !== undefined) {\n set('DATABASE_TIMEOUT', String(config.database.timeout));\n }\n if (config.database.sslMode) {\n set('DATABASE_SSL_MODE', config.database.sslMode);\n }\n\n set('BETTER_AUTH_SECRET', config.auth.secret);\n set('BETTER_AUTH_URL', config.auth.url);\n set('NEXT_PUBLIC_APP_URL', config.auth.publicUrl);\n\n if (config.auth.trustedOrigins?.length) {\n set('BETTER_AUTH_TRUSTED_ORIGINS', config.auth.trustedOrigins.join(','));\n }\n\n const smsProvider = config.auth.sms?.provider;\n if (smsProvider) {\n set('SA2KIT_SMS_PROVIDER', smsProvider);\n }\n\n const aliyunSms = config.auth.sms?.aliyun;\n if (aliyunSms) {\n set('ALIYUN_SMS_ACCESS_KEY_ID', aliyunSms.accessKeyId);\n set('ALIYUN_SMS_ACCESS_KEY_SECRET', aliyunSms.accessKeySecret);\n set('ALIYUN_SMS_SIGN_NAME', aliyunSms.signName);\n set('ALIYUN_SMS_TEMPLATE_CODE', aliyunSms.templateCode);\n set('ALIYUN_SMS_COUNTRY_CODE', aliyunSms.countryCode);\n if (aliyunSms.codeValidMinutes !== undefined) {\n set('ALIYUN_SMS_CODE_VALID_MINUTES', String(aliyunSms.codeValidMinutes));\n }\n set('ALIYUN_SMS_ENDPOINT', aliyunSms.endpoint);\n }\n\n if (config.auth.email?.provider) {\n set('SA2KIT_EMAIL_PROVIDER', config.auth.email.provider);\n }\n\n if (config.auth.logOtpInDev !== undefined) {\n set('SA2KIT_AUTH_LOG_OTP', config.auth.logOtpInDev ? '1' : '0');\n }\n\n const oss = config.storage?.aliyunOss;\n if (oss) {\n if (oss.region) set('ALIYUN_OSS_REGION', oss.region);\n if (oss.bucket) set('ALIYUN_OSS_BUCKET', oss.bucket);\n if (oss.accessKeyId) set('ALIYUN_OSS_ACCESS_KEY_ID', oss.accessKeyId);\n if (oss.accessKeySecret) set('ALIYUN_OSS_ACCESS_KEY_SECRET', oss.accessKeySecret);\n if (oss.customDomain) set('ALIYUN_OSS_CUSTOM_DOMAIN', oss.customDomain);\n if (oss.secure !== undefined) set('ALIYUN_OSS_SECURE', oss.secure ? 'true' : 'false');\n if (oss.internal !== undefined) set('ALIYUN_OSS_INTERNAL', oss.internal ? 'true' : 'false');\n }\n\n const cdn = config.storage?.aliyunCdn;\n if (cdn) {\n if (cdn.domain) set('ALIYUN_CDN_DOMAIN', cdn.domain);\n if (cdn.accessKeyId) set('ALIYUN_CDN_ACCESS_KEY_ID', cdn.accessKeyId);\n if (cdn.accessKeySecret) set('ALIYUN_CDN_ACCESS_KEY_SECRET', cdn.accessKeySecret);\n }\n}\n","import type { AppConfig } from './schema';\n\nexport type ConfigDoctorIssueLevel = 'error' | 'warning' | 'info';\n\nexport type ConfigDoctorIssue = {\n level: ConfigDoctorIssueLevel;\n featureId: string;\n featureName: string;\n message: string;\n hints?: string[];\n};\n\nexport type ConfigDoctorReport = {\n ok: boolean;\n issues: ConfigDoctorIssue[];\n enabledFeatures: string[];\n};\n\nfunction isSet(value: string | undefined): boolean {\n return Boolean(value && value.trim().length > 0);\n}\n\nexport function diagnoseAppConfig(config: AppConfig): ConfigDoctorReport {\n const issues: ConfigDoctorIssue[] = [];\n const enabledFeatures: string[] = ['app', 'database', 'auth-core'];\n\n const env = config.app.env ?? process.env.NODE_ENV ?? 'development';\n const isProd = env === 'production';\n\n // Auth SMS\n const smsProvider = config.auth.sms?.provider ?? (isProd ? undefined : 'console');\n if (smsProvider === 'aliyun-pnvs') {\n const aliyun = config.auth.sms?.aliyun;\n const missing = [\n !isSet(aliyun?.accessKeyId) && 'auth.sms.aliyun.accessKeyId',\n !isSet(aliyun?.accessKeySecret) && 'auth.sms.aliyun.accessKeySecret',\n !isSet(aliyun?.signName) && 'auth.sms.aliyun.signName',\n !isSet(aliyun?.templateCode) && 'auth.sms.aliyun.templateCode',\n ].filter(Boolean) as string[];\n\n if (missing.length === 0) {\n enabledFeatures.push('auth-sms');\n } else {\n issues.push({\n level: 'error',\n featureId: 'auth-sms',\n featureName: '手机短信 OTP',\n message: `sms.provider=aliyun-pnvs 但缺少:${missing.join(', ')}`,\n });\n }\n } else if (smsProvider === 'console') {\n enabledFeatures.push('auth-sms');\n if (isProd) {\n issues.push({\n level: 'warning',\n featureId: 'auth-sms',\n featureName: '手机短信 OTP',\n message: '生产环境使用 console SMS,验证码仅输出到日志。',\n hints: ['生产请改为 aliyun-pnvs 并填写 auth.sms.aliyun.*'],\n });\n }\n } else {\n issues.push({\n level: isProd ? 'warning' : 'info',\n featureId: 'auth-sms',\n featureName: '手机短信 OTP',\n message: isProd\n ? '未配置短信 provider,用户收不到验证码。'\n : '未配置短信;开发可设 auth.sms.provider: console',\n hints: ['开发:auth.sms.provider: console', '生产:auth.sms.provider: aliyun-pnvs'],\n });\n }\n\n // OSS\n const oss = config.storage?.aliyunOss;\n const ossComplete =\n oss?.enabled !== false &&\n isSet(oss?.region) &&\n isSet(oss?.bucket) &&\n isSet(oss?.accessKeyId) &&\n isSet(oss?.accessKeySecret);\n\n if (ossComplete) {\n enabledFeatures.push('storage-oss');\n } else if (oss?.enabled === true) {\n issues.push({\n level: 'error',\n featureId: 'storage-oss',\n featureName: '阿里云 OSS',\n message: 'storage.aliyunOss.enabled 为 true 但配置不完整。',\n });\n } else {\n issues.push({\n level: 'info',\n featureId: 'storage-oss',\n featureName: '阿里云 OSS',\n message: '未启用完整 OSS 配置,文件上传将回退本地存储(若模块允许)。',\n });\n }\n\n const ok = !issues.some((i) => i.level === 'error');\n return { ok, issues, enabledFeatures };\n}\n\nlet loggedOnce = false;\n\nexport function logConfigDoctorReport(report: ConfigDoctorReport, options?: { force?: boolean }): void {\n if (loggedOnce && !options?.force) return;\n loggedOnce = true;\n\n const lines: string[] = ['[sa2kit/config] 配置检查'];\n for (const issue of report.issues) {\n const prefix = issue.level === 'error' ? '✗' : issue.level === 'warning' ? '⚠' : '○';\n lines.push(`${prefix} ${issue.featureName}: ${issue.message}`);\n for (const hint of issue.hints ?? []) {\n lines.push(` → ${hint}`);\n }\n }\n if (report.issues.length === 0) {\n lines.push('✓ 配置项检查通过');\n }\n lines.push(` 已启用: ${report.enabledFeatures.join(', ')}`);\n console.info(lines.join('\\n'));\n}\n","import { readFileSync } from 'node:fs';\nimport { parse as parseYaml } from 'yaml';\nimport { applyAppConfigToProcessEnv } from './apply-to-process-env';\nimport { diagnoseAppConfig, logConfigDoctorReport, type ConfigDoctorReport } from './doctor';\nimport { resolveAppConfigPath, type ResolveAppConfigPathOptions } from './paths';\nimport { appConfigSchema, type AppConfig } from './schema';\n\nexport type LoadAppConfigOptions = ResolveAppConfigPathOptions & {\n /** 是否写入 process.env(默认 true) */\n applyToProcessEnv?: boolean;\n /** 是否打印 doctor 报告(默认 true) */\n logDoctor?: boolean;\n};\n\nlet cachedConfig: AppConfig | undefined;\nlet cachedPath: string | undefined;\n\nexport function readAppConfigFile(filePath: string): AppConfig {\n const raw = readFileSync(filePath, 'utf8');\n const parsed = parseYaml(raw);\n const result = appConfigSchema.safeParse(parsed);\n\n if (!result.success) {\n const details = result.error.issues\n .map((issue) => ` - ${issue.path.join('.')}: ${issue.message}`)\n .join('\\n');\n throw new Error(`AppConfig 校验失败 (${filePath}):\\n${details}`);\n }\n\n return result.data;\n}\n\nexport function loadAppConfig(options: LoadAppConfigOptions = {}): AppConfig {\n const filePath = resolveAppConfigPath(options);\n\n if (cachedConfig && cachedPath === filePath) {\n return cachedConfig;\n }\n\n const config = readAppConfigFile(filePath);\n cachedPath = filePath;\n cachedConfig = config;\n\n if (options.applyToProcessEnv !== false) {\n applyAppConfigToProcessEnv(config);\n }\n\n if (options.logDoctor !== false) {\n logConfigDoctorReport(diagnoseAppConfig(config));\n }\n\n return config;\n}\n\nexport function getAppConfig(): AppConfig {\n if (!cachedConfig) {\n return loadAppConfig();\n }\n return cachedConfig;\n}\n\nexport function resetAppConfigCache(): void {\n cachedConfig = undefined;\n cachedPath = undefined;\n}\n\nexport function checkAppConfigFromFile(\n filePath: string,\n): { config: AppConfig; report: ConfigDoctorReport } {\n const config = readAppConfigFile(filePath);\n return { config, report: diagnoseAppConfig(config) };\n}\n","import type { AliyunPnvsSmsConfig, Sa2kitSmsProvider } from '../types';\n\ntype PopCoreClient = {\n request(\n action: string,\n params: Record<string, string>,\n options?: { method?: string },\n ): Promise<{ Code?: string; Success?: boolean; Message?: string }>;\n};\n\nasync function loadPopCore(): Promise<new (config: Record<string, string>) => PopCoreClient> {\n try {\n const mod = await import('@alicloud/pop-core');\n return (mod.default ?? mod) as unknown as new (config: Record<string, string>) => PopCoreClient;\n } catch {\n throw new Error(\n '启用 SA2KIT_SMS_PROVIDER=aliyun-pnvs 需要安装 @alicloud/pop-core:pnpm add @alicloud/pop-core',\n );\n }\n}\n\nexport function createAliyunPnvsSmsProvider(config: AliyunPnvsSmsConfig): Sa2kitSmsProvider {\n return {\n async sendOTP(phoneNumber, code) {\n const Core = await loadPopCore();\n const client = new Core({\n accessKeyId: config.accessKeyId,\n accessKeySecret: config.accessKeySecret,\n endpoint: config.endpoint ?? 'https://dypnsapi.aliyuncs.com',\n apiVersion: '2017-05-25',\n });\n\n const minutes = String(config.codeValidMinutes ?? 5);\n const result = await client.request(\n 'SendSmsVerifyCode',\n {\n PhoneNumber: phoneNumber,\n CountryCode: config.countryCode ?? '86',\n SignName: config.signName,\n TemplateCode: config.templateCode,\n TemplateParam: JSON.stringify({ code, min: minutes }),\n },\n { method: 'POST' },\n );\n\n if (result.Code !== 'OK' && result.Success !== true) {\n throw new Error(\n `阿里云短信认证发送失败: ${result.Message ?? result.Code ?? 'unknown error'}`,\n );\n }\n },\n };\n}\n","import type { Sa2kitSmsProvider } from '../types';\n\nexport function createConsoleSmsProvider(): Sa2kitSmsProvider {\n return {\n async sendOTP(phoneNumber, code) {\n console.info(`[sa2kit/auth][sms][console] ${phoneNumber} => ${code}`);\n },\n };\n}\n","import type { Sa2kitAuthConfig } from '../../auth/server/types';\nimport type { AppConfig } from './schema';\nimport { createAliyunPnvsSmsProvider } from '../../auth/server/sms/providers/aliyun-pnvs';\nimport { createConsoleSmsProvider } from '../../auth/server/sms/providers/console';\n\nfunction parseTrustedOrigins(config: AppConfig): string[] {\n const baseURL = config.auth.url;\n const defaults = [baseURL, 'http://localhost:3000', 'http://127.0.0.1:3000'];\n const extra = config.auth.trustedOrigins ?? [];\n return [...defaults, ...extra].filter((origin, index, list) => list.indexOf(origin) === index);\n}\n\nexport function resolveAuthConfigFromAppConfig(\n config: AppConfig,\n overrides: Partial<Sa2kitAuthConfig> & Pick<Sa2kitAuthConfig, 'db'>,\n): Sa2kitAuthConfig {\n const smsProvider = config.auth.sms?.provider ?? 'console';\n let sms = overrides.sms;\n\n if (!sms && smsProvider === 'console') {\n const consoleProvider = createConsoleSmsProvider();\n sms = { sendOTP: consoleProvider.sendOTP.bind(consoleProvider) };\n }\n\n if (!sms && smsProvider === 'aliyun-pnvs') {\n const aliyun = config.auth.sms?.aliyun;\n if (\n aliyun?.accessKeyId &&\n aliyun.accessKeySecret &&\n aliyun.signName &&\n aliyun.templateCode\n ) {\n const provider = createAliyunPnvsSmsProvider({\n accessKeyId: aliyun.accessKeyId,\n accessKeySecret: aliyun.accessKeySecret,\n signName: aliyun.signName,\n templateCode: aliyun.templateCode,\n countryCode: aliyun.countryCode ?? '86',\n codeValidMinutes: aliyun.codeValidMinutes ?? 5,\n endpoint: aliyun.endpoint,\n });\n sms = { sendOTP: provider.sendOTP.bind(provider) };\n }\n }\n\n const isProd = (config.app.env ?? process.env.NODE_ENV) === 'production';\n\n return {\n db: overrides.db,\n baseURL: overrides.baseURL ?? config.auth.url,\n secret: overrides.secret ?? config.auth.secret,\n trustedOrigins: overrides.trustedOrigins ?? parseTrustedOrigins(config),\n basePath: overrides.basePath,\n sms: overrides.sms ?? sms,\n email: overrides.email,\n phoneNumberValidator: overrides.phoneNumberValidator,\n logOtpInDev:\n overrides.logOtpInDev ??\n config.auth.logOtpInDev ??\n (!isProd || process.env.SA2KIT_AUTH_LOG_OTP === '1'),\n };\n}\n"]}
|