cgraphx 1.1.0 → 1.3.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.
- package/README.md +0 -1
- package/dist/.claude-template/hooks/precommit-check/precommit-check.cjs +90 -0
- package/dist/.claude-template/skills/cgraphx/SKILL.md +3 -3
- package/dist/.claude-template/skills/cgraphx/agent-prompt.md +1 -1
- package/dist/.claude-template/skills/cgraphx-guide/SKILL.md +94 -0
- package/dist/.claude-template/skills/cgraphx-guide/how-to-use.html +424 -0
- package/dist/.claude-template/skills/clarify-requirements/SKILL.md +19 -8
- package/dist/.claude-template/skills/code-impact-docgen/SKILL.md +186 -176
- package/dist/.claude-template/skills/code-impact-docgen/template-design-html.md +357 -0
- package/dist/.claude-template/skills/code-impact-docgen/template-design-md.md +164 -0
- package/dist/.claude-template/skills/code-impact-init/SKILL.md +47 -47
- package/dist/.claude-template/skills/developer-timeline/SKILL.md +9 -0
- package/dist/.claude-template/skills/precommit-review/SKILL.md +50 -0
- package/dist/.claude-template/skills/run-api-test/SKILL.md +187 -0
- package/dist/.claude-template/skills/run-api-test/assets/template-test-report.md +103 -0
- package/dist/.claude-template/skills/run-api-test/assets/template-test-verify.jsonl +5 -0
- package/dist/.claude-template/skills/run-api-test/references/bru-run.md +60 -0
- package/dist/.claude-template/skills/run-api-test/references/db-verification.md +81 -0
- package/dist/.claude-template/skills/run-api-test/references/report-format.md +104 -0
- package/dist/.claude-template/skills/run-api-test/references/service-readiness.md +61 -0
- package/dist/.claude-template/skills/run-api-test/references/test-scope.md +64 -0
- package/dist/.claude-template/skills/write-api/SKILL.md +150 -0
- package/dist/.claude-template/skills/write-api/assets/template-api-spec.md +112 -0
- package/dist/.claude-template/skills/write-api/assets/template-request.bru +75 -0
- package/dist/.claude-template/skills/write-api/references/ai-prompts.md +133 -0
- package/dist/.claude-template/skills/write-api/references/api-spec-format.md +108 -0
- package/dist/.claude-template/skills/write-api/references/bru-format.md +144 -0
- package/dist/.claude-template/skills/write-api/references/collection-layout.md +81 -0
- package/dist/.claude-template/skills/write-api/references/environment-setup.md +105 -0
- package/dist/.claude-template/skills/write-api/references/interface-scope.md +74 -0
- package/dist/.claude-template/skills/write-api-doc/SKILL.md +317 -0
- package/dist/.claude-template/skills/write-api-doc/template-api-html.md +422 -0
- package/dist/.claude-template/skills/write-plan/SKILL.md +38 -16
- package/dist/.claude-template/skills/write-prd/SKILL.md +32 -8
- package/dist/.claude-template/skills/write-spec/SKILL.md +34 -9
- package/dist/api-test/ai-fields.d.ts +37 -0
- package/dist/api-test/ai-fields.d.ts.map +1 -0
- package/dist/api-test/ai-fields.js +114 -0
- package/dist/api-test/ai-fields.js.map +1 -0
- package/dist/api-test/assemble.d.ts +76 -0
- package/dist/api-test/assemble.d.ts.map +1 -0
- package/dist/api-test/assemble.js +185 -0
- package/dist/api-test/assemble.js.map +1 -0
- package/dist/api-test/bru-cli-invoker.d.ts +72 -0
- package/dist/api-test/bru-cli-invoker.d.ts.map +1 -0
- package/dist/api-test/bru-cli-invoker.js +169 -0
- package/dist/api-test/bru-cli-invoker.js.map +1 -0
- package/dist/api-test/bru-report-parser.d.ts +24 -0
- package/dist/api-test/bru-report-parser.d.ts.map +1 -0
- package/dist/api-test/bru-report-parser.js +110 -0
- package/dist/api-test/bru-report-parser.js.map +1 -0
- package/dist/api-test/bru-runner.d.ts +101 -0
- package/dist/api-test/bru-runner.d.ts.map +1 -0
- package/dist/api-test/bru-runner.js +316 -0
- package/dist/api-test/bru-runner.js.map +1 -0
- package/dist/api-test/bru-writer.d.ts +52 -0
- package/dist/api-test/bru-writer.d.ts.map +1 -0
- package/dist/api-test/bru-writer.js +159 -0
- package/dist/api-test/bru-writer.js.map +1 -0
- package/dist/api-test/call-chain-extractor.d.ts +80 -0
- package/dist/api-test/call-chain-extractor.d.ts.map +1 -0
- package/dist/api-test/call-chain-extractor.js +179 -0
- package/dist/api-test/call-chain-extractor.js.map +1 -0
- package/dist/api-test/cli.d.ts +133 -0
- package/dist/api-test/cli.d.ts.map +1 -0
- package/dist/api-test/cli.js +1009 -0
- package/dist/api-test/cli.js.map +1 -0
- package/dist/api-test/config.d.ts +75 -0
- package/dist/api-test/config.d.ts.map +1 -0
- package/dist/api-test/config.js +406 -0
- package/dist/api-test/config.js.map +1 -0
- package/dist/api-test/db-query-cli.d.ts +51 -0
- package/dist/api-test/db-query-cli.d.ts.map +1 -0
- package/dist/api-test/db-query-cli.js +119 -0
- package/dist/api-test/db-query-cli.js.map +1 -0
- package/dist/api-test/enhance-prepare.d.ts +111 -0
- package/dist/api-test/enhance-prepare.d.ts.map +1 -0
- package/dist/api-test/enhance-prepare.js +425 -0
- package/dist/api-test/enhance-prepare.js.map +1 -0
- package/dist/api-test/enhance-write.d.ts +28 -0
- package/dist/api-test/enhance-write.d.ts.map +1 -0
- package/dist/api-test/enhance-write.js +145 -0
- package/dist/api-test/enhance-write.js.map +1 -0
- package/dist/api-test/errors.d.ts +48 -0
- package/dist/api-test/errors.d.ts.map +1 -0
- package/dist/api-test/errors.js +76 -0
- package/dist/api-test/errors.js.map +1 -0
- package/dist/api-test/field-extractor.d.ts +98 -0
- package/dist/api-test/field-extractor.d.ts.map +1 -0
- package/dist/api-test/field-extractor.js +327 -0
- package/dist/api-test/field-extractor.js.map +1 -0
- package/dist/api-test/impl-finder.d.ts +37 -0
- package/dist/api-test/impl-finder.d.ts.map +1 -0
- package/dist/api-test/impl-finder.js +54 -0
- package/dist/api-test/impl-finder.js.map +1 -0
- package/dist/api-test/index.d.ts +41 -0
- package/dist/api-test/index.d.ts.map +1 -0
- package/dist/api-test/index.js +124 -0
- package/dist/api-test/index.js.map +1 -0
- package/dist/api-test/java-parser.d.ts +89 -0
- package/dist/api-test/java-parser.d.ts.map +1 -0
- package/dist/api-test/java-parser.js +508 -0
- package/dist/api-test/java-parser.js.map +1 -0
- package/dist/api-test/md-writer.d.ts +49 -0
- package/dist/api-test/md-writer.d.ts.map +1 -0
- package/dist/api-test/md-writer.js +202 -0
- package/dist/api-test/md-writer.js.map +1 -0
- package/dist/api-test/parser-httpservice.d.ts +91 -0
- package/dist/api-test/parser-httpservice.d.ts.map +1 -0
- package/dist/api-test/parser-httpservice.js +271 -0
- package/dist/api-test/parser-httpservice.js.map +1 -0
- package/dist/api-test/report.d.ts +188 -0
- package/dist/api-test/report.d.ts.map +1 -0
- package/dist/api-test/report.js +522 -0
- package/dist/api-test/report.js.map +1 -0
- package/dist/api-test/snapshot.d.ts +26 -0
- package/dist/api-test/snapshot.d.ts.map +1 -0
- package/dist/api-test/snapshot.js +150 -0
- package/dist/api-test/snapshot.js.map +1 -0
- package/dist/api-test/test-history.d.ts +48 -0
- package/dist/api-test/test-history.d.ts.map +1 -0
- package/dist/api-test/test-history.js +122 -0
- package/dist/api-test/test-history.js.map +1 -0
- package/dist/api-test/types.d.ts +174 -0
- package/dist/api-test/types.d.ts.map +1 -0
- package/dist/api-test/types.js +13 -0
- package/dist/api-test/types.js.map +1 -0
- package/dist/api-test/verify-prepare.d.ts +30 -0
- package/dist/api-test/verify-prepare.d.ts.map +1 -0
- package/dist/api-test/verify-prepare.js +150 -0
- package/dist/api-test/verify-prepare.js.map +1 -0
- package/dist/api-test/verify-write.d.ts +31 -0
- package/dist/api-test/verify-write.d.ts.map +1 -0
- package/dist/api-test/verify-write.js +159 -0
- package/dist/api-test/verify-write.js.map +1 -0
- package/dist/bin/codegraph.js +0 -100
- package/dist/bin/codegraph.js.map +1 -1
- package/dist/dbquery/dump-schema.d.ts +46 -0
- package/dist/dbquery/dump-schema.d.ts.map +1 -0
- package/dist/dbquery/dump-schema.js +379 -0
- package/dist/dbquery/dump-schema.js.map +1 -0
- package/dist/installer/targets/claude.d.ts +15 -0
- package/dist/installer/targets/claude.d.ts.map +1 -1
- package/dist/installer/targets/claude.js +53 -0
- package/dist/installer/targets/claude.js.map +1 -1
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +13 -0
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/scope-index.d.ts +86 -0
- package/dist/resolution/scope-index.d.ts.map +1 -0
- package/dist/resolution/scope-index.js +143 -0
- package/dist/resolution/scope-index.js.map +1 -0
- package/dist/resolution/stdlib-blocklist.d.ts +53 -0
- package/dist/resolution/stdlib-blocklist.d.ts.map +1 -0
- package/dist/resolution/stdlib-blocklist.js +143 -0
- package/dist/resolution/stdlib-blocklist.js.map +1 -0
- package/dist/search/ast-helpers.d.ts +42 -0
- package/dist/search/ast-helpers.d.ts.map +1 -0
- package/dist/search/ast-helpers.js +106 -0
- package/dist/search/ast-helpers.js.map +1 -0
- package/dist/search/call-sites.d.ts +398 -0
- package/dist/search/call-sites.d.ts.map +1 -0
- package/dist/search/call-sites.js +1433 -0
- package/dist/search/call-sites.js.map +1 -0
- package/dist/search/context.d.ts +134 -0
- package/dist/search/context.d.ts.map +1 -0
- package/dist/search/context.js +575 -0
- package/dist/search/context.js.map +1 -0
- package/dist/search/impact.d.ts +139 -0
- package/dist/search/impact.d.ts.map +1 -0
- package/dist/search/impact.js +646 -0
- package/dist/search/impact.js.map +1 -0
- package/dist/search/related.d.ts +178 -0
- package/dist/search/related.d.ts.map +1 -0
- package/dist/search/related.js +667 -0
- package/dist/search/related.js.map +1 -0
- package/dist/search/slice.d.ts +148 -0
- package/dist/search/slice.d.ts.map +1 -0
- package/dist/search/slice.js +460 -0
- package/dist/search/slice.js.map +1 -0
- package/dist/search/snr-constants.d.ts +41 -0
- package/dist/search/snr-constants.d.ts.map +1 -0
- package/dist/search/snr-constants.js +44 -0
- package/dist/search/snr-constants.js.map +1 -0
- package/dist/search/types.d.ts +28 -0
- package/dist/search/types.d.ts.map +1 -0
- package/dist/search/types.js +12 -0
- package/dist/search/types.js.map +1 -0
- package/dist/timeline/cli.d.ts.map +1 -1
- package/dist/timeline/cli.js +22 -3
- package/dist/timeline/cli.js.map +1 -1
- package/dist/timeline/store.d.ts +5 -0
- package/dist/timeline/store.d.ts.map +1 -1
- package/dist/timeline/store.js +23 -3
- package/dist/timeline/store.js.map +1 -1
- package/package.json +1 -1
- package/scripts/agent-eval/subagent-token-cost.py +188 -0
- package/dist/.claude-template/skills/code-impact-docgen/template-business-html.md +0 -242
- package/dist/.claude-template/skills/code-impact-docgen/template-business-md.md +0 -107
- package/dist/.claude-template/skills/code-impact-docgen/template-technical-html.md +0 -205
- package/dist/.claude-template/skills/code-impact-docgen/template-technical-md.md +0 -155
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Bruno `.bru` file writer.
|
|
4
|
+
*
|
|
5
|
+
* Spec §5.2 template — emits one `.bru` per endpoint. The HTTP method block
|
|
6
|
+
* keyword (`post {` / `get {` / `put {` / `delete {` / `patch {`) reflects
|
|
7
|
+
* `endpoint.httpMethod` (lowercased). Default body is `[{}]` — the assemble
|
|
8
|
+
* phase (T-40) fills it in; scan phase writes the placeholder.
|
|
9
|
+
*
|
|
10
|
+
* Header values from `config.defaultHeaders` are written verbatim, INCLUDING
|
|
11
|
+
* any `{{var}}` placeholders — Bruno resolves those at request time from the
|
|
12
|
+
* collection environment. Per spec §9, scan/analyze/assemble do NOT load the
|
|
13
|
+
* profile (only run does) — Bruno's `{{var}}` syntax does the substitution
|
|
14
|
+
* natively at request time.
|
|
15
|
+
*
|
|
16
|
+
* Public surface:
|
|
17
|
+
* - `renderBru(endpoint, config)` — string
|
|
18
|
+
* - `writeBru(endpoint, config, outputDir)` — Promise<string> (written path)
|
|
19
|
+
*/
|
|
20
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
23
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
24
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
25
|
+
}
|
|
26
|
+
Object.defineProperty(o, k2, desc);
|
|
27
|
+
}) : (function(o, m, k, k2) {
|
|
28
|
+
if (k2 === undefined) k2 = k;
|
|
29
|
+
o[k2] = m[k];
|
|
30
|
+
}));
|
|
31
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
32
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
33
|
+
}) : function(o, v) {
|
|
34
|
+
o["default"] = v;
|
|
35
|
+
});
|
|
36
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
37
|
+
var ownKeys = function(o) {
|
|
38
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
39
|
+
var ar = [];
|
|
40
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
41
|
+
return ar;
|
|
42
|
+
};
|
|
43
|
+
return ownKeys(o);
|
|
44
|
+
};
|
|
45
|
+
return function (mod) {
|
|
46
|
+
if (mod && mod.__esModule) return mod;
|
|
47
|
+
var result = {};
|
|
48
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
49
|
+
__setModuleDefault(result, mod);
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
})();
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.__INTERNAL_BRU = void 0;
|
|
55
|
+
exports.bruFileName = bruFileName;
|
|
56
|
+
exports.serviceDirName = serviceDirName;
|
|
57
|
+
exports.renderBru = renderBru;
|
|
58
|
+
exports.writeBru = writeBru;
|
|
59
|
+
const fs = __importStar(require("node:fs"));
|
|
60
|
+
const path = __importStar(require("node:path"));
|
|
61
|
+
/** Filename for an endpoint's `.bru` pair: `<svc_id>_<methodName>.bru`. */
|
|
62
|
+
function bruFileName(endpoint) {
|
|
63
|
+
return `${endpoint.svcId}_${endpoint.method}.bru`;
|
|
64
|
+
}
|
|
65
|
+
/** Subdirectory under `outputDir` for an endpoint's service: `<service>/`. */
|
|
66
|
+
function serviceDirName(endpoint) {
|
|
67
|
+
return endpoint.service;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Render the `.bru` body for one endpoint, following spec §5.2.
|
|
71
|
+
*
|
|
72
|
+
* The HTTP method keyword is derived from `endpoint.httpMethod`
|
|
73
|
+
* (lowercased). If the method is unknown (not get/post/put/delete/patch),
|
|
74
|
+
* fall back to `post` (the hx default) and emit a comment.
|
|
75
|
+
*/
|
|
76
|
+
function renderBru(endpoint, config) {
|
|
77
|
+
const methodKey = normalizeHttpMethodKey(endpoint.httpMethod);
|
|
78
|
+
const metaName = `${endpoint.svcId}_${endpoint.method}`;
|
|
79
|
+
const url = endpoint.urlPattern;
|
|
80
|
+
const headerLines = Object.entries(config.defaultHeaders).map(([k, v]) => ` ${k}: ${v}`);
|
|
81
|
+
const headersBlock = headerLines.length > 0
|
|
82
|
+
? `headers {\n${headerLines.join('\n')}\n}`
|
|
83
|
+
: 'headers {}';
|
|
84
|
+
const bodyTemplate = config.bodyTemplate || '[{}]';
|
|
85
|
+
const descLine = endpoint.javadoc
|
|
86
|
+
? firstLine(endpoint.javadoc)
|
|
87
|
+
: '(scan 阶段未提取到 Javadoc,请补充业务说明)';
|
|
88
|
+
// The HTTP method block keyword — Bruno's grammar uses the lowercase method
|
|
89
|
+
// name as the block key. We emit the matched key; if the configured method
|
|
90
|
+
// is non-standard, fall back to `post` and add a `docs` note.
|
|
91
|
+
const methodBlockKey = methodKey ?? 'post';
|
|
92
|
+
const methodFallbackNote = methodKey === null
|
|
93
|
+
? `\n # NOTE: endpoint.httpMethod="${endpoint.httpMethod}" is non-standard; defaulting to post.`
|
|
94
|
+
: '';
|
|
95
|
+
return `meta {
|
|
96
|
+
name: ${metaName}
|
|
97
|
+
type: http
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
${methodBlockKey} {${methodFallbackNote}
|
|
101
|
+
url: ${url}
|
|
102
|
+
body: json
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
${headersBlock}
|
|
106
|
+
|
|
107
|
+
body:json {
|
|
108
|
+
${bodyTemplate}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
docs {
|
|
112
|
+
业务说明: ${descLine}
|
|
113
|
+
完整分析见同名 .md 文件
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
tests {
|
|
117
|
+
test("HTTP 200", function() {
|
|
118
|
+
expect(res.getStatus()).to.equal(200);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
`;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Write an endpoint's `.bru` to `<outputDir>/<service>/<svc_id>_<methodName>.bru`.
|
|
125
|
+
* Creates the service directory if needed. Returns the absolute written path.
|
|
126
|
+
*
|
|
127
|
+
* Also stamps the written path back onto `endpoint.bruPath` so the report
|
|
128
|
+
* phase can reference it.
|
|
129
|
+
*/
|
|
130
|
+
async function writeBru(endpoint, config, outputDir) {
|
|
131
|
+
const serviceDir = path.join(outputDir, serviceDirName(endpoint));
|
|
132
|
+
await fs.promises.mkdir(serviceDir, { recursive: true });
|
|
133
|
+
const filePath = path.join(serviceDir, bruFileName(endpoint));
|
|
134
|
+
const content = renderBru(endpoint, config);
|
|
135
|
+
await fs.promises.writeFile(filePath, content, 'utf8');
|
|
136
|
+
endpoint.bruPath = filePath;
|
|
137
|
+
return filePath;
|
|
138
|
+
}
|
|
139
|
+
/** Map an HTTP method string to Bruno's lowercase block key. `null` = unknown. */
|
|
140
|
+
function normalizeHttpMethodKey(method) {
|
|
141
|
+
const m = method.trim().toLowerCase();
|
|
142
|
+
if (m === 'get' || m === 'post' || m === 'put' || m === 'delete' || m === 'patch') {
|
|
143
|
+
return m;
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
/** First non-empty line of a javadoc string, trimmed. */
|
|
148
|
+
function firstLine(javadoc) {
|
|
149
|
+
const line = javadoc.split(/\r?\n/).map((s) => s.trim()).find((s) => s.length > 0);
|
|
150
|
+
return line ?? '';
|
|
151
|
+
}
|
|
152
|
+
/** Internal helpers re-exported for tests. */
|
|
153
|
+
exports.__INTERNAL_BRU = {
|
|
154
|
+
bruFileName,
|
|
155
|
+
serviceDirName,
|
|
156
|
+
normalizeHttpMethodKey,
|
|
157
|
+
firstLine,
|
|
158
|
+
};
|
|
159
|
+
//# sourceMappingURL=bru-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bru-writer.js","sourceRoot":"","sources":["../../src/api-test/bru-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyze phase — extract the call chain, dependency tables, and auth flag
|
|
3
|
+
* from an impl method body.
|
|
4
|
+
*
|
|
5
|
+
* Spec contract (T-30):
|
|
6
|
+
* - Call chain: every `someService.method()` invocation in the body
|
|
7
|
+
* (first-level callees only — no recursion into callees of callees).
|
|
8
|
+
* At least 1 level is expected (impl → first callee).
|
|
9
|
+
* - Dep tables: inferred from Mapper calls (`xxxMapper.selectXxx` etc.)
|
|
10
|
+
* by stripping the `Mapper` suffix from the receiver's declared field
|
|
11
|
+
* type (or receiver name) and lowercasing.
|
|
12
|
+
* - Auth required: true when the impl calls `IAuthInfoService` (field type
|
|
13
|
+
* or receiver name starting with `iAuth` / `IAuthInfoService`) or reads
|
|
14
|
+
* the staffcode header (`ServerHeadersHolder.getStaffcode()` etc.).
|
|
15
|
+
*
|
|
16
|
+
* Implementation note: extraction uses `method.bodyText` (regex) rather than
|
|
17
|
+
* the AST `body` node. The T-11 parser deletes the tree after extraction to
|
|
18
|
+
* release WASM heap, which would invalidate any retained AST node reference;
|
|
19
|
+
* `bodyText` is captured before the delete and stays valid. The task's
|
|
20
|
+
* "允许局部适配" clause permits this regex-based approach.
|
|
21
|
+
*
|
|
22
|
+
* Self-contained: depends only on `./java-parser` (ClassInfo, MethodSignature).
|
|
23
|
+
* No imports from `src/extraction/` / `src/resolution/` / `src/db/`.
|
|
24
|
+
*
|
|
25
|
+
* Public surface:
|
|
26
|
+
* - `extractCallChain(implInfo, method)` —
|
|
27
|
+
* Promise<{ callChain: string[]; depTables: string[]; authRequired: boolean }>
|
|
28
|
+
*/
|
|
29
|
+
import type { ClassInfo, MethodSignature } from './java-parser';
|
|
30
|
+
/**
|
|
31
|
+
* Extract `receiver.methodName` strings from the body text. Dedupes by
|
|
32
|
+
* the full `receiver.method` pair, preserving document order.
|
|
33
|
+
*/
|
|
34
|
+
declare function extractCallChainFromBody(bodyText: string): string[];
|
|
35
|
+
/**
|
|
36
|
+
* Infer dependency table names from Mapper-typed calls in the body.
|
|
37
|
+
*
|
|
38
|
+
* Heuristic:
|
|
39
|
+
* 1. For each `xxxMapper.method()` call in the body, look up the field
|
|
40
|
+
* `xxxMapper` on the impl class. If its type ends with `Mapper`,
|
|
41
|
+
* strip the suffix and lowercase → table name.
|
|
42
|
+
* 2. Fallback: if the receiver name itself ends with `Mapper` (e.g.
|
|
43
|
+
* `orderMapper`), strip + lowercase.
|
|
44
|
+
*
|
|
45
|
+
* Returns deduped table names in document order.
|
|
46
|
+
*/
|
|
47
|
+
declare function inferDepTables(bodyText: string, implInfo: ClassInfo): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Detect whether the impl method touches the auth surface.
|
|
50
|
+
*
|
|
51
|
+
* Signals (any one → true):
|
|
52
|
+
* - The impl class has a field whose type simple-name is `IAuthInfoService`
|
|
53
|
+
* (or whose name starts with `iAuth`).
|
|
54
|
+
* - The body text references `IAuthInfoService`, `getStaffcode`, or
|
|
55
|
+
* `ServerHeadersHolder`.
|
|
56
|
+
*
|
|
57
|
+
* The field-type check catches `@Resource IAuthInfoService iAuthService;`
|
|
58
|
+
* even when the body only calls `iAuthService.check()` (receiver name
|
|
59
|
+
* doesn't carry the type). The body-text check catches direct
|
|
60
|
+
* `ServerHeadersHolder.getStaffcode()` calls without a field.
|
|
61
|
+
*/
|
|
62
|
+
declare function detectAuthRequired(bodyText: string, implInfo: ClassInfo): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Extract the call chain, dependency tables, and auth-required flag for
|
|
65
|
+
* one impl method. Returns empty arrays + `authRequired: false` when the
|
|
66
|
+
* method has no body (interface/abstract method — shouldn't happen for an
|
|
67
|
+
* impl, but defensive per T-11's empty-bodyText caveat).
|
|
68
|
+
*/
|
|
69
|
+
export declare function extractCallChain(implInfo: ClassInfo, method: MethodSignature): Promise<{
|
|
70
|
+
callChain: string[];
|
|
71
|
+
depTables: string[];
|
|
72
|
+
authRequired: boolean;
|
|
73
|
+
}>;
|
|
74
|
+
export declare const __INTERNAL_CALL_CHAIN: {
|
|
75
|
+
extractCallChainFromBody: typeof extractCallChainFromBody;
|
|
76
|
+
inferDepTables: typeof inferDepTables;
|
|
77
|
+
detectAuthRequired: typeof detectAuthRequired;
|
|
78
|
+
};
|
|
79
|
+
export {};
|
|
80
|
+
//# sourceMappingURL=call-chain-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-chain-extractor.d.ts","sourceRoot":"","sources":["../../src/api-test/call-chain-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAoBhE;;;GAGG;AACH,iBAAS,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAkB5D;AAMD;;;;;;;;;;;GAWG;AACH,iBAAS,cAAc,CACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,SAAS,GAClB,MAAM,EAAE,CA8BV;AAMD;;;;;;;;;;;;;GAaG;AACH,iBAAS,kBAAkB,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,SAAS,GAClB,OAAO,CAkBT;AAMD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,CAAC,CAU9E;AAGD,eAAO,MAAM,qBAAqB;;;;CAIjC,CAAC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Analyze phase — extract the call chain, dependency tables, and auth flag
|
|
4
|
+
* from an impl method body.
|
|
5
|
+
*
|
|
6
|
+
* Spec contract (T-30):
|
|
7
|
+
* - Call chain: every `someService.method()` invocation in the body
|
|
8
|
+
* (first-level callees only — no recursion into callees of callees).
|
|
9
|
+
* At least 1 level is expected (impl → first callee).
|
|
10
|
+
* - Dep tables: inferred from Mapper calls (`xxxMapper.selectXxx` etc.)
|
|
11
|
+
* by stripping the `Mapper` suffix from the receiver's declared field
|
|
12
|
+
* type (or receiver name) and lowercasing.
|
|
13
|
+
* - Auth required: true when the impl calls `IAuthInfoService` (field type
|
|
14
|
+
* or receiver name starting with `iAuth` / `IAuthInfoService`) or reads
|
|
15
|
+
* the staffcode header (`ServerHeadersHolder.getStaffcode()` etc.).
|
|
16
|
+
*
|
|
17
|
+
* Implementation note: extraction uses `method.bodyText` (regex) rather than
|
|
18
|
+
* the AST `body` node. The T-11 parser deletes the tree after extraction to
|
|
19
|
+
* release WASM heap, which would invalidate any retained AST node reference;
|
|
20
|
+
* `bodyText` is captured before the delete and stays valid. The task's
|
|
21
|
+
* "允许局部适配" clause permits this regex-based approach.
|
|
22
|
+
*
|
|
23
|
+
* Self-contained: depends only on `./java-parser` (ClassInfo, MethodSignature).
|
|
24
|
+
* No imports from `src/extraction/` / `src/resolution/` / `src/db/`.
|
|
25
|
+
*
|
|
26
|
+
* Public surface:
|
|
27
|
+
* - `extractCallChain(implInfo, method)` —
|
|
28
|
+
* Promise<{ callChain: string[]; depTables: string[]; authRequired: boolean }>
|
|
29
|
+
*/
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.__INTERNAL_CALL_CHAIN = void 0;
|
|
32
|
+
exports.extractCallChain = extractCallChain;
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Call chain extraction
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
/**
|
|
37
|
+
* Match `receiver.methodName(` calls in the body text. Captures the receiver
|
|
38
|
+
* identifier and method name. Skips:
|
|
39
|
+
* - Calls without a receiver (`foo()` — can't qualify).
|
|
40
|
+
* - `super(...)` / `this(...)` constructor calls.
|
|
41
|
+
* - Chained-call inner segments are captured as separate `a.b` and `b.c`
|
|
42
|
+
* pairs; dedup handles the rest.
|
|
43
|
+
*
|
|
44
|
+
* The receiver pattern `[A-Za-z_]\w*` matches simple identifiers (not
|
|
45
|
+
* qualified `this.foo` or `Class.staticMethod` — those are captured as
|
|
46
|
+
* `this.foo` / `Class.staticMethod` with the dotted receiver included).
|
|
47
|
+
*/
|
|
48
|
+
const METHOD_CALL_RE = /\b([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\.([A-Za-z_]\w*)\s*\(/g;
|
|
49
|
+
/**
|
|
50
|
+
* Extract `receiver.methodName` strings from the body text. Dedupes by
|
|
51
|
+
* the full `receiver.method` pair, preserving document order.
|
|
52
|
+
*/
|
|
53
|
+
function extractCallChainFromBody(bodyText) {
|
|
54
|
+
const out = [];
|
|
55
|
+
const seen = new Set();
|
|
56
|
+
METHOD_CALL_RE.lastIndex = 0;
|
|
57
|
+
let m;
|
|
58
|
+
while ((m = METHOD_CALL_RE.exec(bodyText)) !== null) {
|
|
59
|
+
const receiver = m[1] ?? '';
|
|
60
|
+
const methodName = m[2] ?? '';
|
|
61
|
+
if (!receiver || !methodName)
|
|
62
|
+
continue;
|
|
63
|
+
// Skip `super.x` and `this.x` — not service calls.
|
|
64
|
+
if (receiver === 'super' || receiver === 'this')
|
|
65
|
+
continue;
|
|
66
|
+
const key = `${receiver}.${methodName}`;
|
|
67
|
+
if (seen.has(key))
|
|
68
|
+
continue;
|
|
69
|
+
seen.add(key);
|
|
70
|
+
out.push(key);
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Dependency table inference
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
/**
|
|
78
|
+
* Infer dependency table names from Mapper-typed calls in the body.
|
|
79
|
+
*
|
|
80
|
+
* Heuristic:
|
|
81
|
+
* 1. For each `xxxMapper.method()` call in the body, look up the field
|
|
82
|
+
* `xxxMapper` on the impl class. If its type ends with `Mapper`,
|
|
83
|
+
* strip the suffix and lowercase → table name.
|
|
84
|
+
* 2. Fallback: if the receiver name itself ends with `Mapper` (e.g.
|
|
85
|
+
* `orderMapper`), strip + lowercase.
|
|
86
|
+
*
|
|
87
|
+
* Returns deduped table names in document order.
|
|
88
|
+
*/
|
|
89
|
+
function inferDepTables(bodyText, implInfo) {
|
|
90
|
+
// Build a map of field name → field type for the impl class.
|
|
91
|
+
const fieldTypeByName = new Map();
|
|
92
|
+
for (const f of implInfo.fields) {
|
|
93
|
+
fieldTypeByName.set(f.name, f.type);
|
|
94
|
+
}
|
|
95
|
+
const out = [];
|
|
96
|
+
const seen = new Set();
|
|
97
|
+
METHOD_CALL_RE.lastIndex = 0;
|
|
98
|
+
let m;
|
|
99
|
+
while ((m = METHOD_CALL_RE.exec(bodyText)) !== null) {
|
|
100
|
+
const receiver = m[1] ?? '';
|
|
101
|
+
if (!receiver)
|
|
102
|
+
continue;
|
|
103
|
+
// Resolve receiver → field type (if it's a simple identifier matching a field).
|
|
104
|
+
const fieldType = fieldTypeByName.get(receiver);
|
|
105
|
+
const typeForInference = fieldType ?? receiver;
|
|
106
|
+
// Match `XxxMapper` (or `xxxMapper`).
|
|
107
|
+
const mm = /^([A-Za-z_]\w*)Mapper$/.exec(typeForInference);
|
|
108
|
+
if (!mm)
|
|
109
|
+
continue;
|
|
110
|
+
const table = (mm[1] ?? '').toLowerCase();
|
|
111
|
+
if (!table || seen.has(table))
|
|
112
|
+
continue;
|
|
113
|
+
seen.add(table);
|
|
114
|
+
out.push(table);
|
|
115
|
+
}
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Auth-required detection
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
/**
|
|
122
|
+
* Detect whether the impl method touches the auth surface.
|
|
123
|
+
*
|
|
124
|
+
* Signals (any one → true):
|
|
125
|
+
* - The impl class has a field whose type simple-name is `IAuthInfoService`
|
|
126
|
+
* (or whose name starts with `iAuth`).
|
|
127
|
+
* - The body text references `IAuthInfoService`, `getStaffcode`, or
|
|
128
|
+
* `ServerHeadersHolder`.
|
|
129
|
+
*
|
|
130
|
+
* The field-type check catches `@Resource IAuthInfoService iAuthService;`
|
|
131
|
+
* even when the body only calls `iAuthService.check()` (receiver name
|
|
132
|
+
* doesn't carry the type). The body-text check catches direct
|
|
133
|
+
* `ServerHeadersHolder.getStaffcode()` calls without a field.
|
|
134
|
+
*/
|
|
135
|
+
function detectAuthRequired(bodyText, implInfo) {
|
|
136
|
+
// Field-type check.
|
|
137
|
+
for (const f of implInfo.fields) {
|
|
138
|
+
const simple = f.type.split('.').pop() ?? f.type;
|
|
139
|
+
if (simple === 'IAuthInfoService' || simple === 'AuthInfoService') {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
if (/^iAuth\w*/.test(f.name) || /^authService$/i.test(f.name)) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Body-text check.
|
|
147
|
+
if (/IAuthInfoService/.test(bodyText))
|
|
148
|
+
return true;
|
|
149
|
+
if (/getStaffcode/.test(bodyText))
|
|
150
|
+
return true;
|
|
151
|
+
if (/ServerHeadersHolder/.test(bodyText))
|
|
152
|
+
return true;
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
// Public API
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
/**
|
|
159
|
+
* Extract the call chain, dependency tables, and auth-required flag for
|
|
160
|
+
* one impl method. Returns empty arrays + `authRequired: false` when the
|
|
161
|
+
* method has no body (interface/abstract method — shouldn't happen for an
|
|
162
|
+
* impl, but defensive per T-11's empty-bodyText caveat).
|
|
163
|
+
*/
|
|
164
|
+
async function extractCallChain(implInfo, method) {
|
|
165
|
+
if (!method.bodyText) {
|
|
166
|
+
return { callChain: [], depTables: [], authRequired: false };
|
|
167
|
+
}
|
|
168
|
+
const callChain = extractCallChainFromBody(method.bodyText);
|
|
169
|
+
const depTables = inferDepTables(method.bodyText, implInfo);
|
|
170
|
+
const authRequired = detectAuthRequired(method.bodyText, implInfo);
|
|
171
|
+
return { callChain, depTables, authRequired };
|
|
172
|
+
}
|
|
173
|
+
// Internal helpers re-exported for tests.
|
|
174
|
+
exports.__INTERNAL_CALL_CHAIN = {
|
|
175
|
+
extractCallChainFromBody,
|
|
176
|
+
inferDepTables,
|
|
177
|
+
detectAuthRequired,
|
|
178
|
+
};
|
|
179
|
+
//# sourceMappingURL=call-chain-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call-chain-extractor.js","sourceRoot":"","sources":["../../src/api-test/call-chain-extractor.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;;;AAoJH,4CAaC;AA7JD,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,cAAc,GAAG,2DAA2D,CAAC;AAEnF;;;GAGG;AACH,SAAS,wBAAwB,CAAC,QAAgB;IAChD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,cAAc,CAAC,SAAS,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAyB,CAAC;IAC9B,OAAO,CAAC,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU;YAAE,SAAS;QACvC,mDAAmD;QACnD,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,MAAM;YAAE,SAAS;QAC1D,MAAM,GAAG,GAAG,GAAG,QAAQ,IAAI,UAAU,EAAE,CAAC;QACxC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,SAAS,cAAc,CACrB,QAAgB,EAChB,QAAmB;IAEnB,6DAA6D;IAC7D,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QAChC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,cAAc,CAAC,SAAS,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAyB,CAAC;IAC9B,OAAO,CAAC,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,QAAQ;YAAE,SAAS;QAExB,gFAAgF;QAChF,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,gBAAgB,GAAG,SAAS,IAAI,QAAQ,CAAC;QAE/C,sCAAsC;QACtC,MAAM,EAAE,GAAG,wBAAwB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC3D,IAAI,CAAC,EAAE;YAAE,SAAS;QAElB,MAAM,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1C,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS;QACxC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8EAA8E;AAC9E,0BAA0B;AAC1B,8EAA8E;AAE9E;;;;;;;;;;;;;GAaG;AACH,SAAS,kBAAkB,CACzB,QAAgB,EAChB,QAAmB;IAEnB,oBAAoB;IACpB,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC;QACjD,IAAI,MAAM,KAAK,kBAAkB,IAAI,MAAM,KAAK,iBAAiB,EAAE,CAAC;YAClE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,IAAI,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,IAAI,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,IAAI,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;GAKG;AACI,KAAK,UAAU,gBAAgB,CACpC,QAAmB,EACnB,MAAuB;IAEvB,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IAC/D,CAAC;IAED,MAAM,SAAS,GAAG,wBAAwB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5D,MAAM,YAAY,GAAG,kBAAkB,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAEnE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;AAChD,CAAC;AAED,0CAA0C;AAC7B,QAAA,qBAAqB,GAAG;IACnC,wBAAwB;IACxB,cAAc;IACd,kBAAkB;CACnB,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI wiring for the api-test subsystem.
|
|
3
|
+
*
|
|
4
|
+
* Exposes `registerApiTestCommands(program)` — called once from
|
|
5
|
+
* `src/bin/codegraph.ts`. All api-test subcommands live under
|
|
6
|
+
* `codegraph api-test <sub>`. The scan subcommand (T-20) is wired here;
|
|
7
|
+
* the analyze/assemble/run/report/list subcommands will be added in
|
|
8
|
+
* T-30 / T-40 / T-50 / T-60.
|
|
9
|
+
*
|
|
10
|
+
* Spec contract — scan:
|
|
11
|
+
* - Full re-scan (delete `docs/api-test/<service>/` subtree, rebuild).
|
|
12
|
+
* - Writes one `.bru` + one `.md` per endpoint under
|
|
13
|
+
* `docs/api-test/<service>/<svc_id>_<methodName>.{bru,md}`.
|
|
14
|
+
* - Writes `docs/api-test/bruno.json` at the api-test root with the
|
|
15
|
+
* minimal Bruno collection schema.
|
|
16
|
+
* - Failed endpoints don't abort the rest — warnings go to stderr.
|
|
17
|
+
*
|
|
18
|
+
* Exit codes:
|
|
19
|
+
* 0 success (or partial success with warnings)
|
|
20
|
+
* 2 config error (ConfigError — missing/invalid profile or config)
|
|
21
|
+
* 5 argument error
|
|
22
|
+
*/
|
|
23
|
+
import type { Command } from 'commander';
|
|
24
|
+
import { type ClassInfo, type MethodSignature } from './java-parser';
|
|
25
|
+
import { type BrunoRunResult } from './bru-runner';
|
|
26
|
+
import type { Endpoint, ApiTestProfile } from './types';
|
|
27
|
+
/**
|
|
28
|
+
* Attach the `api-test` command group to a commander program.
|
|
29
|
+
*/
|
|
30
|
+
export declare function registerApiTestCommands(program: Command): void;
|
|
31
|
+
/**
|
|
32
|
+
* Walk `projectRoot` and yield every `.java` file path. Same ignore list as
|
|
33
|
+
* the scan phase (parser-httpservice.iterJavaFiles) — duplicated here to
|
|
34
|
+
* avoid leaking the scan module's internal helper through the CLI surface.
|
|
35
|
+
* Symlinks are not followed.
|
|
36
|
+
*/
|
|
37
|
+
declare function iterJavaFilesCached(root: string): IterableIterator<string>;
|
|
38
|
+
/**
|
|
39
|
+
* Run the analyze pipeline for one endpoint:
|
|
40
|
+
* 1. findImplFor(interfaceFqn, allClasses) — locate the impl class.
|
|
41
|
+
* 2. Match the interface method to the impl method (name + param count).
|
|
42
|
+
* 3. extractFields + extractCallChain.
|
|
43
|
+
*
|
|
44
|
+
* Returns the enriched fields/callChain/depTables/authRequired, plus a
|
|
45
|
+
* `skipReason` string when the endpoint should be marked `status: skip`.
|
|
46
|
+
*/
|
|
47
|
+
declare function analyzeEndpoint(endpoint: Endpoint, allClasses: ClassInfo[]): Promise<{
|
|
48
|
+
fields: Endpoint['fields'];
|
|
49
|
+
callChain: string[];
|
|
50
|
+
depTables: string[];
|
|
51
|
+
authRequired: boolean;
|
|
52
|
+
skipReason: string | null;
|
|
53
|
+
}>;
|
|
54
|
+
/** Count parameters in a signature string like `Object qryOrderList(Object reqVo)`. */
|
|
55
|
+
declare function countParamsInSignature(signature: string): number;
|
|
56
|
+
/**
|
|
57
|
+
* Find the impl method matching `name` + `paramCount`. Falls back to
|
|
58
|
+
* name-only match if paramCount is 0 (defensive — shouldn't happen for
|
|
59
|
+
* real @Center methods, which always have ≥1 param).
|
|
60
|
+
*/
|
|
61
|
+
declare function findImplMethod(implInfo: ClassInfo, name: string, paramCount: number): MethodSignature | null;
|
|
62
|
+
/**
|
|
63
|
+
* Remove the existing output subtree so a re-scan doesn't leave stale
|
|
64
|
+
* `.bru` / `.md` files behind for endpoints that no longer exist. Safe to
|
|
65
|
+
* call on a non-existent dir.
|
|
66
|
+
*
|
|
67
|
+
* Preserves any files / subdirs the user might have added that are NOT
|
|
68
|
+
* `.bru` / `.md` pairs? Spec says "full re-scan" = delete the whole
|
|
69
|
+
* `docs/api-test/<service>/` subtree and rewrite bruno.json. We follow
|
|
70
|
+
* that literally: delete the entire output dir's *.bru / *.md / bruno.json,
|
|
71
|
+
* and remove now-empty service subdirs.
|
|
72
|
+
*/
|
|
73
|
+
declare function clearOutputDir(outputDir: string): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Read an endpoint's status from its `.md` frontmatter. Returns 'active'
|
|
76
|
+
* when the .md doesn't exist or the status line can't be found (defensive
|
|
77
|
+
* — a fresh collection with no analyze phase still runs).
|
|
78
|
+
*/
|
|
79
|
+
declare function readEndpointStatus(endpoint: Endpoint, outputDir: string): 'active' | 'skip';
|
|
80
|
+
/**
|
|
81
|
+
* When `--filter` narrows to exactly one service, return that service name
|
|
82
|
+
* so `runBrunoCollection` can narrow Bruno CLI's run to that subdir (faster).
|
|
83
|
+
* When multiple services match (or none), return null — run the whole
|
|
84
|
+
* collection and filter results after.
|
|
85
|
+
*/
|
|
86
|
+
declare function pickFilterService(filterRe: RegExp | null, endpoints: Endpoint[]): string | null;
|
|
87
|
+
/** Judgment outcome for one BrunoRunResult. */
|
|
88
|
+
interface Judgment {
|
|
89
|
+
passed: boolean;
|
|
90
|
+
bizCode: string | null;
|
|
91
|
+
error: string | null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Judge pass/fail for one Bruno run result against the profile's biz-code rule.
|
|
95
|
+
*
|
|
96
|
+
* - Bruno-reported error (timeout / request_failed) → passed=false, error
|
|
97
|
+
* forwarded.
|
|
98
|
+
* - HTTP 5xx → passed=false, error=http_5xx.
|
|
99
|
+
* - HTTP 4xx → passed=false, error=http_4xx.
|
|
100
|
+
* - Other non-200 → passed=false, error=http_non_200.
|
|
101
|
+
* - HTTP 200 + bizCodeField null → passed=true (HTTP-only check).
|
|
102
|
+
* - HTTP 200 + bizCodeField set + value in bizCodeSuccessValues → passed=true.
|
|
103
|
+
* - HTTP 200 + bizCodeField set + value NOT in success values → passed=false,
|
|
104
|
+
* error=biz_code_value_mismatch.
|
|
105
|
+
* - HTTP 200 + bizCodeField set + field missing from response body →
|
|
106
|
+
* passed=false, error=biz_code_field_missing.
|
|
107
|
+
*/
|
|
108
|
+
declare function judgePass(result: BrunoRunResult, profile: ApiTestProfile): Judgment;
|
|
109
|
+
/**
|
|
110
|
+
* Extract the biz code value from a response body. The body may be a JSON
|
|
111
|
+
* object or a JSON string. Returns the stringified value, or null when the
|
|
112
|
+
* field is absent / the body can't be parsed.
|
|
113
|
+
*/
|
|
114
|
+
declare function extractBizCode(responseBody: string, bizCodeField: string): string | null;
|
|
115
|
+
export declare const __INTERNAL_CLI: {
|
|
116
|
+
DEFAULT_OUTPUT_DIR: string;
|
|
117
|
+
BRUNO_COLLECTION_CONFIG: {
|
|
118
|
+
version: number;
|
|
119
|
+
name: string;
|
|
120
|
+
type: string;
|
|
121
|
+
};
|
|
122
|
+
clearOutputDir: typeof clearOutputDir;
|
|
123
|
+
iterJavaFilesCached: typeof iterJavaFilesCached;
|
|
124
|
+
analyzeEndpoint: typeof analyzeEndpoint;
|
|
125
|
+
countParamsInSignature: typeof countParamsInSignature;
|
|
126
|
+
findImplMethod: typeof findImplMethod;
|
|
127
|
+
readEndpointStatus: typeof readEndpointStatus;
|
|
128
|
+
pickFilterService: typeof pickFilterService;
|
|
129
|
+
judgePass: typeof judgePass;
|
|
130
|
+
extractBizCode: typeof extractBizCode;
|
|
131
|
+
};
|
|
132
|
+
export {};
|
|
133
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/api-test/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,OAAO,EAAiB,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAKpF,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAevE,OAAO,KAAK,EAAE,QAAQ,EAAW,cAAc,EAAE,MAAM,SAAS,CAAC;AAcjE;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4rB9D;AAID;;;;;GAKG;AACH,iBAAU,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAkBpE;AAaD;;;;;;;;GAQG;AACH,iBAAe,eAAe,CAC5B,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,SAAS,EAAE,GACtB,OAAO,CAAC;IACT,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC3B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC,CA4CD;AAED,uFAAuF;AACvF,iBAAS,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CASzD;AAED;;;;GAIG;AACH,iBAAS,cAAc,CACrB,QAAQ,EAAE,SAAS,EACnB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,GACjB,eAAe,GAAG,IAAI,CAMxB;AAED;;;;;;;;;;GAUG;AACH,iBAAe,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB9D;AAkED;;;;GAIG;AACH,iBAAS,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAWpF;AAED;;;;;GAKG;AACH,iBAAS,iBAAiB,CACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,SAAS,EAAE,QAAQ,EAAE,GACpB,MAAM,GAAG,IAAI,CAYf;AAED,+CAA+C;AAC/C,UAAU,QAAQ;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;;;;;;;;GAcG;AACH,iBAAS,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,GAAG,QAAQ,CA8B5E;AAED;;;;GAIG;AACH,iBAAS,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgBjF;AAGD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;CAY1B,CAAC"}
|