termcast 1.3.9

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 (699) hide show
  1. package/dist/action-utils.d.ts +25 -0
  2. package/dist/action-utils.d.ts.map +1 -0
  3. package/dist/action-utils.js +209 -0
  4. package/dist/action-utils.js.map +1 -0
  5. package/dist/ai.d.ts +104 -0
  6. package/dist/ai.d.ts.map +1 -0
  7. package/dist/ai.js +135 -0
  8. package/dist/ai.js.map +1 -0
  9. package/dist/apis/ai.d.ts +104 -0
  10. package/dist/apis/ai.d.ts.map +1 -0
  11. package/dist/apis/ai.js +135 -0
  12. package/dist/apis/ai.js.map +1 -0
  13. package/dist/apis/cache.d.ts +84 -0
  14. package/dist/apis/cache.d.ts.map +1 -0
  15. package/dist/apis/cache.js +307 -0
  16. package/dist/apis/cache.js.map +1 -0
  17. package/dist/apis/cache.test.d.ts +2 -0
  18. package/dist/apis/cache.test.d.ts.map +1 -0
  19. package/dist/apis/cache.test.js +246 -0
  20. package/dist/apis/cache.test.js.map +1 -0
  21. package/dist/apis/clipboard.d.ts +36 -0
  22. package/dist/apis/clipboard.d.ts.map +1 -0
  23. package/dist/apis/clipboard.js +154 -0
  24. package/dist/apis/clipboard.js.map +1 -0
  25. package/dist/apis/environment.d.ts +63 -0
  26. package/dist/apis/environment.d.ts.map +1 -0
  27. package/dist/apis/environment.js +189 -0
  28. package/dist/apis/environment.js.map +1 -0
  29. package/dist/apis/hud.d.ts +7 -0
  30. package/dist/apis/hud.d.ts.map +1 -0
  31. package/dist/apis/hud.js +45 -0
  32. package/dist/apis/hud.js.map +1 -0
  33. package/dist/apis/localstorage.d.ts +13 -0
  34. package/dist/apis/localstorage.d.ts.map +1 -0
  35. package/dist/apis/localstorage.js +190 -0
  36. package/dist/apis/localstorage.js.map +1 -0
  37. package/dist/apis/localstorage.test.d.ts +2 -0
  38. package/dist/apis/localstorage.test.d.ts.map +1 -0
  39. package/dist/apis/localstorage.test.js +131 -0
  40. package/dist/apis/localstorage.test.js.map +1 -0
  41. package/dist/apis/oauth.d.ts +142 -0
  42. package/dist/apis/oauth.d.ts.map +1 -0
  43. package/dist/apis/oauth.js +551 -0
  44. package/dist/apis/oauth.js.map +1 -0
  45. package/dist/apis/preferences.d.ts +23 -0
  46. package/dist/apis/preferences.d.ts.map +1 -0
  47. package/dist/apis/preferences.js +105 -0
  48. package/dist/apis/preferences.js.map +1 -0
  49. package/dist/apis/toast.d.ts +81 -0
  50. package/dist/apis/toast.d.ts.map +1 -0
  51. package/dist/apis/toast.js +275 -0
  52. package/dist/apis/toast.js.map +1 -0
  53. package/dist/apis/toast.test.d.ts +2 -0
  54. package/dist/apis/toast.test.d.ts.map +1 -0
  55. package/dist/apis/toast.test.js +67 -0
  56. package/dist/apis/toast.test.js.map +1 -0
  57. package/dist/apis/window.d.ts +12 -0
  58. package/dist/apis/window.d.ts.map +1 -0
  59. package/dist/apis/window.js +47 -0
  60. package/dist/apis/window.js.map +1 -0
  61. package/dist/build.d.ts +15 -0
  62. package/dist/build.d.ts.map +1 -0
  63. package/dist/build.js +213 -0
  64. package/dist/build.js.map +1 -0
  65. package/dist/build.test.d.ts +2 -0
  66. package/dist/build.test.d.ts.map +1 -0
  67. package/dist/build.test.js +73 -0
  68. package/dist/build.test.js.map +1 -0
  69. package/dist/cache.d.ts +32 -0
  70. package/dist/cache.d.ts.map +1 -0
  71. package/dist/cache.js +205 -0
  72. package/dist/cache.js.map +1 -0
  73. package/dist/cache.test.d.ts +2 -0
  74. package/dist/cache.test.d.ts.map +1 -0
  75. package/dist/cache.test.js +246 -0
  76. package/dist/cache.test.js.map +1 -0
  77. package/dist/cli.d.ts +2 -0
  78. package/dist/cli.d.ts.map +1 -0
  79. package/dist/cli.js +278 -0
  80. package/dist/cli.js.map +1 -0
  81. package/dist/clipboard.d.ts +36 -0
  82. package/dist/clipboard.d.ts.map +1 -0
  83. package/dist/clipboard.js +154 -0
  84. package/dist/clipboard.js.map +1 -0
  85. package/dist/colors.d.ts +15 -0
  86. package/dist/colors.d.ts.map +1 -0
  87. package/dist/colors.js +13 -0
  88. package/dist/colors.js.map +1 -0
  89. package/dist/components/actions.d.ts +120 -0
  90. package/dist/components/actions.d.ts.map +1 -0
  91. package/dist/components/actions.js +371 -0
  92. package/dist/components/actions.js.map +1 -0
  93. package/dist/components/alert.d.ts +25 -0
  94. package/dist/components/alert.d.ts.map +1 -0
  95. package/dist/components/alert.js +99 -0
  96. package/dist/components/alert.js.map +1 -0
  97. package/dist/components/detail.d.ts +65 -0
  98. package/dist/components/detail.d.ts.map +1 -0
  99. package/dist/components/detail.js +147 -0
  100. package/dist/components/detail.js.map +1 -0
  101. package/dist/components/dropdown.d.ts +40 -0
  102. package/dist/components/dropdown.d.ts.map +1 -0
  103. package/dist/components/dropdown.js +202 -0
  104. package/dist/components/dropdown.js.map +1 -0
  105. package/dist/components/extension-preferences.d.ts +8 -0
  106. package/dist/components/extension-preferences.d.ts.map +1 -0
  107. package/dist/components/extension-preferences.js +139 -0
  108. package/dist/components/extension-preferences.js.map +1 -0
  109. package/dist/components/form/assign-components.d.ts +2 -0
  110. package/dist/components/form/assign-components.d.ts.map +1 -0
  111. package/dist/components/form/assign-components.js +22 -0
  112. package/dist/components/form/assign-components.js.map +1 -0
  113. package/dist/components/form/checkbox.d.ts +7 -0
  114. package/dist/components/form/checkbox.d.ts.map +1 -0
  115. package/dist/components/form/checkbox.js +46 -0
  116. package/dist/components/form/checkbox.js.map +1 -0
  117. package/dist/components/form/date-picker.d.ts +18 -0
  118. package/dist/components/form/date-picker.d.ts.map +1 -0
  119. package/dist/components/form/date-picker.js +69 -0
  120. package/dist/components/form/date-picker.js.map +1 -0
  121. package/dist/components/form/description.d.ts +7 -0
  122. package/dist/components/form/description.d.ts.map +1 -0
  123. package/dist/components/form/description.js +8 -0
  124. package/dist/components/form/description.js.map +1 -0
  125. package/dist/components/form/dropdown.d.ts +25 -0
  126. package/dist/components/form/dropdown.d.ts.map +1 -0
  127. package/dist/components/form/dropdown.js +286 -0
  128. package/dist/components/form/dropdown.js.map +1 -0
  129. package/dist/components/form/file-autocomplete.d.ts +12 -0
  130. package/dist/components/form/file-autocomplete.d.ts.map +1 -0
  131. package/dist/components/form/file-autocomplete.js +84 -0
  132. package/dist/components/form/file-autocomplete.js.map +1 -0
  133. package/dist/components/form/file-picker.d.ts +31 -0
  134. package/dist/components/form/file-picker.d.ts.map +1 -0
  135. package/dist/components/form/file-picker.js +113 -0
  136. package/dist/components/form/file-picker.js.map +1 -0
  137. package/dist/components/form/form-end.d.ts +2 -0
  138. package/dist/components/form/form-end.d.ts.map +1 -0
  139. package/dist/components/form/form-end.js +6 -0
  140. package/dist/components/form/form-end.js.map +1 -0
  141. package/dist/components/form/form-type-only.d.ts +174 -0
  142. package/dist/components/form/form-type-only.d.ts.map +1 -0
  143. package/dist/components/form/form-type-only.js +2 -0
  144. package/dist/components/form/form-type-only.js.map +1 -0
  145. package/dist/components/form/index.d.ts +46 -0
  146. package/dist/components/form/index.d.ts.map +1 -0
  147. package/dist/components/form/index.js +106 -0
  148. package/dist/components/form/index.js.map +1 -0
  149. package/dist/components/form/password-field.d.ts +7 -0
  150. package/dist/components/form/password-field.d.ts.map +1 -0
  151. package/dist/components/form/password-field.js +34 -0
  152. package/dist/components/form/password-field.js.map +1 -0
  153. package/dist/components/form/separator.d.ts +2 -0
  154. package/dist/components/form/separator.d.ts.map +1 -0
  155. package/dist/components/form/separator.js +8 -0
  156. package/dist/components/form/separator.js.map +1 -0
  157. package/dist/components/form/tagpicker.d.ts +134 -0
  158. package/dist/components/form/tagpicker.d.ts.map +1 -0
  159. package/dist/components/form/tagpicker.js +79 -0
  160. package/dist/components/form/tagpicker.js.map +1 -0
  161. package/dist/components/form/text-area.d.ts +8 -0
  162. package/dist/components/form/text-area.d.ts.map +1 -0
  163. package/dist/components/form/text-area.js +26 -0
  164. package/dist/components/form/text-area.js.map +1 -0
  165. package/dist/components/form/text-field.d.ts +7 -0
  166. package/dist/components/form/text-field.d.ts.map +1 -0
  167. package/dist/components/form/text-field.js +28 -0
  168. package/dist/components/form/text-field.js.map +1 -0
  169. package/dist/components/form/types.d.ts +43 -0
  170. package/dist/components/form/types.d.ts.map +1 -0
  171. package/dist/components/form/types.js +2 -0
  172. package/dist/components/form/types.js.map +1 -0
  173. package/dist/components/form/use-form-handling.d.ts +4 -0
  174. package/dist/components/form/use-form-handling.d.ts.map +1 -0
  175. package/dist/components/form/use-form-handling.js +37 -0
  176. package/dist/components/form/use-form-handling.js.map +1 -0
  177. package/dist/components/form/use-form-navigation.d.ts +8 -0
  178. package/dist/components/form/use-form-navigation.d.ts.map +1 -0
  179. package/dist/components/form/use-form-navigation.js +58 -0
  180. package/dist/components/form/use-form-navigation.js.map +1 -0
  181. package/dist/components/form/with-left-border.d.ts +17 -0
  182. package/dist/components/form/with-left-border.d.ts.map +1 -0
  183. package/dist/components/form/with-left-border.js +10 -0
  184. package/dist/components/form/with-left-border.js.map +1 -0
  185. package/dist/components/icon.d.ts +9 -0
  186. package/dist/components/icon.d.ts.map +1 -0
  187. package/dist/components/icon.js +485 -0
  188. package/dist/components/icon.js.map +1 -0
  189. package/dist/components/image.d.ts +19 -0
  190. package/dist/components/image.d.ts.map +1 -0
  191. package/dist/components/image.js +32 -0
  192. package/dist/components/image.js.map +1 -0
  193. package/dist/components/list.d.ts +234 -0
  194. package/dist/components/list.d.ts.map +1 -0
  195. package/dist/components/list.js +667 -0
  196. package/dist/components/list.js.map +1 -0
  197. package/dist/components/loading-bar.d.ts +8 -0
  198. package/dist/components/loading-bar.d.ts.map +1 -0
  199. package/dist/components/loading-bar.js +107 -0
  200. package/dist/components/loading-bar.js.map +1 -0
  201. package/dist/components/menubar-extra.d.ts +68 -0
  202. package/dist/components/menubar-extra.d.ts.map +1 -0
  203. package/dist/components/menubar-extra.js +39 -0
  204. package/dist/components/menubar-extra.js.map +1 -0
  205. package/dist/descendants.d.ts +25 -0
  206. package/dist/descendants.d.ts.map +1 -0
  207. package/dist/descendants.js +81 -0
  208. package/dist/descendants.js.map +1 -0
  209. package/dist/dev-ui.d.ts +7 -0
  210. package/dist/dev-ui.d.ts.map +1 -0
  211. package/dist/dev-ui.js +118 -0
  212. package/dist/dev-ui.js.map +1 -0
  213. package/dist/e2e-node.d.ts +63 -0
  214. package/dist/e2e-node.d.ts.map +1 -0
  215. package/dist/e2e-node.js +255 -0
  216. package/dist/e2e-node.js.map +1 -0
  217. package/dist/e2e.d.ts +39 -0
  218. package/dist/e2e.d.ts.map +1 -0
  219. package/dist/e2e.js +127 -0
  220. package/dist/e2e.js.map +1 -0
  221. package/dist/environment.d.ts +63 -0
  222. package/dist/environment.d.ts.map +1 -0
  223. package/dist/environment.js +189 -0
  224. package/dist/environment.js.map +1 -0
  225. package/dist/examples/action-show-in-finder.d.ts +2 -0
  226. package/dist/examples/action-show-in-finder.d.ts.map +1 -0
  227. package/dist/examples/action-show-in-finder.js +13 -0
  228. package/dist/examples/action-show-in-finder.js.map +1 -0
  229. package/dist/examples/datepicker.d.ts +2 -0
  230. package/dist/examples/datepicker.d.ts.map +1 -0
  231. package/dist/examples/datepicker.js +344 -0
  232. package/dist/examples/datepicker.js.map +1 -0
  233. package/dist/examples/environment-test.d.ts +2 -0
  234. package/dist/examples/environment-test.d.ts.map +1 -0
  235. package/dist/examples/environment-test.js +28 -0
  236. package/dist/examples/environment-test.js.map +1 -0
  237. package/dist/examples/error-boundary.d.ts +6 -0
  238. package/dist/examples/error-boundary.d.ts.map +1 -0
  239. package/dist/examples/error-boundary.js +67 -0
  240. package/dist/examples/error-boundary.js.map +1 -0
  241. package/dist/examples/form-basic-arrow-keys.vitest.d.ts +2 -0
  242. package/dist/examples/form-basic-arrow-keys.vitest.d.ts.map +1 -0
  243. package/dist/examples/form-basic-arrow-keys.vitest.js +46 -0
  244. package/dist/examples/form-basic-arrow-keys.vitest.js.map +1 -0
  245. package/dist/examples/form-basic.d.ts +2 -0
  246. package/dist/examples/form-basic.d.ts.map +1 -0
  247. package/dist/examples/form-basic.js +21 -0
  248. package/dist/examples/form-basic.js.map +1 -0
  249. package/dist/examples/form-basic.vitest.d.ts +2 -0
  250. package/dist/examples/form-basic.vitest.d.ts.map +1 -0
  251. package/dist/examples/form-basic.vitest.js +995 -0
  252. package/dist/examples/form-basic.vitest.js.map +1 -0
  253. package/dist/examples/form-dropdown-with-sections.d.ts +2 -0
  254. package/dist/examples/form-dropdown-with-sections.d.ts.map +1 -0
  255. package/dist/examples/form-dropdown-with-sections.js +13 -0
  256. package/dist/examples/form-dropdown-with-sections.js.map +1 -0
  257. package/dist/examples/form-dropdown-with-sections.vitest.d.ts +2 -0
  258. package/dist/examples/form-dropdown-with-sections.vitest.d.ts.map +1 -0
  259. package/dist/examples/form-dropdown-with-sections.vitest.js +75 -0
  260. package/dist/examples/form-dropdown-with-sections.vitest.js.map +1 -0
  261. package/dist/examples/form-dropdown.d.ts +2 -0
  262. package/dist/examples/form-dropdown.d.ts.map +1 -0
  263. package/dist/examples/form-dropdown.js +13 -0
  264. package/dist/examples/form-dropdown.js.map +1 -0
  265. package/dist/examples/form-dropdown.vitest.d.ts +2 -0
  266. package/dist/examples/form-dropdown.vitest.d.ts.map +1 -0
  267. package/dist/examples/form-dropdown.vitest.js +722 -0
  268. package/dist/examples/form-dropdown.vitest.js.map +1 -0
  269. package/dist/examples/form-multiselect-dropdown.d.ts +2 -0
  270. package/dist/examples/form-multiselect-dropdown.d.ts.map +1 -0
  271. package/dist/examples/form-multiselect-dropdown.js +13 -0
  272. package/dist/examples/form-multiselect-dropdown.js.map +1 -0
  273. package/dist/examples/form-tagpicker.d.ts +2 -0
  274. package/dist/examples/form-tagpicker.d.ts.map +1 -0
  275. package/dist/examples/form-tagpicker.js +13 -0
  276. package/dist/examples/form-tagpicker.js.map +1 -0
  277. package/dist/examples/form-tagpicker.vitest.d.ts +2 -0
  278. package/dist/examples/form-tagpicker.vitest.d.ts.map +1 -0
  279. package/dist/examples/form-tagpicker.vitest.js +491 -0
  280. package/dist/examples/form-tagpicker.vitest.js.map +1 -0
  281. package/dist/examples/internal/descendants-filtering.d.ts +2 -0
  282. package/dist/examples/internal/descendants-filtering.d.ts.map +1 -0
  283. package/dist/examples/internal/descendants-filtering.js +144 -0
  284. package/dist/examples/internal/descendants-filtering.js.map +1 -0
  285. package/dist/examples/internal/descendants.d.ts +2 -0
  286. package/dist/examples/internal/descendants.d.ts.map +1 -0
  287. package/dist/examples/internal/descendants.js +134 -0
  288. package/dist/examples/internal/descendants.js.map +1 -0
  289. package/dist/examples/internal/nested-boxes.d.ts +2 -0
  290. package/dist/examples/internal/nested-boxes.d.ts.map +1 -0
  291. package/dist/examples/internal/nested-boxes.js +7 -0
  292. package/dist/examples/internal/nested-boxes.js.map +1 -0
  293. package/dist/examples/internal/scrollbox-demo.d.ts +2 -0
  294. package/dist/examples/internal/scrollbox-demo.d.ts.map +1 -0
  295. package/dist/examples/internal/scrollbox-demo.js +104 -0
  296. package/dist/examples/internal/scrollbox-demo.js.map +1 -0
  297. package/dist/examples/internal/simple-dialog.d.ts +2 -0
  298. package/dist/examples/internal/simple-dialog.d.ts.map +1 -0
  299. package/dist/examples/internal/simple-dialog.js +43 -0
  300. package/dist/examples/internal/simple-dialog.js.map +1 -0
  301. package/dist/examples/internal/text-stacking.d.ts +2 -0
  302. package/dist/examples/internal/text-stacking.d.ts.map +1 -0
  303. package/dist/examples/internal/text-stacking.js +53 -0
  304. package/dist/examples/internal/text-stacking.js.map +1 -0
  305. package/dist/examples/internal/unicode-square-repro.d.ts +2 -0
  306. package/dist/examples/internal/unicode-square-repro.d.ts.map +1 -0
  307. package/dist/examples/internal/unicode-square-repro.js +7 -0
  308. package/dist/examples/internal/unicode-square-repro.js.map +1 -0
  309. package/dist/examples/list-dropdown-default.d.ts +2 -0
  310. package/dist/examples/list-dropdown-default.d.ts.map +1 -0
  311. package/dist/examples/list-dropdown-default.js +14 -0
  312. package/dist/examples/list-dropdown-default.js.map +1 -0
  313. package/dist/examples/list-dropdown-default.vitest.d.ts +2 -0
  314. package/dist/examples/list-dropdown-default.vitest.d.ts.map +1 -0
  315. package/dist/examples/list-dropdown-default.vitest.js +164 -0
  316. package/dist/examples/list-dropdown-default.vitest.js.map +1 -0
  317. package/dist/examples/list-fetch-data.d.ts +2 -0
  318. package/dist/examples/list-fetch-data.d.ts.map +1 -0
  319. package/dist/examples/list-fetch-data.js +87 -0
  320. package/dist/examples/list-fetch-data.js.map +1 -0
  321. package/dist/examples/list-fetch-data.vitest.d.ts +2 -0
  322. package/dist/examples/list-fetch-data.vitest.d.ts.map +1 -0
  323. package/dist/examples/list-fetch-data.vitest.js +103 -0
  324. package/dist/examples/list-fetch-data.vitest.js.map +1 -0
  325. package/dist/examples/list-filter-navigation.d.ts +2 -0
  326. package/dist/examples/list-filter-navigation.d.ts.map +1 -0
  327. package/dist/examples/list-filter-navigation.js +8 -0
  328. package/dist/examples/list-filter-navigation.js.map +1 -0
  329. package/dist/examples/list-with-detail.d.ts +2 -0
  330. package/dist/examples/list-with-detail.d.ts.map +1 -0
  331. package/dist/examples/list-with-detail.js +94 -0
  332. package/dist/examples/list-with-detail.js.map +1 -0
  333. package/dist/examples/list-with-detail.vitest.d.ts +2 -0
  334. package/dist/examples/list-with-detail.vitest.d.ts.map +1 -0
  335. package/dist/examples/list-with-detail.vitest.js +438 -0
  336. package/dist/examples/list-with-detail.vitest.js.map +1 -0
  337. package/dist/examples/list-with-dropdown.d.ts +2 -0
  338. package/dist/examples/list-with-dropdown.d.ts.map +1 -0
  339. package/dist/examples/list-with-dropdown.js +43 -0
  340. package/dist/examples/list-with-dropdown.js.map +1 -0
  341. package/dist/examples/list-with-dropdown.vitest.d.ts +2 -0
  342. package/dist/examples/list-with-dropdown.vitest.d.ts.map +1 -0
  343. package/dist/examples/list-with-dropdown.vitest.js +297 -0
  344. package/dist/examples/list-with-dropdown.vitest.js.map +1 -0
  345. package/dist/examples/list-with-sections.d.ts +2 -0
  346. package/dist/examples/list-with-sections.d.ts.map +1 -0
  347. package/dist/examples/list-with-sections.js +67 -0
  348. package/dist/examples/list-with-sections.js.map +1 -0
  349. package/dist/examples/list-with-sections.vitest.d.ts +2 -0
  350. package/dist/examples/list-with-sections.vitest.d.ts.map +1 -0
  351. package/dist/examples/list-with-sections.vitest.js +441 -0
  352. package/dist/examples/list-with-sections.vitest.js.map +1 -0
  353. package/dist/examples/miscellaneous.d.ts +2 -0
  354. package/dist/examples/miscellaneous.d.ts.map +1 -0
  355. package/dist/examples/miscellaneous.js +313 -0
  356. package/dist/examples/miscellaneous.js.map +1 -0
  357. package/dist/examples/nested-navigation.d.ts +2 -0
  358. package/dist/examples/nested-navigation.d.ts.map +1 -0
  359. package/dist/examples/nested-navigation.js +35 -0
  360. package/dist/examples/nested-navigation.js.map +1 -0
  361. package/dist/examples/preferences-test.d.ts +2 -0
  362. package/dist/examples/preferences-test.d.ts.map +1 -0
  363. package/dist/examples/preferences-test.js +43 -0
  364. package/dist/examples/preferences-test.js.map +1 -0
  365. package/dist/examples/simple-dropdown.d.ts +2 -0
  366. package/dist/examples/simple-dropdown.d.ts.map +1 -0
  367. package/dist/examples/simple-dropdown.js +15 -0
  368. package/dist/examples/simple-dropdown.js.map +1 -0
  369. package/dist/examples/simple-file-picker.d.ts +2 -0
  370. package/dist/examples/simple-file-picker.d.ts.map +1 -0
  371. package/dist/examples/simple-file-picker.js +21 -0
  372. package/dist/examples/simple-file-picker.js.map +1 -0
  373. package/dist/examples/simple-file-picker.vitest.d.ts +2 -0
  374. package/dist/examples/simple-file-picker.vitest.d.ts.map +1 -0
  375. package/dist/examples/simple-file-picker.vitest.js +277 -0
  376. package/dist/examples/simple-file-picker.vitest.js.map +1 -0
  377. package/dist/examples/simple-grid.d.ts +2 -0
  378. package/dist/examples/simple-grid.d.ts.map +1 -0
  379. package/dist/examples/simple-grid.js +51 -0
  380. package/dist/examples/simple-grid.js.map +1 -0
  381. package/dist/examples/simple-grid.vitest.d.ts +2 -0
  382. package/dist/examples/simple-grid.vitest.d.ts.map +1 -0
  383. package/dist/examples/simple-grid.vitest.js +498 -0
  384. package/dist/examples/simple-grid.vitest.js.map +1 -0
  385. package/dist/examples/simple-hud.d.ts +2 -0
  386. package/dist/examples/simple-hud.d.ts.map +1 -0
  387. package/dist/examples/simple-hud.js +18 -0
  388. package/dist/examples/simple-hud.js.map +1 -0
  389. package/dist/examples/simple-list-search.d.ts +2 -0
  390. package/dist/examples/simple-list-search.d.ts.map +1 -0
  391. package/dist/examples/simple-list-search.js +26 -0
  392. package/dist/examples/simple-list-search.js.map +1 -0
  393. package/dist/examples/simple-list.d.ts +2 -0
  394. package/dist/examples/simple-list.d.ts.map +1 -0
  395. package/dist/examples/simple-list.js +50 -0
  396. package/dist/examples/simple-list.js.map +1 -0
  397. package/dist/examples/simple-navigation.d.ts +2 -0
  398. package/dist/examples/simple-navigation.d.ts.map +1 -0
  399. package/dist/examples/simple-navigation.js +36 -0
  400. package/dist/examples/simple-navigation.js.map +1 -0
  401. package/dist/examples/simple-navigation.vitest.d.ts +2 -0
  402. package/dist/examples/simple-navigation.vitest.d.ts.map +1 -0
  403. package/dist/examples/simple-navigation.vitest.js +522 -0
  404. package/dist/examples/simple-navigation.vitest.js.map +1 -0
  405. package/dist/examples/store.d.ts +2 -0
  406. package/dist/examples/store.d.ts.map +1 -0
  407. package/dist/examples/store.js +5 -0
  408. package/dist/examples/store.js.map +1 -0
  409. package/dist/examples/store.vitest.d.ts +2 -0
  410. package/dist/examples/store.vitest.d.ts.map +1 -0
  411. package/dist/examples/store.vitest.js +52 -0
  412. package/dist/examples/store.vitest.js.map +1 -0
  413. package/dist/examples/tanstack-demo.d.ts +2 -0
  414. package/dist/examples/tanstack-demo.d.ts.map +1 -0
  415. package/dist/examples/tanstack-demo.js +51 -0
  416. package/dist/examples/tanstack-demo.js.map +1 -0
  417. package/dist/examples/use-promise-demo.d.ts +2 -0
  418. package/dist/examples/use-promise-demo.d.ts.map +1 -0
  419. package/dist/examples/use-promise-demo.js +45 -0
  420. package/dist/examples/use-promise-demo.js.map +1 -0
  421. package/dist/extensions/dev.d.ts +7 -0
  422. package/dist/extensions/dev.d.ts.map +1 -0
  423. package/dist/extensions/dev.js +124 -0
  424. package/dist/extensions/dev.js.map +1 -0
  425. package/dist/extensions/home.d.ts +8 -0
  426. package/dist/extensions/home.d.ts.map +1 -0
  427. package/dist/extensions/home.js +184 -0
  428. package/dist/extensions/home.js.map +1 -0
  429. package/dist/extensions/store.d.ts +6 -0
  430. package/dist/extensions/store.d.ts.map +1 -0
  431. package/dist/extensions/store.js +203 -0
  432. package/dist/extensions/store.js.map +1 -0
  433. package/dist/globals.d.ts +9 -0
  434. package/dist/globals.d.ts.map +1 -0
  435. package/dist/globals.js +21 -0
  436. package/dist/globals.js.map +1 -0
  437. package/dist/home-command.d.ts +8 -0
  438. package/dist/home-command.d.ts.map +1 -0
  439. package/dist/home-command.js +181 -0
  440. package/dist/home-command.js.map +1 -0
  441. package/dist/hooks/hooks.test.d.ts +2 -0
  442. package/dist/hooks/hooks.test.d.ts.map +1 -0
  443. package/dist/hooks/hooks.test.js +37 -0
  444. package/dist/hooks/hooks.test.js.map +1 -0
  445. package/dist/hooks/index.d.ts +6 -0
  446. package/dist/hooks/index.d.ts.map +1 -0
  447. package/dist/hooks/index.js +6 -0
  448. package/dist/hooks/index.js.map +1 -0
  449. package/dist/hooks/use-action-panel.d.ts +16 -0
  450. package/dist/hooks/use-action-panel.d.ts.map +1 -0
  451. package/dist/hooks/use-action-panel.js +19 -0
  452. package/dist/hooks/use-action-panel.js.map +1 -0
  453. package/dist/hooks/use-id.d.ts +9 -0
  454. package/dist/hooks/use-id.d.ts.map +1 -0
  455. package/dist/hooks/use-id.js +17 -0
  456. package/dist/hooks/use-id.js.map +1 -0
  457. package/dist/hooks/use-unstable-ai.d.ts +9 -0
  458. package/dist/hooks/use-unstable-ai.d.ts.map +1 -0
  459. package/dist/hooks/use-unstable-ai.js +13 -0
  460. package/dist/hooks/use-unstable-ai.js.map +1 -0
  461. package/dist/hooks.d.ts +10 -0
  462. package/dist/hooks.d.ts.map +1 -0
  463. package/dist/hooks.js +20 -0
  464. package/dist/hooks.js.map +1 -0
  465. package/dist/hover-repro.d.ts +2 -0
  466. package/dist/hover-repro.d.ts.map +1 -0
  467. package/dist/hover-repro.js +20 -0
  468. package/dist/hover-repro.js.map +1 -0
  469. package/dist/index.d.ts +58 -0
  470. package/dist/index.d.ts.map +1 -0
  471. package/dist/index.js +71 -0
  472. package/dist/index.js.map +1 -0
  473. package/dist/internal/date-picker-widget.d.ts +9 -0
  474. package/dist/internal/date-picker-widget.d.ts.map +1 -0
  475. package/dist/internal/date-picker-widget.js +380 -0
  476. package/dist/internal/date-picker-widget.js.map +1 -0
  477. package/dist/internal/dialog.d.ts +21 -0
  478. package/dist/internal/dialog.d.ts.map +1 -0
  479. package/dist/internal/dialog.js +122 -0
  480. package/dist/internal/dialog.js.map +1 -0
  481. package/dist/internal/error-handler.d.ts +2 -0
  482. package/dist/internal/error-handler.d.ts.map +1 -0
  483. package/dist/internal/error-handler.js +29 -0
  484. package/dist/internal/error-handler.js.map +1 -0
  485. package/dist/internal/focus-context.d.ts +10 -0
  486. package/dist/internal/focus-context.d.ts.map +1 -0
  487. package/dist/internal/focus-context.js +12 -0
  488. package/dist/internal/focus-context.js.map +1 -0
  489. package/dist/internal/navigation.d.ts +18 -0
  490. package/dist/internal/navigation.d.ts.map +1 -0
  491. package/dist/internal/navigation.js +83 -0
  492. package/dist/internal/navigation.js.map +1 -0
  493. package/dist/internal/providers.d.ts +8 -0
  494. package/dist/internal/providers.d.ts.map +1 -0
  495. package/dist/internal/providers.js +262 -0
  496. package/dist/internal/providers.js.map +1 -0
  497. package/dist/localstorage.d.ts +13 -0
  498. package/dist/localstorage.d.ts.map +1 -0
  499. package/dist/localstorage.js +190 -0
  500. package/dist/localstorage.js.map +1 -0
  501. package/dist/localstorage.test.d.ts +2 -0
  502. package/dist/localstorage.test.d.ts.map +1 -0
  503. package/dist/localstorage.test.js +131 -0
  504. package/dist/localstorage.test.js.map +1 -0
  505. package/dist/logger.d.ts +7 -0
  506. package/dist/logger.d.ts.map +1 -0
  507. package/dist/logger.js +70 -0
  508. package/dist/logger.js.map +1 -0
  509. package/dist/oauth.d.ts +142 -0
  510. package/dist/oauth.d.ts.map +1 -0
  511. package/dist/oauth.js +551 -0
  512. package/dist/oauth.js.map +1 -0
  513. package/dist/package-json.d.ts +84 -0
  514. package/dist/package-json.d.ts.map +1 -0
  515. package/dist/package-json.js +77 -0
  516. package/dist/package-json.js.map +1 -0
  517. package/dist/preferences.d.ts +23 -0
  518. package/dist/preferences.d.ts.map +1 -0
  519. package/dist/preferences.js +105 -0
  520. package/dist/preferences.js.map +1 -0
  521. package/dist/preload.d.ts +2 -0
  522. package/dist/preload.d.ts.map +1 -0
  523. package/dist/preload.js +28 -0
  524. package/dist/preload.js.map +1 -0
  525. package/dist/state.d.ts +26 -0
  526. package/dist/state.d.ts.map +1 -0
  527. package/dist/state.js +18 -0
  528. package/dist/state.js.map +1 -0
  529. package/dist/store-api/download.d.ts +8 -0
  530. package/dist/store-api/download.d.ts.map +1 -0
  531. package/dist/store-api/download.js +37 -0
  532. package/dist/store-api/download.js.map +1 -0
  533. package/dist/store-api/download.test.d.ts +2 -0
  534. package/dist/store-api/download.test.d.ts.map +1 -0
  535. package/dist/store-api/download.test.js +36 -0
  536. package/dist/store-api/download.test.js.map +1 -0
  537. package/dist/store-api/extension.d.ts +87 -0
  538. package/dist/store-api/extension.d.ts.map +1 -0
  539. package/dist/store-api/extension.js +23 -0
  540. package/dist/store-api/extension.js.map +1 -0
  541. package/dist/store-api/extension.test.d.ts +2 -0
  542. package/dist/store-api/extension.test.d.ts.map +1 -0
  543. package/dist/store-api/extension.test.js +22 -0
  544. package/dist/store-api/extension.test.js.map +1 -0
  545. package/dist/store-api/search.d.ts +101 -0
  546. package/dist/store-api/search.d.ts.map +1 -0
  547. package/dist/store-api/search.js +29 -0
  548. package/dist/store-api/search.js.map +1 -0
  549. package/dist/store-api/search.test.d.ts +2 -0
  550. package/dist/store-api/search.test.d.ts.map +1 -0
  551. package/dist/store-api/search.test.js +45 -0
  552. package/dist/store-api/search.test.js.map +1 -0
  553. package/dist/store.d.ts +21 -0
  554. package/dist/store.d.ts.map +1 -0
  555. package/dist/store.js +84 -0
  556. package/dist/store.js.map +1 -0
  557. package/dist/theme.d.ts +20 -0
  558. package/dist/theme.d.ts.map +1 -0
  559. package/dist/theme.js +26 -0
  560. package/dist/theme.js.map +1 -0
  561. package/dist/toast.d.ts +44 -0
  562. package/dist/toast.d.ts.map +1 -0
  563. package/dist/toast.js +221 -0
  564. package/dist/toast.js.map +1 -0
  565. package/dist/utils/file-system.d.ts +11 -0
  566. package/dist/utils/file-system.d.ts.map +1 -0
  567. package/dist/utils/file-system.js +66 -0
  568. package/dist/utils/file-system.js.map +1 -0
  569. package/dist/utils.d.ts +234 -0
  570. package/dist/utils.d.ts.map +1 -0
  571. package/dist/utils.js +473 -0
  572. package/dist/utils.js.map +1 -0
  573. package/dist/utils.test.d.ts +2 -0
  574. package/dist/utils.test.d.ts.map +1 -0
  575. package/dist/utils.test.js +152 -0
  576. package/dist/utils.test.js.map +1 -0
  577. package/dist/window.d.ts +12 -0
  578. package/dist/window.d.ts.map +1 -0
  579. package/dist/window.js +48 -0
  580. package/dist/window.js.map +1 -0
  581. package/package.json +56 -0
  582. package/src/action-utils.tsx +207 -0
  583. package/src/apis/ai.tsx +177 -0
  584. package/src/apis/cache.test.ts +311 -0
  585. package/src/apis/cache.tsx +394 -0
  586. package/src/apis/clipboard.tsx +200 -0
  587. package/src/apis/environment.tsx +239 -0
  588. package/src/apis/hud.tsx +86 -0
  589. package/src/apis/localstorage.test.ts +164 -0
  590. package/src/apis/localstorage.tsx +215 -0
  591. package/src/apis/oauth.tsx +744 -0
  592. package/src/apis/preferences.tsx +140 -0
  593. package/src/apis/toast.tsx +388 -0
  594. package/src/apis/window.tsx +61 -0
  595. package/src/build.test.tsx +78 -0
  596. package/src/build.tsx +273 -0
  597. package/src/cli.tsx +328 -0
  598. package/src/colors.tsx +15 -0
  599. package/src/components/actions.tsx +718 -0
  600. package/src/components/alert.tsx +205 -0
  601. package/src/components/detail.tsx +359 -0
  602. package/src/components/dropdown.tsx +438 -0
  603. package/src/components/extension-preferences.tsx +269 -0
  604. package/src/components/form/assign-components.tsx +22 -0
  605. package/src/components/form/checkbox.tsx +96 -0
  606. package/src/components/form/date-picker.tsx +125 -0
  607. package/src/components/form/description.tsx +30 -0
  608. package/src/components/form/dropdown.tsx +512 -0
  609. package/src/components/form/file-autocomplete.tsx +141 -0
  610. package/src/components/form/file-picker.tsx +233 -0
  611. package/src/components/form/form-end.tsx +6 -0
  612. package/src/components/form/index.tsx +242 -0
  613. package/src/components/form/password-field.tsx +87 -0
  614. package/src/components/form/separator.tsx +15 -0
  615. package/src/components/form/tagpicker.tsx +245 -0
  616. package/src/components/form/text-area.tsx +82 -0
  617. package/src/components/form/text-field.tsx +82 -0
  618. package/src/components/form/types.tsx +49 -0
  619. package/src/components/form/use-form-navigation.tsx +65 -0
  620. package/src/components/form/with-left-border.tsx +53 -0
  621. package/src/components/icon.tsx +496 -0
  622. package/src/components/image.tsx +54 -0
  623. package/src/components/list.tsx +1564 -0
  624. package/src/components/loading-bar.tsx +141 -0
  625. package/src/components/menubar-extra.tsx +181 -0
  626. package/src/descendants.tsx +134 -0
  627. package/src/e2e-node.tsx +303 -0
  628. package/src/e2e.tsx +147 -0
  629. package/src/examples/action-show-in-finder.tsx +80 -0
  630. package/src/examples/environment-test.tsx +50 -0
  631. package/src/examples/error-boundary.tsx +217 -0
  632. package/src/examples/form-basic.tsx +122 -0
  633. package/src/examples/form-basic.vitest.tsx +1035 -0
  634. package/src/examples/form-dropdown.tsx +102 -0
  635. package/src/examples/form-dropdown.vitest.tsx +758 -0
  636. package/src/examples/form-tagpicker.tsx +66 -0
  637. package/src/examples/form-tagpicker.vitest.tsx +523 -0
  638. package/src/examples/internal/descendants-filtering.tsx +223 -0
  639. package/src/examples/internal/descendants.tsx +208 -0
  640. package/src/examples/internal/scrollbox-demo.tsx +149 -0
  641. package/src/examples/internal/simple-dialog.tsx +124 -0
  642. package/src/examples/internal/text-stacking.tsx +90 -0
  643. package/src/examples/list-dropdown-default.tsx +69 -0
  644. package/src/examples/list-dropdown-default.vitest.tsx +187 -0
  645. package/src/examples/list-fetch-data.tsx +123 -0
  646. package/src/examples/list-fetch-data.vitest.tsx +110 -0
  647. package/src/examples/list-with-detail.tsx +161 -0
  648. package/src/examples/list-with-detail.vitest.tsx +468 -0
  649. package/src/examples/list-with-dropdown.tsx +97 -0
  650. package/src/examples/list-with-dropdown.vitest.tsx +324 -0
  651. package/src/examples/list-with-sections.tsx +196 -0
  652. package/src/examples/list-with-sections.vitest.tsx +479 -0
  653. package/src/examples/miscellaneous.tsx +780 -0
  654. package/src/examples/nested-navigation.tsx +118 -0
  655. package/src/examples/preferences-test.tsx +82 -0
  656. package/src/examples/simple-dropdown.tsx +95 -0
  657. package/src/examples/simple-file-picker.tsx +75 -0
  658. package/src/examples/simple-file-picker.vitest.tsx +306 -0
  659. package/src/examples/simple-grid.tsx +149 -0
  660. package/src/examples/simple-grid.vitest.tsx +535 -0
  661. package/src/examples/simple-hud.tsx +60 -0
  662. package/src/examples/simple-list-search.tsx +93 -0
  663. package/src/examples/simple-list.tsx +149 -0
  664. package/src/examples/simple-navigation.tsx +89 -0
  665. package/src/examples/simple-navigation.vitest.tsx +571 -0
  666. package/src/examples/store.tsx +4 -0
  667. package/src/examples/store.vitest.tsx +59 -0
  668. package/src/examples/tanstack-demo.tsx +104 -0
  669. package/src/examples/use-promise-demo.tsx +96 -0
  670. package/src/extensions/dev.tsx +215 -0
  671. package/src/extensions/home.tsx +332 -0
  672. package/src/extensions/store.tsx +375 -0
  673. package/src/globals.ts +34 -0
  674. package/src/hooks/index.tsx +8 -0
  675. package/src/hooks/use-action-panel.tsx +28 -0
  676. package/src/hooks/use-id.tsx +19 -0
  677. package/src/hooks/use-unstable-ai.tsx +15 -0
  678. package/src/hooks.tsx +22 -0
  679. package/src/index.tsx +240 -0
  680. package/src/internal/date-picker-widget.tsx +500 -0
  681. package/src/internal/dialog.tsx +202 -0
  682. package/src/internal/error-handler.tsx +32 -0
  683. package/src/internal/focus-context.tsx +23 -0
  684. package/src/internal/navigation.tsx +149 -0
  685. package/src/internal/providers.tsx +430 -0
  686. package/src/logger.tsx +84 -0
  687. package/src/package-json.tsx +197 -0
  688. package/src/preload.tsx +32 -0
  689. package/src/state.tsx +49 -0
  690. package/src/store-api/download.test.tsx +38 -0
  691. package/src/store-api/download.tsx +52 -0
  692. package/src/store-api/extension.test.tsx +24 -0
  693. package/src/store-api/extension.tsx +123 -0
  694. package/src/store-api/search.test.tsx +50 -0
  695. package/src/store-api/search.tsx +146 -0
  696. package/src/theme.tsx +31 -0
  697. package/src/utils/file-system.ts +87 -0
  698. package/src/utils.test.tsx +204 -0
  699. package/src/utils.tsx +657 -0
@@ -0,0 +1,744 @@
1
+ /**
2
+ * OAuth Implicit Flow Implementation
3
+ *
4
+ * The implicit flow returns tokens directly in the redirect URL fragment
5
+ * without requiring a client secret. This is ideal for public clients
6
+ * like browser extensions and CLI tools that need ID tokens.
7
+ *
8
+ * Key features:
9
+ * - Implicit flow for public clients (no client secret required)
10
+ * - Direct token retrieval without server-side exchange
11
+ * - Support for ID tokens and access tokens
12
+ * - Automatic token storage and retrieval
13
+ * - Token expiration checking with buffer
14
+ * - Provider configuration with name and icon
15
+ *
16
+ * Usage:
17
+ * const client = new OAuth.PKCEClient({
18
+ * redirectMethod: OAuth.RedirectMethod.AppURI,
19
+ * providerName: "Google",
20
+ * providerIcon: "google-icon.png"
21
+ * })
22
+ *
23
+ * const authRequest = await client.authorizationRequest({
24
+ * endpoint: "https://accounts.google.com/o/oauth2/v2/auth",
25
+ * clientId: "your-client-id",
26
+ * scope: "openid email profile"
27
+ * })
28
+ *
29
+ * const authResponse = await client.authorize(authRequest)
30
+ * // Tokens are returned directly (idToken, accessToken)
31
+ * await client.setTokens({
32
+ * accessToken: authResponse.accessToken,
33
+ * idToken: authResponse.idToken
34
+ * })
35
+ */
36
+
37
+ import crypto from 'node:crypto'
38
+ import http from 'node:http'
39
+ import { ImageLike } from 'termcast/src/components/image'
40
+ import { logger } from 'termcast/src/logger'
41
+ import { LocalStorage } from 'termcast/src/apis/localstorage'
42
+ import { exec } from 'node:child_process'
43
+ import { promisify } from 'node:util'
44
+
45
+ const execAsync = promisify(exec)
46
+
47
+ export namespace OAuth {
48
+ export enum RedirectMethod {
49
+ Web = 'web',
50
+ App = 'app',
51
+ AppURI = 'appURI',
52
+ Device = 'device',
53
+ Implicit = 'implicit',
54
+ }
55
+
56
+ export interface AuthorizationRequestOptions {
57
+ endpoint: string
58
+ clientId: string
59
+ scope: string
60
+ extraParameters?: { [key: string]: string }
61
+ }
62
+
63
+ export interface AuthorizationRequestURLParams {
64
+ codeChallenge: string
65
+ codeVerifier: string
66
+ state: string
67
+ redirectURI: string
68
+ }
69
+
70
+ export interface AuthorizationRequest extends AuthorizationRequestURLParams {
71
+ toURL(): string
72
+ }
73
+
74
+ export interface AuthorizationOptions {
75
+ url: string
76
+ }
77
+
78
+ export interface AuthorizationResponse {
79
+ authorizationCode: string
80
+ state?: string
81
+ idToken?: string
82
+ accessToken?: string
83
+ }
84
+
85
+ export interface DeviceCodeRequest {
86
+ deviceCode: string
87
+ userCode: string
88
+ verificationUrl: string
89
+ verificationUrlComplete?: string
90
+ expiresIn: number
91
+ interval: number
92
+ }
93
+
94
+ export interface DeviceAuthorizationOptions {
95
+ endpoint: string
96
+ clientId: string
97
+ scope: string
98
+ clientSecret?: string
99
+ }
100
+
101
+ export interface TokenSet {
102
+ accessToken: string
103
+ refreshToken?: string
104
+ idToken?: string
105
+ expiresIn?: number
106
+ scope?: string
107
+ updatedAt: Date
108
+ isExpired(): boolean
109
+ }
110
+
111
+ export interface TokenSetOptions {
112
+ accessToken: string
113
+ refreshToken?: string
114
+ idToken?: string
115
+ expiresIn?: number
116
+ scope?: string
117
+ }
118
+
119
+ export interface TokenResponse {
120
+ access_token: string
121
+ refresh_token?: string
122
+ id_token?: string
123
+ expires_in?: number
124
+ scope?: string
125
+ }
126
+
127
+ export namespace PKCEClient {
128
+ export interface Options {
129
+ redirectMethod: RedirectMethod
130
+ providerName: string
131
+ providerIcon?: ImageLike
132
+ providerId?: string
133
+ description?: string
134
+ }
135
+ }
136
+
137
+ export class PKCEClient {
138
+ redirectMethod: RedirectMethod
139
+ providerName: string
140
+ providerIcon?: ImageLike
141
+ providerId: string
142
+ description?: string
143
+ private storageKey: string
144
+ private implicitFlowTokens?: TokenSetOptions // Store tokens from implicit flow
145
+
146
+ // Properties expected by @raycast/utils
147
+ isAuthorizing: boolean = false
148
+ authorizationURL?: string
149
+
150
+ constructor(options: PKCEClient.Options) {
151
+ this.redirectMethod = options.redirectMethod
152
+ this.providerName = options.providerName
153
+ this.providerIcon = options.providerIcon
154
+ this.providerId =
155
+ options.providerId ||
156
+ options.providerName.toLowerCase().replace(/\s+/g, '-')
157
+ this.description = options.description
158
+ this.storageKey = `oauth-${this.providerId}`
159
+
160
+ // Bind all methods to this instance
161
+ this.authorizationRequest = this.authorizationRequest.bind(this)
162
+ this.authorize = this.authorize.bind(this)
163
+ this.setTokens = this.setTokens.bind(this)
164
+ this.getTokens = this.getTokens.bind(this)
165
+ this.removeTokens = this.removeTokens.bind(this)
166
+ this.generateCodeVerifier = this.generateCodeVerifier.bind(this)
167
+ this.generateCodeChallenge = this.generateCodeChallenge.bind(this)
168
+
169
+ logger.log('PKCEClient initialized', {
170
+ providerName: this.providerName,
171
+ providerId: this.providerId,
172
+ redirectMethod: this.redirectMethod,
173
+ })
174
+ }
175
+
176
+ async authorizationRequest(
177
+ options: AuthorizationRequestOptions,
178
+ ): Promise<AuthorizationRequest> {
179
+ // Generate PKCE parameters
180
+ const codeVerifier = this.generateCodeVerifier()
181
+ const codeChallenge = this.generateCodeChallenge(codeVerifier)
182
+ const state = crypto.randomBytes(32).toString('hex')
183
+
184
+ // Always use localhost for implicit flow
185
+ const redirectURI = 'http://localhost:8989/oauth/callback'
186
+
187
+ const request: AuthorizationRequest = {
188
+ codeChallenge,
189
+ codeVerifier,
190
+ state,
191
+ redirectURI,
192
+ toURL: () => {
193
+ // Always use implicit flow parameters
194
+ const params = new URLSearchParams({
195
+ response_type:
196
+ options.extraParameters?.response_type || 'id_token token',
197
+ client_id: options.clientId,
198
+ redirect_uri: redirectURI,
199
+ scope: options.scope,
200
+ state: state,
201
+ nonce: crypto.randomBytes(32).toString('hex'),
202
+ ...options.extraParameters,
203
+ })
204
+
205
+ return `${options.endpoint}?${params.toString()}`
206
+ },
207
+ }
208
+
209
+ return request
210
+ }
211
+
212
+ async authorizeDevice(
213
+ options: DeviceAuthorizationOptions,
214
+ ): Promise<AuthorizationResponse> {
215
+ logger.log('Starting device authorization flow', {
216
+ endpoint: options.endpoint,
217
+ })
218
+
219
+ // Step 1: Request device and user codes
220
+ const deviceResponse = await this.requestDeviceCode(options)
221
+
222
+ // Step 2: Open browser with the verification URL
223
+ // Use the complete URL if available (it includes the user code)
224
+ const url =
225
+ deviceResponse.verificationUrlComplete ||
226
+ `${deviceResponse.verificationUrl}?user_code=${deviceResponse.userCode}`
227
+
228
+ logger.log('Opening browser for device authorization', {
229
+ url: deviceResponse.verificationUrl,
230
+ userCode: deviceResponse.userCode,
231
+ })
232
+
233
+ try {
234
+ const platform = process.platform
235
+ let command: string
236
+
237
+ if (platform === 'darwin') {
238
+ command = `open "${url}"`
239
+ } else if (platform === 'win32') {
240
+ command = `start "" "${url}"`
241
+ } else {
242
+ command = `xdg-open "${url}" || sensible-browser "${url}" || x-www-browser "${url}"`
243
+ }
244
+
245
+ await execAsync(command)
246
+ logger.log('Browser opened successfully with device authorization URL')
247
+ } catch (error) {
248
+ logger.error('Failed to open browser automatically:', error)
249
+ logger.log('Please manually open:', url)
250
+ }
251
+
252
+ // Step 3: Poll for authorization
253
+ const tokenResponse = await this.pollForToken({
254
+ ...options,
255
+ deviceCode: deviceResponse.deviceCode,
256
+ interval: deviceResponse.interval,
257
+ expiresIn: deviceResponse.expiresIn,
258
+ })
259
+
260
+ return {
261
+ authorizationCode: tokenResponse.access_token,
262
+ state: undefined,
263
+ }
264
+ }
265
+
266
+ private async requestDeviceCode(
267
+ options: DeviceAuthorizationOptions,
268
+ ): Promise<DeviceCodeRequest> {
269
+ const params = new URLSearchParams({
270
+ client_id: options.clientId,
271
+ scope: options.scope,
272
+ })
273
+
274
+ const response = await fetch(options.endpoint, {
275
+ method: 'POST',
276
+ headers: {
277
+ 'Content-Type': 'application/x-www-form-urlencoded',
278
+ },
279
+ body: params.toString(),
280
+ })
281
+
282
+ if (!response.ok) {
283
+ const error = await response.text()
284
+ logger.error('Device code request failed:', error)
285
+ throw new Error(`Failed to request device code: ${response.statusText}`)
286
+ }
287
+
288
+ const data = (await response.json()) as {
289
+ device_code: string
290
+ user_code: string
291
+ verification_url?: string
292
+ verification_uri?: string
293
+ verification_url_complete?: string
294
+ verification_uri_complete?: string
295
+ expires_in: number
296
+ interval?: number
297
+ }
298
+
299
+ return {
300
+ deviceCode: data.device_code,
301
+ userCode: data.user_code,
302
+ verificationUrl:
303
+ data.verification_url ||
304
+ data.verification_uri ||
305
+ 'https://www.google.com/device',
306
+ verificationUrlComplete:
307
+ data.verification_url_complete || data.verification_uri_complete,
308
+ expiresIn: data.expires_in,
309
+ interval: data.interval || 5,
310
+ }
311
+ }
312
+
313
+ private async pollForToken(
314
+ options: DeviceAuthorizationOptions & {
315
+ deviceCode: string
316
+ interval: number
317
+ expiresIn: number
318
+ },
319
+ ): Promise<OAuth.TokenResponse> {
320
+ const tokenEndpoint = options.endpoint.replace('/device/code', '/token')
321
+ const startTime = Date.now()
322
+ const expiresAt = startTime + options.expiresIn * 1000
323
+
324
+ while (Date.now() < expiresAt) {
325
+ // Wait for the specified interval
326
+ await new Promise((resolve) =>
327
+ setTimeout(resolve, options.interval * 1000),
328
+ )
329
+
330
+ const params = new URLSearchParams({
331
+ client_id: options.clientId,
332
+ device_code: options.deviceCode,
333
+ grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
334
+ })
335
+
336
+ // Add client secret if provided (required for Google)
337
+ if (options.clientSecret) {
338
+ params.append('client_secret', options.clientSecret)
339
+ }
340
+
341
+ try {
342
+ const response = await fetch(tokenEndpoint, {
343
+ method: 'POST',
344
+ headers: {
345
+ 'Content-Type': 'application/x-www-form-urlencoded',
346
+ },
347
+ body: params.toString(),
348
+ })
349
+
350
+ const data = (await response.json()) as {
351
+ access_token?: string
352
+ token_type?: string
353
+ expires_in?: number
354
+ refresh_token?: string
355
+ scope?: string
356
+ id_token?: string
357
+ error?: string
358
+ error_description?: string
359
+ interval?: number
360
+ }
361
+
362
+ if (response.ok && data.access_token) {
363
+ logger.log('Device authorization successful')
364
+ return data as OAuth.TokenResponse
365
+ }
366
+
367
+ // Check for specific error codes
368
+ if (data.error === 'authorization_pending') {
369
+ // User hasn't authorized yet, continue polling
370
+ continue
371
+ } else if (data.error === 'slow_down') {
372
+ // Increase interval
373
+ options.interval = (data.interval || options.interval) + 1
374
+ logger.log('Slowing down polling interval to', options.interval)
375
+ } else if (data.error === 'access_denied') {
376
+ throw new Error('User denied access')
377
+ } else if (data.error === 'expired_token') {
378
+ throw new Error('Device code expired')
379
+ } else if (data.error) {
380
+ throw new Error(
381
+ `OAuth error: ${data.error} - ${data.error_description || ''}`,
382
+ )
383
+ }
384
+ } catch (error) {
385
+ if (error instanceof Error && error.message.includes('denied')) {
386
+ throw error
387
+ }
388
+ logger.error('Error polling for token:', error)
389
+ }
390
+ }
391
+
392
+ throw new Error('Device authorization timeout')
393
+ }
394
+
395
+ async authorize(
396
+ options: AuthorizationRequest | AuthorizationOptions,
397
+ ): Promise<AuthorizationResponse> {
398
+ const url = 'toURL' in options ? options.toURL() : options.url
399
+ const expectedState = 'toURL' in options ? options.state : undefined
400
+
401
+ logger.log('Starting OAuth implicit flow authorization', { url })
402
+
403
+ this.isAuthorizing = true
404
+ this.authorizationURL = url
405
+
406
+ return new Promise((resolve, reject) => {
407
+ const port = 8989
408
+
409
+ // Create a local server to handle the OAuth callback
410
+ const server = http.createServer((req, res) => {
411
+ const requestUrl = new URL(req.url || '', `http://localhost:${port}`)
412
+
413
+ // Check if this is the callback
414
+ if (requestUrl.pathname === '/oauth/callback') {
415
+ // For implicit flow, tokens come in the fragment (#), not query
416
+ // We need to serve an HTML page that extracts the fragment and sends it back
417
+ res.writeHead(200, { 'Content-Type': 'text/html' })
418
+ res.end(`
419
+ <!DOCTYPE html>
420
+ <html>
421
+ <head>
422
+ <title>OAuth Authorization</title>
423
+ <style>
424
+ body {
425
+ font-family: system-ui;
426
+ padding: 40px;
427
+ text-align: center;
428
+ background: #f5f5f5;
429
+ }
430
+ .success { color: #28a745; }
431
+ .error { color: #dc3545; }
432
+ .token-info {
433
+ background: white;
434
+ padding: 20px;
435
+ border-radius: 8px;
436
+ margin: 20px auto;
437
+ max-width: 600px;
438
+ text-align: left;
439
+ }
440
+ </style>
441
+ </head>
442
+ <body>
443
+ <h1 id="status">Processing...</h1>
444
+ <div id="message"></div>
445
+ <script>
446
+ // Extract tokens from URL fragment
447
+ const hash = window.location.hash.substring(1);
448
+ const params = new URLSearchParams(hash);
449
+
450
+ const data = {
451
+ access_token: params.get('access_token'),
452
+ id_token: params.get('id_token'),
453
+ expires_in: params.get('expires_in'),
454
+ token_type: params.get('token_type'),
455
+ scope: params.get('scope'),
456
+ state: params.get('state'),
457
+ error: params.get('error'),
458
+ error_description: params.get('error_description')
459
+ };
460
+
461
+ // Send tokens back to our server
462
+ fetch('/oauth/implicit-callback', {
463
+ method: 'POST',
464
+ headers: { 'Content-Type': 'application/json' },
465
+ body: JSON.stringify(data)
466
+ }).then(response => {
467
+ if (response.ok) {
468
+ document.getElementById('status').className = 'success';
469
+ document.getElementById('status').innerHTML = '&#10003; Authorization Successful';
470
+ document.getElementById('message').innerHTML =
471
+ '<p>You can close this window and return to the terminal.</p>' +
472
+ '<div class="token-info">' +
473
+ (data.id_token ? '<p><strong>ID Token received:</strong> Yes</p>' : '') +
474
+ (data.access_token ? '<p><strong>Access Token received:</strong> Yes</p>' : '') +
475
+ (data.expires_in ? '<p><strong>Expires in:</strong> ' + data.expires_in + ' seconds</p>' : '') +
476
+ '</div>';
477
+ } else {
478
+ document.getElementById('status').className = 'error';
479
+ document.getElementById('status').textContent = 'Authorization Failed';
480
+ document.getElementById('message').textContent = data.error_description || data.error || 'Unknown error';
481
+ }
482
+ setTimeout(() => window.close(), 3000);
483
+ }).catch(err => {
484
+ document.getElementById('status').className = 'error';
485
+ document.getElementById('status').textContent = 'Communication Error';
486
+ document.getElementById('message').textContent = err.message;
487
+ });
488
+ </script>
489
+ </body>
490
+ </html>
491
+ `)
492
+ } else if (requestUrl.pathname === '/oauth/implicit-callback') {
493
+ // Handle the tokens sent from the browser
494
+ let body = ''
495
+ req.on('data', (chunk) => {
496
+ body += chunk
497
+ })
498
+ req.on('end', () => {
499
+ try {
500
+ const data = JSON.parse(body)
501
+
502
+ if (data.error) {
503
+ res.writeHead(400, {
504
+ 'Content-Type': 'application/json',
505
+ })
506
+ res.end(JSON.stringify({ error: data.error }))
507
+ server.close()
508
+ reject(
509
+ new Error(
510
+ `OAuth error: ${data.error} - ${data.error_description || ''}`,
511
+ ),
512
+ )
513
+ return
514
+ }
515
+
516
+ // Validate state
517
+ if (data.state !== expectedState) {
518
+ res.writeHead(400, {
519
+ 'Content-Type': 'application/json',
520
+ })
521
+ res.end(
522
+ JSON.stringify({
523
+ error: 'state_mismatch',
524
+ }),
525
+ )
526
+ server.close()
527
+ reject(new Error('OAuth state mismatch'))
528
+ return
529
+ }
530
+
531
+ res.writeHead(200, {
532
+ 'Content-Type': 'application/json',
533
+ })
534
+ res.end(JSON.stringify({ success: true }))
535
+
536
+ server.close()
537
+ this.isAuthorizing = false
538
+
539
+ // For implicit flow, save tokens immediately since we won't do token exchange
540
+ const tokens = {
541
+ accessToken: data.access_token || '',
542
+ idToken: data.id_token,
543
+ expiresIn: data.expires_in ? parseInt(data.expires_in) : 3600,
544
+ scope: data.scope,
545
+ }
546
+
547
+ // Store tokens in memory for later retrieval
548
+ this.implicitFlowTokens = tokens
549
+
550
+ // Save tokens directly to storage
551
+ this.setTokens(tokens)
552
+ .then(() => {
553
+ logger.log('Implicit flow tokens saved directly')
554
+
555
+ // Return the tokens (authorizationCode is a dummy value for compatibility)
556
+ resolve({
557
+ authorizationCode: 'implicit_flow_dummy_code', // Dummy code for compatibility
558
+ accessToken: data.access_token,
559
+ idToken: data.id_token,
560
+ state: data.state,
561
+ })
562
+ })
563
+ .catch((err) => {
564
+ logger.error('Failed to save implicit flow tokens:', err)
565
+ reject(err)
566
+ })
567
+ } catch (error) {
568
+ res.writeHead(500, {
569
+ 'Content-Type': 'application/json',
570
+ })
571
+ res.end(JSON.stringify({ error: 'parse_error' }))
572
+ server.close()
573
+ reject(error)
574
+ }
575
+ })
576
+ } else {
577
+ res.writeHead(404, { 'Content-Type': 'text/plain' })
578
+ res.end('Not found')
579
+ }
580
+ })
581
+
582
+ server.listen(port, async () => {
583
+ logger.log(
584
+ `OAuth implicit flow server listening on http://localhost:${port}/oauth/callback`,
585
+ )
586
+
587
+ // Open the browser
588
+ try {
589
+ const platform = process.platform
590
+ let command: string
591
+
592
+ if (platform === 'darwin') {
593
+ command = `open "${url}"`
594
+ } else if (platform === 'win32') {
595
+ command = `start "" "${url}"`
596
+ } else {
597
+ // Linux and others
598
+ command = `xdg-open "${url}" || sensible-browser "${url}" || x-www-browser "${url}"`
599
+ }
600
+
601
+ await execAsync(command)
602
+ logger.log('Browser opened for implicit flow authorization')
603
+ } catch (error) {
604
+ server.close()
605
+ reject(new Error(`Failed to open browser: ${error}`))
606
+ }
607
+ })
608
+
609
+ server.on('error', (error) => {
610
+ logger.error('OAuth implicit flow server error:', error)
611
+ reject(error)
612
+ })
613
+
614
+ // Set a timeout for the authorization
615
+ setTimeout(
616
+ () => {
617
+ server.close()
618
+ reject(new Error('OAuth authorization timeout'))
619
+ },
620
+ 5 * 60 * 1000,
621
+ ) // 5 minutes timeout
622
+ })
623
+ }
624
+
625
+ async setTokens(options: TokenSetOptions | TokenResponse): Promise<void> {
626
+ // Convert TokenResponse to TokenSetOptions if needed
627
+ const tokenSet: TokenSetOptions =
628
+ 'access_token' in options
629
+ ? {
630
+ accessToken: options.access_token,
631
+ refreshToken: options.refresh_token,
632
+ idToken: options.id_token,
633
+ expiresIn: options.expires_in,
634
+ scope: options.scope,
635
+ }
636
+ : options
637
+
638
+ const storedTokenSet: TokenSet = {
639
+ ...tokenSet,
640
+ updatedAt: new Date(),
641
+ isExpired: function () {
642
+ if (!this.expiresIn) return false
643
+ const expiresAt = new Date(
644
+ this.updatedAt.getTime() + this.expiresIn * 1000,
645
+ )
646
+ // Add 10 seconds buffer
647
+ return new Date().getTime() > expiresAt.getTime() - 10000
648
+ },
649
+ }
650
+
651
+ const dataToStore = {
652
+ ...storedTokenSet,
653
+ updatedAt: storedTokenSet.updatedAt.toISOString(),
654
+ }
655
+
656
+ logger.log('Storing tokens for', this.providerId, {
657
+ storageKey: this.storageKey,
658
+ hasAccessToken: !!tokenSet.accessToken,
659
+ hasRefreshToken: !!tokenSet.refreshToken,
660
+ hasIdToken: !!tokenSet.idToken,
661
+ expiresIn: tokenSet.expiresIn,
662
+ })
663
+
664
+ await LocalStorage.setItem(this.storageKey, JSON.stringify(dataToStore))
665
+
666
+ // Verify storage
667
+ const stored = await LocalStorage.getItem(this.storageKey)
668
+ if (stored) {
669
+ logger.log(
670
+ 'Tokens successfully stored and verified for',
671
+ this.providerId,
672
+ )
673
+ } else {
674
+ logger.error('Failed to verify token storage for', this.providerId)
675
+ }
676
+ }
677
+
678
+ async getTokens(): Promise<TokenSet | undefined> {
679
+ logger.log('Getting tokens for', this.providerId, {
680
+ storageKey: this.storageKey,
681
+ })
682
+
683
+ const stored = await LocalStorage.getItem(this.storageKey)
684
+ if (!stored) {
685
+ logger.log('No tokens found for', this.providerId)
686
+ return undefined
687
+ }
688
+
689
+ const parsed = JSON.parse(stored as string)
690
+ const tokenSet: TokenSet = {
691
+ ...parsed,
692
+ updatedAt: new Date(parsed.updatedAt),
693
+ isExpired: function () {
694
+ if (!this.expiresIn) return false
695
+ const expiresAt = new Date(
696
+ this.updatedAt.getTime() + this.expiresIn * 1000,
697
+ )
698
+ // Add 10 seconds buffer
699
+ return new Date().getTime() > expiresAt.getTime() - 10000
700
+ },
701
+ }
702
+
703
+ logger.log('Retrieved tokens for', this.providerId, {
704
+ hasAccessToken: !!tokenSet.accessToken,
705
+ hasRefreshToken: !!tokenSet.refreshToken,
706
+ isExpired: tokenSet.isExpired(),
707
+ })
708
+
709
+ return tokenSet
710
+ }
711
+
712
+ async removeTokens(): Promise<void> {
713
+ await LocalStorage.removeItem(this.storageKey)
714
+ this.implicitFlowTokens = undefined // Clear in-memory tokens
715
+ logger.log('Tokens removed for', this.providerId)
716
+ }
717
+
718
+ // Method to check if we have implicit flow tokens ready
719
+ hasImplicitFlowTokens(): boolean {
720
+ return !!this.implicitFlowTokens
721
+ }
722
+
723
+ // Method to get implicit flow tokens (for mocking token exchange)
724
+ getImplicitFlowTokens(): TokenResponse | undefined {
725
+ if (!this.implicitFlowTokens) return undefined
726
+
727
+ return {
728
+ access_token: this.implicitFlowTokens.accessToken,
729
+ id_token: this.implicitFlowTokens.idToken,
730
+ expires_in: this.implicitFlowTokens.expiresIn,
731
+ scope: this.implicitFlowTokens.scope,
732
+ refresh_token: this.implicitFlowTokens.refreshToken,
733
+ }
734
+ }
735
+
736
+ private generateCodeVerifier(): string {
737
+ return crypto.randomBytes(32).toString('base64url')
738
+ }
739
+
740
+ private generateCodeChallenge(verifier: string): string {
741
+ return crypto.createHash('sha256').update(verifier).digest('base64url')
742
+ }
743
+ }
744
+ }