@h-ai/core 0.1.0-alpha.42 → 0.1.0-alpha.44
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/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- **统一日志** — Node.js 基于 pino,浏览器基于 loglevel,API 一致
|
|
9
9
|
- **国际化(i18n)** — 集中式 locale 管理 + 类型安全的消息获取器
|
|
10
10
|
- **Zod 校验错误映射** — 兼容 Zod v3/v4 的 issue 提取与默认英文消息本地化
|
|
11
|
-
- **配置管理** — YAML
|
|
11
|
+
- **配置管理** — YAML 加载、约定式环境变量映射、显式环境变量插值、Zod 校验、文件监听(Node.js 专用)
|
|
12
12
|
- **ID 生成** — nanoid 与 UUID v4
|
|
13
13
|
- **错误定义** — 标准化错误码体系,支持跨模块统一的错误定义与实例创建
|
|
14
14
|
- **模块工具** — NotInitializedKit 代理模式,各模块共用的生命周期基础设施
|
|
@@ -319,15 +319,41 @@ core.config.clear('app') // 清除单个
|
|
|
319
319
|
core.config.clear() // 清除全部
|
|
320
320
|
```
|
|
321
321
|
|
|
322
|
-
####
|
|
322
|
+
#### 环境变量映射与插值
|
|
323
323
|
|
|
324
|
-
`core.config.load()`
|
|
324
|
+
`core.config.load(name, ...)` 会为每个 YAML 叶子配置项自动映射
|
|
325
|
+
`HAI_<配置名>_<YAML 路径>` 环境变量。配置名和每层 key 转成大写,层级以 `_`
|
|
326
|
+
分隔,camelCase 不拆词;例如 `ai.llm.apiKey` 对应 `HAI_AI_LLM_APIKEY`,
|
|
327
|
+
`ai.llm.maxTokens` 对应 `HAI_AI_LLM_MAXTOKENS`。数组索引也作为一层,例如
|
|
328
|
+
`ai.llm.models[0].temperature` 对应 `HAI_AI_LLM_MODELS_0_TEMPERATURE`。
|
|
329
|
+
|
|
330
|
+
环境变量存在时覆盖 YAML 值,并按 YAML 标量规则还原 number / boolean 等类型;
|
|
331
|
+
环境变量不存在时保留 YAML 值。映射只覆盖 YAML 中已经声明的叶子项,不会凭空新增配置项。
|
|
332
|
+
|
|
333
|
+
```yaml
|
|
334
|
+
# config/_ai.yml(core.init 扫描后配置名为 ai)
|
|
335
|
+
llm:
|
|
336
|
+
apiKey: ''
|
|
337
|
+
baseUrl: https://api.xiaomimimo.com/v1
|
|
338
|
+
model: mimo-v2.5
|
|
339
|
+
maxTokens: 4096
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
```dotenv
|
|
343
|
+
HAI_AI_LLM_APIKEY=your-api-key
|
|
344
|
+
HAI_AI_LLM_MAXTOKENS=8192
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
确实需要特殊变量名时,继续使用显式 `${VAR}` 语法。优先级固定为:
|
|
348
|
+
约定环境变量 > 显式环境变量 > YAML 默认值。
|
|
325
349
|
|
|
326
350
|
- `${VAR}` — 读取 `process.env.VAR`;若不存在则返回 `CONFIG_ENV_VAR_MISSING` 错误
|
|
327
351
|
- `${VAR:default}` — 读取 `process.env.VAR`;若不存在则使用冒号后的默认值
|
|
328
352
|
|
|
329
353
|
**类型还原:** 当整个值恰好是单个变量表达式(如 `${PORT:3000}`)时,插值结果按 YAML 规则还原为原生类型(number / boolean 等)。混合文本始终为字符串。
|
|
330
354
|
|
|
355
|
+
`${VAR:}` 或值为空字符串的 `${VAR}` 会保留为 `''`,不会被 YAML 转成 `null`。需要表达“未配置”的模块应在自身 Schema 中把空字符串规范化为 `undefined`。
|
|
356
|
+
|
|
331
357
|
```yaml
|
|
332
358
|
# config/app.yml
|
|
333
359
|
debug: ${DEBUG:false} # → boolean false
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as HaiResult, W as WatchCallback, a as CoreOptions, e as CoreLogger, O as I18nFn, Q as zodValidation, R as IdFn, T as TypeUtilFn, S as ObjectFn, U as SanitizeFn, X as StringFn, Y as ArrayFn, _ as AsyncFn, $ as TimeFn, a0 as ErrorFn, a1 as ModuleFn } from './core-function-config.node-
|
|
2
|
-
export { b as CoreConfig, d as CoreConfigSchema, C as CoreFunctions, E as Env, f as EnvSchema, g as ErrorInfo, h as ErrorInfoValue, H as HaiCommonError, i as HaiConfigError, j as HaiError, k as HaiErrorDef, I as IdConfig, m as IdConfigSchema, n as InterpolationParams, L as Locale, o as LocaleInfo, p as LocaleMessages, q as LogContext, r as LogFormat, s as LogFormatSchema, t as LogLevel, u as LogLevelSchema, v as Logger, w as LoggerFunctions, x as LoggerOptions, y as LoggingConfig, z as LoggingConfigSchema, M as MatchHandlers, A as MessageDictionary, B as MessageOptions, P as PaginatedResult, D as PaginationOptions, F as PaginationOptionsInput, V as ValidationFormError, Z as ZodMessageGetter, G as ZodValidationFn, J as ZodValidationMessageKey, K as err, N as ok } from './core-function-config.node-
|
|
1
|
+
import { l as HaiResult, W as WatchCallback, a as CoreOptions, e as CoreLogger, O as I18nFn, Q as zodValidation, R as IdFn, T as TypeUtilFn, S as ObjectFn, U as SanitizeFn, X as StringFn, Y as ArrayFn, _ as AsyncFn, $ as TimeFn, a0 as ErrorFn, a1 as ModuleFn } from './core-function-config.node-DMHeZn-R.js';
|
|
2
|
+
export { b as CoreConfig, d as CoreConfigSchema, C as CoreFunctions, E as Env, f as EnvSchema, g as ErrorInfo, h as ErrorInfoValue, H as HaiCommonError, i as HaiConfigError, j as HaiError, k as HaiErrorDef, I as IdConfig, m as IdConfigSchema, n as InterpolationParams, L as Locale, o as LocaleInfo, p as LocaleMessages, q as LogContext, r as LogFormat, s as LogFormatSchema, t as LogLevel, u as LogLevelSchema, v as Logger, w as LoggerFunctions, x as LoggerOptions, y as LoggingConfig, z as LoggingConfigSchema, M as MatchHandlers, A as MessageDictionary, B as MessageOptions, P as PaginatedResult, D as PaginationOptions, F as PaginationOptionsInput, V as ValidationFormError, Z as ZodMessageGetter, G as ZodValidationFn, J as ZodValidationMessageKey, K as err, N as ok } from './core-function-config.node-DMHeZn-R.js';
|
|
3
3
|
import * as zod from 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/node.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CoreFunctions, c as config, a as CoreOptions } from './core-function-config.node-
|
|
2
|
-
export { b as CoreConfig, d as CoreConfigSchema, e as CoreLogger, E as Env, f as EnvSchema, g as ErrorInfo, h as ErrorInfoValue, H as HaiCommonError, i as HaiConfigError, j as HaiError, k as HaiErrorDef, l as HaiResult, I as IdConfig, m as IdConfigSchema, n as InterpolationParams, L as Locale, o as LocaleInfo, p as LocaleMessages, q as LogContext, r as LogFormat, s as LogFormatSchema, t as LogLevel, u as LogLevelSchema, v as Logger, w as LoggerFunctions, x as LoggerOptions, y as LoggingConfig, z as LoggingConfigSchema, M as MatchHandlers, A as MessageDictionary, B as MessageOptions, P as PaginatedResult, D as PaginationOptions, F as PaginationOptionsInput, V as ValidationFormError, Z as ZodMessageGetter, G as ZodValidationFn, J as ZodValidationMessageKey, K as err, N as ok } from './core-function-config.node-
|
|
1
|
+
import { C as CoreFunctions, c as config, a as CoreOptions } from './core-function-config.node-DMHeZn-R.js';
|
|
2
|
+
export { b as CoreConfig, d as CoreConfigSchema, e as CoreLogger, E as Env, f as EnvSchema, g as ErrorInfo, h as ErrorInfoValue, H as HaiCommonError, i as HaiConfigError, j as HaiError, k as HaiErrorDef, l as HaiResult, I as IdConfig, m as IdConfigSchema, n as InterpolationParams, L as Locale, o as LocaleInfo, p as LocaleMessages, q as LogContext, r as LogFormat, s as LogFormatSchema, t as LogLevel, u as LogLevelSchema, v as Logger, w as LoggerFunctions, x as LoggerOptions, y as LoggingConfig, z as LoggingConfigSchema, M as MatchHandlers, A as MessageDictionary, B as MessageOptions, P as PaginatedResult, D as PaginationOptions, F as PaginationOptionsInput, V as ValidationFormError, Z as ZodMessageGetter, G as ZodValidationFn, J as ZodValidationMessageKey, K as err, N as ok } from './core-function-config.node-DMHeZn-R.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/node.js
CHANGED
|
@@ -10,35 +10,52 @@ import pino from 'pino';
|
|
|
10
10
|
|
|
11
11
|
var ENV_VAR_PATTERN = /\$\{([^}:]+)(?::([^}]*))?\}/g;
|
|
12
12
|
var FULL_VAR_PATTERN = /^\$\{[^}:]+(?::[^}]*)?\}$/;
|
|
13
|
-
function
|
|
13
|
+
function parseEnvValue(value) {
|
|
14
|
+
if (value === "")
|
|
15
|
+
return "";
|
|
16
|
+
try {
|
|
17
|
+
const parsed = parse(value);
|
|
18
|
+
return parsed === void 0 ? value : parsed;
|
|
19
|
+
} catch {
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function normalizeEnvSegment(segment) {
|
|
24
|
+
return segment.replace(/[^a-z0-9]+/gi, "_").replace(/^_+|_+$/g, "").toUpperCase();
|
|
25
|
+
}
|
|
26
|
+
function buildConventionEnvName(name, path) {
|
|
27
|
+
return ["HAI", name, ...path].map(normalizeEnvSegment).filter(Boolean).join("_");
|
|
28
|
+
}
|
|
29
|
+
function resolveEnv(value, name, path = []) {
|
|
14
30
|
if (typeof value === "string") {
|
|
15
|
-
|
|
31
|
+
const conventionEnvValue = process2.env[buildConventionEnvName(name, path)];
|
|
32
|
+
if (conventionEnvValue !== void 0)
|
|
33
|
+
return ok(parseEnvValue(conventionEnvValue));
|
|
16
34
|
ENV_VAR_PATTERN.lastIndex = 0;
|
|
35
|
+
const hasExplicitEnv = ENV_VAR_PATTERN.test(value);
|
|
36
|
+
ENV_VAR_PATTERN.lastIndex = 0;
|
|
37
|
+
if (!hasExplicitEnv)
|
|
38
|
+
return ok(value);
|
|
39
|
+
let result = value;
|
|
17
40
|
while (true) {
|
|
18
41
|
const match = ENV_VAR_PATTERN.exec(value);
|
|
19
42
|
if (!match)
|
|
20
43
|
break;
|
|
21
44
|
const [fullMatch, varName, defaultValue] = match;
|
|
22
|
-
const
|
|
23
|
-
if (
|
|
45
|
+
const envValue2 = process2.env[varName];
|
|
46
|
+
if (envValue2 === void 0 && defaultValue === void 0) {
|
|
24
47
|
return err(HaiConfigError.CONFIG_ENV_VAR_MISSING, i18n.coreM("core_configEnvVarMissing", { params: { varName } }));
|
|
25
48
|
}
|
|
26
|
-
result = result.replace(fullMatch,
|
|
27
|
-
}
|
|
28
|
-
if (FULL_VAR_PATTERN.test(value)) {
|
|
29
|
-
try {
|
|
30
|
-
const coerced = parse(result);
|
|
31
|
-
if (coerced !== void 0)
|
|
32
|
-
return ok(coerced);
|
|
33
|
-
} catch {
|
|
34
|
-
}
|
|
49
|
+
result = result.replace(fullMatch, envValue2 ?? defaultValue ?? "");
|
|
35
50
|
}
|
|
51
|
+
if (FULL_VAR_PATTERN.test(value))
|
|
52
|
+
return ok(parseEnvValue(result));
|
|
36
53
|
return ok(result);
|
|
37
54
|
}
|
|
38
55
|
if (Array.isArray(value)) {
|
|
39
56
|
const results = [];
|
|
40
|
-
for (const item of value) {
|
|
41
|
-
const r =
|
|
57
|
+
for (const [index, item] of value.entries()) {
|
|
58
|
+
const r = resolveEnv(item, name, [...path, String(index)]);
|
|
42
59
|
if (!r.success)
|
|
43
60
|
return r;
|
|
44
61
|
results.push(r.data);
|
|
@@ -48,14 +65,15 @@ function interpolateEnv(value) {
|
|
|
48
65
|
if (typeUtils.isObject(value)) {
|
|
49
66
|
const results = {};
|
|
50
67
|
for (const [k, v] of Object.entries(value)) {
|
|
51
|
-
const r =
|
|
68
|
+
const r = resolveEnv(v, name, [...path, k]);
|
|
52
69
|
if (!r.success)
|
|
53
70
|
return r;
|
|
54
71
|
results[k] = r.data;
|
|
55
72
|
}
|
|
56
73
|
return ok(results);
|
|
57
74
|
}
|
|
58
|
-
|
|
75
|
+
const envValue = process2.env[buildConventionEnvName(name, path)];
|
|
76
|
+
return ok(envValue === void 0 ? value : parseEnvValue(envValue));
|
|
59
77
|
}
|
|
60
78
|
var configCache = /* @__PURE__ */ new Map();
|
|
61
79
|
var watchEntries = /* @__PURE__ */ new Map();
|
|
@@ -85,20 +103,20 @@ function notifyWatchCallbacks(name, result) {
|
|
|
85
103
|
}
|
|
86
104
|
}
|
|
87
105
|
}
|
|
88
|
-
function loadYaml(filePath) {
|
|
106
|
+
function loadYaml(name, filePath) {
|
|
89
107
|
if (!existsSync(filePath)) {
|
|
90
108
|
return err(HaiConfigError.CONFIG_FILE_NOT_FOUND, i18n.coreM("core_configFileNotExist", { params: { filePath } }));
|
|
91
109
|
}
|
|
92
110
|
try {
|
|
93
111
|
const content = readFileSync(filePath, "utf-8");
|
|
94
112
|
const parsed = parse(content);
|
|
95
|
-
return
|
|
113
|
+
return resolveEnv(parsed, name);
|
|
96
114
|
} catch (error) {
|
|
97
115
|
return err(HaiConfigError.CONFIG_PARSE_ERROR, i18n.coreM("core_configParseFailed", { params: { filePath } }), error);
|
|
98
116
|
}
|
|
99
117
|
}
|
|
100
|
-
function loadConfig(filePath, schema) {
|
|
101
|
-
const yamlResult = loadYaml(filePath);
|
|
118
|
+
function loadConfig(name, filePath, schema) {
|
|
119
|
+
const yamlResult = loadYaml(name, filePath);
|
|
102
120
|
if (!yamlResult.success)
|
|
103
121
|
return yamlResult;
|
|
104
122
|
const parseResult = schema.safeParse(yamlResult.data);
|
|
@@ -108,7 +126,7 @@ function loadConfig(filePath, schema) {
|
|
|
108
126
|
return ok(parseResult.data);
|
|
109
127
|
}
|
|
110
128
|
function loadAndCache(name, filePath, schema) {
|
|
111
|
-
const result = schema ? loadConfig(filePath, schema) : loadYaml(filePath);
|
|
129
|
+
const result = schema ? loadConfig(name, filePath, schema) : loadYaml(name, filePath);
|
|
112
130
|
if (result.success) {
|
|
113
131
|
configCache.set(name, {
|
|
114
132
|
data: result.data,
|
|
@@ -144,7 +162,7 @@ function reloadAndNotify(name) {
|
|
|
144
162
|
notifyWatchCallbacks(name, result2);
|
|
145
163
|
return result2;
|
|
146
164
|
}
|
|
147
|
-
const result = entry.schema ? loadConfig(entry.filePath, entry.schema) : loadYaml(entry.filePath);
|
|
165
|
+
const result = entry.schema ? loadConfig(name, entry.filePath, entry.schema) : loadYaml(name, entry.filePath);
|
|
148
166
|
if (result.success) {
|
|
149
167
|
configCache.set(name, {
|
|
150
168
|
...entry,
|
package/dist/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/functions/core-function-config.node.ts","../src/functions/core-function-logger.node.ts","../src/core-main.node.ts"],"names":["process","result","config","logger","existsSync"],"mappings":"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","file":"node.js","sourcesContent":["/**\n * @h-ai/core — 配置管理(Node.js 专用)\n *\n * 提供 YAML 配置文件加载、环境变量插值、缓存管理。\n * @module core-function-config.node\n */\n\nimport type { ZodType } from 'zod'\nimport type { HaiError, HaiResult } from '../core-types.js'\n\nimport { existsSync, readFileSync, watch } from 'node:fs'\nimport process from 'node:process'\nimport { parse } from 'yaml'\n\n// ─── 配置文件监听 ───\n\nimport { err, HaiConfigError, ok } from '../core-types.js'\nimport { i18n } from '../i18n/core-i18n-utils.js'\nimport { typeUtils } from '../utils/core-util-type.js'\n\n/** 缓存项(存储已加载的配置及其元信息) */\ninterface CacheEntry<T = unknown> {\n /** 解析后的配置数据 */\n data: T\n /** 配置文件路径 */\n filePath: string\n /** Zod 校验 Schema(重载时复用,无 Schema 加载时为 undefined) */\n schema?: ZodType<T>\n /** 加载时间戳(毫秒) */\n loadedAt: number\n}\n\n// ─── 内部工具 ───\n\n/** 环境变量插值正则(支持 ${VAR} 与 ${VAR:default}) */\nconst ENV_VAR_PATTERN = /\\$\\{([^}:]+)(?::([^}]*))?\\}/g\n\n/** 判断整个字符串是否恰好是单个 ${VAR} 或 ${VAR:default}(用于类型还原) */\nconst FULL_VAR_PATTERN = /^\\$\\{[^}:]+(?::[^}]*)?\\}$/\n\n/**\n * 递归替换环境变量。\n *\n * 支持 `${VAR}` 和 `${VAR:default}` 两种语法,递归处理字符串、数组和对象。\n *\n * @param value - 任意配置值(字符串、数组、对象或原始值)\n * @returns 插值后的结果;当环境变量缺失且未提供默认值时返回 ENV_VAR_MISSING 错误\n */\nfunction interpolateEnv(value: unknown): HaiResult<unknown> {\n if (typeof value === 'string') {\n let result = value\n ENV_VAR_PATTERN.lastIndex = 0\n\n // 避免在 while 条件中赋值(满足 lint 规则 no-cond-assign)\n while (true) {\n const match = ENV_VAR_PATTERN.exec(value)\n if (!match)\n break\n\n const [fullMatch, varName, defaultValue] = match\n const envValue = process.env[varName]\n\n // 未提供默认值且环境变量不存在时,返回错误\n if (envValue === undefined && defaultValue === undefined) {\n return err(HaiConfigError.CONFIG_ENV_VAR_MISSING, i18n.coreM('core_configEnvVarMissing', { params: { varName } }))\n }\n result = result.replace(fullMatch, envValue ?? defaultValue ?? '')\n }\n\n // 当原值整体是单个 ${VAR:default} 时,插值结果需还原为 YAML 原生类型\n // 例如 ${DEBUG:false} → \"false\" 应还原为 boolean false\n if (FULL_VAR_PATTERN.test(value)) {\n try {\n const coerced = parse(result)\n if (coerced !== undefined)\n return ok(coerced)\n }\n catch { /* 解析失败则保持字符串 */ }\n }\n\n return ok(result)\n }\n\n if (Array.isArray(value)) {\n const results: unknown[] = []\n for (const item of value) {\n const r = interpolateEnv(item)\n if (!r.success)\n return r\n results.push(r.data)\n }\n return ok(results)\n }\n\n if (typeUtils.isObject(value)) {\n const results: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(value)) {\n const r = interpolateEnv(v)\n if (!r.success)\n return r\n results[k] = r.data\n }\n return ok(results)\n }\n\n return ok(value)\n}\n\n// ─── 配置管理器 ───\n\n/** 配置缓存 */\nconst configCache = new Map<string, CacheEntry>()\n\n/**\n * 监听回调类型。\n *\n * @template T - 配置数据类型\n *\n * @example\n * ```ts\n * const callback: WatchCallback<AppConfig> = (cfg, error) => {\n * if (error) { core.logger.error('Config reload failed', { error }); return }\n * // 使用更新后的 cfg\n * }\n * ```\n */\nexport type WatchCallback<T = unknown> = (config: T | null, error?: HaiError) => void\n\n/** 配置监听条目(包含文件 watcher 和回调集合) */\ninterface WatchEntry {\n /** fs.watch 返回的 watcher 实例 */\n watcher: ReturnType<typeof watch>\n /** 已注册的回调函数集合 */\n callbacks: Set<WatchCallback<unknown>>\n /** 防抖定时器(用于 stopWatching 时清理) */\n debounceTimer: ReturnType<typeof setTimeout> | null\n}\n\n/** 配置监听映射 */\nconst watchEntries = new Map<string, WatchEntry>()\n\n/**\n * 创建未加载错误。\n *\n * @param name - 配置名称\n * @returns HaiError,错误码为 NOT_LOADED\n */\nfunction createNotLoadedError(name: string): HaiError {\n const result = err(HaiConfigError.CONFIG_NOT_LOADED, i18n.coreM('core_configNotLoaded', { params: { name } }))\n if (!result.success)\n return result.error\n\n throw new Error('unreachable')\n}\n\n/**\n * 通知监听回调。\n *\n * @param name - 配置名称\n * @param result - 重载结果(成功时传配置数据,失败时传错误)\n */\nfunction notifyWatchCallbacks(name: string, result: HaiResult<unknown>): void {\n const entry = watchEntries.get(name)\n if (!entry)\n return\n\n if (result.success) {\n for (const callback of entry.callbacks) {\n try {\n callback(result.data, undefined)\n }\n catch { /* 隔离单个回调异常,不影响其他回调 */ }\n }\n }\n else {\n for (const callback of entry.callbacks) {\n try {\n callback(null, result.error)\n }\n catch { /* 隔离单个回调异常,不影响其他回调 */ }\n }\n }\n}\n\n/**\n * 加载 YAML 配置文件(不带 Schema 验证)。\n *\n * 流程:检查文件存在 → 读取 YAML → 环境变量插值。\n *\n * @param filePath - YAML 文件路径\n * @returns 解析结果;可能的错误码:FILE_NOT_FOUND / PARSE_ERROR / ENV_VAR_MISSING\n */\nfunction loadYaml(filePath: string): HaiResult<unknown> {\n if (!existsSync(filePath)) {\n return err(HaiConfigError.CONFIG_FILE_NOT_FOUND, i18n.coreM('core_configFileNotExist', { params: { filePath } }))\n }\n\n try {\n const content = readFileSync(filePath, 'utf-8')\n const parsed = parse(content)\n return interpolateEnv(parsed)\n }\n catch (error) {\n return err(HaiConfigError.CONFIG_PARSE_ERROR, i18n.coreM('core_configParseFailed', { params: { filePath } }), error)\n }\n}\n\n/**\n * 加载并验证配置文件。\n *\n * 流程:加载 YAML → 环境变量插值 → Zod Schema 校验。\n *\n * @param filePath - YAML 文件路径\n * @param schema - Zod 校验 Schema\n * @returns 校验后的配置数据;可能的错误码:FILE_NOT_FOUND / PARSE_ERROR / ENV_VAR_MISSING / VALIDATION_ERROR\n */\nfunction loadConfig<T>(\n filePath: string,\n schema: ZodType<T>,\n): HaiResult<T> {\n const yamlResult = loadYaml(filePath)\n if (!yamlResult.success)\n return yamlResult\n\n const parseResult = schema.safeParse(yamlResult.data)\n if (!parseResult.success) {\n return err(HaiConfigError.CONFIG_VALIDATION_ERROR, i18n.coreM('core_configValidationFailed'), parseResult.error.issues)\n }\n\n return ok(parseResult.data)\n}\n\n/**\n * 加载配置并写入缓存。\n *\n * @param name - 配置名称(缓存 key)\n * @param filePath - YAML 文件路径\n * @param schema - 可选 Zod Schema(不传则跳过校验)\n * @returns 加载结果;成功时同时更新缓存\n */\nfunction loadAndCache<T>(\n name: string,\n filePath: string,\n schema?: ZodType<T>,\n): HaiResult<T> {\n const result = schema ? loadConfig(filePath, schema) : loadYaml(filePath) as HaiResult<T>\n if (result.success) {\n configCache.set(name, {\n data: result.data,\n filePath,\n schema: schema as ZodType<unknown> | undefined,\n loadedAt: Date.now(),\n })\n }\n return result\n}\n\n/**\n * 校验已加载的配置并写回缓存。\n *\n * 从缓存中取出原始数据重新用 Schema 校验,校验通过后更新缓存。\n *\n * @param name - 配置名称\n * @param schema - Zod Schema\n * @returns 校验结果;未加载时返回 NOT_LOADED,校验失败返回 VALIDATION_ERROR\n */\nfunction validateLoadedConfig<T>(name: string, schema: ZodType<T>): HaiResult<T> {\n const entry = configCache.get(name)\n if (!entry) {\n return err(createNotLoadedError(name))\n }\n\n const parseResult = schema.safeParse(entry.data)\n if (!parseResult.success) {\n return err(HaiConfigError.CONFIG_VALIDATION_ERROR, i18n.coreM('core_configValidationFailed'), parseResult.error.issues)\n }\n\n const validated = parseResult.data\n configCache.set(name, {\n ...entry,\n data: validated,\n schema,\n loadedAt: Date.now(),\n })\n\n return ok(validated)\n}\n\n/**\n * 重新加载配置并通知监听器。\n *\n * 从缓存中获取文件路径和 Schema,重新加载并触发所有 watch 回调。\n *\n * @param name - 配置名称\n * @returns 重载结果;未加载时返回 NOT_LOADED\n */\nfunction reloadAndNotify(name: string): HaiResult<unknown> {\n const entry = configCache.get(name)\n if (!entry) {\n const result = err(createNotLoadedError(name))\n notifyWatchCallbacks(name, result)\n return result\n }\n\n // 无 Schema 时直接加载 YAML(不做校验),避免 schema 为 undefined 导致运行时崩溃\n const result = entry.schema ? loadConfig(entry.filePath, entry.schema) : loadYaml(entry.filePath)\n if (result.success) {\n configCache.set(name, {\n ...entry,\n data: result.data,\n loadedAt: Date.now(),\n })\n }\n notifyWatchCallbacks(name, result)\n return result\n}\n\n/**\n * 启动配置文件监听。\n *\n * 使用 `fs.watch` 监听文件变更,变更时自动重载并通知回调。\n * 同一配置名只会创建一个 watcher,多次调用返回同一实例。\n *\n * @param name - 配置名称\n * @returns WatchEntry 实例;配置未加载时返回 null\n */\nfunction startFileWatcher(name: string): WatchEntry | null {\n const existing = watchEntries.get(name)\n if (existing)\n return existing\n\n const entry = configCache.get(name)\n if (!entry)\n return null\n\n try {\n const watchEntry: WatchEntry = {\n watcher: null!,\n callbacks: new Set(),\n debounceTimer: null,\n }\n\n // 防抖定时器:fs.watch 可能对同一次文件保存触发多次 'change' 事件\n const watcher = watch(entry.filePath, (eventType) => {\n if (eventType === 'change') {\n if (watchEntry.debounceTimer)\n clearTimeout(watchEntry.debounceTimer)\n watchEntry.debounceTimer = setTimeout(() => {\n watchEntry.debounceTimer = null\n reloadAndNotify(name)\n }, 100)\n }\n })\n\n watchEntry.watcher = watcher\n watchEntries.set(name, watchEntry)\n return watchEntry\n }\n catch {\n return null\n }\n}\n\n/**\n * 注册监听回调。\n *\n * 启动文件 watcher(若尚未启动)并注册回调。\n * 配置未加载时立即回调 NOT_LOADED 错误。\n *\n * @param name - 配置名称\n * @param callback - 变更回调\n * @returns 取消监听函数;调用后自动清理(无回调时关闭 watcher)\n */\nfunction registerWatch<T>(name: string, callback: WatchCallback<T>): () => void {\n const entry = startFileWatcher(name)\n if (!entry) {\n callback(null, createNotLoadedError(name))\n return () => { }\n }\n\n entry.callbacks.add(callback as WatchCallback<unknown>)\n\n return () => {\n const current = watchEntries.get(name)\n if (!current)\n return\n\n current.callbacks.delete(callback as WatchCallback<unknown>)\n if (current.callbacks.size === 0) {\n if (current.debounceTimer)\n clearTimeout(current.debounceTimer)\n current.watcher.close()\n watchEntries.delete(name)\n }\n }\n}\n\n/**\n * 停止监听(内部实现)。\n *\n * @param name - 配置名称;不传则停止所有监听并清空映射\n */\nfunction stopWatching(name?: string): void {\n if (name) {\n const entry = watchEntries.get(name)\n if (entry) {\n if (entry.debounceTimer)\n clearTimeout(entry.debounceTimer)\n entry.watcher.close()\n watchEntries.delete(name)\n }\n }\n else {\n for (const entry of watchEntries.values()) {\n if (entry.debounceTimer)\n clearTimeout(entry.debounceTimer)\n entry.watcher.close()\n }\n watchEntries.clear()\n }\n}\n\n/**\n * 清理缓存(同时停止对应监听)。\n *\n * @param name - 配置名称;不传则清理全部缓存并停止所有监听\n */\nfunction clearCache(name?: string): void {\n if (name) {\n configCache.delete(name)\n stopWatching(name)\n }\n else {\n configCache.clear()\n stopWatching()\n }\n}\n\n/**\n * 配置管理对象。\n *\n * @example\n * ```ts\n * const result = config.load('app', './config/app.yml')\n * if (result.success) {\n * const cfg = config.get('app')\n * }\n * ```\n */\nexport const config = {\n /**\n * 加载配置到缓存。\n *\n * 加载 YAML 文件并可选地用 Zod Schema 校验,成功后写入缓存。\n *\n * @param name - 配置名称(缓存 key)\n * @param filePath - YAML 文件路径\n * @param schema - 可选 Zod Schema(不传则跳过校验)\n * @returns 成功时返回解析后的配置数据;失败时返回 HaiError\n *\n * @example\n * ```ts\n * const result = config.load('core', './config/_core.yml', CoreConfigSchema)\n * if (result.success) {\n * // result.data 为校验后的配置\n * }\n * ```\n */\n load<T>(name: string, filePath: string, schema?: ZodType<T>): HaiResult<T> {\n return loadAndCache(name, filePath, schema)\n },\n\n /**\n * 验证已加载的配置数据。\n *\n * 对缓存中的配置数据重新用 Schema 校验,校验通过后更新缓存。\n *\n * @param name - 配置名称\n * @param schema - Zod 验证模式\n * @returns 校验结果;未加载时返回 NOT_LOADED,格式错误返回 VALIDATION_ERROR\n *\n * @example\n * ```ts\n * const result = config.validate('app', AppSchema)\n * if (!result.success) {\n * // result.error.code 可能为 NOT_LOADED 或 VALIDATION_ERROR\n * }\n * ```\n */\n validate<T>(name: string, schema: ZodType<T>): HaiResult<T> {\n return validateLoadedConfig(name, schema)\n },\n\n /**\n * 获取已加载的配置。\n *\n * @param name - 配置名称\n * @returns 配置数据;未加载时返回 undefined\n *\n * @example\n * ```ts\n * const cfg = config.get<CoreConfig>('core')\n * if (cfg) {\n * // 使用 cfg\n * }\n * ```\n */\n get<T>(name: string): T | undefined {\n return configCache.get(name)?.data as T | undefined\n },\n\n /**\n * 获取配置,不存在时抛出错误。\n *\n * @param name - 配置名称\n * @returns 配置数据\n * @throws 配置未加载时抛出 Error\n *\n * @example\n * ```ts\n * try {\n * const cfg = config.getOrThrow<CoreConfig>('core')\n * } catch (e) {\n * // 配置未加载\n * }\n * ```\n */\n getOrThrow<T>(name: string): T {\n const data = this.get<T>(name)\n if (data === undefined) {\n throw new Error(i18n.coreM('core_configNotLoaded', { params: { name } }))\n }\n return data\n },\n\n /**\n * 重新加载配置。\n *\n * 从磁盘重新读取配置文件并更新缓存,同时通知所有 watch 回调。\n *\n * @param name - 配置名称\n * @returns 重载结果;未加载时返回 NOT_LOADED\n *\n * @example\n * ```ts\n * const result = config.reload('app')\n * ```\n */\n reload(name: string): HaiResult<unknown> {\n return reloadAndNotify(name)\n },\n\n /**\n * 检查配置是否已加载。\n *\n * @param name - 配置名称\n * @returns 是否已加载到缓存\n *\n * @example\n * ```ts\n * if (config.has('db')) {\n * const dbCfg = config.get('db')\n * }\n * ```\n */\n has(name: string): boolean {\n return configCache.has(name)\n },\n\n /**\n * 清除配置缓存(同时停止对应监听)。\n *\n * @param name - 配置名称;不传则清除全部\n *\n * @example\n * ```ts\n * config.clear('app') // 清除单个\n * config.clear() // 清除全部\n * ```\n */\n clear(name?: string): void {\n clearCache(name)\n },\n\n /**\n * 获取所有已加载的配置名称。\n *\n * @returns 配置名称数组\n *\n * @example\n * ```ts\n * const names = config.keys() // ['core', 'db', 'app']\n * ```\n */\n keys(): string[] {\n return Array.from(configCache.keys())\n },\n\n /**\n * 监听配置文件变更并自动重载。\n *\n * 文件变更时自动重新加载并调用回调。配置未加载时立即回调 NOT_LOADED 错误。\n *\n * @param name - 配置名称\n * @param callback - 配置变更回调,接收新配置或错误\n * @returns 取消监听函数\n *\n * @example\n * ```ts\n * const unwatch = config.watch('app', (cfg, error) => {\n * if (error) { core.logger.error('reload failed', { error }); return }\n * core.logger.info('config updated', { cfg })\n * })\n * // 取消监听\n * unwatch()\n * ```\n */\n watch<T = unknown>(name: string, callback: WatchCallback<T>): () => void {\n return registerWatch(name, callback)\n },\n\n /**\n * 停止配置文件监听。\n *\n * @param name - 配置名称;不传则停止所有监听\n *\n * @example\n * ```ts\n * config.unwatch('app') // 停止单个\n * config.unwatch() // 停止全部\n * ```\n */\n unwatch(name?: string): void {\n stopWatching(name)\n },\n\n /**\n * 检查是否正在监听某个配置。\n *\n * @param name - 配置名称\n * @returns 是否有活跃的 watcher\n *\n * @example\n * ```ts\n * if (config.isWatching('app')) {\n * config.unwatch('app')\n * }\n * ```\n */\n isWatching(name: string): boolean {\n return watchEntries.has(name)\n },\n}\n\n/** config 子工具类型 */\nexport type ConfigFn = typeof config\n","/**\n * @h-ai/core — Logger(Node.js 版本,基于 pino)\n *\n * 提供统一的日志接口,Node.js 环境使用 pino 实现。\n * @module core-function-logger.node\n */\n\nimport type { LogFormat, LoggingConfig, LogLevel } from '../core-config.js'\nimport type { LogContext, Logger, LoggerFunctions, LoggerOptions } from '../core-types.js'\nimport { execSync } from 'node:child_process'\nimport { createRequire } from 'node:module'\nimport process from 'node:process'\nimport pino from 'pino'\nimport { sanitize as sanitizeUtils } from '../utils/core-util-sanitize.js'\n\n// ESM 场景下通过 createRequire 复用 CommonJS 的 resolve 能力,用来探测可选依赖是否存在。\nconst nodeRequire = createRequire(import.meta.url)\n\nif (process.platform === 'win32' && process.stdout.isTTY) {\n try {\n // 强制切换控制台代码页为 UTF-8(避免 GBK/GB2312 导致的乱码)\n execSync('chcp 65001 > nul', { stdio: 'ignore' })\n\n // 设置 stdout/stderr 编码为 UTF-8\n if (process.stdout.setDefaultEncoding) {\n process.stdout.setDefaultEncoding('utf8')\n }\n if (process.stderr.setDefaultEncoding) {\n process.stderr.setDefaultEncoding('utf8')\n }\n\n // 通过环境变量强制 Node.js 使用 UTF-8\n process.env.LANG = 'zh_CN.UTF-8'\n process.env.LC_ALL = 'zh_CN.UTF-8'\n process.env.PYTHONIOENCODING = 'utf-8'\n }\n // eslint-disable-next-line unused-imports/no-unused-vars\n catch (_e) {\n // 忽略错误,某些环境可能不支持\n }\n}\n\n// ─── 全局配置 ───\n\n/** 全局日志级别(默认 'info') */\nlet globalLevel: LogLevel = 'info'\n\n/** 全局日志格式(默认 'pretty',适合开发环境) */\nlet globalFormat: LogFormat = 'pretty'\n\n/** 全局默认上下文(每条日志自动附带) */\nlet globalContext: Record<string, unknown> = {}\n\n/** 全局脱敏字段路径列表(如 ['password', 'token']) */\nlet globalRedact: string[] = []\n\n/** 默认 Logger 单例缓存 */\nlet defaultLogger: Logger | null = null\n\n/**\n * 配置全局 Logger 选项。\n *\n * @param config - 日志配置\n *\n * @example\n * ```ts\n * logger.configureLogger({ level: 'debug' })\n * ```\n */\nfunction configureLogger(config: Partial<LoggingConfig>): void {\n if (config.level)\n globalLevel = config.level\n if (config.format)\n globalFormat = config.format\n if (config.context)\n globalContext = { ...globalContext, ...config.context }\n if (config.redact)\n globalRedact = config.redact\n // 重置默认 logger 缓存,使下次 getLogger() 返回新配置的实例\n defaultLogger = null\n}\n\n/**\n * 设置全局日志级别。\n *\n * @param level - 日志级别\n *\n * @example\n * ```ts\n * logger.setLogLevel('warn')\n * ```\n */\nfunction setLogLevel(level: LogLevel): void {\n globalLevel = level\n}\n\n/**\n * 获取当前全局日志级别。\n *\n * @example\n * ```ts\n * const level = logger.getLogLevel()\n * ```\n */\nfunction getLogLevel(): LogLevel {\n return globalLevel\n}\n\nfunction sanitizeLogContext(ctx?: LogContext): LogContext | undefined {\n if (!ctx || Object.keys(ctx).length === 0) {\n return ctx\n }\n\n return sanitizeUtils.sanitizeSensitiveFields(ctx) as LogContext\n}\n\n// ─── Logger 实现 ───\n\n/**\n * 包装 pino 实例为统一 Logger 接口。\n *\n * 将 pino 的原生方法映射为 Logger 接口,自动合并上下文。\n *\n * @param pinoLogger - pino 实例\n * @param context - 基础上下文(会与每次调用时的 ctx 合并)\n * @returns 统一 Logger 实例\n */\nfunction wrapPino(pinoLogger: pino.Logger, context: Record<string, unknown>): Logger {\n return {\n trace(message: string, ctx?: LogContext) {\n pinoLogger.trace(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n debug(message: string, ctx?: LogContext) {\n pinoLogger.debug(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n info(message: string, ctx?: LogContext) {\n pinoLogger.info(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n warn(message: string, ctx?: LogContext) {\n pinoLogger.warn(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n error(message: string, ctx?: LogContext) {\n pinoLogger.error(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n fatal(message: string, ctx?: LogContext) {\n pinoLogger.fatal(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n child(childContext: Record<string, unknown>): Logger {\n const sanitizedChildContext = sanitizeLogContext(childContext) ?? {}\n return wrapPino(pinoLogger.child(sanitizedChildContext), { ...context, ...sanitizedChildContext })\n },\n }\n}\n\n/**\n * 创建 Logger 实例。\n *\n * @param options - Logger 选项\n * @returns Logger 实例\n *\n * @example\n * ```ts\n * const appLogger = logger.createLogger({ name: 'api', level: 'info' })\n * appLogger.info('ready')\n * ```\n */\nfunction createLogger(options: LoggerOptions = {}): Logger {\n const level = options.level ?? globalLevel\n const format = options.format ?? globalFormat\n const context = { ...globalContext, ...options.context }\n\n // 先构造一份与输出介质无关的基础配置,后面再按 transport 能力决定是否启用 pretty。\n const pinoOptions: pino.LoggerOptions = {\n level,\n name: options.name,\n formatters: {\n level: label => ({ level: label }),\n },\n }\n\n // redact 支持\n if (globalRedact.length > 0) {\n pinoOptions.redact = {\n paths: globalRedact,\n censor: '[REDACTED]',\n }\n }\n\n let pinoInstance: pino.Logger\n\n if (format === 'pretty' && isPrettyTransportAvailable()) {\n // 只有在 pino-pretty 可解析时才挂载 transport,避免可选依赖缺失直接导致 logger 初始化失败。\n try {\n pinoInstance = pino({\n ...pinoOptions,\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'SYS:standard',\n ignore: 'pid,hostname',\n },\n },\n })\n }\n catch (error) {\n // 其他初始化异常应重新抛出,便于排查\n if (isPrettyTransportUnavailable(error)) {\n pinoInstance = pino(pinoOptions)\n }\n else {\n throw error\n }\n }\n }\n else {\n pinoInstance = pino(pinoOptions)\n }\n\n return wrapPino(pinoInstance, context)\n}\n\nfunction isPrettyTransportAvailable(): boolean {\n try {\n // pino-pretty 是可选依赖,这里用 resolve 做能力探测,避免在缺失场景下直接 import 失败。\n nodeRequire.resolve('pino-pretty')\n return true\n }\n catch {\n return false\n }\n}\n\nfunction isPrettyTransportUnavailable(error: unknown): boolean {\n const message\n = error instanceof Error\n ? error.message\n : typeof error === 'string'\n ? error\n : ''\n\n const normalized = message.toLowerCase()\n\n return normalized.includes('pino-pretty')\n && (normalized.includes('cannot find module')\n || normalized.includes('unable to determine transport target')\n || normalized.includes('cannot load')\n || normalized.includes('not found'))\n}\n\n// ─── 默认 Logger 实例 ───\n\n/**\n * 获取默认 Logger 实例(单例)。\n *\n * @example\n * ```ts\n * const defaultLogger = logger.getLogger()\n * ```\n */\nfunction getLogger(): Logger {\n if (!defaultLogger) {\n defaultLogger = createLogger()\n }\n return defaultLogger\n}\n\n// ─── 对外出口 ───\n\n/**\n * Node.js Logger 函数集合。\n *\n * @example\n * ```ts\n * logger.createLogger({ name: 'service' }).info('boot')\n * ```\n */\nexport const logger: LoggerFunctions = {\n configureLogger,\n setLogLevel,\n getLogLevel,\n createLogger,\n getLogger,\n}\n","/**\n * @h-ai/core — Core 服务聚合(Node.js)\n *\n * 提供 Node.js 环境的 core 对象,聚合常用功能。 所有功能统一通过 core 对象访问,并提供配置加载能力。\n * @module core-main.node\n */\n\nimport type { CoreFunctions, CoreOptions } from './core-types.js'\nimport { existsSync, readdirSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { CoreConfigSchema } from './core-config.js'\nimport { createCore } from './core-main.js'\nimport { config } from './functions/core-function-config.node.js'\nimport { logger } from './functions/core-function-logger.node.js'\n\nconst YAML_EXTENSION_REGEX = /\\.ya?ml$/\ntype NodeCoreFunctions = CoreFunctions & {\n readonly config: typeof config\n readonly init: typeof initCore\n}\n\n// ─── Core 实例 ───\n\n/**\n * 创建 Node.js 版本的 core 对象。\n *\n * @example\n * ```ts\n * import { core } from '@h-ai/core'\n * core.logger.info('ready')\n * ```\n */\nfunction createNodeCore(): NodeCoreFunctions {\n const baseCore = createCore({\n createLogger: logger.createLogger,\n getLogger: logger.getLogger,\n configureLogger: logger.configureLogger,\n setLogLevel: logger.setLogLevel,\n getLogLevel: logger.getLogLevel,\n })\n\n // 扩展 config 和 init 功能\n return {\n ...baseCore,\n /** Zod 校验错误 → i18n 消息映射工具(kit / serv / api-client 共享)。 */\n zodValidation: baseCore.zodValidation,\n /** 配置管理 */\n config,\n /** 初始化 Core */\n init: initCore,\n }\n}\n\n/**\n * Core 服务对象 - 聚合常用功能(Node.js)。\n *\n * @example\n * ```ts\n * import { core } from '@h-ai/core'\n * core.init({ configDir: './config' })\n * ```\n */\nexport const core: NodeCoreFunctions = createNodeCore()\n\n// ─── Initialization ───\n\n/**\n * 配置加载项(描述单个待加载的配置文件)。\n */\ninterface ConfigLoadItem {\n /** 配置名称(用作缓存 key,如 'core'、'db'、'app') */\n name: string\n /** 配置文件绝对路径 */\n filePath: string\n}\n\n/**\n * 扫描配置目录并构建配置加载项列表。\n *\n * 约定:\n * - 以 `_` 开头的文件为内置模块配置(如 `_core.yml` → name='core')\n * - 其他文件为业务配置(如 `app.yml` → name='app')\n *\n * @param configDir - 配置目录路径\n * @returns 配置加载项列表;目录不存在时返回空数组并输出警告\n *\n * @example\n * ```ts\n * const items = scanConfigDir('./config')\n * // [{ name: 'core', filePath: './config/_core.yml' }, { name: 'app', filePath: './config/app.yml' }]\n * ```\n */\nfunction scanConfigDir(\n configDir: string,\n): ConfigLoadItem[] {\n const logger = core.logger\n const items: ConfigLoadItem[] = []\n\n if (!existsSync(configDir)) {\n logger.warn(`[core] Config directory not found: ${configDir}`)\n return items\n }\n\n const files = readdirSync(configDir).filter(f =>\n f.endsWith('.yml') || f.endsWith('.yaml'),\n )\n\n for (const file of files) {\n const filePath = join(configDir, file)\n const baseName = file.replace(YAML_EXTENSION_REGEX, '')\n\n // 判断是否为内置模块配置(以 _ 开头)\n if (baseName.startsWith('_')) {\n const moduleName = baseName.slice(1) // 去掉 _ 前缀\n items.push({\n name: moduleName,\n filePath,\n })\n }\n else {\n // 业务配置(文件名作为配置名)\n items.push({\n name: baseName,\n filePath,\n })\n }\n }\n return items\n}\n\n/**\n * 初始化 Core(内部实现,通过 `core.init()` 调用)。\n *\n * 执行流程:\n * 1. 配置日志(若提供 `options.logging`)\n * 2. 扫描并加载配置目录中的所有 YAML 文件\n * 3. 启用配置文件监听(若 `options.watchConfig` 为 true)\n *\n * @param options - 初始化选项\n *\n * @example\n * ```ts\n * core.init({ configDir: './config', watchConfig: true })\n * ```\n */\nfunction initCore(options: CoreOptions = {}): void {\n const startTime = Date.now()\n const logger = core.logger\n\n // 1. Configure logging\n if (options.logging) {\n core.logger.configure(options.logging)\n }\n\n logger.info('[core] Initializing...')\n\n let configItems: ConfigLoadItem[] = []\n\n if (options.configDir) {\n // 约定优于配置模式\n configItems = scanConfigDir(options.configDir)\n }\n\n // 2. Load config files\n for (const item of configItems) {\n if (item.name === 'core') {\n const result = config.load(item.name, item.filePath, CoreConfigSchema)\n if (result.success) {\n if (!options.logging) {\n core.logger.configure(result.data.logging || {})\n }\n logger.info(`[core] Config loaded: ${item.name} <- ${item.filePath}`)\n }\n else {\n logger.error(`[core] Config load failed: ${item.name}`, {\n error: result.error,\n })\n }\n }\n else {\n const result = config.load(item.name, item.filePath)\n if (result.success) {\n logger.info(`[core] Config loaded: ${item.name} <- ${item.filePath}`)\n }\n else {\n logger.error(`[core] Config load failed: ${item.name}`, {\n error: result.error,\n })\n }\n }\n }\n\n // 3. Enable config file watching\n if (options.watchConfig && configItems.length > 0) {\n setupConfigWatch(configItems)\n }\n\n const duration = Date.now() - startTime\n logger.info(`[core] Initialized (${duration}ms)`)\n}\n\n/**\n * 启用配置文件监听。\n *\n * 为每个已加载的配置项注册文件 watcher,变更时自动重载并输出日志。\n *\n * @param configs - 需要监听的配置项列表\n */\nfunction setupConfigWatch(configs: ConfigLoadItem[]): void {\n const logger = core.logger\n\n for (const item of configs) {\n config.watch(item.name, (_config, error) => {\n if (error) {\n logger.error(`[core] Config reload failed: ${item.name}`, { error })\n return\n }\n logger.info(`[core] Config reloaded: ${item.name}`)\n })\n\n logger.debug(`[core] Config watch enabled: ${item.name}`)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/functions/core-function-config.node.ts","../src/functions/core-function-logger.node.ts","../src/core-main.node.ts"],"names":["process","envValue","result","config","logger","existsSync"],"mappings":"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","file":"node.js","sourcesContent":["/**\n * @h-ai/core — 配置管理(Node.js 专用)\n *\n * 提供 YAML 配置文件加载、约定式环境变量映射、显式环境变量插值、缓存管理。\n * @module core-function-config.node\n */\n\nimport type { ZodType } from 'zod'\nimport type { HaiError, HaiResult } from '../core-types.js'\n\nimport { existsSync, readFileSync, watch } from 'node:fs'\nimport process from 'node:process'\nimport { parse } from 'yaml'\n\n// ─── 配置文件监听 ───\n\nimport { err, HaiConfigError, ok } from '../core-types.js'\nimport { i18n } from '../i18n/core-i18n-utils.js'\nimport { typeUtils } from '../utils/core-util-type.js'\n\n/** 缓存项(存储已加载的配置及其元信息) */\ninterface CacheEntry<T = unknown> {\n /** 解析后的配置数据 */\n data: T\n /** 配置文件路径 */\n filePath: string\n /** Zod 校验 Schema(重载时复用,无 Schema 加载时为 undefined) */\n schema?: ZodType<T>\n /** 加载时间戳(毫秒) */\n loadedAt: number\n}\n\n// ─── 内部工具 ───\n\n/** 环境变量插值正则(支持 ${VAR} 与 ${VAR:default}) */\nconst ENV_VAR_PATTERN = /\\$\\{([^}:]+)(?::([^}]*))?\\}/g\n\n/** 判断整个字符串是否恰好是单个 ${VAR} 或 ${VAR:default}(用于类型还原) */\nconst FULL_VAR_PATTERN = /^\\$\\{[^}:]+(?::[^}]*)?\\}$/\n\n/**\n * 将环境变量字符串按 YAML 标量规则还原类型。\n *\n * @param value - 环境变量原始字符串\n * @returns 空字符串保持不变;其余值尽量还原为 YAML 原生类型\n */\nfunction parseEnvValue(value: string): unknown {\n // YAML 会把空文档解析为 null;空环境变量仍是明确的字符串值,不能改变其类型。\n if (value === '')\n return ''\n\n try {\n const parsed = parse(value)\n return parsed === undefined ? value : parsed\n }\n catch {\n return value\n }\n}\n\n/**\n * 将配置名或 YAML 路径片段规范化为环境变量片段。\n *\n * camelCase 不拆词,例如 apiKey → APIKEY;非字母数字字符统一为下划线。\n *\n * @param segment - 配置名、键名或数组索引\n * @returns 可用于环境变量名的片段\n */\nfunction normalizeEnvSegment(segment: string): string {\n return segment\n .replace(/[^a-z0-9]+/gi, '_')\n .replace(/^_+|_+$/g, '')\n .toUpperCase()\n}\n\n/**\n * 构建配置项的约定环境变量名。\n *\n * @example `ai` + `llm.apiKey` → `HAI_AI_LLM_APIKEY`\n *\n * @param name - 配置名称\n * @param path - YAML 中从根到叶子的键路径;数组索引也作为一段\n * @returns 以 HAI 开头的环境变量名\n */\nfunction buildConventionEnvName(name: string, path: string[]): string {\n return ['HAI', name, ...path]\n .map(normalizeEnvSegment)\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * 解析配置中的环境变量。\n *\n * 每个叶子配置项都会优先读取 `HAI_<配置名>_<YAML 路径>`;\n * 约定变量不存在时再解析显式 `${VAR}`,显式语法用于指定特殊变量名。\n *\n * @param value - 任意配置值(字符串、数组、对象或原始值)\n * @param name - 配置名称\n * @param path - 当前值的 YAML 路径\n * @returns 插值后的结果;当环境变量缺失且未提供默认值时返回 ENV_VAR_MISSING 错误\n */\nfunction resolveEnv(value: unknown, name: string, path: string[] = []): HaiResult<unknown> {\n if (typeof value === 'string') {\n const conventionEnvValue = process.env[buildConventionEnvName(name, path)]\n if (conventionEnvValue !== undefined)\n return ok(parseEnvValue(conventionEnvValue))\n\n ENV_VAR_PATTERN.lastIndex = 0\n const hasExplicitEnv = ENV_VAR_PATTERN.test(value)\n ENV_VAR_PATTERN.lastIndex = 0\n\n if (!hasExplicitEnv)\n return ok(value)\n\n let result = value\n // 避免在 while 条件中赋值(满足 lint 规则 no-cond-assign)\n while (true) {\n const match = ENV_VAR_PATTERN.exec(value)\n if (!match)\n break\n\n const [fullMatch, varName, defaultValue] = match\n const envValue = process.env[varName]\n\n // 未提供默认值且环境变量不存在时,返回错误\n if (envValue === undefined && defaultValue === undefined) {\n return err(HaiConfigError.CONFIG_ENV_VAR_MISSING, i18n.coreM('core_configEnvVarMissing', { params: { varName } }))\n }\n result = result.replace(fullMatch, envValue ?? defaultValue ?? '')\n }\n\n // 当原值整体是单个 ${VAR:default} 时,插值结果需还原为 YAML 原生类型。\n if (FULL_VAR_PATTERN.test(value))\n return ok(parseEnvValue(result))\n\n return ok(result)\n }\n\n if (Array.isArray(value)) {\n const results: unknown[] = []\n for (const [index, item] of value.entries()) {\n const r = resolveEnv(item, name, [...path, String(index)])\n if (!r.success)\n return r\n results.push(r.data)\n }\n return ok(results)\n }\n\n if (typeUtils.isObject(value)) {\n const results: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(value)) {\n const r = resolveEnv(v, name, [...path, k])\n if (!r.success)\n return r\n results[k] = r.data\n }\n return ok(results)\n }\n\n const envValue = process.env[buildConventionEnvName(name, path)]\n return ok(envValue === undefined ? value : parseEnvValue(envValue))\n}\n\n// ─── 配置管理器 ───\n\n/** 配置缓存 */\nconst configCache = new Map<string, CacheEntry>()\n\n/**\n * 监听回调类型。\n *\n * @template T - 配置数据类型\n *\n * @example\n * ```ts\n * const callback: WatchCallback<AppConfig> = (cfg, error) => {\n * if (error) { core.logger.error('Config reload failed', { error }); return }\n * // 使用更新后的 cfg\n * }\n * ```\n */\nexport type WatchCallback<T = unknown> = (config: T | null, error?: HaiError) => void\n\n/** 配置监听条目(包含文件 watcher 和回调集合) */\ninterface WatchEntry {\n /** fs.watch 返回的 watcher 实例 */\n watcher: ReturnType<typeof watch>\n /** 已注册的回调函数集合 */\n callbacks: Set<WatchCallback<unknown>>\n /** 防抖定时器(用于 stopWatching 时清理) */\n debounceTimer: ReturnType<typeof setTimeout> | null\n}\n\n/** 配置监听映射 */\nconst watchEntries = new Map<string, WatchEntry>()\n\n/**\n * 创建未加载错误。\n *\n * @param name - 配置名称\n * @returns HaiError,错误码为 NOT_LOADED\n */\nfunction createNotLoadedError(name: string): HaiError {\n const result = err(HaiConfigError.CONFIG_NOT_LOADED, i18n.coreM('core_configNotLoaded', { params: { name } }))\n if (!result.success)\n return result.error\n\n throw new Error('unreachable')\n}\n\n/**\n * 通知监听回调。\n *\n * @param name - 配置名称\n * @param result - 重载结果(成功时传配置数据,失败时传错误)\n */\nfunction notifyWatchCallbacks(name: string, result: HaiResult<unknown>): void {\n const entry = watchEntries.get(name)\n if (!entry)\n return\n\n if (result.success) {\n for (const callback of entry.callbacks) {\n try {\n callback(result.data, undefined)\n }\n catch { /* 隔离单个回调异常,不影响其他回调 */ }\n }\n }\n else {\n for (const callback of entry.callbacks) {\n try {\n callback(null, result.error)\n }\n catch { /* 隔离单个回调异常,不影响其他回调 */ }\n }\n }\n}\n\n/**\n * 加载 YAML 配置文件(不带 Schema 验证)。\n *\n * 流程:检查文件存在 → 读取 YAML → 约定式环境变量映射与显式插值。\n *\n * @param name - 配置名称,用于生成 `HAI_<配置名>_<YAML 路径>` 环境变量名\n * @param filePath - YAML 文件路径\n * @returns 解析结果;可能的错误码:FILE_NOT_FOUND / PARSE_ERROR / ENV_VAR_MISSING\n */\nfunction loadYaml(name: string, filePath: string): HaiResult<unknown> {\n if (!existsSync(filePath)) {\n return err(HaiConfigError.CONFIG_FILE_NOT_FOUND, i18n.coreM('core_configFileNotExist', { params: { filePath } }))\n }\n\n try {\n const content = readFileSync(filePath, 'utf-8')\n const parsed = parse(content)\n return resolveEnv(parsed, name)\n }\n catch (error) {\n return err(HaiConfigError.CONFIG_PARSE_ERROR, i18n.coreM('core_configParseFailed', { params: { filePath } }), error)\n }\n}\n\n/**\n * 加载并验证配置文件。\n *\n * 流程:加载 YAML → 环境变量映射与插值 → Zod Schema 校验。\n *\n * @param name - 配置名称\n * @param filePath - YAML 文件路径\n * @param schema - Zod 校验 Schema\n * @returns 校验后的配置数据;可能的错误码:FILE_NOT_FOUND / PARSE_ERROR / ENV_VAR_MISSING / VALIDATION_ERROR\n */\nfunction loadConfig<T>(\n name: string,\n filePath: string,\n schema: ZodType<T>,\n): HaiResult<T> {\n const yamlResult = loadYaml(name, filePath)\n if (!yamlResult.success)\n return yamlResult\n\n const parseResult = schema.safeParse(yamlResult.data)\n if (!parseResult.success) {\n return err(HaiConfigError.CONFIG_VALIDATION_ERROR, i18n.coreM('core_configValidationFailed'), parseResult.error.issues)\n }\n\n return ok(parseResult.data)\n}\n\n/**\n * 加载配置并写入缓存。\n *\n * @param name - 配置名称(缓存 key)\n * @param filePath - YAML 文件路径\n * @param schema - 可选 Zod Schema(不传则跳过校验)\n * @returns 加载结果;成功时同时更新缓存\n */\nfunction loadAndCache<T>(\n name: string,\n filePath: string,\n schema?: ZodType<T>,\n): HaiResult<T> {\n const result = schema ? loadConfig(name, filePath, schema) : loadYaml(name, filePath) as HaiResult<T>\n if (result.success) {\n configCache.set(name, {\n data: result.data,\n filePath,\n schema: schema as ZodType<unknown> | undefined,\n loadedAt: Date.now(),\n })\n }\n return result\n}\n\n/**\n * 校验已加载的配置并写回缓存。\n *\n * 从缓存中取出原始数据重新用 Schema 校验,校验通过后更新缓存。\n *\n * @param name - 配置名称\n * @param schema - Zod Schema\n * @returns 校验结果;未加载时返回 NOT_LOADED,校验失败返回 VALIDATION_ERROR\n */\nfunction validateLoadedConfig<T>(name: string, schema: ZodType<T>): HaiResult<T> {\n const entry = configCache.get(name)\n if (!entry) {\n return err(createNotLoadedError(name))\n }\n\n const parseResult = schema.safeParse(entry.data)\n if (!parseResult.success) {\n return err(HaiConfigError.CONFIG_VALIDATION_ERROR, i18n.coreM('core_configValidationFailed'), parseResult.error.issues)\n }\n\n const validated = parseResult.data\n configCache.set(name, {\n ...entry,\n data: validated,\n schema,\n loadedAt: Date.now(),\n })\n\n return ok(validated)\n}\n\n/**\n * 重新加载配置并通知监听器。\n *\n * 从缓存中获取文件路径和 Schema,重新加载并触发所有 watch 回调。\n *\n * @param name - 配置名称\n * @returns 重载结果;未加载时返回 NOT_LOADED\n */\nfunction reloadAndNotify(name: string): HaiResult<unknown> {\n const entry = configCache.get(name)\n if (!entry) {\n const result = err(createNotLoadedError(name))\n notifyWatchCallbacks(name, result)\n return result\n }\n\n // 无 Schema 时直接加载 YAML(不做校验),避免 schema 为 undefined 导致运行时崩溃\n const result = entry.schema ? loadConfig(name, entry.filePath, entry.schema) : loadYaml(name, entry.filePath)\n if (result.success) {\n configCache.set(name, {\n ...entry,\n data: result.data,\n loadedAt: Date.now(),\n })\n }\n notifyWatchCallbacks(name, result)\n return result\n}\n\n/**\n * 启动配置文件监听。\n *\n * 使用 `fs.watch` 监听文件变更,变更时自动重载并通知回调。\n * 同一配置名只会创建一个 watcher,多次调用返回同一实例。\n *\n * @param name - 配置名称\n * @returns WatchEntry 实例;配置未加载时返回 null\n */\nfunction startFileWatcher(name: string): WatchEntry | null {\n const existing = watchEntries.get(name)\n if (existing)\n return existing\n\n const entry = configCache.get(name)\n if (!entry)\n return null\n\n try {\n const watchEntry: WatchEntry = {\n watcher: null!,\n callbacks: new Set(),\n debounceTimer: null,\n }\n\n // 防抖定时器:fs.watch 可能对同一次文件保存触发多次 'change' 事件\n const watcher = watch(entry.filePath, (eventType) => {\n if (eventType === 'change') {\n if (watchEntry.debounceTimer)\n clearTimeout(watchEntry.debounceTimer)\n watchEntry.debounceTimer = setTimeout(() => {\n watchEntry.debounceTimer = null\n reloadAndNotify(name)\n }, 100)\n }\n })\n\n watchEntry.watcher = watcher\n watchEntries.set(name, watchEntry)\n return watchEntry\n }\n catch {\n return null\n }\n}\n\n/**\n * 注册监听回调。\n *\n * 启动文件 watcher(若尚未启动)并注册回调。\n * 配置未加载时立即回调 NOT_LOADED 错误。\n *\n * @param name - 配置名称\n * @param callback - 变更回调\n * @returns 取消监听函数;调用后自动清理(无回调时关闭 watcher)\n */\nfunction registerWatch<T>(name: string, callback: WatchCallback<T>): () => void {\n const entry = startFileWatcher(name)\n if (!entry) {\n callback(null, createNotLoadedError(name))\n return () => { }\n }\n\n entry.callbacks.add(callback as WatchCallback<unknown>)\n\n return () => {\n const current = watchEntries.get(name)\n if (!current)\n return\n\n current.callbacks.delete(callback as WatchCallback<unknown>)\n if (current.callbacks.size === 0) {\n if (current.debounceTimer)\n clearTimeout(current.debounceTimer)\n current.watcher.close()\n watchEntries.delete(name)\n }\n }\n}\n\n/**\n * 停止监听(内部实现)。\n *\n * @param name - 配置名称;不传则停止所有监听并清空映射\n */\nfunction stopWatching(name?: string): void {\n if (name) {\n const entry = watchEntries.get(name)\n if (entry) {\n if (entry.debounceTimer)\n clearTimeout(entry.debounceTimer)\n entry.watcher.close()\n watchEntries.delete(name)\n }\n }\n else {\n for (const entry of watchEntries.values()) {\n if (entry.debounceTimer)\n clearTimeout(entry.debounceTimer)\n entry.watcher.close()\n }\n watchEntries.clear()\n }\n}\n\n/**\n * 清理缓存(同时停止对应监听)。\n *\n * @param name - 配置名称;不传则清理全部缓存并停止所有监听\n */\nfunction clearCache(name?: string): void {\n if (name) {\n configCache.delete(name)\n stopWatching(name)\n }\n else {\n configCache.clear()\n stopWatching()\n }\n}\n\n/**\n * 配置管理对象。\n *\n * @example\n * ```ts\n * const result = config.load('app', './config/app.yml')\n * if (result.success) {\n * const cfg = config.get('app')\n * }\n * ```\n */\nexport const config = {\n /**\n * 加载配置到缓存。\n *\n * 加载 YAML 文件并可选地用 Zod Schema 校验,成功后写入缓存。\n *\n * @param name - 配置名称(缓存 key)\n * @param filePath - YAML 文件路径\n * @param schema - 可选 Zod Schema(不传则跳过校验)\n * @returns 成功时返回解析后的配置数据;失败时返回 HaiError\n *\n * @example\n * ```ts\n * const result = config.load('core', './config/_core.yml', CoreConfigSchema)\n * if (result.success) {\n * // result.data 为校验后的配置\n * }\n * ```\n */\n load<T>(name: string, filePath: string, schema?: ZodType<T>): HaiResult<T> {\n return loadAndCache(name, filePath, schema)\n },\n\n /**\n * 验证已加载的配置数据。\n *\n * 对缓存中的配置数据重新用 Schema 校验,校验通过后更新缓存。\n *\n * @param name - 配置名称\n * @param schema - Zod 验证模式\n * @returns 校验结果;未加载时返回 NOT_LOADED,格式错误返回 VALIDATION_ERROR\n *\n * @example\n * ```ts\n * const result = config.validate('app', AppSchema)\n * if (!result.success) {\n * // result.error.code 可能为 NOT_LOADED 或 VALIDATION_ERROR\n * }\n * ```\n */\n validate<T>(name: string, schema: ZodType<T>): HaiResult<T> {\n return validateLoadedConfig(name, schema)\n },\n\n /**\n * 获取已加载的配置。\n *\n * @param name - 配置名称\n * @returns 配置数据;未加载时返回 undefined\n *\n * @example\n * ```ts\n * const cfg = config.get<CoreConfig>('core')\n * if (cfg) {\n * // 使用 cfg\n * }\n * ```\n */\n get<T>(name: string): T | undefined {\n return configCache.get(name)?.data as T | undefined\n },\n\n /**\n * 获取配置,不存在时抛出错误。\n *\n * @param name - 配置名称\n * @returns 配置数据\n * @throws 配置未加载时抛出 Error\n *\n * @example\n * ```ts\n * try {\n * const cfg = config.getOrThrow<CoreConfig>('core')\n * } catch (e) {\n * // 配置未加载\n * }\n * ```\n */\n getOrThrow<T>(name: string): T {\n const data = this.get<T>(name)\n if (data === undefined) {\n throw new Error(i18n.coreM('core_configNotLoaded', { params: { name } }))\n }\n return data\n },\n\n /**\n * 重新加载配置。\n *\n * 从磁盘重新读取配置文件并更新缓存,同时通知所有 watch 回调。\n *\n * @param name - 配置名称\n * @returns 重载结果;未加载时返回 NOT_LOADED\n *\n * @example\n * ```ts\n * const result = config.reload('app')\n * ```\n */\n reload(name: string): HaiResult<unknown> {\n return reloadAndNotify(name)\n },\n\n /**\n * 检查配置是否已加载。\n *\n * @param name - 配置名称\n * @returns 是否已加载到缓存\n *\n * @example\n * ```ts\n * if (config.has('db')) {\n * const dbCfg = config.get('db')\n * }\n * ```\n */\n has(name: string): boolean {\n return configCache.has(name)\n },\n\n /**\n * 清除配置缓存(同时停止对应监听)。\n *\n * @param name - 配置名称;不传则清除全部\n *\n * @example\n * ```ts\n * config.clear('app') // 清除单个\n * config.clear() // 清除全部\n * ```\n */\n clear(name?: string): void {\n clearCache(name)\n },\n\n /**\n * 获取所有已加载的配置名称。\n *\n * @returns 配置名称数组\n *\n * @example\n * ```ts\n * const names = config.keys() // ['core', 'db', 'app']\n * ```\n */\n keys(): string[] {\n return Array.from(configCache.keys())\n },\n\n /**\n * 监听配置文件变更并自动重载。\n *\n * 文件变更时自动重新加载并调用回调。配置未加载时立即回调 NOT_LOADED 错误。\n *\n * @param name - 配置名称\n * @param callback - 配置变更回调,接收新配置或错误\n * @returns 取消监听函数\n *\n * @example\n * ```ts\n * const unwatch = config.watch('app', (cfg, error) => {\n * if (error) { core.logger.error('reload failed', { error }); return }\n * core.logger.info('config updated', { cfg })\n * })\n * // 取消监听\n * unwatch()\n * ```\n */\n watch<T = unknown>(name: string, callback: WatchCallback<T>): () => void {\n return registerWatch(name, callback)\n },\n\n /**\n * 停止配置文件监听。\n *\n * @param name - 配置名称;不传则停止所有监听\n *\n * @example\n * ```ts\n * config.unwatch('app') // 停止单个\n * config.unwatch() // 停止全部\n * ```\n */\n unwatch(name?: string): void {\n stopWatching(name)\n },\n\n /**\n * 检查是否正在监听某个配置。\n *\n * @param name - 配置名称\n * @returns 是否有活跃的 watcher\n *\n * @example\n * ```ts\n * if (config.isWatching('app')) {\n * config.unwatch('app')\n * }\n * ```\n */\n isWatching(name: string): boolean {\n return watchEntries.has(name)\n },\n}\n\n/** config 子工具类型 */\nexport type ConfigFn = typeof config\n","/**\n * @h-ai/core — Logger(Node.js 版本,基于 pino)\n *\n * 提供统一的日志接口,Node.js 环境使用 pino 实现。\n * @module core-function-logger.node\n */\n\nimport type { LogFormat, LoggingConfig, LogLevel } from '../core-config.js'\nimport type { LogContext, Logger, LoggerFunctions, LoggerOptions } from '../core-types.js'\nimport { execSync } from 'node:child_process'\nimport { createRequire } from 'node:module'\nimport process from 'node:process'\nimport pino from 'pino'\nimport { sanitize as sanitizeUtils } from '../utils/core-util-sanitize.js'\n\n// ESM 场景下通过 createRequire 复用 CommonJS 的 resolve 能力,用来探测可选依赖是否存在。\nconst nodeRequire = createRequire(import.meta.url)\n\nif (process.platform === 'win32' && process.stdout.isTTY) {\n try {\n // 强制切换控制台代码页为 UTF-8(避免 GBK/GB2312 导致的乱码)\n execSync('chcp 65001 > nul', { stdio: 'ignore' })\n\n // 设置 stdout/stderr 编码为 UTF-8\n if (process.stdout.setDefaultEncoding) {\n process.stdout.setDefaultEncoding('utf8')\n }\n if (process.stderr.setDefaultEncoding) {\n process.stderr.setDefaultEncoding('utf8')\n }\n\n // 通过环境变量强制 Node.js 使用 UTF-8\n process.env.LANG = 'zh_CN.UTF-8'\n process.env.LC_ALL = 'zh_CN.UTF-8'\n process.env.PYTHONIOENCODING = 'utf-8'\n }\n // eslint-disable-next-line unused-imports/no-unused-vars\n catch (_e) {\n // 忽略错误,某些环境可能不支持\n }\n}\n\n// ─── 全局配置 ───\n\n/** 全局日志级别(默认 'info') */\nlet globalLevel: LogLevel = 'info'\n\n/** 全局日志格式(默认 'pretty',适合开发环境) */\nlet globalFormat: LogFormat = 'pretty'\n\n/** 全局默认上下文(每条日志自动附带) */\nlet globalContext: Record<string, unknown> = {}\n\n/** 全局脱敏字段路径列表(如 ['password', 'token']) */\nlet globalRedact: string[] = []\n\n/** 默认 Logger 单例缓存 */\nlet defaultLogger: Logger | null = null\n\n/**\n * 配置全局 Logger 选项。\n *\n * @param config - 日志配置\n *\n * @example\n * ```ts\n * logger.configureLogger({ level: 'debug' })\n * ```\n */\nfunction configureLogger(config: Partial<LoggingConfig>): void {\n if (config.level)\n globalLevel = config.level\n if (config.format)\n globalFormat = config.format\n if (config.context)\n globalContext = { ...globalContext, ...config.context }\n if (config.redact)\n globalRedact = config.redact\n // 重置默认 logger 缓存,使下次 getLogger() 返回新配置的实例\n defaultLogger = null\n}\n\n/**\n * 设置全局日志级别。\n *\n * @param level - 日志级别\n *\n * @example\n * ```ts\n * logger.setLogLevel('warn')\n * ```\n */\nfunction setLogLevel(level: LogLevel): void {\n globalLevel = level\n}\n\n/**\n * 获取当前全局日志级别。\n *\n * @example\n * ```ts\n * const level = logger.getLogLevel()\n * ```\n */\nfunction getLogLevel(): LogLevel {\n return globalLevel\n}\n\nfunction sanitizeLogContext(ctx?: LogContext): LogContext | undefined {\n if (!ctx || Object.keys(ctx).length === 0) {\n return ctx\n }\n\n return sanitizeUtils.sanitizeSensitiveFields(ctx) as LogContext\n}\n\n// ─── Logger 实现 ───\n\n/**\n * 包装 pino 实例为统一 Logger 接口。\n *\n * 将 pino 的原生方法映射为 Logger 接口,自动合并上下文。\n *\n * @param pinoLogger - pino 实例\n * @param context - 基础上下文(会与每次调用时的 ctx 合并)\n * @returns 统一 Logger 实例\n */\nfunction wrapPino(pinoLogger: pino.Logger, context: Record<string, unknown>): Logger {\n return {\n trace(message: string, ctx?: LogContext) {\n pinoLogger.trace(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n debug(message: string, ctx?: LogContext) {\n pinoLogger.debug(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n info(message: string, ctx?: LogContext) {\n pinoLogger.info(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n warn(message: string, ctx?: LogContext) {\n pinoLogger.warn(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n error(message: string, ctx?: LogContext) {\n pinoLogger.error(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n fatal(message: string, ctx?: LogContext) {\n pinoLogger.fatal(sanitizeLogContext({ ...context, ...ctx }) ?? {}, message)\n },\n child(childContext: Record<string, unknown>): Logger {\n const sanitizedChildContext = sanitizeLogContext(childContext) ?? {}\n return wrapPino(pinoLogger.child(sanitizedChildContext), { ...context, ...sanitizedChildContext })\n },\n }\n}\n\n/**\n * 创建 Logger 实例。\n *\n * @param options - Logger 选项\n * @returns Logger 实例\n *\n * @example\n * ```ts\n * const appLogger = logger.createLogger({ name: 'api', level: 'info' })\n * appLogger.info('ready')\n * ```\n */\nfunction createLogger(options: LoggerOptions = {}): Logger {\n const level = options.level ?? globalLevel\n const format = options.format ?? globalFormat\n const context = { ...globalContext, ...options.context }\n\n // 先构造一份与输出介质无关的基础配置,后面再按 transport 能力决定是否启用 pretty。\n const pinoOptions: pino.LoggerOptions = {\n level,\n name: options.name,\n formatters: {\n level: label => ({ level: label }),\n },\n }\n\n // redact 支持\n if (globalRedact.length > 0) {\n pinoOptions.redact = {\n paths: globalRedact,\n censor: '[REDACTED]',\n }\n }\n\n let pinoInstance: pino.Logger\n\n if (format === 'pretty' && isPrettyTransportAvailable()) {\n // 只有在 pino-pretty 可解析时才挂载 transport,避免可选依赖缺失直接导致 logger 初始化失败。\n try {\n pinoInstance = pino({\n ...pinoOptions,\n transport: {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'SYS:standard',\n ignore: 'pid,hostname',\n },\n },\n })\n }\n catch (error) {\n // 其他初始化异常应重新抛出,便于排查\n if (isPrettyTransportUnavailable(error)) {\n pinoInstance = pino(pinoOptions)\n }\n else {\n throw error\n }\n }\n }\n else {\n pinoInstance = pino(pinoOptions)\n }\n\n return wrapPino(pinoInstance, context)\n}\n\nfunction isPrettyTransportAvailable(): boolean {\n try {\n // pino-pretty 是可选依赖,这里用 resolve 做能力探测,避免在缺失场景下直接 import 失败。\n nodeRequire.resolve('pino-pretty')\n return true\n }\n catch {\n return false\n }\n}\n\nfunction isPrettyTransportUnavailable(error: unknown): boolean {\n const message\n = error instanceof Error\n ? error.message\n : typeof error === 'string'\n ? error\n : ''\n\n const normalized = message.toLowerCase()\n\n return normalized.includes('pino-pretty')\n && (normalized.includes('cannot find module')\n || normalized.includes('unable to determine transport target')\n || normalized.includes('cannot load')\n || normalized.includes('not found'))\n}\n\n// ─── 默认 Logger 实例 ───\n\n/**\n * 获取默认 Logger 实例(单例)。\n *\n * @example\n * ```ts\n * const defaultLogger = logger.getLogger()\n * ```\n */\nfunction getLogger(): Logger {\n if (!defaultLogger) {\n defaultLogger = createLogger()\n }\n return defaultLogger\n}\n\n// ─── 对外出口 ───\n\n/**\n * Node.js Logger 函数集合。\n *\n * @example\n * ```ts\n * logger.createLogger({ name: 'service' }).info('boot')\n * ```\n */\nexport const logger: LoggerFunctions = {\n configureLogger,\n setLogLevel,\n getLogLevel,\n createLogger,\n getLogger,\n}\n","/**\n * @h-ai/core — Core 服务聚合(Node.js)\n *\n * 提供 Node.js 环境的 core 对象,聚合常用功能。 所有功能统一通过 core 对象访问,并提供配置加载能力。\n * @module core-main.node\n */\n\nimport type { CoreFunctions, CoreOptions } from './core-types.js'\nimport { existsSync, readdirSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { CoreConfigSchema } from './core-config.js'\nimport { createCore } from './core-main.js'\nimport { config } from './functions/core-function-config.node.js'\nimport { logger } from './functions/core-function-logger.node.js'\n\nconst YAML_EXTENSION_REGEX = /\\.ya?ml$/\ntype NodeCoreFunctions = CoreFunctions & {\n readonly config: typeof config\n readonly init: typeof initCore\n}\n\n// ─── Core 实例 ───\n\n/**\n * 创建 Node.js 版本的 core 对象。\n *\n * @example\n * ```ts\n * import { core } from '@h-ai/core'\n * core.logger.info('ready')\n * ```\n */\nfunction createNodeCore(): NodeCoreFunctions {\n const baseCore = createCore({\n createLogger: logger.createLogger,\n getLogger: logger.getLogger,\n configureLogger: logger.configureLogger,\n setLogLevel: logger.setLogLevel,\n getLogLevel: logger.getLogLevel,\n })\n\n // 扩展 config 和 init 功能\n return {\n ...baseCore,\n /** Zod 校验错误 → i18n 消息映射工具(kit / serv / api-client 共享)。 */\n zodValidation: baseCore.zodValidation,\n /** 配置管理 */\n config,\n /** 初始化 Core */\n init: initCore,\n }\n}\n\n/**\n * Core 服务对象 - 聚合常用功能(Node.js)。\n *\n * @example\n * ```ts\n * import { core } from '@h-ai/core'\n * core.init({ configDir: './config' })\n * ```\n */\nexport const core: NodeCoreFunctions = createNodeCore()\n\n// ─── Initialization ───\n\n/**\n * 配置加载项(描述单个待加载的配置文件)。\n */\ninterface ConfigLoadItem {\n /** 配置名称(用作缓存 key,如 'core'、'db'、'app') */\n name: string\n /** 配置文件绝对路径 */\n filePath: string\n}\n\n/**\n * 扫描配置目录并构建配置加载项列表。\n *\n * 约定:\n * - 以 `_` 开头的文件为内置模块配置(如 `_core.yml` → name='core')\n * - 其他文件为业务配置(如 `app.yml` → name='app')\n *\n * @param configDir - 配置目录路径\n * @returns 配置加载项列表;目录不存在时返回空数组并输出警告\n *\n * @example\n * ```ts\n * const items = scanConfigDir('./config')\n * // [{ name: 'core', filePath: './config/_core.yml' }, { name: 'app', filePath: './config/app.yml' }]\n * ```\n */\nfunction scanConfigDir(\n configDir: string,\n): ConfigLoadItem[] {\n const logger = core.logger\n const items: ConfigLoadItem[] = []\n\n if (!existsSync(configDir)) {\n logger.warn(`[core] Config directory not found: ${configDir}`)\n return items\n }\n\n const files = readdirSync(configDir).filter(f =>\n f.endsWith('.yml') || f.endsWith('.yaml'),\n )\n\n for (const file of files) {\n const filePath = join(configDir, file)\n const baseName = file.replace(YAML_EXTENSION_REGEX, '')\n\n // 判断是否为内置模块配置(以 _ 开头)\n if (baseName.startsWith('_')) {\n const moduleName = baseName.slice(1) // 去掉 _ 前缀\n items.push({\n name: moduleName,\n filePath,\n })\n }\n else {\n // 业务配置(文件名作为配置名)\n items.push({\n name: baseName,\n filePath,\n })\n }\n }\n return items\n}\n\n/**\n * 初始化 Core(内部实现,通过 `core.init()` 调用)。\n *\n * 执行流程:\n * 1. 配置日志(若提供 `options.logging`)\n * 2. 扫描并加载配置目录中的所有 YAML 文件\n * 3. 启用配置文件监听(若 `options.watchConfig` 为 true)\n *\n * @param options - 初始化选项\n *\n * @example\n * ```ts\n * core.init({ configDir: './config', watchConfig: true })\n * ```\n */\nfunction initCore(options: CoreOptions = {}): void {\n const startTime = Date.now()\n const logger = core.logger\n\n // 1. Configure logging\n if (options.logging) {\n core.logger.configure(options.logging)\n }\n\n logger.info('[core] Initializing...')\n\n let configItems: ConfigLoadItem[] = []\n\n if (options.configDir) {\n // 约定优于配置模式\n configItems = scanConfigDir(options.configDir)\n }\n\n // 2. Load config files\n for (const item of configItems) {\n if (item.name === 'core') {\n const result = config.load(item.name, item.filePath, CoreConfigSchema)\n if (result.success) {\n if (!options.logging) {\n core.logger.configure(result.data.logging || {})\n }\n logger.info(`[core] Config loaded: ${item.name} <- ${item.filePath}`)\n }\n else {\n logger.error(`[core] Config load failed: ${item.name}`, {\n error: result.error,\n })\n }\n }\n else {\n const result = config.load(item.name, item.filePath)\n if (result.success) {\n logger.info(`[core] Config loaded: ${item.name} <- ${item.filePath}`)\n }\n else {\n logger.error(`[core] Config load failed: ${item.name}`, {\n error: result.error,\n })\n }\n }\n }\n\n // 3. Enable config file watching\n if (options.watchConfig && configItems.length > 0) {\n setupConfigWatch(configItems)\n }\n\n const duration = Date.now() - startTime\n logger.info(`[core] Initialized (${duration}ms)`)\n}\n\n/**\n * 启用配置文件监听。\n *\n * 为每个已加载的配置项注册文件 watcher,变更时自动重载并输出日志。\n *\n * @param configs - 需要监听的配置项列表\n */\nfunction setupConfigWatch(configs: ConfigLoadItem[]): void {\n const logger = core.logger\n\n for (const item of configs) {\n config.watch(item.name, (_config, error) => {\n if (error) {\n logger.error(`[core] Config reload failed: ${item.name}`, { error })\n return\n }\n logger.info(`[core] Config reloaded: ${item.name}`)\n })\n\n logger.debug(`[core] Config watch enabled: ${item.name}`)\n }\n}\n"]}
|
package/package.json
CHANGED