@jackwener/opencli 0.9.5 → 0.9.8

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.
Files changed (270) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +83 -0
  2. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.yml +42 -0
  4. package/.github/ISSUE_TEMPLATE/new_site_adapter.yml +57 -0
  5. package/.github/dependabot.yml +27 -0
  6. package/.github/pull_request_template.md +24 -0
  7. package/.github/workflows/ci.yml +14 -8
  8. package/.github/workflows/e2e-headed.yml +6 -2
  9. package/.github/workflows/pkg-pr-new.yml +2 -2
  10. package/.github/workflows/release-please.yml +25 -0
  11. package/.github/workflows/release.yml +2 -2
  12. package/.github/workflows/security.yml +36 -0
  13. package/CLI-ELECTRON.md +89 -36
  14. package/CONTRIBUTING.md +167 -0
  15. package/README.md +98 -32
  16. package/README.zh-CN.md +99 -33
  17. package/dist/browser/discover.js +22 -7
  18. package/dist/browser.test.js +23 -0
  19. package/dist/build-manifest.d.ts +26 -0
  20. package/dist/build-manifest.js +132 -60
  21. package/dist/build-manifest.test.d.ts +1 -0
  22. package/dist/build-manifest.test.js +26 -0
  23. package/dist/cli-manifest.json +1875 -271
  24. package/dist/clis/antigravity/model.js +2 -2
  25. package/dist/clis/antigravity/send.js +2 -2
  26. package/dist/clis/bilibili/download.d.ts +10 -0
  27. package/dist/clis/bilibili/download.js +135 -0
  28. package/dist/clis/chatgpt/ask.d.ts +1 -0
  29. package/dist/clis/chatgpt/ask.js +68 -0
  30. package/dist/clis/chatgpt/send.js +11 -0
  31. package/dist/clis/chatwise/ask.d.ts +1 -0
  32. package/dist/clis/chatwise/ask.js +76 -0
  33. package/dist/clis/chatwise/export.d.ts +1 -0
  34. package/dist/clis/chatwise/export.js +46 -0
  35. package/dist/clis/chatwise/history.d.ts +1 -0
  36. package/dist/clis/chatwise/history.js +43 -0
  37. package/dist/clis/chatwise/model.d.ts +1 -0
  38. package/dist/clis/chatwise/model.js +81 -0
  39. package/dist/clis/chatwise/new.d.ts +1 -0
  40. package/dist/clis/chatwise/new.js +18 -0
  41. package/dist/clis/chatwise/read.d.ts +1 -0
  42. package/dist/clis/chatwise/read.js +39 -0
  43. package/dist/clis/chatwise/screenshot.d.ts +1 -0
  44. package/dist/clis/chatwise/screenshot.js +27 -0
  45. package/dist/clis/chatwise/send.d.ts +1 -0
  46. package/dist/clis/chatwise/send.js +45 -0
  47. package/dist/clis/chatwise/status.d.ts +1 -0
  48. package/dist/clis/chatwise/status.js +22 -0
  49. package/dist/clis/codex/ask.d.ts +1 -0
  50. package/dist/clis/codex/ask.js +67 -0
  51. package/dist/clis/codex/export.d.ts +1 -0
  52. package/dist/clis/codex/export.js +37 -0
  53. package/dist/clis/codex/history.d.ts +1 -0
  54. package/dist/clis/codex/history.js +43 -0
  55. package/dist/clis/codex/read.js +3 -5
  56. package/dist/clis/codex/screenshot.d.ts +1 -0
  57. package/dist/clis/codex/screenshot.js +27 -0
  58. package/dist/clis/codex/send.js +3 -6
  59. package/dist/clis/codex/status.js +2 -1
  60. package/dist/clis/cursor/ask.d.ts +1 -0
  61. package/dist/clis/cursor/ask.js +69 -0
  62. package/dist/clis/cursor/composer.js +9 -28
  63. package/dist/clis/cursor/export.d.ts +1 -0
  64. package/dist/clis/cursor/export.js +51 -0
  65. package/dist/clis/cursor/history.d.ts +1 -0
  66. package/dist/clis/cursor/history.js +43 -0
  67. package/dist/clis/cursor/new.js +4 -13
  68. package/dist/clis/cursor/screenshot.d.ts +1 -0
  69. package/dist/clis/cursor/screenshot.js +31 -0
  70. package/dist/clis/discord-app/channels.d.ts +1 -0
  71. package/dist/clis/discord-app/channels.js +45 -0
  72. package/dist/clis/discord-app/members.d.ts +1 -0
  73. package/dist/clis/discord-app/members.js +38 -0
  74. package/dist/clis/discord-app/read.d.ts +1 -0
  75. package/dist/clis/discord-app/read.js +45 -0
  76. package/dist/clis/discord-app/search.d.ts +1 -0
  77. package/dist/clis/discord-app/search.js +56 -0
  78. package/dist/clis/discord-app/send.d.ts +1 -0
  79. package/dist/clis/discord-app/send.js +27 -0
  80. package/dist/clis/discord-app/servers.d.ts +1 -0
  81. package/dist/clis/discord-app/servers.js +36 -0
  82. package/dist/clis/discord-app/status.d.ts +1 -0
  83. package/dist/clis/discord-app/status.js +16 -0
  84. package/dist/clis/feishu/new.d.ts +1 -0
  85. package/dist/clis/feishu/new.js +27 -0
  86. package/dist/clis/feishu/read.d.ts +1 -0
  87. package/dist/clis/feishu/read.js +40 -0
  88. package/dist/clis/feishu/search.d.ts +1 -0
  89. package/dist/clis/feishu/search.js +30 -0
  90. package/dist/clis/feishu/send.d.ts +1 -0
  91. package/dist/clis/feishu/send.js +39 -0
  92. package/dist/clis/feishu/status.d.ts +1 -0
  93. package/dist/clis/feishu/status.js +28 -0
  94. package/dist/clis/grok/ask.d.ts +1 -0
  95. package/dist/clis/grok/ask.js +82 -0
  96. package/dist/clis/grok/debug.d.ts +1 -0
  97. package/dist/clis/grok/debug.js +45 -0
  98. package/dist/clis/jimeng/generate.yaml +84 -0
  99. package/dist/clis/jimeng/history.yaml +47 -0
  100. package/dist/clis/linux-do/categories.yaml +41 -0
  101. package/dist/clis/linux-do/category.yaml +49 -0
  102. package/dist/clis/linux-do/hot.yaml +50 -0
  103. package/dist/clis/linux-do/latest.yaml +40 -0
  104. package/dist/clis/linux-do/search.yaml +45 -0
  105. package/dist/clis/linux-do/topic.yaml +38 -0
  106. package/dist/clis/notion/export.d.ts +1 -0
  107. package/dist/clis/notion/export.js +31 -0
  108. package/dist/clis/notion/favorites.d.ts +1 -0
  109. package/dist/clis/notion/favorites.js +84 -0
  110. package/dist/clis/notion/new.d.ts +1 -0
  111. package/dist/clis/notion/new.js +34 -0
  112. package/dist/clis/notion/read.d.ts +1 -0
  113. package/dist/clis/notion/read.js +30 -0
  114. package/dist/clis/notion/search.d.ts +1 -0
  115. package/dist/clis/notion/search.js +46 -0
  116. package/dist/clis/notion/sidebar.d.ts +1 -0
  117. package/dist/clis/notion/sidebar.js +41 -0
  118. package/dist/clis/notion/status.d.ts +1 -0
  119. package/dist/clis/notion/status.js +16 -0
  120. package/dist/clis/notion/write.d.ts +1 -0
  121. package/dist/clis/notion/write.js +40 -0
  122. package/dist/clis/twitter/download.d.ts +8 -0
  123. package/dist/clis/twitter/download.js +204 -0
  124. package/dist/clis/wechat/chats.d.ts +1 -0
  125. package/dist/clis/wechat/chats.js +28 -0
  126. package/dist/clis/wechat/contacts.d.ts +1 -0
  127. package/dist/clis/wechat/contacts.js +28 -0
  128. package/dist/clis/wechat/read.d.ts +1 -0
  129. package/dist/clis/wechat/read.js +58 -0
  130. package/dist/clis/wechat/search.d.ts +1 -0
  131. package/dist/clis/wechat/search.js +31 -0
  132. package/dist/clis/wechat/send.d.ts +1 -0
  133. package/dist/clis/wechat/send.js +42 -0
  134. package/dist/clis/wechat/status.d.ts +1 -0
  135. package/dist/clis/wechat/status.js +29 -0
  136. package/dist/clis/xiaohongshu/creator-note-detail.d.ts +10 -0
  137. package/dist/clis/xiaohongshu/creator-note-detail.js +88 -0
  138. package/dist/clis/xiaohongshu/creator-notes.d.ts +11 -0
  139. package/dist/clis/xiaohongshu/creator-notes.js +109 -0
  140. package/dist/clis/xiaohongshu/creator-profile.d.ts +10 -0
  141. package/dist/clis/xiaohongshu/creator-profile.js +54 -0
  142. package/dist/clis/xiaohongshu/creator-stats.d.ts +10 -0
  143. package/dist/clis/xiaohongshu/creator-stats.js +74 -0
  144. package/dist/clis/xiaohongshu/download.d.ts +7 -0
  145. package/dist/clis/xiaohongshu/download.js +155 -0
  146. package/dist/clis/xiaohongshu/search.js +1 -1
  147. package/dist/clis/xiaohongshu/user-helpers.d.ts +15 -0
  148. package/dist/clis/xiaohongshu/user-helpers.js +67 -0
  149. package/dist/clis/xiaohongshu/user-helpers.test.d.ts +1 -0
  150. package/dist/clis/xiaohongshu/user-helpers.test.js +81 -0
  151. package/dist/clis/xiaohongshu/user.js +46 -29
  152. package/dist/clis/zhihu/download.d.ts +11 -0
  153. package/dist/clis/zhihu/download.js +186 -0
  154. package/dist/clis/zhihu/download.test.d.ts +1 -0
  155. package/dist/clis/zhihu/download.test.js +10 -0
  156. package/dist/download/index.d.ts +79 -0
  157. package/dist/download/index.js +325 -0
  158. package/dist/download/progress.d.ts +36 -0
  159. package/dist/download/progress.js +111 -0
  160. package/dist/engine.test.js +15 -0
  161. package/dist/main.js +16 -3
  162. package/dist/pipeline/registry.js +2 -0
  163. package/dist/pipeline/steps/download.d.ts +34 -0
  164. package/dist/pipeline/steps/download.js +251 -0
  165. package/dist/pipeline/template.js +28 -0
  166. package/package.json +4 -3
  167. package/scripts/test-site.mjs +70 -0
  168. package/src/browser/discover.ts +23 -7
  169. package/src/browser.test.ts +23 -0
  170. package/src/build-manifest.test.ts +28 -0
  171. package/src/build-manifest.ts +147 -57
  172. package/src/clis/antigravity/README.md +2 -3
  173. package/src/clis/antigravity/README.zh-CN.md +2 -3
  174. package/src/clis/antigravity/SKILL.md +1 -1
  175. package/src/clis/antigravity/model.ts +2 -2
  176. package/src/clis/antigravity/send.ts +2 -2
  177. package/src/clis/bilibili/download.ts +161 -0
  178. package/src/clis/chatgpt/README.md +25 -16
  179. package/src/clis/chatgpt/README.zh-CN.md +27 -18
  180. package/src/clis/chatgpt/ask.ts +77 -0
  181. package/src/clis/chatgpt/send.ts +12 -0
  182. package/src/clis/chatwise/README.md +38 -0
  183. package/src/clis/chatwise/README.zh-CN.md +38 -0
  184. package/src/clis/chatwise/ask.ts +87 -0
  185. package/src/clis/chatwise/export.ts +51 -0
  186. package/src/clis/chatwise/history.ts +47 -0
  187. package/src/clis/chatwise/model.ts +87 -0
  188. package/src/clis/chatwise/new.ts +21 -0
  189. package/src/clis/chatwise/read.ts +42 -0
  190. package/src/clis/chatwise/screenshot.ts +33 -0
  191. package/src/clis/chatwise/send.ts +50 -0
  192. package/src/clis/chatwise/status.ts +25 -0
  193. package/src/clis/codex/ask.ts +77 -0
  194. package/src/clis/codex/export.ts +42 -0
  195. package/src/clis/codex/extract-diff.ts +1 -0
  196. package/src/clis/codex/history.ts +47 -0
  197. package/src/clis/codex/read.ts +5 -6
  198. package/src/clis/codex/screenshot.ts +33 -0
  199. package/src/clis/codex/send.ts +6 -7
  200. package/src/clis/codex/status.ts +4 -2
  201. package/src/clis/cursor/ask.ts +81 -0
  202. package/src/clis/cursor/composer.ts +9 -30
  203. package/src/clis/cursor/export.ts +57 -0
  204. package/src/clis/cursor/history.ts +47 -0
  205. package/src/clis/cursor/new.ts +4 -15
  206. package/src/clis/cursor/screenshot.ts +38 -0
  207. package/src/clis/discord-app/README.md +28 -0
  208. package/src/clis/discord-app/README.zh-CN.md +28 -0
  209. package/src/clis/discord-app/channels.ts +48 -0
  210. package/src/clis/discord-app/members.ts +41 -0
  211. package/src/clis/discord-app/read.ts +49 -0
  212. package/src/clis/discord-app/search.ts +64 -0
  213. package/src/clis/discord-app/send.ts +32 -0
  214. package/src/clis/discord-app/servers.ts +39 -0
  215. package/src/clis/discord-app/status.ts +18 -0
  216. package/src/clis/feishu/README.md +20 -0
  217. package/src/clis/feishu/README.zh-CN.md +20 -0
  218. package/src/clis/feishu/new.ts +32 -0
  219. package/src/clis/feishu/read.ts +48 -0
  220. package/src/clis/feishu/search.ts +35 -0
  221. package/src/clis/feishu/send.ts +46 -0
  222. package/src/clis/feishu/status.ts +34 -0
  223. package/src/clis/grok/ask.ts +90 -0
  224. package/src/clis/grok/debug.ts +49 -0
  225. package/src/clis/jimeng/generate.yaml +84 -0
  226. package/src/clis/jimeng/history.yaml +47 -0
  227. package/src/clis/linux-do/categories.yaml +41 -0
  228. package/src/clis/linux-do/category.yaml +49 -0
  229. package/src/clis/linux-do/hot.yaml +50 -0
  230. package/src/clis/linux-do/latest.yaml +40 -0
  231. package/src/clis/linux-do/search.yaml +45 -0
  232. package/src/clis/linux-do/topic.yaml +38 -0
  233. package/src/clis/notion/README.md +29 -0
  234. package/src/clis/notion/README.zh-CN.md +29 -0
  235. package/src/clis/notion/export.ts +36 -0
  236. package/src/clis/notion/favorites.ts +87 -0
  237. package/src/clis/notion/new.ts +39 -0
  238. package/src/clis/notion/read.ts +33 -0
  239. package/src/clis/notion/search.ts +54 -0
  240. package/src/clis/notion/sidebar.ts +44 -0
  241. package/src/clis/notion/status.ts +18 -0
  242. package/src/clis/notion/write.ts +45 -0
  243. package/src/clis/twitter/download.ts +227 -0
  244. package/src/clis/wechat/README.md +28 -0
  245. package/src/clis/wechat/README.zh-CN.md +28 -0
  246. package/src/clis/wechat/chats.ts +33 -0
  247. package/src/clis/wechat/contacts.ts +33 -0
  248. package/src/clis/wechat/read.ts +72 -0
  249. package/src/clis/wechat/search.ts +36 -0
  250. package/src/clis/wechat/send.ts +49 -0
  251. package/src/clis/wechat/status.ts +35 -0
  252. package/src/clis/xiaohongshu/creator-note-detail.ts +95 -0
  253. package/src/clis/xiaohongshu/creator-notes.ts +116 -0
  254. package/src/clis/xiaohongshu/creator-profile.ts +60 -0
  255. package/src/clis/xiaohongshu/creator-stats.ts +81 -0
  256. package/src/clis/xiaohongshu/download.ts +173 -0
  257. package/src/clis/xiaohongshu/search.ts +1 -1
  258. package/src/clis/xiaohongshu/user-helpers.test.ts +106 -0
  259. package/src/clis/xiaohongshu/user-helpers.ts +85 -0
  260. package/src/clis/xiaohongshu/user.ts +52 -32
  261. package/src/clis/zhihu/download.test.ts +12 -0
  262. package/src/clis/zhihu/download.ts +223 -0
  263. package/src/download/index.ts +395 -0
  264. package/src/download/progress.ts +125 -0
  265. package/src/engine.test.ts +17 -0
  266. package/src/main.ts +12 -3
  267. package/src/pipeline/registry.ts +2 -0
  268. package/src/pipeline/steps/download.ts +310 -0
  269. package/src/pipeline/template.ts +26 -0
  270. package/tests/e2e/browser-auth.test.ts +25 -0
@@ -10,11 +10,108 @@
10
10
  */
11
11
  import * as fs from 'node:fs';
12
12
  import * as path from 'node:path';
13
- import { fileURLToPath } from 'node:url';
13
+ import { fileURLToPath, pathToFileURL } from 'node:url';
14
14
  import yaml from 'js-yaml';
15
15
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
16
16
  const CLIS_DIR = path.resolve(__dirname, 'clis');
17
17
  const OUTPUT = path.resolve(__dirname, '..', 'dist', 'cli-manifest.json');
18
+ function extractBalancedBlock(source, startIndex, openChar, closeChar) {
19
+ let depth = 0;
20
+ let quote = null;
21
+ let escaped = false;
22
+ for (let i = startIndex; i < source.length; i++) {
23
+ const ch = source[i];
24
+ if (quote) {
25
+ if (escaped) {
26
+ escaped = false;
27
+ continue;
28
+ }
29
+ if (ch === '\\') {
30
+ escaped = true;
31
+ continue;
32
+ }
33
+ if (ch === quote)
34
+ quote = null;
35
+ continue;
36
+ }
37
+ if (ch === '"' || ch === '\'' || ch === '`') {
38
+ quote = ch;
39
+ continue;
40
+ }
41
+ if (ch === openChar) {
42
+ depth++;
43
+ }
44
+ else if (ch === closeChar) {
45
+ depth--;
46
+ if (depth === 0) {
47
+ return source.slice(startIndex + 1, i);
48
+ }
49
+ }
50
+ }
51
+ return null;
52
+ }
53
+ function extractTsArgsBlock(source) {
54
+ const argsMatch = source.match(/args\s*:/);
55
+ if (!argsMatch || argsMatch.index === undefined)
56
+ return null;
57
+ const bracketIndex = source.indexOf('[', argsMatch.index);
58
+ if (bracketIndex === -1)
59
+ return null;
60
+ return extractBalancedBlock(source, bracketIndex, '[', ']');
61
+ }
62
+ function parseInlineChoices(body) {
63
+ const choicesMatch = body.match(/choices\s*:\s*\[([^\]]*)\]/);
64
+ if (!choicesMatch)
65
+ return undefined;
66
+ const values = choicesMatch[1]
67
+ .split(',')
68
+ .map(s => s.trim().replace(/^['"`]|['"`]$/g, ''))
69
+ .filter(Boolean);
70
+ return values.length > 0 ? values : undefined;
71
+ }
72
+ export function parseTsArgsBlock(argsBlock) {
73
+ const args = [];
74
+ let cursor = 0;
75
+ while (cursor < argsBlock.length) {
76
+ const nameMatch = argsBlock.slice(cursor).match(/\{\s*name\s*:\s*['"`](\w+)['"`]/);
77
+ if (!nameMatch || nameMatch.index === undefined)
78
+ break;
79
+ const objectStart = cursor + nameMatch.index;
80
+ const body = extractBalancedBlock(argsBlock, objectStart, '{', '}');
81
+ if (body == null)
82
+ break;
83
+ const typeMatch = body.match(/type\s*:\s*['"`](\w+)['"`]/);
84
+ const defaultMatch = body.match(/default\s*:\s*([^,}]+)/);
85
+ const requiredMatch = body.match(/required\s*:\s*(true|false)/);
86
+ const helpMatch = body.match(/help\s*:\s*['"`]([^'"`]*)['"`]/);
87
+ const positionalMatch = body.match(/positional\s*:\s*(true|false)/);
88
+ let defaultVal = undefined;
89
+ if (defaultMatch) {
90
+ const raw = defaultMatch[1].trim();
91
+ if (raw === 'true')
92
+ defaultVal = true;
93
+ else if (raw === 'false')
94
+ defaultVal = false;
95
+ else if (/^\d+$/.test(raw))
96
+ defaultVal = parseInt(raw, 10);
97
+ else if (/^\d+\.\d+$/.test(raw))
98
+ defaultVal = parseFloat(raw);
99
+ else
100
+ defaultVal = raw.replace(/^['"`]|['"`]$/g, '');
101
+ }
102
+ args.push({
103
+ name: nameMatch[1],
104
+ type: typeMatch?.[1] ?? 'str',
105
+ default: defaultVal,
106
+ required: requiredMatch?.[1] === 'true',
107
+ positional: positionalMatch?.[1] === 'true' || undefined,
108
+ help: helpMatch?.[1] ?? '',
109
+ choices: parseInlineChoices(body),
110
+ });
111
+ cursor = objectStart + body.length + 2;
112
+ }
113
+ return args;
114
+ }
18
115
  function scanYaml(filePath, site) {
19
116
  try {
20
117
  const raw = fs.readFileSync(filePath, 'utf-8');
@@ -95,42 +192,9 @@ function scanTs(filePath, site) {
95
192
  entry.columns = colMatch[1].split(',').map(s => s.trim().replace(/^['"`]|['"`]$/g, '')).filter(Boolean);
96
193
  }
97
194
  // Extract args array items: { name: '...', ... }
98
- const argsBlockMatch = src.match(/args\s*:\s*\[([\s\S]*?)\]\s*,/);
99
- if (argsBlockMatch) {
100
- const argsBlock = argsBlockMatch[1];
101
- const argRegex = /\{\s*name\s*:\s*['"`](\w+)['"`]([^}]*)\}/g;
102
- let m;
103
- while ((m = argRegex.exec(argsBlock)) !== null) {
104
- const argName = m[1];
105
- const body = m[2];
106
- const typeMatch = body.match(/type\s*:\s*['"`](\w+)['"`]/);
107
- const defaultMatch = body.match(/default\s*:\s*([^,}]+)/);
108
- const requiredMatch = body.match(/required\s*:\s*(true|false)/);
109
- const helpMatch = body.match(/help\s*:\s*['"`]([^'"`]*)['"`]/);
110
- const positionalMatch = body.match(/positional\s*:\s*(true|false)/);
111
- let defaultVal = undefined;
112
- if (defaultMatch) {
113
- const raw = defaultMatch[1].trim();
114
- if (raw === 'true')
115
- defaultVal = true;
116
- else if (raw === 'false')
117
- defaultVal = false;
118
- else if (/^\d+$/.test(raw))
119
- defaultVal = parseInt(raw, 10);
120
- else if (/^\d+\.\d+$/.test(raw))
121
- defaultVal = parseFloat(raw);
122
- else
123
- defaultVal = raw.replace(/^['"`]|['"`]$/g, '');
124
- }
125
- entry.args.push({
126
- name: argName,
127
- type: typeMatch?.[1] ?? 'str',
128
- default: defaultVal,
129
- required: requiredMatch?.[1] === 'true',
130
- positional: positionalMatch?.[1] === 'true' || undefined,
131
- help: helpMatch?.[1] ?? '',
132
- });
133
- }
195
+ const argsBlock = extractTsArgsBlock(src);
196
+ if (argsBlock) {
197
+ entry.args = parseTsArgsBlock(argsBlock);
134
198
  }
135
199
  }
136
200
  catch {
@@ -138,30 +202,38 @@ function scanTs(filePath, site) {
138
202
  }
139
203
  return entry;
140
204
  }
141
- // Main
142
- const manifest = [];
143
- if (fs.existsSync(CLIS_DIR)) {
144
- for (const site of fs.readdirSync(CLIS_DIR)) {
145
- const siteDir = path.join(CLIS_DIR, site);
146
- if (!fs.statSync(siteDir).isDirectory())
147
- continue;
148
- for (const file of fs.readdirSync(siteDir)) {
149
- const filePath = path.join(siteDir, file);
150
- if (file.endsWith('.yaml') || file.endsWith('.yml')) {
151
- const entry = scanYaml(filePath, site);
152
- if (entry)
153
- manifest.push(entry);
154
- }
155
- else if ((file.endsWith('.ts') && !file.endsWith('.d.ts') && file !== 'index.ts') ||
156
- (file.endsWith('.js') && !file.endsWith('.d.js') && file !== 'index.js')) {
157
- manifest.push(scanTs(filePath, site));
205
+ export function buildManifest() {
206
+ const manifest = [];
207
+ if (fs.existsSync(CLIS_DIR)) {
208
+ for (const site of fs.readdirSync(CLIS_DIR)) {
209
+ const siteDir = path.join(CLIS_DIR, site);
210
+ if (!fs.statSync(siteDir).isDirectory())
211
+ continue;
212
+ for (const file of fs.readdirSync(siteDir)) {
213
+ const filePath = path.join(siteDir, file);
214
+ if (file.endsWith('.yaml') || file.endsWith('.yml')) {
215
+ const entry = scanYaml(filePath, site);
216
+ if (entry)
217
+ manifest.push(entry);
218
+ }
219
+ else if ((file.endsWith('.ts') && !file.endsWith('.d.ts') && file !== 'index.ts') ||
220
+ (file.endsWith('.js') && !file.endsWith('.d.js') && file !== 'index.js')) {
221
+ manifest.push(scanTs(filePath, site));
222
+ }
158
223
  }
159
224
  }
160
225
  }
226
+ return manifest;
227
+ }
228
+ function main() {
229
+ const manifest = buildManifest();
230
+ fs.mkdirSync(path.dirname(OUTPUT), { recursive: true });
231
+ fs.writeFileSync(OUTPUT, JSON.stringify(manifest, null, 2));
232
+ const yamlCount = manifest.filter(e => e.type === 'yaml').length;
233
+ const tsCount = manifest.filter(e => e.type === 'ts').length;
234
+ console.log(`✅ Manifest compiled: ${manifest.length} entries (${yamlCount} YAML, ${tsCount} TS) → ${OUTPUT}`);
235
+ }
236
+ const entrypoint = process.argv[1] ? pathToFileURL(path.resolve(process.argv[1])).href : null;
237
+ if (entrypoint === import.meta.url) {
238
+ main();
161
239
  }
162
- // Ensure output directory exists
163
- fs.mkdirSync(path.dirname(OUTPUT), { recursive: true });
164
- fs.writeFileSync(OUTPUT, JSON.stringify(manifest, null, 2));
165
- const yamlCount = manifest.filter(e => e.type === 'yaml').length;
166
- const tsCount = manifest.filter(e => e.type === 'ts').length;
167
- console.log(`✅ Manifest compiled: ${manifest.length} entries (${yamlCount} YAML, ${tsCount} TS) → ${OUTPUT}`);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { parseTsArgsBlock } from './build-manifest.js';
3
+ describe('parseTsArgsBlock', () => {
4
+ it('keeps args with nested choices arrays', () => {
5
+ const args = parseTsArgsBlock(`
6
+ {
7
+ name: 'period',
8
+ type: 'string',
9
+ default: 'seven',
10
+ help: 'Stats period: seven or thirty',
11
+ choices: ['seven', 'thirty'],
12
+ },
13
+ `);
14
+ expect(args).toEqual([
15
+ {
16
+ name: 'period',
17
+ type: 'string',
18
+ default: 'seven',
19
+ required: false,
20
+ positional: undefined,
21
+ help: 'Stats period: seven or thirty',
22
+ choices: ['seven', 'thirty'],
23
+ },
24
+ ]);
25
+ });
26
+ });