@jackwener/opencli 1.7.12 → 1.7.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -7
- package/README.zh-CN.md +9 -8
- package/cli-manifest.json +12194 -6843
- package/clis/1point3acres/digest.js +35 -0
- package/clis/1point3acres/forum.js +51 -0
- package/clis/1point3acres/forums.js +44 -0
- package/clis/1point3acres/hot.js +35 -0
- package/clis/1point3acres/latest.js +35 -0
- package/clis/1point3acres/notifications.js +64 -0
- package/clis/1point3acres/search.js +71 -0
- package/clis/1point3acres/thread.js +117 -0
- package/clis/1point3acres/user.js +77 -0
- package/clis/1point3acres/utils.js +247 -0
- package/clis/_shared/desktop-commands.js +4 -0
- package/clis/aibase/news.js +110 -0
- package/clis/aibase/news.test.js +59 -0
- package/clis/amazon/discussion.test.js +1 -28
- package/clis/antigravity/watch.js +3 -2
- package/clis/arxiv/author.js +44 -0
- package/clis/baidu-scholar/search.js +0 -1
- package/clis/bbc/topic.js +57 -0
- package/clis/bbc/utils.js +79 -0
- package/clis/chaoxing/assignments.js +1 -1
- package/clis/chaoxing/exams.js +1 -1
- package/clis/chatgpt/ask.js +57 -0
- package/clis/chatgpt/commands.test.js +45 -0
- package/clis/chatgpt/detail.js +46 -0
- package/clis/chatgpt/history.js +39 -0
- package/clis/chatgpt/image.js +12 -11
- package/clis/chatgpt/image.test.js +23 -0
- package/clis/chatgpt/new.js +25 -0
- package/clis/chatgpt/read.js +43 -0
- package/clis/chatgpt/send.js +46 -0
- package/clis/chatgpt/status.js +29 -0
- package/clis/chatgpt/utils.js +294 -4
- package/clis/chatgpt/utils.test.js +13 -0
- package/clis/chatgpt-app/ask.js +6 -3
- package/clis/chatwise/ask.js +16 -43
- package/clis/chatwise/composer.test.js +186 -0
- package/clis/chatwise/send.js +2 -24
- package/clis/chatwise/utils.js +143 -0
- package/clis/claude/ask.js +1 -1
- package/clis/claude/detail.js +1 -0
- package/clis/claude/history.js +1 -0
- package/clis/claude/new.js +1 -0
- package/clis/claude/read.js +1 -0
- package/clis/claude/send.js +1 -0
- package/clis/claude/status.js +1 -0
- package/clis/codex/ask.js +15 -9
- package/clis/codex/history.js +16 -33
- package/clis/codex/projects.js +28 -0
- package/clis/codex/read.js +10 -4
- package/clis/codex/send.js +10 -3
- package/clis/codex/sidebar.js +356 -0
- package/clis/codex/sidebar.test.js +329 -0
- package/clis/coingecko/categories.js +75 -0
- package/clis/coingecko/coin.js +107 -0
- package/clis/coingecko/coingecko.test.js +109 -0
- package/clis/coingecko/derivatives.js +84 -0
- package/clis/coingecko/exchanges.js +74 -0
- package/clis/coingecko/global.js +71 -0
- package/clis/coingecko/top.js +64 -0
- package/clis/coingecko/trending.js +55 -0
- package/clis/coupang/add-to-cart.js +21 -13
- package/clis/coupang/coupang.test.js +159 -0
- package/clis/coupang/product.js +257 -0
- package/clis/coupang/search.js +38 -16
- package/clis/coupang/utils.js +55 -1
- package/clis/crates/crate.js +62 -0
- package/clis/crates/search.js +44 -0
- package/clis/crates/utils.js +72 -0
- package/clis/ctrip/ctrip.test.js +234 -0
- package/clis/ctrip/hotel-suggest.js +45 -0
- package/clis/ctrip/search.js +22 -68
- package/clis/ctrip/utils.js +175 -0
- package/clis/cursor/ask.js +6 -3
- package/clis/dblp/author.js +133 -0
- package/clis/dblp/venue.js +64 -0
- package/clis/deepseek/ask.js +12 -7
- package/clis/deepseek/ask.test.js +13 -13
- package/clis/deepseek/detail.js +38 -0
- package/clis/deepseek/detail.test.js +81 -0
- package/clis/deepseek/history.js +1 -0
- package/clis/deepseek/new.js +1 -0
- package/clis/deepseek/read.js +1 -0
- package/clis/deepseek/send.js +140 -0
- package/clis/deepseek/send.test.js +107 -0
- package/clis/deepseek/status.js +1 -0
- package/clis/deepseek/utils.js +66 -0
- package/clis/deepseek/utils.test.js +107 -1
- package/clis/defillama/defillama.test.js +99 -0
- package/clis/defillama/protocol.js +84 -0
- package/clis/defillama/protocols.js +55 -0
- package/clis/defillama/utils.js +99 -0
- package/clis/devto/latest.js +74 -0
- package/clis/dockerhub/image.js +52 -0
- package/clis/dockerhub/search.js +47 -0
- package/clis/dockerhub/utils.js +100 -0
- package/clis/doubao/ask.js +7 -3
- package/clis/doubao/detail.js +1 -0
- package/clis/doubao/history.js +1 -0
- package/clis/doubao/meeting-summary.js +1 -0
- package/clis/doubao/meeting-transcript.js +1 -0
- package/clis/doubao/new.js +1 -0
- package/clis/doubao/read.js +1 -0
- package/clis/doubao/send.js +1 -0
- package/clis/doubao/status.js +1 -0
- package/clis/douyin/draft.test.js +1 -30
- package/clis/endoflife/endoflife.test.js +51 -0
- package/clis/endoflife/product.js +55 -0
- package/clis/endoflife/utils.js +89 -0
- package/clis/facebook/__fixtures__/notifications-page.html +13 -0
- package/clis/facebook/notifications.js +326 -30
- package/clis/facebook/notifications.test.js +458 -0
- package/clis/flathub/app.js +71 -0
- package/clis/flathub/flathub.test.js +90 -0
- package/clis/flathub/search.js +80 -0
- package/clis/flathub/utils.js +114 -0
- package/clis/gemini/ask.js +7 -3
- package/clis/gemini/ask.test.js +2 -2
- package/clis/gemini/deep-research-result.js +6 -2
- package/clis/gemini/deep-research-result.test.js +15 -14
- package/clis/gemini/deep-research.js +8 -4
- package/clis/gemini/deep-research.test.js +15 -18
- package/clis/gemini/image.js +7 -2
- package/clis/gemini/new.js +1 -0
- package/clis/gemini/utils.js +0 -4
- package/clis/google-scholar/cite.js +0 -1
- package/clis/google-scholar/profile.js +0 -1
- package/clis/google-scholar/search.js +0 -1
- package/clis/goproxy/goproxy.test.js +103 -0
- package/clis/goproxy/module.js +47 -0
- package/clis/goproxy/utils.js +165 -0
- package/clis/goproxy/versions.js +59 -0
- package/clis/gov-law/recent.js +0 -1
- package/clis/gov-law/search.js +0 -1
- package/clis/gov-policy/__fixtures__/recent.html +16 -0
- package/clis/gov-policy/__fixtures__/search.html +41 -0
- package/clis/gov-policy/gov-policy.test.js +224 -0
- package/clis/gov-policy/recent.js +66 -24
- package/clis/gov-policy/search.js +65 -23
- package/clis/gov-policy/utils.js +54 -0
- package/clis/grok/ask.js +49 -265
- package/clis/grok/ask.test.js +21 -46
- package/clis/grok/detail.js +60 -0
- package/clis/grok/history.js +48 -0
- package/clis/grok/{image.ts → image.js} +56 -70
- package/clis/grok/image.test.ts +20 -0
- package/clis/grok/new.js +20 -0
- package/clis/grok/read.js +39 -0
- package/clis/grok/send.js +50 -0
- package/clis/grok/status.js +41 -0
- package/clis/grok/utils.js +326 -0
- package/clis/grok/utils.test.js +103 -0
- package/clis/hf/datasets.js +88 -0
- package/clis/hf/hf.test.js +16 -0
- package/clis/hf/models.js +91 -0
- package/clis/hf/paper.js +79 -0
- package/clis/hf/spaces.js +101 -0
- package/clis/hf/top.js +1 -0
- package/clis/homebrew/cask.js +39 -0
- package/clis/homebrew/formula.js +41 -0
- package/clis/homebrew/popular.js +54 -0
- package/clis/homebrew/utils.js +100 -0
- package/clis/hupu/__fixtures__/hot-home.html +64 -0
- package/clis/hupu/detail.js +0 -1
- package/clis/hupu/hot.js +156 -35
- package/clis/hupu/hot.test.js +224 -0
- package/clis/hupu/search.js +0 -1
- package/clis/instagram/note.js +1 -1
- package/clis/instagram/note.test.js +1 -29
- package/clis/instagram/post.js +1 -1
- package/clis/instagram/post.test.js +1 -1
- package/clis/instagram/reel.js +1 -1
- package/clis/instagram/story.js +1 -1
- package/clis/instagram/story.test.js +1 -34
- package/clis/jd/commands.test.js +1 -24
- package/clis/lichess/lichess.test.js +85 -0
- package/clis/lichess/top.js +46 -0
- package/clis/lichess/user.js +91 -0
- package/clis/lichess/utils.js +97 -0
- package/clis/linkedin/search.js +107 -10
- package/clis/linkedin/search.test.js +222 -0
- package/clis/linux-do/feed.js +2 -5
- package/clis/linux-do/feed.test.js +35 -0
- package/clis/lobsters/domain.js +92 -0
- package/clis/maven/artifact.js +49 -0
- package/clis/maven/search.js +51 -0
- package/clis/maven/utils.js +110 -0
- package/clis/mdn/search.js +97 -0
- package/clis/medium/tag.js +135 -0
- package/clis/npm/downloads.js +59 -0
- package/clis/npm/package.js +70 -0
- package/clis/npm/search.js +49 -0
- package/clis/npm/utils.js +76 -0
- package/clis/nuget/nuget.test.js +111 -0
- package/clis/nuget/package.js +101 -0
- package/clis/nuget/search.js +69 -0
- package/clis/nuget/utils.js +87 -0
- package/clis/nvd/cve.js +121 -0
- package/clis/oeis/oeis.test.js +88 -0
- package/clis/oeis/search.js +63 -0
- package/clis/oeis/sequence.js +71 -0
- package/clis/oeis/utils.js +88 -0
- package/clis/openalex/search.js +69 -0
- package/clis/openalex/utils.js +160 -0
- package/clis/openalex/work.js +65 -0
- package/clis/openfda/drug-label.js +74 -0
- package/clis/openfda/food-recall.js +65 -0
- package/clis/openfda/openfda.test.js +114 -0
- package/clis/openfda/utils.js +67 -0
- package/clis/osv/osv.test.js +97 -0
- package/clis/osv/query.js +72 -0
- package/clis/osv/utils.js +169 -0
- package/clis/osv/vulnerability.js +54 -0
- package/clis/packagist/package.js +49 -0
- package/clis/packagist/search.js +43 -0
- package/clis/packagist/utils.js +113 -0
- package/clis/paperreview/feedback.js +1 -1
- package/clis/paperreview/review.js +1 -1
- package/clis/paperreview/submit.js +1 -1
- package/clis/pixiv/download.test.js +1 -1
- package/clis/pixiv/illusts.test.js +1 -1
- package/clis/pixiv/search.test.js +1 -1
- package/clis/pubmed/article.js +50 -0
- package/clis/pubmed/author.js +64 -0
- package/clis/pubmed/citations.js +36 -0
- package/clis/pubmed/pubmed.test.js +276 -0
- package/clis/pubmed/related.js +45 -0
- package/clis/pubmed/search.js +75 -0
- package/clis/pubmed/utils.js +309 -0
- package/clis/pypi/downloads.js +66 -0
- package/clis/pypi/package.js +79 -0
- package/clis/pypi/utils.js +55 -0
- package/clis/quark/mv.js +1 -1
- package/clis/quark/save.js +1 -1
- package/clis/qwen/ask.js +85 -0
- package/clis/qwen/detail.js +62 -0
- package/clis/qwen/history.js +61 -0
- package/clis/qwen/image.js +179 -0
- package/clis/qwen/new.js +23 -0
- package/clis/qwen/read.js +41 -0
- package/clis/qwen/send.js +55 -0
- package/clis/qwen/status.js +37 -0
- package/clis/qwen/utils.js +409 -0
- package/clis/qwen/utils.test.js +45 -0
- package/clis/rest-countries/country.js +65 -0
- package/clis/rest-countries/region.js +64 -0
- package/clis/rest-countries/rest-countries.test.js +83 -0
- package/clis/rest-countries/utils.js +126 -0
- package/clis/reuters/article-detail.js +53 -0
- package/clis/reuters/reuters.test.js +299 -0
- package/clis/reuters/search.js +45 -34
- package/clis/reuters/utils.js +159 -0
- package/clis/rfc/rfc.js +52 -0
- package/clis/rfc/rfc.test.js +74 -0
- package/clis/rfc/utils.js +72 -0
- package/clis/rubygems/gem.js +42 -0
- package/clis/rubygems/search.js +47 -0
- package/clis/rubygems/utils.js +86 -0
- package/clis/stackoverflow/related.js +66 -0
- package/clis/stackoverflow/stackoverflow.test.js +58 -0
- package/clis/stackoverflow/tag.js +60 -0
- package/clis/stackoverflow/user.js +50 -0
- package/clis/stackoverflow/utils.js +118 -0
- package/clis/steam/app.js +67 -0
- package/clis/steam/search.js +58 -0
- package/clis/steam/steam.test.js +46 -0
- package/clis/steam/utils.js +107 -0
- package/clis/taobao/commands.test.js +1 -24
- package/clis/test-utils.js +61 -0
- package/clis/tieba/hot.js +0 -1
- package/clis/tiktok/comment.js +128 -41
- package/clis/tiktok/creator-videos.js +270 -0
- package/clis/tiktok/creator-videos.test.js +113 -0
- package/clis/tiktok/explore.js +137 -29
- package/clis/tiktok/follow.js +115 -33
- package/clis/tiktok/following.js +157 -36
- package/clis/tiktok/friends.js +139 -37
- package/clis/tiktok/live.js +137 -41
- package/clis/tiktok/notifications.js +141 -38
- package/clis/tiktok/refactor.test.js +389 -0
- package/clis/tiktok/unfollow.js +124 -38
- package/clis/tiktok/user.js +203 -29
- package/clis/tiktok/utils.js +505 -0
- package/clis/tiktok/write-refactor.test.js +370 -0
- package/clis/toutiao/articles.js +36 -62
- package/clis/toutiao/hot.js +63 -0
- package/clis/toutiao/toutiao.test.js +378 -0
- package/clis/toutiao/utils.js +161 -0
- package/clis/tvmaze/search.js +61 -0
- package/clis/tvmaze/show.js +60 -0
- package/clis/tvmaze/tvmaze.test.js +93 -0
- package/clis/tvmaze/utils.js +110 -0
- package/clis/twitter/accept.js +1 -1
- package/clis/twitter/followers.js +134 -69
- package/clis/twitter/reply-dm.js +1 -1
- package/clis/twitter/reply.test.js +1 -29
- package/clis/uisdc/news.js +105 -0
- package/clis/uisdc/news.test.js +66 -0
- package/clis/wanfang/search.js +0 -1
- package/clis/web/read.js +47 -17
- package/clis/web/read.test.js +101 -1
- package/clis/weixin/create-draft.js +1 -1
- package/clis/weixin/drafts.js +1 -1
- package/clis/weixin/drafts.test.js +5 -1
- package/clis/weixin/search.js +157 -0
- package/clis/weixin/search.test.js +227 -0
- package/clis/wikidata/entity.js +60 -0
- package/clis/wikidata/search.js +50 -0
- package/clis/wikidata/utils.js +117 -0
- package/clis/wikidata/wikidata.test.js +83 -0
- package/clis/wikipedia/page.js +95 -0
- package/clis/wttr/current.js +63 -0
- package/clis/wttr/forecast.js +71 -0
- package/clis/wttr/utils.js +50 -0
- package/clis/wttr/wttr.test.js +84 -0
- package/clis/xianyu/chat.js +16 -4
- package/clis/xianyu/chat.test.js +64 -0
- package/clis/xianyu/publish.js +485 -0
- package/clis/xianyu/publish.test.js +220 -0
- package/clis/xiaoe/catalog.js +105 -40
- package/clis/xiaoe/content.js +164 -29
- package/clis/xiaoe/courses.js +86 -29
- package/clis/xiaoe/xiaoe.test.js +486 -0
- package/clis/xiaohongshu/creator-notes-summary.js +1 -1
- package/clis/xiaohongshu/publish.js +16 -3
- package/clis/xiaohongshu/publish.test.js +46 -1
- package/clis/youtube/transcript.js +13 -19
- package/clis/youtube/transcript.test.js +17 -0
- package/clis/yuanbao/ask.js +17 -66
- package/clis/yuanbao/ask.test.js +5 -5
- package/clis/yuanbao/detail.js +65 -0
- package/clis/yuanbao/history.js +51 -0
- package/clis/yuanbao/new.js +1 -0
- package/clis/yuanbao/read.js +38 -0
- package/clis/yuanbao/send.js +57 -0
- package/clis/yuanbao/shared.js +297 -5
- package/clis/yuanbao/shared.test.js +80 -0
- package/clis/yuanbao/status.js +44 -0
- package/clis/zlibrary/commands.test.js +1 -11
- package/dist/src/browser/base-page.d.ts +9 -0
- package/dist/src/browser/base-page.js +44 -1
- package/dist/src/browser/base-page.test.js +66 -0
- package/dist/src/browser/cdp.d.ts +1 -0
- package/dist/src/browser/cdp.js +51 -9
- package/dist/src/browser/daemon-client.d.ts +4 -0
- package/dist/src/browser/errors.js +1 -1
- package/dist/src/browser/page.d.ts +1 -1
- package/dist/src/browser/page.js +3 -1
- package/dist/src/browser/page.test.js +29 -0
- package/dist/src/browser/target-errors.d.ts +2 -1
- package/dist/src/browser/target-errors.js +1 -0
- package/dist/src/browser/target-resolver.d.ts +25 -0
- package/dist/src/browser/target-resolver.js +43 -0
- package/dist/src/build-manifest.js +9 -4
- package/dist/src/build-manifest.test.js +2 -8
- package/dist/src/capabilityRouting.d.ts +16 -1
- package/dist/src/capabilityRouting.js +24 -1
- package/dist/src/capabilityRouting.test.js +19 -1
- package/dist/src/cli.js +76 -11
- package/dist/src/cli.test.js +150 -0
- package/dist/src/commanderAdapter.js +0 -5
- package/dist/src/commanderAdapter.test.js +0 -1
- package/dist/src/discovery.js +2 -5
- package/dist/src/errors.js +1 -1
- package/dist/src/execution.d.ts +1 -1
- package/dist/src/execution.js +111 -27
- package/dist/src/execution.test.js +326 -17
- package/dist/src/help.d.ts +23 -2
- package/dist/src/help.js +41 -19
- package/dist/src/help.test.d.ts +1 -0
- package/dist/src/help.test.js +54 -0
- package/dist/src/main.js +14 -1
- package/dist/src/manifest-types.d.ts +5 -3
- package/dist/src/pipeline/executor.js +1 -1
- package/dist/src/pipeline/executor.test.js +8 -0
- package/dist/src/pipeline/registry.d.ts +9 -0
- package/dist/src/pipeline/registry.js +13 -1
- package/dist/src/pipeline/steps/browser.d.ts +1 -0
- package/dist/src/pipeline/steps/browser.js +10 -0
- package/dist/src/pipeline/steps/download.test.js +1 -0
- package/dist/src/registry-api.d.ts +1 -1
- package/dist/src/registry.d.ts +12 -11
- package/dist/src/registry.js +16 -6
- package/dist/src/registry.test.js +2 -2
- package/dist/src/runtime.d.ts +2 -1
- package/dist/src/runtime.js +1 -1
- package/dist/src/serialization.d.ts +2 -2
- package/dist/src/serialization.js +4 -6
- package/dist/src/serialization.test.js +17 -0
- package/dist/src/types.d.ts +17 -0
- package/dist/src/validate.js +15 -11
- package/dist/src/validate.test.d.ts +9 -0
- package/dist/src/validate.test.js +90 -0
- package/package.json +1 -1
- package/scripts/fetch-adapters.js +1 -1
- package/scripts/typed-error-lint-baseline.json +5 -77
- package/clis/ctrip/search.test.js +0 -64
- package/clis/gov-policy/commands.test.js +0 -27
- package/clis/linux-do/category.js +0 -37
- package/clis/linux-do/hot.js +0 -26
- package/clis/linux-do/latest.js +0 -19
- package/clis/pixiv/test-utils.js +0 -23
- package/clis/toutiao/articles.test.js +0 -30
- package/dist/src/analysis.d.ts +0 -40
- package/dist/src/analysis.js +0 -172
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Allows core and third-party plugins to register custom YAML operations.
|
|
4
4
|
*/
|
|
5
5
|
// Import core steps
|
|
6
|
-
import { stepNavigate, stepClick, stepType, stepWait, stepPress, stepSnapshot, stepEvaluate } from './steps/browser.js';
|
|
6
|
+
import { stepNavigate, stepClick, stepType, stepFill, stepWait, stepPress, stepSnapshot, stepEvaluate } from './steps/browser.js';
|
|
7
7
|
import { stepFetch } from './steps/fetch.js';
|
|
8
8
|
import { stepSelect, stepMap, stepFilter, stepSort, stepLimit } from './steps/transform.js';
|
|
9
9
|
import { stepIntercept } from './steps/intercept.js';
|
|
@@ -16,6 +16,17 @@ const _stepRegistry = new Map();
|
|
|
16
16
|
export function getStep(name) {
|
|
17
17
|
return _stepRegistry.get(name);
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* List all currently registered step names. Used by `validate.ts` to allowlist
|
|
21
|
+
* step names without maintaining a parallel hand-coded list.
|
|
22
|
+
*
|
|
23
|
+
* Note: this depends on registerStep() side effects below already having run.
|
|
24
|
+
* Importing this module triggers all core registrations at the bottom of the
|
|
25
|
+
* file, so the returned array reflects every core + plugin step at call time.
|
|
26
|
+
*/
|
|
27
|
+
export function getRegisteredStepNames() {
|
|
28
|
+
return [..._stepRegistry.keys()];
|
|
29
|
+
}
|
|
19
30
|
/**
|
|
20
31
|
* Register a new custom step handler for the YAML pipeline.
|
|
21
32
|
*/
|
|
@@ -32,6 +43,7 @@ registerStep('evaluate', stepEvaluate);
|
|
|
32
43
|
registerStep('snapshot', stepSnapshot);
|
|
33
44
|
registerStep('click', stepClick);
|
|
34
45
|
registerStep('type', stepType);
|
|
46
|
+
registerStep('fill', stepFill);
|
|
35
47
|
registerStep('wait', stepWait);
|
|
36
48
|
registerStep('press', stepPress);
|
|
37
49
|
registerStep('map', stepMap);
|
|
@@ -6,6 +6,7 @@ import type { IPage } from '../../types.js';
|
|
|
6
6
|
export declare function stepNavigate(page: IPage | null, params: unknown, data: unknown, args: Record<string, unknown>): Promise<unknown>;
|
|
7
7
|
export declare function stepClick(page: IPage | null, params: unknown, data: unknown, args: Record<string, unknown>): Promise<unknown>;
|
|
8
8
|
export declare function stepType(page: IPage | null, params: unknown, data: unknown, args: Record<string, unknown>): Promise<unknown>;
|
|
9
|
+
export declare function stepFill(page: IPage | null, params: unknown, data: unknown, args: Record<string, unknown>): Promise<unknown>;
|
|
9
10
|
export declare function stepWait(page: IPage | null, params: unknown, data: unknown, args: Record<string, unknown>): Promise<unknown>;
|
|
10
11
|
export declare function stepPress(page: IPage | null, params: unknown, data: unknown, args: Record<string, unknown>): Promise<unknown>;
|
|
11
12
|
export declare function stepSnapshot(page: IPage | null, params: unknown, _data: unknown, _args: Record<string, unknown>): Promise<unknown>;
|
|
@@ -29,6 +29,16 @@ export async function stepType(page, params, data, args) {
|
|
|
29
29
|
}
|
|
30
30
|
return data;
|
|
31
31
|
}
|
|
32
|
+
export async function stepFill(page, params, data, args) {
|
|
33
|
+
if (isRecord(params)) {
|
|
34
|
+
const ref = String(render(params.ref ?? '', { args, data })).replace(/^@/, '');
|
|
35
|
+
const text = String(render(params.text ?? '', { args, data }));
|
|
36
|
+
await page.fillText(ref, text);
|
|
37
|
+
if (params.submit)
|
|
38
|
+
await page.pressKey('Enter');
|
|
39
|
+
}
|
|
40
|
+
return data;
|
|
41
|
+
}
|
|
32
42
|
export async function stepWait(page, params, data, args) {
|
|
33
43
|
if (typeof params === 'number')
|
|
34
44
|
await page.wait(params);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* plugins are dynamically imported during discoverPlugins().
|
|
8
8
|
*/
|
|
9
9
|
export { cli, Strategy, getRegistry, fullName, registerCommand } from './registry.js';
|
|
10
|
-
export type { CliCommand, Arg, CliOptions, CommandArgs } from './registry.js';
|
|
10
|
+
export type { CliCommand, Arg, CliOptions, CommandArgs, BrowserSessionOptions, BrowserSessionReuse } from './registry.js';
|
|
11
11
|
export type { IPage } from './types.js';
|
|
12
12
|
export { onStartup, onBeforeExecute, onAfterExecute } from './hooks.js';
|
|
13
13
|
export type { HookFn, HookContext, HookName } from './hooks.js';
|
package/dist/src/registry.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ export declare enum Strategy {
|
|
|
6
6
|
PUBLIC = "public",
|
|
7
7
|
LOCAL = "local",
|
|
8
8
|
COOKIE = "cookie",
|
|
9
|
-
HEADER = "header",
|
|
10
9
|
INTERCEPT = "intercept",
|
|
11
10
|
UI = "ui"
|
|
12
11
|
}
|
|
@@ -20,14 +19,20 @@ export interface Arg {
|
|
|
20
19
|
help?: string;
|
|
21
20
|
choices?: string[];
|
|
22
21
|
}
|
|
23
|
-
export interface RequiredEnv {
|
|
24
|
-
name: string;
|
|
25
|
-
help?: string;
|
|
26
|
-
}
|
|
27
22
|
export type CommandArgs = Record<string, any>;
|
|
28
23
|
export type BrowserCommandFunc = (page: IPage, kwargs: CommandArgs, debug?: boolean) => Promise<unknown>;
|
|
29
24
|
export type NonBrowserCommandFunc = (kwargs: CommandArgs, debug?: boolean) => Promise<unknown>;
|
|
30
25
|
export type CommandAccess = 'read' | 'write';
|
|
26
|
+
export type BrowserSessionReuse = 'none' | 'site';
|
|
27
|
+
export interface BrowserSessionOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Control whether browser-backed adapter commands reuse a stable tab lease.
|
|
30
|
+
*
|
|
31
|
+
* - `none`: one-shot workspace per command execution (default)
|
|
32
|
+
* - `site`: all commands for this site share `site:<site>` until idle expiry
|
|
33
|
+
*/
|
|
34
|
+
reuse?: BrowserSessionReuse;
|
|
35
|
+
}
|
|
31
36
|
interface BaseCliCommand {
|
|
32
37
|
site: string;
|
|
33
38
|
name: string;
|
|
@@ -41,16 +46,10 @@ interface BaseCliCommand {
|
|
|
41
46
|
args: Arg[];
|
|
42
47
|
columns?: string[];
|
|
43
48
|
pipeline?: Record<string, unknown>[];
|
|
44
|
-
timeoutSeconds?: number;
|
|
45
49
|
/** Origin of this command: 'yaml', 'ts', or plugin name. */
|
|
46
50
|
source?: string;
|
|
47
51
|
footerExtra?: (kwargs: CommandArgs) => string | undefined;
|
|
48
|
-
requiredEnv?: RequiredEnv[];
|
|
49
52
|
validateArgs?: (kwargs: CommandArgs) => void;
|
|
50
|
-
/** Deprecation note shown in help / execution warnings. */
|
|
51
|
-
deprecated?: boolean | string;
|
|
52
|
-
/** Preferred replacement command, if any. */
|
|
53
|
-
replacedBy?: string;
|
|
54
53
|
/**
|
|
55
54
|
* Control pre-navigation and browser-session requirement.
|
|
56
55
|
*
|
|
@@ -67,6 +66,8 @@ interface BaseCliCommand {
|
|
|
67
66
|
* Adapter authors can set this explicitly to override the strategy-based default.
|
|
68
67
|
*/
|
|
69
68
|
navigateBefore?: boolean | string;
|
|
69
|
+
/** Browser session lifecycle defaults for adapter commands. */
|
|
70
|
+
browserSession?: BrowserSessionOptions;
|
|
70
71
|
/** Override the default CLI output format when the user does not pass -f/--format. */
|
|
71
72
|
defaultFormat?: 'table' | 'plain' | 'json' | 'yaml' | 'yml' | 'md' | 'markdown' | 'csv';
|
|
72
73
|
}
|
package/dist/src/registry.js
CHANGED
|
@@ -6,7 +6,6 @@ export var Strategy;
|
|
|
6
6
|
Strategy["PUBLIC"] = "public";
|
|
7
7
|
Strategy["LOCAL"] = "local";
|
|
8
8
|
Strategy["COOKIE"] = "cookie";
|
|
9
|
-
Strategy["HEADER"] = "header";
|
|
10
9
|
Strategy["INTERCEPT"] = "intercept";
|
|
11
10
|
Strategy["UI"] = "ui";
|
|
12
11
|
})(Strategy || (Strategy = {}));
|
|
@@ -18,6 +17,7 @@ export function cli(opts) {
|
|
|
18
17
|
aliases: opts.aliases,
|
|
19
18
|
description: opts.description ?? '',
|
|
20
19
|
access: opts.access,
|
|
20
|
+
example: opts.example,
|
|
21
21
|
domain: opts.domain,
|
|
22
22
|
strategy: opts.strategy,
|
|
23
23
|
browser: opts.browser,
|
|
@@ -25,12 +25,9 @@ export function cli(opts) {
|
|
|
25
25
|
columns: opts.columns,
|
|
26
26
|
func: opts.func,
|
|
27
27
|
pipeline: opts.pipeline,
|
|
28
|
-
timeoutSeconds: opts.timeoutSeconds,
|
|
29
28
|
footerExtra: opts.footerExtra,
|
|
30
|
-
requiredEnv: opts.requiredEnv,
|
|
31
|
-
deprecated: opts.deprecated,
|
|
32
|
-
replacedBy: opts.replacedBy,
|
|
33
29
|
navigateBefore: opts.navigateBefore,
|
|
30
|
+
browserSession: opts.browserSession,
|
|
34
31
|
defaultFormat: opts.defaultFormat,
|
|
35
32
|
};
|
|
36
33
|
registerCommand(cmd);
|
|
@@ -60,11 +57,12 @@ export function strategyLabel(cmd) {
|
|
|
60
57
|
*/
|
|
61
58
|
function normalizeCommand(cmd) {
|
|
62
59
|
assertCommandAccess(cmd);
|
|
60
|
+
assertBrowserSessionOptions(cmd);
|
|
63
61
|
const strategy = cmd.strategy ?? (cmd.browser === false ? Strategy.PUBLIC : Strategy.COOKIE);
|
|
64
62
|
const browser = cmd.browser ?? (strategy !== Strategy.PUBLIC && strategy !== Strategy.LOCAL);
|
|
65
63
|
let navigateBefore = cmd.navigateBefore;
|
|
66
64
|
if (navigateBefore === undefined) {
|
|
67
|
-
if (
|
|
65
|
+
if (strategy === Strategy.COOKIE && cmd.domain) {
|
|
68
66
|
navigateBefore = `https://${cmd.domain}`;
|
|
69
67
|
}
|
|
70
68
|
else if (strategy !== Strategy.PUBLIC && strategy !== Strategy.LOCAL) {
|
|
@@ -84,6 +82,18 @@ function assertCommandAccess(cmd) {
|
|
|
84
82
|
const key = `${cmd.site}/${cmd.name}`;
|
|
85
83
|
throw new Error(`Command ${key} must declare access: 'read' | 'write'`);
|
|
86
84
|
}
|
|
85
|
+
function assertBrowserSessionOptions(cmd) {
|
|
86
|
+
if (cmd.browserSession === undefined)
|
|
87
|
+
return;
|
|
88
|
+
const key = `${cmd.site}/${cmd.name}`;
|
|
89
|
+
if (cmd.browserSession === null || typeof cmd.browserSession !== 'object' || Array.isArray(cmd.browserSession)) {
|
|
90
|
+
throw new Error(`Command ${key} browserSession must be an object`);
|
|
91
|
+
}
|
|
92
|
+
const reuse = cmd.browserSession.reuse;
|
|
93
|
+
if (reuse !== undefined && reuse !== 'none' && reuse !== 'site') {
|
|
94
|
+
throw new Error(`Command ${key} browserSession.reuse must be one of: none, site`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
87
97
|
export function registerCommand(cmd) {
|
|
88
98
|
const normalized = normalizeCommand(cmd);
|
|
89
99
|
const canonicalKey = fullName(normalized);
|
|
@@ -121,12 +121,12 @@ describe('registerCommand', () => {
|
|
|
121
121
|
name: 'direct-reg', access: 'read',
|
|
122
122
|
description: 'directly registered',
|
|
123
123
|
args: [],
|
|
124
|
-
strategy: Strategy.
|
|
124
|
+
strategy: Strategy.COOKIE,
|
|
125
125
|
browser: true,
|
|
126
126
|
};
|
|
127
127
|
registerCommand(cmd);
|
|
128
128
|
const reg = getRegistry();
|
|
129
|
-
expect(reg.get('test-registry/direct-reg')?.strategy).toBe(Strategy.
|
|
129
|
+
expect(reg.get('test-registry/direct-reg')?.strategy).toBe(Strategy.COOKIE);
|
|
130
130
|
});
|
|
131
131
|
});
|
|
132
132
|
describe('normalizeCommand (via registerCommand)', () => {
|
package/dist/src/runtime.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ import type { IPage } from './types.js';
|
|
|
6
6
|
export declare function getBrowserFactory(site?: string): new () => IBrowserFactory;
|
|
7
7
|
export declare const DEFAULT_BROWSER_CONNECT_TIMEOUT: number;
|
|
8
8
|
export declare const DEFAULT_BROWSER_COMMAND_TIMEOUT: number;
|
|
9
|
-
export declare const DEFAULT_BROWSER_EXPLORE_TIMEOUT: number;
|
|
10
9
|
/**
|
|
11
10
|
* Timeout with seconds unit. Used for high-level command timeouts.
|
|
12
11
|
*/
|
|
@@ -28,6 +27,7 @@ export interface IBrowserFactory {
|
|
|
28
27
|
workspace?: string;
|
|
29
28
|
cdpEndpoint?: string;
|
|
30
29
|
contextId?: string;
|
|
30
|
+
idleTimeout?: number;
|
|
31
31
|
}): Promise<IPage>;
|
|
32
32
|
close(): Promise<void>;
|
|
33
33
|
}
|
|
@@ -35,4 +35,5 @@ export declare function browserSession<T>(BrowserFactory: new () => IBrowserFact
|
|
|
35
35
|
workspace?: string;
|
|
36
36
|
cdpEndpoint?: string;
|
|
37
37
|
contextId?: string;
|
|
38
|
+
idleTimeout?: number;
|
|
38
39
|
}): Promise<T>;
|
package/dist/src/runtime.js
CHANGED
|
@@ -24,7 +24,6 @@ function parseEnvTimeout(envVar, fallback) {
|
|
|
24
24
|
}
|
|
25
25
|
export const DEFAULT_BROWSER_CONNECT_TIMEOUT = parseEnvTimeout('OPENCLI_BROWSER_CONNECT_TIMEOUT', 30);
|
|
26
26
|
export const DEFAULT_BROWSER_COMMAND_TIMEOUT = parseEnvTimeout('OPENCLI_BROWSER_COMMAND_TIMEOUT', 60);
|
|
27
|
-
export const DEFAULT_BROWSER_EXPLORE_TIMEOUT = parseEnvTimeout('OPENCLI_BROWSER_EXPLORE_TIMEOUT', 120);
|
|
28
27
|
/**
|
|
29
28
|
* Timeout with seconds unit. Used for high-level command timeouts.
|
|
30
29
|
*/
|
|
@@ -54,6 +53,7 @@ export async function browserSession(BrowserFactory, fn, opts = {}) {
|
|
|
54
53
|
workspace: opts.workspace,
|
|
55
54
|
cdpEndpoint: opts.cdpEndpoint,
|
|
56
55
|
contextId: opts.contextId,
|
|
56
|
+
idleTimeout: opts.idleTimeout,
|
|
57
57
|
});
|
|
58
58
|
return await fn(page);
|
|
59
59
|
}
|
|
@@ -31,8 +31,8 @@ export declare function serializeCommand(cmd: CliCommand): {
|
|
|
31
31
|
columns: string[];
|
|
32
32
|
domain: string | null;
|
|
33
33
|
example: string;
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
defaultFormat: "table" | "plain" | "json" | "yaml" | "yml" | "md" | "markdown" | "csv" | null;
|
|
35
|
+
browserSession: import("./registry.js").BrowserSessionOptions | null;
|
|
36
36
|
};
|
|
37
37
|
/** Human-readable arg summary: `<required> [optional]` style. */
|
|
38
38
|
export declare function formatArgSummary(args: Arg[]): string;
|
|
@@ -33,8 +33,8 @@ export function serializeCommand(cmd) {
|
|
|
33
33
|
columns: cmd.columns ?? [],
|
|
34
34
|
domain: cmd.domain ?? null,
|
|
35
35
|
example: formatCommandExample(cmd),
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
defaultFormat: cmd.defaultFormat ?? null,
|
|
37
|
+
browserSession: cmd.browserSession ?? null,
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
// ── Formatting ──────────────────────────────────────────────────────────────
|
|
@@ -90,10 +90,8 @@ export function formatRegistryHelpText(cmd) {
|
|
|
90
90
|
meta.push(`Browser: ${cmd.browser ? 'yes' : 'no'}`);
|
|
91
91
|
if (cmd.domain)
|
|
92
92
|
meta.push(`Domain: ${cmd.domain}`);
|
|
93
|
-
if (cmd.
|
|
94
|
-
meta.push(`
|
|
95
|
-
if (cmd.replacedBy)
|
|
96
|
-
meta.push(`Use instead: ${cmd.replacedBy}`);
|
|
93
|
+
if (cmd.defaultFormat)
|
|
94
|
+
meta.push(`Default format: ${cmd.defaultFormat}`);
|
|
97
95
|
if (cmd.aliases?.length)
|
|
98
96
|
meta.push(`Aliases: ${cmd.aliases.join(', ')}`);
|
|
99
97
|
lines.push(meta.join(' | '));
|
|
@@ -58,4 +58,21 @@ describe('formatRegistryHelpText', () => {
|
|
|
58
58
|
expect(formatRegistryHelpText(cmd)).toContain('Example: opencli bilibili hot -f yaml');
|
|
59
59
|
expect(formatRegistryHelpText(cmd)).not.toContain('Strategy:');
|
|
60
60
|
});
|
|
61
|
+
it('surfaces command default output format in structured serialization and help text', () => {
|
|
62
|
+
const cmd = {
|
|
63
|
+
site: 'gemini',
|
|
64
|
+
name: 'ask',
|
|
65
|
+
access: 'read',
|
|
66
|
+
description: 'Ask Gemini',
|
|
67
|
+
strategy: Strategy.COOKIE,
|
|
68
|
+
browser: true,
|
|
69
|
+
args: [],
|
|
70
|
+
defaultFormat: 'plain',
|
|
71
|
+
};
|
|
72
|
+
expect(serializeCommand(cmd)).toMatchObject({
|
|
73
|
+
command: 'gemini/ask',
|
|
74
|
+
defaultFormat: 'plain',
|
|
75
|
+
});
|
|
76
|
+
expect(formatRegistryHelpText(cmd)).toContain('Default format: plain');
|
|
77
|
+
});
|
|
61
78
|
});
|
package/dist/src/types.d.ts
CHANGED
|
@@ -31,6 +31,10 @@ export interface ScreenshotOptions {
|
|
|
31
31
|
format?: 'png' | 'jpeg';
|
|
32
32
|
quality?: number;
|
|
33
33
|
fullPage?: boolean;
|
|
34
|
+
/** Override viewport width in CSS pixels for the screenshot only (cleared after). */
|
|
35
|
+
width?: number;
|
|
36
|
+
/** Override viewport height in CSS pixels for the screenshot only (ignored when fullPage). */
|
|
37
|
+
height?: number;
|
|
34
38
|
path?: string;
|
|
35
39
|
}
|
|
36
40
|
export interface FetchJsonOptions {
|
|
@@ -87,6 +91,19 @@ export interface IPage {
|
|
|
87
91
|
matches_n: number;
|
|
88
92
|
match_level: 'exact' | 'stable' | 'reidentified';
|
|
89
93
|
}>;
|
|
94
|
+
fillText(ref: string, text: string, opts?: {
|
|
95
|
+
nth?: number;
|
|
96
|
+
firstOnMulti?: boolean;
|
|
97
|
+
}): Promise<{
|
|
98
|
+
filled: boolean;
|
|
99
|
+
verified: boolean;
|
|
100
|
+
expected: string;
|
|
101
|
+
actual: string;
|
|
102
|
+
length: number;
|
|
103
|
+
matches_n: number;
|
|
104
|
+
match_level: 'exact' | 'stable' | 'reidentified';
|
|
105
|
+
mode?: 'input' | 'textarea' | 'contenteditable';
|
|
106
|
+
}>;
|
|
90
107
|
pressKey(key: string): Promise<void>;
|
|
91
108
|
scrollTo(ref: string, opts?: {
|
|
92
109
|
nth?: number;
|
package/dist/src/validate.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/** Validate CLI definitions from the registry (JS-first). */
|
|
2
2
|
import { getRegistry, fullName } from './registry.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
import { getRegisteredStepNames } from './pipeline/registry.js';
|
|
4
|
+
/**
|
|
5
|
+
* Pipeline step names — derived from the live pipeline registry on each
|
|
6
|
+
* validate call so a new step registered in src/pipeline/registry.ts (or by
|
|
7
|
+
* a plugin at runtime) is automatically allowlisted here (no parallel
|
|
8
|
+
* hand-maintained list, no stale-snapshot drift).
|
|
9
|
+
*/
|
|
10
|
+
function getKnownStepNames() {
|
|
11
|
+
return new Set(getRegisteredStepNames());
|
|
12
|
+
}
|
|
10
13
|
/**
|
|
11
14
|
* Validate registered CLI commands from the in-memory registry.
|
|
12
15
|
*
|
|
@@ -66,18 +69,19 @@ function validateCommand(cmd) {
|
|
|
66
69
|
const warnings = [];
|
|
67
70
|
if (!cmd.description)
|
|
68
71
|
warnings.push('Missing description');
|
|
69
|
-
// Browser commands should specify a domain for
|
|
72
|
+
// Browser commands should specify a domain for authenticated browser context
|
|
70
73
|
if (cmd.browser && !cmd.domain) {
|
|
71
|
-
warnings.push('Browser command without "domain" —
|
|
74
|
+
warnings.push('Browser command without "domain" — authenticated browser context may not work');
|
|
72
75
|
}
|
|
73
76
|
// Pipeline validation: check step names for typos
|
|
74
77
|
if (Array.isArray(cmd.pipeline)) {
|
|
78
|
+
const knownStepNames = getKnownStepNames();
|
|
75
79
|
for (let i = 0; i < cmd.pipeline.length; i++) {
|
|
76
80
|
const step = cmd.pipeline[i];
|
|
77
81
|
if (step && typeof step === 'object') {
|
|
78
82
|
for (const key of Object.keys(step)) {
|
|
79
|
-
if (!
|
|
80
|
-
warnings.push(`Pipeline step ${i}: unknown step name "${key}" (did you mean one of: ${[...
|
|
83
|
+
if (!knownStepNames.has(key)) {
|
|
84
|
+
warnings.push(`Pipeline step ${i}: unknown step name "${key}" (did you mean one of: ${[...knownStepNames].join(', ')}?)`);
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for src/validate.ts.
|
|
3
|
+
*
|
|
4
|
+
* Focus: regression guards for the "single source of truth" link between
|
|
5
|
+
* pipeline step registry (src/pipeline/registry.ts) and validate.ts step
|
|
6
|
+
* allowlist. A new step registered via `registerStep()` must automatically
|
|
7
|
+
* be allowlisted by `opencli validate` — no parallel hand-maintained list.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for src/validate.ts.
|
|
3
|
+
*
|
|
4
|
+
* Focus: regression guards for the "single source of truth" link between
|
|
5
|
+
* pipeline step registry (src/pipeline/registry.ts) and validate.ts step
|
|
6
|
+
* allowlist. A new step registered via `registerStep()` must automatically
|
|
7
|
+
* be allowlisted by `opencli validate` — no parallel hand-maintained list.
|
|
8
|
+
*/
|
|
9
|
+
import { describe, it, expect } from 'vitest';
|
|
10
|
+
import { getRegisteredStepNames, registerStep } from './pipeline/registry.js';
|
|
11
|
+
import { cli, getRegistry, Strategy } from './registry.js';
|
|
12
|
+
import { validateClisWithTarget } from './validate.js';
|
|
13
|
+
describe('validate.ts pipeline step allowlist', () => {
|
|
14
|
+
it('uses every step name registered in pipeline/registry.ts', () => {
|
|
15
|
+
const registered = getRegisteredStepNames();
|
|
16
|
+
expect(registered).toContain('navigate');
|
|
17
|
+
expect(registered).toContain('click');
|
|
18
|
+
expect(registered).toContain('type');
|
|
19
|
+
expect(registered).toContain('fill');
|
|
20
|
+
expect(registered).toContain('fetch');
|
|
21
|
+
expect(registered.length).toBeGreaterThanOrEqual(15);
|
|
22
|
+
});
|
|
23
|
+
it('does not warn for any step name currently registered in the pipeline registry', () => {
|
|
24
|
+
// Snapshot the registry before mutating it for the test.
|
|
25
|
+
const reg = getRegistry();
|
|
26
|
+
const original = reg.get('validate-allowlist-test/all-steps');
|
|
27
|
+
if (original)
|
|
28
|
+
reg.delete('validate-allowlist-test/all-steps');
|
|
29
|
+
const allRegisteredSteps = getRegisteredStepNames();
|
|
30
|
+
cli({
|
|
31
|
+
site: 'validate-allowlist-test',
|
|
32
|
+
name: 'all-steps',
|
|
33
|
+
access: 'read',
|
|
34
|
+
browser: false,
|
|
35
|
+
strategy: Strategy.PUBLIC,
|
|
36
|
+
args: [],
|
|
37
|
+
pipeline: allRegisteredSteps.map(stepName => ({ [stepName]: {} })),
|
|
38
|
+
func: async () => [],
|
|
39
|
+
});
|
|
40
|
+
try {
|
|
41
|
+
const report = validateClisWithTarget([], 'validate-allowlist-test/all-steps');
|
|
42
|
+
const r = report.results[0];
|
|
43
|
+
const unknownStepWarning = r.warnings.find(w => w.startsWith('Pipeline step '));
|
|
44
|
+
expect(unknownStepWarning).toBeUndefined();
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
reg.delete('validate-allowlist-test/all-steps');
|
|
48
|
+
if (original)
|
|
49
|
+
reg.set('validate-allowlist-test/all-steps', original);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
it('newly registered step automatically appears in validator allowlist', () => {
|
|
53
|
+
const customStep = '__test_custom_step__';
|
|
54
|
+
expect(getRegisteredStepNames()).not.toContain(customStep);
|
|
55
|
+
registerStep(customStep, async (_p, _params, data) => data);
|
|
56
|
+
try {
|
|
57
|
+
expect(getRegisteredStepNames()).toContain(customStep);
|
|
58
|
+
const reg = getRegistry();
|
|
59
|
+
const original = reg.get('validate-dynamic-test/uses-custom');
|
|
60
|
+
if (original)
|
|
61
|
+
reg.delete('validate-dynamic-test/uses-custom');
|
|
62
|
+
cli({
|
|
63
|
+
site: 'validate-dynamic-test',
|
|
64
|
+
name: 'uses-custom',
|
|
65
|
+
access: 'read',
|
|
66
|
+
browser: false,
|
|
67
|
+
strategy: Strategy.PUBLIC,
|
|
68
|
+
args: [],
|
|
69
|
+
pipeline: [{ [customStep]: {} }],
|
|
70
|
+
func: async () => [],
|
|
71
|
+
});
|
|
72
|
+
try {
|
|
73
|
+
const report = validateClisWithTarget([], 'validate-dynamic-test/uses-custom');
|
|
74
|
+
const r = report.results[0];
|
|
75
|
+
const unknownStepWarning = r.warnings.find(w => w.includes(customStep));
|
|
76
|
+
expect(unknownStepWarning).toBeUndefined();
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
reg.delete('validate-dynamic-test/uses-custom');
|
|
80
|
+
if (original)
|
|
81
|
+
reg.set('validate-dynamic-test/uses-custom', original);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
// Best-effort cleanup of the test step. There is no `unregisterStep` —
|
|
86
|
+
// leaving it registered is harmless because the test step name is
|
|
87
|
+
// namespaced and never used outside this file.
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
package/package.json
CHANGED
|
@@ -188,7 +188,7 @@ export function fetchAdapters() {
|
|
|
188
188
|
|
|
189
189
|
// 3b. Clean up stale .yaml/.yml adapter files left by older versions (pre-1.7.0)
|
|
190
190
|
// Older versions shipped adapters as YAML; current versions use .js only.
|
|
191
|
-
// These
|
|
191
|
+
// These are no longer discoverable and can shadow the current .js adapter layout.
|
|
192
192
|
let yamlCleaned = 0;
|
|
193
193
|
for (const relPath of walkFiles(USER_CLIS_DIR)) {
|
|
194
194
|
if (relPath.endsWith('.yaml') || relPath.endsWith('.yml')) {
|