@oh-my-pi/pi-coding-agent 5.6.77 → 5.7.68
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/CHANGELOG.md +15 -0
- package/package.json +8 -8
- package/src/migrations.ts +1 -34
- package/src/utils/image-convert.ts +1 -1
- package/src/utils/image-resize.ts +2 -2
- package/src/vendor/photon/LICENSE.md +201 -0
- package/src/vendor/photon/README.md +158 -0
- package/src/vendor/photon/index.d.ts +3013 -0
- package/src/vendor/photon/index.js +4461 -0
- package/src/vendor/photon/photon_rs_bg.wasm +0 -0
- package/src/vendor/photon/photon_rs_bg.wasm.b64.js +1 -0
- package/src/vendor/photon/photon_rs_bg.wasm.d.ts +193 -0
- package/src/core/python-executor-display.test.ts +0 -42
- package/src/core/python-executor-lifecycle.test.ts +0 -99
- package/src/core/python-executor-mapping.test.ts +0 -41
- package/src/core/python-executor-per-call.test.ts +0 -49
- package/src/core/python-executor-session.test.ts +0 -103
- package/src/core/python-executor-streaming.test.ts +0 -77
- package/src/core/python-executor-timeout.test.ts +0 -35
- package/src/core/python-executor.lifecycle.test.ts +0 -139
- package/src/core/python-executor.result.test.ts +0 -49
- package/src/core/python-executor.test.ts +0 -180
- package/src/core/python-kernel-display.test.ts +0 -54
- package/src/core/python-kernel-env.test.ts +0 -138
- package/src/core/python-kernel-session.test.ts +0 -87
- package/src/core/python-kernel-ws.test.ts +0 -104
- package/src/core/python-kernel.lifecycle.test.ts +0 -249
- package/src/core/python-kernel.test.ts +0 -461
- package/src/core/python-modules.test.ts +0 -102
- package/src/core/python-prelude.test.ts +0 -140
- package/src/core/settings-manager-python.test.ts +0 -23
- package/src/core/streaming-output.test.ts +0 -26
- package/src/core/system-prompt.python.test.ts +0 -17
- package/src/core/tools/index.test.ts +0 -212
- package/src/core/tools/python-execution.test.ts +0 -68
- package/src/core/tools/python-fallback.test.ts +0 -72
- package/src/core/tools/python-renderer.test.ts +0 -36
- package/src/core/tools/python-tool-mode.test.ts +0 -43
- package/src/core/tools/python.test.ts +0 -121
- package/src/core/tools/schema-validation.test.ts +0 -530
- package/src/core/tools/web-scrapers/academic.test.ts +0 -239
- package/src/core/tools/web-scrapers/business.test.ts +0 -82
- package/src/core/tools/web-scrapers/dev-platforms.test.ts +0 -254
- package/src/core/tools/web-scrapers/documentation.test.ts +0 -85
- package/src/core/tools/web-scrapers/finance-media.test.ts +0 -144
- package/src/core/tools/web-scrapers/git-hosting.test.ts +0 -272
- package/src/core/tools/web-scrapers/media.test.ts +0 -138
- package/src/core/tools/web-scrapers/package-managers-2.test.ts +0 -199
- package/src/core/tools/web-scrapers/package-managers.test.ts +0 -171
- package/src/core/tools/web-scrapers/package-registries.test.ts +0 -259
- package/src/core/tools/web-scrapers/research.test.ts +0 -107
- package/src/core/tools/web-scrapers/security.test.ts +0 -103
- package/src/core/tools/web-scrapers/social-extended.test.ts +0 -192
- package/src/core/tools/web-scrapers/social.test.ts +0 -259
- package/src/core/tools/web-scrapers/stackexchange.test.ts +0 -120
- package/src/core/tools/web-scrapers/standards.test.ts +0 -122
- package/src/core/tools/web-scrapers/wikipedia.test.ts +0 -73
- package/src/core/tools/web-scrapers/youtube.test.ts +0 -198
- package/src/discovery/helpers.test.ts +0 -131
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { handleChocolatey } from "./chocolatey";
|
|
3
|
-
import { handleDockerHub } from "./dockerhub";
|
|
4
|
-
import { handleHackage } from "./hackage";
|
|
5
|
-
import { handleMetaCPAN } from "./metacpan";
|
|
6
|
-
import { handleRepology } from "./repology";
|
|
7
|
-
import { handleTerraform } from "./terraform";
|
|
8
|
-
|
|
9
|
-
const SKIP = !process.env.WEB_FETCH_INTEGRATION;
|
|
10
|
-
|
|
11
|
-
describe.skipIf(SKIP)("handleMetaCPAN", () => {
|
|
12
|
-
it("returns null for non-MetaCPAN URLs", async () => {
|
|
13
|
-
const result = await handleMetaCPAN("https://example.com", 20);
|
|
14
|
-
expect(result).toBeNull();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("returns null for non-matching MetaCPAN paths", async () => {
|
|
18
|
-
const result = await handleMetaCPAN("https://metacpan.org/about", 20);
|
|
19
|
-
expect(result).toBeNull();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("fetches Moose module", async () => {
|
|
23
|
-
const result = await handleMetaCPAN("https://metacpan.org/pod/Moose", 20);
|
|
24
|
-
expect(result).not.toBeNull();
|
|
25
|
-
expect(result?.method).toBe("metacpan");
|
|
26
|
-
expect(result?.content).toContain("Moose");
|
|
27
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
28
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
29
|
-
expect(result?.truncated).toBeDefined();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it("fetches release by distribution name", async () => {
|
|
33
|
-
const result = await handleMetaCPAN("https://metacpan.org/release/Moose", 20);
|
|
34
|
-
expect(result).not.toBeNull();
|
|
35
|
-
expect(result?.method).toBe("metacpan");
|
|
36
|
-
expect(result?.content).toContain("Moose");
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe.skipIf(SKIP)("handleHackage", () => {
|
|
41
|
-
it("returns null for non-Hackage URLs", async () => {
|
|
42
|
-
const result = await handleHackage("https://example.com", 20);
|
|
43
|
-
expect(result).toBeNull();
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("returns null for non-package Hackage paths", async () => {
|
|
47
|
-
const result = await handleHackage("https://hackage.haskell.org/", 20);
|
|
48
|
-
expect(result).toBeNull();
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("fetches aeson package", async () => {
|
|
52
|
-
const result = await handleHackage("https://hackage.haskell.org/package/aeson", 20);
|
|
53
|
-
expect(result).not.toBeNull();
|
|
54
|
-
expect(result?.method).toBe("hackage");
|
|
55
|
-
expect(result?.content).toContain("aeson");
|
|
56
|
-
expect(result?.content).toContain("JSON");
|
|
57
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
58
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
59
|
-
expect(result?.truncated).toBeDefined();
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("fetches text package", async () => {
|
|
63
|
-
const result = await handleHackage("https://hackage.haskell.org/package/text", 20);
|
|
64
|
-
expect(result).not.toBeNull();
|
|
65
|
-
expect(result?.method).toBe("hackage");
|
|
66
|
-
expect(result?.content).toContain("text");
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe.skipIf(SKIP)("handleDockerHub", () => {
|
|
71
|
-
it("returns null for non-DockerHub URLs", async () => {
|
|
72
|
-
const result = await handleDockerHub("https://example.com", 20);
|
|
73
|
-
expect(result).toBeNull();
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it("returns null for non-matching DockerHub paths", async () => {
|
|
77
|
-
const result = await handleDockerHub("https://hub.docker.com/search", 20);
|
|
78
|
-
expect(result).toBeNull();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it("fetches official nginx image", async () => {
|
|
82
|
-
const result = await handleDockerHub("https://hub.docker.com/_/nginx", 20);
|
|
83
|
-
expect(result).not.toBeNull();
|
|
84
|
-
expect(result?.method).toBe("dockerhub");
|
|
85
|
-
expect(result?.content).toContain("nginx");
|
|
86
|
-
expect(result?.content).toContain("docker pull");
|
|
87
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
88
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
89
|
-
expect(result?.truncated).toBeDefined();
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it("fetches grafana/grafana image", async () => {
|
|
93
|
-
const result = await handleDockerHub("https://hub.docker.com/r/grafana/grafana", 20);
|
|
94
|
-
expect(result).not.toBeNull();
|
|
95
|
-
expect(result?.method).toBe("dockerhub");
|
|
96
|
-
expect(result?.content).toContain("grafana");
|
|
97
|
-
expect(result?.content).toContain("docker pull");
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
describe.skipIf(SKIP)("handleChocolatey", () => {
|
|
102
|
-
it("returns null for non-Chocolatey URLs", async () => {
|
|
103
|
-
const result = await handleChocolatey("https://example.com", 20);
|
|
104
|
-
expect(result).toBeNull();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it("returns null for non-package Chocolatey paths", async () => {
|
|
108
|
-
const result = await handleChocolatey("https://community.chocolatey.org/", 20);
|
|
109
|
-
expect(result).toBeNull();
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it("fetches git package", async () => {
|
|
113
|
-
const result = await handleChocolatey("https://community.chocolatey.org/packages/git", 20);
|
|
114
|
-
expect(result).not.toBeNull();
|
|
115
|
-
expect(result?.method).toBe("chocolatey");
|
|
116
|
-
expect(result?.content).toContain("Git");
|
|
117
|
-
expect(result?.content).toContain("choco install");
|
|
118
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
119
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
120
|
-
expect(result?.truncated).toBeDefined();
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it("fetches nodejs package", async () => {
|
|
124
|
-
const result = await handleChocolatey("https://community.chocolatey.org/packages/nodejs", 20);
|
|
125
|
-
expect(result).not.toBeNull();
|
|
126
|
-
expect(result?.method).toBe("chocolatey");
|
|
127
|
-
expect(result?.content).toContain("Node");
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
describe.skipIf(SKIP)("handleRepology", () => {
|
|
132
|
-
it("returns null for non-Repology URLs", async () => {
|
|
133
|
-
const result = await handleRepology("https://example.com", 20);
|
|
134
|
-
expect(result).toBeNull();
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it("returns null for non-project Repology paths", async () => {
|
|
138
|
-
const result = await handleRepology("https://repology.org/", 20);
|
|
139
|
-
expect(result).toBeNull();
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it("fetches firefox project", async () => {
|
|
143
|
-
const result = await handleRepology("https://repology.org/project/firefox", 20);
|
|
144
|
-
expect(result).not.toBeNull();
|
|
145
|
-
expect(result?.method).toBe("repology");
|
|
146
|
-
expect(result?.content).toContain("firefox");
|
|
147
|
-
expect(result?.content).toContain("Repositories");
|
|
148
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
149
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
150
|
-
expect(result?.truncated).toBeDefined();
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it("fetches vim project", async () => {
|
|
154
|
-
const result = await handleRepology("https://repology.org/project/vim/versions", 20);
|
|
155
|
-
expect(result).not.toBeNull();
|
|
156
|
-
expect(result?.method).toBe("repology");
|
|
157
|
-
expect(result?.content).toContain("vim");
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describe.skipIf(SKIP)("handleTerraform", () => {
|
|
162
|
-
it("returns null for non-Terraform URLs", async () => {
|
|
163
|
-
const result = await handleTerraform("https://example.com", 20);
|
|
164
|
-
expect(result).toBeNull();
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it("returns null for non-matching Terraform paths", async () => {
|
|
168
|
-
const result = await handleTerraform("https://registry.terraform.io/", 20);
|
|
169
|
-
expect(result).toBeNull();
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it("fetches hashicorp/aws provider", async () => {
|
|
173
|
-
const result = await handleTerraform("https://registry.terraform.io/providers/hashicorp/aws", 20);
|
|
174
|
-
expect(result).not.toBeNull();
|
|
175
|
-
expect(result?.method).toBe("terraform");
|
|
176
|
-
expect(result?.content).toContain("aws");
|
|
177
|
-
expect(result?.content).toContain("hashicorp");
|
|
178
|
-
expect(result?.content).toContain("required_providers");
|
|
179
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
180
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
181
|
-
expect(result?.truncated).toBeDefined();
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it("fetches terraform-aws-modules/vpc/aws module", async () => {
|
|
185
|
-
const result = await handleTerraform("https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws", 20);
|
|
186
|
-
expect(result).not.toBeNull();
|
|
187
|
-
expect(result?.method).toBe("terraform");
|
|
188
|
-
expect(result?.content).toContain("vpc");
|
|
189
|
-
expect(result?.content).toContain("terraform-aws-modules");
|
|
190
|
-
expect(result?.content).toContain("module");
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it("fetches hashicorp/random provider", async () => {
|
|
194
|
-
const result = await handleTerraform("https://registry.terraform.io/providers/hashicorp/random", 20);
|
|
195
|
-
expect(result).not.toBeNull();
|
|
196
|
-
expect(result?.method).toBe("terraform");
|
|
197
|
-
expect(result?.content).toContain("random");
|
|
198
|
-
});
|
|
199
|
-
});
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { handleAur } from "./aur";
|
|
3
|
-
import { handleBrew } from "./brew";
|
|
4
|
-
import { handleMaven } from "./maven";
|
|
5
|
-
import { handleNuGet } from "./nuget";
|
|
6
|
-
import { handlePackagist } from "./packagist";
|
|
7
|
-
import { handleRubyGems } from "./rubygems";
|
|
8
|
-
|
|
9
|
-
const SKIP = !process.env.WEB_FETCH_INTEGRATION;
|
|
10
|
-
|
|
11
|
-
describe.skipIf(SKIP)("handleBrew", () => {
|
|
12
|
-
it("returns null for non-Homebrew URLs", async () => {
|
|
13
|
-
const result = await handleBrew("https://example.com", 20);
|
|
14
|
-
expect(result).toBeNull();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("returns null for non-package Homebrew URLs", async () => {
|
|
18
|
-
const result = await handleBrew("https://formulae.brew.sh/", 20);
|
|
19
|
-
expect(result).toBeNull();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("fetches wget formula", async () => {
|
|
23
|
-
const result = await handleBrew("https://formulae.brew.sh/formula/wget", 20);
|
|
24
|
-
expect(result).not.toBeNull();
|
|
25
|
-
expect(result?.method).toBe("brew");
|
|
26
|
-
expect(result?.content).toContain("wget");
|
|
27
|
-
expect(result?.content).toContain("brew install wget");
|
|
28
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
29
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
30
|
-
expect(result?.truncated).toBeDefined();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("fetches firefox cask", async () => {
|
|
34
|
-
const result = await handleBrew("https://formulae.brew.sh/cask/firefox", 20);
|
|
35
|
-
expect(result).not.toBeNull();
|
|
36
|
-
expect(result?.method).toBe("brew");
|
|
37
|
-
expect(result?.content).toContain("Firefox");
|
|
38
|
-
expect(result?.content).toContain("brew install --cask firefox");
|
|
39
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
40
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
41
|
-
expect(result?.truncated).toBeDefined();
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
describe.skipIf(SKIP)("handleAur", () => {
|
|
46
|
-
it("returns null for non-AUR URLs", async () => {
|
|
47
|
-
const result = await handleAur("https://example.com", 20);
|
|
48
|
-
expect(result).toBeNull();
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("returns null for non-package AUR URLs", async () => {
|
|
52
|
-
const result = await handleAur("https://aur.archlinux.org/", 20);
|
|
53
|
-
expect(result).toBeNull();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("fetches yay package", async () => {
|
|
57
|
-
const result = await handleAur("https://aur.archlinux.org/packages/yay", 20);
|
|
58
|
-
expect(result).not.toBeNull();
|
|
59
|
-
expect(result?.method).toBe("aur");
|
|
60
|
-
expect(result?.content).toContain("yay");
|
|
61
|
-
expect(result?.content).toContain("AUR helper");
|
|
62
|
-
expect(result?.content).toContain("yay -S yay");
|
|
63
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
64
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
65
|
-
expect(result?.truncated).toBeDefined();
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
describe.skipIf(SKIP)("handleRubyGems", () => {
|
|
70
|
-
it("returns null for non-RubyGems URLs", async () => {
|
|
71
|
-
const result = await handleRubyGems("https://example.com", 20);
|
|
72
|
-
expect(result).toBeNull();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("returns null for non-gem RubyGems URLs", async () => {
|
|
76
|
-
const result = await handleRubyGems("https://rubygems.org/", 20);
|
|
77
|
-
expect(result).toBeNull();
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("fetches rails gem", async () => {
|
|
81
|
-
const result = await handleRubyGems("https://rubygems.org/gems/rails", 20);
|
|
82
|
-
expect(result).not.toBeNull();
|
|
83
|
-
expect(result?.method).toBe("rubygems");
|
|
84
|
-
expect(result?.content).toContain("rails");
|
|
85
|
-
expect(result?.content).toContain("Total Downloads");
|
|
86
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
87
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
88
|
-
expect(result?.truncated).toBeDefined();
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
describe.skipIf(SKIP)("handleNuGet", () => {
|
|
93
|
-
it("returns null for non-NuGet URLs", async () => {
|
|
94
|
-
const result = await handleNuGet("https://example.com", 20);
|
|
95
|
-
expect(result).toBeNull();
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it("returns null for non-package NuGet URLs", async () => {
|
|
99
|
-
const result = await handleNuGet("https://www.nuget.org/", 20);
|
|
100
|
-
expect(result).toBeNull();
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it("fetches Newtonsoft.Json package", async () => {
|
|
104
|
-
const result = await handleNuGet("https://www.nuget.org/packages/Newtonsoft.Json", 20);
|
|
105
|
-
expect(result).not.toBeNull();
|
|
106
|
-
expect(result?.method).toBe("nuget");
|
|
107
|
-
expect(result?.content).toContain("Newtonsoft.Json");
|
|
108
|
-
expect(result?.content).toContain("JSON");
|
|
109
|
-
expect(result?.content).toContain("Total Downloads");
|
|
110
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
111
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
112
|
-
expect(result?.truncated).toBeDefined();
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
describe.skipIf(SKIP)("handlePackagist", () => {
|
|
117
|
-
it("returns null for non-Packagist URLs", async () => {
|
|
118
|
-
const result = await handlePackagist("https://example.com", 20);
|
|
119
|
-
expect(result).toBeNull();
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it("returns null for non-package Packagist URLs", async () => {
|
|
123
|
-
const result = await handlePackagist("https://packagist.org/", 20);
|
|
124
|
-
expect(result).toBeNull();
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it("fetches laravel/framework package", async () => {
|
|
128
|
-
const result = await handlePackagist("https://packagist.org/packages/laravel/framework", 20);
|
|
129
|
-
expect(result).not.toBeNull();
|
|
130
|
-
expect(result?.method).toBe("packagist");
|
|
131
|
-
expect(result?.content).toContain("laravel/framework");
|
|
132
|
-
expect(result?.content).toContain("Downloads");
|
|
133
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
134
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
135
|
-
expect(result?.truncated).toBeDefined();
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
describe.skipIf(SKIP)("handleMaven", () => {
|
|
140
|
-
it("returns null for non-Maven URLs", async () => {
|
|
141
|
-
const result = await handleMaven("https://example.com", 20);
|
|
142
|
-
expect(result).toBeNull();
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it("returns null for non-artifact Maven URLs", async () => {
|
|
146
|
-
const result = await handleMaven("https://search.maven.org/", 20);
|
|
147
|
-
expect(result).toBeNull();
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it("fetches commons-lang3 artifact from search.maven.org", async () => {
|
|
151
|
-
const result = await handleMaven("https://search.maven.org/artifact/org.apache.commons/commons-lang3", 20);
|
|
152
|
-
expect(result).not.toBeNull();
|
|
153
|
-
expect(result?.method).toBe("maven");
|
|
154
|
-
expect(result?.content).toContain("org.apache.commons");
|
|
155
|
-
expect(result?.content).toContain("commons-lang3");
|
|
156
|
-
expect(result?.content).toContain("<groupId>");
|
|
157
|
-
expect(result?.content).toContain("implementation");
|
|
158
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
159
|
-
expect(result?.fetchedAt).toBeTruthy();
|
|
160
|
-
expect(result?.truncated).toBeDefined();
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it("fetches commons-lang3 artifact from mvnrepository.com", async () => {
|
|
164
|
-
const result = await handleMaven("https://mvnrepository.com/artifact/org.apache.commons/commons-lang3", 20);
|
|
165
|
-
expect(result).not.toBeNull();
|
|
166
|
-
expect(result?.method).toBe("maven");
|
|
167
|
-
expect(result?.content).toContain("org.apache.commons");
|
|
168
|
-
expect(result?.content).toContain("commons-lang3");
|
|
169
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
170
|
-
});
|
|
171
|
-
});
|
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { handleCratesIo } from "./crates-io";
|
|
3
|
-
import { handleGoPkg } from "./go-pkg";
|
|
4
|
-
import { handleHex } from "./hex";
|
|
5
|
-
import { handleNpm } from "./npm";
|
|
6
|
-
import { handlePubDev } from "./pub-dev";
|
|
7
|
-
import { handlePyPI } from "./pypi";
|
|
8
|
-
|
|
9
|
-
const SKIP = !process.env.WEB_FETCH_INTEGRATION;
|
|
10
|
-
|
|
11
|
-
describe.skipIf(SKIP)("handlePyPI", () => {
|
|
12
|
-
it("returns null for non-PyPI URLs", async () => {
|
|
13
|
-
const result = await handlePyPI("https://example.com", 10);
|
|
14
|
-
expect(result).toBeNull();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("returns null for invalid PyPI URLs", async () => {
|
|
18
|
-
const result = await handlePyPI("https://pypi.org/invalid", 10);
|
|
19
|
-
expect(result).toBeNull();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("returns null for PyPI URLs without project path", async () => {
|
|
23
|
-
const result = await handlePyPI("https://pypi.org/", 10);
|
|
24
|
-
expect(result).toBeNull();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("fetches requests package", async () => {
|
|
28
|
-
const result = await handlePyPI("https://pypi.org/project/requests/", 20);
|
|
29
|
-
expect(result).not.toBeNull();
|
|
30
|
-
expect(result?.method).toBe("pypi");
|
|
31
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
32
|
-
expect(result?.content).toContain("requests");
|
|
33
|
-
expect(result?.content).toMatch(/Latest.*\d+\.\d+/);
|
|
34
|
-
expect(result?.notes).toContain("Fetched via PyPI JSON API");
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("extracts package name correctly", async () => {
|
|
38
|
-
const result = await handlePyPI("https://pypi.org/project/requests/2.28.0/", 20);
|
|
39
|
-
expect(result).not.toBeNull();
|
|
40
|
-
expect(result?.content).toContain("requests");
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("handles www subdomain", async () => {
|
|
44
|
-
const result = await handlePyPI("https://www.pypi.org/project/requests/", 20);
|
|
45
|
-
expect(result).not.toBeNull();
|
|
46
|
-
expect(result?.method).toBe("pypi");
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
describe.skipIf(SKIP)("handleGoPkg", () => {
|
|
51
|
-
it("returns null for non-pkg.go.dev URLs", async () => {
|
|
52
|
-
const result = await handleGoPkg("https://example.com", 10);
|
|
53
|
-
expect(result).toBeNull();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("returns null for pkg.go.dev root without package", async () => {
|
|
57
|
-
const result = await handleGoPkg("https://pkg.go.dev/", 10);
|
|
58
|
-
expect(result).toBeNull();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it("fetches gin package", async () => {
|
|
62
|
-
const result = await handleGoPkg("https://pkg.go.dev/github.com/gin-gonic/gin", 20);
|
|
63
|
-
expect(result).not.toBeNull();
|
|
64
|
-
expect(result?.method).toBe("go-pkg");
|
|
65
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
66
|
-
expect(result?.content).toMatch(/Module:/);
|
|
67
|
-
expect(result?.content).toMatch(/Version:/);
|
|
68
|
-
expect(result?.content).toMatch(/License:/);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("handles package with version", async () => {
|
|
72
|
-
const result = await handleGoPkg("https://pkg.go.dev/github.com/gin-gonic/gin@v1.9.0", 20);
|
|
73
|
-
expect(result).not.toBeNull();
|
|
74
|
-
expect(result?.content).toMatch(/Version:\*\*\s*v1\.9\.0/);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("extracts package documentation", async () => {
|
|
78
|
-
const result = await handleGoPkg("https://pkg.go.dev/github.com/gin-gonic/gin", 20);
|
|
79
|
-
expect(result).not.toBeNull();
|
|
80
|
-
expect(result?.content).toMatch(/Documentation|Synopsis|Index/);
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
describe.skipIf(SKIP)("handleHex", () => {
|
|
85
|
-
it("returns null for non-hex.pm URLs", async () => {
|
|
86
|
-
const result = await handleHex("https://example.com", 10);
|
|
87
|
-
expect(result).toBeNull();
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it("returns null for invalid hex.pm URLs", async () => {
|
|
91
|
-
const result = await handleHex("https://hex.pm/invalid", 10);
|
|
92
|
-
expect(result).toBeNull();
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("returns null for hex.pm URLs without package path", async () => {
|
|
96
|
-
const result = await handleHex("https://hex.pm/", 10);
|
|
97
|
-
expect(result).toBeNull();
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it("fetches phoenix package", async () => {
|
|
101
|
-
const result = await handleHex("https://hex.pm/packages/phoenix", 20);
|
|
102
|
-
expect(result).not.toBeNull();
|
|
103
|
-
expect(result?.method).toBe("hex");
|
|
104
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
105
|
-
expect(result?.content).toContain("phoenix");
|
|
106
|
-
expect(result?.content).toMatch(/Latest.*\d+\.\d+/);
|
|
107
|
-
expect(result?.notes).toContain("Fetched via Hex.pm API");
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("extracts package description", async () => {
|
|
111
|
-
const result = await handleHex("https://hex.pm/packages/phoenix", 20);
|
|
112
|
-
expect(result).not.toBeNull();
|
|
113
|
-
expect(result?.content).toMatch(/phoenix|Phoenix|web framework/i);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it("handles www subdomain", async () => {
|
|
117
|
-
const result = await handleHex("https://www.hex.pm/packages/phoenix", 20);
|
|
118
|
-
expect(result).not.toBeNull();
|
|
119
|
-
expect(result?.method).toBe("hex");
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it("includes download statistics", async () => {
|
|
123
|
-
const result = await handleHex("https://hex.pm/packages/phoenix", 20);
|
|
124
|
-
expect(result).not.toBeNull();
|
|
125
|
-
expect(result?.content).toMatch(/Total Downloads|This Week/);
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
describe.skipIf(SKIP)("handlePubDev", () => {
|
|
130
|
-
it("returns null for non-pub.dev URLs", async () => {
|
|
131
|
-
const result = await handlePubDev("https://example.com", 10);
|
|
132
|
-
expect(result).toBeNull();
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it("returns null for invalid pub.dev URLs", async () => {
|
|
136
|
-
const result = await handlePubDev("https://pub.dev/invalid", 10);
|
|
137
|
-
expect(result).toBeNull();
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it("returns null for pub.dev URLs without package path", async () => {
|
|
141
|
-
const result = await handlePubDev("https://pub.dev/", 10);
|
|
142
|
-
expect(result).toBeNull();
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it("fetches flutter package", async () => {
|
|
146
|
-
const result = await handlePubDev("https://pub.dev/packages/flutter", 20);
|
|
147
|
-
expect(result).not.toBeNull();
|
|
148
|
-
expect(result?.method).toBe("pub.dev");
|
|
149
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
150
|
-
expect(result?.content).toContain("flutter");
|
|
151
|
-
expect(result?.content).toMatch(/Latest.*\d+\.\d+/);
|
|
152
|
-
expect(result?.notes).toContain("Fetched via pub.dev API");
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it("extracts package metadata", async () => {
|
|
156
|
-
const result = await handlePubDev("https://pub.dev/packages/http", 20);
|
|
157
|
-
expect(result).not.toBeNull();
|
|
158
|
-
expect(result?.content).toMatch(/SDK:/);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it("handles www subdomain", async () => {
|
|
162
|
-
const result = await handlePubDev("https://www.pub.dev/packages/flutter", 20);
|
|
163
|
-
expect(result).not.toBeNull();
|
|
164
|
-
expect(result?.method).toBe("pub.dev");
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it("includes package dependencies", async () => {
|
|
168
|
-
const result = await handlePubDev("https://pub.dev/packages/http", 20);
|
|
169
|
-
expect(result).not.toBeNull();
|
|
170
|
-
expect(result?.content).toMatch(/Dependencies/);
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
describe.skipIf(SKIP)("handleNpm", () => {
|
|
175
|
-
it("returns null for non-npm URLs", async () => {
|
|
176
|
-
const result = await handleNpm("https://example.com", 10);
|
|
177
|
-
expect(result).toBeNull();
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it("returns null for invalid npm URLs", async () => {
|
|
181
|
-
const result = await handleNpm("https://www.npmjs.com/invalid", 10);
|
|
182
|
-
expect(result).toBeNull();
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it("fetches lodash package", async () => {
|
|
186
|
-
const result = await handleNpm("https://www.npmjs.com/package/lodash", 20000);
|
|
187
|
-
expect(result).not.toBeNull();
|
|
188
|
-
expect(result?.method).toBe("npm");
|
|
189
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
190
|
-
expect(result?.content).toContain("lodash");
|
|
191
|
-
expect(result?.content).toMatch(/Latest.*\d+\.\d+/);
|
|
192
|
-
expect(result?.notes).toContain("Fetched via npm registry");
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it("includes version info", async () => {
|
|
196
|
-
const result = await handleNpm("https://www.npmjs.com/package/express", 20000);
|
|
197
|
-
expect(result).not.toBeNull();
|
|
198
|
-
expect(result?.content).toMatch(/Latest:\*\*\s*\d+\.\d+\.\d+/);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
it("includes download stats", async () => {
|
|
202
|
-
const result = await handleNpm("https://www.npmjs.com/package/express", 20000);
|
|
203
|
-
expect(result).not.toBeNull();
|
|
204
|
-
expect(result?.content).toMatch(/Weekly Downloads/);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it("handles www subdomain", async () => {
|
|
208
|
-
const result = await handleNpm("https://www.npmjs.com/package/lodash", 20000);
|
|
209
|
-
expect(result).not.toBeNull();
|
|
210
|
-
expect(result?.method).toBe("npm");
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it("handles npmjs.com without www", async () => {
|
|
214
|
-
const result = await handleNpm("https://npmjs.com/package/lodash", 20000);
|
|
215
|
-
expect(result).not.toBeNull();
|
|
216
|
-
expect(result?.method).toBe("npm");
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
describe.skipIf(SKIP)("handleCratesIo", () => {
|
|
221
|
-
it("returns null for non-crates.io URLs", async () => {
|
|
222
|
-
const result = await handleCratesIo("https://example.com", 10);
|
|
223
|
-
expect(result).toBeNull();
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it("returns null for invalid crates.io URLs", async () => {
|
|
227
|
-
const result = await handleCratesIo("https://crates.io/invalid", 10);
|
|
228
|
-
expect(result).toBeNull();
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
it("fetches serde package", async () => {
|
|
232
|
-
const result = await handleCratesIo("https://crates.io/crates/serde", 20000);
|
|
233
|
-
expect(result).not.toBeNull();
|
|
234
|
-
expect(result?.method).toBe("crates.io");
|
|
235
|
-
expect(result?.contentType).toBe("text/markdown");
|
|
236
|
-
expect(result?.content).toContain("serde");
|
|
237
|
-
expect(result?.content).toMatch(/Latest.*\d+\.\d+/);
|
|
238
|
-
expect(result?.notes).toContain("Fetched via crates.io API");
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
it("includes version info", async () => {
|
|
242
|
-
const result = await handleCratesIo("https://crates.io/crates/tokio", 20000);
|
|
243
|
-
expect(result).not.toBeNull();
|
|
244
|
-
expect(result?.content).toMatch(/Latest:\*\*\s*\d+\.\d+\.\d+/);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it("includes download stats", async () => {
|
|
248
|
-
const result = await handleCratesIo("https://crates.io/crates/tokio", 20000);
|
|
249
|
-
expect(result).not.toBeNull();
|
|
250
|
-
expect(result?.content).toMatch(/Downloads:\*\*/);
|
|
251
|
-
expect(result?.content).toMatch(/total.*recent/);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
it("handles www subdomain", async () => {
|
|
255
|
-
const result = await handleCratesIo("https://www.crates.io/crates/serde", 20000);
|
|
256
|
-
expect(result).not.toBeNull();
|
|
257
|
-
expect(result?.method).toBe("crates.io");
|
|
258
|
-
});
|
|
259
|
-
});
|