huozige-ontology-builder 0.1.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 (44) hide show
  1. package/README.md +157 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +72 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/core/errors.d.ts +4 -0
  6. package/dist/core/errors.js +9 -0
  7. package/dist/core/errors.js.map +1 -0
  8. package/dist/core/fs.d.ts +5 -0
  9. package/dist/core/fs.js +51 -0
  10. package/dist/core/fs.js.map +1 -0
  11. package/dist/core/git.d.ts +1 -0
  12. package/dist/core/git.js +24 -0
  13. package/dist/core/git.js.map +1 -0
  14. package/dist/core/json.d.ts +1 -0
  15. package/dist/core/json.js +16 -0
  16. package/dist/core/json.js.map +1 -0
  17. package/dist/core/output.d.ts +4 -0
  18. package/dist/core/output.js +169 -0
  19. package/dist/core/output.js.map +1 -0
  20. package/dist/core/parser.d.ts +2 -0
  21. package/dist/core/parser.js +31 -0
  22. package/dist/core/parser.js.map +1 -0
  23. package/dist/core/parsers/pages.d.ts +2 -0
  24. package/dist/core/parsers/pages.js +543 -0
  25. package/dist/core/parsers/pages.js.map +1 -0
  26. package/dist/core/parsers/server-commands.d.ts +2 -0
  27. package/dist/core/parsers/server-commands.js +340 -0
  28. package/dist/core/parsers/server-commands.js.map +1 -0
  29. package/dist/core/parsers/shared/forguncy-json.d.ts +10 -0
  30. package/dist/core/parsers/shared/forguncy-json.js +113 -0
  31. package/dist/core/parsers/shared/forguncy-json.js.map +1 -0
  32. package/dist/core/parsers/shared/normalize.d.ts +3 -0
  33. package/dist/core/parsers/shared/normalize.js +15 -0
  34. package/dist/core/parsers/shared/normalize.js.map +1 -0
  35. package/dist/core/parsers/tables.d.ts +2 -0
  36. package/dist/core/parsers/tables.js +109 -0
  37. package/dist/core/parsers/tables.js.map +1 -0
  38. package/dist/types/output.d.ts +50 -0
  39. package/dist/types/output.js +2 -0
  40. package/dist/types/output.js.map +1 -0
  41. package/dist/types/schema.d.ts +68 -0
  42. package/dist/types/schema.js +2 -0
  43. package/dist/types/schema.js.map +1 -0
  44. package/package.json +34 -0
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # huozige-ontology-builder
2
+
3
+ 一个可发布到 npm 的 TypeScript CLI,用纯规则方式解析活字格工程,提取:
4
+
5
+ - 表结构
6
+ - 公开服务端命令
7
+ - 服务端命令在页面中的引用位置
8
+
9
+ 整个解析过程不使用 AI,只依赖文件扫描、JSON 结构分析和固定规则。
10
+
11
+ ## 解析范围
12
+
13
+ - 表:`Tables/*.json`
14
+ - 服务端命令:`ServerCommands/*.json`
15
+ - 页面引用:`Pages/**/*.json`、`MasterPages/**/*.json`
16
+
17
+ 当前“公开服务端命令”的判定规则是:
18
+
19
+ - `ServerCommands` 中存在 `PostRequestTrigger`
20
+
21
+ ## 输出模板
22
+
23
+ CLI 输出遵循当前项目约定的模板结构:
24
+
25
+ ```json
26
+ {
27
+ "repo-name": "simple-forguncy-reporting-system",
28
+ "huozige-version": "11.0.104.0",
29
+ "builder-version": "0.1.0",
30
+ "tables": [
31
+ {
32
+ "table-name": "工序",
33
+ "table-description": "存储工序信息",
34
+ "columns": [
35
+ {
36
+ "column-name": "工序编号",
37
+ "column-alias": "工序唯一标识",
38
+ "column-datatype": "Number",
39
+ "column-required": true,
40
+ "column-unique": true
41
+ }
42
+ ]
43
+ }
44
+ ],
45
+ "servercommands": [
46
+ {
47
+ "servercommand-name": "添加报工记录",
48
+ "servercommand-description": "PostRequestTrigger",
49
+ "verb": "post",
50
+ "input-arguments": [
51
+ {
52
+ "argument-name": "工序编号",
53
+ "argument-type": "number",
54
+ "argument-description": "type=number; source=Triggers.$values[].Parameters",
55
+ "argument-required": true
56
+ }
57
+ ],
58
+ "output-arguments": [
59
+ {
60
+ "argument-name": "OrderID",
61
+ "argument-type": "unknown",
62
+ "argument-description": "type=unknown; source=ReturnProperties",
63
+ "argument-required": true
64
+ }
65
+ ],
66
+ "used-by": []
67
+ }
68
+ ]
69
+ }
70
+ ```
71
+
72
+ 字段说明:
73
+
74
+ - `repo-name`:仓库目录名。
75
+ - `huozige-version`:从 `DocumentInfo` 中读取的活字格版本。
76
+ - `builder-version`:当前解析器版本,来自工具自身的 `package.json`。
77
+ - `tables`:工程中的逻辑表定义。
78
+ - `servercommands`:公开服务端命令列表。
79
+ - `input-arguments`:来自 `PostRequestTrigger.Parameters`。
80
+ - `input-arguments[].argument-type`:确定性推导出的参数类型。
81
+ - `output-arguments`:来自 `ReturnProperties`,并结合命令流推导返回值类型。
82
+ - `output-arguments[].argument-type`:确定性推导出的返回参数类型。
83
+ - `used-by`:页面中对该服务端命令的引用位置。
84
+ - `used-by[].page`:页面相对路径,不带 `.json` 后缀。
85
+ - `used-by[].page-title`:页面标题,来自 `PageInfo.Title`。
86
+ - `used-by[].location`:人类可读的位置说明。
87
+ - `used-by[].component-type`:组件类型,例如 `Button`、`ComboBox`。
88
+ - `used-by[].event`:触发事件,例如 `click`、`change`、`page-load`。
89
+
90
+ ## 安装
91
+
92
+ 默认使用方式:
93
+
94
+ ```bash
95
+ npm install -g huozige-ontology-builder
96
+ ```
97
+
98
+ ## 使用
99
+
100
+ 安装完成后,直接执行 CLI:
101
+
102
+ ```bash
103
+ hzg-ontology-builder https://gitee.com/nimotea/simple-forguncy-reporting-system --out sample.json
104
+ ```
105
+
106
+ 本地开发调试时再使用源码构建后的入口:
107
+
108
+ ```bash
109
+ npm install
110
+ npm run build
111
+ node dist/cli.js https://gitee.com/nimotea/simple-forguncy-reporting-system --workdir /tmp --out sample.json
112
+ ```
113
+
114
+ 参数说明:
115
+
116
+ - `--out <file>`:输出文件路径,默认 `./ontology-output.json`
117
+ - `--workdir <dir>`:克隆目标仓库时使用的工作目录,默认 `./.tmp`
118
+
119
+ ## 代码结构
120
+
121
+ - [src/core/parser.ts](/Users/ningwei/VSCodeProjects/huozige-ontology-builder/src/core/parser.ts)
122
+ 负责聚合各解析器并合并结果
123
+ - [src/core/parsers/server-commands.ts](/Users/ningwei/VSCodeProjects/huozige-ontology-builder/src/core/parsers/server-commands.ts)
124
+ 负责解析公开服务端命令、输入参数、输出参数
125
+ - [src/core/parsers/pages.ts](/Users/ningwei/VSCodeProjects/huozige-ontology-builder/src/core/parsers/pages.ts)
126
+ 负责解析页面中的 `RequestServerCommand` 引用和触发位置
127
+ - [src/core/parsers/tables.ts](/Users/ningwei/VSCodeProjects/huozige-ontology-builder/src/core/parsers/tables.ts)
128
+ 负责解析逻辑表定义
129
+ - [src/core/parsers/shared/forguncy-json.ts](/Users/ningwei/VSCodeProjects/huozige-ontology-builder/src/core/parsers/shared/forguncy-json.ts)
130
+ 负责活字格导出 JSON 的容错解析
131
+
132
+ ## 设计约束
133
+
134
+ - 不使用 AI 推断内容
135
+ - 同一份输入应产生稳定输出
136
+ - 不直接依赖活字格运行时
137
+ - 优先解析导出的设计期 JSON,而不是运行时数据库
138
+
139
+ ## 示例文件
140
+
141
+ - 样例模板:[src/sample.json](/Users/ningwei/VSCodeProjects/huozige-ontology-builder/src/sample.json)
142
+ - 示例输出 1:[sample.json](/Users/ningwei/VSCodeProjects/huozige-ontology-builder/sample.json)
143
+ - 示例输出 2:[sample-simple-reporting.json](/Users/ningwei/VSCodeProjects/huozige-ontology-builder/sample-simple-reporting.json)
144
+
145
+ ## 校验与发布
146
+
147
+ ```bash
148
+ npm run check
149
+ npm run build
150
+ env npm_config_cache=/tmp/hzg-ontology-builder-npm-cache npm pack --dry-run
151
+ ```
152
+
153
+ 正式发布:
154
+
155
+ ```bash
156
+ npm publish
157
+ ```
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+ import path from 'node:path';
3
+ import process from 'node:process';
4
+ import { cloneRepo } from './core/git.js';
5
+ import { ensureDir, exists, writeText } from './core/fs.js';
6
+ import { buildSampleOutput, stringifyOutput } from './core/output.js';
7
+ import { extractInterfaces } from './core/parser.js';
8
+ import { CliError } from './core/errors.js';
9
+ function printHelp() {
10
+ process.stdout.write([
11
+ 'Usage: hzg-ontology-builder <git-url> [options]',
12
+ '',
13
+ 'Options:',
14
+ ' --out <file> Output JSON file path. Default: ./ontology-output.json',
15
+ ' --workdir <dir> Directory used to clone the target repository. Default: ./.tmp',
16
+ ' -h, --help Show this help message',
17
+ '',
18
+ ].join('\n'));
19
+ }
20
+ function parseArgs(argv) {
21
+ if (argv.includes('-h') || argv.includes('--help')) {
22
+ printHelp();
23
+ process.exit(0);
24
+ }
25
+ const positional = argv.filter((value) => !value.startsWith('-'));
26
+ if (positional.length === 0) {
27
+ throw new CliError('missing required git repository url');
28
+ }
29
+ const repoUrl = positional[0];
30
+ let outFile = path.resolve('ontology-output.json');
31
+ let workdir = path.resolve('.tmp');
32
+ for (let index = 0; index < argv.length; index += 1) {
33
+ const current = argv[index];
34
+ if (current === '--out') {
35
+ outFile = path.resolve(argv[index + 1] ?? '');
36
+ index += 1;
37
+ }
38
+ else if (current === '--workdir') {
39
+ workdir = path.resolve(argv[index + 1] ?? '');
40
+ index += 1;
41
+ }
42
+ }
43
+ return { repoUrl, outFile, workdir };
44
+ }
45
+ function repoDirName(repoUrl) {
46
+ const trimmed = repoUrl.replace(/\/+$/, '');
47
+ const lastSegment = trimmed.split('/').at(-1) ?? 'repo';
48
+ return lastSegment.endsWith('.git') ? lastSegment.slice(0, -4) : lastSegment;
49
+ }
50
+ async function main() {
51
+ const options = parseArgs(process.argv.slice(2));
52
+ await ensureDir(options.workdir);
53
+ const repoPath = path.join(options.workdir, repoDirName(options.repoUrl));
54
+ if (!(await exists(repoPath))) {
55
+ await cloneRepo(options.repoUrl, repoPath);
56
+ }
57
+ const result = await extractInterfaces(options.repoUrl, repoPath);
58
+ const output = await buildSampleOutput(result);
59
+ await writeText(options.outFile, stringifyOutput(output));
60
+ process.stdout.write(`analysis written to ${options.outFile}\n`);
61
+ }
62
+ main().catch((error) => {
63
+ if (error instanceof CliError) {
64
+ process.stderr.write(`${error.message}\n`);
65
+ process.exit(error.exitCode);
66
+ return;
67
+ }
68
+ const message = error instanceof Error ? error.stack ?? error.message : String(error);
69
+ process.stderr.write(`${message}\n`);
70
+ process.exit(1);
71
+ });
72
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare class CliError extends Error {
2
+ readonly exitCode: number;
3
+ constructor(message: string, exitCode?: number);
4
+ }
@@ -0,0 +1,9 @@
1
+ export class CliError extends Error {
2
+ exitCode;
3
+ constructor(message, exitCode = 1) {
4
+ super(message);
5
+ this.exitCode = exitCode;
6
+ this.name = 'CliError';
7
+ }
8
+ }
9
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACK;IAAtC,YAAY,OAAe,EAAW,WAAW,CAAC;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QADqB,aAAQ,GAAR,QAAQ,CAAI;QAEhD,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ export declare function ensureDir(targetPath: string): Promise<void>;
2
+ export declare function exists(targetPath: string): Promise<boolean>;
3
+ export declare function readText(targetPath: string): Promise<string>;
4
+ export declare function writeText(targetPath: string, content: string): Promise<void>;
5
+ export declare function walkFiles(rootDir: string): Promise<string[]>;
@@ -0,0 +1,51 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ const DEFAULT_IGNORES = new Set([
4
+ '.git',
5
+ 'node_modules',
6
+ 'dist',
7
+ 'coverage',
8
+ '.idea',
9
+ '.vscode',
10
+ ]);
11
+ export async function ensureDir(targetPath) {
12
+ await fs.mkdir(targetPath, { recursive: true });
13
+ }
14
+ export async function exists(targetPath) {
15
+ try {
16
+ await fs.access(targetPath);
17
+ return true;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ export async function readText(targetPath) {
24
+ return fs.readFile(targetPath, 'utf8');
25
+ }
26
+ export async function writeText(targetPath, content) {
27
+ await ensureDir(path.dirname(targetPath));
28
+ await fs.writeFile(targetPath, content, 'utf8');
29
+ }
30
+ export async function walkFiles(rootDir) {
31
+ const results = [];
32
+ async function visit(currentDir) {
33
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
34
+ for (const entry of entries) {
35
+ if (DEFAULT_IGNORES.has(entry.name)) {
36
+ continue;
37
+ }
38
+ const fullPath = path.join(currentDir, entry.name);
39
+ if (entry.isDirectory()) {
40
+ await visit(fullPath);
41
+ }
42
+ else if (entry.isFile()) {
43
+ results.push(fullPath);
44
+ }
45
+ }
46
+ }
47
+ await visit(rootDir);
48
+ results.sort((left, right) => left.localeCompare(right));
49
+ return results;
50
+ }
51
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/core/fs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,MAAM;IACN,cAAc;IACd,MAAM;IACN,UAAU;IACV,OAAO;IACP,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,UAAkB;IAChD,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,UAAkB;IAC7C,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,UAAkB;IAC/C,OAAO,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,UAAkB,EAAE,OAAe;IACjE,MAAM,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAC1C,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe;IAC7C,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,UAAU,KAAK,CAAC,UAAkB;QACrC,MAAM,OAAO,GAAa,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAEhF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpC,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACnD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBAC1B,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function cloneRepo(repoUrl: string, targetDir: string): Promise<void>;
@@ -0,0 +1,24 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { CliError } from './errors.js';
3
+ function runGit(args, cwd) {
4
+ return new Promise((resolve, reject) => {
5
+ const child = spawn('git', args, {
6
+ cwd,
7
+ stdio: 'inherit',
8
+ });
9
+ child.on('error', (error) => {
10
+ reject(new CliError(`failed to run git: ${error.message}`));
11
+ });
12
+ child.on('exit', (code) => {
13
+ if (code === 0) {
14
+ resolve();
15
+ return;
16
+ }
17
+ reject(new CliError(`git ${args.join(' ')} exited with code ${code ?? 'unknown'}`));
18
+ });
19
+ });
20
+ }
21
+ export async function cloneRepo(repoUrl, targetDir) {
22
+ await runGit(['clone', '--depth', '1', repoUrl, targetDir]);
23
+ }
24
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/core/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,SAAS,MAAM,CAAC,IAAc,EAAE,GAAY;IAC1C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE;YAC/B,GAAG;YACH,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,MAAM,CAAC,IAAI,QAAQ,CAAC,sBAAsB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YAED,MAAM,CAAC,IAAI,QAAQ,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,qBAAqB,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC;QACtF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,SAAiB;IAChE,MAAM,MAAM,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function stringifyStable(value: unknown): string;
@@ -0,0 +1,16 @@
1
+ export function stringifyStable(value) {
2
+ return JSON.stringify(sortValue(value), null, 2);
3
+ }
4
+ function sortValue(value) {
5
+ if (Array.isArray(value)) {
6
+ return value.map(sortValue);
7
+ }
8
+ if (value && typeof value === 'object') {
9
+ const entries = Object.entries(value)
10
+ .sort(([left], [right]) => left.localeCompare(right))
11
+ .map(([key, entryValue]) => [key, sortValue(entryValue)]);
12
+ return Object.fromEntries(entries);
13
+ }
14
+ return value;
15
+ }
16
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/core/json.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC;aAC7D,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;aACpD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAE5D,OAAO,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ExtractionResult } from '../types/schema.js';
2
+ import type { SampleOutput } from '../types/output.js';
3
+ export declare function buildSampleOutput(result: ExtractionResult): Promise<SampleOutput>;
4
+ export declare function stringifyOutput(output: SampleOutput): string;
@@ -0,0 +1,169 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { readText } from './fs.js';
4
+ export async function buildSampleOutput(result) {
5
+ return {
6
+ 'repo-name': path.basename(result.repoPath),
7
+ 'huozige-version': await readHuozigeVersion(result.repoPath),
8
+ 'builder-version': await readBuilderVersion(),
9
+ tables: result.tables.map(toSampleTable).sort((left, right) => left['table-name'].localeCompare(right['table-name'])),
10
+ servercommands: result.interfaces
11
+ .map((item) => toSampleServerCommand(item))
12
+ .sort((left, right) => left['servercommand-name'].localeCompare(right['servercommand-name'])),
13
+ };
14
+ }
15
+ async function readHuozigeVersion(repoPath) {
16
+ try {
17
+ const content = await readText(path.join(repoPath, 'DocumentInfo'));
18
+ const parsed = JSON.parse(content);
19
+ return typeof parsed.VersionString === 'string' ? parsed.VersionString : 'unknown';
20
+ }
21
+ catch {
22
+ return 'unknown';
23
+ }
24
+ }
25
+ async function readBuilderVersion() {
26
+ try {
27
+ const currentFilePath = fileURLToPath(import.meta.url);
28
+ const packageJsonPath = path.resolve(path.dirname(currentFilePath), '../../package.json');
29
+ const content = await readText(packageJsonPath);
30
+ const parsed = JSON.parse(content);
31
+ return typeof parsed.version === 'string' ? parsed.version : 'unknown';
32
+ }
33
+ catch {
34
+ return 'unknown';
35
+ }
36
+ }
37
+ function toSampleServerCommand(item) {
38
+ return {
39
+ 'servercommand-name': item.name,
40
+ 'servercommand-description': item.description || 'PostRequestTrigger',
41
+ verb: item.method.toLowerCase(),
42
+ 'input-arguments': item.input
43
+ .map(toSampleArgument)
44
+ .sort((left, right) => left['argument-name'].localeCompare(right['argument-name'])),
45
+ 'output-arguments': item.output
46
+ .map(toSampleArgument)
47
+ .sort((left, right) => left['argument-name'].localeCompare(right['argument-name'])),
48
+ 'used-by': item.usages.map((usage) => toSampleUsage(item.name, usage)).sort(compareUsage),
49
+ };
50
+ }
51
+ function toSampleArgument(field) {
52
+ return {
53
+ 'argument-name': field.name,
54
+ 'argument-type': normalizeArgumentType(field.type),
55
+ 'argument-description': formatArgumentDescription(field),
56
+ 'argument-sharp': field.shape ?? null,
57
+ 'argument-required': field.required,
58
+ };
59
+ }
60
+ function toSampleUsage(_serverCommandName, usage) {
61
+ return {
62
+ page: toPagePath(usage),
63
+ 'page-title': usage.location.pageTitle ?? '',
64
+ location: usage.location.description,
65
+ 'component-type': usage.location.trigger === 'page-load' ? 'page' : toComponentType(usage.location.componentName),
66
+ event: toEventName(usage.location.eventName, usage.location.trigger),
67
+ };
68
+ }
69
+ function compareUsage(left, right) {
70
+ return left.location.localeCompare(right.location);
71
+ }
72
+ export function stringifyOutput(output) {
73
+ return `${JSON.stringify(output, null, 2)}\n`;
74
+ }
75
+ function toSampleTable(table) {
76
+ return {
77
+ 'table-name': table.name,
78
+ 'table-description': table.description,
79
+ columns: table.columns.map(toSampleColumn).sort((left, right) => left['column-name'].localeCompare(right['column-name'])),
80
+ relationships: table.relationships
81
+ .map(toSampleRelationship)
82
+ .sort((left, right) => left['column-name'].localeCompare(right['column-name'])),
83
+ };
84
+ }
85
+ function toSampleColumn(column) {
86
+ return {
87
+ 'column-name': column.name,
88
+ 'column-alias': column.alias,
89
+ 'column-datatype': column.dataType,
90
+ 'column-required': column.required,
91
+ 'column-unique': column.unique,
92
+ };
93
+ }
94
+ function toSampleRelationship(relationship) {
95
+ return {
96
+ 'column-name': relationship.columnName,
97
+ 'related-table': relationship.relatedTable,
98
+ 'related-table-column-name': relationship.relatedTableColumnName,
99
+ 'relationship-type': relationship.relationshipType,
100
+ 'relationship-is-master-slave': relationship.relationshipIsMasterSlave,
101
+ };
102
+ }
103
+ function formatArgumentDescription(field) {
104
+ return field.description ?? '';
105
+ }
106
+ function normalizeArgumentType(type) {
107
+ return type === 'unknown' ? 'basic' : type;
108
+ }
109
+ function toPagePath(usage) {
110
+ return usage.location.filePath.replace(/\.json$/i, '');
111
+ }
112
+ function toComponentType(componentName) {
113
+ if (!componentName) {
114
+ return 'Unknown';
115
+ }
116
+ if (componentName.endsWith('按钮')) {
117
+ return 'Button';
118
+ }
119
+ if (componentName.endsWith('组合框')) {
120
+ return 'ComboBox';
121
+ }
122
+ if (componentName.endsWith('下拉列表')) {
123
+ return 'DropDownList';
124
+ }
125
+ if (componentName.endsWith('复选框')) {
126
+ return 'CheckBox';
127
+ }
128
+ if (componentName.endsWith('单选框')) {
129
+ return 'RadioButton';
130
+ }
131
+ if (componentName.endsWith('文本框')) {
132
+ return 'TextBox';
133
+ }
134
+ if (componentName.endsWith('图片')) {
135
+ return 'Image';
136
+ }
137
+ if (componentName.endsWith('超链接')) {
138
+ return 'Hyperlink';
139
+ }
140
+ return 'Unknown';
141
+ }
142
+ function toEventName(eventName, trigger) {
143
+ if (eventName === '点击') {
144
+ return 'click';
145
+ }
146
+ if (eventName === '值改变') {
147
+ return 'change';
148
+ }
149
+ if (eventName === '获得焦点') {
150
+ return 'focus';
151
+ }
152
+ if (eventName === '上传成功') {
153
+ return 'upload-success';
154
+ }
155
+ if (eventName === '页面加载') {
156
+ return 'page-load';
157
+ }
158
+ if (eventName === '定时触发') {
159
+ return 'timer';
160
+ }
161
+ if (trigger === 'button-click') {
162
+ return 'click';
163
+ }
164
+ if (trigger === 'page-load') {
165
+ return 'page-load';
166
+ }
167
+ return 'unknown';
168
+ }
169
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/core/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { ExtractionResult } from '../types/schema.js';
2
+ export declare function extractInterfaces(repoUrl: string, repoPath: string): Promise<ExtractionResult>;
@@ -0,0 +1,31 @@
1
+ import path from 'node:path';
2
+ import { loadPageUsages } from './parsers/pages.js';
3
+ import { loadServerCommands } from './parsers/server-commands.js';
4
+ import { loadTables } from './parsers/tables.js';
5
+ import { uniqueSorted } from './parsers/shared/normalize.js';
6
+ // 聚合三个确定性解析器,并把页面中的引用关系回填到公开服务端命令上。
7
+ export async function extractInterfaces(repoUrl, repoPath) {
8
+ const normalizedRepoPath = path.resolve(repoPath);
9
+ const warnings = [];
10
+ const commands = await loadServerCommands(path.join(normalizedRepoPath, 'ServerCommands'), normalizedRepoPath, warnings);
11
+ const usages = await loadPageUsages(normalizedRepoPath, warnings);
12
+ const tables = await loadTables(path.join(normalizedRepoPath, 'Tables'), normalizedRepoPath, warnings);
13
+ for (const usage of usages) {
14
+ const target = commands.get(usage.name);
15
+ if (!target) {
16
+ warnings.push(`page usage references missing server command "${usage.name}" in ${usage.location.filePath}`);
17
+ continue;
18
+ }
19
+ target.usages.push(usage);
20
+ target.sourceFiles = uniqueSorted([...target.sourceFiles, usage.location.filePath]);
21
+ }
22
+ return {
23
+ repoUrl,
24
+ repoPath: normalizedRepoPath,
25
+ scannedAt: new Date().toISOString(),
26
+ interfaces: [...commands.values()].sort((left, right) => left.name.localeCompare(right.name)),
27
+ tables,
28
+ warnings: uniqueSorted(warnings),
29
+ };
30
+ }
31
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/core/parser.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,oCAAoC;AACpC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAe,EAAE,QAAgB;IACvE,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CACvC,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,EAC/C,kBAAkB,EAClB,QAAQ,CACT,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IAEvG,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,QAAQ,CAAC,IAAI,CACX,iDAAiD,KAAK,CAAC,IAAI,QAAQ,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAC7F,CAAC;YACF,SAAS;QACX,CAAC;QAED,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,MAAM,CAAC,WAAW,GAAG,YAAY,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtF,CAAC;IAED,OAAO;QACL,OAAO;QACP,QAAQ,EAAE,kBAAkB;QAC5B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,UAAU,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7F,MAAM;QACN,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC;KACjC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { InterfaceUsage } from '../../types/schema.js';
2
+ export declare function loadPageUsages(repoRoot: string, warnings: string[]): Promise<InterfaceUsage[]>;