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,401 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { existsSync, readFileSync } from 'fs';
|
|
3
|
+
import { resolve } from 'path';
|
|
4
|
+
import { parse } from 'yaml';
|
|
5
|
+
|
|
6
|
+
// src/common/config/bootstrap/schema.ts
|
|
7
|
+
var aliyunSmsSchema = z.object({
|
|
8
|
+
accessKeyId: z.string().optional(),
|
|
9
|
+
accessKeySecret: z.string().optional(),
|
|
10
|
+
signName: z.string().optional(),
|
|
11
|
+
templateCode: z.string().optional(),
|
|
12
|
+
countryCode: z.string().optional(),
|
|
13
|
+
codeValidMinutes: z.coerce.number().int().positive().optional(),
|
|
14
|
+
endpoint: z.string().url().optional()
|
|
15
|
+
});
|
|
16
|
+
var authSchema = z.object({
|
|
17
|
+
secret: z.string().min(32, "auth.secret \u81F3\u5C11 32 \u5B57\u7B26"),
|
|
18
|
+
url: z.string().url("auth.url \u987B\u4E3A\u5408\u6CD5 URL"),
|
|
19
|
+
publicUrl: z.string().url("auth.publicUrl \u987B\u4E3A\u5408\u6CD5 URL"),
|
|
20
|
+
trustedOrigins: z.array(z.string().url()).optional(),
|
|
21
|
+
logOtpInDev: z.boolean().optional(),
|
|
22
|
+
sms: z.object({
|
|
23
|
+
provider: z.enum(["console", "aliyun-pnvs", "none"]).optional(),
|
|
24
|
+
aliyun: aliyunSmsSchema.optional()
|
|
25
|
+
}).optional(),
|
|
26
|
+
email: z.object({
|
|
27
|
+
provider: z.string().optional()
|
|
28
|
+
}).optional()
|
|
29
|
+
});
|
|
30
|
+
var databaseSchema = z.object({
|
|
31
|
+
url: z.string().min(1, "database.url \u4E0D\u80FD\u4E3A\u7A7A"),
|
|
32
|
+
poolSize: z.coerce.number().int().positive().max(100).optional(),
|
|
33
|
+
timeout: z.coerce.number().int().positive().max(3e4).optional(),
|
|
34
|
+
sslMode: z.enum(["disable", "prefer", "require"]).optional()
|
|
35
|
+
});
|
|
36
|
+
var aliyunOssSchema = z.object({
|
|
37
|
+
enabled: z.boolean().optional(),
|
|
38
|
+
region: z.string().optional(),
|
|
39
|
+
bucket: z.string().optional(),
|
|
40
|
+
accessKeyId: z.string().optional(),
|
|
41
|
+
accessKeySecret: z.string().optional(),
|
|
42
|
+
customDomain: z.string().optional(),
|
|
43
|
+
secure: z.boolean().optional(),
|
|
44
|
+
internal: z.boolean().optional()
|
|
45
|
+
});
|
|
46
|
+
var aliyunCdnSchema = z.object({
|
|
47
|
+
enabled: z.boolean().optional(),
|
|
48
|
+
domain: z.string().optional(),
|
|
49
|
+
accessKeyId: z.string().optional(),
|
|
50
|
+
accessKeySecret: z.string().optional()
|
|
51
|
+
});
|
|
52
|
+
var appConfigSchema = z.object({
|
|
53
|
+
app: z.object({
|
|
54
|
+
name: z.string().min(1),
|
|
55
|
+
env: z.enum(["development", "production", "test"]).optional()
|
|
56
|
+
}),
|
|
57
|
+
database: databaseSchema,
|
|
58
|
+
auth: authSchema,
|
|
59
|
+
storage: z.object({
|
|
60
|
+
aliyunOss: aliyunOssSchema.optional(),
|
|
61
|
+
aliyunCdn: aliyunCdnSchema.optional()
|
|
62
|
+
}).optional()
|
|
63
|
+
});
|
|
64
|
+
var FILE_BY_ENV = {
|
|
65
|
+
local: "config/app.config.local.yaml",
|
|
66
|
+
production: "config/app.config.production.yaml",
|
|
67
|
+
test: "config/app.config.test.yaml"
|
|
68
|
+
};
|
|
69
|
+
var SOPS_ENCRYPTED_PATH = "config/production.enc.yaml";
|
|
70
|
+
function resolveAppConfigEnv() {
|
|
71
|
+
const fromEnv = process.env.APP_CONFIG_ENV?.trim();
|
|
72
|
+
if (fromEnv === "local" || fromEnv === "production" || fromEnv === "test") {
|
|
73
|
+
return fromEnv;
|
|
74
|
+
}
|
|
75
|
+
if (process.env.NODE_ENV === "production") return "production";
|
|
76
|
+
if (process.env.NODE_ENV === "test") return "test";
|
|
77
|
+
return "local";
|
|
78
|
+
}
|
|
79
|
+
function isNextBuildPhaseWithoutRuntimeEnv() {
|
|
80
|
+
return process.env.NEXT_PHASE === "phase-production-build" || process.env.NEXT_PHASE === "phase-export";
|
|
81
|
+
}
|
|
82
|
+
function resolveAppConfigPath(options = {}) {
|
|
83
|
+
const cwd = options.cwd ?? process.cwd();
|
|
84
|
+
if (options.explicitPath) {
|
|
85
|
+
return resolve(cwd, options.explicitPath);
|
|
86
|
+
}
|
|
87
|
+
const fromEnv = process.env.APP_CONFIG_PATH?.trim();
|
|
88
|
+
if (fromEnv) {
|
|
89
|
+
return resolve(cwd, fromEnv);
|
|
90
|
+
}
|
|
91
|
+
const envName = options.env ?? resolveAppConfigEnv();
|
|
92
|
+
const candidate = resolve(cwd, FILE_BY_ENV[envName]);
|
|
93
|
+
if (existsSync(candidate)) {
|
|
94
|
+
return candidate;
|
|
95
|
+
}
|
|
96
|
+
const examplePath = resolve(cwd, "config/app.config.example.yaml");
|
|
97
|
+
if (isNextBuildPhaseWithoutRuntimeEnv() && existsSync(examplePath)) {
|
|
98
|
+
return examplePath;
|
|
99
|
+
}
|
|
100
|
+
if (envName === "local") {
|
|
101
|
+
const productionFallback = resolve(cwd, FILE_BY_ENV.production);
|
|
102
|
+
if (existsSync(productionFallback)) {
|
|
103
|
+
return productionFallback;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return candidate;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/common/config/bootstrap/apply-to-process-env.ts
|
|
110
|
+
function applyAppConfigToProcessEnv(config) {
|
|
111
|
+
const set = (key, value) => {
|
|
112
|
+
if (!value || process.env[key] && process.env[key].length > 0) return;
|
|
113
|
+
process.env[key] = value;
|
|
114
|
+
};
|
|
115
|
+
set("DATABASE_URL", config.database.url);
|
|
116
|
+
if (config.database.poolSize !== void 0) {
|
|
117
|
+
set("DATABASE_POOL_SIZE", String(config.database.poolSize));
|
|
118
|
+
}
|
|
119
|
+
if (config.database.timeout !== void 0) {
|
|
120
|
+
set("DATABASE_TIMEOUT", String(config.database.timeout));
|
|
121
|
+
}
|
|
122
|
+
if (config.database.sslMode) {
|
|
123
|
+
set("DATABASE_SSL_MODE", config.database.sslMode);
|
|
124
|
+
}
|
|
125
|
+
set("BETTER_AUTH_SECRET", config.auth.secret);
|
|
126
|
+
set("BETTER_AUTH_URL", config.auth.url);
|
|
127
|
+
set("NEXT_PUBLIC_APP_URL", config.auth.publicUrl);
|
|
128
|
+
if (config.auth.trustedOrigins?.length) {
|
|
129
|
+
set("BETTER_AUTH_TRUSTED_ORIGINS", config.auth.trustedOrigins.join(","));
|
|
130
|
+
}
|
|
131
|
+
const smsProvider = config.auth.sms?.provider;
|
|
132
|
+
if (smsProvider) {
|
|
133
|
+
set("SA2KIT_SMS_PROVIDER", smsProvider);
|
|
134
|
+
}
|
|
135
|
+
const aliyunSms = config.auth.sms?.aliyun;
|
|
136
|
+
if (aliyunSms) {
|
|
137
|
+
set("ALIYUN_SMS_ACCESS_KEY_ID", aliyunSms.accessKeyId);
|
|
138
|
+
set("ALIYUN_SMS_ACCESS_KEY_SECRET", aliyunSms.accessKeySecret);
|
|
139
|
+
set("ALIYUN_SMS_SIGN_NAME", aliyunSms.signName);
|
|
140
|
+
set("ALIYUN_SMS_TEMPLATE_CODE", aliyunSms.templateCode);
|
|
141
|
+
set("ALIYUN_SMS_COUNTRY_CODE", aliyunSms.countryCode);
|
|
142
|
+
if (aliyunSms.codeValidMinutes !== void 0) {
|
|
143
|
+
set("ALIYUN_SMS_CODE_VALID_MINUTES", String(aliyunSms.codeValidMinutes));
|
|
144
|
+
}
|
|
145
|
+
set("ALIYUN_SMS_ENDPOINT", aliyunSms.endpoint);
|
|
146
|
+
}
|
|
147
|
+
if (config.auth.email?.provider) {
|
|
148
|
+
set("SA2KIT_EMAIL_PROVIDER", config.auth.email.provider);
|
|
149
|
+
}
|
|
150
|
+
if (config.auth.logOtpInDev !== void 0) {
|
|
151
|
+
set("SA2KIT_AUTH_LOG_OTP", config.auth.logOtpInDev ? "1" : "0");
|
|
152
|
+
}
|
|
153
|
+
const oss = config.storage?.aliyunOss;
|
|
154
|
+
if (oss) {
|
|
155
|
+
if (oss.region) set("ALIYUN_OSS_REGION", oss.region);
|
|
156
|
+
if (oss.bucket) set("ALIYUN_OSS_BUCKET", oss.bucket);
|
|
157
|
+
if (oss.accessKeyId) set("ALIYUN_OSS_ACCESS_KEY_ID", oss.accessKeyId);
|
|
158
|
+
if (oss.accessKeySecret) set("ALIYUN_OSS_ACCESS_KEY_SECRET", oss.accessKeySecret);
|
|
159
|
+
if (oss.customDomain) set("ALIYUN_OSS_CUSTOM_DOMAIN", oss.customDomain);
|
|
160
|
+
if (oss.secure !== void 0) set("ALIYUN_OSS_SECURE", oss.secure ? "true" : "false");
|
|
161
|
+
if (oss.internal !== void 0) set("ALIYUN_OSS_INTERNAL", oss.internal ? "true" : "false");
|
|
162
|
+
}
|
|
163
|
+
const cdn = config.storage?.aliyunCdn;
|
|
164
|
+
if (cdn) {
|
|
165
|
+
if (cdn.domain) set("ALIYUN_CDN_DOMAIN", cdn.domain);
|
|
166
|
+
if (cdn.accessKeyId) set("ALIYUN_CDN_ACCESS_KEY_ID", cdn.accessKeyId);
|
|
167
|
+
if (cdn.accessKeySecret) set("ALIYUN_CDN_ACCESS_KEY_SECRET", cdn.accessKeySecret);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// src/common/config/bootstrap/doctor.ts
|
|
172
|
+
function isSet(value) {
|
|
173
|
+
return Boolean(value && value.trim().length > 0);
|
|
174
|
+
}
|
|
175
|
+
function diagnoseAppConfig(config) {
|
|
176
|
+
const issues = [];
|
|
177
|
+
const enabledFeatures = ["app", "database", "auth-core"];
|
|
178
|
+
const env = config.app.env ?? process.env.NODE_ENV ?? "development";
|
|
179
|
+
const isProd = env === "production";
|
|
180
|
+
const smsProvider = config.auth.sms?.provider ?? (isProd ? void 0 : "console");
|
|
181
|
+
if (smsProvider === "aliyun-pnvs") {
|
|
182
|
+
const aliyun = config.auth.sms?.aliyun;
|
|
183
|
+
const missing = [
|
|
184
|
+
!isSet(aliyun?.accessKeyId) && "auth.sms.aliyun.accessKeyId",
|
|
185
|
+
!isSet(aliyun?.accessKeySecret) && "auth.sms.aliyun.accessKeySecret",
|
|
186
|
+
!isSet(aliyun?.signName) && "auth.sms.aliyun.signName",
|
|
187
|
+
!isSet(aliyun?.templateCode) && "auth.sms.aliyun.templateCode"
|
|
188
|
+
].filter(Boolean);
|
|
189
|
+
if (missing.length === 0) {
|
|
190
|
+
enabledFeatures.push("auth-sms");
|
|
191
|
+
} else {
|
|
192
|
+
issues.push({
|
|
193
|
+
level: "error",
|
|
194
|
+
featureId: "auth-sms",
|
|
195
|
+
featureName: "\u624B\u673A\u77ED\u4FE1 OTP",
|
|
196
|
+
message: `sms.provider=aliyun-pnvs \u4F46\u7F3A\u5C11\uFF1A${missing.join(", ")}`
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
} else if (smsProvider === "console") {
|
|
200
|
+
enabledFeatures.push("auth-sms");
|
|
201
|
+
if (isProd) {
|
|
202
|
+
issues.push({
|
|
203
|
+
level: "warning",
|
|
204
|
+
featureId: "auth-sms",
|
|
205
|
+
featureName: "\u624B\u673A\u77ED\u4FE1 OTP",
|
|
206
|
+
message: "\u751F\u4EA7\u73AF\u5883\u4F7F\u7528 console SMS\uFF0C\u9A8C\u8BC1\u7801\u4EC5\u8F93\u51FA\u5230\u65E5\u5FD7\u3002",
|
|
207
|
+
hints: ["\u751F\u4EA7\u8BF7\u6539\u4E3A aliyun-pnvs \u5E76\u586B\u5199 auth.sms.aliyun.*"]
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
} else {
|
|
211
|
+
issues.push({
|
|
212
|
+
level: isProd ? "warning" : "info",
|
|
213
|
+
featureId: "auth-sms",
|
|
214
|
+
featureName: "\u624B\u673A\u77ED\u4FE1 OTP",
|
|
215
|
+
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",
|
|
216
|
+
hints: ["\u5F00\u53D1\uFF1Aauth.sms.provider: console", "\u751F\u4EA7\uFF1Aauth.sms.provider: aliyun-pnvs"]
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
const oss = config.storage?.aliyunOss;
|
|
220
|
+
const ossComplete = oss?.enabled !== false && isSet(oss?.region) && isSet(oss?.bucket) && isSet(oss?.accessKeyId) && isSet(oss?.accessKeySecret);
|
|
221
|
+
if (ossComplete) {
|
|
222
|
+
enabledFeatures.push("storage-oss");
|
|
223
|
+
} else if (oss?.enabled === true) {
|
|
224
|
+
issues.push({
|
|
225
|
+
level: "error",
|
|
226
|
+
featureId: "storage-oss",
|
|
227
|
+
featureName: "\u963F\u91CC\u4E91 OSS",
|
|
228
|
+
message: "storage.aliyunOss.enabled \u4E3A true \u4F46\u914D\u7F6E\u4E0D\u5B8C\u6574\u3002"
|
|
229
|
+
});
|
|
230
|
+
} else {
|
|
231
|
+
issues.push({
|
|
232
|
+
level: "info",
|
|
233
|
+
featureId: "storage-oss",
|
|
234
|
+
featureName: "\u963F\u91CC\u4E91 OSS",
|
|
235
|
+
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"
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
const ok = !issues.some((i) => i.level === "error");
|
|
239
|
+
return { ok, issues, enabledFeatures };
|
|
240
|
+
}
|
|
241
|
+
var loggedOnce = false;
|
|
242
|
+
function logConfigDoctorReport(report, options) {
|
|
243
|
+
if (loggedOnce && !options?.force) return;
|
|
244
|
+
loggedOnce = true;
|
|
245
|
+
const lines = ["[sa2kit/config] \u914D\u7F6E\u68C0\u67E5"];
|
|
246
|
+
for (const issue of report.issues) {
|
|
247
|
+
const prefix = issue.level === "error" ? "\u2717" : issue.level === "warning" ? "\u26A0" : "\u25CB";
|
|
248
|
+
lines.push(`${prefix} ${issue.featureName}: ${issue.message}`);
|
|
249
|
+
for (const hint of issue.hints ?? []) {
|
|
250
|
+
lines.push(` \u2192 ${hint}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (report.issues.length === 0) {
|
|
254
|
+
lines.push("\u2713 \u914D\u7F6E\u9879\u68C0\u67E5\u901A\u8FC7");
|
|
255
|
+
}
|
|
256
|
+
lines.push(` \u5DF2\u542F\u7528: ${report.enabledFeatures.join(", ")}`);
|
|
257
|
+
console.info(lines.join("\n"));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/common/config/bootstrap/load-app-config.ts
|
|
261
|
+
var cachedConfig;
|
|
262
|
+
var cachedPath;
|
|
263
|
+
function readAppConfigFile(filePath) {
|
|
264
|
+
const raw = readFileSync(filePath, "utf8");
|
|
265
|
+
const parsed = parse(raw);
|
|
266
|
+
const result = appConfigSchema.safeParse(parsed);
|
|
267
|
+
if (!result.success) {
|
|
268
|
+
const details = result.error.issues.map((issue) => ` - ${issue.path.join(".")}: ${issue.message}`).join("\n");
|
|
269
|
+
throw new Error(`AppConfig \u6821\u9A8C\u5931\u8D25 (${filePath}):
|
|
270
|
+
${details}`);
|
|
271
|
+
}
|
|
272
|
+
return result.data;
|
|
273
|
+
}
|
|
274
|
+
function loadAppConfig(options = {}) {
|
|
275
|
+
const filePath = resolveAppConfigPath(options);
|
|
276
|
+
if (cachedConfig && cachedPath === filePath) {
|
|
277
|
+
return cachedConfig;
|
|
278
|
+
}
|
|
279
|
+
const config = readAppConfigFile(filePath);
|
|
280
|
+
cachedPath = filePath;
|
|
281
|
+
cachedConfig = config;
|
|
282
|
+
if (options.applyToProcessEnv !== false) {
|
|
283
|
+
applyAppConfigToProcessEnv(config);
|
|
284
|
+
}
|
|
285
|
+
if (options.logDoctor !== false) {
|
|
286
|
+
logConfigDoctorReport(diagnoseAppConfig(config));
|
|
287
|
+
}
|
|
288
|
+
return config;
|
|
289
|
+
}
|
|
290
|
+
function getAppConfig() {
|
|
291
|
+
if (!cachedConfig) {
|
|
292
|
+
return loadAppConfig();
|
|
293
|
+
}
|
|
294
|
+
return cachedConfig;
|
|
295
|
+
}
|
|
296
|
+
function resetAppConfigCache() {
|
|
297
|
+
cachedConfig = void 0;
|
|
298
|
+
cachedPath = void 0;
|
|
299
|
+
}
|
|
300
|
+
function checkAppConfigFromFile(filePath) {
|
|
301
|
+
const config = readAppConfigFile(filePath);
|
|
302
|
+
return { config, report: diagnoseAppConfig(config) };
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// src/common/auth/server/sms/providers/aliyun-pnvs.ts
|
|
306
|
+
async function loadPopCore() {
|
|
307
|
+
try {
|
|
308
|
+
const mod = await import('@alicloud/pop-core');
|
|
309
|
+
return mod.default ?? mod;
|
|
310
|
+
} catch {
|
|
311
|
+
throw new Error(
|
|
312
|
+
"\u542F\u7528 SA2KIT_SMS_PROVIDER=aliyun-pnvs \u9700\u8981\u5B89\u88C5 @alicloud/pop-core\uFF1Apnpm add @alicloud/pop-core"
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function createAliyunPnvsSmsProvider(config) {
|
|
317
|
+
return {
|
|
318
|
+
async sendOTP(phoneNumber, code) {
|
|
319
|
+
const Core = await loadPopCore();
|
|
320
|
+
const client = new Core({
|
|
321
|
+
accessKeyId: config.accessKeyId,
|
|
322
|
+
accessKeySecret: config.accessKeySecret,
|
|
323
|
+
endpoint: config.endpoint ?? "https://dypnsapi.aliyuncs.com",
|
|
324
|
+
apiVersion: "2017-05-25"
|
|
325
|
+
});
|
|
326
|
+
const minutes = String(config.codeValidMinutes ?? 5);
|
|
327
|
+
const result = await client.request(
|
|
328
|
+
"SendSmsVerifyCode",
|
|
329
|
+
{
|
|
330
|
+
PhoneNumber: phoneNumber,
|
|
331
|
+
CountryCode: config.countryCode ?? "86",
|
|
332
|
+
SignName: config.signName,
|
|
333
|
+
TemplateCode: config.templateCode,
|
|
334
|
+
TemplateParam: JSON.stringify({ code, min: minutes })
|
|
335
|
+
},
|
|
336
|
+
{ method: "POST" }
|
|
337
|
+
);
|
|
338
|
+
if (result.Code !== "OK" && result.Success !== true) {
|
|
339
|
+
throw new Error(
|
|
340
|
+
`\u963F\u91CC\u4E91\u77ED\u4FE1\u8BA4\u8BC1\u53D1\u9001\u5931\u8D25: ${result.Message ?? result.Code ?? "unknown error"}`
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// src/common/auth/server/sms/providers/console.ts
|
|
348
|
+
function createConsoleSmsProvider() {
|
|
349
|
+
return {
|
|
350
|
+
async sendOTP(phoneNumber, code) {
|
|
351
|
+
console.info(`[sa2kit/auth][sms][console] ${phoneNumber} => ${code}`);
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// src/common/config/bootstrap/resolve-auth-from-config.ts
|
|
357
|
+
function parseTrustedOrigins(config) {
|
|
358
|
+
const baseURL = config.auth.url;
|
|
359
|
+
const defaults = [baseURL, "http://localhost:3000", "http://127.0.0.1:3000"];
|
|
360
|
+
const extra = config.auth.trustedOrigins ?? [];
|
|
361
|
+
return [...defaults, ...extra].filter((origin, index, list) => list.indexOf(origin) === index);
|
|
362
|
+
}
|
|
363
|
+
function resolveAuthConfigFromAppConfig(config, overrides) {
|
|
364
|
+
const smsProvider = config.auth.sms?.provider ?? "console";
|
|
365
|
+
let sms = overrides.sms;
|
|
366
|
+
if (!sms && smsProvider === "console") {
|
|
367
|
+
const consoleProvider = createConsoleSmsProvider();
|
|
368
|
+
sms = { sendOTP: consoleProvider.sendOTP.bind(consoleProvider) };
|
|
369
|
+
}
|
|
370
|
+
if (!sms && smsProvider === "aliyun-pnvs") {
|
|
371
|
+
const aliyun = config.auth.sms?.aliyun;
|
|
372
|
+
if (aliyun?.accessKeyId && aliyun.accessKeySecret && aliyun.signName && aliyun.templateCode) {
|
|
373
|
+
const provider = createAliyunPnvsSmsProvider({
|
|
374
|
+
accessKeyId: aliyun.accessKeyId,
|
|
375
|
+
accessKeySecret: aliyun.accessKeySecret,
|
|
376
|
+
signName: aliyun.signName,
|
|
377
|
+
templateCode: aliyun.templateCode,
|
|
378
|
+
countryCode: aliyun.countryCode ?? "86",
|
|
379
|
+
codeValidMinutes: aliyun.codeValidMinutes ?? 5,
|
|
380
|
+
endpoint: aliyun.endpoint
|
|
381
|
+
});
|
|
382
|
+
sms = { sendOTP: provider.sendOTP.bind(provider) };
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
const isProd = (config.app.env ?? process.env.NODE_ENV) === "production";
|
|
386
|
+
return {
|
|
387
|
+
db: overrides.db,
|
|
388
|
+
baseURL: overrides.baseURL ?? config.auth.url,
|
|
389
|
+
secret: overrides.secret ?? config.auth.secret,
|
|
390
|
+
trustedOrigins: overrides.trustedOrigins ?? parseTrustedOrigins(config),
|
|
391
|
+
basePath: overrides.basePath,
|
|
392
|
+
sms: overrides.sms ?? sms,
|
|
393
|
+
email: overrides.email,
|
|
394
|
+
phoneNumberValidator: overrides.phoneNumberValidator,
|
|
395
|
+
logOtpInDev: overrides.logOtpInDev ?? config.auth.logOtpInDev ?? (!isProd || process.env.SA2KIT_AUTH_LOG_OTP === "1")
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
export { SOPS_ENCRYPTED_PATH, appConfigSchema, applyAppConfigToProcessEnv, checkAppConfigFromFile, createAliyunPnvsSmsProvider, createConsoleSmsProvider, diagnoseAppConfig, getAppConfig, isNextBuildPhaseWithoutRuntimeEnv, loadAppConfig, logConfigDoctorReport, readAppConfigFile, resetAppConfigCache, resolveAppConfigEnv, resolveAppConfigPath, resolveAuthConfigFromAppConfig };
|
|
400
|
+
//# sourceMappingURL=chunk-LGVPFYPR.mjs.map
|
|
401
|
+
//# sourceMappingURL=chunk-LGVPFYPR.mjs.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":["parseYaml"],"mappings":"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","file":"chunk-LGVPFYPR.mjs","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"]}
|
|
@@ -1,43 +1,10 @@
|
|
|
1
1
|
export { Account, NewAccount, NewSession, NewUser, NewVerification, Session, User, Verification, account, accountRelations, authDrizzleSchema, session, sessionRelations, user, userRelations, verification, verifications } from '../schema/index.mjs';
|
|
2
|
+
import { S as Sa2kitAuthConfig, a as Sa2kitAuthInstance } from '../../../types-272dN1B6.mjs';
|
|
3
|
+
export { d as Sa2kitAuth, c as Sa2kitEmailProvider, b as Sa2kitSmsProvider } from '../../../types-272dN1B6.mjs';
|
|
2
4
|
export { U as UserRole, u as userRole } from '../../../enums-Dume-V5Y.mjs';
|
|
3
5
|
import 'drizzle-orm';
|
|
4
6
|
import 'drizzle-orm/pg-core';
|
|
5
7
|
|
|
6
|
-
/**
|
|
7
|
-
* sa2kit auth 服务端配置类型(Better Auth 3.0)
|
|
8
|
-
*/
|
|
9
|
-
type Sa2kitSmsProvider$1 = {
|
|
10
|
-
sendOTP: (phoneNumber: string, code: string) => void | Promise<void>;
|
|
11
|
-
};
|
|
12
|
-
type Sa2kitEmailProvider = {
|
|
13
|
-
sendVerificationOTP: (email: string, otp: string, type: string) => void | Promise<void>;
|
|
14
|
-
};
|
|
15
|
-
type Sa2kitAuthConfig = {
|
|
16
|
-
db: unknown;
|
|
17
|
-
baseURL: string;
|
|
18
|
-
secret: string;
|
|
19
|
-
trustedOrigins?: string[];
|
|
20
|
-
basePath?: string;
|
|
21
|
-
sms?: Sa2kitSmsProvider$1;
|
|
22
|
-
email?: Sa2kitEmailProvider;
|
|
23
|
-
phoneNumberValidator?: (phoneNumber: string) => boolean;
|
|
24
|
-
logOtpInDev?: boolean;
|
|
25
|
-
};
|
|
26
|
-
/** Better Auth 实例(运行时完整 API,类型刻意保持宽松以便跨插件版本) */
|
|
27
|
-
type Sa2kitAuthInstance = {
|
|
28
|
-
handler: (request: Request) => Promise<Response>;
|
|
29
|
-
api: {
|
|
30
|
-
getSession: (ctx: {
|
|
31
|
-
headers: Headers;
|
|
32
|
-
}) => Promise<{
|
|
33
|
-
user: Record<string, unknown>;
|
|
34
|
-
} | null>;
|
|
35
|
-
[key: string]: unknown;
|
|
36
|
-
};
|
|
37
|
-
[key: string]: unknown;
|
|
38
|
-
};
|
|
39
|
-
type Sa2kitAuth = Sa2kitAuthInstance;
|
|
40
|
-
|
|
41
8
|
declare function createSa2kitAuth(config: Sa2kitAuthConfig): Sa2kitAuthInstance;
|
|
42
9
|
|
|
43
10
|
type AuthEnvPlacement = 'env_file' | 'github_secret' | 'runtime_env' | 'database';
|
|
@@ -93,6 +60,12 @@ declare function createSa2kitAuthFromEnv(input: ResolveAuthEnvInput, options?: {
|
|
|
93
60
|
logEnvReport?: boolean;
|
|
94
61
|
}): Sa2kitAuthInstance;
|
|
95
62
|
|
|
63
|
+
type CreateSa2kitAuthFromAppConfigInput = Partial<ResolveAuthEnvInput> & Pick<ResolveAuthEnvInput, 'db'>;
|
|
64
|
+
declare function createSa2kitAuthFromAppConfig(input: CreateSa2kitAuthFromAppConfigInput, options?: {
|
|
65
|
+
logDoctor?: boolean;
|
|
66
|
+
configPath?: string;
|
|
67
|
+
}): Sa2kitAuthInstance;
|
|
68
|
+
|
|
96
69
|
declare function mountNextAuthHandler(auth: Sa2kitAuthInstance): {
|
|
97
70
|
GET: (request: Request) => Promise<Response>;
|
|
98
71
|
POST: (request: Request) => Promise<Response>;
|
|
@@ -169,4 +142,4 @@ declare function handlePhoneSignupIntentRequest(request: Request): Promise<Respo
|
|
|
169
142
|
/** 为手机号注册用户写入 credential 密码,供「手机+密码」登录 */
|
|
170
143
|
declare function upsertCredentialPassword(db: unknown, userId: string, plainPassword: string): Promise<void>;
|
|
171
144
|
|
|
172
|
-
export { AUTH_ENV_ALIASES, AUTH_ENV_CATALOG, AUTH_FEATURES, type AliyunPnvsSmsConfig, type AuthEnvIssue, type AuthEnvReport, type AuthEnvVarDefinition, type AuthFeatureDefinition,
|
|
145
|
+
export { AUTH_ENV_ALIASES, AUTH_ENV_CATALOG, AUTH_FEATURES, type AliyunPnvsSmsConfig, type AuthEnvIssue, type AuthEnvReport, type AuthEnvVarDefinition, type AuthFeatureDefinition, Sa2kitAuthConfig, Sa2kitAuthInstance, type Sa2kitSmsProviderId, type SessionUser, checkAuthEnv, checkAuthEnvFromProcessEnv, consumePhoneSignupPassword, createAliyunPnvsSmsProvider, createAuthRouteHandlers, createConsoleSmsProvider, createSa2kitAuth, createSa2kitAuthFromAppConfig, createSa2kitAuthFromEnv, createSessionValidator, createSmsProviderFromEnv, defaultPhoneValidator, defaultTempEmailFromPhone, formatAuthEnvSetupMarkdown, getSessionUser, getSessionUserNumeric, handlePhoneSignupIntentRequest, logAuthEnvReport, mountAuthHandler, mountNextAuthHandler, resolveAuthEnv, resolveSmsProviderId, stashPhoneSignupPassword, upsertCredentialPassword };
|
|
@@ -1,43 +1,10 @@
|
|
|
1
1
|
export { Account, NewAccount, NewSession, NewUser, NewVerification, Session, User, Verification, account, accountRelations, authDrizzleSchema, session, sessionRelations, user, userRelations, verification, verifications } from '../schema/index.js';
|
|
2
|
+
import { S as Sa2kitAuthConfig, a as Sa2kitAuthInstance } from '../../../types-272dN1B6.js';
|
|
3
|
+
export { d as Sa2kitAuth, c as Sa2kitEmailProvider, b as Sa2kitSmsProvider } from '../../../types-272dN1B6.js';
|
|
2
4
|
export { U as UserRole, u as userRole } from '../../../enums-Dume-V5Y.js';
|
|
3
5
|
import 'drizzle-orm';
|
|
4
6
|
import 'drizzle-orm/pg-core';
|
|
5
7
|
|
|
6
|
-
/**
|
|
7
|
-
* sa2kit auth 服务端配置类型(Better Auth 3.0)
|
|
8
|
-
*/
|
|
9
|
-
type Sa2kitSmsProvider$1 = {
|
|
10
|
-
sendOTP: (phoneNumber: string, code: string) => void | Promise<void>;
|
|
11
|
-
};
|
|
12
|
-
type Sa2kitEmailProvider = {
|
|
13
|
-
sendVerificationOTP: (email: string, otp: string, type: string) => void | Promise<void>;
|
|
14
|
-
};
|
|
15
|
-
type Sa2kitAuthConfig = {
|
|
16
|
-
db: unknown;
|
|
17
|
-
baseURL: string;
|
|
18
|
-
secret: string;
|
|
19
|
-
trustedOrigins?: string[];
|
|
20
|
-
basePath?: string;
|
|
21
|
-
sms?: Sa2kitSmsProvider$1;
|
|
22
|
-
email?: Sa2kitEmailProvider;
|
|
23
|
-
phoneNumberValidator?: (phoneNumber: string) => boolean;
|
|
24
|
-
logOtpInDev?: boolean;
|
|
25
|
-
};
|
|
26
|
-
/** Better Auth 实例(运行时完整 API,类型刻意保持宽松以便跨插件版本) */
|
|
27
|
-
type Sa2kitAuthInstance = {
|
|
28
|
-
handler: (request: Request) => Promise<Response>;
|
|
29
|
-
api: {
|
|
30
|
-
getSession: (ctx: {
|
|
31
|
-
headers: Headers;
|
|
32
|
-
}) => Promise<{
|
|
33
|
-
user: Record<string, unknown>;
|
|
34
|
-
} | null>;
|
|
35
|
-
[key: string]: unknown;
|
|
36
|
-
};
|
|
37
|
-
[key: string]: unknown;
|
|
38
|
-
};
|
|
39
|
-
type Sa2kitAuth = Sa2kitAuthInstance;
|
|
40
|
-
|
|
41
8
|
declare function createSa2kitAuth(config: Sa2kitAuthConfig): Sa2kitAuthInstance;
|
|
42
9
|
|
|
43
10
|
type AuthEnvPlacement = 'env_file' | 'github_secret' | 'runtime_env' | 'database';
|
|
@@ -93,6 +60,12 @@ declare function createSa2kitAuthFromEnv(input: ResolveAuthEnvInput, options?: {
|
|
|
93
60
|
logEnvReport?: boolean;
|
|
94
61
|
}): Sa2kitAuthInstance;
|
|
95
62
|
|
|
63
|
+
type CreateSa2kitAuthFromAppConfigInput = Partial<ResolveAuthEnvInput> & Pick<ResolveAuthEnvInput, 'db'>;
|
|
64
|
+
declare function createSa2kitAuthFromAppConfig(input: CreateSa2kitAuthFromAppConfigInput, options?: {
|
|
65
|
+
logDoctor?: boolean;
|
|
66
|
+
configPath?: string;
|
|
67
|
+
}): Sa2kitAuthInstance;
|
|
68
|
+
|
|
96
69
|
declare function mountNextAuthHandler(auth: Sa2kitAuthInstance): {
|
|
97
70
|
GET: (request: Request) => Promise<Response>;
|
|
98
71
|
POST: (request: Request) => Promise<Response>;
|
|
@@ -169,4 +142,4 @@ declare function handlePhoneSignupIntentRequest(request: Request): Promise<Respo
|
|
|
169
142
|
/** 为手机号注册用户写入 credential 密码,供「手机+密码」登录 */
|
|
170
143
|
declare function upsertCredentialPassword(db: unknown, userId: string, plainPassword: string): Promise<void>;
|
|
171
144
|
|
|
172
|
-
export { AUTH_ENV_ALIASES, AUTH_ENV_CATALOG, AUTH_FEATURES, type AliyunPnvsSmsConfig, type AuthEnvIssue, type AuthEnvReport, type AuthEnvVarDefinition, type AuthFeatureDefinition,
|
|
145
|
+
export { AUTH_ENV_ALIASES, AUTH_ENV_CATALOG, AUTH_FEATURES, type AliyunPnvsSmsConfig, type AuthEnvIssue, type AuthEnvReport, type AuthEnvVarDefinition, type AuthFeatureDefinition, Sa2kitAuthConfig, Sa2kitAuthInstance, type Sa2kitSmsProviderId, type SessionUser, checkAuthEnv, checkAuthEnvFromProcessEnv, consumePhoneSignupPassword, createAliyunPnvsSmsProvider, createAuthRouteHandlers, createConsoleSmsProvider, createSa2kitAuth, createSa2kitAuthFromAppConfig, createSa2kitAuthFromEnv, createSessionValidator, createSmsProviderFromEnv, defaultPhoneValidator, defaultTempEmailFromPhone, formatAuthEnvSetupMarkdown, getSessionUser, getSessionUserNumeric, handlePhoneSignupIntentRequest, logAuthEnvReport, mountAuthHandler, mountNextAuthHandler, resolveAuthEnv, resolveSmsProviderId, stashPhoneSignupPassword, upsertCredentialPassword };
|