@spaceflow/core 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +75 -56
  2. package/dist/index.js +5589 -970
  3. package/dist/index.js.map +1 -1
  4. package/package.json +9 -3
  5. package/src/cli-runtime/di/config.ts +157 -0
  6. package/src/cli-runtime/di/container.ts +120 -0
  7. package/src/cli-runtime/di/index.ts +3 -0
  8. package/src/cli-runtime/di/services.ts +53 -0
  9. package/src/cli-runtime/extension-loader.ts +74 -0
  10. package/src/{shared → cli-runtime}/i18n/index.ts +7 -1
  11. package/src/cli-runtime/i18n/init.ts +117 -0
  12. package/src/cli-runtime/index.ts +131 -0
  13. package/src/cli-runtime/internal-extensions.ts +33 -0
  14. package/src/commands/build/build.service.ts +323 -0
  15. package/src/commands/build/index.ts +49 -0
  16. package/src/commands/clear/clear.service.ts +159 -0
  17. package/src/commands/clear/index.ts +35 -0
  18. package/src/commands/commit/commit.config.ts +168 -0
  19. package/src/commands/commit/commit.service.ts +950 -0
  20. package/src/commands/commit/index.ts +58 -0
  21. package/src/commands/create/create.service.ts +318 -0
  22. package/src/commands/create/index.ts +42 -0
  23. package/src/commands/dev/index.ts +30 -0
  24. package/src/commands/install/index.ts +65 -0
  25. package/src/commands/install/install.service.ts +1539 -0
  26. package/src/commands/list/index.ts +33 -0
  27. package/src/commands/list/list.service.ts +127 -0
  28. package/src/commands/mcp/index.ts +37 -0
  29. package/src/commands/mcp/mcp.service.ts +246 -0
  30. package/src/commands/runx/index.ts +47 -0
  31. package/src/commands/runx/runx.service.ts +142 -0
  32. package/src/commands/runx/runx.utils.ts +83 -0
  33. package/src/commands/schema/index.ts +30 -0
  34. package/src/commands/setup/index.ts +34 -0
  35. package/src/commands/setup/setup.service.ts +234 -0
  36. package/src/commands/uninstall/index.ts +42 -0
  37. package/src/commands/uninstall/uninstall.service.ts +166 -0
  38. package/src/commands/update/index.ts +42 -0
  39. package/src/commands/update/update.service.ts +373 -0
  40. package/src/config/index.ts +1 -30
  41. package/src/config/spaceflow.config.ts +226 -278
  42. package/src/index.ts +11 -1
  43. package/src/locales/en/build.json +22 -0
  44. package/src/locales/en/clear.json +16 -0
  45. package/src/locales/en/commit.json +45 -0
  46. package/src/locales/en/create.json +27 -0
  47. package/src/locales/en/dev.json +5 -0
  48. package/src/locales/en/install.json +71 -0
  49. package/src/locales/en/list.json +8 -0
  50. package/src/locales/en/mcp.json +19 -0
  51. package/src/locales/en/runx.json +13 -0
  52. package/src/locales/en/schema.json +4 -0
  53. package/src/locales/en/setup.json +14 -0
  54. package/src/locales/en/uninstall.json +18 -0
  55. package/src/locales/en/update.json +28 -0
  56. package/src/locales/zh-cn/build.json +22 -0
  57. package/src/locales/zh-cn/clear.json +16 -0
  58. package/src/locales/zh-cn/commit.json +45 -0
  59. package/src/locales/zh-cn/create.json +27 -0
  60. package/src/locales/zh-cn/dev.json +5 -0
  61. package/src/locales/zh-cn/install.json +71 -0
  62. package/src/locales/zh-cn/list.json +8 -0
  63. package/src/locales/zh-cn/mcp.json +19 -0
  64. package/src/locales/zh-cn/runx.json +13 -0
  65. package/src/locales/zh-cn/schema.json +4 -0
  66. package/src/locales/zh-cn/setup.json +14 -0
  67. package/src/locales/zh-cn/uninstall.json +18 -0
  68. package/src/locales/zh-cn/update.json +28 -0
  69. package/src/shared/editor-config/index.ts +2 -21
  70. package/src/shared/llm-proxy/adapters/openai.adapter.ts +3 -1
  71. package/src/shared/package-manager/index.ts +5 -76
  72. package/src/shared/source-utils/index.ts +12 -130
  73. package/src/shared/spaceflow-dir/index.ts +13 -135
  74. package/src/shared/verbose/index.ts +10 -87
  75. package/dist/524.js +0 -9
  76. package/src/config/ci.config.ts +0 -29
  77. package/src/config/config-loader.ts +0 -100
  78. package/src/config/config-reader.service.ts +0 -128
  79. package/src/config/config-reader.ts +0 -75
  80. package/src/config/feishu.config.ts +0 -35
  81. package/src/config/git-provider.config.ts +0 -29
  82. package/src/config/llm.config.ts +0 -110
  83. package/src/config/load-env.ts +0 -15
  84. package/src/config/storage.config.ts +0 -33
  85. /package/src/{shared → cli-runtime}/i18n/i18n.spec.ts +0 -0
  86. /package/src/{shared → cli-runtime}/i18n/i18n.ts +0 -0
  87. /package/src/{shared → cli-runtime}/i18n/locale-detect.ts +0 -0
@@ -1,81 +1,11 @@
1
- import { execSync } from "child_process";
2
- import { existsSync } from "fs";
3
- import { join } from "path";
4
-
5
1
  /**
6
- * 检测项目使用的包管理器
7
- * 必须同时满足:命令可用 AND lock 文件存在
8
- * @param cwd 工作目录,默认为 process.cwd()
2
+ * 从 @spaceflow/shared 重导出 package-manager 工具函数
9
3
  */
10
- export function getPackageManager(cwd?: string): string {
11
- const workDir = cwd || process.cwd();
12
-
13
- // pnpm: 命令可用 + pnpm-lock.yaml 存在
14
- if (existsSync(join(workDir, "pnpm-lock.yaml"))) {
15
- try {
16
- execSync("pnpm --version", { stdio: "ignore" });
17
- return "pnpm";
18
- } catch {
19
- // pnpm 命令不可用,继续检测其他
20
- }
21
- }
22
-
23
- // yarn: 命令可用 + yarn.lock 存在
24
- if (existsSync(join(workDir, "yarn.lock"))) {
25
- try {
26
- execSync("yarn --version", { stdio: "ignore" });
27
- return "yarn";
28
- } catch {
29
- // yarn 命令不可用,继续检测其他
30
- }
31
- }
32
-
33
- // npm: 命令可用 + package-lock.json 存在
34
- if (existsSync(join(workDir, "package-lock.json"))) {
35
- try {
36
- execSync("npm --version", { stdio: "ignore" });
37
- return "npm";
38
- } catch {
39
- // npm 命令不可用
40
- }
41
- }
42
-
43
- // 默认回退到 npm
44
- return "npm";
45
- }
4
+ export { getPackageManager, detectPackageManager, isPnpmWorkspace } from "@spaceflow/shared";
46
5
 
47
- /**
48
- * 检测指定目录使用的包管理器(基于 lock 文件)
49
- * 如果没有 lock 文件,尝试检测 pnpm 是否可用
50
- * @param dir 目标目录
51
- */
52
- export function detectPackageManager(dir: string): string {
53
- if (existsSync(join(dir, "pnpm-lock.yaml"))) {
54
- return "pnpm";
55
- }
56
- if (existsSync(join(dir, "yarn.lock"))) {
57
- return "yarn";
58
- }
59
- if (existsSync(join(dir, "package-lock.json"))) {
60
- return "npm";
61
- }
62
- // 默认使用 pnpm(如果可用)
63
- try {
64
- execSync("pnpm --version", { stdio: "ignore" });
65
- return "pnpm";
66
- } catch {
67
- return "npm";
68
- }
69
- }
70
-
71
- /**
72
- * 检测当前目录是否为 pnpm workspace
73
- * @param cwd 工作目录,默认为 process.cwd()
74
- */
75
- export function isPnpmWorkspace(cwd?: string): boolean {
76
- const workDir = cwd || process.cwd();
77
- return existsSync(join(workDir, "pnpm-workspace.yaml"));
78
- }
6
+ // addSpaceflowToDevDependencies 是 core 独有的,保留在这里
7
+ import { existsSync, readFileSync, writeFileSync } from "fs";
8
+ import { join } from "path";
79
9
 
80
10
  /**
81
11
  * 将 .spaceflow 添加到根项目的 devDependencies 中
@@ -84,7 +14,6 @@ export function isPnpmWorkspace(cwd?: string): boolean {
84
14
  * @returns 是否成功添加(如果已存在则返回 false)
85
15
  */
86
16
  export function addSpaceflowToDevDependencies(cwd?: string): boolean {
87
- const { readFileSync, writeFileSync } = require("fs");
88
17
  const workDir = cwd || process.cwd();
89
18
  const packageJsonPath = join(workDir, "package.json");
90
19
 
@@ -1,131 +1,13 @@
1
1
  /**
2
- * Source 类型定义
3
- */
4
- export type SourceType = "npm" | "git" | "local";
5
-
6
- /**
7
- * 判断是否为 Git URL
8
- * 支持: git@xxx.git, https://xxx.git, git+ssh://xxx, git+https://xxx
9
- */
10
- export function isGitUrl(source: string): boolean {
11
- return (
12
- source.startsWith("git@") ||
13
- source.startsWith("git+") ||
14
- (source.startsWith("https://") && source.endsWith(".git")) ||
15
- source.endsWith(".git")
16
- );
17
- }
18
-
19
- /**
20
- * 判断是否为本地路径
21
- * 支持: ./path, ../path, /path, link:./path, skills/
22
- */
23
- export function isLocalPath(source: string): boolean {
24
- return (
25
- source.startsWith("workspace:") ||
26
- source.startsWith("link:") ||
27
- source.startsWith("./") ||
28
- source.startsWith("../") ||
29
- source.startsWith("/") ||
30
- source.startsWith("skills/")
31
- );
32
- }
33
-
34
- /**
35
- * 获取 source 类型
36
- */
37
- export function getSourceType(source: string): SourceType {
38
- if (isLocalPath(source)) return "local";
39
- if (isGitUrl(source)) return "git";
40
- return "npm";
41
- }
42
-
43
- /**
44
- * 规范化 source(移除 link: 前缀等)
45
- */
46
- export function normalizeSource(source: string): string {
47
- if (source.startsWith("link:")) {
48
- return source.substring(5); // 移除 "link:" 前缀
49
- }
50
- return source;
51
- }
52
-
53
- /**
54
- * 从 npm 包名中提取纯包名(去除版本号后缀)
55
- * 例如: @spaceflow/review@0.10.0 → @spaceflow/review
56
- * some-package@1.2.3 → some-package
57
- */
58
- export function extractNpmPackageName(source: string): string {
59
- // 处理 scoped 包: @scope/name@version
60
- if (source.startsWith("@")) {
61
- const slashIndex = source.indexOf("/");
62
- if (slashIndex !== -1) {
63
- const afterSlash = source.substring(slashIndex + 1);
64
- const atIndex = afterSlash.indexOf("@");
65
- if (atIndex !== -1) {
66
- return source.substring(0, slashIndex + 1 + atIndex);
67
- }
68
- }
69
- return source;
70
- }
71
- // 处理普通包: name@version
72
- const atIndex = source.indexOf("@");
73
- if (atIndex !== -1) {
74
- return source.substring(0, atIndex);
75
- }
76
- return source;
77
- }
78
-
79
- /**
80
- * 从 source 提取名称
81
- * npm 包: @scope/package -> package
82
- * git URL: git@git.example.com:org/repo.git -> repo
83
- * 本地路径: ./skills/publish -> publish
84
- */
85
- export function extractName(source: string): string {
86
- if (isLocalPath(source)) {
87
- // 本地路径:取最后一个目录名
88
- const parts = source.replace(/\/$/, "").split("/").filter(Boolean);
89
- return parts[parts.length - 1] || "unknown";
90
- } else if (isGitUrl(source)) {
91
- let path = source;
92
- path = path.replace(/\.git$/, "");
93
- path = path.replace(/^git@[^:]+:/, "");
94
- path = path.replace(/^https?:\/\/[^/]+\//, "");
95
- const parts = path.split("/").filter(Boolean);
96
- return parts[parts.length - 1] || "unknown";
97
- } else {
98
- // npm 包名:先去除版本号后缀,再提取名称
99
- // @spaceflow/review@0.10.0 → @spaceflow/review → review
100
- const packageName = extractNpmPackageName(source);
101
- const parts = packageName.split("/");
102
- const lastPart = parts[parts.length - 1];
103
- // 移除 spaceflow-plugin- 或 plugin- 前缀
104
- return lastPart.replace(/^spaceflow-plugin-/, "").replace(/^plugin-/, "");
105
- }
106
- }
107
-
108
- /**
109
- * 构建 git 仓库的 package spec(用于 pnpm add)
110
- * git@xxx.git -> git+ssh://git@xxx.git
111
- * https://xxx.git -> git+https://xxx.git
112
- */
113
- export function buildGitPackageSpec(source: string, ref?: string): string {
114
- let spec: string;
115
- if (source.startsWith("git@")) {
116
- // SSH 格式: git@host:org/repo.git -> git+ssh://git@host/org/repo.git
117
- const sshUrl = source.replace(":", "/").replace("git@", "git+ssh://git@");
118
- spec = sshUrl;
119
- } else if (source.startsWith("https://")) {
120
- spec = `git+${source}`;
121
- } else {
122
- spec = source;
123
- }
124
-
125
- // 添加 ref(分支/tag/commit)
126
- if (ref) {
127
- spec += `#${ref}`;
128
- }
129
-
130
- return spec;
131
- }
2
+ * @spaceflow/shared 重导出 source-utils
3
+ */
4
+ export type { SourceType } from "@spaceflow/shared";
5
+ export {
6
+ isGitUrl,
7
+ isLocalPath,
8
+ getSourceType,
9
+ normalizeSource,
10
+ extractNpmPackageName,
11
+ extractName,
12
+ buildGitPackageSpec,
13
+ } from "@spaceflow/shared";
@@ -1,136 +1,14 @@
1
- import { existsSync, readFileSync, mkdirSync, writeFileSync } from "fs";
2
- import { join } from "path";
3
- import { homedir } from "os";
4
- import { SPACEFLOW_DIR, PACKAGE_JSON } from "../../extension-system/extension.interface";
5
-
6
1
  /**
7
- * 获取 .spaceflow 目录路径
8
- * @param isGlobal 是否为全局目录(~/.spaceflow)
9
- * @param cwd 工作目录,默认为 process.cwd()
10
- */
11
- export function getSpaceflowDir(isGlobal: boolean, cwd?: string): string {
12
- if (isGlobal) {
13
- return join(homedir(), SPACEFLOW_DIR);
14
- }
15
- return join(cwd || process.cwd(), SPACEFLOW_DIR);
16
- }
17
-
18
- /**
19
- * 确保 .spaceflow 目录存在
20
- * @param spaceflowDir .spaceflow 目录路径
21
- */
22
- export function ensureSpaceflowDir(spaceflowDir: string): void {
23
- if (!existsSync(spaceflowDir)) {
24
- mkdirSync(spaceflowDir, { recursive: true });
25
- }
26
-
27
- // 创建 .gitignore
28
- const gitignorePath = join(spaceflowDir, ".gitignore");
29
- if (!existsSync(gitignorePath)) {
30
- const gitignoreContent = `# Spaceflow Extension dependencies
31
- node_modules/
32
- pnpm-lock.yaml
33
- config-schema.json
34
- `;
35
- writeFileSync(gitignorePath, gitignoreContent);
36
- }
37
-
38
- }
39
-
40
- /**
41
- * 获取 @spaceflow/core 的版本号
42
- * 从 process.argv[1](cli 入口)向上找到 @spaceflow/cli 的 package.json
43
- * 读取其中声明的 @spaceflow/core 依赖版本,保证 cli 和 core 版本一致
44
- */
45
- export function getSpaceflowCoreVersion(): string {
46
- const cliEntryPath = process.argv[1];
47
- if (cliEntryPath) {
48
- // cli 入口: .../node_modules/@spaceflow/cli/dist/cli.js → 往上两级是包根目录
49
- const cliDir = join(cliEntryPath, "..", "..");
50
- const cliPkgPath = join(cliDir, PACKAGE_JSON);
51
- if (existsSync(cliPkgPath)) {
52
- try {
53
- const cliPkg = JSON.parse(readFileSync(cliPkgPath, "utf-8"));
54
- if (cliPkg.name === "@spaceflow/cli") {
55
- const coreVersion = cliPkg.dependencies?.["@spaceflow/core"];
56
- if (coreVersion) {
57
- return coreVersion;
58
- }
59
- }
60
- } catch {
61
- // ignore
62
- }
63
- }
64
- }
65
- return "latest";
66
- }
67
-
68
- /**
69
- * 确保 .spaceflow 目录及 package.json 存在,并保持 @spaceflow/core 版本与 cli 一致
70
- * @param spaceflowDir .spaceflow 目录路径
71
- */
72
- export function ensureSpaceflowPackageJson(spaceflowDir: string): void {
73
- ensureSpaceflowDir(spaceflowDir);
74
-
75
- const packageJsonPath = join(spaceflowDir, PACKAGE_JSON);
76
- const coreVersion = getSpaceflowCoreVersion();
77
-
78
- if (existsSync(packageJsonPath)) {
79
- // 已存在:检查并更新 @spaceflow/core 版本
80
- try {
81
- const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
82
- if (pkg.dependencies?.["@spaceflow/core"] !== coreVersion) {
83
- pkg.dependencies = pkg.dependencies || {};
84
- pkg.dependencies["@spaceflow/core"] = coreVersion;
85
- writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + "\n");
86
- }
87
- } catch {
88
- // ignore
89
- }
90
- } else {
91
- // 不存在:创建
92
- const packageJson = {
93
- name: "spaceflow",
94
- private: true,
95
- dependencies: {
96
- "@spaceflow/core": coreVersion,
97
- },
98
- };
99
- writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n");
100
- }
101
- }
102
-
103
- /**
104
- * 确保编辑器目录有 .gitignore 文件,并将生成的文件加入忽略列表
105
- * @param editorRoot 编辑器根目录(如 .claude)
106
- * @param itemType 项目类型 (skills 或 commands)
107
- * @param itemName 项目名称
108
- */
109
- export async function ensureEditorGitignore(
110
- editorRoot: string,
111
- itemType: "skills" | "commands",
112
- itemName: string,
113
- ): Promise<void> {
114
- const { readFile, writeFile } = await import("fs/promises");
115
- const gitignorePath = join(editorRoot, ".gitignore");
116
- const ignoreEntry = itemType === "skills" ? `skills/${itemName}` : `commands/${itemName}.md`;
117
-
118
- let content = "";
119
- if (existsSync(gitignorePath)) {
120
- content = await readFile(gitignorePath, "utf-8");
121
- // 检查是否已包含该条目
122
- const lines = content.split("\n").map((l) => l.trim());
123
- if (lines.includes(ignoreEntry)) {
124
- return;
125
- }
126
- // 确保末尾有换行
127
- if (!content.endsWith("\n")) {
128
- content += "\n";
129
- }
130
- } else {
131
- content = "# 自动生成的 .gitignore - spaceflow 安装的 skills 和 commands\n";
132
- }
133
-
134
- content += `${ignoreEntry}\n`;
135
- await writeFile(gitignorePath, content);
136
- }
2
+ * @spaceflow/shared 重导出 spaceflow-dir 工具函数
3
+ */
4
+ export {
5
+ getSpaceflowDir,
6
+ ensureSpaceflowDir,
7
+ getSpaceflowCoreVersion,
8
+ ensureSpaceflowPackageJson,
9
+ ensureDependencies,
10
+ loadExtensionsFromDir,
11
+ ensureEditorGitignore,
12
+ SPACEFLOW_DIR,
13
+ PACKAGE_JSON,
14
+ } from "@spaceflow/shared";
@@ -1,88 +1,11 @@
1
1
  /**
2
- * 日志级别(字符串模式)
3
- * - "silent": 静默模式,不输出任何日志
4
- * - "info": 显示过程日志(如 "开始审查"、"完成审查")
5
- * - "verbose": 显示详细日志
6
- * - "debug": 显示调试日志(包括大模型的输入提示词和输出过程)
7
- */
8
- export type LogLevel = "silent" | "info" | "verbose" | "debug";
9
-
10
- /**
11
- * Verbose 日志级别(数字模式,向后兼容)
12
- * - 0 / false: 静默模式,只返回结果
13
- * - 1 / true: 显示过程日志
14
- * - 2: 显示详细日志
15
- * - 3: 显示调试日志
16
- */
17
- export type VerboseLevel = 0 | 1 | 2 | 3 | false | true;
18
-
19
- /** 日志级别优先级映射 */
20
- export const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {
21
- silent: 0,
22
- info: 1,
23
- verbose: 2,
24
- debug: 3,
25
- } as const;
26
-
27
- /** VerboseLevel 数字到 LogLevel 字符串的映射 */
28
- const VERBOSE_TO_LOG_LEVEL: Record<number, LogLevel> = {
29
- 0: "silent",
30
- 1: "info",
31
- 2: "verbose",
32
- 3: "debug",
33
- } as const;
34
-
35
- /**
36
- * 将任意级别值统一转为 LogLevel 字符串
37
- * @param level 日志级别(字符串、数字、布尔值)
38
- * @returns LogLevel 字符串
39
- */
40
- export const toLogLevel = (level: LogLevel | VerboseLevel | undefined): LogLevel => {
41
- if (level === undefined) return "info";
42
- if (typeof level === "string") return level;
43
- if (level === true) return "info";
44
- if (level === false) return "silent";
45
- return VERBOSE_TO_LOG_LEVEL[level] ?? "info";
46
- };
47
-
48
- /**
49
- * 将 verbose 值规范化为数字
50
- * @param verbose verbose 值(支持字符串、数字、布尔值)
51
- * @returns 规范化后的数字 (0, 1, 2, 3)
52
- */
53
- export function normalizeVerbose(
54
- verbose: LogLevel | VerboseLevel | boolean | undefined,
55
- ): 0 | 1 | 2 | 3 {
56
- if (verbose === undefined || verbose === false || verbose === 0 || verbose === "silent") return 0;
57
- if (verbose === true || verbose === 1 || verbose === "info") return 1;
58
- if (verbose === 2 || verbose === "verbose") return 2;
59
- return 3;
60
- }
61
-
62
- /**
63
- * 判断是否应该打印指定级别的日志
64
- * @param verbose 当前 verbose 级别(支持字符串或数字)
65
- * @param requiredLevel 需要的最低级别 (1, 2, 3)
66
- * @returns 是否应该打印
67
- */
68
- export function shouldLog(
69
- verbose: LogLevel | VerboseLevel | undefined,
70
- requiredLevel: 1 | 2 | 3,
71
- ): boolean {
72
- return normalizeVerbose(verbose) >= requiredLevel;
73
- }
74
-
75
- /**
76
- * 解析命令行 verbose 参数
77
- * 支持: -v, -v 2, -v 3, --verbose, --verbose 2, -vvv (计数模式)
78
- * @param val 命令行参数值(字符串、布尔值、数字或 undefined)
79
- * @returns 规范化后的 VerboseLevel
80
- */
81
- export function parseVerbose(val: string | boolean | number | undefined): 0 | 1 | 2 | 3 {
82
- if (val === undefined || val === 0) return 1;
83
- if (val === true || val === "") return 1;
84
- if (typeof val === "number") return normalizeVerbose(val as VerboseLevel);
85
- const level = parseInt(val as string, 10);
86
- if (isNaN(level)) return 1;
87
- return normalizeVerbose(level as VerboseLevel);
88
- }
2
+ * 从 @spaceflow/shared 重导出 verbose 工具
3
+ */
4
+ export type { LogLevel, VerboseLevel } from "@spaceflow/shared";
5
+ export {
6
+ LOG_LEVEL_PRIORITY,
7
+ toLogLevel,
8
+ normalizeVerbose,
9
+ shouldLog,
10
+ parseVerbose,
11
+ } from "@spaceflow/shared";
package/dist/524.js DELETED
@@ -1,9 +0,0 @@
1
- export const __rspack_esm_id = "524";
2
- export const __rspack_esm_ids = ["524"];
3
- export const __webpack_modules__ = {
4
- 463(module) {
5
- module.exports = import("fs/promises").then(function(module) { return module; });
6
-
7
- },
8
-
9
- };
@@ -1,29 +0,0 @@
1
- import { z } from "zod";
2
- import { createEnvConfigLoader } from "./config-loader";
3
-
4
- /** CI 配置 Schema */
5
- const schemaFactory = () =>
6
- z.object({
7
- /** 仓库名称 (owner/repo 格式) */
8
- repository: z
9
- .string()
10
- .default(process.env.GITHUB_REPOSITORY || "")
11
- .describe("仓库名称 (owner/repo 格式)"),
12
- /** 当前分支名称 */
13
- refName: z
14
- .string()
15
- .default(process.env.GITHUB_REF_NAME || "")
16
- .describe("当前分支名称"),
17
- actor: z
18
- .string()
19
- .default(process.env.GITHUB_ACTOR || "")
20
- .describe("当前操作者"),
21
- });
22
-
23
- /** CI 配置类型 */
24
- export type CiConfig = z.infer<ReturnType<typeof schemaFactory>>;
25
-
26
- export const ciConfig = createEnvConfigLoader({
27
- configKey: "ci",
28
- schemaFactory,
29
- });
@@ -1,100 +0,0 @@
1
- import { z } from "zod";
2
- import { readConfigSync } from "./spaceflow.config";
3
- import { registerPluginSchema } from "./schema-generator.service";
4
-
5
- /**
6
- * 配置加载器选项
7
- */
8
- export interface ConfigLoaderOptions<T extends z.ZodObject<z.ZodRawShape>> {
9
- /** 配置 key(用于从 spaceflow.json 读取) */
10
- configKey: string;
11
- /** zod schema(应包含 .default() 设置默认值) */
12
- schemaFactory: () => T;
13
- /** 配置描述(用于生成 JSON Schema) */
14
- description?: string;
15
- }
16
-
17
- /**
18
- * 创建配置加载器
19
- * 统一使用 zod 进行配置验证和默认值填充
20
- *
21
- * @example
22
- * ```ts
23
- * const GitProviderConfigSchema = z.object({
24
- * serverUrl: z.string().default(process.env.GITHUB_SERVER_URL || ""),
25
- * token: z.string().default(process.env.GITHUB_TOKEN || ""),
26
- * });
27
- *
28
- * export type GitProviderConfig = z.infer<typeof GitProviderConfigSchema>;
29
- *
30
- * export const gitProviderConfig = createConfigLoader({
31
- * configKey: "gitProvider",
32
- * schemaFactory: GitProviderConfigSchema,
33
- * description: "Git Provider 服务配置",
34
- * });
35
- * ```
36
- */
37
- export function createConfigLoader<T extends z.ZodObject<z.ZodRawShape>>(
38
- options: ConfigLoaderOptions<T>,
39
- ) {
40
- const { configKey, schemaFactory, description } = options;
41
-
42
- // 创建配置加载器
43
- return (): z.infer<T> => {
44
- const schema = schemaFactory();
45
- // 注册 schema 用于 JSON Schema 生成
46
- registerPluginSchema({
47
- configKey,
48
- schemaFactory: () => schema,
49
- description,
50
- });
51
-
52
- const fileConfig = readConfigSync();
53
- const rawConfig = fileConfig[configKey] ?? {};
54
-
55
- // 使用 zod 验证并填充默认值
56
- const result = schema.safeParse(rawConfig);
57
-
58
- if (!result.success) {
59
- const errors = result.error.issues
60
- .map((e) => ` - ${e.path.join(".")}: ${e.message}`)
61
- .join("\n");
62
- throw new Error(`配置 "${configKey}" 验证失败:\n${errors}`);
63
- }
64
-
65
- return result.data;
66
- };
67
- }
68
-
69
- /**
70
- * 创建简单配置加载器(仅从环境变量读取,不读取配置文件)
71
- * 适用于 CI 等纯环境变量配置
72
- */
73
- export function createEnvConfigLoader<T extends z.ZodObject<z.ZodRawShape>>(
74
- options: Omit<ConfigLoaderOptions<T>, "description"> & { description?: string },
75
- ) {
76
- const { configKey, schemaFactory, description } = options;
77
-
78
- return (): z.infer<T> => {
79
- const schema = schemaFactory();
80
- // 注册 schema(如果有描述)
81
- if (description) {
82
- registerPluginSchema({
83
- configKey,
84
- schemaFactory: () => schema,
85
- description,
86
- });
87
- }
88
- // 直接使用空对象,让 schema 的 default 值生效
89
- const result = schema.safeParse({});
90
-
91
- if (!result.success) {
92
- const errors = result.error.issues
93
- .map((e) => ` - ${e.path.join(".")}: ${e.message}`)
94
- .join("\n");
95
- throw new Error(`配置 "${configKey}" 验证失败:\n${errors}`);
96
- }
97
-
98
- return result.data;
99
- };
100
- }