@page.su/ai-blog-cli 0.1.0-beta.1 → 0.1.0-beta.10
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/cli.js +14 -5
- package/dist/cli.js.map +1 -1
- package/dist/commands/comments.js +1 -1
- package/dist/commands/comments.js.map +1 -1
- package/dist/commands/config.d.ts +12 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +128 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/demo.js +2 -2
- package/dist/commands/demo.js.map +1 -1
- package/dist/commands/post.d.ts.map +1 -1
- package/dist/commands/post.js +30 -3
- package/dist/commands/post.js.map +1 -1
- package/dist/commands/render-errors.d.ts +4 -0
- package/dist/commands/render-errors.d.ts.map +1 -0
- package/dist/commands/render-errors.js +22 -0
- package/dist/commands/render-errors.js.map +1 -0
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +67 -19
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/syntax.d.ts +4 -0
- package/dist/commands/syntax.d.ts.map +1 -0
- package/dist/commands/syntax.js +29 -0
- package/dist/commands/syntax.js.map +1 -0
- package/dist/config.d.ts +84 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +196 -29
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +150 -19
- package/dist/config.test.js.map +1 -1
- package/package.json +12 -6
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -100
- package/dist/index.js.map +0 -1
- package/dist/prompts/index.d.ts +0 -9
- package/dist/prompts/index.d.ts.map +0 -1
- package/dist/prompts/index.js +0 -178
- package/dist/prompts/index.js.map +0 -1
- package/dist/resources/syntax-spec.d.ts +0 -23
- package/dist/resources/syntax-spec.d.ts.map +0 -1
- package/dist/resources/syntax-spec.js +0 -105
- package/dist/resources/syntax-spec.js.map +0 -1
- package/dist/resources/syntax-spec.test.d.ts +0 -2
- package/dist/resources/syntax-spec.test.d.ts.map +0 -1
- package/dist/resources/syntax-spec.test.js +0 -47
- package/dist/resources/syntax-spec.test.js.map +0 -1
- package/dist/tools/build.d.ts +0 -13
- package/dist/tools/build.d.ts.map +0 -1
- package/dist/tools/build.js +0 -181
- package/dist/tools/build.js.map +0 -1
- package/dist/tools/code-repos.d.ts +0 -5
- package/dist/tools/code-repos.d.ts.map +0 -1
- package/dist/tools/code-repos.js +0 -149
- package/dist/tools/code-repos.js.map +0 -1
- package/dist/tools/comments.d.ts +0 -12
- package/dist/tools/comments.d.ts.map +0 -1
- package/dist/tools/comments.js +0 -87
- package/dist/tools/comments.js.map +0 -1
- package/dist/tools/demos.d.ts +0 -5
- package/dist/tools/demos.d.ts.map +0 -1
- package/dist/tools/demos.js +0 -98
- package/dist/tools/demos.js.map +0 -1
- package/dist/tools/glossary.d.ts +0 -4
- package/dist/tools/glossary.d.ts.map +0 -1
- package/dist/tools/glossary.js +0 -139
- package/dist/tools/glossary.js.map +0 -1
- package/dist/tools/helpers.d.ts +0 -44
- package/dist/tools/helpers.d.ts.map +0 -1
- package/dist/tools/helpers.js +0 -65
- package/dist/tools/helpers.js.map +0 -1
- package/dist/tools/knowledge.d.ts +0 -4
- package/dist/tools/knowledge.d.ts.map +0 -1
- package/dist/tools/knowledge.js +0 -140
- package/dist/tools/knowledge.js.map +0 -1
- package/dist/tools/math-concepts.d.ts +0 -4
- package/dist/tools/math-concepts.d.ts.map +0 -1
- package/dist/tools/math-concepts.js +0 -158
- package/dist/tools/math-concepts.js.map +0 -1
- package/dist/tools/posts.d.ts +0 -35
- package/dist/tools/posts.d.ts.map +0 -1
- package/dist/tools/posts.js +0 -278
- package/dist/tools/posts.js.map +0 -1
- package/dist/tools/scout.d.ts +0 -10
- package/dist/tools/scout.d.ts.map +0 -1
- package/dist/tools/scout.js +0 -111
- package/dist/tools/scout.js.map +0 -1
- package/dist/tools/series.d.ts +0 -12
- package/dist/tools/series.d.ts.map +0 -1
- package/dist/tools/series.js +0 -120
- package/dist/tools/series.js.map +0 -1
- package/dist/tools/syntax-capabilities.d.ts +0 -15
- package/dist/tools/syntax-capabilities.d.ts.map +0 -1
- package/dist/tools/syntax-capabilities.js +0 -859
- package/dist/tools/syntax-capabilities.js.map +0 -1
- package/dist/tools/taxonomy.d.ts +0 -4
- package/dist/tools/taxonomy.d.ts.map +0 -1
- package/dist/tools/taxonomy.js +0 -73
- package/dist/tools/taxonomy.js.map +0 -1
- package/dist/tools/uploads.d.ts +0 -15
- package/dist/tools/uploads.d.ts.map +0 -1
- package/dist/tools/uploads.js +0 -56
- package/dist/tools/uploads.js.map +0 -1
- package/dist/tools/workflows.d.ts +0 -9
- package/dist/tools/workflows.d.ts.map +0 -1
- package/dist/tools/workflows.js +0 -249
- package/dist/tools/workflows.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syntax.js","sourceRoot":"","sources":["../../src/commands/syntax.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,UAAU,sBAAsB,CAAC,OAAgB,EAAE,GAAc;IACrE,MAAM,MAAM,GAAG,OAAO;SACnB,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,6CAA6C,CAAC,CAAC;IAE9D,oBAAoB;IACpB,MAAM;SACH,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,sDAAsD,CAAC;SACnE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,+BAA+B,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEL,6BAA6B;IAC7B,MAAM;SACH,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,wDAAwD,CAAC;SACrE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC9B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,wBAAwB,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACtF,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,19 +1,95 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ai-blog CLI
|
|
2
|
+
* ai-blog CLI 的运行时配置,支持多环境。
|
|
3
|
+
*
|
|
4
|
+
* .aib.env 文件格式:
|
|
5
|
+
* ```
|
|
6
|
+
* # 顶层仅放元数据:默认环境名
|
|
7
|
+
* AIB_DEFAULT_ENV=prod
|
|
8
|
+
*
|
|
9
|
+
* # 每个环境必须独立配置在 [section] 段中
|
|
10
|
+
* [local]
|
|
11
|
+
* AI_BLOG_BASE_URL=http://localhost:3000
|
|
12
|
+
* AI_BLOG_PAT=aib_pat_local
|
|
13
|
+
*
|
|
14
|
+
* [prod]
|
|
15
|
+
* AI_BLOG_BASE_URL=https://blog.example.com
|
|
16
|
+
* AI_BLOG_PAT=aib_pat_prod
|
|
17
|
+
*
|
|
18
|
+
* [staging]
|
|
19
|
+
* AI_BLOG_BASE_URL=https://staging.blog.example.com
|
|
20
|
+
* AI_BLOG_PAT=aib_pat_staging
|
|
21
|
+
* ```
|
|
3
22
|
*
|
|
4
23
|
* 配置优先级(从高到低):
|
|
5
|
-
* 1. 环境变量(AI_BLOG_BASE_URL / AI_BLOG_PAT
|
|
6
|
-
* 2.
|
|
7
|
-
* 3.
|
|
24
|
+
* 1. 环境变量(AI_BLOG_BASE_URL / AI_BLOG_PAT 等)
|
|
25
|
+
* 2. 本地 ./.aib.env 的 [envName] 段
|
|
26
|
+
* 3. 全局 ~/.aib.env 的 [envName] 段
|
|
8
27
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
28
|
+
* 环境选择优先级:
|
|
29
|
+
* 1. --env <name> CLI flag
|
|
30
|
+
* 2. AIB_DEFAULT_ENV 环境变量
|
|
31
|
+
* 3. .aib.env 顶层 AIB_DEFAULT_ENV
|
|
11
32
|
*/
|
|
12
33
|
export interface CliConfig {
|
|
13
34
|
baseUrl: string;
|
|
14
35
|
pat: string;
|
|
15
36
|
requestTimeoutMs: number;
|
|
16
37
|
}
|
|
17
|
-
|
|
18
|
-
|
|
38
|
+
interface ParsedEnvFile {
|
|
39
|
+
/** 顶层键值对(仅用于 AIB_DEFAULT_ENV 元数据) */
|
|
40
|
+
default: Record<string, string>;
|
|
41
|
+
/** 命名段:{ [sectionName]: { KEY: VALUE } } */
|
|
42
|
+
sections: Record<string, Record<string, string>>;
|
|
43
|
+
}
|
|
44
|
+
export interface EnvInfo {
|
|
45
|
+
name: string;
|
|
46
|
+
baseUrl?: string;
|
|
47
|
+
hasPat: boolean;
|
|
48
|
+
/** 配置来源:global ~/.aib.env / local ./.aib.env / both */
|
|
49
|
+
source: "global" | "local" | "both";
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 解析 .env 格式文件内容,支持 [section] 环境段。
|
|
53
|
+
* 忽略空行和 # 注释行,支持 VALUE 中包含 = 号。
|
|
54
|
+
*/
|
|
55
|
+
export declare function parseEnvFileWithSections(content: string): ParsedEnvFile;
|
|
56
|
+
export declare function getGlobalEnvPath(): string;
|
|
57
|
+
export declare function getLocalEnvPath(): string;
|
|
58
|
+
/**
|
|
59
|
+
* 从两个解析后的文件 + process.env 合并出最终配置键值对。
|
|
60
|
+
*
|
|
61
|
+
* 环境配置必须全部在 [section] 段中,顶层不承载业务配置。
|
|
62
|
+
* @internal 导出仅供测试使用
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveConfigFromParsed(globalParsed: ParsedEnvFile, localParsed: ParsedEnvFile, processEnv: Record<string, string | undefined>, envName?: string): Record<string, string>;
|
|
65
|
+
/** 读取并校验配置;返回归一化后的 CliConfig */
|
|
66
|
+
export declare function loadCliConfig(opts?: {
|
|
67
|
+
env?: string;
|
|
68
|
+
}): CliConfig;
|
|
69
|
+
/**
|
|
70
|
+
* 从已合并的 env-like 对象构建并校验 CliConfig。
|
|
71
|
+
* @internal 导出仅供测试使用
|
|
72
|
+
*/
|
|
73
|
+
export declare function buildCliConfig(env: Record<string, string>): CliConfig;
|
|
74
|
+
/** 列出所有环境及其基本信息 */
|
|
75
|
+
export declare function listEnvironments(): {
|
|
76
|
+
environments: EnvInfo[];
|
|
77
|
+
defaultEnv: string | null;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* 查看指定环境的配置详情。
|
|
81
|
+
* 不传 name 时查看默认环境(由 AIB_DEFAULT_ENV 决定)。
|
|
82
|
+
* 返回 null 表示环境不存在;返回 { name: null } 表示未设置默认环境。
|
|
83
|
+
*/
|
|
84
|
+
export declare function showEnvironment(name?: string): {
|
|
85
|
+
name: string | null;
|
|
86
|
+
baseUrl?: string;
|
|
87
|
+
hasPat: boolean;
|
|
88
|
+
requestTimeoutMs?: string;
|
|
89
|
+
} | null;
|
|
90
|
+
/** 添加或更新环境配置,写入本地 ./.aib.env */
|
|
91
|
+
export declare function addEnvironment(name: string, baseUrl: string, pat: string): void;
|
|
92
|
+
/** 设置默认环境(写入 AIB_DEFAULT_ENV 到本地 ./.aib.env) */
|
|
93
|
+
export declare function setDefaultEnv(name: string): void;
|
|
94
|
+
export {};
|
|
19
95
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAOD,UAAU,aAAa;IACrB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,uDAAuD;IACvD,MAAM,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;CACrC;AAID;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAuCvE;AAID,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAaD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,aAAa,EAC3B,WAAW,EAAE,aAAa,EAC1B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAC9C,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkCxB;AAUD,gCAAgC;AAChC,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAGhE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CA+BrE;AAcD,mBAAmB;AACnB,wBAAgB,gBAAgB,IAAI;IAAE,YAAY,EAAE,OAAO,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CA6BzF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,IAAI,CAAC,EAAE,MAAM,GACZ;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA4B9F;AAED,gCAAgC;AAChC,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAW/E;AAED,gDAAgD;AAChD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAmBhD"}
|
package/dist/config.js
CHANGED
|
@@ -1,18 +1,30 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
5
|
+
const ENV_FILE_NAME = ".aib.env";
|
|
6
|
+
// ── Parsing ──
|
|
5
7
|
/**
|
|
6
|
-
* 解析 .env
|
|
8
|
+
* 解析 .env 格式文件内容,支持 [section] 环境段。
|
|
7
9
|
* 忽略空行和 # 注释行,支持 VALUE 中包含 = 号。
|
|
8
10
|
*/
|
|
9
|
-
function
|
|
10
|
-
const result = {};
|
|
11
|
+
export function parseEnvFileWithSections(content) {
|
|
12
|
+
const result = { default: {}, sections: {} };
|
|
13
|
+
let currentSection = null;
|
|
11
14
|
for (const line of content.split("\n")) {
|
|
12
15
|
const trimmed = line.trim();
|
|
13
16
|
if (!trimmed || trimmed.startsWith("#")) {
|
|
14
17
|
continue;
|
|
15
18
|
}
|
|
19
|
+
// [section] 头
|
|
20
|
+
const sectionMatch = trimmed.match(/^\[([^\]]+)\]$/);
|
|
21
|
+
if (sectionMatch) {
|
|
22
|
+
const name = sectionMatch[1].trim();
|
|
23
|
+
currentSection = {};
|
|
24
|
+
result.sections[name] = currentSection;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
// KEY=VALUE
|
|
16
28
|
const eqIndex = trimmed.indexOf("=");
|
|
17
29
|
if (eqIndex === -1) {
|
|
18
30
|
continue;
|
|
@@ -23,62 +35,217 @@ function parseEnvFile(content) {
|
|
|
23
35
|
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
24
36
|
value = value.slice(1, -1);
|
|
25
37
|
}
|
|
26
|
-
|
|
38
|
+
if (currentSection) {
|
|
39
|
+
currentSection[key] = value;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
result.default[key] = value;
|
|
43
|
+
}
|
|
27
44
|
}
|
|
28
45
|
return result;
|
|
29
46
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
function
|
|
47
|
+
// ── File paths ──
|
|
48
|
+
export function getGlobalEnvPath() {
|
|
49
|
+
return join(homedir(), ENV_FILE_NAME);
|
|
50
|
+
}
|
|
51
|
+
export function getLocalEnvPath() {
|
|
52
|
+
return join(process.cwd(), ENV_FILE_NAME);
|
|
53
|
+
}
|
|
54
|
+
function loadParsedFile(filePath) {
|
|
35
55
|
try {
|
|
36
56
|
const content = readFileSync(filePath, "utf-8");
|
|
37
|
-
return
|
|
57
|
+
return parseEnvFileWithSections(content);
|
|
38
58
|
}
|
|
39
59
|
catch {
|
|
40
|
-
return {};
|
|
60
|
+
return { default: {}, sections: {} };
|
|
41
61
|
}
|
|
42
62
|
}
|
|
63
|
+
// ── Config resolution ──
|
|
43
64
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
65
|
+
* 从两个解析后的文件 + process.env 合并出最终配置键值对。
|
|
66
|
+
*
|
|
67
|
+
* 环境配置必须全部在 [section] 段中,顶层不承载业务配置。
|
|
68
|
+
* @internal 导出仅供测试使用
|
|
46
69
|
*/
|
|
47
|
-
function
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
//
|
|
51
|
-
|
|
70
|
+
export function resolveConfigFromParsed(globalParsed, localParsed, processEnv, envName) {
|
|
71
|
+
// 1. 顶层仅用于 AIB_DEFAULT_ENV 元数据
|
|
72
|
+
const mergedDefault = { ...globalParsed.default, ...localParsed.default };
|
|
73
|
+
// 2. 确定环境名
|
|
74
|
+
const resolvedEnvName = envName ?? processEnv.AIB_DEFAULT_ENV ?? mergedDefault.AIB_DEFAULT_ENV ?? null;
|
|
75
|
+
if (!resolvedEnvName) {
|
|
76
|
+
const available = listEnvNames(globalParsed, localParsed);
|
|
77
|
+
throw new Error("No environment selected. Use --env <name>, set AIB_DEFAULT_ENV, or run 'aib config use <name>'.\n" +
|
|
78
|
+
(available.length > 0
|
|
79
|
+
? `Available: ${available.join(", ")}`
|
|
80
|
+
: "No environments defined. Use 'aib config add <name>' to create one."));
|
|
81
|
+
}
|
|
82
|
+
// 3. 只从段读取配置(不继承顶层)
|
|
83
|
+
const globalSection = globalParsed.sections[resolvedEnvName];
|
|
84
|
+
const localSection = localParsed.sections[resolvedEnvName];
|
|
85
|
+
if (!globalSection && !localSection) {
|
|
86
|
+
const available = listEnvNames(globalParsed, localParsed);
|
|
87
|
+
throw new Error(`Environment "${resolvedEnvName}" not found in .aib.env.\n` +
|
|
88
|
+
(available.length > 0
|
|
89
|
+
? `Available: ${available.join(", ")}`
|
|
90
|
+
: "No environments defined. Use 'aib config add <name>' to create one."));
|
|
91
|
+
}
|
|
92
|
+
const sectionConfig = { ...globalSection, ...localSection };
|
|
93
|
+
// 4. 段 + process.env
|
|
94
|
+
return { ...sectionConfig, ...processEnv };
|
|
95
|
+
}
|
|
96
|
+
function resolveConfig(envName) {
|
|
97
|
+
const globalParsed = loadParsedFile(getGlobalEnvPath());
|
|
98
|
+
const localParsed = loadParsedFile(getLocalEnvPath());
|
|
99
|
+
return resolveConfigFromParsed(globalParsed, localParsed, process.env, envName);
|
|
52
100
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
101
|
+
// ── Config loading ──
|
|
102
|
+
/** 读取并校验配置;返回归一化后的 CliConfig */
|
|
103
|
+
export function loadCliConfig(opts) {
|
|
104
|
+
const resolvedEnv = resolveConfig(opts?.env);
|
|
105
|
+
return buildCliConfig(resolvedEnv);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 从已合并的 env-like 对象构建并校验 CliConfig。
|
|
109
|
+
* @internal 导出仅供测试使用
|
|
110
|
+
*/
|
|
111
|
+
export function buildCliConfig(env) {
|
|
112
|
+
const baseUrl = (env.AI_BLOG_BASE_URL ?? "").trim();
|
|
57
113
|
if (!baseUrl) {
|
|
58
114
|
throw new Error("AI_BLOG_BASE_URL is required.\n" +
|
|
59
|
-
"Set it via environment variable or in ~/.aib.env:\n" +
|
|
115
|
+
"Set it via environment variable, --env flag, or in ~/.aib.env:\n" +
|
|
60
116
|
' AI_BLOG_BASE_URL=https://your-blog.example.com');
|
|
61
117
|
}
|
|
62
118
|
// 去掉末尾的 `/`,避免拼接 URL 时出现 `//` 双斜杠
|
|
63
119
|
const normalizedBaseUrl = baseUrl.replace(/\/+$/, "");
|
|
64
|
-
const pat = (
|
|
120
|
+
const pat = (env.AI_BLOG_PAT ?? "").trim();
|
|
65
121
|
if (!pat) {
|
|
66
122
|
throw new Error("AI_BLOG_PAT is required.\n" +
|
|
67
123
|
"Create a token at /admin/settings/tokens, then set it:\n" +
|
|
68
124
|
" export AI_BLOG_PAT=aib_pat_xxx # or put it in ~/.aib.env");
|
|
69
125
|
}
|
|
70
126
|
let requestTimeoutMs = DEFAULT_TIMEOUT_MS;
|
|
71
|
-
const rawTimeout =
|
|
127
|
+
const rawTimeout = env.AI_BLOG_REQUEST_TIMEOUT_MS;
|
|
72
128
|
if (rawTimeout) {
|
|
73
129
|
const parsed = Number.parseInt(rawTimeout, 10);
|
|
74
130
|
if (Number.isFinite(parsed) && parsed > 0) {
|
|
75
131
|
requestTimeoutMs = parsed;
|
|
76
132
|
}
|
|
77
133
|
}
|
|
134
|
+
return { baseUrl: normalizedBaseUrl, pat, requestTimeoutMs };
|
|
135
|
+
}
|
|
136
|
+
// ── Config management helpers (for `aib config` command) ──
|
|
137
|
+
function listEnvNames(...parsed) {
|
|
138
|
+
const names = new Set();
|
|
139
|
+
for (const p of parsed) {
|
|
140
|
+
for (const name of Object.keys(p.sections)) {
|
|
141
|
+
names.add(name);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return [...names];
|
|
145
|
+
}
|
|
146
|
+
/** 列出所有环境及其基本信息 */
|
|
147
|
+
export function listEnvironments() {
|
|
148
|
+
const globalParsed = loadParsedFile(getGlobalEnvPath());
|
|
149
|
+
const localParsed = loadParsedFile(getLocalEnvPath());
|
|
150
|
+
const mergedDefault = { ...globalParsed.default, ...localParsed.default };
|
|
151
|
+
const defaultEnv = process.env.AIB_DEFAULT_ENV ?? mergedDefault.AIB_DEFAULT_ENV ?? null;
|
|
152
|
+
const names = listEnvNames(globalParsed, localParsed);
|
|
153
|
+
const environments = names.map((name) => {
|
|
154
|
+
const globalSection = globalParsed.sections[name] ?? {};
|
|
155
|
+
const localSection = localParsed.sections[name] ?? {};
|
|
156
|
+
const merged = { ...globalSection, ...localSection };
|
|
157
|
+
const source = globalParsed.sections[name] && localParsed.sections[name]
|
|
158
|
+
? "both"
|
|
159
|
+
: localParsed.sections[name]
|
|
160
|
+
? "local"
|
|
161
|
+
: "global";
|
|
162
|
+
return {
|
|
163
|
+
name,
|
|
164
|
+
baseUrl: merged.AI_BLOG_BASE_URL,
|
|
165
|
+
hasPat: !!merged.AI_BLOG_PAT,
|
|
166
|
+
source,
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
return { environments, defaultEnv };
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* 查看指定环境的配置详情。
|
|
173
|
+
* 不传 name 时查看默认环境(由 AIB_DEFAULT_ENV 决定)。
|
|
174
|
+
* 返回 null 表示环境不存在;返回 { name: null } 表示未设置默认环境。
|
|
175
|
+
*/
|
|
176
|
+
export function showEnvironment(name) {
|
|
177
|
+
const globalParsed = loadParsedFile(getGlobalEnvPath());
|
|
178
|
+
const localParsed = loadParsedFile(getLocalEnvPath());
|
|
179
|
+
let envName = name;
|
|
180
|
+
if (!envName) {
|
|
181
|
+
const mergedDefault = { ...globalParsed.default, ...localParsed.default };
|
|
182
|
+
envName = process.env.AIB_DEFAULT_ENV ?? mergedDefault.AIB_DEFAULT_ENV ?? null;
|
|
183
|
+
}
|
|
184
|
+
if (!envName) {
|
|
185
|
+
return { name: null, hasPat: false };
|
|
186
|
+
}
|
|
187
|
+
const globalSection = globalParsed.sections[envName] ?? {};
|
|
188
|
+
const localSection = localParsed.sections[envName] ?? {};
|
|
189
|
+
if (!globalParsed.sections[envName] && !localParsed.sections[envName]) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
const merged = { ...globalSection, ...localSection };
|
|
78
193
|
return {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
194
|
+
name: envName,
|
|
195
|
+
baseUrl: merged.AI_BLOG_BASE_URL,
|
|
196
|
+
hasPat: !!merged.AI_BLOG_PAT,
|
|
197
|
+
requestTimeoutMs: merged.AI_BLOG_REQUEST_TIMEOUT_MS,
|
|
82
198
|
};
|
|
83
199
|
}
|
|
200
|
+
/** 添加或更新环境配置,写入本地 ./.aib.env */
|
|
201
|
+
export function addEnvironment(name, baseUrl, pat) {
|
|
202
|
+
const localPath = getLocalEnvPath();
|
|
203
|
+
const parsed = loadParsedFile(localPath);
|
|
204
|
+
if (!parsed.sections[name]) {
|
|
205
|
+
parsed.sections[name] = {};
|
|
206
|
+
}
|
|
207
|
+
parsed.sections[name].AI_BLOG_BASE_URL = baseUrl;
|
|
208
|
+
parsed.sections[name].AI_BLOG_PAT = pat;
|
|
209
|
+
writeFileSync(localPath, serializeEnvFile(parsed), { mode: 0o600 });
|
|
210
|
+
}
|
|
211
|
+
/** 设置默认环境(写入 AIB_DEFAULT_ENV 到本地 ./.aib.env) */
|
|
212
|
+
export function setDefaultEnv(name) {
|
|
213
|
+
const localPath = getLocalEnvPath();
|
|
214
|
+
const parsed = loadParsedFile(localPath);
|
|
215
|
+
// 验证环境存在
|
|
216
|
+
const globalParsed = loadParsedFile(getGlobalEnvPath());
|
|
217
|
+
if (!parsed.sections[name] && !globalParsed.sections[name]) {
|
|
218
|
+
const available = listEnvNames(parsed, globalParsed);
|
|
219
|
+
throw new Error(`Environment "${name}" not found.\n` +
|
|
220
|
+
(available.length > 0
|
|
221
|
+
? `Available: ${available.join(", ")}\n`
|
|
222
|
+
: "No environments defined.\n") +
|
|
223
|
+
`Add it first: aib config add ${name} --base-url <url> --pat <token>`);
|
|
224
|
+
}
|
|
225
|
+
parsed.default.AIB_DEFAULT_ENV = name;
|
|
226
|
+
writeFileSync(localPath, serializeEnvFile(parsed), { mode: 0o600 });
|
|
227
|
+
}
|
|
228
|
+
// ── Serialization ──
|
|
229
|
+
function serializeEnvFile(parsed) {
|
|
230
|
+
const lines = [];
|
|
231
|
+
// 顶层
|
|
232
|
+
for (const [key, value] of Object.entries(parsed.default)) {
|
|
233
|
+
lines.push(`${key}=${formatValue(value)}`);
|
|
234
|
+
}
|
|
235
|
+
// 命名段
|
|
236
|
+
for (const [sectionName, values] of Object.entries(parsed.sections)) {
|
|
237
|
+
lines.push("");
|
|
238
|
+
lines.push(`[${sectionName}]`);
|
|
239
|
+
for (const [key, value] of Object.entries(values)) {
|
|
240
|
+
lines.push(`${key}=${formatValue(value)}`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return lines.join("\n") + "\n";
|
|
244
|
+
}
|
|
245
|
+
function formatValue(value) {
|
|
246
|
+
if (value.includes(" ") || value.includes("#")) {
|
|
247
|
+
return `"${value}"`;
|
|
248
|
+
}
|
|
249
|
+
return value;
|
|
250
|
+
}
|
|
84
251
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.test.js
CHANGED
|
@@ -1,40 +1,34 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
* 验证 loadCliConfig 的边界行为:
|
|
5
|
-
* - 缺关键变量直接抛
|
|
6
|
-
* - URL 末尾斜杠会被归一化
|
|
7
|
-
* - 默认超时存在
|
|
8
|
-
* - AI_BLOG_REQUEST_TIMEOUT_MS 合法时被采纳
|
|
9
|
-
*
|
|
10
|
-
* 注:NodeJS.ProcessEnv 在 @types/node 里被声明为含 NODE_ENV 等必填字段的接口,
|
|
11
|
-
* 但 loadCliConfig 只读取自己关心的几个字段。这里通过 unknown 中转,
|
|
12
|
-
* 让 TypeScript 接受我们构造的"局部 env 对象"。
|
|
13
|
-
*/
|
|
2
|
+
import { buildCliConfig, parseEnvFileWithSections, resolveConfigFromParsed, } from "./config.js";
|
|
3
|
+
// ── Helpers ──
|
|
14
4
|
function makeEnv(env) {
|
|
15
5
|
return env;
|
|
16
6
|
}
|
|
17
|
-
|
|
7
|
+
function emptyParsed() {
|
|
8
|
+
return { default: {}, sections: {} };
|
|
9
|
+
}
|
|
10
|
+
// ── buildCliConfig: 校验与归一化 ──
|
|
11
|
+
describe("buildCliConfig", () => {
|
|
18
12
|
it("缺少 AI_BLOG_BASE_URL 时直接抛错", () => {
|
|
19
|
-
expect(() =>
|
|
13
|
+
expect(() => buildCliConfig(makeEnv({ AI_BLOG_PAT: "x" }))).toThrow(/AI_BLOG_BASE_URL/);
|
|
20
14
|
});
|
|
21
15
|
it("缺少 AI_BLOG_PAT 时直接抛错", () => {
|
|
22
|
-
expect(() =>
|
|
16
|
+
expect(() => buildCliConfig(makeEnv({ AI_BLOG_BASE_URL: "https://example.com" }))).toThrow(/AI_BLOG_PAT/);
|
|
23
17
|
});
|
|
24
18
|
it("BASE_URL 末尾的斜杠被归一化", () => {
|
|
25
|
-
const config =
|
|
19
|
+
const config = buildCliConfig(makeEnv({
|
|
26
20
|
AI_BLOG_BASE_URL: "https://example.com///",
|
|
27
21
|
AI_BLOG_PAT: "aib_pat_xxx",
|
|
28
22
|
}));
|
|
29
23
|
expect(config.baseUrl).toBe("https://example.com");
|
|
30
24
|
});
|
|
31
25
|
it("默认超时为 30s,合法配置覆盖默认值", () => {
|
|
32
|
-
const defaults =
|
|
26
|
+
const defaults = buildCliConfig(makeEnv({
|
|
33
27
|
AI_BLOG_BASE_URL: "https://example.com",
|
|
34
28
|
AI_BLOG_PAT: "aib_pat_xxx",
|
|
35
29
|
}));
|
|
36
30
|
expect(defaults.requestTimeoutMs).toBe(30_000);
|
|
37
|
-
const overridden =
|
|
31
|
+
const overridden = buildCliConfig(makeEnv({
|
|
38
32
|
AI_BLOG_BASE_URL: "https://example.com",
|
|
39
33
|
AI_BLOG_PAT: "aib_pat_xxx",
|
|
40
34
|
AI_BLOG_REQUEST_TIMEOUT_MS: "5000",
|
|
@@ -42,7 +36,7 @@ describe("loadCliConfig", () => {
|
|
|
42
36
|
expect(overridden.requestTimeoutMs).toBe(5_000);
|
|
43
37
|
});
|
|
44
38
|
it("非法超时值被忽略并回落默认", () => {
|
|
45
|
-
const config =
|
|
39
|
+
const config = buildCliConfig(makeEnv({
|
|
46
40
|
AI_BLOG_BASE_URL: "https://example.com",
|
|
47
41
|
AI_BLOG_PAT: "aib_pat_xxx",
|
|
48
42
|
AI_BLOG_REQUEST_TIMEOUT_MS: "not-a-number",
|
|
@@ -50,4 +44,141 @@ describe("loadCliConfig", () => {
|
|
|
50
44
|
expect(config.requestTimeoutMs).toBe(30_000);
|
|
51
45
|
});
|
|
52
46
|
});
|
|
47
|
+
// ── parseEnvFileWithSections: 段解析 ──
|
|
48
|
+
describe("parseEnvFileWithSections", () => {
|
|
49
|
+
it("正确解析 [section] 段", () => {
|
|
50
|
+
const content = `AIB_DEFAULT_ENV=prod
|
|
51
|
+
|
|
52
|
+
[local]
|
|
53
|
+
AI_BLOG_BASE_URL=http://localhost:3000
|
|
54
|
+
AI_BLOG_PAT=local_pat
|
|
55
|
+
|
|
56
|
+
[prod]
|
|
57
|
+
AI_BLOG_BASE_URL=https://blog.example.com
|
|
58
|
+
AI_BLOG_PAT=prod_pat
|
|
59
|
+
|
|
60
|
+
[staging]
|
|
61
|
+
AI_BLOG_BASE_URL=https://staging.example.com
|
|
62
|
+
AI_BLOG_PAT=staging_pat
|
|
63
|
+
`;
|
|
64
|
+
const parsed = parseEnvFileWithSections(content);
|
|
65
|
+
expect(parsed.default.AIB_DEFAULT_ENV).toBe("prod");
|
|
66
|
+
expect(parsed.sections.local.AI_BLOG_BASE_URL).toBe("http://localhost:3000");
|
|
67
|
+
expect(parsed.sections.prod.AI_BLOG_BASE_URL).toBe("https://blog.example.com");
|
|
68
|
+
expect(parsed.sections.staging.AI_BLOG_PAT).toBe("staging_pat");
|
|
69
|
+
});
|
|
70
|
+
it("忽略空行和注释", () => {
|
|
71
|
+
const content = `# comment
|
|
72
|
+
AIB_DEFAULT_ENV=prod
|
|
73
|
+
|
|
74
|
+
# another comment
|
|
75
|
+
[prod]
|
|
76
|
+
AI_BLOG_BASE_URL=https://prod.example.com
|
|
77
|
+
`;
|
|
78
|
+
const parsed = parseEnvFileWithSections(content);
|
|
79
|
+
expect(parsed.default.AIB_DEFAULT_ENV).toBe("prod");
|
|
80
|
+
expect(parsed.sections.prod.AI_BLOG_BASE_URL).toBe("https://prod.example.com");
|
|
81
|
+
});
|
|
82
|
+
it("VALUE 中包含 = 号", () => {
|
|
83
|
+
const content = "[prod]\nAI_BLOG_PAT=aib_pat_key=value\n";
|
|
84
|
+
const parsed = parseEnvFileWithSections(content);
|
|
85
|
+
expect(parsed.sections.prod.AI_BLOG_PAT).toBe("aib_pat_key=value");
|
|
86
|
+
});
|
|
87
|
+
it("引号包裹的值被正确去除", () => {
|
|
88
|
+
const content = '[prod]\nAI_BLOG_BASE_URL="https://example.com"\nAI_BLOG_PAT=\'single\'\n';
|
|
89
|
+
const parsed = parseEnvFileWithSections(content);
|
|
90
|
+
expect(parsed.sections.prod.AI_BLOG_BASE_URL).toBe("https://example.com");
|
|
91
|
+
expect(parsed.sections.prod.AI_BLOG_PAT).toBe("single");
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
// ── resolveConfigFromParsed: 多环境合并 ──
|
|
95
|
+
describe("resolveConfigFromParsed", () => {
|
|
96
|
+
it("无 --env 且无 AIB_DEFAULT_ENV 时抛错", () => {
|
|
97
|
+
expect(() => resolveConfigFromParsed(emptyParsed(), emptyParsed(), {})).toThrow(/No environment selected/);
|
|
98
|
+
});
|
|
99
|
+
it("--env 选择对应段", () => {
|
|
100
|
+
const globalParsed = {
|
|
101
|
+
default: {},
|
|
102
|
+
sections: {
|
|
103
|
+
prod: { AI_BLOG_BASE_URL: "https://blog.example.com", AI_BLOG_PAT: "prod_pat" },
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
const result = resolveConfigFromParsed(globalParsed, emptyParsed(), {}, "prod");
|
|
107
|
+
expect(result.AI_BLOG_BASE_URL).toBe("https://blog.example.com");
|
|
108
|
+
expect(result.AI_BLOG_PAT).toBe("prod_pat");
|
|
109
|
+
});
|
|
110
|
+
it("AIB_DEFAULT_ENV 在顶层配置时自动选择", () => {
|
|
111
|
+
const globalParsed = {
|
|
112
|
+
default: { AIB_DEFAULT_ENV: "prod" },
|
|
113
|
+
sections: {
|
|
114
|
+
prod: { AI_BLOG_BASE_URL: "https://blog.example.com", AI_BLOG_PAT: "prod_pat" },
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
const result = resolveConfigFromParsed(globalParsed, emptyParsed(), {});
|
|
118
|
+
expect(result.AI_BLOG_BASE_URL).toBe("https://blog.example.com");
|
|
119
|
+
expect(result.AI_BLOG_PAT).toBe("prod_pat");
|
|
120
|
+
});
|
|
121
|
+
it("--env 优先于 AIB_DEFAULT_ENV", () => {
|
|
122
|
+
const globalParsed = {
|
|
123
|
+
default: { AIB_DEFAULT_ENV: "prod" },
|
|
124
|
+
sections: {
|
|
125
|
+
prod: { AI_BLOG_BASE_URL: "https://prod.example.com", AI_BLOG_PAT: "prod_pat" },
|
|
126
|
+
staging: { AI_BLOG_BASE_URL: "https://staging.example.com", AI_BLOG_PAT: "staging_pat" },
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
const result = resolveConfigFromParsed(globalParsed, emptyParsed(), {}, "staging");
|
|
130
|
+
expect(result.AI_BLOG_BASE_URL).toBe("https://staging.example.com");
|
|
131
|
+
});
|
|
132
|
+
it("process.env.AIB_DEFAULT_ENV 优先于文件中的 AIB_DEFAULT_ENV", () => {
|
|
133
|
+
const globalParsed = {
|
|
134
|
+
default: { AIB_DEFAULT_ENV: "prod" },
|
|
135
|
+
sections: {
|
|
136
|
+
prod: { AI_BLOG_BASE_URL: "https://prod.example.com", AI_BLOG_PAT: "prod_pat" },
|
|
137
|
+
staging: { AI_BLOG_BASE_URL: "https://staging.example.com", AI_BLOG_PAT: "staging_pat" },
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
const result = resolveConfigFromParsed(globalParsed, emptyParsed(), { AIB_DEFAULT_ENV: "staging" });
|
|
141
|
+
expect(result.AI_BLOG_BASE_URL).toBe("https://staging.example.com");
|
|
142
|
+
});
|
|
143
|
+
it("process.env 最终覆盖段值", () => {
|
|
144
|
+
const globalParsed = {
|
|
145
|
+
default: {},
|
|
146
|
+
sections: {
|
|
147
|
+
prod: { AI_BLOG_BASE_URL: "https://blog.example.com", AI_BLOG_PAT: "prod_pat" },
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
const result = resolveConfigFromParsed(globalParsed, emptyParsed(), {
|
|
151
|
+
AI_BLOG_PAT: "env_override_pat",
|
|
152
|
+
}, "prod");
|
|
153
|
+
expect(result.AI_BLOG_BASE_URL).toBe("https://blog.example.com");
|
|
154
|
+
expect(result.AI_BLOG_PAT).toBe("env_override_pat");
|
|
155
|
+
});
|
|
156
|
+
it("local 段补充 global 段缺失的键", () => {
|
|
157
|
+
const globalParsed = {
|
|
158
|
+
default: {},
|
|
159
|
+
sections: {
|
|
160
|
+
prod: { AI_BLOG_PAT: "g_pat" },
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
const localParsed = {
|
|
164
|
+
default: {},
|
|
165
|
+
sections: {
|
|
166
|
+
prod: { AI_BLOG_BASE_URL: "https://local.example.com" },
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
const result = resolveConfigFromParsed(globalParsed, localParsed, {}, "prod");
|
|
170
|
+
expect(result.AI_BLOG_BASE_URL).toBe("https://local.example.com");
|
|
171
|
+
expect(result.AI_BLOG_PAT).toBe("g_pat");
|
|
172
|
+
});
|
|
173
|
+
it("--env 指定不存在的环境时抛错并列出可用环境", () => {
|
|
174
|
+
const globalParsed = {
|
|
175
|
+
default: {},
|
|
176
|
+
sections: {
|
|
177
|
+
prod: { AI_BLOG_BASE_URL: "https://prod.example.com", AI_BLOG_PAT: "prod_pat" },
|
|
178
|
+
staging: { AI_BLOG_BASE_URL: "https://staging.example.com", AI_BLOG_PAT: "staging_pat" },
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
expect(() => resolveConfigFromParsed(globalParsed, emptyParsed(), {}, "nonexistent")).toThrow(/Environment "nonexistent" not found[\s\S]*prod[\s\S]*staging/);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
53
184
|
//# sourceMappingURL=config.test.js.map
|
package/dist/config.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":"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"}
|