@icyouo/evt-cli 0.1.0 → 0.1.1

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.
@@ -0,0 +1,196 @@
1
+ const test = require("node:test");
2
+ const assert = require("node:assert/strict");
3
+ const fs = require("node:fs");
4
+ const os = require("node:os");
5
+ const path = require("node:path");
6
+ const { scanServices } = require("../src/config/serviceScanner");
7
+
8
+ function writeFile(root, relative, content) {
9
+ const file = path.join(root, relative);
10
+ fs.mkdirSync(path.dirname(file), { recursive: true });
11
+ fs.writeFileSync(file, content);
12
+ return file;
13
+ }
14
+
15
+ test("scans configurable kotlin, swift, js, and dart targets", () => {
16
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "everything-scan-"));
17
+
18
+ writeFile(root, "kotlin/ITradeService.kt", `
19
+ class TradeService(val http: Http) {
20
+ override suspend fun listTrades(): Resp<Unit> {
21
+ return http.get("/api/trades")
22
+ }
23
+
24
+ suspend fun createTrade(code: String): Resp<Unit> {
25
+ return http.postUrlEncoded<Unit, Unit, Unit>("/api/trades/$code", Unit)
26
+ }
27
+ }
28
+ `);
29
+
30
+ writeFile(root, "swift/AccountService.swift", `
31
+ final class AccountService {
32
+ func detail(id: String) async throws {
33
+ try await client.get("/api/account/\\(id)")
34
+ }
35
+ }
36
+ `);
37
+
38
+ writeFile(root, "js/authApi.ts", `
39
+ export async function login() {
40
+ return axios.post("/api/login")
41
+ }
42
+
43
+ const logout = async (id) => {
44
+ return fetch(\`/api/logout/\${id}\`, { method: "DELETE" })
45
+ }
46
+ `);
47
+
48
+ writeFile(root, "dart/user_service.dart", `
49
+ class UserService {
50
+ Future<void> loadUser() async {
51
+ return client.get('/api/user');
52
+ }
53
+
54
+ Future<void> updateUser(String id) async {
55
+ return dio.post(Uri.parse('/api/user/$id'));
56
+ }
57
+ }
58
+ `);
59
+
60
+ const endpoints = scanServices({
61
+ config: {
62
+ root,
63
+ targets: [
64
+ { language: "kotlin", paths: ["kotlin"], namespaceStripPrefixes: ["I"], namespaceStripSuffixes: ["Service"] },
65
+ { language: "swift", paths: ["swift"] },
66
+ { language: "js", paths: ["js"] },
67
+ { language: "dart", paths: ["dart"] }
68
+ ]
69
+ }
70
+ });
71
+
72
+ assert.deepEqual(
73
+ endpoints.map((endpoint) => [endpoint.id, endpoint.method, endpoint.path, endpoint.bodyType]).sort(),
74
+ [
75
+ ["account.detail", "GET", "/api/account/:id", "json"],
76
+ ["auth.login", "POST", "/api/login", "json"],
77
+ ["auth.logout", "DELETE", "/api/logout/:id", "json"],
78
+ ["trade.createTrade", "POST", "/api/trades/:code", "formUrlEncoded"],
79
+ ["trade.listTrades", "GET", "/api/trades", "json"],
80
+ ["user_service.loadUser", "GET", "/api/user", "json"],
81
+ ["user_service.updateUser", "POST", "/api/user/:id", "json"]
82
+ ]
83
+ );
84
+ });
85
+
86
+ test("scans endpoints from an external skill command", () => {
87
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "everything-skill-scan-"));
88
+ writeFile(root, "scan.js", `
89
+ process.stdout.write(JSON.stringify({
90
+ endpoints: [
91
+ {
92
+ id: "wallet.balance",
93
+ namespace: "wallet",
94
+ functionName: "balance",
95
+ method: "GET",
96
+ path: "/api/wallet/balance",
97
+ auth: true
98
+ }
99
+ ]
100
+ }))
101
+ `);
102
+
103
+ const endpoints = scanServices({
104
+ config: {
105
+ root,
106
+ targets: [
107
+ {
108
+ language: "skill",
109
+ name: "fixture-scanner",
110
+ command: process.execPath,
111
+ args: ["scan.js"]
112
+ }
113
+ ]
114
+ }
115
+ });
116
+
117
+ assert.deepEqual(endpoints, [
118
+ {
119
+ id: "wallet.balance",
120
+ namespace: "wallet",
121
+ functionName: "balance",
122
+ method: "GET",
123
+ path: "/api/wallet/balance",
124
+ bodyType: "json",
125
+ service: undefined,
126
+ helper: "fixture-scanner",
127
+ auth: true,
128
+ dangerous: undefined,
129
+ file: undefined,
130
+ source: "fixture-scanner"
131
+ }
132
+ ]);
133
+ });
134
+
135
+ test("uses bundled skill scanner target", () => {
136
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "evt-bundled-skill-scan-"));
137
+ writeFile(root, "src/AuthService.kt", `
138
+ class AuthService(val http: Http) {
139
+ suspend fun login(): Resp<Unit> {
140
+ return http.post("/api/login")
141
+ }
142
+ }
143
+ `);
144
+
145
+ const endpoints = scanServices({
146
+ config: {
147
+ root,
148
+ targets: [
149
+ {
150
+ language: "skill",
151
+ name: "evt-api-scanner",
152
+ skill: "evt-api-scanner"
153
+ }
154
+ ]
155
+ }
156
+ });
157
+
158
+ assert.deepEqual(endpoints.map((endpoint) => [endpoint.id, endpoint.method, endpoint.path]), [
159
+ ["auth.login", "POST", "/api/login"]
160
+ ]);
161
+ });
162
+
163
+ test("falls back to regex targets when skill scanner fails", () => {
164
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), "evt-skill-fallback-"));
165
+ writeFile(root, "src/ITradeService.kt", `
166
+ class TradeService(val http: Http) {
167
+ suspend fun listTrades(): Resp<Unit> {
168
+ return http.get("/api/trades")
169
+ }
170
+ }
171
+ `);
172
+
173
+ const endpoints = scanServices({
174
+ config: {
175
+ root,
176
+ targets: [
177
+ {
178
+ language: "skill",
179
+ name: "broken-scanner",
180
+ command: process.execPath,
181
+ args: ["missing-scanner.js"]
182
+ },
183
+ {
184
+ language: "kotlin",
185
+ paths: ["src"],
186
+ namespaceStripPrefixes: ["I"],
187
+ namespaceStripSuffixes: ["Service"]
188
+ }
189
+ ]
190
+ }
191
+ });
192
+
193
+ assert.deepEqual(endpoints.map((endpoint) => [endpoint.id, endpoint.method, endpoint.path]), [
194
+ ["trade.listTrades", "GET", "/api/trades"]
195
+ ]);
196
+ });
@@ -0,0 +1,18 @@
1
+ const test = require("node:test");
2
+ const assert = require("node:assert/strict");
3
+ const { interpolate, pruneUndefined } = require("../src/template/interpolate");
4
+
5
+ test("interpolates exact templates as native values", () => {
6
+ const rendered = interpolate({ token: "{{cache.token}}", label: "Bearer {{cache.token}}" }, {
7
+ cache: { token: "abc" }
8
+ });
9
+
10
+ assert.equal(rendered.token, "abc");
11
+ assert.equal(rendered.label, "Bearer abc");
12
+ });
13
+
14
+ test("prunes missing exact template values", () => {
15
+ const rendered = pruneUndefined(interpolate({ symbol: "{{args.symbol}}", fixed: "" }, { args: {} }));
16
+
17
+ assert.deepEqual(rendered, { fixed: "" });
18
+ });
@@ -0,0 +1,20 @@
1
+ const test = require("node:test");
2
+ const assert = require("node:assert/strict");
3
+ const { parseYaml } = require("../src/config/yaml");
4
+
5
+ test("parses mappings and sequence objects", () => {
6
+ const parsed = parseYaml(`
7
+ name: login
8
+ steps:
9
+ - id: loginCheck
10
+ call: auth.loginCheck
11
+ body:
12
+ email: "{{inputs.email}}"
13
+ - wait: 1s
14
+ `);
15
+
16
+ assert.equal(parsed.name, "login");
17
+ assert.equal(parsed.steps[0].id, "loginCheck");
18
+ assert.equal(parsed.steps[0].body.email, "{{inputs.email}}");
19
+ assert.equal(parsed.steps[1].wait, "1s");
20
+ });