grf-cli 1.0.0 → 1.0.3

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 (104) hide show
  1. package/README.md +5 -5
  2. package/README.zh-CN.md +5 -5
  3. package/dist/cli.js +2 -14
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/add.d.ts +5 -0
  6. package/dist/commands/add.d.ts.map +1 -1
  7. package/dist/commands/add.js +15 -16
  8. package/dist/commands/add.js.map +1 -1
  9. package/dist/commands/clean.d.ts +5 -0
  10. package/dist/commands/clean.d.ts.map +1 -1
  11. package/dist/commands/clean.js +15 -33
  12. package/dist/commands/clean.js.map +1 -1
  13. package/dist/commands/config.d.ts +5 -0
  14. package/dist/commands/config.d.ts.map +1 -1
  15. package/dist/commands/config.js +19 -39
  16. package/dist/commands/config.js.map +1 -1
  17. package/dist/commands/index.d.ts +27 -0
  18. package/dist/commands/index.d.ts.map +1 -0
  19. package/dist/commands/index.js +52 -0
  20. package/dist/commands/index.js.map +1 -0
  21. package/dist/commands/list.d.ts +5 -0
  22. package/dist/commands/list.d.ts.map +1 -1
  23. package/dist/commands/list.js +27 -59
  24. package/dist/commands/list.js.map +1 -1
  25. package/dist/commands/load.d.ts +5 -0
  26. package/dist/commands/load.d.ts.map +1 -1
  27. package/dist/commands/load.js +23 -61
  28. package/dist/commands/load.js.map +1 -1
  29. package/dist/commands/unload.d.ts +6 -1
  30. package/dist/commands/unload.d.ts.map +1 -1
  31. package/dist/commands/unload.js +157 -162
  32. package/dist/commands/unload.js.map +1 -1
  33. package/dist/commands/update.d.ts +6 -1
  34. package/dist/commands/update.d.ts.map +1 -1
  35. package/dist/commands/update.js +66 -74
  36. package/dist/commands/update.js.map +1 -1
  37. package/dist/core/config-manager.d.ts +83 -0
  38. package/dist/core/config-manager.d.ts.map +1 -0
  39. package/dist/core/config-manager.js +170 -0
  40. package/dist/core/config-manager.js.map +1 -0
  41. package/dist/core/config.d.ts +22 -2
  42. package/dist/core/config.d.ts.map +1 -1
  43. package/dist/core/config.js +71 -35
  44. package/dist/core/config.js.map +1 -1
  45. package/dist/core/loading-state.d.ts +125 -0
  46. package/dist/core/loading-state.d.ts.map +1 -0
  47. package/dist/core/loading-state.js +212 -0
  48. package/dist/core/loading-state.js.map +1 -0
  49. package/dist/core/loading.d.ts +21 -26
  50. package/dist/core/loading.d.ts.map +1 -1
  51. package/dist/core/loading.js +124 -87
  52. package/dist/core/loading.js.map +1 -1
  53. package/dist/core/migration.d.ts +54 -0
  54. package/dist/core/migration.d.ts.map +1 -0
  55. package/dist/core/migration.js +279 -0
  56. package/dist/core/migration.js.map +1 -0
  57. package/dist/core/paths.d.ts +58 -0
  58. package/dist/core/paths.d.ts.map +1 -0
  59. package/dist/core/paths.js +103 -0
  60. package/dist/core/paths.js.map +1 -0
  61. package/dist/core/repos-index.d.ts +113 -0
  62. package/dist/core/repos-index.d.ts.map +1 -0
  63. package/dist/core/repos-index.js +206 -0
  64. package/dist/core/repos-index.js.map +1 -0
  65. package/dist/core/sync.d.ts.map +1 -1
  66. package/dist/core/sync.js +3 -3
  67. package/dist/core/sync.js.map +1 -1
  68. package/dist/ui/format.d.ts +159 -0
  69. package/dist/ui/format.d.ts.map +1 -0
  70. package/dist/ui/format.js +300 -0
  71. package/dist/ui/format.js.map +1 -0
  72. package/dist/ui/index.d.ts +9 -0
  73. package/dist/ui/index.d.ts.map +1 -0
  74. package/dist/ui/index.js +53 -0
  75. package/dist/ui/index.js.map +1 -0
  76. package/dist/ui/prompt.d.ts +94 -0
  77. package/dist/ui/prompt.d.ts.map +1 -0
  78. package/dist/ui/prompt.js +223 -0
  79. package/dist/ui/prompt.js.map +1 -0
  80. package/dist/ui/spinner.d.ts +99 -0
  81. package/dist/ui/spinner.d.ts.map +1 -0
  82. package/dist/ui/spinner.js +136 -0
  83. package/dist/ui/spinner.js.map +1 -0
  84. package/dist/ui/table.d.ts +142 -0
  85. package/dist/ui/table.d.ts.map +1 -0
  86. package/dist/ui/table.js +213 -0
  87. package/dist/ui/table.js.map +1 -0
  88. package/dist/utils/constants.d.ts +152 -0
  89. package/dist/utils/constants.d.ts.map +1 -0
  90. package/dist/utils/constants.js +160 -0
  91. package/dist/utils/constants.js.map +1 -0
  92. package/dist/utils/error.d.ts +109 -0
  93. package/dist/utils/error.d.ts.map +1 -0
  94. package/dist/utils/error.js +212 -0
  95. package/dist/utils/error.js.map +1 -0
  96. package/dist/utils/index.d.ts +8 -0
  97. package/dist/utils/index.d.ts.map +1 -0
  98. package/dist/utils/index.js +44 -0
  99. package/dist/utils/index.js.map +1 -0
  100. package/dist/utils/validation.d.ts +122 -0
  101. package/dist/utils/validation.d.ts.map +1 -0
  102. package/dist/utils/validation.js +248 -0
  103. package/dist/utils/validation.js.map +1 -0
  104. package/package.json +4 -4
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ /**
3
+ * 表格输出模块
4
+ * 封装表格格式化和输出功能
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.padEnd = padEnd;
11
+ exports.padStart = padStart;
12
+ exports.truncate = truncate;
13
+ exports.printTable = printTable;
14
+ exports.printKeyValue = printKeyValue;
15
+ exports.printSeparator = printSeparator;
16
+ exports.printEmptyLine = printEmptyLine;
17
+ exports.printTitle = printTitle;
18
+ exports.printTotal = printTotal;
19
+ const chalk_1 = __importDefault(require("chalk"));
20
+ /**
21
+ * 将字符串填充到指定宽度(右侧填充空格)
22
+ * @param str 原始字符串
23
+ * @param width 目标宽度
24
+ * @returns 填充后的字符串
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * padEnd("hello", 10); // "hello "
29
+ * padEnd("hello world", 5); // "hello world" (不截断)
30
+ * ```
31
+ */
32
+ function padEnd(str, width) {
33
+ if (str.length >= width)
34
+ return str;
35
+ return str + " ".repeat(width - str.length);
36
+ }
37
+ /**
38
+ * 将字符串填充到指定宽度(左侧填充空格)
39
+ * @param str 原始字符串
40
+ * @param width 目标宽度
41
+ * @returns 填充后的字符串
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * padStart("42", 5); // " 42"
46
+ * ```
47
+ */
48
+ function padStart(str, width) {
49
+ if (str.length >= width)
50
+ return str;
51
+ return " ".repeat(width - str.length) + str;
52
+ }
53
+ /**
54
+ * 截断长字符串
55
+ * @param str 原始字符串
56
+ * @param maxLength 最大长度
57
+ * @param suffix 截断后缀,默认为 "..."
58
+ * @returns 截断后的字符串
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * truncate("hello world", 8); // "hello..."
63
+ * truncate("hello", 10); // "hello"
64
+ * ```
65
+ */
66
+ function truncate(str, maxLength, suffix = "...") {
67
+ if (str.length <= maxLength)
68
+ return str;
69
+ return str.slice(0, maxLength - suffix.length) + suffix;
70
+ }
71
+ /**
72
+ * 格式化单元格内容
73
+ * @param value 单元格值
74
+ * @param column 列定义
75
+ * @returns 格式化后的字符串
76
+ */
77
+ function formatCell(value, column) {
78
+ const truncated = truncate(value, column.width - 2);
79
+ switch (column.align) {
80
+ case "right":
81
+ return padStart(truncated, column.width);
82
+ case "center": {
83
+ const totalPadding = column.width - truncated.length;
84
+ const leftPadding = Math.floor(totalPadding / 2);
85
+ const rightPadding = totalPadding - leftPadding;
86
+ return " ".repeat(leftPadding) + truncated + " ".repeat(rightPadding);
87
+ }
88
+ case "left":
89
+ default:
90
+ return padEnd(truncated, column.width);
91
+ }
92
+ }
93
+ /**
94
+ * 打印表格
95
+ * @param options 表格配置
96
+ * @param rows 数据行(每行是一个字符串数组)
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * printTable(
101
+ * {
102
+ * columns: [
103
+ * { header: "NAME", width: 20 },
104
+ * { header: "STATUS", width: 15 },
105
+ * { header: "COUNT", width: 10, align: "right" }
106
+ * ],
107
+ * indent: " ",
108
+ * showHeader: true
109
+ * },
110
+ * [
111
+ * ["repo1", "active", "42"],
112
+ * ["repo2", "inactive", "0"]
113
+ * ]
114
+ * );
115
+ * ```
116
+ */
117
+ function printTable(options, rows) {
118
+ const { columns, indent = "", showHeader = true, headerColor = "gray", } = options;
119
+ // 打印表头
120
+ if (showHeader) {
121
+ const headerRow = columns
122
+ .map((col) => formatCell(col.header, col))
123
+ .join("");
124
+ const coloredHeader = applyColor(headerRow, headerColor);
125
+ console.log(indent + coloredHeader);
126
+ }
127
+ // 打印数据行
128
+ for (const row of rows) {
129
+ const formattedRow = columns
130
+ .map((col, index) => formatCell(row[index] ?? "", col))
131
+ .join("");
132
+ console.log(indent + formattedRow);
133
+ }
134
+ }
135
+ /**
136
+ * 应用颜色
137
+ * @param text 文本
138
+ * @param color 颜色名称
139
+ * @returns 带颜色的文本
140
+ */
141
+ function applyColor(text, color) {
142
+ switch (color) {
143
+ case "gray":
144
+ return chalk_1.default.gray(text);
145
+ case "white":
146
+ return chalk_1.default.white(text);
147
+ case "cyan":
148
+ return chalk_1.default.cyan(text);
149
+ case "yellow":
150
+ return chalk_1.default.yellow(text);
151
+ default:
152
+ return text;
153
+ }
154
+ }
155
+ /**
156
+ * 打印简单的键值对列表
157
+ * @param items 键值对数组
158
+ * @param options 配置选项
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * printKeyValue([
163
+ * { key: "Name", value: "my-repo" },
164
+ * { key: "Path", value: "/path/to/repo" },
165
+ * { key: "Branch", value: "main" }
166
+ * ], { indent: " ", keyWidth: 10 });
167
+ * ```
168
+ */
169
+ function printKeyValue(items, options = {}) {
170
+ const { indent = "", keyWidth = 12, separator = ":" } = options;
171
+ for (const item of items) {
172
+ const key = chalk_1.default.gray(padEnd(item.key + separator, keyWidth));
173
+ console.log(`${indent}${key} ${item.value}`);
174
+ }
175
+ }
176
+ /**
177
+ * 打印分隔线
178
+ * @param length 分隔线长度
179
+ * @param char 分隔字符,默认为 "-"
180
+ */
181
+ function printSeparator(length, char = "-") {
182
+ console.log(chalk_1.default.gray(char.repeat(length)));
183
+ }
184
+ /**
185
+ * 打印空行
186
+ * @param count 空行数量,默认为 1
187
+ */
188
+ function printEmptyLine(count = 1) {
189
+ for (let i = 0; i < count; i++) {
190
+ console.log();
191
+ }
192
+ }
193
+ /**
194
+ * 打印标题
195
+ * @param title 标题文本
196
+ * @param options 配置选项
197
+ */
198
+ function printTitle(title, options = {}) {
199
+ const { bold = true, icon } = options;
200
+ const text = icon ? `${icon} ${title}` : title;
201
+ console.log(bold ? chalk_1.default.bold(text) : text);
202
+ }
203
+ /**
204
+ * 打印统计信息
205
+ * @param total 总数
206
+ * @param unit 单位(单数形式)
207
+ * @param pluralUnit 单位(复数形式),默认为单数形式加 "s"
208
+ */
209
+ function printTotal(total, unit, pluralUnit) {
210
+ const actualUnit = total === 1 ? unit : (pluralUnit ?? unit + "s");
211
+ console.log(chalk_1.default.gray(`Total: ${total} ${actualUnit}`));
212
+ }
213
+ //# sourceMappingURL=table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.js","sourceRoot":"","sources":["../../src/ui/table.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * 常量定义模块
3
+ * 项目中使用的各种常量
4
+ */
5
+ /**
6
+ * 目录名称常量
7
+ */
8
+ export declare const DIR_NAMES: {
9
+ /** .gitreference 目录名 */
10
+ readonly GITREFERENCE: ".gitreference";
11
+ /** .git 目录名 */
12
+ readonly GIT: ".git";
13
+ };
14
+ /**
15
+ * 文件名称常量
16
+ */
17
+ export declare const FILE_NAMES: {
18
+ /** 加载状态文件 */
19
+ readonly LOADING_JSON: "loading.json";
20
+ /** 仓库元信息文件 */
21
+ readonly META_JSON: "meta.json";
22
+ /** 旧版元信息文件名 */
23
+ readonly GRF_META_JSON: ".grf-meta.json";
24
+ /** 旧版元信息文件名 */
25
+ readonly GITREFERENCE_META_JSON: ".gitreference-meta.json";
26
+ /** Git 忽略文件 */
27
+ readonly GITIGNORE: ".gitignore";
28
+ /** 全局配置文件 */
29
+ readonly CONFIG_JSON: "config.json";
30
+ };
31
+ /**
32
+ * 默认值常量
33
+ */
34
+ export declare const DEFAULTS: {
35
+ /** 默认分支名 */
36
+ readonly BRANCH: "main";
37
+ /** 默认浅克隆深度 */
38
+ readonly SHALLOW_DEPTH: 1;
39
+ /** 是否默认使用浅克隆 */
40
+ readonly SHALLOW_CLONE: true;
41
+ /** 短 commit ID 长度 */
42
+ readonly SHORT_COMMIT_LENGTH: 7;
43
+ };
44
+ /**
45
+ * 表格列宽常量
46
+ */
47
+ export declare const TABLE_COLUMNS: {
48
+ /** 仓库名称列宽 */
49
+ readonly NAME: 40;
50
+ /** 分支列宽 */
51
+ readonly BRANCH: 15;
52
+ /** Commit ID 列宽 */
53
+ readonly COMMIT: 10;
54
+ /** 日期列宽 */
55
+ readonly DATE: 12;
56
+ /** 路径列宽 */
57
+ readonly PATH: 30;
58
+ /** 状态列宽 */
59
+ readonly STATUS: 15;
60
+ };
61
+ /**
62
+ * 排除的文件/目录列表(复制时排除)
63
+ */
64
+ export declare const COPY_EXCLUDES: readonly [".git", "meta.json", ".grf-meta.json", ".gitreference-meta.json"];
65
+ /**
66
+ * Git 相关常量
67
+ */
68
+ export declare const GIT: {
69
+ /** 远程名称 */
70
+ readonly REMOTE_NAME: "origin";
71
+ /** 默认分支候选列表 */
72
+ readonly DEFAULT_BRANCHES: readonly ["main", "master"];
73
+ };
74
+ /**
75
+ * 超时设置(毫秒)
76
+ */
77
+ export declare const TIMEOUTS: {
78
+ /** Git 操作超时 */
79
+ readonly GIT_OPERATION: 60000;
80
+ /** 网络请求超时 */
81
+ readonly NETWORK_REQUEST: 30000;
82
+ };
83
+ /**
84
+ * 限制设置
85
+ */
86
+ export declare const LIMITS: {
87
+ /** 最大路径长度 */
88
+ readonly MAX_PATH_LENGTH: 260;
89
+ /** 最大仓库名称长度 */
90
+ readonly MAX_REPO_NAME_LENGTH: 255;
91
+ /** 最大并发操作数 */
92
+ readonly MAX_CONCURRENT_OPERATIONS: 5;
93
+ };
94
+ /**
95
+ * 正则表达式模式
96
+ */
97
+ export declare const PATTERNS: {
98
+ /** HTTPS Git URL */
99
+ readonly HTTPS_GIT_URL: RegExp;
100
+ /** SSH Git URL */
101
+ readonly SSH_GIT_URL: RegExp;
102
+ /** 非法文件名字符 */
103
+ readonly INVALID_FILENAME_CHARS: RegExp;
104
+ /** 非法分支名字符 */
105
+ readonly INVALID_BRANCH_CHARS: RegExp;
106
+ };
107
+ /**
108
+ * 消息模板
109
+ */
110
+ export declare const MESSAGES: {
111
+ /** 操作取消 */
112
+ readonly OPERATION_CANCELLED: "Operation cancelled.";
113
+ /** 无仓库可清理 */
114
+ readonly NO_REPOS_TO_CLEAN: "No repositories to clean.";
115
+ /** 无已缓存仓库 */
116
+ readonly NO_CACHED_REPOS: "No repositories cached yet.";
117
+ /** 无已加载参考代码 */
118
+ readonly NO_LOADED_REFS: "No loaded reference code in current project.";
119
+ /** 仓库未找到 */
120
+ readonly REPO_NOT_FOUND: (name: string) => string;
121
+ /** 仓库已存在 */
122
+ readonly REPO_ALREADY_EXISTS: (name: string) => string;
123
+ };
124
+ /**
125
+ * 命令提示
126
+ */
127
+ export declare const HINTS: {
128
+ /** 添加仓库提示 */
129
+ readonly ADD_REPO: "Use 'grf add <url>' to add a repository.";
130
+ /** 查看列表提示 */
131
+ readonly LIST_REPOS: "Use 'grf list' to see all cached repositories.";
132
+ /** 查看已加载提示 */
133
+ readonly LIST_LOADED: "Use 'grf unload --list' to see all loaded reference code.";
134
+ /** 加载仓库提示 */
135
+ readonly LOAD_REPO: "Use 'grf load <name>' to load reference code to workspace.";
136
+ /** 更新仓库提示 */
137
+ readonly UPDATE_REPO: "Use 'grf update <name>' to update the repository.";
138
+ /** 清理仓库提示 */
139
+ readonly CLEAN_REPO: "Use 'grf clean <name>' to remove the repository.";
140
+ };
141
+ /**
142
+ * 应用信息
143
+ */
144
+ export declare const APP_INFO: {
145
+ /** 应用名称 */
146
+ readonly NAME: "gitreference";
147
+ /** 命令名称 */
148
+ readonly COMMAND: "grf";
149
+ /** 配置目录名 */
150
+ readonly CONFIG_DIR: ".gitreference";
151
+ };
152
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,eAAO,MAAM,SAAS;IACpB,wBAAwB;;IAExB,eAAe;;CAEP,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,UAAU;IACrB,aAAa;;IAEb,cAAc;;IAEd,eAAe;;IAEf,eAAe;;IAEf,eAAe;;IAEf,aAAa;;CAEL,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,QAAQ;IACnB,YAAY;;IAEZ,cAAc;;IAEd,gBAAgB;;IAEhB,qBAAqB;;CAEb,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,aAAa;IACxB,aAAa;;IAEb,WAAW;;IAEX,mBAAmB;;IAEnB,WAAW;;IAEX,WAAW;;IAEX,WAAW;;CAEH,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,aAAa,6EAKhB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,GAAG;IACd,WAAW;;IAEX,eAAe;;CAEP,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,QAAQ;IACnB,eAAe;;IAEf,aAAa;;CAEL,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,MAAM;IACjB,aAAa;;IAEb,eAAe;;IAEf,cAAc;;CAEN,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,QAAQ;IACnB,oBAAoB;;IAEpB,kBAAkB;;IAElB,cAAc;;IAEd,cAAc;;CAEN,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,QAAQ;IACnB,WAAW;;IAEX,aAAa;;IAEb,aAAa;;IAEb,eAAe;;IAEf,YAAY;oCACW,MAAM;IAC7B,YAAY;yCACgB,MAAM;CAC1B,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,KAAK;IAChB,aAAa;;IAEb,aAAa;;IAEb,cAAc;;IAEd,aAAa;;IAEb,aAAa;;IAEb,aAAa;;CAEL,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,QAAQ;IACnB,WAAW;;IAEX,WAAW;;IAEX,YAAY;;CAEJ,CAAC"}
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ /**
3
+ * 常量定义模块
4
+ * 项目中使用的各种常量
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.APP_INFO = exports.HINTS = exports.MESSAGES = exports.PATTERNS = exports.LIMITS = exports.TIMEOUTS = exports.GIT = exports.COPY_EXCLUDES = exports.TABLE_COLUMNS = exports.DEFAULTS = exports.FILE_NAMES = exports.DIR_NAMES = void 0;
8
+ /**
9
+ * 目录名称常量
10
+ */
11
+ exports.DIR_NAMES = {
12
+ /** .gitreference 目录名 */
13
+ GITREFERENCE: ".gitreference",
14
+ /** .git 目录名 */
15
+ GIT: ".git",
16
+ };
17
+ /**
18
+ * 文件名称常量
19
+ */
20
+ exports.FILE_NAMES = {
21
+ /** 加载状态文件 */
22
+ LOADING_JSON: "loading.json",
23
+ /** 仓库元信息文件 */
24
+ META_JSON: "meta.json",
25
+ /** 旧版元信息文件名 */
26
+ GRF_META_JSON: ".grf-meta.json",
27
+ /** 旧版元信息文件名 */
28
+ GITREFERENCE_META_JSON: ".gitreference-meta.json",
29
+ /** Git 忽略文件 */
30
+ GITIGNORE: ".gitignore",
31
+ /** 全局配置文件 */
32
+ CONFIG_JSON: "config.json",
33
+ };
34
+ /**
35
+ * 默认值常量
36
+ */
37
+ exports.DEFAULTS = {
38
+ /** 默认分支名 */
39
+ BRANCH: "main",
40
+ /** 默认浅克隆深度 */
41
+ SHALLOW_DEPTH: 1,
42
+ /** 是否默认使用浅克隆 */
43
+ SHALLOW_CLONE: true,
44
+ /** 短 commit ID 长度 */
45
+ SHORT_COMMIT_LENGTH: 7,
46
+ };
47
+ /**
48
+ * 表格列宽常量
49
+ */
50
+ exports.TABLE_COLUMNS = {
51
+ /** 仓库名称列宽 */
52
+ NAME: 40,
53
+ /** 分支列宽 */
54
+ BRANCH: 15,
55
+ /** Commit ID 列宽 */
56
+ COMMIT: 10,
57
+ /** 日期列宽 */
58
+ DATE: 12,
59
+ /** 路径列宽 */
60
+ PATH: 30,
61
+ /** 状态列宽 */
62
+ STATUS: 15,
63
+ };
64
+ /**
65
+ * 排除的文件/目录列表(复制时排除)
66
+ */
67
+ exports.COPY_EXCLUDES = [
68
+ ".git",
69
+ "meta.json",
70
+ ".grf-meta.json",
71
+ ".gitreference-meta.json",
72
+ ];
73
+ /**
74
+ * Git 相关常量
75
+ */
76
+ exports.GIT = {
77
+ /** 远程名称 */
78
+ REMOTE_NAME: "origin",
79
+ /** 默认分支候选列表 */
80
+ DEFAULT_BRANCHES: ["main", "master"],
81
+ };
82
+ /**
83
+ * 超时设置(毫秒)
84
+ */
85
+ exports.TIMEOUTS = {
86
+ /** Git 操作超时 */
87
+ GIT_OPERATION: 60000,
88
+ /** 网络请求超时 */
89
+ NETWORK_REQUEST: 30000,
90
+ };
91
+ /**
92
+ * 限制设置
93
+ */
94
+ exports.LIMITS = {
95
+ /** 最大路径长度 */
96
+ MAX_PATH_LENGTH: 260,
97
+ /** 最大仓库名称长度 */
98
+ MAX_REPO_NAME_LENGTH: 255,
99
+ /** 最大并发操作数 */
100
+ MAX_CONCURRENT_OPERATIONS: 5,
101
+ };
102
+ /**
103
+ * 正则表达式模式
104
+ */
105
+ exports.PATTERNS = {
106
+ /** HTTPS Git URL */
107
+ HTTPS_GIT_URL: /^https?:\/\/[^/]+\/[^/]+\/[^/]+/,
108
+ /** SSH Git URL */
109
+ SSH_GIT_URL: /^git@[^:]+:[^/]+\/[^/]+/,
110
+ /** 非法文件名字符 */
111
+ INVALID_FILENAME_CHARS: /[<>:"|?*\x00-\x1f]/,
112
+ /** 非法分支名字符 */
113
+ INVALID_BRANCH_CHARS: /[\s~^:?*\[\]\\@{}\x00-\x1f\x7f]/,
114
+ };
115
+ /**
116
+ * 消息模板
117
+ */
118
+ exports.MESSAGES = {
119
+ /** 操作取消 */
120
+ OPERATION_CANCELLED: "Operation cancelled.",
121
+ /** 无仓库可清理 */
122
+ NO_REPOS_TO_CLEAN: "No repositories to clean.",
123
+ /** 无已缓存仓库 */
124
+ NO_CACHED_REPOS: "No repositories cached yet.",
125
+ /** 无已加载参考代码 */
126
+ NO_LOADED_REFS: "No loaded reference code in current project.",
127
+ /** 仓库未找到 */
128
+ REPO_NOT_FOUND: (name) => `Repository not found: ${name}`,
129
+ /** 仓库已存在 */
130
+ REPO_ALREADY_EXISTS: (name) => `Repository already exists: ${name}`,
131
+ };
132
+ /**
133
+ * 命令提示
134
+ */
135
+ exports.HINTS = {
136
+ /** 添加仓库提示 */
137
+ ADD_REPO: "Use 'grf add <url>' to add a repository.",
138
+ /** 查看列表提示 */
139
+ LIST_REPOS: "Use 'grf list' to see all cached repositories.",
140
+ /** 查看已加载提示 */
141
+ LIST_LOADED: "Use 'grf unload --list' to see all loaded reference code.",
142
+ /** 加载仓库提示 */
143
+ LOAD_REPO: "Use 'grf load <name>' to load reference code to workspace.",
144
+ /** 更新仓库提示 */
145
+ UPDATE_REPO: "Use 'grf update <name>' to update the repository.",
146
+ /** 清理仓库提示 */
147
+ CLEAN_REPO: "Use 'grf clean <name>' to remove the repository.",
148
+ };
149
+ /**
150
+ * 应用信息
151
+ */
152
+ exports.APP_INFO = {
153
+ /** 应用名称 */
154
+ NAME: "gitreference",
155
+ /** 命令名称 */
156
+ COMMAND: "grf",
157
+ /** 配置目录名 */
158
+ CONFIG_DIR: ".gitreference",
159
+ };
160
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * 错误处理模块
3
+ * 提供统一的错误处理工具
4
+ */
5
+ import { GrfError, ErrorCode } from "../types/index.js";
6
+ /**
7
+ * 错误处理选项
8
+ */
9
+ export interface HandleErrorOptions {
10
+ /** 是否退出进程 */
11
+ exit?: boolean;
12
+ /** 退出码 */
13
+ exitCode?: number;
14
+ /** 是否显示详细信息 */
15
+ verbose?: boolean;
16
+ /** 额外的提示信息 */
17
+ hints?: string[];
18
+ }
19
+ /**
20
+ * 统一处理错误并输出到控制台
21
+ * @param error 错误对象
22
+ * @param options 处理选项
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * try {
27
+ * await someOperation();
28
+ * } catch (error) {
29
+ * handleError(error, { exit: true });
30
+ * }
31
+ * ```
32
+ */
33
+ export declare function handleError(error: unknown, options?: HandleErrorOptions): void;
34
+ /**
35
+ * 获取错误消息
36
+ * @param error 错误对象
37
+ * @returns 错误消息字符串
38
+ */
39
+ export declare function getErrorMessage(error: unknown): string;
40
+ /**
41
+ * 创建一个 GrfError 实例
42
+ * @param code 错误码
43
+ * @param message 错误消息
44
+ * @returns GrfError 实例
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * throw createError(ErrorCode.REPO_NOT_FOUND, "Repository 'my-repo' not found");
49
+ * ```
50
+ */
51
+ export declare function createError(code: ErrorCode, message: string): GrfError;
52
+ /**
53
+ * 包装异步操作,统一处理错误
54
+ * @param operation 异步操作
55
+ * @param options 错误处理选项
56
+ * @returns 操作结果或 undefined(如果发生错误且不退出)
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const result = await wrapAsync(
61
+ * async () => await fetchData(),
62
+ * { exit: true }
63
+ * );
64
+ * ```
65
+ */
66
+ export declare function wrapAsync<T>(operation: () => Promise<T>, options?: HandleErrorOptions): Promise<T | undefined>;
67
+ /**
68
+ * 断言条件为真,否则抛出错误
69
+ * @param condition 条件
70
+ * @param code 错误码
71
+ * @param message 错误消息
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * assertCondition(repo !== null, ErrorCode.REPO_NOT_FOUND, "Repository not found");
76
+ * ```
77
+ */
78
+ export declare function assertCondition(condition: boolean, code: ErrorCode, message: string): asserts condition;
79
+ /**
80
+ * 断言值不为 null 或 undefined
81
+ * @param value 要检查的值
82
+ * @param code 错误码
83
+ * @param message 错误消息
84
+ * @returns 非空值
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * const repo = assertNotNull(
89
+ * await repository.get(name),
90
+ * ErrorCode.REPO_NOT_FOUND,
91
+ * `Repository '${name}' not found`
92
+ * );
93
+ * ```
94
+ */
95
+ export declare function assertNotNull<T>(value: T | null | undefined, code: ErrorCode, message: string): T;
96
+ /**
97
+ * 检查是否为 GrfError
98
+ * @param error 错误对象
99
+ * @returns 是否为 GrfError
100
+ */
101
+ export declare function isGrfError(error: unknown): error is GrfError;
102
+ /**
103
+ * 检查错误是否为特定错误码
104
+ * @param error 错误对象
105
+ * @param code 错误码
106
+ * @returns 是否匹配
107
+ */
108
+ export declare function isErrorCode(error: unknown, code: ErrorCode): boolean;
109
+ //# sourceMappingURL=error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/utils/error.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,aAAa;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU;IACV,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,kBAAuB,GAC/B,IAAI,CA+BN;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CActD;AAkED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ,CAEtE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAWxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,OAAO,EAClB,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAInB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,EAC3B,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,GACd,CAAC,CAKH;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAEpE"}