bluera-knowledge 0.14.0 → 0.14.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.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +7 -0
- package/package.json +12 -1
- package/.claude/commands/code-review.md +0 -15
- package/.claude/commands/commit.md +0 -34
- package/.claude/council-cache/1a43ed5977b8f29afc79a9bf5c4082ee5ad8338c42ab991a4241a48f80c1e46d.json +0 -7
- package/.claude/hooks/post-edit-check.sh +0 -40
- package/.claude/rules/code-quality.md +0 -12
- package/.claude/rules/git.md +0 -5
- package/.claude/rules/versioning.md +0 -7
- package/.claude/settings.local.json.example +0 -45
- package/.claude/skills/atomic-commits/SKILL.md +0 -61
- package/.claude/skills/code-review-repo/skill.md +0 -62
- package/.editorconfig +0 -15
- package/.env.example +0 -21
- package/.github/workflows/auto-release.yml +0 -64
- package/.github/workflows/ci.yml +0 -168
- package/.github/workflows/release.yml +0 -74
- package/.github/workflows/update-marketplace.yml +0 -96
- package/.husky/pre-commit +0 -48
- package/.husky/pre-push +0 -39
- package/.mcp.json +0 -11
- package/.prettierrc +0 -9
- package/.versionrc.json +0 -24
- package/CLAUDE.md +0 -110
- package/CONTRIBUTING.md +0 -307
- package/NOTICE +0 -47
- package/SECURITY.md +0 -65
- package/bun.lock +0 -2036
- package/docs/claude-code-best-practices.md +0 -458
- package/docs/cli.md +0 -170
- package/docs/commands.md +0 -392
- package/docs/crawler-architecture.md +0 -89
- package/docs/mcp-integration.md +0 -130
- package/docs/token-efficiency.md +0 -91
- package/eslint-rules/require-skip-comment.js +0 -81
- package/eslint.config.js +0 -103
- package/knip.json +0 -43
- package/scripts/test-mcp-dev.js +0 -260
- package/scripts/validate-npm-release.sh +0 -314
- package/src/analysis/adapter-registry.test.ts +0 -211
- package/src/analysis/adapter-registry.ts +0 -155
- package/src/analysis/ast-parser.test.ts +0 -470
- package/src/analysis/ast-parser.ts +0 -198
- package/src/analysis/code-graph.test.ts +0 -718
- package/src/analysis/code-graph.ts +0 -249
- package/src/analysis/dependency-usage-analyzer.test.ts +0 -619
- package/src/analysis/dependency-usage-analyzer.ts +0 -433
- package/src/analysis/go-ast-parser.test.ts +0 -531
- package/src/analysis/go-ast-parser.ts +0 -471
- package/src/analysis/language-adapter.ts +0 -127
- package/src/analysis/parser-factory.test.ts +0 -210
- package/src/analysis/parser-factory.ts +0 -52
- package/src/analysis/python-ast-parser.test.ts +0 -210
- package/src/analysis/python-ast-parser.ts +0 -34
- package/src/analysis/repo-url-resolver.test.ts +0 -533
- package/src/analysis/repo-url-resolver.ts +0 -233
- package/src/analysis/rust-ast-parser.test.ts +0 -568
- package/src/analysis/rust-ast-parser.ts +0 -467
- package/src/analysis/tree-sitter-parser.test.ts +0 -297
- package/src/analysis/tree-sitter-parser.ts +0 -217
- package/src/analysis/zil/index.ts +0 -34
- package/src/analysis/zil/zil-adapter.test.ts +0 -187
- package/src/analysis/zil/zil-adapter.ts +0 -121
- package/src/analysis/zil/zil-lexer.test.ts +0 -222
- package/src/analysis/zil/zil-lexer.ts +0 -239
- package/src/analysis/zil/zil-parser.test.ts +0 -210
- package/src/analysis/zil/zil-parser.ts +0 -360
- package/src/analysis/zil/zil-special-forms.ts +0 -193
- package/src/cli/commands/crawl.test.ts +0 -1086
- package/src/cli/commands/crawl.ts +0 -220
- package/src/cli/commands/index-cmd.test.ts +0 -733
- package/src/cli/commands/index-cmd.ts +0 -128
- package/src/cli/commands/mcp.test.ts +0 -218
- package/src/cli/commands/mcp.ts +0 -18
- package/src/cli/commands/plugin-api.test.ts +0 -373
- package/src/cli/commands/plugin-api.ts +0 -82
- package/src/cli/commands/search.test.ts +0 -1047
- package/src/cli/commands/search.ts +0 -197
- package/src/cli/commands/serve.test.ts +0 -371
- package/src/cli/commands/serve.ts +0 -43
- package/src/cli/commands/setup.test.ts +0 -895
- package/src/cli/commands/setup.ts +0 -176
- package/src/cli/commands/store.test.ts +0 -1370
- package/src/cli/commands/store.ts +0 -229
- package/src/cli/commands/sync.test.ts +0 -54
- package/src/cli/commands/sync.ts +0 -313
- package/src/cli/index.ts +0 -8
- package/src/cli/program.ts +0 -59
- package/src/crawl/article-converter.test.ts +0 -576
- package/src/crawl/article-converter.ts +0 -142
- package/src/crawl/bridge.test.ts +0 -796
- package/src/crawl/bridge.ts +0 -349
- package/src/crawl/claude-client.test.ts +0 -902
- package/src/crawl/claude-client.ts +0 -261
- package/src/crawl/intelligent-crawler.test.ts +0 -1028
- package/src/crawl/intelligent-crawler.ts +0 -478
- package/src/crawl/markdown-utils.test.ts +0 -703
- package/src/crawl/markdown-utils.ts +0 -225
- package/src/crawl/schemas.ts +0 -114
- package/src/db/embeddings.test.ts +0 -79
- package/src/db/embeddings.ts +0 -78
- package/src/db/index.ts +0 -2
- package/src/db/lance.test.ts +0 -479
- package/src/db/lance.ts +0 -190
- package/src/defaults/repos.ts +0 -67
- package/src/index.ts +0 -124
- package/src/logging/index.ts +0 -25
- package/src/logging/logger.test.ts +0 -75
- package/src/logging/logger.ts +0 -145
- package/src/logging/payload.test.ts +0 -152
- package/src/logging/payload.ts +0 -119
- package/src/mcp/cache.test.ts +0 -202
- package/src/mcp/cache.ts +0 -103
- package/src/mcp/commands/index.ts +0 -24
- package/src/mcp/commands/job.commands.ts +0 -48
- package/src/mcp/commands/meta.commands.ts +0 -54
- package/src/mcp/commands/registry.ts +0 -180
- package/src/mcp/commands/store.commands.ts +0 -75
- package/src/mcp/commands/sync.commands.test.ts +0 -371
- package/src/mcp/commands/sync.commands.ts +0 -263
- package/src/mcp/commands/uninstall.commands.test.ts +0 -37
- package/src/mcp/commands/uninstall.commands.ts +0 -29
- package/src/mcp/handlers/execute.handler.test.ts +0 -179
- package/src/mcp/handlers/execute.handler.ts +0 -23
- package/src/mcp/handlers/index.ts +0 -39
- package/src/mcp/handlers/job.handler.test.ts +0 -189
- package/src/mcp/handlers/job.handler.ts +0 -118
- package/src/mcp/handlers/search.handler.test.ts +0 -324
- package/src/mcp/handlers/search.handler.ts +0 -287
- package/src/mcp/handlers/store.handler.test.ts +0 -408
- package/src/mcp/handlers/store.handler.ts +0 -318
- package/src/mcp/handlers/uninstall.handler.test.ts +0 -194
- package/src/mcp/handlers/uninstall.handler.ts +0 -142
- package/src/mcp/plugin-mcp-config.test.ts +0 -71
- package/src/mcp/schemas/index.test.ts +0 -356
- package/src/mcp/schemas/index.ts +0 -155
- package/src/mcp/server.test.ts +0 -91
- package/src/mcp/server.ts +0 -235
- package/src/mcp/types.ts +0 -41
- package/src/plugin/commands.test.ts +0 -925
- package/src/plugin/commands.ts +0 -311
- package/src/plugin/dependency-analyzer.test.ts +0 -380
- package/src/plugin/dependency-analyzer.ts +0 -210
- package/src/plugin/git-clone.test.ts +0 -387
- package/src/plugin/git-clone.ts +0 -57
- package/src/scripts/validate-npm-release.test.ts +0 -70
- package/src/server/app.test.ts +0 -752
- package/src/server/app.ts +0 -128
- package/src/server/index.test.ts +0 -475
- package/src/server/index.ts +0 -1
- package/src/services/chunking.service.test.ts +0 -363
- package/src/services/chunking.service.ts +0 -380
- package/src/services/code-graph.service.test.ts +0 -298
- package/src/services/code-graph.service.ts +0 -326
- package/src/services/code-unit.service.test.ts +0 -693
- package/src/services/code-unit.service.ts +0 -234
- package/src/services/config.service.test.ts +0 -146
- package/src/services/config.service.ts +0 -92
- package/src/services/gitignore.service.test.ts +0 -157
- package/src/services/gitignore.service.ts +0 -132
- package/src/services/index.service.test.ts +0 -2301
- package/src/services/index.service.ts +0 -442
- package/src/services/index.ts +0 -119
- package/src/services/job.service.test.ts +0 -531
- package/src/services/job.service.ts +0 -298
- package/src/services/project-root.service.test.ts +0 -504
- package/src/services/project-root.service.ts +0 -112
- package/src/services/search.service.test.ts +0 -2263
- package/src/services/search.service.ts +0 -1341
- package/src/services/services.test.ts +0 -108
- package/src/services/snippet.service.test.ts +0 -213
- package/src/services/snippet.service.ts +0 -193
- package/src/services/store-definition.service.test.ts +0 -440
- package/src/services/store-definition.service.ts +0 -198
- package/src/services/store.service.test.ts +0 -843
- package/src/services/store.service.ts +0 -363
- package/src/services/token.service.test.ts +0 -45
- package/src/services/token.service.ts +0 -33
- package/src/services/watch.service.test.ts +0 -600
- package/src/services/watch.service.ts +0 -84
- package/src/types/brands.test.ts +0 -47
- package/src/types/brands.ts +0 -32
- package/src/types/config.ts +0 -79
- package/src/types/document.ts +0 -54
- package/src/types/index.ts +0 -73
- package/src/types/job.ts +0 -61
- package/src/types/progress.ts +0 -9
- package/src/types/result.test.ts +0 -54
- package/src/types/result.ts +0 -41
- package/src/types/search.ts +0 -105
- package/src/types/store-definition.test.ts +0 -492
- package/src/types/store-definition.ts +0 -129
- package/src/types/store.test.ts +0 -69
- package/src/types/store.ts +0 -47
- package/src/utils/type-guards.test.ts +0 -351
- package/src/utils/type-guards.ts +0 -61
- package/src/workers/background-worker-cli.test.ts +0 -35
- package/src/workers/background-worker-cli.ts +0 -149
- package/src/workers/background-worker.test.ts +0 -222
- package/src/workers/background-worker.ts +0 -322
- package/src/workers/pid-file.test.ts +0 -167
- package/src/workers/pid-file.ts +0 -82
- package/src/workers/spawn-worker.test.ts +0 -194
- package/src/workers/spawn-worker.ts +0 -70
- package/tests/analysis/ast-parser.test.ts +0 -98
- package/tests/analysis/code-graph.test.ts +0 -60
- package/tests/fixtures/README.md +0 -114
- package/tests/fixtures/code-snippets/api/error-handling.ts +0 -256
- package/tests/fixtures/code-snippets/api/rest-controller.ts +0 -297
- package/tests/fixtures/code-snippets/auth/jwt-auth.ts +0 -197
- package/tests/fixtures/code-snippets/auth/oauth-flow.ts +0 -245
- package/tests/fixtures/code-snippets/database/repository-pattern.ts +0 -280
- package/tests/fixtures/corpus/VERSION.md +0 -25
- package/tests/fixtures/corpus/articles/jwt-authentication.md +0 -97
- package/tests/fixtures/corpus/articles/react-hooks-patterns.md +0 -127
- package/tests/fixtures/corpus/articles/typescript-generics.md +0 -111
- package/tests/fixtures/corpus/documentation/express-middleware.md +0 -71
- package/tests/fixtures/corpus/documentation/express-routing.md +0 -83
- package/tests/fixtures/corpus/documentation/node-streams.md +0 -78
- package/tests/fixtures/corpus/oss-repos/express/History.md +0 -3871
- package/tests/fixtures/corpus/oss-repos/express/LICENSE +0 -24
- package/tests/fixtures/corpus/oss-repos/express/README.md +0 -276
- package/tests/fixtures/corpus/oss-repos/express/SECURITY.md +0 -56
- package/tests/fixtures/corpus/oss-repos/express/benchmarks/Makefile +0 -17
- package/tests/fixtures/corpus/oss-repos/express/benchmarks/README.md +0 -34
- package/tests/fixtures/corpus/oss-repos/express/benchmarks/middleware.js +0 -20
- package/tests/fixtures/corpus/oss-repos/express/benchmarks/run +0 -18
- package/tests/fixtures/corpus/oss-repos/express/examples/README.md +0 -29
- package/tests/fixtures/corpus/oss-repos/express/examples/auth/index.js +0 -134
- package/tests/fixtures/corpus/oss-repos/express/examples/auth/views/foot.ejs +0 -2
- package/tests/fixtures/corpus/oss-repos/express/examples/auth/views/head.ejs +0 -20
- package/tests/fixtures/corpus/oss-repos/express/examples/auth/views/login.ejs +0 -21
- package/tests/fixtures/corpus/oss-repos/express/examples/content-negotiation/db.js +0 -9
- package/tests/fixtures/corpus/oss-repos/express/examples/content-negotiation/index.js +0 -46
- package/tests/fixtures/corpus/oss-repos/express/examples/content-negotiation/users.js +0 -19
- package/tests/fixtures/corpus/oss-repos/express/examples/cookie-sessions/index.js +0 -25
- package/tests/fixtures/corpus/oss-repos/express/examples/cookies/index.js +0 -53
- package/tests/fixtures/corpus/oss-repos/express/examples/downloads/files/CCTV/345/244/247/350/265/233/344/270/212/346/265/267/345/210/206/350/265/233/345/214/272.txt +0 -2
- package/tests/fixtures/corpus/oss-repos/express/examples/downloads/files/amazing.txt +0 -1
- package/tests/fixtures/corpus/oss-repos/express/examples/downloads/files/notes/groceries.txt +0 -3
- package/tests/fixtures/corpus/oss-repos/express/examples/downloads/index.js +0 -40
- package/tests/fixtures/corpus/oss-repos/express/examples/ejs/index.js +0 -57
- package/tests/fixtures/corpus/oss-repos/express/examples/ejs/public/stylesheets/style.css +0 -4
- package/tests/fixtures/corpus/oss-repos/express/examples/ejs/views/footer.html +0 -2
- package/tests/fixtures/corpus/oss-repos/express/examples/ejs/views/header.html +0 -9
- package/tests/fixtures/corpus/oss-repos/express/examples/ejs/views/users.html +0 -10
- package/tests/fixtures/corpus/oss-repos/express/examples/error/index.js +0 -53
- package/tests/fixtures/corpus/oss-repos/express/examples/error-pages/index.js +0 -103
- package/tests/fixtures/corpus/oss-repos/express/examples/error-pages/views/404.ejs +0 -3
- package/tests/fixtures/corpus/oss-repos/express/examples/error-pages/views/500.ejs +0 -8
- package/tests/fixtures/corpus/oss-repos/express/examples/error-pages/views/error_header.ejs +0 -10
- package/tests/fixtures/corpus/oss-repos/express/examples/error-pages/views/footer.ejs +0 -2
- package/tests/fixtures/corpus/oss-repos/express/examples/error-pages/views/index.ejs +0 -20
- package/tests/fixtures/corpus/oss-repos/express/examples/hello-world/index.js +0 -15
- package/tests/fixtures/corpus/oss-repos/express/examples/markdown/index.js +0 -44
- package/tests/fixtures/corpus/oss-repos/express/examples/markdown/views/index.md +0 -4
- package/tests/fixtures/corpus/oss-repos/express/examples/multi-router/controllers/api_v1.js +0 -15
- package/tests/fixtures/corpus/oss-repos/express/examples/multi-router/controllers/api_v2.js +0 -15
- package/tests/fixtures/corpus/oss-repos/express/examples/multi-router/index.js +0 -18
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/controllers/main/index.js +0 -5
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/controllers/pet/index.js +0 -31
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/controllers/pet/views/edit.ejs +0 -17
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/controllers/pet/views/show.ejs +0 -15
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/controllers/user/index.js +0 -41
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/controllers/user/views/edit.hbs +0 -27
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/controllers/user/views/list.hbs +0 -18
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/controllers/user/views/show.hbs +0 -31
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/controllers/user-pet/index.js +0 -22
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/db.js +0 -16
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/index.js +0 -95
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/lib/boot.js +0 -83
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/public/style.css +0 -14
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/views/404.ejs +0 -13
- package/tests/fixtures/corpus/oss-repos/express/examples/mvc/views/5xx.ejs +0 -13
- package/tests/fixtures/corpus/oss-repos/express/examples/online/index.js +0 -61
- package/tests/fixtures/corpus/oss-repos/express/examples/params/index.js +0 -74
- package/tests/fixtures/corpus/oss-repos/express/examples/resource/index.js +0 -95
- package/tests/fixtures/corpus/oss-repos/express/examples/route-map/index.js +0 -75
- package/tests/fixtures/corpus/oss-repos/express/examples/route-middleware/index.js +0 -90
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/index.js +0 -55
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/post.js +0 -13
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/public/style.css +0 -24
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/site.js +0 -5
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/user.js +0 -47
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/views/footer.ejs +0 -2
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/views/header.ejs +0 -9
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/views/index.ejs +0 -10
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/views/posts/index.ejs +0 -12
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/views/users/edit.ejs +0 -23
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/views/users/index.ejs +0 -14
- package/tests/fixtures/corpus/oss-repos/express/examples/route-separation/views/users/view.ejs +0 -9
- package/tests/fixtures/corpus/oss-repos/express/examples/search/index.js +0 -61
- package/tests/fixtures/corpus/oss-repos/express/examples/search/public/client.js +0 -15
- package/tests/fixtures/corpus/oss-repos/express/examples/search/public/index.html +0 -21
- package/tests/fixtures/corpus/oss-repos/express/examples/session/index.js +0 -37
- package/tests/fixtures/corpus/oss-repos/express/examples/session/redis.js +0 -39
- package/tests/fixtures/corpus/oss-repos/express/examples/static-files/index.js +0 -43
- package/tests/fixtures/corpus/oss-repos/express/examples/static-files/public/css/style.css +0 -3
- package/tests/fixtures/corpus/oss-repos/express/examples/static-files/public/hello.txt +0 -1
- package/tests/fixtures/corpus/oss-repos/express/examples/static-files/public/js/app.js +0 -1
- package/tests/fixtures/corpus/oss-repos/express/examples/vhost/index.js +0 -53
- package/tests/fixtures/corpus/oss-repos/express/examples/view-constructor/github-view.js +0 -53
- package/tests/fixtures/corpus/oss-repos/express/examples/view-constructor/index.js +0 -48
- package/tests/fixtures/corpus/oss-repos/express/examples/view-locals/index.js +0 -155
- package/tests/fixtures/corpus/oss-repos/express/examples/view-locals/user.js +0 -36
- package/tests/fixtures/corpus/oss-repos/express/examples/view-locals/views/index.ejs +0 -20
- package/tests/fixtures/corpus/oss-repos/express/examples/web-service/index.js +0 -117
- package/tests/fixtures/corpus/oss-repos/express/index.js +0 -11
- package/tests/fixtures/corpus/oss-repos/express/lib/application.js +0 -631
- package/tests/fixtures/corpus/oss-repos/express/lib/express.js +0 -81
- package/tests/fixtures/corpus/oss-repos/express/lib/request.js +0 -514
- package/tests/fixtures/corpus/oss-repos/express/lib/response.js +0 -1053
- package/tests/fixtures/corpus/oss-repos/express/lib/utils.js +0 -271
- package/tests/fixtures/corpus/oss-repos/express/lib/view.js +0 -205
- package/tests/fixtures/corpus/oss-repos/express/package.json +0 -99
- package/tests/fixtures/corpus/oss-repos/express/test/Route.js +0 -274
- package/tests/fixtures/corpus/oss-repos/express/test/Router.js +0 -636
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/auth.js +0 -117
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/content-negotiation.js +0 -49
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/cookie-sessions.js +0 -38
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/cookies.js +0 -71
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/downloads.js +0 -47
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/ejs.js +0 -17
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/error-pages.js +0 -99
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/error.js +0 -29
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/hello-world.js +0 -21
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/markdown.js +0 -21
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/multi-router.js +0 -44
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/mvc.js +0 -132
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/params.js +0 -44
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/resource.js +0 -68
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/route-map.js +0 -45
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/route-separation.js +0 -97
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/vhost.js +0 -46
- package/tests/fixtures/corpus/oss-repos/express/test/acceptance/web-service.js +0 -105
- package/tests/fixtures/corpus/oss-repos/express/test/app.all.js +0 -38
- package/tests/fixtures/corpus/oss-repos/express/test/app.engine.js +0 -83
- package/tests/fixtures/corpus/oss-repos/express/test/app.head.js +0 -66
- package/tests/fixtures/corpus/oss-repos/express/test/app.js +0 -120
- package/tests/fixtures/corpus/oss-repos/express/test/app.listen.js +0 -55
- package/tests/fixtures/corpus/oss-repos/express/test/app.locals.js +0 -26
- package/tests/fixtures/corpus/oss-repos/express/test/app.options.js +0 -116
- package/tests/fixtures/corpus/oss-repos/express/test/app.param.js +0 -323
- package/tests/fixtures/corpus/oss-repos/express/test/app.render.js +0 -374
- package/tests/fixtures/corpus/oss-repos/express/test/app.request.js +0 -143
- package/tests/fixtures/corpus/oss-repos/express/test/app.response.js +0 -143
- package/tests/fixtures/corpus/oss-repos/express/test/app.route.js +0 -197
- package/tests/fixtures/corpus/oss-repos/express/test/app.router.js +0 -1217
- package/tests/fixtures/corpus/oss-repos/express/test/app.routes.error.js +0 -62
- package/tests/fixtures/corpus/oss-repos/express/test/app.use.js +0 -542
- package/tests/fixtures/corpus/oss-repos/express/test/config.js +0 -207
- package/tests/fixtures/corpus/oss-repos/express/test/exports.js +0 -82
- package/tests/fixtures/corpus/oss-repos/express/test/express.json.js +0 -755
- package/tests/fixtures/corpus/oss-repos/express/test/express.raw.js +0 -513
- package/tests/fixtures/corpus/oss-repos/express/test/express.static.js +0 -815
- package/tests/fixtures/corpus/oss-repos/express/test/express.text.js +0 -566
- package/tests/fixtures/corpus/oss-repos/express/test/express.urlencoded.js +0 -828
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/% of dogs.txt +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/.name +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/blog/index.html +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/blog/post/index.tmpl +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/broken.send +0 -0
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/default_layout/name.tmpl +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/default_layout/user.tmpl +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/email.tmpl +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/empty.txt +0 -0
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/local_layout/user.tmpl +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/name.tmpl +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/name.txt +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/nums.txt +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/pets/names.txt +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/snow /342/230/203/.gitkeep +0 -0
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/todo.html +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/todo.txt +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/user.html +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/user.tmpl +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/users/index.html +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/fixtures/users/tobi.txt +0 -1
- package/tests/fixtures/corpus/oss-repos/express/test/middleware.basic.js +0 -42
- package/tests/fixtures/corpus/oss-repos/express/test/regression.js +0 -20
- package/tests/fixtures/corpus/oss-repos/express/test/req.accepts.js +0 -125
- package/tests/fixtures/corpus/oss-repos/express/test/req.acceptsCharsets.js +0 -50
- package/tests/fixtures/corpus/oss-repos/express/test/req.acceptsEncodings.js +0 -39
- package/tests/fixtures/corpus/oss-repos/express/test/req.acceptsLanguages.js +0 -57
- package/tests/fixtures/corpus/oss-repos/express/test/req.baseUrl.js +0 -88
- package/tests/fixtures/corpus/oss-repos/express/test/req.fresh.js +0 -70
- package/tests/fixtures/corpus/oss-repos/express/test/req.get.js +0 -60
- package/tests/fixtures/corpus/oss-repos/express/test/req.host.js +0 -156
- package/tests/fixtures/corpus/oss-repos/express/test/req.hostname.js +0 -188
- package/tests/fixtures/corpus/oss-repos/express/test/req.ip.js +0 -113
- package/tests/fixtures/corpus/oss-repos/express/test/req.ips.js +0 -71
- package/tests/fixtures/corpus/oss-repos/express/test/req.is.js +0 -169
- package/tests/fixtures/corpus/oss-repos/express/test/req.path.js +0 -20
- package/tests/fixtures/corpus/oss-repos/express/test/req.protocol.js +0 -113
- package/tests/fixtures/corpus/oss-repos/express/test/req.query.js +0 -106
- package/tests/fixtures/corpus/oss-repos/express/test/req.range.js +0 -104
- package/tests/fixtures/corpus/oss-repos/express/test/req.route.js +0 -28
- package/tests/fixtures/corpus/oss-repos/express/test/req.secure.js +0 -101
- package/tests/fixtures/corpus/oss-repos/express/test/req.signedCookies.js +0 -37
- package/tests/fixtures/corpus/oss-repos/express/test/req.stale.js +0 -50
- package/tests/fixtures/corpus/oss-repos/express/test/req.subdomains.js +0 -173
- package/tests/fixtures/corpus/oss-repos/express/test/req.xhr.js +0 -42
- package/tests/fixtures/corpus/oss-repos/express/test/res.append.js +0 -116
- package/tests/fixtures/corpus/oss-repos/express/test/res.attachment.js +0 -79
- package/tests/fixtures/corpus/oss-repos/express/test/res.clearCookie.js +0 -62
- package/tests/fixtures/corpus/oss-repos/express/test/res.cookie.js +0 -295
- package/tests/fixtures/corpus/oss-repos/express/test/res.download.js +0 -487
- package/tests/fixtures/corpus/oss-repos/express/test/res.format.js +0 -248
- package/tests/fixtures/corpus/oss-repos/express/test/res.get.js +0 -21
- package/tests/fixtures/corpus/oss-repos/express/test/res.json.js +0 -186
- package/tests/fixtures/corpus/oss-repos/express/test/res.jsonp.js +0 -344
- package/tests/fixtures/corpus/oss-repos/express/test/res.links.js +0 -65
- package/tests/fixtures/corpus/oss-repos/express/test/res.locals.js +0 -40
- package/tests/fixtures/corpus/oss-repos/express/test/res.location.js +0 -316
- package/tests/fixtures/corpus/oss-repos/express/test/res.redirect.js +0 -214
- package/tests/fixtures/corpus/oss-repos/express/test/res.render.js +0 -367
- package/tests/fixtures/corpus/oss-repos/express/test/res.send.js +0 -569
- package/tests/fixtures/corpus/oss-repos/express/test/res.sendFile.js +0 -913
- package/tests/fixtures/corpus/oss-repos/express/test/res.sendStatus.js +0 -44
- package/tests/fixtures/corpus/oss-repos/express/test/res.set.js +0 -124
- package/tests/fixtures/corpus/oss-repos/express/test/res.status.js +0 -206
- package/tests/fixtures/corpus/oss-repos/express/test/res.type.js +0 -46
- package/tests/fixtures/corpus/oss-repos/express/test/res.vary.js +0 -90
- package/tests/fixtures/corpus/oss-repos/express/test/support/env.js +0 -3
- package/tests/fixtures/corpus/oss-repos/express/test/support/tmpl.js +0 -36
- package/tests/fixtures/corpus/oss-repos/express/test/support/utils.js +0 -86
- package/tests/fixtures/corpus/oss-repos/express/test/utils.js +0 -83
- package/tests/fixtures/corpus/oss-repos/hono/.devcontainer/Dockerfile +0 -11
- package/tests/fixtures/corpus/oss-repos/hono/.devcontainer/devcontainer.json +0 -21
- package/tests/fixtures/corpus/oss-repos/hono/.devcontainer/docker-compose.yml +0 -18
- package/tests/fixtures/corpus/oss-repos/hono/.eslintignore +0 -1
- package/tests/fixtures/corpus/oss-repos/hono/.eslintrc.cjs +0 -9
- package/tests/fixtures/corpus/oss-repos/hono/.gitpod.yml +0 -9
- package/tests/fixtures/corpus/oss-repos/hono/.prettierrc +0 -9
- package/tests/fixtures/corpus/oss-repos/hono/.vitest.config/jsx-runtime-default.ts +0 -15
- package/tests/fixtures/corpus/oss-repos/hono/.vitest.config/jsx-runtime-dom.ts +0 -15
- package/tests/fixtures/corpus/oss-repos/hono/.vitest.config/setup-vitest.ts +0 -47
- package/tests/fixtures/corpus/oss-repos/hono/LICENSE +0 -21
- package/tests/fixtures/corpus/oss-repos/hono/README.md +0 -91
- package/tests/fixtures/corpus/oss-repos/hono/build.ts +0 -80
- package/tests/fixtures/corpus/oss-repos/hono/bun.lockb +0 -0
- package/tests/fixtures/corpus/oss-repos/hono/bunfig.toml +0 -7
- package/tests/fixtures/corpus/oss-repos/hono/codecov.yml +0 -13
- package/tests/fixtures/corpus/oss-repos/hono/docs/CODE_OF_CONDUCT.md +0 -128
- package/tests/fixtures/corpus/oss-repos/hono/docs/CONTRIBUTING.md +0 -62
- package/tests/fixtures/corpus/oss-repos/hono/docs/MIGRATION.md +0 -295
- package/tests/fixtures/corpus/oss-repos/hono/docs/images/hono-logo.png +0 -0
- package/tests/fixtures/corpus/oss-repos/hono/docs/images/hono-logo.pxm +0 -0
- package/tests/fixtures/corpus/oss-repos/hono/docs/images/hono-logo.svg +0 -6
- package/tests/fixtures/corpus/oss-repos/hono/docs/images/hono-title.png +0 -0
- package/tests/fixtures/corpus/oss-repos/hono/docs/images/hono-title.pxm +0 -0
- package/tests/fixtures/corpus/oss-repos/hono/jsr.json +0 -119
- package/tests/fixtures/corpus/oss-repos/hono/package.cjs.json +0 -3
- package/tests/fixtures/corpus/oss-repos/hono/package.json +0 -650
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/aws-lambda/handler.ts +0 -492
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/aws-lambda/index.ts +0 -13
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/aws-lambda/types.ts +0 -144
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/bun/conninfo.ts +0 -28
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/bun/index.ts +0 -9
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/bun/serve-static.ts +0 -35
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/bun/server.ts +0 -30
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/bun/ssg.ts +0 -27
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/bun/websocket.ts +0 -110
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-pages/handler.ts +0 -120
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-pages/index.ts +0 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-workers/conninfo.ts +0 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-workers/index.ts +0 -8
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-workers/serve-static-module.ts +0 -12
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-workers/serve-static.ts +0 -39
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-workers/utils.ts +0 -50
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-workers/websocket.ts +0 -50
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/deno/conninfo.ts +0 -17
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/deno/deno.d.ts +0 -28
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/deno/index.ts +0 -9
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/deno/serve-static.ts +0 -40
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/deno/ssg.ts +0 -27
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/deno/websocket.ts +0 -51
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/lambda-edge/conninfo.ts +0 -15
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/lambda-edge/handler.ts +0 -189
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/lambda-edge/index.ts +0 -14
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/netlify/handler.ts +0 -10
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/netlify/index.ts +0 -6
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/netlify/mod.ts +0 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/service-worker/handler.ts +0 -34
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/service-worker/index.ts +0 -5
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/service-worker/types.ts +0 -14
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/vercel/conninfo.ts +0 -8
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/vercel/handler.ts +0 -9
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/vercel/index.ts +0 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/client/client.ts +0 -214
- package/tests/fixtures/corpus/oss-repos/hono/src/client/index.ts +0 -14
- package/tests/fixtures/corpus/oss-repos/hono/src/client/types.ts +0 -182
- package/tests/fixtures/corpus/oss-repos/hono/src/client/utils.ts +0 -54
- package/tests/fixtures/corpus/oss-repos/hono/src/compose.ts +0 -94
- package/tests/fixtures/corpus/oss-repos/hono/src/context.ts +0 -917
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/accepts/accepts.ts +0 -84
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/accepts/index.ts +0 -6
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/adapter/index.ts +0 -85
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/conninfo/index.ts +0 -6
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/conninfo/types.ts +0 -45
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/cookie/index.ts +0 -130
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/css/common.ts +0 -243
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/css/index.ts +0 -220
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/dev/index.ts +0 -79
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/factory/index.ts +0 -246
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/html/index.ts +0 -56
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/ssg/index.ts +0 -13
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/ssg/middleware.ts +0 -79
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/ssg/ssg.ts +0 -388
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/ssg/utils.ts +0 -71
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/streaming/index.ts +0 -9
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/streaming/sse.ts +0 -89
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/streaming/stream.ts +0 -36
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/streaming/text.ts +0 -15
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/testing/index.ts +0 -26
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/websocket/index.ts +0 -57
- package/tests/fixtures/corpus/oss-repos/hono/src/hono-base.ts +0 -523
- package/tests/fixtures/corpus/oss-repos/hono/src/hono.ts +0 -34
- package/tests/fixtures/corpus/oss-repos/hono/src/http-exception.ts +0 -78
- package/tests/fixtures/corpus/oss-repos/hono/src/index.ts +0 -51
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/base.ts +0 -419
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/children.ts +0 -20
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/components.ts +0 -195
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/constants.ts +0 -5
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/context.ts +0 -50
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/client.ts +0 -89
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/components.ts +0 -39
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/context.ts +0 -52
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/css.ts +0 -246
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/hooks/index.ts +0 -91
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/index.ts +0 -159
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/intrinsic-element/components.ts +0 -398
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/jsx-dev-runtime.ts +0 -22
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/jsx-runtime.ts +0 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/render.ts +0 -772
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/server.ts +0 -70
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/utils.ts +0 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/hooks/index.ts +0 -426
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/index.ts +0 -114
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/intrinsic-element/common.ts +0 -11
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/intrinsic-element/components.ts +0 -196
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/intrinsic-elements.ts +0 -924
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/jsx-dev-runtime.ts +0 -26
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/jsx-runtime.ts +0 -18
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/streaming.ts +0 -184
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/types.ts +0 -41
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/utils.ts +0 -36
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/basic-auth/index.ts +0 -128
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/bearer-auth/index.ts +0 -159
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/body-limit/index.ts +0 -115
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/cache/index.ts +0 -127
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/combine/index.ts +0 -153
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/compress/index.ts +0 -79
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/context-storage/index.ts +0 -55
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/cors/index.ts +0 -141
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/csrf/index.ts +0 -90
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/etag/index.ts +0 -88
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/ip-restriction/index.ts +0 -178
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/jsx-renderer/index.ts +0 -158
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/jwt/index.ts +0 -8
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/jwt/jwt.ts +0 -159
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/logger/index.ts +0 -93
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/method-override/index.ts +0 -146
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/powered-by/index.ts +0 -13
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/pretty-json/index.ts +0 -50
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/request-id/index.ts +0 -8
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/request-id/request-id.ts +0 -59
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/secure-headers/index.ts +0 -8
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/secure-headers/permissions-policy.ts +0 -86
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/secure-headers/secure-headers.ts +0 -319
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/serve-static/index.ts +0 -140
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/timeout/index.ts +0 -58
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/timing/index.ts +0 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/timing/timing.ts +0 -225
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/trailing-slash/index.ts +0 -71
- package/tests/fixtures/corpus/oss-repos/hono/src/preset/quick.ts +0 -24
- package/tests/fixtures/corpus/oss-repos/hono/src/preset/tiny.ts +0 -20
- package/tests/fixtures/corpus/oss-repos/hono/src/request.ts +0 -403
- package/tests/fixtures/corpus/oss-repos/hono/src/router/linear-router/index.ts +0 -6
- package/tests/fixtures/corpus/oss-repos/hono/src/router/linear-router/router.ts +0 -132
- package/tests/fixtures/corpus/oss-repos/hono/src/router/pattern-router/index.ts +0 -6
- package/tests/fixtures/corpus/oss-repos/hono/src/router/pattern-router/router.ts +0 -54
- package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/index.ts +0 -6
- package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/node.ts +0 -159
- package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/router.ts +0 -274
- package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/trie.ts +0 -74
- package/tests/fixtures/corpus/oss-repos/hono/src/router/smart-router/index.ts +0 -6
- package/tests/fixtures/corpus/oss-repos/hono/src/router/smart-router/router.ts +0 -69
- package/tests/fixtures/corpus/oss-repos/hono/src/router/trie-router/index.ts +0 -6
- package/tests/fixtures/corpus/oss-repos/hono/src/router/trie-router/node.ts +0 -205
- package/tests/fixtures/corpus/oss-repos/hono/src/router/trie-router/router.ts +0 -28
- package/tests/fixtures/corpus/oss-repos/hono/src/router.ts +0 -103
- package/tests/fixtures/corpus/oss-repos/hono/src/types.ts +0 -2006
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/basic-auth.ts +0 -26
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/body.ts +0 -225
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/buffer.ts +0 -65
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/color.ts +0 -26
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/concurrent.ts +0 -55
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/cookie.ts +0 -230
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/crypto.ts +0 -65
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/encode.ts +0 -34
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/filepath.ts +0 -56
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/handler.ts +0 -15
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/html.ts +0 -182
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/http-status.ts +0 -69
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/ipaddr.ts +0 -113
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/jwt/index.ts +0 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/jwt/jwa.ts +0 -23
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/jwt/jws.ts +0 -226
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/jwt/jwt.ts +0 -114
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/jwt/types.ts +0 -83
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/jwt/utf8.ts +0 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/mime.ts +0 -142
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/stream.ts +0 -96
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/types.ts +0 -102
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/url.ts +0 -310
- package/tests/fixtures/corpus/oss-repos/hono/src/validator/index.ts +0 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/validator/validator.ts +0 -151
- package/tests/fixtures/corpus/oss-repos/hono/tsconfig.build.json +0 -23
- package/tests/fixtures/corpus/oss-repos/hono/tsconfig.json +0 -28
- package/tests/fixtures/corpus/oss-repos/hono/vitest.config.ts +0 -34
- package/tests/fixtures/corpus/oss-repos/hono/yarn.lock +0 -6232
- package/tests/fixtures/documentation/api-reference.md +0 -412
- package/tests/fixtures/documentation/architecture.md +0 -214
- package/tests/fixtures/documentation/deployment-guide.md +0 -420
- package/tests/fixtures/github-readmes/express.md +0 -133
- package/tests/fixtures/github-readmes/nextjs.md +0 -106
- package/tests/fixtures/github-readmes/react.md +0 -74
- package/tests/fixtures/github-readmes/typescript.md +0 -93
- package/tests/fixtures/github-readmes/vite.md +0 -79
- package/tests/fixtures/queries/core.json +0 -125
- package/tests/fixtures/queries/extended.json +0 -427
- package/tests/fixtures/queries/generated/.gitkeep +0 -0
- package/tests/fixtures/test-server.ts +0 -268
- package/tests/helpers/performance-metrics.ts +0 -370
- package/tests/helpers/search-relevance.ts +0 -326
- package/tests/integration/cli-consistency.test.ts +0 -298
- package/tests/integration/cli.test.ts +0 -69
- package/tests/integration/e2e-workflow.test.ts +0 -614
- package/tests/integration/mcp.test.ts +0 -250
- package/tests/integration/python-bridge.test.ts +0 -193
- package/tests/integration/search-quality.test.ts +0 -720
- package/tests/integration/serve.test.ts +0 -260
- package/tests/integration/stress.test.ts +0 -326
- package/tests/mcp/server.test.ts +0 -15
- package/tests/scripts/schemas/evaluation.json +0 -44
- package/tests/scripts/schemas/query-generation.json +0 -21
- package/tests/services/code-unit.service.test.ts +0 -95
- package/tests/services/job.service.test.ts +0 -124
- package/tests/services/search.progressive-context.test.ts +0 -35
- package/tsconfig.json +0 -34
- package/tsup.config.ts +0 -15
- package/turndown-plugin-gfm.d.ts +0 -29
- package/vitest.config.ts +0 -90
|
@@ -1,1028 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Comprehensive tests for IntelligentCrawler
|
|
3
|
-
* Coverage: mode selection, network errors, loop prevention, memory, events, stop, limits, domain filtering
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
7
|
-
import { IntelligentCrawler } from './intelligent-crawler.js';
|
|
8
|
-
import type { CrawlProgress } from './intelligent-crawler.js';
|
|
9
|
-
import axios from 'axios';
|
|
10
|
-
import * as articleConverter from './article-converter.js';
|
|
11
|
-
|
|
12
|
-
// Mock dependencies
|
|
13
|
-
vi.mock('axios');
|
|
14
|
-
vi.mock('./claude-client.js');
|
|
15
|
-
vi.mock('./bridge.js');
|
|
16
|
-
vi.mock('./article-converter.js');
|
|
17
|
-
|
|
18
|
-
// Import mocked classes after mocking
|
|
19
|
-
const { ClaudeClient } = await import('./claude-client.js');
|
|
20
|
-
const { PythonBridge } = await import('./bridge.js');
|
|
21
|
-
|
|
22
|
-
describe('IntelligentCrawler', () => {
|
|
23
|
-
let crawler: IntelligentCrawler;
|
|
24
|
-
let mockClaudeClient: any;
|
|
25
|
-
let mockPythonBridge: any;
|
|
26
|
-
let progressEvents: CrawlProgress[];
|
|
27
|
-
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
// Reset all mocks
|
|
30
|
-
vi.clearAllMocks();
|
|
31
|
-
progressEvents = [];
|
|
32
|
-
|
|
33
|
-
// Setup ClaudeClient mock - ensure isAvailable returns true for intelligent mode tests
|
|
34
|
-
mockClaudeClient = {
|
|
35
|
-
determineCrawlUrls: vi.fn(),
|
|
36
|
-
extractContent: vi.fn(),
|
|
37
|
-
};
|
|
38
|
-
vi.mocked(ClaudeClient).mockImplementation(function () {
|
|
39
|
-
return mockClaudeClient;
|
|
40
|
-
});
|
|
41
|
-
// Mock static isAvailable to return true (Claude CLI is available in tests)
|
|
42
|
-
vi.mocked(ClaudeClient.isAvailable).mockReturnValue(true);
|
|
43
|
-
|
|
44
|
-
// Setup PythonBridge mock
|
|
45
|
-
mockPythonBridge = {
|
|
46
|
-
crawl: vi.fn(),
|
|
47
|
-
fetchHeadless: vi.fn(),
|
|
48
|
-
stop: vi.fn().mockResolvedValue(undefined),
|
|
49
|
-
};
|
|
50
|
-
vi.mocked(PythonBridge).mockImplementation(function () {
|
|
51
|
-
return mockPythonBridge;
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Setup axios mock
|
|
55
|
-
vi.mocked(axios.get).mockResolvedValue({
|
|
56
|
-
data: '<html><body><h1>Test</h1><a href="https://example.com/page1">Link</a></body></html>',
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Setup convertHtmlToMarkdown mock
|
|
60
|
-
vi.mocked(articleConverter.convertHtmlToMarkdown).mockResolvedValue({
|
|
61
|
-
markdown: '# Test\n\nContent',
|
|
62
|
-
title: 'Test Page',
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// Create crawler instance
|
|
66
|
-
crawler = new IntelligentCrawler();
|
|
67
|
-
|
|
68
|
-
// Listen to progress events
|
|
69
|
-
crawler.on('progress', (progress: CrawlProgress) => {
|
|
70
|
-
progressEvents.push(progress);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
afterEach(async () => {
|
|
75
|
-
await crawler.stop();
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe('Mode Selection', () => {
|
|
79
|
-
it('should use intelligent mode when crawlInstruction is provided', async () => {
|
|
80
|
-
mockClaudeClient.determineCrawlUrls.mockResolvedValue({
|
|
81
|
-
urls: ['https://example.com/page1'],
|
|
82
|
-
reasoning: 'Found relevant page',
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const results = [];
|
|
86
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
87
|
-
crawlInstruction: 'Find all docs',
|
|
88
|
-
})) {
|
|
89
|
-
results.push(result);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
expect(mockClaudeClient.determineCrawlUrls).toHaveBeenCalledOnce();
|
|
93
|
-
expect(results).toHaveLength(1);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('should use simple mode when crawlInstruction is empty string', async () => {
|
|
97
|
-
mockPythonBridge.crawl.mockResolvedValue({
|
|
98
|
-
pages: [{ links: [] }],
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const results = [];
|
|
102
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
103
|
-
crawlInstruction: '',
|
|
104
|
-
})) {
|
|
105
|
-
results.push(result);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
expect(mockClaudeClient.determineCrawlUrls).not.toHaveBeenCalled();
|
|
109
|
-
expect(results).toHaveLength(1);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it('should use simple mode when crawlInstruction is undefined', async () => {
|
|
113
|
-
mockPythonBridge.crawl.mockResolvedValue({
|
|
114
|
-
pages: [{ links: [] }],
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
const results = [];
|
|
118
|
-
for await (const result of crawler.crawl('https://example.com', {})) {
|
|
119
|
-
results.push(result);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
expect(mockClaudeClient.determineCrawlUrls).not.toHaveBeenCalled();
|
|
123
|
-
expect(results).toHaveLength(1);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('should force simple mode when simple option is true', async () => {
|
|
127
|
-
mockPythonBridge.crawl.mockResolvedValue({
|
|
128
|
-
pages: [{ links: [] }],
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
const results = [];
|
|
132
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
133
|
-
crawlInstruction: 'Find all docs',
|
|
134
|
-
simple: true,
|
|
135
|
-
})) {
|
|
136
|
-
results.push(result);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
expect(mockClaudeClient.determineCrawlUrls).not.toHaveBeenCalled();
|
|
140
|
-
expect(results).toHaveLength(1);
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
describe('Network Error Handling', () => {
|
|
145
|
-
it('should handle timeout errors gracefully', async () => {
|
|
146
|
-
vi.mocked(axios.get).mockRejectedValueOnce({
|
|
147
|
-
code: 'ETIMEDOUT',
|
|
148
|
-
message: 'timeout of 30000ms exceeded',
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
const results = [];
|
|
152
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
153
|
-
results.push(result);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Should fail to fetch and emit error but not crash
|
|
157
|
-
expect(results).toHaveLength(0);
|
|
158
|
-
const errorEvents = progressEvents.filter((e) => e.type === 'error');
|
|
159
|
-
expect(errorEvents.length).toBeGreaterThan(0);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it('should handle DNS failures', async () => {
|
|
163
|
-
vi.mocked(axios.get).mockRejectedValueOnce({
|
|
164
|
-
code: 'ENOTFOUND',
|
|
165
|
-
message: 'getaddrinfo ENOTFOUND invalid.example.com',
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
const results = [];
|
|
169
|
-
for await (const result of crawler.crawl('https://invalid.example.com', { simple: true })) {
|
|
170
|
-
results.push(result);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
expect(results).toHaveLength(0);
|
|
174
|
-
const errorEvents = progressEvents.filter((e) => e.type === 'error');
|
|
175
|
-
expect(errorEvents.length).toBeGreaterThan(0);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it('should handle 404 errors', async () => {
|
|
179
|
-
vi.mocked(axios.get).mockRejectedValueOnce({
|
|
180
|
-
response: { status: 404 },
|
|
181
|
-
message: 'Request failed with status code 404',
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
const results = [];
|
|
185
|
-
for await (const result of crawler.crawl('https://example.com/404', { simple: true })) {
|
|
186
|
-
results.push(result);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
expect(results).toHaveLength(0);
|
|
190
|
-
const errorEvents = progressEvents.filter((e) => e.type === 'error');
|
|
191
|
-
expect(errorEvents.length).toBeGreaterThan(0);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('should handle 500 errors', async () => {
|
|
195
|
-
vi.mocked(axios.get).mockRejectedValueOnce({
|
|
196
|
-
response: { status: 500 },
|
|
197
|
-
message: 'Request failed with status code 500',
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
const results = [];
|
|
201
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
202
|
-
results.push(result);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
expect(results).toHaveLength(0);
|
|
206
|
-
const errorEvents = progressEvents.filter((e) => e.type === 'error');
|
|
207
|
-
expect(errorEvents.length).toBeGreaterThan(0);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
it('should handle network connection refused', async () => {
|
|
211
|
-
vi.mocked(axios.get).mockRejectedValueOnce({
|
|
212
|
-
code: 'ECONNREFUSED',
|
|
213
|
-
message: 'connect ECONNREFUSED 127.0.0.1:80',
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
const results = [];
|
|
217
|
-
for await (const result of crawler.crawl('http://localhost', { simple: true })) {
|
|
218
|
-
results.push(result);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
expect(results).toHaveLength(0);
|
|
222
|
-
const errorEvents = progressEvents.filter((e) => e.type === 'error');
|
|
223
|
-
expect(errorEvents.length).toBeGreaterThan(0);
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
describe('Infinite Loop Prevention', () => {
|
|
228
|
-
it('should not visit the same URL twice in simple mode', async () => {
|
|
229
|
-
const circular = 'https://example.com/page1';
|
|
230
|
-
mockPythonBridge.crawl.mockResolvedValue({
|
|
231
|
-
pages: [{ links: [circular] }], // Link back to itself
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
vi.mocked(axios.get).mockResolvedValueOnce({
|
|
235
|
-
data: `<html><body><a href="${circular}">Self</a></body></html>`,
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
const results = [];
|
|
239
|
-
for await (const result of crawler.crawl(circular, { simple: true, maxPages: 10 })) {
|
|
240
|
-
results.push(result);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Should only crawl once despite circular link
|
|
244
|
-
expect(results).toHaveLength(1);
|
|
245
|
-
expect(vi.mocked(axios.get)).toHaveBeenCalledTimes(1);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
it('should not visit the same URL twice in intelligent mode', async () => {
|
|
249
|
-
const duplicate = 'https://example.com/page1';
|
|
250
|
-
mockClaudeClient.determineCrawlUrls.mockResolvedValue({
|
|
251
|
-
urls: [duplicate, duplicate, duplicate], // Same URL repeated
|
|
252
|
-
reasoning: 'Found duplicate URLs',
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
const results = [];
|
|
256
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
257
|
-
crawlInstruction: 'Find all',
|
|
258
|
-
maxPages: 10,
|
|
259
|
-
})) {
|
|
260
|
-
results.push(result);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// Should only crawl the URL once
|
|
264
|
-
expect(results).toHaveLength(1);
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('should handle circular references across multiple pages', async () => {
|
|
268
|
-
const page1 = 'https://example.com/page1';
|
|
269
|
-
const page2 = 'https://example.com/page2';
|
|
270
|
-
|
|
271
|
-
mockPythonBridge.crawl
|
|
272
|
-
.mockResolvedValueOnce({ pages: [{ links: [page2] }] }) // page1 -> page2
|
|
273
|
-
.mockResolvedValueOnce({ pages: [{ links: [page1] }] }); // page2 -> page1
|
|
274
|
-
|
|
275
|
-
vi.mocked(axios.get)
|
|
276
|
-
.mockResolvedValueOnce({ data: `<html><body><a href="${page2}">Next</a></body></html>` })
|
|
277
|
-
.mockResolvedValueOnce({ data: `<html><body><a href="${page1}">Back</a></body></html>` });
|
|
278
|
-
|
|
279
|
-
const results = [];
|
|
280
|
-
for await (const result of crawler.crawl(page1, { simple: true, maxPages: 10 })) {
|
|
281
|
-
results.push(result);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Should crawl both pages once, not infinitely
|
|
285
|
-
expect(results).toHaveLength(2);
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
describe('Memory Management', () => {
|
|
290
|
-
it('should track visited URLs in a Set', async () => {
|
|
291
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
292
|
-
|
|
293
|
-
const results = [];
|
|
294
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
295
|
-
results.push(result);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
expect(results).toHaveLength(1);
|
|
299
|
-
// Verify visited set is working by attempting to crawl again
|
|
300
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
301
|
-
results.push(result);
|
|
302
|
-
}
|
|
303
|
-
// Second crawl should also work (visited set cleared)
|
|
304
|
-
expect(results).toHaveLength(2);
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
it('should clear visited set on new crawl', async () => {
|
|
308
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
309
|
-
|
|
310
|
-
// First crawl
|
|
311
|
-
const results1 = [];
|
|
312
|
-
for await (const result of crawler.crawl('https://example.com/a', { simple: true })) {
|
|
313
|
-
results1.push(result);
|
|
314
|
-
}
|
|
315
|
-
expect(results1).toHaveLength(1);
|
|
316
|
-
|
|
317
|
-
// Second crawl with same URL should work (set was cleared)
|
|
318
|
-
const results2 = [];
|
|
319
|
-
for await (const result of crawler.crawl('https://example.com/a', { simple: true })) {
|
|
320
|
-
results2.push(result);
|
|
321
|
-
}
|
|
322
|
-
expect(results2).toHaveLength(1);
|
|
323
|
-
});
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
describe('Event Emission', () => {
|
|
327
|
-
it('should emit start event', async () => {
|
|
328
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
329
|
-
|
|
330
|
-
const results = [];
|
|
331
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
332
|
-
simple: true,
|
|
333
|
-
maxPages: 10,
|
|
334
|
-
})) {
|
|
335
|
-
results.push(result);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
const startEvents = progressEvents.filter((e) => e.type === 'start');
|
|
339
|
-
expect(startEvents).toHaveLength(1);
|
|
340
|
-
expect(startEvents[0]?.pagesVisited).toBe(0);
|
|
341
|
-
expect(startEvents[0]?.totalPages).toBe(10);
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
it('should emit page events', async () => {
|
|
345
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
346
|
-
|
|
347
|
-
const results = [];
|
|
348
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
349
|
-
results.push(result);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const pageEvents = progressEvents.filter((e) => e.type === 'page');
|
|
353
|
-
expect(pageEvents.length).toBeGreaterThan(0);
|
|
354
|
-
expect(pageEvents[0]?.currentUrl).toBe('https://example.com');
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
it('should emit complete event', async () => {
|
|
358
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
359
|
-
|
|
360
|
-
const results = [];
|
|
361
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
362
|
-
results.push(result);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
const completeEvents = progressEvents.filter((e) => e.type === 'complete');
|
|
366
|
-
expect(completeEvents).toHaveLength(1);
|
|
367
|
-
expect(completeEvents[0]?.pagesVisited).toBe(1);
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
it('should emit strategy events in intelligent mode', async () => {
|
|
371
|
-
mockClaudeClient.determineCrawlUrls.mockResolvedValue({
|
|
372
|
-
urls: ['https://example.com/page1'],
|
|
373
|
-
reasoning: 'Strategy reasoning',
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
const results = [];
|
|
377
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
378
|
-
crawlInstruction: 'Find all',
|
|
379
|
-
})) {
|
|
380
|
-
results.push(result);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
const strategyEvents = progressEvents.filter((e) => e.type === 'strategy');
|
|
384
|
-
expect(strategyEvents.length).toBeGreaterThanOrEqual(1);
|
|
385
|
-
expect(strategyEvents.some((e) => e.message?.includes('Strategy reasoning'))).toBe(true);
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
it('should emit extraction events when extract instruction provided', async () => {
|
|
389
|
-
mockClaudeClient.extractContent.mockResolvedValue('Extracted content');
|
|
390
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
391
|
-
|
|
392
|
-
const results = [];
|
|
393
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
394
|
-
simple: true,
|
|
395
|
-
extractInstruction: 'Extract pricing',
|
|
396
|
-
})) {
|
|
397
|
-
results.push(result);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
const extractionEvents = progressEvents.filter((e) => e.type === 'extraction');
|
|
401
|
-
expect(extractionEvents.length).toBeGreaterThan(0);
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
it('should emit error events on page fetch failures', async () => {
|
|
405
|
-
vi.mocked(axios.get).mockRejectedValueOnce(new Error('Network error'));
|
|
406
|
-
|
|
407
|
-
const results = [];
|
|
408
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
409
|
-
results.push(result);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
const errorEvents = progressEvents.filter((e) => e.type === 'error');
|
|
413
|
-
expect(errorEvents.length).toBeGreaterThan(0);
|
|
414
|
-
expect(errorEvents[0]?.error).toBeDefined();
|
|
415
|
-
});
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
describe('Stop Functionality', () => {
|
|
419
|
-
it('should stop crawling when stop is called', async () => {
|
|
420
|
-
mockPythonBridge.crawl.mockImplementation(async () => {
|
|
421
|
-
// Simulate slow crawl
|
|
422
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
423
|
-
return { pages: [{ links: ['https://example.com/next'] }] };
|
|
424
|
-
});
|
|
425
|
-
|
|
426
|
-
const results = [];
|
|
427
|
-
const crawlPromise = (async () => {
|
|
428
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
429
|
-
simple: true,
|
|
430
|
-
maxPages: 100,
|
|
431
|
-
})) {
|
|
432
|
-
results.push(result);
|
|
433
|
-
}
|
|
434
|
-
})();
|
|
435
|
-
|
|
436
|
-
// Stop after a short delay
|
|
437
|
-
setTimeout(() => crawler.stop(), 50);
|
|
438
|
-
|
|
439
|
-
await crawlPromise;
|
|
440
|
-
|
|
441
|
-
// Should have stopped early
|
|
442
|
-
expect(results.length).toBeLessThan(100);
|
|
443
|
-
expect(mockPythonBridge.stop).toHaveBeenCalled();
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
it('should reset stopped flag on new crawl', async () => {
|
|
447
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
448
|
-
|
|
449
|
-
// First crawl with stop
|
|
450
|
-
await crawler.stop();
|
|
451
|
-
|
|
452
|
-
// Second crawl should work
|
|
453
|
-
const results = [];
|
|
454
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
455
|
-
results.push(result);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
expect(results).toHaveLength(1);
|
|
459
|
-
});
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
describe('Max Pages Enforcement', () => {
|
|
463
|
-
it('should respect maxPages limit in simple mode', async () => {
|
|
464
|
-
const links = Array.from({ length: 20 }, (_, i) => `https://example.com/page${i}`);
|
|
465
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links }] });
|
|
466
|
-
|
|
467
|
-
const results = [];
|
|
468
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
469
|
-
simple: true,
|
|
470
|
-
maxPages: 3,
|
|
471
|
-
})) {
|
|
472
|
-
results.push(result);
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
expect(results.length).toBeLessThanOrEqual(3);
|
|
476
|
-
});
|
|
477
|
-
|
|
478
|
-
it('should respect maxPages limit in intelligent mode', async () => {
|
|
479
|
-
const urls = Array.from({ length: 20 }, (_, i) => `https://example.com/page${i}`);
|
|
480
|
-
mockClaudeClient.determineCrawlUrls.mockResolvedValue({
|
|
481
|
-
urls,
|
|
482
|
-
reasoning: 'Found many pages',
|
|
483
|
-
});
|
|
484
|
-
|
|
485
|
-
const results = [];
|
|
486
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
487
|
-
crawlInstruction: 'Find all',
|
|
488
|
-
maxPages: 5,
|
|
489
|
-
})) {
|
|
490
|
-
results.push(result);
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
expect(results.length).toBeLessThanOrEqual(5);
|
|
494
|
-
});
|
|
495
|
-
|
|
496
|
-
it('should use default maxPages of 50', async () => {
|
|
497
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
498
|
-
|
|
499
|
-
const results = [];
|
|
500
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
501
|
-
results.push(result);
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
const startEvent = progressEvents.find((e) => e.type === 'start');
|
|
505
|
-
expect(startEvent?.totalPages).toBe(50);
|
|
506
|
-
});
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
describe('Same-Domain Filtering Logic', () => {
|
|
510
|
-
it('should filter out different domain links in simple mode', async () => {
|
|
511
|
-
mockPythonBridge.crawl
|
|
512
|
-
.mockResolvedValueOnce({
|
|
513
|
-
pages: [
|
|
514
|
-
{
|
|
515
|
-
links: [
|
|
516
|
-
'https://example.com/page1', // Same domain
|
|
517
|
-
'https://other.com/page2', // Different domain
|
|
518
|
-
],
|
|
519
|
-
},
|
|
520
|
-
],
|
|
521
|
-
})
|
|
522
|
-
.mockResolvedValueOnce({ pages: [{ links: [] }] });
|
|
523
|
-
|
|
524
|
-
vi.mocked(axios.get)
|
|
525
|
-
.mockResolvedValueOnce({ data: '<html><body>Seed</body></html>' })
|
|
526
|
-
.mockResolvedValueOnce({ data: '<html><body>Page1</body></html>' });
|
|
527
|
-
|
|
528
|
-
const results = [];
|
|
529
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
530
|
-
simple: true,
|
|
531
|
-
maxPages: 10,
|
|
532
|
-
})) {
|
|
533
|
-
results.push(result);
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// Should only crawl same-domain link
|
|
537
|
-
expect(results).toHaveLength(2); // Seed + page1
|
|
538
|
-
expect(results.some((r) => r.url.includes('other.com'))).toBe(false);
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
it('should allow subdomain links', async () => {
|
|
542
|
-
mockPythonBridge.crawl
|
|
543
|
-
.mockResolvedValueOnce({
|
|
544
|
-
pages: [{ links: ['https://docs.example.com/page1'] }],
|
|
545
|
-
})
|
|
546
|
-
.mockResolvedValueOnce({ pages: [{ links: [] }] });
|
|
547
|
-
|
|
548
|
-
vi.mocked(axios.get)
|
|
549
|
-
.mockResolvedValueOnce({ data: '<html><body>Seed</body></html>' })
|
|
550
|
-
.mockResolvedValueOnce({ data: '<html><body>Page1</body></html>' });
|
|
551
|
-
|
|
552
|
-
const results = [];
|
|
553
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
554
|
-
simple: true,
|
|
555
|
-
maxPages: 10,
|
|
556
|
-
})) {
|
|
557
|
-
results.push(result);
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
expect(results).toHaveLength(2);
|
|
561
|
-
expect(results.some((r) => r.url.includes('docs.example.com'))).toBe(true);
|
|
562
|
-
});
|
|
563
|
-
|
|
564
|
-
it('should handle invalid URLs in link extraction', async () => {
|
|
565
|
-
mockPythonBridge.crawl.mockResolvedValue({
|
|
566
|
-
pages: [
|
|
567
|
-
{
|
|
568
|
-
links: ['not-a-valid-url', 'javascript:void(0)', 'mailto:test@example.com'],
|
|
569
|
-
},
|
|
570
|
-
],
|
|
571
|
-
});
|
|
572
|
-
|
|
573
|
-
const results = [];
|
|
574
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
575
|
-
results.push(result);
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
// Should only crawl the seed URL
|
|
579
|
-
expect(results).toHaveLength(1);
|
|
580
|
-
});
|
|
581
|
-
});
|
|
582
|
-
|
|
583
|
-
describe('Intelligent Mode Error Handling', () => {
|
|
584
|
-
it('should throw when Claude strategy fails', async () => {
|
|
585
|
-
mockClaudeClient.determineCrawlUrls.mockRejectedValue(new Error('Claude API error'));
|
|
586
|
-
|
|
587
|
-
const results = [];
|
|
588
|
-
await expect(async () => {
|
|
589
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
590
|
-
crawlInstruction: 'Find all docs',
|
|
591
|
-
})) {
|
|
592
|
-
results.push(result);
|
|
593
|
-
}
|
|
594
|
-
}).rejects.toThrow('Claude API error');
|
|
595
|
-
|
|
596
|
-
expect(results).toHaveLength(0);
|
|
597
|
-
});
|
|
598
|
-
});
|
|
599
|
-
|
|
600
|
-
describe('Content Extraction', () => {
|
|
601
|
-
it('should extract content when extractInstruction provided', async () => {
|
|
602
|
-
mockClaudeClient.extractContent.mockResolvedValue('Extracted pricing info');
|
|
603
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
604
|
-
|
|
605
|
-
const results = [];
|
|
606
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
607
|
-
simple: true,
|
|
608
|
-
extractInstruction: 'Extract pricing',
|
|
609
|
-
})) {
|
|
610
|
-
results.push(result);
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
expect(results).toHaveLength(1);
|
|
614
|
-
expect(results[0]?.extracted).toBe('Extracted pricing info');
|
|
615
|
-
expect(mockClaudeClient.extractContent).toHaveBeenCalledWith(
|
|
616
|
-
expect.any(String),
|
|
617
|
-
'Extract pricing'
|
|
618
|
-
);
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
it('should throw when extraction fails', async () => {
|
|
622
|
-
mockClaudeClient.extractContent.mockRejectedValue(new Error('Extraction failed'));
|
|
623
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
624
|
-
|
|
625
|
-
const results = [];
|
|
626
|
-
await expect(async () => {
|
|
627
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
628
|
-
simple: true,
|
|
629
|
-
extractInstruction: 'Extract pricing',
|
|
630
|
-
})) {
|
|
631
|
-
results.push(result);
|
|
632
|
-
}
|
|
633
|
-
}).rejects.toThrow('Extraction failed');
|
|
634
|
-
|
|
635
|
-
expect(results).toHaveLength(0);
|
|
636
|
-
});
|
|
637
|
-
|
|
638
|
-
it('should not extract when extractInstruction is empty', async () => {
|
|
639
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
640
|
-
|
|
641
|
-
const results = [];
|
|
642
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
643
|
-
simple: true,
|
|
644
|
-
extractInstruction: '',
|
|
645
|
-
})) {
|
|
646
|
-
results.push(result);
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
expect(results).toHaveLength(1);
|
|
650
|
-
expect(results[0]?.extracted).toBeUndefined();
|
|
651
|
-
expect(mockClaudeClient.extractContent).not.toHaveBeenCalled();
|
|
652
|
-
});
|
|
653
|
-
});
|
|
654
|
-
|
|
655
|
-
describe('Link Extraction Error Handling', () => {
|
|
656
|
-
it('should throw error when Python bridge fails', async () => {
|
|
657
|
-
mockPythonBridge.crawl.mockRejectedValue(new Error('Network timeout'));
|
|
658
|
-
|
|
659
|
-
const crawler = new IntelligentCrawler();
|
|
660
|
-
// Access private property for testing
|
|
661
|
-
(crawler as any).pythonBridge = mockPythonBridge;
|
|
662
|
-
|
|
663
|
-
await expect((crawler as any).extractLinks('https://example.com')).rejects.toThrow(
|
|
664
|
-
'Link extraction failed'
|
|
665
|
-
);
|
|
666
|
-
});
|
|
667
|
-
|
|
668
|
-
it('should throw error on invalid response structure', async () => {
|
|
669
|
-
// Return a response without pages array
|
|
670
|
-
mockPythonBridge.crawl.mockResolvedValue({ invalid: 'structure' });
|
|
671
|
-
|
|
672
|
-
const crawler = new IntelligentCrawler();
|
|
673
|
-
(crawler as any).pythonBridge = mockPythonBridge;
|
|
674
|
-
|
|
675
|
-
await expect((crawler as any).extractLinks('https://example.com')).rejects.toThrow(
|
|
676
|
-
'Invalid crawl response structure'
|
|
677
|
-
);
|
|
678
|
-
});
|
|
679
|
-
|
|
680
|
-
it('should throw error when pages array is empty', async () => {
|
|
681
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [] });
|
|
682
|
-
|
|
683
|
-
const crawler = new IntelligentCrawler();
|
|
684
|
-
(crawler as any).pythonBridge = mockPythonBridge;
|
|
685
|
-
|
|
686
|
-
await expect((crawler as any).extractLinks('https://example.com')).rejects.toThrow(
|
|
687
|
-
'Invalid crawl response structure'
|
|
688
|
-
);
|
|
689
|
-
});
|
|
690
|
-
|
|
691
|
-
it('should use headless mode for link extraction when enabled', async () => {
|
|
692
|
-
const headlessResult = {
|
|
693
|
-
html: '<html/>',
|
|
694
|
-
markdown: 'test',
|
|
695
|
-
links: ['https://example.com/page2', 'https://example.com/page3'],
|
|
696
|
-
};
|
|
697
|
-
mockPythonBridge.fetchHeadless.mockResolvedValue(headlessResult);
|
|
698
|
-
|
|
699
|
-
const crawler = new IntelligentCrawler();
|
|
700
|
-
(crawler as any).pythonBridge = mockPythonBridge;
|
|
701
|
-
|
|
702
|
-
const links = await (crawler as any).extractLinks('https://example.com', true);
|
|
703
|
-
|
|
704
|
-
expect(mockPythonBridge.fetchHeadless).toHaveBeenCalledWith('https://example.com');
|
|
705
|
-
expect(mockPythonBridge.crawl).not.toHaveBeenCalled();
|
|
706
|
-
expect(links).toEqual(['https://example.com/page2', 'https://example.com/page3']);
|
|
707
|
-
});
|
|
708
|
-
|
|
709
|
-
it('should extract href from link objects in headless mode', async () => {
|
|
710
|
-
// crawl4ai returns link objects, not strings
|
|
711
|
-
const headlessResult = {
|
|
712
|
-
html: '<html/>',
|
|
713
|
-
markdown: 'test',
|
|
714
|
-
links: [
|
|
715
|
-
{
|
|
716
|
-
href: 'https://example.com/page1',
|
|
717
|
-
text: 'Page 1',
|
|
718
|
-
title: '',
|
|
719
|
-
base_domain: 'example.com',
|
|
720
|
-
head_data: null,
|
|
721
|
-
head_extraction_status: null,
|
|
722
|
-
head_extraction_error: null,
|
|
723
|
-
intrinsic_score: 0,
|
|
724
|
-
contextual_score: null,
|
|
725
|
-
total_score: null,
|
|
726
|
-
},
|
|
727
|
-
{
|
|
728
|
-
href: 'https://example.com/page2',
|
|
729
|
-
text: 'Page 2',
|
|
730
|
-
title: '',
|
|
731
|
-
base_domain: 'example.com',
|
|
732
|
-
head_data: null,
|
|
733
|
-
head_extraction_status: null,
|
|
734
|
-
head_extraction_error: null,
|
|
735
|
-
intrinsic_score: 0,
|
|
736
|
-
contextual_score: null,
|
|
737
|
-
total_score: null,
|
|
738
|
-
},
|
|
739
|
-
'https://example.com/page3', // Also support plain strings
|
|
740
|
-
],
|
|
741
|
-
};
|
|
742
|
-
mockPythonBridge.fetchHeadless.mockResolvedValue(headlessResult);
|
|
743
|
-
|
|
744
|
-
const crawler = new IntelligentCrawler();
|
|
745
|
-
(crawler as any).pythonBridge = mockPythonBridge;
|
|
746
|
-
|
|
747
|
-
const links = await (crawler as any).extractLinks('https://example.com', true);
|
|
748
|
-
|
|
749
|
-
expect(links).toEqual([
|
|
750
|
-
'https://example.com/page1',
|
|
751
|
-
'https://example.com/page2',
|
|
752
|
-
'https://example.com/page3',
|
|
753
|
-
]);
|
|
754
|
-
});
|
|
755
|
-
|
|
756
|
-
it('should use regular crawl when headless is disabled', async () => {
|
|
757
|
-
mockPythonBridge.crawl.mockResolvedValue({
|
|
758
|
-
pages: [{ links: ['https://example.com/page1'] }],
|
|
759
|
-
});
|
|
760
|
-
|
|
761
|
-
const crawler = new IntelligentCrawler();
|
|
762
|
-
(crawler as any).pythonBridge = mockPythonBridge;
|
|
763
|
-
|
|
764
|
-
const links = await (crawler as any).extractLinks('https://example.com', false);
|
|
765
|
-
|
|
766
|
-
expect(mockPythonBridge.crawl).toHaveBeenCalledWith('https://example.com');
|
|
767
|
-
expect(mockPythonBridge.fetchHeadless).not.toHaveBeenCalled();
|
|
768
|
-
expect(links).toEqual(['https://example.com/page1']);
|
|
769
|
-
});
|
|
770
|
-
|
|
771
|
-
it('should continue crawling other pages when link extraction fails in simple mode', async () => {
|
|
772
|
-
// First page succeeds, link extraction fails, second page succeeds
|
|
773
|
-
mockClaudeClient.determineCrawlUrls.mockResolvedValue({
|
|
774
|
-
urls: ['https://example.com/page1', 'https://example.com/page2'],
|
|
775
|
-
reasoning: 'Test URLs',
|
|
776
|
-
});
|
|
777
|
-
|
|
778
|
-
vi.mocked(axios.get)
|
|
779
|
-
.mockResolvedValueOnce({ data: '<html><body>Seed</body></html>' }) // Seed page
|
|
780
|
-
.mockResolvedValueOnce({ data: '<html><body>Page1</body></html>' }) // First URL
|
|
781
|
-
.mockResolvedValueOnce({ data: '<html><body>Page2</body></html>' }); // Second URL
|
|
782
|
-
|
|
783
|
-
// Make link extraction fail for first URL only
|
|
784
|
-
mockPythonBridge.crawl
|
|
785
|
-
.mockRejectedValueOnce(new Error('Link extraction failed'))
|
|
786
|
-
.mockResolvedValueOnce({ pages: [{ links: [] }] });
|
|
787
|
-
|
|
788
|
-
const results = [];
|
|
789
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
790
|
-
crawlInstruction: 'Find all',
|
|
791
|
-
})) {
|
|
792
|
-
results.push(result);
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
// Should successfully crawl both URLs despite link extraction failure
|
|
796
|
-
expect(results).toHaveLength(2);
|
|
797
|
-
expect(results[0]?.url).toBe('https://example.com/page1');
|
|
798
|
-
expect(results[1]?.url).toBe('https://example.com/page2');
|
|
799
|
-
});
|
|
800
|
-
});
|
|
801
|
-
|
|
802
|
-
describe('HTML to Markdown Conversion', () => {
|
|
803
|
-
it('should convert HTML to markdown for each page', async () => {
|
|
804
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
805
|
-
|
|
806
|
-
const results = [];
|
|
807
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
808
|
-
results.push(result);
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
expect(vi.mocked(articleConverter.convertHtmlToMarkdown)).toHaveBeenCalledWith(
|
|
812
|
-
expect.any(String),
|
|
813
|
-
'https://example.com'
|
|
814
|
-
);
|
|
815
|
-
expect(results[0]?.markdown).toBe('# Test\n\nContent');
|
|
816
|
-
});
|
|
817
|
-
|
|
818
|
-
it('should include title when available', async () => {
|
|
819
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
820
|
-
vi.mocked(articleConverter.convertHtmlToMarkdown).mockResolvedValue({
|
|
821
|
-
markdown: '# Test',
|
|
822
|
-
title: 'Test Page Title',
|
|
823
|
-
});
|
|
824
|
-
|
|
825
|
-
const results = [];
|
|
826
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
827
|
-
results.push(result);
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
expect(results[0]?.title).toBe('Test Page Title');
|
|
831
|
-
});
|
|
832
|
-
|
|
833
|
-
it('should handle conversion failures', async () => {
|
|
834
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
835
|
-
vi.mocked(articleConverter.convertHtmlToMarkdown).mockRejectedValue(
|
|
836
|
-
new Error('Conversion error')
|
|
837
|
-
);
|
|
838
|
-
|
|
839
|
-
const results = [];
|
|
840
|
-
for await (const result of crawler.crawl('https://example.com', { simple: true })) {
|
|
841
|
-
results.push(result);
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
// Should fail to create result
|
|
845
|
-
expect(results).toHaveLength(0);
|
|
846
|
-
const errorEvents = progressEvents.filter((e) => e.type === 'error');
|
|
847
|
-
expect(errorEvents.length).toBeGreaterThan(0);
|
|
848
|
-
});
|
|
849
|
-
});
|
|
850
|
-
|
|
851
|
-
describe('Simple Mode Depth Control', () => {
|
|
852
|
-
it('should respect depth limit of 2 in simple mode', async () => {
|
|
853
|
-
mockPythonBridge.crawl
|
|
854
|
-
.mockResolvedValueOnce({ pages: [{ links: ['https://example.com/depth1'] }] })
|
|
855
|
-
.mockResolvedValueOnce({ pages: [{ links: ['https://example.com/depth2'] }] })
|
|
856
|
-
.mockResolvedValueOnce({ pages: [{ links: ['https://example.com/depth3'] }] });
|
|
857
|
-
|
|
858
|
-
vi.mocked(axios.get).mockResolvedValue({ data: '<html><body>Test</body></html>' });
|
|
859
|
-
|
|
860
|
-
const results = [];
|
|
861
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
862
|
-
simple: true,
|
|
863
|
-
maxPages: 10,
|
|
864
|
-
})) {
|
|
865
|
-
results.push(result);
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
// Should stop at depth 2 (seed=0, depth1=1, depth2=2)
|
|
869
|
-
expect(results.length).toBeLessThanOrEqual(3);
|
|
870
|
-
expect(results.every((r) => (r.depth ?? 0) <= 2)).toBe(true);
|
|
871
|
-
});
|
|
872
|
-
});
|
|
873
|
-
|
|
874
|
-
describe('Error Recovery', () => {
|
|
875
|
-
it('should continue crawling other pages after one page fails', async () => {
|
|
876
|
-
mockClaudeClient.determineCrawlUrls.mockResolvedValue({
|
|
877
|
-
urls: ['https://example.com/fail', 'https://example.com/success'],
|
|
878
|
-
reasoning: 'Test URLs',
|
|
879
|
-
});
|
|
880
|
-
|
|
881
|
-
vi.mocked(axios.get)
|
|
882
|
-
.mockResolvedValueOnce({ data: '<html><body>Seed page</body></html>' }) // Seed URL fetch
|
|
883
|
-
.mockRejectedValueOnce(new Error('Failed to fetch')) // First URL fails
|
|
884
|
-
.mockResolvedValueOnce({ data: '<html><body>Success</body></html>' }); // Second URL succeeds
|
|
885
|
-
|
|
886
|
-
const results = [];
|
|
887
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
888
|
-
crawlInstruction: 'Find all',
|
|
889
|
-
})) {
|
|
890
|
-
results.push(result);
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
// Should successfully crawl the second URL
|
|
894
|
-
expect(results).toHaveLength(1);
|
|
895
|
-
expect(results[0]?.url).toBe('https://example.com/success');
|
|
896
|
-
});
|
|
897
|
-
});
|
|
898
|
-
|
|
899
|
-
describe('Headless Mode Error Handling', () => {
|
|
900
|
-
it('should throw when headless fetch fails', async () => {
|
|
901
|
-
mockPythonBridge.fetchHeadless.mockRejectedValue(new Error('Browser crashed'));
|
|
902
|
-
|
|
903
|
-
const results = [];
|
|
904
|
-
await expect(async () => {
|
|
905
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
906
|
-
simple: true,
|
|
907
|
-
useHeadless: true,
|
|
908
|
-
})) {
|
|
909
|
-
results.push(result);
|
|
910
|
-
}
|
|
911
|
-
}).rejects.toThrow('Headless fetch failed: Browser crashed');
|
|
912
|
-
|
|
913
|
-
expect(results).toHaveLength(0);
|
|
914
|
-
// Should not have fallen back to axios
|
|
915
|
-
expect(axios.get).not.toHaveBeenCalled();
|
|
916
|
-
});
|
|
917
|
-
});
|
|
918
|
-
|
|
919
|
-
describe('Claude CLI Not Installed', () => {
|
|
920
|
-
it('should throw when intelligent mode requested but Claude CLI not available', async () => {
|
|
921
|
-
// Simulate npm package usage without Claude Code installed
|
|
922
|
-
vi.mocked(ClaudeClient.isAvailable).mockReturnValue(false);
|
|
923
|
-
|
|
924
|
-
const results: { url: string }[] = [];
|
|
925
|
-
|
|
926
|
-
await expect(async () => {
|
|
927
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
928
|
-
crawlInstruction: 'Find all documentation pages', // Requires intelligent mode
|
|
929
|
-
maxPages: 5,
|
|
930
|
-
})) {
|
|
931
|
-
results.push(result);
|
|
932
|
-
}
|
|
933
|
-
}).rejects.toThrow('Claude CLI not available');
|
|
934
|
-
|
|
935
|
-
expect(results).toHaveLength(0);
|
|
936
|
-
expect(mockClaudeClient.determineCrawlUrls).not.toHaveBeenCalled();
|
|
937
|
-
});
|
|
938
|
-
|
|
939
|
-
it('should throw when extraction requested but Claude CLI not available', async () => {
|
|
940
|
-
// Simulate npm package usage without Claude Code installed
|
|
941
|
-
vi.mocked(ClaudeClient.isAvailable).mockReturnValue(false);
|
|
942
|
-
|
|
943
|
-
mockPythonBridge.crawl.mockResolvedValue({
|
|
944
|
-
pages: [{ links: [] }],
|
|
945
|
-
});
|
|
946
|
-
|
|
947
|
-
const results: { url: string; extracted?: string }[] = [];
|
|
948
|
-
|
|
949
|
-
await expect(async () => {
|
|
950
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
951
|
-
simple: true,
|
|
952
|
-
extractInstruction: 'Extract pricing info', // Requires Claude
|
|
953
|
-
maxPages: 1,
|
|
954
|
-
})) {
|
|
955
|
-
results.push(result);
|
|
956
|
-
}
|
|
957
|
-
}).rejects.toThrow('Claude CLI not available');
|
|
958
|
-
|
|
959
|
-
expect(results).toHaveLength(0);
|
|
960
|
-
expect(mockClaudeClient.extractContent).not.toHaveBeenCalled();
|
|
961
|
-
});
|
|
962
|
-
});
|
|
963
|
-
|
|
964
|
-
describe('Single-Page Crawl Warning', () => {
|
|
965
|
-
it('should emit warning when only 1 page crawled with maxPages > 1', async () => {
|
|
966
|
-
// Mock no links found - single page crawl
|
|
967
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
968
|
-
|
|
969
|
-
const results = [];
|
|
970
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
971
|
-
simple: true,
|
|
972
|
-
maxPages: 50,
|
|
973
|
-
})) {
|
|
974
|
-
results.push(result);
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
expect(results).toHaveLength(1);
|
|
978
|
-
const warningEvents = progressEvents.filter(
|
|
979
|
-
(e) => e.type === 'error' && e.message?.includes('Only crawled 1 page')
|
|
980
|
-
);
|
|
981
|
-
expect(warningEvents).toHaveLength(1);
|
|
982
|
-
expect(warningEvents[0]?.message).toContain('--fast');
|
|
983
|
-
expect(warningEvents[0]?.message).toContain('maxPages=50');
|
|
984
|
-
});
|
|
985
|
-
|
|
986
|
-
it('should NOT emit warning when maxPages is 1', async () => {
|
|
987
|
-
mockPythonBridge.crawl.mockResolvedValue({ pages: [{ links: [] }] });
|
|
988
|
-
|
|
989
|
-
const results = [];
|
|
990
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
991
|
-
simple: true,
|
|
992
|
-
maxPages: 1,
|
|
993
|
-
})) {
|
|
994
|
-
results.push(result);
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
expect(results).toHaveLength(1);
|
|
998
|
-
const warningEvents = progressEvents.filter(
|
|
999
|
-
(e) => e.type === 'error' && e.message?.includes('Only crawled 1 page')
|
|
1000
|
-
);
|
|
1001
|
-
expect(warningEvents).toHaveLength(0);
|
|
1002
|
-
});
|
|
1003
|
-
|
|
1004
|
-
it('should NOT emit warning when multiple pages crawled', async () => {
|
|
1005
|
-
mockPythonBridge.crawl
|
|
1006
|
-
.mockResolvedValueOnce({ pages: [{ links: ['https://example.com/page2'] }] })
|
|
1007
|
-
.mockResolvedValueOnce({ pages: [{ links: [] }] });
|
|
1008
|
-
|
|
1009
|
-
vi.mocked(axios.get)
|
|
1010
|
-
.mockResolvedValueOnce({ data: '<html><body>Page1</body></html>' })
|
|
1011
|
-
.mockResolvedValueOnce({ data: '<html><body>Page2</body></html>' });
|
|
1012
|
-
|
|
1013
|
-
const results = [];
|
|
1014
|
-
for await (const result of crawler.crawl('https://example.com', {
|
|
1015
|
-
simple: true,
|
|
1016
|
-
maxPages: 50,
|
|
1017
|
-
})) {
|
|
1018
|
-
results.push(result);
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
expect(results).toHaveLength(2);
|
|
1022
|
-
const warningEvents = progressEvents.filter(
|
|
1023
|
-
(e) => e.type === 'error' && e.message?.includes('Only crawled 1 page')
|
|
1024
|
-
);
|
|
1025
|
-
expect(warningEvents).toHaveLength(0);
|
|
1026
|
-
});
|
|
1027
|
-
});
|
|
1028
|
-
});
|