@hasna/skills 0.1.62 → 0.1.64

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 (541) hide show
  1. package/README.md +38 -12
  2. package/bin/index.js +15743 -21709
  3. package/bin/mcp.js +3866 -11522
  4. package/bin/migrate.js +281 -35
  5. package/bin/server.js +5805 -2682
  6. package/bin/worker.js +5280 -2388
  7. package/dist/cli/commands/publish.d.ts +2 -0
  8. package/dist/cli/commands/registry-reconcile.d.ts +2 -0
  9. package/dist/cli/components/App.d.ts +2 -1
  10. package/dist/cli/components/CategorySelect.d.ts +2 -1
  11. package/dist/cli/components/Header.d.ts +2 -1
  12. package/dist/cli/components/InstallProgress.d.ts +2 -1
  13. package/dist/cli/components/SearchView.d.ts +2 -1
  14. package/dist/cli/components/SkillSelect.d.ts +2 -1
  15. package/dist/index.d.ts +5 -2
  16. package/dist/index.js +5386 -13739
  17. package/dist/lib/agent-sync.d.ts +61 -6
  18. package/dist/lib/auth-store.d.ts +37 -0
  19. package/dist/lib/config.d.ts +51 -0
  20. package/dist/lib/home-adoption.d.ts +91 -0
  21. package/dist/lib/home-census.d.ts +26 -0
  22. package/dist/lib/home-migration.d.ts +60 -0
  23. package/dist/lib/native-storage.d.ts +1 -1
  24. package/dist/lib/portable-skills-files.d.ts +21 -1
  25. package/dist/lib/portable-skills-types.d.ts +46 -0
  26. package/dist/lib/portable-skills.d.ts +35 -6
  27. package/dist/lib/pull.d.ts +97 -0
  28. package/dist/lib/registry-reconcile.d.ts +114 -0
  29. package/dist/lib/registry.d.ts +7 -4
  30. package/dist/lib/remote-client.d.ts +124 -1
  31. package/dist/lib/remote-registry.d.ts +26 -0
  32. package/dist/lib/revision.d.ts +29 -0
  33. package/dist/lib/run-state.d.ts +5 -0
  34. package/dist/lib/skill-bundles.d.ts +54 -0
  35. package/dist/lib/skill-contract.d.ts +35 -0
  36. package/dist/lib/skill-hash.d.ts +77 -0
  37. package/dist/sdk/cancel.d.ts +30 -0
  38. package/dist/sdk/dispatcher.d.ts +40 -0
  39. package/dist/sdk/event-sink.d.ts +2 -0
  40. package/dist/sdk/events.d.ts +79 -0
  41. package/dist/sdk/execution/admission.d.ts +44 -0
  42. package/dist/sdk/execution/dispatchers/e2b.d.ts +17 -0
  43. package/dist/sdk/execution/dispatchers/ecs.d.ts +151 -0
  44. package/dist/sdk/execution/image-profile.d.ts +73 -0
  45. package/dist/sdk/execution/index.d.ts +15 -0
  46. package/dist/sdk/execution/receipts.d.ts +44 -0
  47. package/dist/sdk/execution/state-machine.d.ts +38 -0
  48. package/dist/sdk/execution/storage.d.ts +158 -0
  49. package/dist/sdk/execution/types.d.ts +130 -0
  50. package/dist/sdk/executor.d.ts +17 -0
  51. package/dist/sdk/governance-store.d.ts +156 -0
  52. package/dist/sdk/governance.d.ts +92 -0
  53. package/dist/sdk/index.d.ts +26 -0
  54. package/dist/sdk/index.js +49728 -0
  55. package/dist/sdk/offline.d.ts +16 -0
  56. package/dist/sdk/outputs.d.ts +71 -0
  57. package/dist/sdk/registry.d.ts +28 -0
  58. package/dist/sdk/runs.d.ts +229 -0
  59. package/dist/sdk/server.d.ts +35 -0
  60. package/dist/sdk/spend.d.ts +36 -0
  61. package/dist/sdk/storage.d.ts +25 -0
  62. package/dist/server/app.d.ts +42 -0
  63. package/dist/server/artifact-storage.d.ts +102 -0
  64. package/dist/server/auth.d.ts +5 -0
  65. package/dist/server/config.d.ts +50 -0
  66. package/dist/server/database-url.d.ts +42 -0
  67. package/dist/server/handlers.d.ts +3 -0
  68. package/dist/server/index.d.ts +2 -0
  69. package/dist/server/migrate.d.ts +13 -0
  70. package/dist/server/migrations-dir.d.ts +18 -0
  71. package/dist/server/redaction.d.ts +1 -0
  72. package/dist/server/registry.d.ts +5 -0
  73. package/dist/server/rows.d.ts +24 -0
  74. package/dist/server/skills-api.d.ts +170 -0
  75. package/dist/server/sqlite-store.d.ts +131 -0
  76. package/dist/server/store-fixtures.d.ts +25 -0
  77. package/dist/server/store.d.ts +170 -0
  78. package/dist/server/types.d.ts +337 -0
  79. package/dist/server/worker.d.ts +4 -0
  80. package/dist/storage.js +39 -2
  81. package/docs/skill-standard.md +211 -39
  82. package/migrations/postgres/0003_run_outputs_governance.sql +83 -0
  83. package/migrations/postgres/0004_hosted_pins.sql +28 -0
  84. package/migrations/postgres/0005_revision_tombstone_registry.sql +37 -0
  85. package/migrations/postgres/0005_tag_projection.sql +36 -0
  86. package/migrations/sqlite/0003_run_outputs_governance.sql +58 -0
  87. package/migrations/sqlite/0004_hosted_pins.sql +21 -0
  88. package/migrations/sqlite/0005_revision_tombstone_registry.sql +18 -0
  89. package/migrations/sqlite/0005_tag_projection.sql +25 -0
  90. package/package.json +12 -8
  91. package/schemas/skill.schema.json +181 -0
  92. package/agent-skills/README.md +0 -41
  93. package/agent-skills/fleet-package-rollout/SKILL.md +0 -169
  94. package/agent-skills/inbox/SKILL.md +0 -25
  95. package/agent-skills/inbox/scripts/inbox +0 -109
  96. package/agent-skills/inbox/tests/test_registered_sender_id.sh +0 -92
  97. package/agent-skills/inbox-monitor/SKILL.md +0 -41
  98. package/agent-skills/inbox-monitor/scripts/inbox_monitor.sh +0 -91
  99. package/agent-skills/inbox-monitor/scripts/test_inbox_monitor.sh +0 -71
  100. package/agent-skills/merge-pr/SKILL.md +0 -85
  101. package/agent-skills/merge-pr/references/merge-safety.md +0 -82
  102. package/agent-skills/merge-pr/scripts/merge_pr_guard.py +0 -694
  103. package/agent-skills/merge-pr/scripts/test_merge_pr_guard.py +0 -647
  104. package/agent-skills/merge-pr/tests/fixtures/multi-commit-synthesized.json +0 -28
  105. package/agent-skills/merge-pr/tests/fixtures/trailer-free-provider.json +0 -28
  106. package/agent-skills/skill-goal-execute/SKILL.md +0 -115
  107. package/agent-skills/skill-login/SKILL.md +0 -109
  108. package/agent-skills/skill-project-create/SKILL.md +0 -91
  109. package/agent-skills/skill-publish/SKILL.md +0 -254
  110. package/agent-skills/skill-publish/scripts/capture_registry.js +0 -47
  111. package/agent-skills/skill-publish/scripts/publish_with_git_head.sh +0 -143
  112. package/agent-skills/skill-publish/scripts/test_publish_with_git_head.sh +0 -231
  113. package/skills/_common/auth.ts +0 -45
  114. package/skills/_common/http-client.ts +0 -143
  115. package/skills/_common/index.ts +0 -26
  116. package/skills/_common/install.sh +0 -7
  117. package/skills/_common/installer.ts +0 -72
  118. package/skills/_common/skill-install.ts +0 -37
  119. package/skills/_common/vision.ts +0 -374
  120. package/skills/ad-creative-pack/SKILL.md +0 -55
  121. package/skills/ad-creative-pack/package.json +0 -10
  122. package/skills/analyze-data/CLAUDE.md +0 -16
  123. package/skills/analyze-data/SKILL.md +0 -112
  124. package/skills/analyze-data/package.json +0 -23
  125. package/skills/analyze-data/src/analysis.ts +0 -401
  126. package/skills/analyze-data/src/cli.ts +0 -66
  127. package/skills/analyze-data/src/formatters.ts +0 -235
  128. package/skills/analyze-data/src/index.ts +0 -74
  129. package/skills/analyze-data/src/logger.ts +0 -36
  130. package/skills/analyze-data/src/parsers.ts +0 -57
  131. package/skills/analyze-data/src/stats.ts +0 -151
  132. package/skills/analyze-data/src/types.ts +0 -85
  133. package/skills/analyze-data/tsconfig.json +0 -19
  134. package/skills/api-docs-portal/SKILL.md +0 -84
  135. package/skills/api-docs-portal/package.json +0 -35
  136. package/skills/api-docs-portal/src/index.ts +0 -919
  137. package/skills/api-docs-portal/tsconfig.json +0 -17
  138. package/skills/api-test-suite/CLAUDE.md +0 -19
  139. package/skills/api-test-suite/package.json +0 -27
  140. package/skills/api-test-suite/src/index.ts +0 -381
  141. package/skills/api-test-suite/tsconfig.json +0 -10
  142. package/skills/audio-extract/CLAUDE.md +0 -9
  143. package/skills/audio-extract/SKILL.md +0 -73
  144. package/skills/audio-extract/package.json +0 -23
  145. package/skills/audio-extract/src/index.ts +0 -323
  146. package/skills/audio-extract/tsconfig.json +0 -11
  147. package/skills/bio-sequence-tool/CLAUDE.md +0 -19
  148. package/skills/bio-sequence-tool/package.json +0 -27
  149. package/skills/bio-sequence-tool/src/index.ts +0 -85
  150. package/skills/bio-sequence-tool/tsconfig.json +0 -10
  151. package/skills/blog-article/CLAUDE.md +0 -12
  152. package/skills/blog-article/SKILL.md +0 -55
  153. package/skills/blog-article/package.json +0 -10
  154. package/skills/blog-article/tsconfig.json +0 -10
  155. package/skills/brand-assets/SKILL.md +0 -118
  156. package/skills/brand-assets/package.json +0 -35
  157. package/skills/brand-assets/src/cli.ts +0 -155
  158. package/skills/brand-assets/src/constants.ts +0 -8
  159. package/skills/brand-assets/src/extract.ts +0 -236
  160. package/skills/brand-assets/src/index.ts +0 -668
  161. package/skills/brand-assets/src/types.ts +0 -59
  162. package/skills/brand-assets/tsconfig.json +0 -17
  163. package/skills/brand-kit/SKILL.md +0 -54
  164. package/skills/brand-kit/package.json +0 -10
  165. package/skills/businessactivity/CLAUDE.md +0 -176
  166. package/skills/businessactivity/LICENSE +0 -192
  167. package/skills/businessactivity/README.md +0 -287
  168. package/skills/businessactivity/package.json +0 -25
  169. package/skills/businessactivity/scripts/publish.ts +0 -210
  170. package/skills/businessactivity/src/commands/activity.ts +0 -211
  171. package/skills/businessactivity/src/commands/function.ts +0 -227
  172. package/skills/businessactivity/src/commands/owner.ts +0 -193
  173. package/skills/businessactivity/src/commands/profile.ts +0 -121
  174. package/skills/businessactivity/src/commands/responsibility.ts +0 -264
  175. package/skills/businessactivity/src/commands/team.ts +0 -244
  176. package/skills/businessactivity/src/commands/workflow.ts +0 -359
  177. package/skills/businessactivity/src/index.ts +0 -3
  178. package/skills/businessactivity/src/lib/config.ts +0 -167
  179. package/skills/businessactivity/src/lib/output.ts +0 -76
  180. package/skills/businessactivity/src/lib/paths.ts +0 -79
  181. package/skills/businessactivity/src/lib/storage.ts +0 -95
  182. package/skills/businessactivity/src/types/index.ts +0 -86
  183. package/skills/businessactivity/tsconfig.json +0 -29
  184. package/skills/codefix/LICENSE +0 -192
  185. package/skills/codefix/README.md +0 -232
  186. package/skills/codefix/SKILL.md +0 -94
  187. package/skills/codefix/package.json +0 -21
  188. package/skills/codefix/src/fixers/batch.ts +0 -213
  189. package/skills/codefix/src/fixers/detector.ts +0 -160
  190. package/skills/codefix/src/fixers/index.ts +0 -7
  191. package/skills/codefix/src/fixers/runner.ts +0 -522
  192. package/skills/codefix/src/index-local.ts +0 -431
  193. package/skills/codefix/src/index.ts +0 -4
  194. package/skills/codefix/src/types.ts +0 -211
  195. package/skills/codefix/tsconfig.json +0 -15
  196. package/skills/commitpush/SKILL.md +0 -57
  197. package/skills/commitpush/package.json +0 -33
  198. package/skills/commitpush/src/index.ts +0 -34
  199. package/skills/commitpush/tsconfig.json +0 -17
  200. package/skills/commitpushpr/SKILL.md +0 -55
  201. package/skills/commitpushpr/package.json +0 -33
  202. package/skills/commitpushpr/src/index.ts +0 -34
  203. package/skills/commitpushpr/tsconfig.json +0 -17
  204. package/skills/compress-video/CLAUDE.md +0 -9
  205. package/skills/compress-video/SKILL.md +0 -79
  206. package/skills/compress-video/package.json +0 -23
  207. package/skills/compress-video/src/index.ts +0 -473
  208. package/skills/compress-video/tsconfig.json +0 -11
  209. package/skills/contract-review-report/SKILL.md +0 -52
  210. package/skills/contract-review-report/package.json +0 -10
  211. package/skills/customer-feedback-report/SKILL.md +0 -52
  212. package/skills/customer-feedback-report/package.json +0 -10
  213. package/skills/dashboard-builder/CLAUDE.md +0 -19
  214. package/skills/dashboard-builder/package.json +0 -29
  215. package/skills/dashboard-builder/src/index.ts +0 -150
  216. package/skills/dashboard-builder/tsconfig.json +0 -10
  217. package/skills/data-anonymizer/CLAUDE.md +0 -19
  218. package/skills/data-anonymizer/package.json +0 -27
  219. package/skills/data-anonymizer/src/index.ts +0 -183
  220. package/skills/data-anonymizer/tsconfig.json +0 -10
  221. package/skills/database-explorer/CLAUDE.md +0 -19
  222. package/skills/database-explorer/package.json +0 -29
  223. package/skills/database-explorer/src/index.ts +0 -95
  224. package/skills/database-explorer/tsconfig.json +0 -10
  225. package/skills/diff-viewer/CLAUDE.md +0 -19
  226. package/skills/diff-viewer/package.json +0 -30
  227. package/skills/diff-viewer/src/index.ts +0 -164
  228. package/skills/diff-viewer/tsconfig.json +0 -10
  229. package/skills/doc-read/SKILL.md +0 -45
  230. package/skills/doc-read/package.json +0 -29
  231. package/skills/doc-read/src/index.ts +0 -324
  232. package/skills/doc-read/tsconfig.json +0 -8
  233. package/skills/domainpurchase/LICENSE +0 -192
  234. package/skills/domainpurchase/SKILL.md +0 -29
  235. package/skills/domainpurchase/package.json +0 -30
  236. package/skills/domainpurchase/src/index.ts +0 -3
  237. package/skills/domainpurchase/tsconfig.json +0 -21
  238. package/skills/email-sequence/SKILL.md +0 -53
  239. package/skills/email-sequence/package.json +0 -10
  240. package/skills/experiment-power-calculator/CLAUDE.md +0 -19
  241. package/skills/experiment-power-calculator/package.json +0 -29
  242. package/skills/experiment-power-calculator/src/index.ts +0 -86
  243. package/skills/experiment-power-calculator/tsconfig.json +0 -10
  244. package/skills/extract-frames/CLAUDE.md +0 -19
  245. package/skills/extract-frames/package.json +0 -27
  246. package/skills/extract-frames/src/index.ts +0 -616
  247. package/skills/extract-frames/tsconfig.json +0 -10
  248. package/skills/file-organizer/CLAUDE.md +0 -19
  249. package/skills/file-organizer/package.json +0 -27
  250. package/skills/file-organizer/src/index.ts +0 -91
  251. package/skills/file-organizer/tsconfig.json +0 -10
  252. package/skills/folder-tree/CLAUDE.md +0 -19
  253. package/skills/folder-tree/package.json +0 -29
  254. package/skills/folder-tree/src/index.ts +0 -568
  255. package/skills/folder-tree/tsconfig.json +0 -10
  256. package/skills/form-filler/CLAUDE.md +0 -19
  257. package/skills/form-filler/package.json +0 -29
  258. package/skills/form-filler/src/index.ts +0 -81
  259. package/skills/form-filler/tsconfig.json +0 -10
  260. package/skills/generate-api-client/CLAUDE.md +0 -19
  261. package/skills/generate-api-client/package.json +0 -29
  262. package/skills/generate-api-client/src/generator.ts +0 -47
  263. package/skills/generate-api-client/src/index.ts +0 -92
  264. package/skills/generate-api-client/src/logger.ts +0 -34
  265. package/skills/generate-api-client/src/python-generator.ts +0 -245
  266. package/skills/generate-api-client/src/spec-loader.ts +0 -48
  267. package/skills/generate-api-client/src/type-mappers.ts +0 -79
  268. package/skills/generate-api-client/src/types.ts +0 -76
  269. package/skills/generate-api-client/src/typescript-generator.ts +0 -247
  270. package/skills/generate-api-client/tsconfig.json +0 -10
  271. package/skills/generate-chart/CLAUDE.md +0 -19
  272. package/skills/generate-chart/package.json +0 -27
  273. package/skills/generate-chart/src/index.ts +0 -510
  274. package/skills/generate-chart/tsconfig.json +0 -10
  275. package/skills/generate-dockerfile/CLAUDE.md +0 -19
  276. package/skills/generate-dockerfile/package.json +0 -27
  277. package/skills/generate-dockerfile/src/cli.ts +0 -78
  278. package/skills/generate-dockerfile/src/dockerfile-templates.ts +0 -392
  279. package/skills/generate-dockerfile/src/index.ts +0 -81
  280. package/skills/generate-dockerfile/src/logger.ts +0 -30
  281. package/skills/generate-dockerfile/src/project-detection.ts +0 -68
  282. package/skills/generate-dockerfile/src/support-files.ts +0 -171
  283. package/skills/generate-dockerfile/src/types.ts +0 -29
  284. package/skills/generate-dockerfile/tsconfig.json +0 -10
  285. package/skills/generate-env/CLAUDE.md +0 -19
  286. package/skills/generate-env/package.json +0 -29
  287. package/skills/generate-env/src/cli.ts +0 -85
  288. package/skills/generate-env/src/detection.ts +0 -161
  289. package/skills/generate-env/src/env-data.ts +0 -66
  290. package/skills/generate-env/src/generators.ts +0 -240
  291. package/skills/generate-env/src/index.ts +0 -120
  292. package/skills/generate-env/src/runtime.ts +0 -30
  293. package/skills/generate-env/src/types.ts +0 -32
  294. package/skills/generate-env/tsconfig.json +0 -10
  295. package/skills/generate-favicon/CLAUDE.md +0 -19
  296. package/skills/generate-favicon/package.json +0 -29
  297. package/skills/generate-favicon/src/index.ts +0 -421
  298. package/skills/generate-favicon/tsconfig.json +0 -10
  299. package/skills/generate-qrcode/CLAUDE.md +0 -19
  300. package/skills/generate-qrcode/package.json +0 -30
  301. package/skills/generate-qrcode/src/index.ts +0 -584
  302. package/skills/generate-qrcode/tsconfig.json +0 -10
  303. package/skills/generate-resume/CLAUDE.md +0 -19
  304. package/skills/generate-resume/package.json +0 -27
  305. package/skills/generate-resume/src/cli.ts +0 -157
  306. package/skills/generate-resume/src/index.ts +0 -178
  307. package/skills/generate-resume/src/parsers.ts +0 -95
  308. package/skills/generate-resume/src/renderers.ts +0 -538
  309. package/skills/generate-resume/src/security.ts +0 -39
  310. package/skills/generate-resume/src/types.ts +0 -86
  311. package/skills/generate-resume/tsconfig.json +0 -10
  312. package/skills/generate-sitemap/CLAUDE.md +0 -19
  313. package/skills/generate-sitemap/package.json +0 -27
  314. package/skills/generate-sitemap/src/index.ts +0 -626
  315. package/skills/generate-sitemap/tsconfig.json +0 -10
  316. package/skills/gif-maker/CLAUDE.md +0 -19
  317. package/skills/gif-maker/package.json +0 -30
  318. package/skills/gif-maker/src/index.ts +0 -600
  319. package/skills/gif-maker/tsconfig.json +0 -10
  320. package/skills/hook/LICENSE +0 -192
  321. package/skills/hook/README.md +0 -74
  322. package/skills/hook/SKILL.md +0 -85
  323. package/skills/hook/bunfig.toml +0 -5
  324. package/skills/hook/package.json +0 -28
  325. package/skills/hook/src/commands/create.ts +0 -112
  326. package/skills/hook/src/commands/events.ts +0 -37
  327. package/skills/hook/src/commands/validate.ts +0 -117
  328. package/skills/hook/src/index.ts +0 -118
  329. package/skills/hook/src/templates/root.ts +0 -196
  330. package/skills/hook/src/templates/source.ts +0 -647
  331. package/skills/hook/tsconfig.json +0 -18
  332. package/skills/http-server/CLAUDE.md +0 -19
  333. package/skills/http-server/package.json +0 -29
  334. package/skills/http-server/src/index.ts +0 -51
  335. package/skills/http-server/tsconfig.json +0 -10
  336. package/skills/implementation/LICENSE +0 -192
  337. package/skills/implementation/README.md +0 -53
  338. package/skills/implementation/SKILL.md +0 -57
  339. package/skills/implementation/bunfig.toml +0 -5
  340. package/skills/implementation/package.json +0 -28
  341. package/skills/implementation/src/commands/create.ts +0 -187
  342. package/skills/implementation/src/index.ts +0 -62
  343. package/skills/implementation/tsconfig.json +0 -18
  344. package/skills/implementation-plan/CLAUDE.md +0 -19
  345. package/skills/implementation-plan/package.json +0 -29
  346. package/skills/implementation-plan/src/index.ts +0 -520
  347. package/skills/implementation-plan/tsconfig.json +0 -10
  348. package/skills/implementation-todo/CLAUDE.md +0 -19
  349. package/skills/implementation-todo/package.json +0 -29
  350. package/skills/implementation-todo/src/index.ts +0 -429
  351. package/skills/implementation-todo/tsconfig.json +0 -10
  352. package/skills/invoice/.env.example +0 -3
  353. package/skills/invoice/CLAUDE.md +0 -31
  354. package/skills/invoice/LICENSE +0 -192
  355. package/skills/invoice/README.md +0 -70
  356. package/skills/invoice/package.json +0 -26
  357. package/skills/invoice/src/commands/companies.ts +0 -202
  358. package/skills/invoice/src/commands/config.ts +0 -132
  359. package/skills/invoice/src/commands/generate.ts +0 -177
  360. package/skills/invoice/src/commands/invoices.ts +0 -218
  361. package/skills/invoice/src/index.ts +0 -3
  362. package/skills/invoice/src/lib/api.ts +0 -124
  363. package/skills/invoice/src/lib/storage.ts +0 -171
  364. package/skills/invoice/src/types/index.ts +0 -86
  365. package/skills/invoice/src/utils/logger.ts +0 -33
  366. package/skills/invoice/src/utils/paths.ts +0 -25
  367. package/skills/invoice/tsconfig.json +0 -23
  368. package/skills/invoice-reconciliation/SKILL.md +0 -98
  369. package/skills/invoice-reconciliation/package.json +0 -36
  370. package/skills/invoice-reconciliation/src/index.ts +0 -743
  371. package/skills/invoice-reconciliation/tsconfig.json +0 -17
  372. package/skills/landing-page-pack/SKILL.md +0 -55
  373. package/skills/landing-page-pack/package.json +0 -10
  374. package/skills/latex-table-generator/CLAUDE.md +0 -19
  375. package/skills/latex-table-generator/package.json +0 -29
  376. package/skills/latex-table-generator/src/index.ts +0 -113
  377. package/skills/latex-table-generator/tsconfig.json +0 -10
  378. package/skills/logo-design/SKILL.md +0 -94
  379. package/skills/logo-design/package.json +0 -35
  380. package/skills/logo-design/src/cli.ts +0 -132
  381. package/skills/logo-design/src/constants.ts +0 -5
  382. package/skills/logo-design/src/docs.ts +0 -102
  383. package/skills/logo-design/src/geometry.ts +0 -324
  384. package/skills/logo-design/src/index.ts +0 -212
  385. package/skills/logo-design/src/palette.ts +0 -258
  386. package/skills/logo-design/src/types.ts +0 -50
  387. package/skills/logo-design/tsconfig.json +0 -17
  388. package/skills/lorem-generator/CLAUDE.md +0 -19
  389. package/skills/lorem-generator/package.json +0 -29
  390. package/skills/lorem-generator/src/index.ts +0 -59
  391. package/skills/lorem-generator/tsconfig.json +0 -10
  392. package/skills/managemcp/CLAUDE.md +0 -14
  393. package/skills/managemcp/README.md +0 -24
  394. package/skills/managemcp/package.json +0 -16
  395. package/skills/managemcp/src/index.ts +0 -3
  396. package/skills/managemcp/tsconfig.json +0 -27
  397. package/skills/markdown-validator/CLAUDE.md +0 -19
  398. package/skills/markdown-validator/package.json +0 -29
  399. package/skills/markdown-validator/src/index.ts +0 -92
  400. package/skills/markdown-validator/tsconfig.json +0 -10
  401. package/skills/market-research-report/SKILL.md +0 -51
  402. package/skills/market-research-report/package.json +0 -10
  403. package/skills/meeting-pack/SKILL.md +0 -52
  404. package/skills/meeting-pack/package.json +0 -10
  405. package/skills/merge-pdfs/CLAUDE.md +0 -19
  406. package/skills/merge-pdfs/package.json +0 -31
  407. package/skills/merge-pdfs/src/index.ts +0 -427
  408. package/skills/merge-pdfs/tsconfig.json +0 -10
  409. package/skills/migration-plan-pack/SKILL.md +0 -56
  410. package/skills/migration-plan-pack/package.json +0 -10
  411. package/skills/monitor/SKILL.md +0 -69
  412. package/skills/monitor/package.json +0 -33
  413. package/skills/monitor/src/index.ts +0 -34
  414. package/skills/monitor/tsconfig.json +0 -17
  415. package/skills/one-page-website/SKILL.md +0 -128
  416. package/skills/one-page-website/package.json +0 -34
  417. package/skills/one-page-website/src/design.ts +0 -336
  418. package/skills/one-page-website/src/docs.ts +0 -159
  419. package/skills/one-page-website/src/index.ts +0 -357
  420. package/skills/one-page-website/src/page.ts +0 -340
  421. package/skills/one-page-website/src/styles.ts +0 -508
  422. package/skills/one-page-website/src/types.ts +0 -78
  423. package/skills/one-page-website/tsconfig.json +0 -17
  424. package/skills/pdf-generate/CLAUDE.md +0 -19
  425. package/skills/pdf-generate/SKILL.md +0 -86
  426. package/skills/pdf-generate/package.json +0 -21
  427. package/skills/pdf-generate/src/cli.ts +0 -162
  428. package/skills/pdf-generate/src/html.ts +0 -84
  429. package/skills/pdf-generate/src/index.ts +0 -62
  430. package/skills/pdf-generate/src/markdown.ts +0 -27
  431. package/skills/pdf-generate/src/pdf-writer.ts +0 -78
  432. package/skills/pdf-generate/src/runtime.ts +0 -34
  433. package/skills/pdf-generate/src/security.ts +0 -37
  434. package/skills/pdf-generate/src/templates.ts +0 -311
  435. package/skills/pdf-generate/src/types.ts +0 -28
  436. package/skills/pdf-generate/tsconfig.json +0 -16
  437. package/skills/pdf-to-dataset/SKILL.md +0 -88
  438. package/skills/pdf-to-dataset/package.json +0 -37
  439. package/skills/pdf-to-dataset/src/index.ts +0 -790
  440. package/skills/pdf-to-dataset/tsconfig.json +0 -17
  441. package/skills/pdf-to-markdown/SKILL.md +0 -81
  442. package/skills/pdf-to-markdown/package.json +0 -35
  443. package/skills/pdf-to-markdown/src/index.ts +0 -694
  444. package/skills/pdf-to-markdown/tsconfig.json +0 -17
  445. package/skills/performance-audit-report/SKILL.md +0 -49
  446. package/skills/performance-audit-report/package.json +0 -10
  447. package/skills/pitch-deck/SKILL.md +0 -51
  448. package/skills/pitch-deck/package.json +0 -10
  449. package/skills/product-mockup/SKILL.md +0 -107
  450. package/skills/product-mockup/package.json +0 -32
  451. package/skills/product-mockup/src/cli.ts +0 -150
  452. package/skills/product-mockup/src/design.ts +0 -151
  453. package/skills/product-mockup/src/docs.ts +0 -134
  454. package/skills/product-mockup/src/index.ts +0 -182
  455. package/skills/product-mockup/src/render.ts +0 -407
  456. package/skills/product-mockup/src/types.ts +0 -66
  457. package/skills/product-mockup/tsconfig.json +0 -17
  458. package/skills/proposal-pack/SKILL.md +0 -53
  459. package/skills/proposal-pack/package.json +0 -10
  460. package/skills/read-csv/SKILL.md +0 -62
  461. package/skills/read-csv/package.json +0 -37
  462. package/skills/read-csv/src/index.ts +0 -356
  463. package/skills/read-csv/tsconfig.json +0 -17
  464. package/skills/read-excel/SKILL.md +0 -64
  465. package/skills/read-excel/package.json +0 -36
  466. package/skills/read-excel/src/index.ts +0 -266
  467. package/skills/read-excel/tsconfig.json +0 -17
  468. package/skills/regex-tester/CLAUDE.md +0 -19
  469. package/skills/regex-tester/package.json +0 -27
  470. package/skills/regex-tester/src/index.ts +0 -183
  471. package/skills/regex-tester/tsconfig.json +0 -10
  472. package/skills/repo-onboarding-report/SKILL.md +0 -52
  473. package/skills/repo-onboarding-report/package.json +0 -10
  474. package/skills/scancommitpr/SKILL.md +0 -178
  475. package/skills/scancommitpr/package.json +0 -34
  476. package/skills/scancommitpr/src/index.ts +0 -44
  477. package/skills/scancommitpr/tsconfig.json +0 -13
  478. package/skills/scancommitpush/SKILL.md +0 -174
  479. package/skills/scancommitpush/package.json +0 -32
  480. package/skills/scancommitpush/src/index.ts +0 -44
  481. package/skills/scancommitpush/tsconfig.json +0 -13
  482. package/skills/scientific-figure-check/CLAUDE.md +0 -19
  483. package/skills/scientific-figure-check/package.json +0 -29
  484. package/skills/scientific-figure-check/src/index.ts +0 -83
  485. package/skills/scientific-figure-check/tsconfig.json +0 -10
  486. package/skills/security-audit/CLAUDE.md +0 -19
  487. package/skills/security-audit/package.json +0 -27
  488. package/skills/security-audit/src/index.ts +0 -145
  489. package/skills/security-audit/tsconfig.json +0 -10
  490. package/skills/security-audit-report/SKILL.md +0 -52
  491. package/skills/security-audit-report/package.json +0 -10
  492. package/skills/seo-content-pack/SKILL.md +0 -54
  493. package/skills/seo-content-pack/package.json +0 -10
  494. package/skills/siteanalyze/SKILL.md +0 -25
  495. package/skills/siteanalyze/package.json +0 -27
  496. package/skills/siteanalyze/src/index.ts +0 -592
  497. package/skills/slide-deck-generator/SKILL.md +0 -93
  498. package/skills/slide-deck-generator/package.json +0 -38
  499. package/skills/slide-deck-generator/src/cli.ts +0 -133
  500. package/skills/slide-deck-generator/src/index.ts +0 -148
  501. package/skills/slide-deck-generator/src/model.ts +0 -307
  502. package/skills/slide-deck-generator/src/pptx.ts +0 -143
  503. package/skills/slide-deck-generator/src/render.ts +0 -248
  504. package/skills/slide-deck-generator/src/types.ts +0 -114
  505. package/skills/slide-deck-generator/src/utils.ts +0 -53
  506. package/skills/slide-deck-generator/tsconfig.json +0 -17
  507. package/skills/social-content-calendar/SKILL.md +0 -54
  508. package/skills/social-content-calendar/package.json +0 -10
  509. package/skills/split-pdf/CLAUDE.md +0 -19
  510. package/skills/split-pdf/package.json +0 -30
  511. package/skills/split-pdf/src/index.ts +0 -301
  512. package/skills/split-pdf/tsconfig.json +0 -10
  513. package/skills/statistical-test-selector/CLAUDE.md +0 -19
  514. package/skills/statistical-test-selector/package.json +0 -27
  515. package/skills/statistical-test-selector/src/index.ts +0 -75
  516. package/skills/statistical-test-selector/tsconfig.json +0 -10
  517. package/skills/test-suite-generator/SKILL.md +0 -51
  518. package/skills/test-suite-generator/package.json +0 -10
  519. package/skills/tmux-session/SKILL.md +0 -109
  520. package/skills/tmux-session/package.json +0 -33
  521. package/skills/tmux-session/src/index.ts +0 -34
  522. package/skills/tmux-session/tsconfig.json +0 -17
  523. package/skills/todos-plan/SKILL.md +0 -363
  524. package/skills/todos-plan/agents/openai.yaml +0 -4
  525. package/skills/todos-plan/package.json +0 -9
  526. package/skills/todos-plan/src/index.ts +0 -68
  527. package/skills/tsconfig.base.json +0 -12
  528. package/skills/validate-config/CLAUDE.md +0 -19
  529. package/skills/validate-config/package.json +0 -29
  530. package/skills/validate-config/src/index.ts +0 -56
  531. package/skills/validate-config/tsconfig.json +0 -10
  532. package/skills/video-downloader/CLAUDE.md +0 -19
  533. package/skills/video-downloader/package.json +0 -29
  534. package/skills/video-downloader/src/index.ts +0 -561
  535. package/skills/video-downloader/tsconfig.json +0 -10
  536. package/skills/video-highlight-pack/SKILL.md +0 -54
  537. package/skills/video-highlight-pack/package.json +0 -10
  538. package/skills/watermark/CLAUDE.md +0 -19
  539. package/skills/watermark/package.json +0 -32
  540. package/skills/watermark/src/index.ts +0 -587
  541. package/skills/watermark/tsconfig.json +0 -10
@@ -1,919 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import { mkdir, readFile, stat, writeFile } from "fs/promises";
4
- import { extname, join, resolve } from "path";
5
-
6
- const VERSION = "0.1.0";
7
-
8
- type Theme = "light" | "slate";
9
-
10
- interface CliOptions {
11
- spec?: string;
12
- output: string;
13
- theme: Theme;
14
- baseUrl?: string;
15
- title?: string;
16
- json: boolean;
17
- }
18
-
19
- interface JsonObject {
20
- [key: string]: unknown;
21
- }
22
-
23
- interface ParamModel {
24
- name: string;
25
- in: string;
26
- required: boolean;
27
- description: string;
28
- type: string;
29
- enum?: string[];
30
- example?: string;
31
- }
32
-
33
- interface BodyModel {
34
- contentType: string;
35
- required: boolean;
36
- description: string;
37
- schema: SchemaField[];
38
- raw: unknown;
39
- }
40
-
41
- interface ResponseModel {
42
- status: string;
43
- description: string;
44
- contentType: string | null;
45
- schema: SchemaField[];
46
- }
47
-
48
- interface SchemaField {
49
- name: string;
50
- type: string;
51
- required: boolean;
52
- description: string;
53
- children?: SchemaField[];
54
- }
55
-
56
- interface EndpointModel {
57
- id: string;
58
- method: string;
59
- path: string;
60
- operationId: string | null;
61
- summary: string;
62
- description: string;
63
- tags: string[];
64
- group: string;
65
- deprecated: boolean;
66
- parameters: ParamModel[];
67
- requestBody: BodyModel | null;
68
- responses: ResponseModel[];
69
- security: string[];
70
- }
71
-
72
- interface PortalModel {
73
- title: string;
74
- version: string;
75
- description: string;
76
- baseUrl: string;
77
- servers: string[];
78
- theme: Theme;
79
- generatedAt: string;
80
- groups: Array<{ name: string; description: string; endpoints: EndpointModel[] }>;
81
- endpointCount: number;
82
- securitySchemes: Array<{ name: string; type: string; detail: string }>;
83
- }
84
-
85
- const METHODS = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
86
-
87
- /* ------------------------------------------------------------------ *
88
- * dependency loading
89
- * ------------------------------------------------------------------ */
90
-
91
- async function loadYaml(): Promise<{ parse: (text: string) => unknown }> {
92
- try {
93
- return await import("yaml");
94
- } catch {
95
- throw new Error("Missing dependency 'yaml'. Run bun install in this skill directory.");
96
- }
97
- }
98
-
99
- /* ------------------------------------------------------------------ *
100
- * CLI
101
- * ------------------------------------------------------------------ */
102
-
103
- function printHelp(): void {
104
- console.log(`api-docs-portal v${VERSION}
105
-
106
- USAGE:
107
- api-docs-portal --spec <openapi.json|openapi.yaml> [options]
108
-
109
- OPTIONS:
110
- -s, --spec <path> OpenAPI 3.x or Swagger 2.0 document (JSON or YAML)
111
- -o, --output <dir> Output directory (default: ./api-portal)
112
- --theme <name> Portal theme: light | slate (default: light)
113
- --base-url <url> Base URL shown in the portal and cURL examples
114
- --title <text> Override the portal title (default: spec info.title)
115
- --json Print a JSON summary on stdout
116
- --help Show this help message
117
- --version Show the current version
118
-
119
- OUTPUT FILES:
120
- index.html Self-contained portal (inline CSS, no external requests)
121
- endpoints.json Normalized endpoint model
122
- reference.md Markdown API reference
123
-
124
- EXAMPLES:
125
- api-docs-portal --spec ./openapi.yaml
126
- api-docs-portal --spec ./openapi.json --output ./docs/api --theme slate
127
- api-docs-portal --spec ./openapi.yaml --base-url https://api.example.com --json
128
- `);
129
- }
130
-
131
- function parseArgs(argv: string[]): CliOptions {
132
- const options: CliOptions = {
133
- output: "./api-portal",
134
- theme: "light",
135
- json: false,
136
- };
137
-
138
- for (let i = 0; i < argv.length; i += 1) {
139
- const arg = argv[i];
140
- switch (arg) {
141
- case "--help":
142
- case "-h":
143
- printHelp();
144
- process.exit(0);
145
- case "--version":
146
- case "-v":
147
- console.log(VERSION);
148
- process.exit(0);
149
- case "--spec":
150
- case "-s":
151
- options.spec = argv[++i];
152
- break;
153
- case "--output":
154
- case "-o":
155
- options.output = argv[++i] ?? options.output;
156
- break;
157
- case "--theme": {
158
- const value = (argv[++i] ?? "").toLowerCase();
159
- if (value !== "light" && value !== "slate") {
160
- throw new Error(`Invalid --theme value: ${value || "(empty)"} (expected light or slate)`);
161
- }
162
- options.theme = value;
163
- break;
164
- }
165
- case "--base-url":
166
- options.baseUrl = argv[++i];
167
- break;
168
- case "--title":
169
- options.title = argv[++i];
170
- break;
171
- case "--json":
172
- options.json = true;
173
- break;
174
- default:
175
- if (arg.startsWith("-")) throw new Error(`Unknown option: ${arg}`);
176
- if (!options.spec) {
177
- options.spec = arg;
178
- break;
179
- }
180
- throw new Error(`Unexpected argument: ${arg}`);
181
- }
182
- }
183
-
184
- if (!options.spec) throw new Error("Missing required --spec <path> argument");
185
- return options;
186
- }
187
-
188
- /* ------------------------------------------------------------------ *
189
- * spec loading + $ref resolution
190
- * ------------------------------------------------------------------ */
191
-
192
- function isObject(value: unknown): value is JsonObject {
193
- return typeof value === "object" && value !== null && !Array.isArray(value);
194
- }
195
-
196
- function asString(value: unknown, fallback = ""): string {
197
- if (typeof value === "string") return value;
198
- if (typeof value === "number" || typeof value === "boolean") return String(value);
199
- return fallback;
200
- }
201
-
202
- async function loadSpec(path: string): Promise<JsonObject> {
203
- let fileStat;
204
- try {
205
- fileStat = await stat(path);
206
- } catch {
207
- throw new Error(`Cannot read spec file: ${path}`);
208
- }
209
- if (!fileStat.isFile()) throw new Error(`Spec path is not a file: ${path}`);
210
-
211
- const text = await readFile(path, "utf8");
212
- if (text.trim() === "") throw new Error(`Spec file is empty: ${path}`);
213
-
214
- const extension = extname(path).toLowerCase();
215
- const looksJson = extension === ".json" || text.trimStart().startsWith("{");
216
-
217
- let parsed: unknown;
218
- if (looksJson) {
219
- try {
220
- parsed = JSON.parse(text);
221
- } catch (error) {
222
- const message = error instanceof Error ? error.message : String(error);
223
- throw new Error(`Spec file is not valid JSON (${path}): ${message}`);
224
- }
225
- } else {
226
- const yaml = await loadYaml();
227
- try {
228
- parsed = yaml.parse(text);
229
- } catch (error) {
230
- const message = error instanceof Error ? error.message : String(error);
231
- throw new Error(`Spec file is not valid YAML (${path}): ${message}`);
232
- }
233
- }
234
-
235
- if (!isObject(parsed)) throw new Error(`Spec file did not contain an object: ${path}`);
236
- if (!isObject(parsed.paths)) {
237
- throw new Error(`Spec file has no "paths" object; this does not look like an OpenAPI document: ${path}`);
238
- }
239
- return parsed;
240
- }
241
-
242
- /** Resolve a local `#/...` JSON pointer against the root document. */
243
- function resolvePointer(root: JsonObject, pointer: string): unknown {
244
- if (!pointer.startsWith("#/")) return undefined;
245
- const segments = pointer
246
- .slice(2)
247
- .split("/")
248
- .map((segment) => segment.replace(/~1/gu, "/").replace(/~0/gu, "~"));
249
-
250
- let current: unknown = root;
251
- for (const segment of segments) {
252
- if (Array.isArray(current)) {
253
- const index = Number.parseInt(segment, 10);
254
- if (!Number.isFinite(index)) return undefined;
255
- current = current[index];
256
- continue;
257
- }
258
- if (!isObject(current)) return undefined;
259
- current = current[segment];
260
- }
261
- return current;
262
- }
263
-
264
- function deref(root: JsonObject, node: unknown, seen: Set<string> = new Set()): unknown {
265
- if (Array.isArray(node)) return node.map((item) => deref(root, item, seen));
266
- if (!isObject(node)) return node;
267
-
268
- if (typeof node.$ref === "string") {
269
- const pointer = node.$ref;
270
- if (!pointer.startsWith("#/")) {
271
- return { ...node, "x-unresolved-ref": pointer };
272
- }
273
- if (seen.has(pointer)) return { type: "object", description: `Circular reference to ${pointer}` };
274
- const target = resolvePointer(root, pointer);
275
- if (target === undefined) return { ...node, "x-unresolved-ref": pointer };
276
- const nextSeen = new Set(seen);
277
- nextSeen.add(pointer);
278
- const resolved = deref(root, target, nextSeen);
279
- const rest = { ...node };
280
- delete rest.$ref;
281
- return isObject(resolved) ? { ...resolved, ...rest } : resolved;
282
- }
283
-
284
- const out: JsonObject = {};
285
- for (const [key, value] of Object.entries(node)) out[key] = deref(root, value, seen);
286
- return out;
287
- }
288
-
289
- /* ------------------------------------------------------------------ *
290
- * schema flattening
291
- * ------------------------------------------------------------------ */
292
-
293
- function schemaTypeLabel(schema: unknown): string {
294
- if (!isObject(schema)) return "any";
295
- if (typeof schema["x-unresolved-ref"] === "string") return `ref(${schema["x-unresolved-ref"]})`;
296
-
297
- const compose = ["oneOf", "anyOf", "allOf"] as const;
298
- for (const key of compose) {
299
- const branches = schema[key];
300
- if (Array.isArray(branches)) {
301
- const parts = branches.map((branch) => schemaTypeLabel(branch));
302
- return key === "allOf" ? parts.join(" & ") : parts.join(" | ");
303
- }
304
- }
305
-
306
- const type = asString(schema.type);
307
- if (type === "array") return `${schemaTypeLabel(schema.items)}[]`;
308
- if (Array.isArray(schema.enum)) {
309
- const values = schema.enum.map((value) => asString(value)).join(" | ");
310
- return type ? `${type} (${values})` : values;
311
- }
312
- if (schema.format) return `${type || "string"}<${asString(schema.format)}>`;
313
- if (type) return type;
314
- if (isObject(schema.properties)) return "object";
315
- return "any";
316
- }
317
-
318
- function flattenSchema(schema: unknown, depth = 0): SchemaField[] {
319
- if (!isObject(schema) || depth > 3) return [];
320
-
321
- let target = schema;
322
- if (asString(schema.type) === "array" && isObject(schema.items)) target = schema.items;
323
-
324
- if (Array.isArray(target.allOf)) {
325
- const merged: SchemaField[] = [];
326
- for (const branch of target.allOf) merged.push(...flattenSchema(branch, depth));
327
- return merged;
328
- }
329
-
330
- if (!isObject(target.properties)) return [];
331
- const required = new Set(Array.isArray(target.required) ? target.required.map((item) => asString(item)) : []);
332
-
333
- return Object.entries(target.properties).map(([name, value]) => {
334
- const field: SchemaField = {
335
- name,
336
- type: schemaTypeLabel(value),
337
- required: required.has(name),
338
- description: isObject(value) ? asString(value.description) : "",
339
- };
340
- const children = flattenSchema(value, depth + 1);
341
- if (children.length > 0) field.children = children;
342
- return field;
343
- });
344
- }
345
-
346
- /* ------------------------------------------------------------------ *
347
- * endpoint model
348
- * ------------------------------------------------------------------ */
349
-
350
- function firstContent(content: unknown): { contentType: string | null; media: JsonObject | null } {
351
- if (!isObject(content)) return { contentType: null, media: null };
352
- const preferred = Object.keys(content).find((key) => key.includes("json")) ?? Object.keys(content)[0];
353
- if (!preferred) return { contentType: null, media: null };
354
- const media = content[preferred];
355
- return { contentType: preferred, media: isObject(media) ? media : null };
356
- }
357
-
358
- function buildParameters(raw: unknown): ParamModel[] {
359
- if (!Array.isArray(raw)) return [];
360
- return raw.filter(isObject).map((parameter) => {
361
- const schema = isObject(parameter.schema) ? parameter.schema : parameter;
362
- return {
363
- name: asString(parameter.name, "(unnamed)"),
364
- in: asString(parameter.in, "query"),
365
- required: parameter.required === true || asString(parameter.in) === "path",
366
- description: asString(parameter.description),
367
- type: schemaTypeLabel(schema),
368
- enum: Array.isArray(schema.enum) ? schema.enum.map((value) => asString(value)) : undefined,
369
- example: parameter.example !== undefined ? asString(parameter.example) : undefined,
370
- };
371
- });
372
- }
373
-
374
- function buildRequestBody(operation: JsonObject): BodyModel | null {
375
- const body = operation.requestBody;
376
- if (!isObject(body)) return null;
377
- const { contentType, media } = firstContent(body.content);
378
- const schema = media?.schema;
379
- return {
380
- contentType: contentType ?? "application/json",
381
- required: body.required === true,
382
- description: asString(body.description),
383
- schema: flattenSchema(schema),
384
- raw: schema ?? null,
385
- };
386
- }
387
-
388
- function buildResponses(operation: JsonObject): ResponseModel[] {
389
- if (!isObject(operation.responses)) return [];
390
- return Object.entries(operation.responses).map(([status, value]) => {
391
- const response = isObject(value) ? value : {};
392
- const { contentType, media } = firstContent(response.content);
393
- return {
394
- status,
395
- description: asString(response.description),
396
- contentType,
397
- schema: flattenSchema(media?.schema),
398
- };
399
- });
400
- }
401
-
402
- function groupName(tags: string[], path: string): string {
403
- if (tags.length > 0) return tags[0];
404
- const segment = path.split("/").filter((part) => part && !part.startsWith("{"))[0];
405
- return segment ? segment.replace(/[-_]/gu, " ") : "default";
406
- }
407
-
408
- function buildModel(spec: JsonObject, options: CliOptions): PortalModel {
409
- const info = isObject(spec.info) ? spec.info : {};
410
- const servers = Array.isArray(spec.servers)
411
- ? spec.servers.filter(isObject).map((server) => asString(server.url)).filter(Boolean)
412
- : [];
413
- if (typeof spec.host === "string") {
414
- const scheme = Array.isArray(spec.schemes) && spec.schemes.length > 0 ? asString(spec.schemes[0]) : "https";
415
- servers.push(`${scheme}://${spec.host}${asString(spec.basePath)}`);
416
- }
417
-
418
- const baseUrl = options.baseUrl ?? servers[0] ?? "";
419
- const paths = isObject(spec.paths) ? spec.paths : {};
420
- const groups = new Map<string, EndpointModel[]>();
421
- let counter = 0;
422
-
423
- for (const [path, rawItem] of Object.entries(paths)) {
424
- if (!isObject(rawItem)) continue;
425
- const item = deref(spec, rawItem) as JsonObject;
426
- const sharedParameters = buildParameters(item.parameters);
427
-
428
- for (const method of METHODS) {
429
- const rawOperation = item[method];
430
- if (!isObject(rawOperation)) continue;
431
- const operation = rawOperation;
432
-
433
- const tags = Array.isArray(operation.tags) ? operation.tags.map((tag) => asString(tag)).filter(Boolean) : [];
434
- const group = groupName(tags, path);
435
- const parameters = [...sharedParameters, ...buildParameters(operation.parameters)];
436
- const security = Array.isArray(operation.security)
437
- ? operation.security.flatMap((entry) => (isObject(entry) ? Object.keys(entry) : []))
438
- : Array.isArray(spec.security)
439
- ? spec.security.flatMap((entry) => (isObject(entry) ? Object.keys(entry) : []))
440
- : [];
441
-
442
- counter += 1;
443
- const endpoint: EndpointModel = {
444
- id: `${method}-${path}`.replace(/[^a-zA-Z0-9]+/gu, "-").replace(/^-+|-+$/gu, "").toLowerCase() || `endpoint-${counter}`,
445
- method: method.toUpperCase(),
446
- path,
447
- operationId: operation.operationId ? asString(operation.operationId) : null,
448
- summary: asString(operation.summary) || asString(operation.operationId) || `${method.toUpperCase()} ${path}`,
449
- description: asString(operation.description),
450
- tags,
451
- group,
452
- deprecated: operation.deprecated === true,
453
- parameters,
454
- requestBody: buildRequestBody(operation),
455
- responses: buildResponses(operation),
456
- security: [...new Set(security)],
457
- };
458
-
459
- const bucket = groups.get(group);
460
- if (bucket) bucket.push(endpoint);
461
- else groups.set(group, [endpoint]);
462
- }
463
- }
464
-
465
- if (counter === 0) throw new Error("Spec contains no operations under \"paths\"");
466
-
467
- const tagDescriptions = new Map<string, string>();
468
- if (Array.isArray(spec.tags)) {
469
- for (const tag of spec.tags) {
470
- if (isObject(tag)) tagDescriptions.set(asString(tag.name), asString(tag.description));
471
- }
472
- }
473
-
474
- const components = isObject(spec.components) ? spec.components : {};
475
- const schemes = isObject(components.securitySchemes)
476
- ? components.securitySchemes
477
- : isObject(spec.securityDefinitions)
478
- ? spec.securityDefinitions
479
- : {};
480
-
481
- const securitySchemes = Object.entries(schemes)
482
- .filter((entry): entry is [string, JsonObject] => isObject(entry[1]))
483
- .map(([name, scheme]) => ({
484
- name,
485
- type: asString(scheme.type, "unknown"),
486
- detail: [
487
- scheme.scheme ? `scheme: ${asString(scheme.scheme)}` : "",
488
- scheme.bearerFormat ? `format: ${asString(scheme.bearerFormat)}` : "",
489
- scheme.in ? `in: ${asString(scheme.in)}` : "",
490
- scheme.name ? `name: ${asString(scheme.name)}` : "",
491
- asString(scheme.description),
492
- ]
493
- .filter(Boolean)
494
- .join(", "),
495
- }));
496
-
497
- return {
498
- title: options.title ?? asString(info.title, "API Documentation"),
499
- version: asString(info.version, "unversioned"),
500
- description: asString(info.description),
501
- baseUrl,
502
- servers,
503
- theme: options.theme,
504
- generatedAt: new Date().toISOString(),
505
- groups: [...groups.entries()]
506
- .sort((a, b) => a[0].localeCompare(b[0]))
507
- .map(([name, endpoints]) => ({
508
- name,
509
- description: tagDescriptions.get(name) ?? "",
510
- endpoints: endpoints.sort((a, b) => a.path.localeCompare(b.path) || a.method.localeCompare(b.method)),
511
- })),
512
- endpointCount: counter,
513
- securitySchemes,
514
- };
515
- }
516
-
517
- /* ------------------------------------------------------------------ *
518
- * rendering
519
- * ------------------------------------------------------------------ */
520
-
521
- function escapeHtml(value: string): string {
522
- return value
523
- .replace(/&/gu, "&amp;")
524
- .replace(/</gu, "&lt;")
525
- .replace(/>/gu, "&gt;")
526
- .replace(/"/gu, "&quot;")
527
- .replace(/'/gu, "&#39;");
528
- }
529
-
530
- const THEMES: Record<Theme, Record<string, string>> = {
531
- light: {
532
- bg: "#f7f8fa",
533
- surface: "#ffffff",
534
- text: "#1b1f24",
535
- muted: "#5b6472",
536
- border: "#e2e6ec",
537
- accent: "#2c5fd8",
538
- code: "#f2f4f7",
539
- sidebar: "#ffffff",
540
- },
541
- slate: {
542
- bg: "#11151c",
543
- surface: "#182029",
544
- text: "#e6ebf2",
545
- muted: "#93a1b3",
546
- border: "#26313d",
547
- accent: "#63a4ff",
548
- code: "#0d1219",
549
- sidebar: "#151c24",
550
- },
551
- };
552
-
553
- const METHOD_COLORS: Record<string, string> = {
554
- GET: "#1f8a4c",
555
- POST: "#2c5fd8",
556
- PUT: "#a86a12",
557
- PATCH: "#8a5cd6",
558
- DELETE: "#c2392e",
559
- HEAD: "#5b6472",
560
- OPTIONS: "#5b6472",
561
- TRACE: "#5b6472",
562
- };
563
-
564
- function renderSchemaRows(fields: SchemaField[], prefix = "", depth = 0): string {
565
- return fields
566
- .map((field) => {
567
- const name = prefix ? `${prefix}.${field.name}` : field.name;
568
- const row = `<tr${depth > 0 ? ' class="nested"' : ""}><td><code>${escapeHtml(name)}</code></td><td><span class="type">${escapeHtml(
569
- field.type,
570
- )}</span></td><td>${
571
- field.required ? '<span class="req">required</span>' : '<span class="opt">optional</span>'
572
- }</td><td>${escapeHtml(field.description)}</td></tr>`;
573
- return field.children ? row + renderSchemaRows(field.children, name, depth + 1) : row;
574
- })
575
- .join("");
576
- }
577
-
578
- function renderSchemaTable(fields: SchemaField[]): string {
579
- if (fields.length === 0) return "";
580
- return `<div class="table-wrap"><table><thead><tr><th>Field</th><th>Type</th><th></th><th>Description</th></tr></thead><tbody>${renderSchemaRows(
581
- fields,
582
- )}</tbody></table></div>`;
583
- }
584
-
585
- function curlExample(endpoint: EndpointModel, baseUrl: string): string {
586
- const url = `${baseUrl.replace(/\/+$/u, "")}${endpoint.path}`;
587
- const parts = [`curl -X ${endpoint.method} "${url}"`];
588
- if (endpoint.security.length > 0) parts.push(` -H "Authorization: Bearer $TOKEN"`);
589
- if (endpoint.requestBody) {
590
- parts.push(` -H "Content-Type: ${endpoint.requestBody.contentType}"`);
591
- const sample = endpoint.requestBody.schema
592
- .slice(0, 3)
593
- .map((field) => `"${field.name}": "..."`)
594
- .join(", ");
595
- parts.push(` -d '{${sample}}'`);
596
- }
597
- return parts.join(" \\\n");
598
- }
599
-
600
- function renderEndpoint(endpoint: EndpointModel, baseUrl: string): string {
601
- const paramGroups = new Map<string, ParamModel[]>();
602
- for (const parameter of endpoint.parameters) {
603
- const bucket = paramGroups.get(parameter.in);
604
- if (bucket) bucket.push(parameter);
605
- else paramGroups.set(parameter.in, [parameter]);
606
- }
607
-
608
- const params = [...paramGroups.entries()]
609
- .map(
610
- ([location, list]) => `<h4>${escapeHtml(location)} parameters</h4>
611
- <div class="table-wrap"><table><thead><tr><th>Name</th><th>Type</th><th></th><th>Description</th></tr></thead><tbody>${list
612
- .map(
613
- (parameter) =>
614
- `<tr><td><code>${escapeHtml(parameter.name)}</code></td><td><span class="type">${escapeHtml(parameter.type)}</span></td><td>${
615
- parameter.required ? '<span class="req">required</span>' : '<span class="opt">optional</span>'
616
- }</td><td>${escapeHtml(parameter.description)}${
617
- parameter.enum ? ` <em>(${escapeHtml(parameter.enum.join(", "))})</em>` : ""
618
- }</td></tr>`,
619
- )
620
- .join("")}</tbody></table></div>`,
621
- )
622
- .join("");
623
-
624
- const body = endpoint.requestBody
625
- ? `<h4>Request body <span class="muted">(${escapeHtml(endpoint.requestBody.contentType)}${
626
- endpoint.requestBody.required ? ", required" : ""
627
- })</span></h4>${
628
- endpoint.requestBody.description ? `<p>${escapeHtml(endpoint.requestBody.description)}</p>` : ""
629
- }${renderSchemaTable(endpoint.requestBody.schema) || '<p class="muted">No object schema declared.</p>'}`
630
- : "";
631
-
632
- const responses = endpoint.responses.length
633
- ? `<h4>Responses</h4>${endpoint.responses
634
- .map(
635
- (response) =>
636
- `<div class="response"><span class="status status-${response.status.startsWith("2") ? "ok" : "err"}">${escapeHtml(
637
- response.status,
638
- )}</span> <span class="muted">${escapeHtml(response.description)}${
639
- response.contentType ? ` — ${escapeHtml(response.contentType)}` : ""
640
- }</span>${renderSchemaTable(response.schema)}</div>`,
641
- )
642
- .join("")}`
643
- : "";
644
-
645
- return `<article class="endpoint" id="${escapeHtml(endpoint.id)}">
646
- <header>
647
- <span class="method method-${escapeHtml(endpoint.method.toLowerCase())}">${escapeHtml(endpoint.method)}</span>
648
- <code class="path">${escapeHtml(endpoint.path)}</code>
649
- ${endpoint.deprecated ? '<span class="deprecated">deprecated</span>' : ""}
650
- </header>
651
- <h3>${escapeHtml(endpoint.summary)}</h3>
652
- ${endpoint.description ? `<p>${escapeHtml(endpoint.description)}</p>` : ""}
653
- ${endpoint.security.length ? `<p class="muted">Security: ${escapeHtml(endpoint.security.join(", "))}</p>` : ""}
654
- ${params}
655
- ${body}
656
- ${responses}
657
- <h4>Example</h4>
658
- <pre><code>${escapeHtml(curlExample(endpoint, baseUrl))}</code></pre>
659
- </article>`;
660
- }
661
-
662
- function renderHtml(model: PortalModel): string {
663
- const palette = THEMES[model.theme];
664
- const methodCss = Object.entries(METHOD_COLORS)
665
- .map(([method, color]) => `.method-${method.toLowerCase()}{background:${color};}`)
666
- .join("");
667
-
668
- const nav = model.groups
669
- .map(
670
- (group) => `<li class="nav-group"><span>${escapeHtml(group.name)}</span><ul>${group.endpoints
671
- .map(
672
- (endpoint) =>
673
- `<li><a href="#${escapeHtml(endpoint.id)}"><span class="tag method-${escapeHtml(
674
- endpoint.method.toLowerCase(),
675
- )}">${escapeHtml(endpoint.method)}</span>${escapeHtml(endpoint.path)}</a></li>`,
676
- )
677
- .join("")}</ul></li>`,
678
- )
679
- .join("");
680
-
681
- const sections = model.groups
682
- .map(
683
- (group) => `<section class="group">
684
- <h2 id="group-${escapeHtml(group.name.replace(/[^a-zA-Z0-9]+/gu, "-").toLowerCase())}">${escapeHtml(group.name)}</h2>
685
- ${group.description ? `<p class="muted">${escapeHtml(group.description)}</p>` : ""}
686
- ${group.endpoints.map((endpoint) => renderEndpoint(endpoint, model.baseUrl)).join("\n")}
687
- </section>`,
688
- )
689
- .join("\n");
690
-
691
- const security = model.securitySchemes.length
692
- ? `<section class="group"><h2 id="group-authentication">Authentication</h2>${model.securitySchemes
693
- .map(
694
- (scheme) =>
695
- `<p><code>${escapeHtml(scheme.name)}</code> — <strong>${escapeHtml(scheme.type)}</strong>${
696
- scheme.detail ? ` <span class="muted">(${escapeHtml(scheme.detail)})</span>` : ""
697
- }</p>`,
698
- )
699
- .join("")}</section>`
700
- : "";
701
-
702
- return `<!DOCTYPE html>
703
- <html lang="en">
704
- <head>
705
- <meta charset="utf-8">
706
- <meta name="viewport" content="width=device-width, initial-scale=1">
707
- <title>${escapeHtml(model.title)} — API Reference</title>
708
- <style>
709
- :root{--bg:${palette.bg};--surface:${palette.surface};--text:${palette.text};--muted:${palette.muted};--border:${palette.border};--accent:${palette.accent};--code:${palette.code};--sidebar:${palette.sidebar};}
710
- *{box-sizing:border-box;}
711
- body{margin:0;background:var(--bg);color:var(--text);font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;}
712
- code,pre{font-family:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;}
713
- .layout{display:flex;min-height:100vh;align-items:flex-start;}
714
- aside{width:290px;flex:0 0 290px;background:var(--sidebar);border-right:1px solid var(--border);padding:24px 18px;position:sticky;top:0;max-height:100vh;overflow-y:auto;}
715
- aside h1{font-size:17px;margin:0 0 4px;}
716
- aside .version{color:var(--muted);font-size:12px;margin-bottom:18px;display:block;}
717
- aside ul{list-style:none;margin:0;padding:0;}
718
- aside .nav-group>span{display:block;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:16px 0 6px;}
719
- aside a{display:flex;gap:8px;align-items:center;color:var(--text);text-decoration:none;font-size:13px;padding:3px 6px;border-radius:5px;word-break:break-all;}
720
- aside a:hover{background:var(--code);color:var(--accent);}
721
- main{flex:1;padding:32px 40px 80px;max-width:1000px;min-width:0;}
722
- .intro{margin-bottom:32px;}
723
- .intro h1{margin:0 0 6px;font-size:28px;}
724
- .base-url{display:inline-block;background:var(--code);border:1px solid var(--border);border-radius:6px;padding:4px 10px;font-size:13px;}
725
- .group{margin-bottom:40px;}
726
- .group>h2{font-size:22px;border-bottom:1px solid var(--border);padding-bottom:8px;text-transform:capitalize;}
727
- .endpoint{background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:18px 20px;margin:18px 0;}
728
- .endpoint header{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
729
- .endpoint h3{margin:12px 0 4px;font-size:16px;}
730
- .endpoint h4{margin:18px 0 6px;font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);}
731
- .method,.tag{color:#fff;border-radius:4px;font-size:11px;font-weight:700;padding:2px 7px;letter-spacing:.04em;}
732
- .tag{min-width:52px;text-align:center;}
733
- ${methodCss}
734
- .path{font-size:14px;word-break:break-all;}
735
- .deprecated{background:#c2392e;color:#fff;border-radius:4px;font-size:11px;padding:2px 7px;}
736
- .muted{color:var(--muted);}
737
- .table-wrap{overflow-x:auto;}
738
- table{border-collapse:collapse;width:100%;font-size:13px;margin:6px 0 4px;}
739
- th,td{text-align:left;padding:6px 10px;border-bottom:1px solid var(--border);vertical-align:top;}
740
- th{color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.05em;}
741
- tr.nested td:first-child{padding-left:22px;}
742
- .type{color:var(--accent);font-family:ui-monospace,monospace;font-size:12px;}
743
- .req{color:#c2392e;font-size:11px;text-transform:uppercase;letter-spacing:.05em;}
744
- .opt{color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.05em;}
745
- .response{margin:10px 0;}
746
- .status{border-radius:4px;padding:2px 8px;font-size:12px;font-weight:700;color:#fff;}
747
- .status-ok{background:#1f8a4c;}
748
- .status-err{background:#c2392e;}
749
- pre{background:var(--code);border:1px solid var(--border);border-radius:8px;padding:12px 14px;overflow-x:auto;font-size:12.5px;}
750
- footer{color:var(--muted);font-size:12px;border-top:1px solid var(--border);padding-top:14px;}
751
- @media (max-width:860px){.layout{flex-direction:column;}aside{width:100%;flex:none;position:static;max-height:none;border-right:none;border-bottom:1px solid var(--border);}main{padding:24px 18px 60px;}}
752
- </style>
753
- </head>
754
- <body>
755
- <div class="layout">
756
- <aside>
757
- <h1>${escapeHtml(model.title)}</h1>
758
- <span class="version">v${escapeHtml(model.version)} · ${model.endpointCount} endpoints</span>
759
- <ul>${nav}</ul>
760
- </aside>
761
- <main>
762
- <div class="intro">
763
- <h1>${escapeHtml(model.title)}</h1>
764
- ${model.description ? `<p>${escapeHtml(model.description)}</p>` : ""}
765
- ${model.baseUrl ? `<p><span class="base-url">${escapeHtml(model.baseUrl)}</span></p>` : ""}
766
- </div>
767
- ${security}
768
- ${sections}
769
- <footer>Generated by api-docs-portal v${VERSION} on ${escapeHtml(model.generatedAt)}. Static, self-contained, no external requests.</footer>
770
- </main>
771
- </div>
772
- </body>
773
- </html>
774
- `;
775
- }
776
-
777
- function renderMarkdown(model: PortalModel): string {
778
- const lines: string[] = [];
779
- lines.push(`# ${model.title}`, "");
780
- lines.push(`Version: ${model.version}`);
781
- if (model.baseUrl) lines.push(`Base URL: \`${model.baseUrl}\``);
782
- lines.push(`Endpoints: ${model.endpointCount}`, "");
783
- if (model.description) lines.push(model.description, "");
784
-
785
- if (model.securitySchemes.length > 0) {
786
- lines.push("## Authentication", "");
787
- for (const scheme of model.securitySchemes) {
788
- lines.push(`- \`${scheme.name}\` — ${scheme.type}${scheme.detail ? ` (${scheme.detail})` : ""}`);
789
- }
790
- lines.push("");
791
- }
792
-
793
- for (const group of model.groups) {
794
- lines.push(`## ${group.name}`, "");
795
- if (group.description) lines.push(group.description, "");
796
- for (const endpoint of group.endpoints) {
797
- lines.push(`### ${endpoint.method} ${endpoint.path}`, "");
798
- if (endpoint.summary) lines.push(`${endpoint.summary}${endpoint.deprecated ? " **(deprecated)**" : ""}`, "");
799
- if (endpoint.description) lines.push(endpoint.description, "");
800
- if (endpoint.security.length > 0) lines.push(`Security: ${endpoint.security.join(", ")}`, "");
801
-
802
- if (endpoint.parameters.length > 0) {
803
- lines.push("| Parameter | In | Type | Required | Description |");
804
- lines.push("|-----------|----|------|----------|-------------|");
805
- for (const parameter of endpoint.parameters) {
806
- lines.push(
807
- `| \`${parameter.name}\` | ${parameter.in} | ${parameter.type} | ${parameter.required ? "yes" : "no"} | ${parameter.description.replace(/\|/gu, "\\|")} |`,
808
- );
809
- }
810
- lines.push("");
811
- }
812
-
813
- if (endpoint.requestBody) {
814
- lines.push(`Request body (\`${endpoint.requestBody.contentType}\`${endpoint.requestBody.required ? ", required" : ""}):`, "");
815
- if (endpoint.requestBody.schema.length > 0) {
816
- lines.push("| Field | Type | Required | Description |");
817
- lines.push("|-------|------|----------|-------------|");
818
- for (const field of endpoint.requestBody.schema) {
819
- lines.push(`| \`${field.name}\` | ${field.type} | ${field.required ? "yes" : "no"} | ${field.description.replace(/\|/gu, "\\|")} |`);
820
- }
821
- lines.push("");
822
- } else {
823
- lines.push("_No object schema declared._", "");
824
- }
825
- }
826
-
827
- if (endpoint.responses.length > 0) {
828
- lines.push("Responses:", "");
829
- for (const response of endpoint.responses) {
830
- const fields = response.schema.map((field) => `\`${field.name}\` (${field.type})`).join(", ");
831
- lines.push(
832
- `- **${response.status}** ${response.description}${response.contentType ? ` — ${response.contentType}` : ""}${fields ? ` — ${fields}` : ""}`,
833
- );
834
- }
835
- lines.push("");
836
- }
837
-
838
- lines.push("```bash", curlExample(endpoint, model.baseUrl), "```", "");
839
- }
840
- }
841
-
842
- lines.push(`_Generated by api-docs-portal v${VERSION} on ${model.generatedAt}._`);
843
- return `${lines.join("\n")}\n`;
844
- }
845
-
846
- /* ------------------------------------------------------------------ *
847
- * main
848
- * ------------------------------------------------------------------ */
849
-
850
- async function main(): Promise<void> {
851
- const options = parseArgs(process.argv.slice(2));
852
- const specPath = resolve(options.spec!);
853
- const outputDir = resolve(options.output);
854
-
855
- const spec = await loadSpec(specPath);
856
- const model = buildModel(spec, options);
857
-
858
- await mkdir(outputDir, { recursive: true });
859
- const files: string[] = [];
860
- const write = async (name: string, content: string) => {
861
- await writeFile(join(outputDir, name), content, "utf8");
862
- files.push(name);
863
- };
864
-
865
- await write("index.html", renderHtml(model));
866
- await write(
867
- "endpoints.json",
868
- `${JSON.stringify(
869
- {
870
- title: model.title,
871
- version: model.version,
872
- baseUrl: model.baseUrl,
873
- servers: model.servers,
874
- generatedAt: model.generatedAt,
875
- securitySchemes: model.securitySchemes,
876
- endpoints: model.groups.flatMap((group) => group.endpoints),
877
- },
878
- null,
879
- 2,
880
- )}\n`,
881
- );
882
- await write("reference.md", renderMarkdown(model));
883
-
884
- if (options.json) {
885
- process.stdout.write(
886
- `${JSON.stringify(
887
- {
888
- spec: specPath,
889
- outputDir,
890
- title: model.title,
891
- version: model.version,
892
- theme: model.theme,
893
- baseUrl: model.baseUrl,
894
- endpointCount: model.endpointCount,
895
- groups: model.groups.map((group) => ({ name: group.name, endpoints: group.endpoints.length })),
896
- files,
897
- },
898
- null,
899
- 2,
900
- )}\n`,
901
- );
902
- return;
903
- }
904
-
905
- console.log(`api-docs-portal: ${specPath}`);
906
- console.log(` title ${model.title} v${model.version}`);
907
- console.log(` base url ${model.baseUrl || "(none declared)"}`);
908
- console.log(` theme ${model.theme}`);
909
- console.log(` endpoints ${model.endpointCount} in ${model.groups.length} groups`);
910
- for (const group of model.groups) console.log(` ${group.name}: ${group.endpoints.length}`);
911
- console.log(` output ${outputDir}`);
912
- console.log(` files ${files.join(", ")}`);
913
- }
914
-
915
- main().catch((error) => {
916
- const message = error instanceof Error ? error.message : String(error);
917
- process.stderr.write(`api-docs-portal: ${message}\n`);
918
- process.exit(1);
919
- });