@jant/core 0.6.16 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (592) hide show
  1. package/README.md +11 -11
  2. package/bin/commands/assets/upload.js +192 -15
  3. package/bin/commands/export.js +3 -1
  4. package/bin/commands/import-site.js +749 -220
  5. package/bin/commands/reset-password.js +21 -8
  6. package/bin/commands/setup.js +136 -0
  7. package/bin/commands/site/export.js +71 -34
  8. package/bin/commands/site/pull-media.js +2 -6
  9. package/bin/commands/site/snapshot/export.js +19 -61
  10. package/bin/commands/site/snapshot/import.js +23 -24
  11. package/bin/lib/d1-query.js +92 -18
  12. package/bin/lib/hugo-markdown.js +4 -0
  13. package/bin/lib/node-env.js +40 -4
  14. package/bin/lib/site-pull-media.js +21 -28
  15. package/bin/lib/site-selection.js +94 -29
  16. package/bin/lib/site-snapshot.js +338 -3
  17. package/bin/lib/sql-export.js +68 -5
  18. package/bin/lib/wrangler-cli.js +37 -2
  19. package/bin/lib/wrangler-json.js +35 -0
  20. package/bin/lib/zip-archive.js +187 -0
  21. package/dist/{app-C7_4oab9.js → app-ZcaI1kPN.js} +53190 -13529
  22. package/dist/client/.vite/manifest.json +255 -90
  23. package/dist/client/_assets/chunks/confirm-D7GrwsCN.js +45 -0
  24. package/dist/client/_assets/chunks/create-editor-B-m7X7S5.js +261 -0
  25. package/dist/client/_assets/chunks/{native-DpcrFAPh.js → emoji-mart-C4RpRKcU.js} +716 -1
  26. package/dist/client/_assets/chunks/footnote-rail-CmeoVtnU.js +1 -0
  27. package/dist/client/_assets/chunks/heic-to-CuP2Qlsw.js +1 -0
  28. package/dist/client/_assets/chunks/jant-locale-picker-DL6mIOT5.js +69 -0
  29. package/dist/client/_assets/chunks/lit-DW8VmJAT.js +2 -0
  30. package/dist/client/_assets/chunks/mediabunny-DRaCQ1r-.js +31 -0
  31. package/dist/client/_assets/chunks/rolldown-runtime-hePW80VL.js +1 -0
  32. package/dist/client/_assets/chunks/settings-paths-BcdySNx6.js +84 -0
  33. package/dist/client/_assets/chunks/site-header-nav-DzXsFk05.js +1 -0
  34. package/dist/client/_assets/chunks/slug-format-CRXO1AL5.js +1 -0
  35. package/dist/client/_assets/chunks/slugify-373citbs.js +1 -0
  36. package/dist/client/_assets/chunks/sortable-list-BJyd-LXE.js +2 -0
  37. package/dist/client/_assets/chunks/types-D5iF3H1a.js +1 -0
  38. package/dist/client/_assets/chunks/unsafe-html-B5ZEXaxg.js +1 -0
  39. package/dist/client/_assets/chunks/unsafe-svg-BkscJx69.js +2 -0
  40. package/dist/client/_assets/client-DAhoqPdr.css +2 -0
  41. package/dist/client/_assets/client-auth-CAMfTrKW.js +828 -0
  42. package/dist/client/_assets/client-author-DQ8R-8KR.css +2 -0
  43. package/dist/client/_assets/client-compose-D6rExKVK.js +2004 -0
  44. package/dist/client/_assets/client-knSEyUJO.js +295 -0
  45. package/dist/client/_assets/client-manage-sVOkqVbH.js +2170 -0
  46. package/dist/client/_assets/client-settings-CGR_nZ78.js +1112 -0
  47. package/dist/github-sync-Gw4orAHk.js +8398 -0
  48. package/dist/index.js +2 -5
  49. package/dist/node.js +11 -9
  50. package/package.json +15 -5
  51. package/src/__tests__/auth-session-freshness.test.ts +57 -0
  52. package/src/__tests__/basecoat-variants.test.ts +121 -0
  53. package/src/__tests__/bin/assets-upload.test.ts +68 -0
  54. package/src/__tests__/dev-scripts.test.ts +203 -0
  55. package/src/__tests__/export-collection-order.test.ts +276 -0
  56. package/src/__tests__/export-feed-ids.test.ts +184 -0
  57. package/src/__tests__/export-feed-order.test.ts +294 -0
  58. package/src/__tests__/export-hugo-build.test.ts +390 -0
  59. package/src/__tests__/export-import-roundtrip.test.ts +94 -0
  60. package/src/__tests__/export-service.test.ts +842 -28
  61. package/src/__tests__/export-smart-collection.test.ts +329 -0
  62. package/src/__tests__/helpers/component-css.ts +91 -0
  63. package/src/__tests__/helpers/db.ts +33 -0
  64. package/src/__tests__/helpers/export-fixtures.ts +3 -0
  65. package/src/__tests__/helpers/hugo-site.ts +146 -0
  66. package/src/__tests__/import-site-command.test.ts +487 -1
  67. package/src/__tests__/mise-config.test.ts +75 -4
  68. package/src/__tests__/node-dev-tasks.test.ts +264 -0
  69. package/src/__tests__/site-export-canonical-import.test.ts +149 -0
  70. package/src/__tests__/snapshot-canonical-replay.test.ts +179 -0
  71. package/src/__tests__/snapshot-settings.test.ts +97 -0
  72. package/src/__tests__/snapshot-tables.test.ts +219 -0
  73. package/src/__tests__/sql-export.test.ts +173 -0
  74. package/src/__tests__/stylesheet-audience.test.ts +159 -0
  75. package/src/__tests__/stylesheet-breakpoints.test.ts +183 -0
  76. package/src/__tests__/zip-archive.test.ts +106 -0
  77. package/src/app.tsx +86 -22
  78. package/src/auth.ts +18 -1
  79. package/src/client/__tests__/collection-page-actions.test.ts +51 -2
  80. package/src/client/__tests__/compose-bridge-image-upload.test.ts +196 -0
  81. package/src/client/__tests__/compose-bridge-video-poster.test.ts +159 -0
  82. package/src/client/__tests__/compose-bridge.test.ts +272 -0
  83. package/src/client/__tests__/compose-launch.test.ts +62 -1
  84. package/src/client/__tests__/compose-shortcuts.test.ts +38 -9
  85. package/src/client/__tests__/compose-triggers.test.ts +90 -0
  86. package/src/client/__tests__/copy-field.test.ts +162 -0
  87. package/src/client/__tests__/custom-url-menu.test.ts +127 -6
  88. package/src/client/__tests__/image-processor.test.ts +324 -2
  89. package/src/client/__tests__/lazy-entries.test.ts +92 -0
  90. package/src/client/__tests__/media-scroll-hint.test.ts +155 -0
  91. package/src/client/__tests__/runtime-paths.test.ts +84 -0
  92. package/src/client/__tests__/smart-collection-page-actions.test.ts +158 -0
  93. package/src/client/__tests__/toast.test.ts +23 -0
  94. package/src/client/__tests__/video-processor-probe.test.ts +175 -0
  95. package/src/client/__tests__/video-processor.test.ts +181 -0
  96. package/src/client/audio-processor.ts +24 -15
  97. package/src/client/audio-waveform.ts +49 -0
  98. package/src/client/collection-dialog-host.ts +72 -0
  99. package/src/client/collection-navigation.ts +51 -16
  100. package/src/client/collection-page-actions.ts +26 -0
  101. package/src/client/components/__tests__/jant-collection-dialog.test.ts +329 -0
  102. package/src/client/components/__tests__/jant-collection-directory.test.ts +274 -10
  103. package/src/client/components/__tests__/jant-collection-form.test.ts +59 -178
  104. package/src/client/components/__tests__/jant-command-palette.test.ts +28 -0
  105. package/src/client/components/__tests__/jant-compose-dialog-draft-storage.test.ts +340 -0
  106. package/src/client/components/__tests__/jant-compose-dialog.test.ts +1250 -53
  107. package/src/client/components/__tests__/jant-compose-editor.test.ts +544 -40
  108. package/src/client/components/__tests__/jant-compose-fullscreen.test.ts +0 -1
  109. package/src/client/components/__tests__/jant-locale-picker.test.ts +207 -0
  110. package/src/client/components/__tests__/jant-nav-manager.test.ts +234 -15
  111. package/src/client/components/__tests__/jant-post-menu.test.ts +413 -2
  112. package/src/client/components/__tests__/jant-post-picker.test.ts +197 -0
  113. package/src/client/components/__tests__/jant-settings-avatar.test.ts +15 -12
  114. package/src/client/components/__tests__/jant-settings-general.test.ts +561 -172
  115. package/src/client/components/__tests__/jant-settings-language.test.ts +851 -0
  116. package/src/client/components/__tests__/jant-smart-collection-dialog.test.ts +665 -0
  117. package/src/client/components/collection-dialog-types.ts +49 -0
  118. package/src/client/components/collection-manager-types.ts +32 -1
  119. package/src/client/components/collection-types.ts +1 -15
  120. package/src/client/components/compose-types.ts +75 -1
  121. package/src/client/components/jant-collection-dialog.ts +722 -0
  122. package/src/client/components/jant-collection-directory.ts +567 -182
  123. package/src/client/components/jant-collection-form.ts +53 -232
  124. package/src/client/components/jant-command-palette.ts +100 -49
  125. package/src/client/components/jant-compose-dialog.ts +1486 -707
  126. package/src/client/components/jant-compose-editor.ts +673 -336
  127. package/src/client/components/jant-compose-fullscreen.ts +51 -43
  128. package/src/client/components/jant-config-editor.ts +65 -53
  129. package/src/client/components/jant-confirm-dialog.ts +13 -11
  130. package/src/client/components/jant-locale-picker.ts +418 -0
  131. package/src/client/components/jant-media-lightbox.ts +146 -136
  132. package/src/client/components/jant-nav-manager.ts +690 -366
  133. package/src/client/components/jant-post-menu.ts +1086 -282
  134. package/src/client/components/jant-post-picker.ts +324 -0
  135. package/src/client/components/jant-repo-picker-types.ts +6 -1
  136. package/src/client/components/jant-repo-picker.ts +137 -108
  137. package/src/client/components/jant-settings-avatar.ts +31 -27
  138. package/src/client/components/jant-settings-general.ts +622 -543
  139. package/src/client/components/jant-settings-language.ts +1087 -0
  140. package/src/client/components/jant-smart-collection-dialog.ts +1021 -0
  141. package/src/client/components/jant-text-preview.ts +94 -86
  142. package/src/client/components/nav-manager-types.ts +62 -1
  143. package/src/client/components/settings-types.ts +14 -29
  144. package/src/client/components/smart-collection-conditions.ts +285 -0
  145. package/src/client/components/smart-collection-dialog-types.ts +68 -0
  146. package/src/client/compose-bridge.ts +214 -141
  147. package/src/client/compose-launch.ts +76 -2
  148. package/src/client/compose-shortcuts.ts +6 -8
  149. package/src/client/compose-triggers.ts +50 -0
  150. package/src/client/copy-field.ts +108 -0
  151. package/src/client/custom-url-menu.ts +60 -4
  152. package/src/client/icons.ts +14 -0
  153. package/src/client/image-plan.ts +165 -0
  154. package/src/client/image-processor.ts +195 -117
  155. package/src/client/image-worker-client.ts +45 -0
  156. package/src/client/image-worker.ts +135 -0
  157. package/src/client/lazy-entries.ts +95 -0
  158. package/src/client/lazy-slugify.ts +2 -2
  159. package/src/client/media-scroll-hint.ts +43 -2
  160. package/src/client/mediabunny.ts +29 -0
  161. package/src/client/post-picker.ts +41 -0
  162. package/src/client/runtime-paths.ts +74 -1
  163. package/src/client/settings-bridge.ts +4 -10
  164. package/src/client/site-header-nav.js +18 -6
  165. package/src/client/smart-collection-dialog-host.ts +116 -0
  166. package/src/client/smart-collection-page-actions.ts +208 -0
  167. package/src/client/tiptap/__tests__/bubble-menu.test.ts +110 -0
  168. package/src/client/tiptap/__tests__/floating-position.test.ts +136 -1
  169. package/src/client/tiptap/__tests__/inline-image-upload.test.ts +37 -0
  170. package/src/client/tiptap/__tests__/list-editing.test.ts +224 -86
  171. package/src/client/tiptap/__tests__/mark-exit.test.ts +1 -2
  172. package/src/client/tiptap/__tests__/markdown-clipboard.test.ts +26 -0
  173. package/src/client/tiptap/bubble-menu.ts +47 -16
  174. package/src/client/tiptap/extensions.ts +0 -3
  175. package/src/client/tiptap/floating-position.ts +216 -2
  176. package/src/client/tiptap/inline-image-upload.ts +7 -3
  177. package/src/client/tiptap/link-toolbar.ts +22 -9
  178. package/src/client/tiptap/structural-keymap.ts +158 -47
  179. package/src/client/toast.ts +13 -0
  180. package/src/client/types/vite-worker.d.ts +12 -0
  181. package/src/client/upload-with-metadata.ts +3 -13
  182. package/src/client/video-processor.ts +351 -107
  183. package/src/client-auth.ts +14 -31
  184. package/src/client-compose.ts +19 -0
  185. package/src/client-manage.ts +13 -0
  186. package/src/client-settings.ts +14 -0
  187. package/src/client-site.ts +10 -3
  188. package/src/client.ts +4 -0
  189. package/src/db/__tests__/backfill-nav-label-mirrors.test.ts +149 -0
  190. package/src/db/__tests__/d1-query.test.ts +56 -1
  191. package/src/db/__tests__/schema-enum-sources.test.ts +33 -0
  192. package/src/db/__tests__/smart-collection-placement.test.ts +402 -0
  193. package/src/db/backfills/0006_clear_mirrored_page_nav_labels.sql +31 -0
  194. package/src/db/migrations/0032_married_tomas.sql +3 -0
  195. package/src/db/migrations/0033_busy_johnny_storm.sql +198 -0
  196. package/src/db/migrations/0034_cheerful_rumiko_fujikawa.sql +35 -0
  197. package/src/db/migrations/meta/0032_snapshot.json +2582 -0
  198. package/src/db/migrations/meta/0033_snapshot.json +2816 -0
  199. package/src/db/migrations/meta/0034_snapshot.json +2816 -0
  200. package/src/db/migrations/meta/_journal.json +21 -0
  201. package/src/db/migrations/pg/0030_abandoned_nighthawk.sql +3 -0
  202. package/src/db/migrations/pg/0031_strong_ultimatum.sql +128 -0
  203. package/src/db/migrations/pg/0032_furry_multiple_man.sql +6 -0
  204. package/src/db/migrations/pg/meta/0030_snapshot.json +3329 -0
  205. package/src/db/migrations/pg/meta/0031_snapshot.json +3660 -0
  206. package/src/db/migrations/pg/meta/0032_snapshot.json +3660 -0
  207. package/src/db/migrations/pg/meta/_journal.json +21 -0
  208. package/src/db/pg/schema.ts +195 -27
  209. package/src/db/post-visibility.ts +117 -0
  210. package/src/db/schema.ts +222 -27
  211. package/src/i18n/__tests__/detect.test.ts +26 -81
  212. package/src/i18n/__tests__/supported-locales.test.ts +83 -0
  213. package/src/i18n/context.tsx +12 -2
  214. package/src/i18n/detect.ts +7 -66
  215. package/src/i18n/locales/glossary.zh-Hans.yml +44 -4
  216. package/src/i18n/locales/glossary.zh-Hant.yml +44 -4
  217. package/src/i18n/locales/public/en.po +490 -158
  218. package/src/i18n/locales/public/en.ts +1 -1
  219. package/src/i18n/locales/public/zh-Hans.po +487 -155
  220. package/src/i18n/locales/public/zh-Hans.ts +1 -1
  221. package/src/i18n/locales/public/zh-Hant.po +487 -155
  222. package/src/i18n/locales/public/zh-Hant.ts +1 -1
  223. package/src/i18n/locales/settings/en.po +555 -73
  224. package/src/i18n/locales/settings/en.ts +1 -1
  225. package/src/i18n/locales/settings/zh-Hans.po +601 -119
  226. package/src/i18n/locales/settings/zh-Hans.ts +1 -1
  227. package/src/i18n/locales/settings/zh-Hant.po +614 -132
  228. package/src/i18n/locales/settings/zh-Hant.ts +1 -1
  229. package/src/i18n/locales.ts +94 -0
  230. package/src/i18n/middleware.ts +12 -2
  231. package/src/i18n/supported-locales.ts +80 -0
  232. package/src/lib/__tests__/api-settings.test.ts +11 -2
  233. package/src/lib/__tests__/asset-path.test.ts +92 -0
  234. package/src/lib/__tests__/deferred.test.ts +90 -0
  235. package/src/lib/__tests__/discover-ping.test.ts +89 -0
  236. package/src/lib/__tests__/discover.test.ts +410 -0
  237. package/src/lib/__tests__/feed-policy.test.ts +26 -0
  238. package/src/lib/__tests__/feed.test.ts +1526 -15
  239. package/src/lib/__tests__/filter-dimensions.test.ts +341 -0
  240. package/src/lib/__tests__/github-sync-repo-name.test.ts +40 -0
  241. package/src/lib/__tests__/hosted-signin.test.ts +1 -1
  242. package/src/lib/__tests__/http-cache.test.ts +162 -0
  243. package/src/lib/__tests__/image.test.ts +27 -1
  244. package/src/lib/__tests__/jant-docs-dev.test.ts +21 -0
  245. package/src/lib/__tests__/jant-docs.test.ts +23 -0
  246. package/src/lib/__tests__/lang-detect.test.ts +231 -0
  247. package/src/lib/__tests__/markdown-to-tiptap.test.ts +105 -0
  248. package/src/lib/__tests__/markdown.test.ts +10 -0
  249. package/src/lib/__tests__/media-helpers.test.ts +81 -0
  250. package/src/lib/__tests__/navigation.test.ts +135 -1
  251. package/src/lib/__tests__/resolve-config.test.ts +131 -3
  252. package/src/lib/__tests__/schemas.test.ts +69 -5
  253. package/src/lib/__tests__/site-unavailable-page.test.ts +25 -0
  254. package/src/lib/__tests__/slug.test.ts +70 -0
  255. package/src/lib/__tests__/slugify.test.ts +85 -0
  256. package/src/lib/__tests__/storage.test.ts +32 -0
  257. package/src/lib/__tests__/thread-fold.test.ts +113 -0
  258. package/src/lib/__tests__/timeline.test.ts +87 -0
  259. package/src/lib/__tests__/tiptap-to-markdown.test.ts +172 -4
  260. package/src/lib/__tests__/upload-sideload.test.ts +14 -0
  261. package/src/lib/__tests__/url-fetch.test.ts +1 -2
  262. package/src/lib/__tests__/url.test.ts +78 -72
  263. package/src/lib/__tests__/view-language.test.ts +413 -0
  264. package/src/lib/__tests__/worker-response-cache.test.ts +90 -0
  265. package/src/lib/address.ts +57 -0
  266. package/src/lib/api-posts.ts +12 -0
  267. package/src/lib/asset-path.ts +98 -1
  268. package/src/lib/build-env.ts +16 -0
  269. package/src/lib/collection-groups.ts +5 -1
  270. package/src/lib/collection-paths.ts +3 -10
  271. package/src/lib/constants.ts +28 -3
  272. package/src/lib/copy-field.ts +36 -0
  273. package/src/lib/crypto.ts +40 -0
  274. package/src/lib/csp-builder.ts +2 -1
  275. package/src/lib/deferred.ts +79 -0
  276. package/src/lib/discover-ping.ts +141 -0
  277. package/src/lib/discover.ts +439 -0
  278. package/src/lib/env.ts +134 -0
  279. package/src/lib/errors.ts +33 -0
  280. package/src/lib/feed-policy.ts +236 -2
  281. package/src/lib/feed.ts +926 -73
  282. package/src/lib/filter-dimensions.ts +1349 -0
  283. package/src/lib/github-sync-repo-name.ts +45 -0
  284. package/src/lib/github-sync-site-config.ts +3 -0
  285. package/src/lib/hosted-signin.ts +1 -1
  286. package/src/lib/http-cache.ts +148 -0
  287. package/src/lib/hugo-markdown.ts +62 -0
  288. package/src/lib/icons.ts +9 -2
  289. package/src/lib/ids.ts +3 -0
  290. package/src/lib/image.ts +17 -4
  291. package/src/lib/jant-docs.ts +42 -0
  292. package/src/lib/lang-detect.ts +308 -0
  293. package/src/lib/markdown-manager.ts +392 -2
  294. package/src/lib/media-helpers.ts +13 -1
  295. package/src/lib/navigation.ts +78 -11
  296. package/src/lib/pagination.ts +28 -24
  297. package/src/lib/per-language-surfaces.ts +67 -0
  298. package/src/lib/post-body-html.ts +11 -4
  299. package/src/lib/post-meta.ts +19 -0
  300. package/src/lib/render.tsx +55 -7
  301. package/src/lib/resolve-config.ts +111 -6
  302. package/src/lib/schemas.ts +251 -15
  303. package/src/lib/site-header-fragment.tsx +2 -1
  304. package/src/lib/site-unavailable-page.ts +47 -0
  305. package/src/lib/slug.ts +51 -7
  306. package/src/lib/slugify.ts +113 -0
  307. package/src/lib/startup-config.ts +4 -6
  308. package/src/lib/storage.ts +7 -0
  309. package/src/lib/summary.ts +50 -0
  310. package/src/lib/thread-fold.ts +161 -0
  311. package/src/lib/time.ts +32 -0
  312. package/src/lib/timeline.ts +43 -2
  313. package/src/lib/tiptap-render.ts +1 -2
  314. package/src/lib/tiptap-to-markdown.ts +13 -7
  315. package/src/lib/upload.ts +16 -13
  316. package/src/lib/url.ts +159 -86
  317. package/src/lib/version.ts +10 -8
  318. package/src/lib/view-language.ts +436 -0
  319. package/src/lib/view.ts +53 -25
  320. package/src/lib/viewer-context.ts +62 -0
  321. package/src/middleware/__tests__/auth.test.ts +70 -2
  322. package/src/middleware/__tests__/cache-control.test.ts +71 -3
  323. package/src/middleware/__tests__/onboarding.test.ts +76 -5
  324. package/src/middleware/__tests__/secure-headers.test.ts +1 -1
  325. package/src/middleware/__tests__/session.test.ts +181 -33
  326. package/src/middleware/auth.ts +50 -31
  327. package/src/middleware/cache-control.ts +75 -10
  328. package/src/middleware/config.ts +6 -6
  329. package/src/middleware/error-handler.ts +12 -0
  330. package/src/middleware/onboarding.ts +32 -10
  331. package/src/middleware/secure-headers.ts +1 -1
  332. package/src/middleware/session.ts +96 -8
  333. package/src/node/__tests__/cli-migrate.test.ts +21 -19
  334. package/src/node/__tests__/cli-reset-password.test.ts +81 -8
  335. package/src/node/__tests__/cli-runtime-target.test.ts +48 -1
  336. package/src/node/__tests__/cli-setup.test.ts +163 -0
  337. package/src/node/__tests__/cli-site-selection.test.ts +128 -38
  338. package/src/node/__tests__/cli-site-snapshot.test.ts +67 -0
  339. package/src/node/__tests__/cli-snapshot-meta.test.ts +20 -0
  340. package/src/node/__tests__/runtime.test.ts +75 -0
  341. package/src/node/index.ts +3 -0
  342. package/src/node/request-handler.ts +3 -1
  343. package/src/preset.css +76 -22
  344. package/src/routes/__tests__/feed-validator.test.ts +156 -0
  345. package/src/routes/api/__tests__/collections.test.ts +114 -0
  346. package/src/routes/api/__tests__/discover.test.ts +222 -0
  347. package/src/routes/api/__tests__/nav-items.test.ts +212 -2
  348. package/src/routes/api/__tests__/post-translations.test.ts +829 -0
  349. package/src/routes/api/__tests__/posts.test.ts +24 -0
  350. package/src/routes/api/__tests__/settings.test.ts +24 -3
  351. package/src/routes/api/__tests__/telegram.test.ts +6 -5
  352. package/src/routes/api/__tests__/upload.test.ts +34 -0
  353. package/src/routes/api/collections.ts +49 -6
  354. package/src/routes/api/custom-urls.ts +0 -1
  355. package/src/routes/api/discover.ts +95 -0
  356. package/src/routes/api/export.ts +6 -3
  357. package/src/routes/api/internal/__tests__/sites.test.ts +42 -2
  358. package/src/routes/api/internal/sites.ts +0 -1
  359. package/src/routes/api/nav-items.ts +55 -8
  360. package/src/routes/api/posts.ts +161 -0
  361. package/src/routes/api/public/__tests__/archive.test.ts +111 -0
  362. package/src/routes/api/public/archive.ts +77 -81
  363. package/src/routes/api/public/posts.ts +44 -7
  364. package/src/routes/api/smart-collections.ts +132 -0
  365. package/src/routes/api/telegram.ts +2 -40
  366. package/src/routes/api/upload.ts +10 -3
  367. package/src/routes/api/uploads.ts +1 -2
  368. package/src/routes/auth/__tests__/setup-auth.test.ts +137 -0
  369. package/src/routes/auth/__tests__/setup-discover.test.ts +204 -0
  370. package/src/routes/auth/__tests__/setup-flow.test.ts +270 -0
  371. package/src/routes/auth/__tests__/setup-page.test.tsx +329 -0
  372. package/src/routes/auth/__tests__/setup-steps.test.ts +310 -0
  373. package/src/routes/auth/__tests__/setup.test.ts +278 -26
  374. package/src/routes/auth/__tests__/signin.test.ts +135 -0
  375. package/src/routes/auth/setup.tsx +934 -186
  376. package/src/routes/auth/signin.tsx +10 -8
  377. package/src/routes/compose.tsx +9 -0
  378. package/src/routes/dash/__tests__/custom-urls-archive.test.ts +44 -0
  379. package/src/routes/dash/__tests__/custom-urls-page.test.ts +49 -0
  380. package/src/routes/dash/__tests__/delete-account.test.ts +106 -0
  381. package/src/routes/dash/__tests__/github-sync-app.test.ts +365 -0
  382. package/src/routes/dash/__tests__/settings-discover.test.ts +213 -0
  383. package/src/routes/dash/custom-urls.tsx +1 -37
  384. package/src/routes/dash/settings.tsx +714 -111
  385. package/src/routes/discover-announce.ts +96 -0
  386. package/src/routes/feed/__tests__/feed.test.ts +165 -2
  387. package/src/routes/feed/feed.ts +69 -40
  388. package/src/routes/feed/sitemap.ts +95 -11
  389. package/src/routes/pages/__tests__/archive-indexing.test.ts +200 -0
  390. package/src/routes/pages/__tests__/archive-params.test.ts +370 -6
  391. package/src/routes/pages/__tests__/collection-routing.test.ts +16 -0
  392. package/src/routes/pages/__tests__/collections-feed-links.test.ts +72 -0
  393. package/src/routes/pages/__tests__/collections.test.ts +9 -3
  394. package/src/routes/pages/__tests__/custom-archive-url.test.ts +119 -0
  395. package/src/routes/pages/__tests__/feed-autodiscovery.test.ts +148 -0
  396. package/src/routes/pages/__tests__/language-routing.test.ts +679 -0
  397. package/src/routes/pages/__tests__/post-page-round-trips.test.ts +211 -0
  398. package/src/routes/pages/__tests__/post-preview-partial.test.ts +96 -0
  399. package/src/routes/pages/__tests__/smart-collection.test.ts +298 -0
  400. package/src/routes/pages/__tests__/subscribe.test.ts +248 -0
  401. package/src/routes/pages/__tests__/thread-order.test.ts +179 -0
  402. package/src/routes/pages/archive.tsx +487 -379
  403. package/src/routes/pages/collection.tsx +94 -96
  404. package/src/routes/pages/collections.tsx +38 -50
  405. package/src/routes/pages/featured.tsx +43 -18
  406. package/src/routes/pages/home.tsx +25 -6
  407. package/src/routes/pages/language.tsx +113 -0
  408. package/src/routes/pages/latest.tsx +26 -16
  409. package/src/routes/pages/new.tsx +3 -0
  410. package/src/routes/pages/page.tsx +228 -45
  411. package/src/routes/pages/partials.tsx +41 -0
  412. package/src/routes/pages/search.tsx +22 -5
  413. package/src/routes/pages/smart-collection.tsx +340 -0
  414. package/src/routes/pages/subscribe.tsx +182 -0
  415. package/src/runtime/__tests__/index.test.ts +19 -0
  416. package/src/runtime/__tests__/node.test.ts +129 -4
  417. package/src/runtime/__tests__/readiness.test.ts +23 -0
  418. package/src/runtime/cloudflare.ts +21 -2
  419. package/src/runtime/index.ts +27 -1
  420. package/src/runtime/node.ts +67 -1
  421. package/src/runtime/readiness.ts +15 -0
  422. package/src/runtime/site.ts +95 -24
  423. package/src/services/__tests__/auth.test.ts +116 -7
  424. package/src/services/__tests__/bootstrap-setup-instance.test.ts +230 -0
  425. package/src/services/__tests__/collection.test.ts +108 -4
  426. package/src/services/__tests__/custom-url.test.ts +34 -0
  427. package/src/services/__tests__/github-app-installations.test.ts +153 -0
  428. package/src/services/__tests__/github-sync-push.test.ts +46 -0
  429. package/src/services/__tests__/language.test.ts +495 -0
  430. package/src/services/__tests__/media.test.ts +31 -0
  431. package/src/services/__tests__/navigation.test.ts +213 -10
  432. package/src/services/__tests__/path.test.ts +236 -0
  433. package/src/services/__tests__/post-language.test.ts +830 -0
  434. package/src/services/__tests__/post-timeline.test.ts +127 -0
  435. package/src/services/__tests__/post.test.ts +120 -9
  436. package/src/services/__tests__/settings.test.ts +228 -17
  437. package/src/services/__tests__/site-admin.test.ts +5 -5
  438. package/src/services/__tests__/smart-collection.test.ts +651 -0
  439. package/src/services/about-page.ts +22 -1
  440. package/src/services/auth.ts +51 -49
  441. package/src/services/bootstrap.ts +408 -39
  442. package/src/services/collection-directory-position.ts +76 -0
  443. package/src/services/collection.ts +331 -46
  444. package/src/services/custom-url.ts +29 -24
  445. package/src/services/export-theme/assets/client-site.css +1 -1
  446. package/src/services/export-theme/assets/client-site.js +123 -123
  447. package/src/services/export-theme/layouts/_default/alias.html +27 -1
  448. package/src/services/export-theme/layouts/_default/list.html +2 -63
  449. package/src/services/export-theme/layouts/_default/rss.xml +103 -38
  450. package/src/services/export-theme/layouts/collections/list.html +3 -3
  451. package/src/services/export-theme/layouts/featured/list.html +1 -4
  452. package/src/services/export-theme/layouts/index.html +40 -26
  453. package/src/services/export-theme/layouts/partials/collection-members.html +100 -0
  454. package/src/services/export-theme/layouts/partials/collection-threads.html +33 -0
  455. package/src/services/export-theme/layouts/partials/featured-members.html +35 -0
  456. package/src/services/export-theme/layouts/partials/featured-thread.html +1 -1
  457. package/src/services/export-theme/layouts/partials/feed-post-content.xml +105 -2
  458. package/src/services/export-theme/layouts/partials/footer.html +1 -1
  459. package/src/services/export-theme/layouts/partials/head.html +1 -1
  460. package/src/services/export-theme/layouts/partials/header.html +5 -3
  461. package/src/services/export-theme/layouts/partials/jant-data.html +23 -0
  462. package/src/services/export-theme/layouts/partials/latest-members.html +48 -0
  463. package/src/services/export-theme/layouts/partials/media-gallery.html +35 -21
  464. package/src/services/export-theme/layouts/partials/pagination.html +14 -13
  465. package/src/services/export-theme/layouts/partials/post-card.html +8 -4
  466. package/src/services/export-theme/layouts/partials/reply.html +2 -1
  467. package/src/services/export-theme/layouts/partials/smart-collection-members.html +129 -0
  468. package/src/services/export-theme/layouts/partials/thread-preview.html +41 -31
  469. package/src/services/export-theme/layouts/post/list.html +1 -1
  470. package/src/services/export-theme/layouts/smart_collection/list.html +24 -0
  471. package/src/services/export-theme/styles/main.css +13 -2
  472. package/src/services/export-theme/theme.toml +1 -1
  473. package/src/services/export.ts +880 -72
  474. package/src/services/github-app-installations.ts +171 -4
  475. package/src/services/github-sync.ts +69 -15
  476. package/src/services/index.ts +34 -3
  477. package/src/services/language.ts +412 -0
  478. package/src/services/mcp.ts +22 -2
  479. package/src/services/media.ts +22 -7
  480. package/src/services/navigation.ts +429 -67
  481. package/src/services/path.ts +254 -6
  482. package/src/services/post.ts +1234 -190
  483. package/src/services/search.ts +39 -2
  484. package/src/services/settings.ts +238 -43
  485. package/src/services/site-admin.ts +27 -14
  486. package/src/services/site.ts +160 -32
  487. package/src/services/smart-collection.ts +636 -0
  488. package/src/services/telegram.ts +20 -22
  489. package/src/services/upload-session.ts +1 -3
  490. package/src/style-author.css +27 -0
  491. package/src/styles/components-author.css +1622 -0
  492. package/src/styles/components.css +24 -1571
  493. package/src/styles/site-media.css +16 -2
  494. package/src/styles/tokens.css +82 -12
  495. package/src/styles/ui-author.css +7602 -0
  496. package/src/styles/ui.css +1090 -7216
  497. package/src/types/app-context.ts +23 -0
  498. package/src/types/bindings.ts +8 -0
  499. package/src/types/config.ts +94 -15
  500. package/src/types/constants.ts +188 -16
  501. package/src/types/entities.ts +87 -1
  502. package/src/types/operations.ts +74 -2
  503. package/src/types/props.ts +157 -31
  504. package/src/types/views.ts +55 -1
  505. package/src/ui/__tests__/font-themes.test.ts +52 -12
  506. package/src/ui/compose/ComposeDialog.tsx +201 -7
  507. package/src/ui/compose/ComposePrompt.tsx +1 -5
  508. package/src/ui/compose/__tests__/ComposeDialog.test.tsx +125 -0
  509. package/src/ui/dash/appearance/AdvancedContent.tsx +2 -2
  510. package/src/ui/dash/appearance/CodeInjectionContent.tsx +12 -16
  511. package/src/ui/dash/appearance/NavigationContent.tsx +117 -16
  512. package/src/ui/dash/appearance/__tests__/NavigationContent.test.tsx +33 -11
  513. package/src/ui/dash/appearance/__tests__/system-nav-descriptions.test.ts +44 -0
  514. package/src/ui/dash/appearance/system-nav-descriptions.ts +75 -0
  515. package/src/ui/dash/settings/AccountMenuContent.tsx +2 -2
  516. package/src/ui/dash/settings/ApiTokensContent.tsx +2 -1
  517. package/src/ui/dash/settings/ConfigEditorContent.tsx +35 -16
  518. package/src/ui/dash/settings/GeneralContent.tsx +277 -113
  519. package/src/ui/dash/settings/LanguageContent.tsx +409 -0
  520. package/src/ui/dash/settings/SettingsRootContent.tsx +19 -1
  521. package/src/ui/dash/settings/__tests__/GeneralContent.test.tsx +324 -4
  522. package/src/ui/dash/settings/__tests__/LanguageContent.test.tsx +144 -0
  523. package/src/ui/dash/settings/__tests__/discover-copy.test.ts +66 -0
  524. package/src/ui/dash/settings/discover-copy.ts +116 -0
  525. package/src/ui/feed/LinkCard.tsx +55 -45
  526. package/src/ui/feed/NoteCard.tsx +9 -4
  527. package/src/ui/feed/PostStatusBadges.tsx +90 -43
  528. package/src/ui/feed/QuoteCard.tsx +55 -30
  529. package/src/ui/feed/ThreadPreview.tsx +6 -2
  530. package/src/ui/feed/__tests__/thread-preview.test.ts +13 -16
  531. package/src/ui/feed/__tests__/timeline-cards.test.ts +314 -49
  532. package/src/ui/feed/thread-preview-state.ts +20 -6
  533. package/src/ui/font-themes.ts +39 -29
  534. package/src/ui/layouts/BaseLayout.tsx +155 -10
  535. package/src/ui/layouts/SiteLayout.tsx +192 -34
  536. package/src/ui/layouts/__tests__/BaseLayout.test.tsx +196 -17
  537. package/src/ui/layouts/__tests__/SiteLayout.test.tsx +109 -85
  538. package/src/ui/pages/ArchivePage.tsx +282 -289
  539. package/src/ui/pages/CollectionPage.tsx +86 -76
  540. package/src/ui/pages/CollectionsPage.tsx +5 -0
  541. package/src/ui/pages/ComposePage.tsx +8 -0
  542. package/src/ui/pages/PostPage.tsx +47 -0
  543. package/src/ui/pages/SearchPage.tsx +3 -3
  544. package/src/ui/pages/SmartCollectionPage.tsx +434 -0
  545. package/src/ui/pages/SubscribePage.tsx +236 -0
  546. package/src/ui/pages/__tests__/ArchivePage.test.tsx +65 -9
  547. package/src/ui/pages/__tests__/collections-directory-rows.test.tsx +92 -0
  548. package/src/ui/pages/__tests__/collections-view-links.test.tsx +81 -0
  549. package/src/ui/shared/CollectionDirectory.tsx +178 -3
  550. package/src/ui/shared/CollectionsManager.tsx +70 -17
  551. package/src/ui/shared/CopyField.tsx +127 -0
  552. package/src/ui/shared/EmptyPostContent.tsx +23 -0
  553. package/src/ui/shared/MediaGallery.tsx +125 -46
  554. package/src/ui/shared/Pagination.tsx +20 -5
  555. package/src/ui/shared/PostFooter.tsx +20 -11
  556. package/src/ui/shared/__tests__/archive-labels.test.ts +100 -0
  557. package/src/ui/shared/__tests__/media-gallery.test.ts +210 -2
  558. package/src/ui/shared/__tests__/navigation-labels.test.ts +16 -22
  559. package/src/ui/shared/__tests__/pagination.test.ts +38 -24
  560. package/src/ui/shared/__tests__/post-footer.test.ts +32 -0
  561. package/src/ui/shared/archive-labels.ts +98 -0
  562. package/src/ui/shared/collection-management-labels.ts +94 -16
  563. package/src/ui/shared/navigation-labels.ts +45 -71
  564. package/src/ui/shared/post-article-attributes.ts +2 -0
  565. package/src/ui/shared/smart-collection-labels.ts +343 -0
  566. package/dist/app-C75Zc8dD.js +0 -6
  567. package/dist/client/_assets/chunks/heic-to-DUUaO23q.js +0 -1
  568. package/dist/client/_assets/chunks/module-DcsAZQZ_.js +0 -716
  569. package/dist/client/_assets/chunks/url-CU9pEbk5.js +0 -1
  570. package/dist/client/_assets/client-Bq0vre8Y.js +0 -296
  571. package/dist/client/_assets/client-D3VZyG4L.css +0 -2
  572. package/dist/client/_assets/client-auth-F2rb9WfF.js +0 -5571
  573. package/dist/env-BPYViDJJ.js +0 -281
  574. package/dist/export-Dl5KCiEs.js +0 -5562
  575. package/dist/github-api-BNF35Lkx.js +0 -176
  576. package/dist/github-app-DdiD-bC4.js +0 -275
  577. package/dist/github-sync-Bqg62IvV.js +0 -4
  578. package/dist/github-sync-HdK2EgvJ.js +0 -431
  579. package/dist/url-CbLAtlZe.js +0 -900
  580. package/src/client/__tests__/collection-created-notice.test.ts +0 -36
  581. package/src/client/__tests__/collection-form-bridge.test.ts +0 -216
  582. package/src/client/__tests__/post-form-bridge.test.ts +0 -82
  583. package/src/client/collection-created-notice.ts +0 -66
  584. package/src/client/collection-form-bridge.ts +0 -191
  585. package/src/client/components/__tests__/jant-post-form.test.ts +0 -193
  586. package/src/client/components/jant-post-form.ts +0 -422
  587. package/src/client/components/post-form-template.ts +0 -352
  588. package/src/client/components/post-form-types.ts +0 -96
  589. package/src/client/media-metadata.ts +0 -247
  590. package/src/client/post-form-bridge.ts +0 -193
  591. package/src/client/tiptap/exitable-marks.ts +0 -73
  592. package/src/ui/pages/CollectionEditorPage.tsx +0 -175
@@ -1,176 +0,0 @@
1
- import { x as __exportAll } from "./url-CbLAtlZe.js";
2
- //#region src/lib/github-api.ts
3
- var github_api_exports = /* @__PURE__ */ __exportAll({
4
- GitHubApiError: () => GitHubApiError,
5
- createGitHubClient: () => createGitHubClient,
6
- parseRepoSlug: () => parseRepoSlug
7
- });
8
- /**
9
- * GitHub REST API client for content sync.
10
- *
11
- * Pure fetch-based — no npm dependencies. Works in both Cloudflare Workers
12
- * and Node 18+.
13
- */ var API_BASE = "https://api.github.com";
14
- var COMMON_HEADERS = {
15
- Accept: "application/vnd.github+json",
16
- "X-GitHub-Api-Version": "2022-11-28",
17
- "User-Agent": "jant-github-sync"
18
- };
19
- var GitHubApiError = class extends Error {
20
- status;
21
- body;
22
- url;
23
- constructor(status, body, url) {
24
- super(`GitHub API ${status}: ${body} (${url})`), this.status = status, this.body = body, this.url = url;
25
- this.name = "GitHubApiError";
26
- }
27
- };
28
- /**
29
- * Create a GitHub API client.
30
- *
31
- * Accepts either a static token (PAT) or a provider function that returns a
32
- * fresh token on each request (used for short-lived GitHub App installation
33
- * tokens which need to be refreshed before expiry — the provider handles
34
- * caching internally).
35
- */ function createGitHubClient(auth) {
36
- const getToken = typeof auth === "string" ? async () => auth : auth;
37
- async function request(method, path, body) {
38
- const url = `${API_BASE}${path}`;
39
- const token = await getToken();
40
- const res = await fetch(url, {
41
- method,
42
- headers: {
43
- ...COMMON_HEADERS,
44
- Authorization: `Bearer ${token}`,
45
- ...body !== void 0 ? { "Content-Type": "application/json" } : {}
46
- },
47
- body: body !== void 0 ? JSON.stringify(body) : void 0
48
- });
49
- if (!res.ok) {
50
- const text = await res.text();
51
- throw new GitHubApiError(res.status, text, url);
52
- }
53
- if (res.status === 204) return void 0;
54
- return await res.json();
55
- }
56
- async function requestOrNull(method, path) {
57
- const url = `${API_BASE}${path}`;
58
- const token = await getToken();
59
- const res = await fetch(url, {
60
- method,
61
- headers: {
62
- ...COMMON_HEADERS,
63
- Authorization: `Bearer ${token}`
64
- }
65
- });
66
- if (res.status === 404) return null;
67
- if (!res.ok) {
68
- const text = await res.text();
69
- throw new GitHubApiError(res.status, text, url);
70
- }
71
- return await res.json();
72
- }
73
- return {
74
- async getRepo(owner, repo) {
75
- return request("GET", `/repos/${owner}/${repo}`);
76
- },
77
- async getRef(owner, repo, ref) {
78
- return { sha: (await request("GET", `/repos/${owner}/${repo}/git/ref/${ref}`)).object.sha };
79
- },
80
- async getCommit(owner, repo, sha) {
81
- const data = await request("GET", `/repos/${owner}/${repo}/git/commits/${sha}`);
82
- return {
83
- sha: data.sha,
84
- treeSha: data.tree.sha
85
- };
86
- },
87
- async updateRef(owner, repo, ref, sha) {
88
- await request("PATCH", `/repos/${owner}/${repo}/git/refs/${ref}`, {
89
- sha,
90
- force: false
91
- });
92
- },
93
- async createRef(owner, repo, ref, sha) {
94
- await request("POST", `/repos/${owner}/${repo}/git/refs`, {
95
- ref: `refs/${ref}`,
96
- sha
97
- });
98
- },
99
- async getFileContent(owner, repo, path, ref) {
100
- return requestOrNull("GET", `/repos/${owner}/${repo}/contents/${path}${ref ? `?ref=${encodeURIComponent(ref)}` : ""}`);
101
- },
102
- async createOrUpdateFile(owner, repo, path, opts) {
103
- const body = {
104
- message: opts.message,
105
- content: btoa(unescape(encodeURIComponent(opts.content)))
106
- };
107
- if (opts.sha) body.sha = opts.sha;
108
- if (opts.branch) body.branch = opts.branch;
109
- return { sha: (await request("PUT", `/repos/${owner}/${repo}/contents/${path}`, body)).content.sha };
110
- },
111
- async deleteFile(owner, repo, path, opts) {
112
- await request("DELETE", `/repos/${owner}/${repo}/contents/${path}`, {
113
- message: opts.message,
114
- sha: opts.sha,
115
- ...opts.branch ? { branch: opts.branch } : {}
116
- });
117
- },
118
- async createBlob(owner, repo, content, encoding) {
119
- return request("POST", `/repos/${owner}/${repo}/git/blobs`, {
120
- content,
121
- encoding
122
- });
123
- },
124
- async createTree(owner, repo, items, baseTree) {
125
- return request("POST", `/repos/${owner}/${repo}/git/trees`, {
126
- tree: items,
127
- ...baseTree ? { base_tree: baseTree } : {}
128
- });
129
- },
130
- async getTree(owner, repo, sha, opts) {
131
- return request("GET", `/repos/${owner}/${repo}/git/trees/${sha}${opts?.recursive ? "?recursive=1" : ""}`);
132
- },
133
- async createCommit(owner, repo, opts) {
134
- return request("POST", `/repos/${owner}/${repo}/git/commits`, {
135
- message: opts.message,
136
- tree: opts.tree,
137
- parents: opts.parents
138
- });
139
- },
140
- async createWebhook(owner, repo, opts) {
141
- return request("POST", `/repos/${owner}/${repo}/hooks`, {
142
- name: "web",
143
- active: true,
144
- events: opts.events,
145
- config: {
146
- url: opts.url,
147
- secret: opts.secret,
148
- content_type: "json",
149
- insecure_ssl: "0"
150
- }
151
- });
152
- },
153
- async listWebhooks(owner, repo) {
154
- return request("GET", `/repos/${owner}/${repo}/hooks`);
155
- },
156
- async deleteWebhook(owner, repo, hookId) {
157
- await request("DELETE", `/repos/${owner}/${repo}/hooks/${hookId}`);
158
- }
159
- };
160
- }
161
- /**
162
- * Parse an `owner/repo` string into its parts.
163
- *
164
- * @returns `{ owner, repo }` or `null` if the format is invalid.
165
- */ function parseRepoSlug(slug) {
166
- const match = /^([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)$/.exec(slug.trim());
167
- if (!match) return null;
168
- const [, owner, repo] = match;
169
- if (!owner || !repo) return null;
170
- return {
171
- owner,
172
- repo
173
- };
174
- }
175
- //#endregion
176
- export { github_api_exports as n, parseRepoSlug as r, createGitHubClient as t };
@@ -1,275 +0,0 @@
1
- import { x as __exportAll } from "./url-CbLAtlZe.js";
2
- //#region src/lib/github-app.ts
3
- var github_app_exports = /* @__PURE__ */ __exportAll({
4
- buildInstallUrl: () => buildInstallUrl,
5
- createAppJwt: () => createAppJwt,
6
- getInstallation: () => getInstallation,
7
- getInstallationToken: () => getInstallationToken,
8
- listInstallationReposPage: () => listInstallationReposPage,
9
- searchInstallationRepos: () => searchInstallationRepos
10
- });
11
- /**
12
- * GitHub App authentication helpers.
13
- *
14
- * Implements the App → installation token exchange using Web Crypto so it
15
- * runs unchanged in Cloudflare Workers and Node 18+.
16
- *
17
- * Flow:
18
- * 1. Sign a short-lived JWT with the App's RSA private key (RS256).
19
- * 2. Exchange the JWT for a per-installation access token.
20
- * 3. Cache the installation token in-process until shortly before expiry.
21
- *
22
- * The installation token can then be passed to `createGitHubClient` the same
23
- * way a PAT is — the downstream client is auth-agnostic.
24
- */ var GITHUB_API = "https://api.github.com";
25
- var tokenCache = /* @__PURE__ */ new Map();
26
- var CACHE_SAFETY_MARGIN_SECONDS = 60;
27
- function cacheKey(appId, installationId) {
28
- return `${appId}:${installationId}`;
29
- }
30
- function base64UrlEncode(input) {
31
- let bytes;
32
- if (typeof input === "string") bytes = new TextEncoder().encode(input);
33
- else if (input instanceof Uint8Array) bytes = input;
34
- else bytes = new Uint8Array(input);
35
- let binary = "";
36
- for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
37
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
38
- }
39
- /**
40
- * ASN.1 DER length encoding (short form for < 128, long form otherwise).
41
- * Used to wrap a PKCS#1 key inside a PKCS#8 envelope.
42
- */ function encodeDerLength(len) {
43
- if (len < 128) return [len];
44
- if (len <= 255) return [129, len];
45
- if (len <= 65535) return [
46
- 130,
47
- len >> 8 & 255,
48
- len & 255
49
- ];
50
- throw new Error("Private key too large to encode");
51
- }
52
- /**
53
- * Wrap a PKCS#1 `RSAPrivateKey` DER blob in a PKCS#8 `PrivateKeyInfo` envelope.
54
- * Web Crypto's `importKey("pkcs8", ...)` only accepts PKCS#8, but GitHub
55
- * hands out PKCS#1 PEMs (`-----BEGIN RSA PRIVATE KEY-----`) by default, so
56
- * we wrap on the fly when we detect that header.
57
- */ function wrapPkcs1AsPkcs8(pkcs1) {
58
- const rsaAlgorithmIdentifier = [
59
- 48,
60
- 13,
61
- 6,
62
- 9,
63
- 42,
64
- 134,
65
- 72,
66
- 134,
67
- 247,
68
- 13,
69
- 1,
70
- 1,
71
- 1,
72
- 5,
73
- 0
74
- ];
75
- const version = [
76
- 2,
77
- 1,
78
- 0
79
- ];
80
- const octetStringHeader = [4, ...encodeDerLength(pkcs1.length)];
81
- const bodyLen = version.length + rsaAlgorithmIdentifier.length + octetStringHeader.length + pkcs1.length;
82
- const outerHeader = [48, ...encodeDerLength(bodyLen)];
83
- const out = new Uint8Array(outerHeader.length + bodyLen);
84
- let off = 0;
85
- out.set(outerHeader, off);
86
- off += outerHeader.length;
87
- out.set(version, off);
88
- off += version.length;
89
- out.set(rsaAlgorithmIdentifier, off);
90
- off += rsaAlgorithmIdentifier.length;
91
- out.set(octetStringHeader, off);
92
- off += octetStringHeader.length;
93
- out.set(pkcs1, off);
94
- return out;
95
- }
96
- function pemToPkcs8(pem) {
97
- const isPkcs1 = /-----BEGIN RSA PRIVATE KEY-----/.test(pem);
98
- const cleaned = pem.replace(/-----BEGIN [^-]+-----/g, "").replace(/-----END [^-]+-----/g, "").replace(/\s+/g, "");
99
- if (!cleaned) throw new Error("Empty GitHub App private key");
100
- const binary = atob(cleaned);
101
- const rawDer = new Uint8Array(binary.length);
102
- for (let i = 0; i < binary.length; i++) rawDer[i] = binary.charCodeAt(i);
103
- const pkcs8 = isPkcs1 ? wrapPkcs1AsPkcs8(rawDer) : rawDer;
104
- const out = new ArrayBuffer(pkcs8.byteLength);
105
- new Uint8Array(out).set(pkcs8);
106
- return out;
107
- }
108
- async function importPrivateKey(pem) {
109
- return crypto.subtle.importKey("pkcs8", pemToPkcs8(pem), {
110
- name: "RSASSA-PKCS1-v1_5",
111
- hash: "SHA-256"
112
- }, false, ["sign"]);
113
- }
114
- /**
115
- * Create a JWT signed with the GitHub App's private key.
116
- *
117
- * GitHub allows up to 10 minutes; we issue 9 minutes with a 60s backdated `iat`
118
- * to tolerate clock skew.
119
- */ async function createAppJwt(appId, privateKeyPem) {
120
- const now = Math.floor(Date.now() / 1e3);
121
- const header = {
122
- alg: "RS256",
123
- typ: "JWT"
124
- };
125
- const payload = {
126
- iat: now - 60,
127
- exp: now + 540,
128
- iss: appId
129
- };
130
- const signingInput = `${base64UrlEncode(JSON.stringify(header))}.${base64UrlEncode(JSON.stringify(payload))}`;
131
- const key = await importPrivateKey(privateKeyPem);
132
- return `${signingInput}.${base64UrlEncode(await crypto.subtle.sign("RSASSA-PKCS1-v1_5", key, new TextEncoder().encode(signingInput)))}`;
133
- }
134
- /**
135
- * Fetch (or reuse) a short-lived installation access token.
136
- *
137
- * Results are cached in-process until `CACHE_SAFETY_MARGIN_SECONDS` before the
138
- * real expiry so the same token can be reused across a burst of API calls.
139
- */ async function getInstallationToken(app, installationId) {
140
- const key = cacheKey(app.appId, installationId);
141
- const cached = tokenCache.get(key);
142
- const nowSec = Math.floor(Date.now() / 1e3);
143
- if (cached && cached.expiresAt > nowSec) return cached.token;
144
- const jwt = await createAppJwt(app.appId, app.privateKey);
145
- const res = await fetch(`${GITHUB_API}/app/installations/${installationId}/access_tokens`, {
146
- method: "POST",
147
- headers: {
148
- Accept: "application/vnd.github+json",
149
- Authorization: `Bearer ${jwt}`,
150
- "User-Agent": "jant-github-sync",
151
- "X-GitHub-Api-Version": "2022-11-28"
152
- }
153
- });
154
- if (!res.ok) {
155
- const body = await res.text();
156
- throw new Error(`GitHub App token exchange failed (${res.status}): ${body}`);
157
- }
158
- const data = await res.json();
159
- const expiresAt = Math.floor(new Date(data.expires_at).getTime() / 1e3) - CACHE_SAFETY_MARGIN_SECONDS;
160
- tokenCache.set(key, {
161
- token: data.token,
162
- expiresAt
163
- });
164
- return data.token;
165
- }
166
- /**
167
- * Build the URL users visit to install the GitHub App on their account/org.
168
- *
169
- * `state` is a CSRF token the caller should verify on the redirect back.
170
- */ function buildInstallUrl(slug, state) {
171
- const params = new URLSearchParams({ state });
172
- return `https://github.com/apps/${encodeURIComponent(slug)}/installations/new?${params.toString()}`;
173
- }
174
- /**
175
- * Fetch metadata for a given installation, including the account it's
176
- * installed on. Uses an App JWT because the target endpoint is
177
- * `/app/installations/{id}`, which is App-scoped, not installation-scoped.
178
- */ async function getInstallation(app, installationId) {
179
- const jwt = await createAppJwt(app.appId, app.privateKey);
180
- const res = await fetch(`${GITHUB_API}/app/installations/${encodeURIComponent(installationId)}`, { headers: {
181
- Accept: "application/vnd.github+json",
182
- Authorization: `Bearer ${jwt}`,
183
- "User-Agent": "jant-github-sync",
184
- "X-GitHub-Api-Version": "2022-11-28"
185
- } });
186
- if (!res.ok) {
187
- const body = await res.text();
188
- throw new Error(`Fetching installation failed (${res.status}): ${body}`);
189
- }
190
- const data = await res.json();
191
- const type = data.account.type === "Organization" ? "Organization" : "User";
192
- return { account: {
193
- login: data.account.login,
194
- type,
195
- avatarUrl: data.account.avatar_url ?? ""
196
- } };
197
- }
198
- /**
199
- * Fetch a single page of installation repositories.
200
- *
201
- * Used by the picker for lazy-loading. Callers can either stop after the
202
- * first page (UI does local filtering) or keep paging for larger accounts.
203
- * For search, prefer `searchInstallationRepos` — this endpoint does not
204
- * support a query parameter.
205
- */ async function listInstallationReposPage(app, installationId, page, perPage = 100) {
206
- const token = await getInstallationToken(app, installationId);
207
- const res = await fetch(`${GITHUB_API}/installation/repositories?per_page=${perPage}&page=${page}`, { headers: {
208
- Accept: "application/vnd.github+json",
209
- Authorization: `Bearer ${token}`,
210
- "User-Agent": "jant-github-sync",
211
- "X-GitHub-Api-Version": "2022-11-28"
212
- } });
213
- if (!res.ok) {
214
- const body = await res.text();
215
- throw new Error(`Listing installation repos failed: ${res.status} ${body}`);
216
- }
217
- const data = await res.json();
218
- const repos = data.repositories.slice().sort((a, b) => {
219
- const at = Date.parse(a.updated_at ?? a.created_at ?? "") || 0;
220
- return (Date.parse(b.updated_at ?? b.created_at ?? "") || 0) - at;
221
- }).map((r) => ({
222
- fullName: r.full_name,
223
- name: r.name,
224
- private: r.private,
225
- defaultBranch: r.default_branch
226
- }));
227
- const hasMore = repos.length === perPage;
228
- return {
229
- repos,
230
- totalCount: data.total_count,
231
- hasMore,
232
- nextPage: hasMore ? page + 1 : null
233
- };
234
- }
235
- /**
236
- * Search the installation's repositories via `GET /search/repositories`.
237
- *
238
- * GitHub's Search API doesn't scope automatically to an installation, so
239
- * we filter server-side by the installation's account login. This keeps
240
- * results relevant while still covering repos past the first 100.
241
- *
242
- * The `q` string is wrapped (caller passes raw user input, we add the
243
- * scope qualifier). Uses the installation token for auth.
244
- */ async function searchInstallationRepos(app, installationId, accountLogin, q, perPage = 30) {
245
- const token = await getInstallationToken(app, installationId);
246
- const fullQuery = `${q} in:name user:${accountLogin} fork:true`;
247
- const params = new URLSearchParams({
248
- q: fullQuery,
249
- per_page: String(perPage),
250
- sort: "updated",
251
- order: "desc"
252
- });
253
- const res = await fetch(`${GITHUB_API}/search/repositories?${params.toString()}`, { headers: {
254
- Accept: "application/vnd.github+json",
255
- Authorization: `Bearer ${token}`,
256
- "User-Agent": "jant-github-sync",
257
- "X-GitHub-Api-Version": "2022-11-28"
258
- } });
259
- if (!res.ok) {
260
- const body = await res.text();
261
- throw new Error(`Searching repos failed: ${res.status} ${body}`);
262
- }
263
- const data = await res.json();
264
- return {
265
- repos: data.items.map((r) => ({
266
- fullName: r.full_name,
267
- name: r.name,
268
- private: r.private,
269
- defaultBranch: r.default_branch
270
- })),
271
- totalCount: data.total_count
272
- };
273
- }
274
- //#endregion
275
- export { listInstallationReposPage as a, github_app_exports as i, getInstallation as n, searchInstallationRepos as o, getInstallationToken as r, buildInstallUrl as t };
@@ -1,4 +0,0 @@
1
- import "./url-CbLAtlZe.js";
2
- import "./export-Dl5KCiEs.js";
3
- import { i as classifyRepoForSync, o as createGitHubSyncService } from "./github-sync-HdK2EgvJ.js";
4
- export { classifyRepoForSync, createGitHubSyncService };