nebula-cms 0.1.0 → 0.1.4

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 (386) hide show
  1. package/README.md +2 -0
  2. package/dist/astro/index.d.ts +43 -0
  3. package/dist/astro/index.d.ts.map +1 -0
  4. package/dist/astro/index.js +223 -0
  5. package/dist/client/Admin.svelte.d.ts +11 -0
  6. package/dist/client/Admin.svelte.d.ts.map +1 -0
  7. package/dist/client/components/BackendPicker.svelte.d.ts +4 -0
  8. package/dist/client/components/BackendPicker.svelte.d.ts.map +1 -0
  9. package/dist/client/components/DraftChip.svelte.d.ts +10 -0
  10. package/dist/client/components/DraftChip.svelte.d.ts.map +1 -0
  11. package/dist/client/components/MetadataForm.svelte.d.ts +12 -0
  12. package/dist/client/components/MetadataForm.svelte.d.ts.map +1 -0
  13. package/dist/client/components/ThemeToggle.svelte.d.ts +19 -0
  14. package/dist/client/components/ThemeToggle.svelte.d.ts.map +1 -0
  15. package/dist/client/components/dialogs/DeleteDraftDialog.svelte.d.ts +11 -0
  16. package/dist/client/components/dialogs/DeleteDraftDialog.svelte.d.ts.map +1 -0
  17. package/dist/client/components/dialogs/FilenameDialog.svelte.d.ts +13 -0
  18. package/dist/client/components/dialogs/FilenameDialog.svelte.d.ts.map +1 -0
  19. package/dist/client/components/editor/EditorPane.svelte.d.ts +4 -0
  20. package/dist/client/components/editor/EditorPane.svelte.d.ts.map +1 -0
  21. package/dist/client/components/editor/EditorTabs.svelte.d.ts +8 -0
  22. package/dist/client/components/editor/EditorTabs.svelte.d.ts.map +1 -0
  23. package/dist/client/components/editor/EditorToolbar.svelte.d.ts +4 -0
  24. package/dist/client/components/editor/EditorToolbar.svelte.d.ts.map +1 -0
  25. package/dist/client/components/editor/FormatSelector.svelte.d.ts +4 -0
  26. package/dist/client/components/editor/FormatSelector.svelte.d.ts.map +1 -0
  27. package/dist/client/components/editor/Toolbar.svelte.d.ts +19 -0
  28. package/dist/client/components/editor/Toolbar.svelte.d.ts.map +1 -0
  29. package/dist/client/components/fields/ArrayField.svelte.d.ts +15 -0
  30. package/dist/client/components/fields/ArrayField.svelte.d.ts.map +1 -0
  31. package/dist/client/components/fields/ArrayItem.svelte.d.ts +28 -0
  32. package/dist/client/components/fields/ArrayItem.svelte.d.ts.map +1 -0
  33. package/dist/client/components/fields/BooleanField.svelte.d.ts +16 -0
  34. package/dist/client/components/fields/BooleanField.svelte.d.ts.map +1 -0
  35. package/dist/client/components/fields/DateField.svelte.d.ts +16 -0
  36. package/dist/client/components/fields/DateField.svelte.d.ts.map +1 -0
  37. package/dist/client/components/fields/EnumField.svelte.d.ts +17 -0
  38. package/dist/client/components/fields/EnumField.svelte.d.ts.map +1 -0
  39. package/dist/client/components/fields/FieldWrapper.svelte.d.ts +18 -0
  40. package/dist/client/components/fields/FieldWrapper.svelte.d.ts.map +1 -0
  41. package/dist/client/components/fields/NumberField.svelte.d.ts +16 -0
  42. package/dist/client/components/fields/NumberField.svelte.d.ts.map +1 -0
  43. package/dist/client/components/fields/ObjectField.svelte.d.ts +16 -0
  44. package/dist/client/components/fields/ObjectField.svelte.d.ts.map +1 -0
  45. package/dist/client/components/fields/SchemaField.svelte.d.ts +16 -0
  46. package/dist/client/components/fields/SchemaField.svelte.d.ts.map +1 -0
  47. package/dist/client/components/fields/StringField.svelte.d.ts +16 -0
  48. package/dist/client/components/fields/StringField.svelte.d.ts.map +1 -0
  49. package/dist/client/components/sidebar/AdminSidebar.svelte.d.ts +19 -0
  50. package/dist/client/components/sidebar/AdminSidebar.svelte.d.ts.map +1 -0
  51. package/dist/client/components/sidebar/AdminSidebarSort.svelte.d.ts +12 -0
  52. package/dist/client/components/sidebar/AdminSidebarSort.svelte.d.ts.map +1 -0
  53. package/dist/client/css/icons.css +29 -0
  54. package/dist/client/index.d.ts +2 -0
  55. package/dist/client/index.d.ts.map +1 -0
  56. package/dist/client/js/drafts/merge.svelte.d.ts +24 -0
  57. package/dist/client/js/drafts/merge.svelte.d.ts.map +1 -0
  58. package/dist/client/js/drafts/merge.svelte.js +106 -0
  59. package/dist/client/js/drafts/ops.svelte.d.ts +31 -0
  60. package/dist/client/js/drafts/ops.svelte.d.ts.map +1 -0
  61. package/dist/client/js/drafts/ops.svelte.js +182 -0
  62. package/dist/client/js/drafts/storage.d.ts +45 -0
  63. package/dist/client/js/drafts/storage.d.ts.map +1 -0
  64. package/dist/client/js/drafts/storage.js +76 -0
  65. package/dist/client/js/drafts/workers/diff.d.ts +2 -0
  66. package/dist/client/js/drafts/workers/diff.d.ts.map +1 -0
  67. package/dist/client/js/drafts/workers/diff.js +20 -0
  68. package/dist/client/js/editor/editor.svelte.d.ts +124 -0
  69. package/dist/client/js/editor/editor.svelte.d.ts.map +1 -0
  70. package/dist/client/js/editor/editor.svelte.js +294 -0
  71. package/dist/client/js/editor/languages.d.ts +11 -0
  72. package/dist/client/js/editor/languages.d.ts.map +1 -0
  73. package/dist/client/js/editor/languages.js +93 -0
  74. package/dist/client/js/editor/link-wrap.d.ts +6 -0
  75. package/dist/client/js/editor/link-wrap.d.ts.map +1 -0
  76. package/{src/client/js/editor/link-wrap.ts → dist/client/js/editor/link-wrap.js} +17 -24
  77. package/dist/client/js/editor/markdown-shortcuts.d.ts +4 -0
  78. package/dist/client/js/editor/markdown-shortcuts.d.ts.map +1 -0
  79. package/dist/client/js/editor/markdown-shortcuts.js +219 -0
  80. package/dist/client/js/handlers/admin.d.ts +64 -0
  81. package/dist/client/js/handlers/admin.d.ts.map +1 -0
  82. package/dist/client/js/handlers/admin.js +186 -0
  83. package/dist/client/js/state/dialogs.svelte.d.ts +16 -0
  84. package/dist/client/js/state/dialogs.svelte.d.ts.map +1 -0
  85. package/dist/client/js/state/dialogs.svelte.js +28 -0
  86. package/dist/client/js/state/router.svelte.d.ts +44 -0
  87. package/dist/client/js/state/router.svelte.d.ts.map +1 -0
  88. package/dist/client/js/state/router.svelte.js +135 -0
  89. package/dist/client/js/state/schema.svelte.d.ts +51 -0
  90. package/dist/client/js/state/schema.svelte.d.ts.map +1 -0
  91. package/{src/client/js/state/schema.svelte.ts → dist/client/js/state/schema.svelte.js} +55 -70
  92. package/dist/client/js/state/state.svelte.d.ts +68 -0
  93. package/dist/client/js/state/state.svelte.d.ts.map +1 -0
  94. package/dist/client/js/state/state.svelte.js +291 -0
  95. package/dist/client/js/state/theme.svelte.d.ts +24 -0
  96. package/dist/client/js/state/theme.svelte.d.ts.map +1 -0
  97. package/{src/client/js/state/theme.svelte.ts → dist/client/js/state/theme.svelte.js} +54 -91
  98. package/dist/client/js/storage/adapter.d.ts +130 -0
  99. package/dist/client/js/storage/adapter.d.ts.map +1 -0
  100. package/dist/client/js/storage/adapter.js +5 -0
  101. package/dist/client/js/storage/client.d.ts +72 -0
  102. package/dist/client/js/storage/client.d.ts.map +1 -0
  103. package/dist/client/js/storage/client.js +121 -0
  104. package/dist/client/js/storage/db.d.ts +8 -0
  105. package/dist/client/js/storage/db.d.ts.map +1 -0
  106. package/dist/client/js/storage/db.js +35 -0
  107. package/dist/client/js/storage/fsa.d.ts +51 -0
  108. package/dist/client/js/storage/fsa.d.ts.map +1 -0
  109. package/dist/client/js/storage/fsa.js +91 -0
  110. package/dist/client/js/storage/github.d.ts +62 -0
  111. package/dist/client/js/storage/github.d.ts.map +1 -0
  112. package/dist/client/js/storage/github.js +216 -0
  113. package/dist/client/js/storage/storage.d.ts +32 -0
  114. package/dist/client/js/storage/storage.d.ts.map +1 -0
  115. package/dist/client/js/storage/storage.js +68 -0
  116. package/dist/client/js/storage/workers/frontmatter.d.ts +2 -0
  117. package/dist/client/js/storage/workers/frontmatter.d.ts.map +1 -0
  118. package/dist/client/js/storage/workers/frontmatter.js +253 -0
  119. package/dist/client/js/storage/workers/storage.d.ts +2 -0
  120. package/dist/client/js/storage/workers/storage.d.ts.map +1 -0
  121. package/dist/client/js/storage/workers/storage.js +167 -0
  122. package/dist/client/js/storage/workers/toml-parser.d.ts +2 -0
  123. package/dist/client/js/storage/workers/toml-parser.d.ts.map +1 -0
  124. package/dist/client/js/storage/workers/toml-parser.js +75 -0
  125. package/dist/client/js/storage/workers/yaml-parser.d.ts +2 -0
  126. package/dist/client/js/storage/workers/yaml-parser.d.ts.map +1 -0
  127. package/dist/client/js/storage/workers/yaml-parser.js +100 -0
  128. package/dist/client/js/utils/file-types.d.ts +58 -0
  129. package/dist/client/js/utils/file-types.d.ts.map +1 -0
  130. package/{src/client/js/utils/file-types.ts → dist/client/js/utils/file-types.js} +75 -107
  131. package/dist/client/js/utils/format.d.ts +8 -0
  132. package/dist/client/js/utils/format.d.ts.map +1 -0
  133. package/{src/client/js/utils/format.ts → dist/client/js/utils/format.js} +5 -6
  134. package/dist/client/js/utils/frontmatter.d.ts +12 -0
  135. package/dist/client/js/utils/frontmatter.d.ts.map +1 -0
  136. package/dist/client/js/utils/frontmatter.js +29 -0
  137. package/dist/client/js/utils/schema-utils.d.ts +110 -0
  138. package/dist/client/js/utils/schema-utils.d.ts.map +1 -0
  139. package/dist/client/js/utils/schema-utils.js +242 -0
  140. package/dist/client/js/utils/slug.d.ts +8 -0
  141. package/dist/client/js/utils/slug.d.ts.map +1 -0
  142. package/{src/client/js/utils/slug.ts → dist/client/js/utils/slug.js} +6 -7
  143. package/dist/client/js/utils/sort.d.ts +41 -0
  144. package/dist/client/js/utils/sort.d.ts.map +1 -0
  145. package/dist/client/js/utils/sort.js +65 -0
  146. package/dist/client/js/utils/stable-stringify.d.ts +8 -0
  147. package/dist/client/js/utils/stable-stringify.d.ts.map +1 -0
  148. package/dist/client/js/utils/stable-stringify.js +23 -0
  149. package/dist/client/js/utils/url-utils.d.ts +11 -0
  150. package/dist/client/js/utils/url-utils.d.ts.map +1 -0
  151. package/{src/client/js/utils/url-utils.ts → dist/client/js/utils/url-utils.js} +22 -23
  152. package/dist/types.d.ts +22 -0
  153. package/dist/types.d.ts.map +1 -0
  154. package/dist/types.js +1 -0
  155. package/package.json +8 -1
  156. package/.claude/settings.local.json +0 -42
  157. package/.github/workflows/ci.yml +0 -31
  158. package/.mcp.json +0 -12
  159. package/.prettierignore +0 -5
  160. package/.prettierrc.cjs +0 -22
  161. package/AGENTS.md +0 -183
  162. package/playground/.claude/settings.local.json +0 -5
  163. package/playground/astro.config.mjs +0 -7
  164. package/playground/node_modules/.bin/astro +0 -21
  165. package/playground/node_modules/.bin/rollup +0 -21
  166. package/playground/node_modules/.bin/tsc +0 -21
  167. package/playground/node_modules/.bin/tsserver +0 -21
  168. package/playground/node_modules/.bin/vite +0 -21
  169. package/playground/node_modules/.vite/_svelte_metadata.json +0 -1
  170. package/playground/node_modules/.vite/deps/@astrojs_svelte_client__js.js +0 -80
  171. package/playground/node_modules/.vite/deps/@astrojs_svelte_client__js.js.map +0 -7
  172. package/playground/node_modules/.vite/deps/_metadata.json +0 -184
  173. package/playground/node_modules/.vite/deps/astro___aria-query.js +0 -6776
  174. package/playground/node_modules/.vite/deps/astro___aria-query.js.map +0 -7
  175. package/playground/node_modules/.vite/deps/astro___axobject-query.js +0 -3754
  176. package/playground/node_modules/.vite/deps/astro___axobject-query.js.map +0 -7
  177. package/playground/node_modules/.vite/deps/astro___html-escaper.js +0 -34
  178. package/playground/node_modules/.vite/deps/astro___html-escaper.js.map +0 -7
  179. package/playground/node_modules/.vite/deps/chunk-AJXJMYAF.js +0 -0
  180. package/playground/node_modules/.vite/deps/chunk-AJXJMYAF.js.map +0 -7
  181. package/playground/node_modules/.vite/deps/chunk-ALJIOON6.js +0 -1005
  182. package/playground/node_modules/.vite/deps/chunk-ALJIOON6.js.map +0 -7
  183. package/playground/node_modules/.vite/deps/chunk-BUSYA2B4.js +0 -8
  184. package/playground/node_modules/.vite/deps/chunk-BUSYA2B4.js.map +0 -7
  185. package/playground/node_modules/.vite/deps/chunk-CNYJBM5F.js +0 -21
  186. package/playground/node_modules/.vite/deps/chunk-CNYJBM5F.js.map +0 -7
  187. package/playground/node_modules/.vite/deps/chunk-DBPNBGEI.js +0 -223
  188. package/playground/node_modules/.vite/deps/chunk-DBPNBGEI.js.map +0 -7
  189. package/playground/node_modules/.vite/deps/chunk-G3C2FXJT.js +0 -204
  190. package/playground/node_modules/.vite/deps/chunk-G3C2FXJT.js.map +0 -7
  191. package/playground/node_modules/.vite/deps/chunk-GKDKFWC5.js +0 -27
  192. package/playground/node_modules/.vite/deps/chunk-GKDKFWC5.js.map +0 -7
  193. package/playground/node_modules/.vite/deps/chunk-HNCLEOC5.js +0 -4376
  194. package/playground/node_modules/.vite/deps/chunk-HNCLEOC5.js.map +0 -7
  195. package/playground/node_modules/.vite/deps/chunk-JICYXBFU.js +0 -688
  196. package/playground/node_modules/.vite/deps/chunk-JICYXBFU.js.map +0 -7
  197. package/playground/node_modules/.vite/deps/chunk-KCUTL6DD.js +0 -5099
  198. package/playground/node_modules/.vite/deps/chunk-KCUTL6DD.js.map +0 -7
  199. package/playground/node_modules/.vite/deps/chunk-ZP4UNCSN.js +0 -23
  200. package/playground/node_modules/.vite/deps/chunk-ZP4UNCSN.js.map +0 -7
  201. package/playground/node_modules/.vite/deps/chunk-ZREFNRZZ.js +0 -148
  202. package/playground/node_modules/.vite/deps/chunk-ZREFNRZZ.js.map +0 -7
  203. package/playground/node_modules/.vite/deps/package.json +0 -3
  204. package/playground/node_modules/.vite/deps/smol-toml.js +0 -843
  205. package/playground/node_modules/.vite/deps/smol-toml.js.map +0 -7
  206. package/playground/node_modules/.vite/deps/svelte.js +0 -55
  207. package/playground/node_modules/.vite/deps/svelte.js.map +0 -7
  208. package/playground/node_modules/.vite/deps/svelte___clsx.js +0 -9
  209. package/playground/node_modules/.vite/deps/svelte___clsx.js.map +0 -7
  210. package/playground/node_modules/.vite/deps/svelte_animate.js +0 -57
  211. package/playground/node_modules/.vite/deps/svelte_animate.js.map +0 -7
  212. package/playground/node_modules/.vite/deps/svelte_attachments.js +0 -15
  213. package/playground/node_modules/.vite/deps/svelte_attachments.js.map +0 -7
  214. package/playground/node_modules/.vite/deps/svelte_easing.js +0 -67
  215. package/playground/node_modules/.vite/deps/svelte_easing.js.map +0 -7
  216. package/playground/node_modules/.vite/deps/svelte_events.js +0 -11
  217. package/playground/node_modules/.vite/deps/svelte_events.js.map +0 -7
  218. package/playground/node_modules/.vite/deps/svelte_internal.js +0 -5
  219. package/playground/node_modules/.vite/deps/svelte_internal.js.map +0 -7
  220. package/playground/node_modules/.vite/deps/svelte_internal_client.js +0 -402
  221. package/playground/node_modules/.vite/deps/svelte_internal_client.js.map +0 -7
  222. package/playground/node_modules/.vite/deps/svelte_internal_disclose-version.js +0 -10
  223. package/playground/node_modules/.vite/deps/svelte_internal_disclose-version.js.map +0 -7
  224. package/playground/node_modules/.vite/deps/svelte_internal_flags_async.js +0 -8
  225. package/playground/node_modules/.vite/deps/svelte_internal_flags_async.js.map +0 -7
  226. package/playground/node_modules/.vite/deps/svelte_internal_flags_legacy.js +0 -8
  227. package/playground/node_modules/.vite/deps/svelte_internal_flags_legacy.js.map +0 -7
  228. package/playground/node_modules/.vite/deps/svelte_internal_flags_tracing.js +0 -8
  229. package/playground/node_modules/.vite/deps/svelte_internal_flags_tracing.js.map +0 -7
  230. package/playground/node_modules/.vite/deps/svelte_legacy.js +0 -35
  231. package/playground/node_modules/.vite/deps/svelte_legacy.js.map +0 -7
  232. package/playground/node_modules/.vite/deps/svelte_motion.js +0 -545
  233. package/playground/node_modules/.vite/deps/svelte_motion.js.map +0 -7
  234. package/playground/node_modules/.vite/deps/svelte_reactivity.js +0 -29
  235. package/playground/node_modules/.vite/deps/svelte_reactivity.js.map +0 -7
  236. package/playground/node_modules/.vite/deps/svelte_reactivity_window.js +0 -127
  237. package/playground/node_modules/.vite/deps/svelte_reactivity_window.js.map +0 -7
  238. package/playground/node_modules/.vite/deps/svelte_store.js +0 -103
  239. package/playground/node_modules/.vite/deps/svelte_store.js.map +0 -7
  240. package/playground/node_modules/.vite/deps/svelte_transition.js +0 -208
  241. package/playground/node_modules/.vite/deps/svelte_transition.js.map +0 -7
  242. package/playground/package.json +0 -16
  243. package/playground/pnpm-lock.yaml +0 -3167
  244. package/playground/src/content/authors/jane-doe.json +0 -8
  245. package/playground/src/content/config/build.toml +0 -2
  246. package/playground/src/content/courses/web-fundamentals.json +0 -29
  247. package/playground/src/content/docs/advanced.mdx +0 -6
  248. package/playground/src/content/docs/intro.md +0 -6
  249. package/playground/src/content/guides/getting-started.mdx +0 -6
  250. package/playground/src/content/posts/hello-world.md +0 -7
  251. package/playground/src/content/products/t-shirt.json +0 -16
  252. package/playground/src/content/recipes/pancakes.mdoc +0 -8
  253. package/playground/src/content/settings/site.yml +0 -2
  254. package/playground/src/content.config.ts +0 -198
  255. package/playground/src/env.d.ts +0 -1
  256. package/playground/src/pages/index.astro +0 -11
  257. package/playground/src/pages/nebula.astro +0 -14
  258. package/pnpm-workspace.yaml +0 -2
  259. package/scripts/subset-icons.mjs +0 -178
  260. package/src/astro/index.ts +0 -295
  261. package/src/client/js/drafts/merge.svelte.ts +0 -121
  262. package/src/client/js/drafts/ops.svelte.ts +0 -227
  263. package/src/client/js/drafts/storage.ts +0 -108
  264. package/src/client/js/drafts/workers/diff.ts +0 -40
  265. package/src/client/js/editor/editor.svelte.ts +0 -343
  266. package/src/client/js/editor/languages.ts +0 -98
  267. package/src/client/js/editor/markdown-shortcuts.ts +0 -261
  268. package/src/client/js/handlers/admin.ts +0 -246
  269. package/src/client/js/state/dialogs.svelte.ts +0 -35
  270. package/src/client/js/state/router.svelte.ts +0 -156
  271. package/src/client/js/state/state.svelte.ts +0 -334
  272. package/src/client/js/storage/adapter.ts +0 -102
  273. package/src/client/js/storage/client.ts +0 -150
  274. package/src/client/js/storage/db.ts +0 -36
  275. package/src/client/js/storage/fsa.ts +0 -110
  276. package/src/client/js/storage/github.ts +0 -297
  277. package/src/client/js/storage/storage.ts +0 -83
  278. package/src/client/js/storage/workers/frontmatter.ts +0 -320
  279. package/src/client/js/storage/workers/storage.ts +0 -177
  280. package/src/client/js/storage/workers/toml-parser.ts +0 -106
  281. package/src/client/js/storage/workers/yaml-parser.ts +0 -132
  282. package/src/client/js/utils/frontmatter.ts +0 -38
  283. package/src/client/js/utils/schema-utils.ts +0 -295
  284. package/src/client/js/utils/sort.ts +0 -84
  285. package/src/client/js/utils/stable-stringify.ts +0 -27
  286. package/src/types.ts +0 -25
  287. package/svelte.config.js +0 -4
  288. package/tests/astro/build.test.ts +0 -63
  289. package/tests/astro/index.test.ts +0 -689
  290. package/tests/client/components/Admin.test.ts +0 -446
  291. package/tests/client/components/BackendPicker.test.ts +0 -239
  292. package/tests/client/components/DraftChip.test.ts +0 -53
  293. package/tests/client/components/MetadataForm.test.ts +0 -164
  294. package/tests/client/components/dialogs/DeleteDraftDialog.test.ts +0 -91
  295. package/tests/client/components/dialogs/FilenameDialog.test.ts +0 -209
  296. package/tests/client/components/dialogs/dialog-stubs.ts +0 -19
  297. package/tests/client/components/editor/EditorPane.test.ts +0 -100
  298. package/tests/client/components/editor/EditorTabs.test.ts +0 -253
  299. package/tests/client/components/editor/EditorToolbar.test.ts +0 -252
  300. package/tests/client/components/editor/fixtures.ts +0 -31
  301. package/tests/client/components/fields/ArrayField.test.ts +0 -197
  302. package/tests/client/components/fields/BooleanField.test.ts +0 -206
  303. package/tests/client/components/fields/DateField.test.ts +0 -210
  304. package/tests/client/components/fields/EnumField.test.ts +0 -246
  305. package/tests/client/components/fields/NumberField.test.ts +0 -240
  306. package/tests/client/components/fields/ObjectField.test.ts +0 -157
  307. package/tests/client/components/fields/SchemaField.test.ts +0 -190
  308. package/tests/client/components/fields/StringField.test.ts +0 -223
  309. package/tests/client/components/sidebar/AdminSidebar.test.ts +0 -285
  310. package/tests/client/components/sidebar/AdminSidebarSort.test.ts +0 -135
  311. package/tests/client/components/sidebar/sort-mock.ts +0 -23
  312. package/tests/client/js/drafts/fixtures.ts +0 -22
  313. package/tests/client/js/drafts/merge.test.ts +0 -282
  314. package/tests/client/js/drafts/ops.test.ts +0 -658
  315. package/tests/client/js/drafts/storage.test.ts +0 -200
  316. package/tests/client/js/drafts/workers/diff.test.ts +0 -165
  317. package/tests/client/js/editor/editor.test.ts +0 -616
  318. package/tests/client/js/editor/link-wrap.test.ts +0 -225
  319. package/tests/client/js/editor/markdown-shortcuts.test.ts +0 -370
  320. package/tests/client/js/handlers/admin.test.ts +0 -467
  321. package/tests/client/js/state/router.test.ts +0 -619
  322. package/tests/client/js/state/schema.test.ts +0 -266
  323. package/tests/client/js/state/state.test.ts +0 -328
  324. package/tests/client/js/storage/adapter.test.ts +0 -115
  325. package/tests/client/js/storage/client.test.ts +0 -250
  326. package/tests/client/js/storage/db.test.ts +0 -59
  327. package/tests/client/js/storage/fsa.test.ts +0 -284
  328. package/tests/client/js/storage/github.test.ts +0 -349
  329. package/tests/client/js/storage/mock-port.ts +0 -95
  330. package/tests/client/js/storage/storage.test.ts +0 -77
  331. package/tests/client/js/storage/workers/frontmatter.test.ts +0 -479
  332. package/tests/client/js/storage/workers/storage.test.ts +0 -299
  333. package/tests/client/js/storage/workers/toml-parser.test.ts +0 -169
  334. package/tests/client/js/storage/workers/yaml-parser.test.ts +0 -168
  335. package/tests/client/js/utils/file-types.test.ts +0 -268
  336. package/tests/client/js/utils/frontmatter.test.ts +0 -87
  337. package/tests/client/js/utils/schema-utils.test.ts +0 -318
  338. package/tests/client/js/utils/slug.test.ts +0 -58
  339. package/tests/client/js/utils/sort.test.ts +0 -276
  340. package/tests/client/js/utils/stable-stringify.test.ts +0 -68
  341. package/tests/client/js/utils/url-utils.test.ts +0 -70
  342. package/tests/e2e/backend-connection.test.ts +0 -301
  343. package/tests/e2e/draft-lifecycle.test.ts +0 -388
  344. package/tests/e2e/editing.test.ts +0 -355
  345. package/tests/e2e/github-adapter.test.ts +0 -330
  346. package/tests/e2e/helpers/mock-adapter.ts +0 -166
  347. package/tests/e2e/helpers/test-app.ts +0 -155
  348. package/tests/e2e/navigation.test.ts +0 -358
  349. package/tests/e2e/publishing.test.ts +0 -345
  350. package/tests/e2e/unsaved-changes.test.ts +0 -317
  351. package/tests/setup.ts +0 -2
  352. package/tests/stubs/codemirror.ts +0 -197
  353. package/tsconfig.json +0 -19
  354. package/vitest.config.ts +0 -178
  355. /package/{src → dist}/client/Admin.svelte +0 -0
  356. /package/{src → dist}/client/components/BackendPicker.svelte +0 -0
  357. /package/{src → dist}/client/components/DraftChip.svelte +0 -0
  358. /package/{src → dist}/client/components/MetadataForm.svelte +0 -0
  359. /package/{src → dist}/client/components/ThemeToggle.svelte +0 -0
  360. /package/{src → dist}/client/components/dialogs/DeleteDraftDialog.svelte +0 -0
  361. /package/{src → dist}/client/components/dialogs/FilenameDialog.svelte +0 -0
  362. /package/{src → dist}/client/components/editor/EditorPane.svelte +0 -0
  363. /package/{src → dist}/client/components/editor/EditorTabs.svelte +0 -0
  364. /package/{src → dist}/client/components/editor/EditorToolbar.svelte +0 -0
  365. /package/{src → dist}/client/components/editor/FormatSelector.svelte +0 -0
  366. /package/{src → dist}/client/components/editor/Toolbar.svelte +0 -0
  367. /package/{src → dist}/client/components/fields/ArrayField.svelte +0 -0
  368. /package/{src → dist}/client/components/fields/ArrayItem.svelte +0 -0
  369. /package/{src → dist}/client/components/fields/BooleanField.svelte +0 -0
  370. /package/{src → dist}/client/components/fields/DateField.svelte +0 -0
  371. /package/{src → dist}/client/components/fields/EnumField.svelte +0 -0
  372. /package/{src → dist}/client/components/fields/FieldWrapper.svelte +0 -0
  373. /package/{src → dist}/client/components/fields/NumberField.svelte +0 -0
  374. /package/{src → dist}/client/components/fields/ObjectField.svelte +0 -0
  375. /package/{src → dist}/client/components/fields/SchemaField.svelte +0 -0
  376. /package/{src → dist}/client/components/fields/StringField.svelte +0 -0
  377. /package/{src → dist}/client/components/sidebar/AdminSidebar.svelte +0 -0
  378. /package/{src → dist}/client/components/sidebar/AdminSidebarSort.svelte +0 -0
  379. /package/{src → dist}/client/css/a11y.css +0 -0
  380. /package/{src → dist}/client/css/btn.css +0 -0
  381. /package/{src → dist}/client/css/dialog.css +0 -0
  382. /package/{src → dist}/client/css/field-input.css +0 -0
  383. /package/{src → dist}/client/css/reset.css +0 -0
  384. /package/{src → dist}/client/css/theme.css +0 -0
  385. /package/{src/client/index.ts → dist/client/index.js} +0 -0
  386. /package/{src → dist}/virtual.d.ts +0 -0
@@ -0,0 +1,291 @@
1
+ /*
2
+ * Global application state for the admin SPA.
3
+ * Manages backend connection, schema loading, collections, and navigation state.
4
+ */
5
+ import schemas from 'virtual:nebula/collections';
6
+ import { loadBackend, saveBackend, clearBackend, } from '../storage/storage';
7
+ import { StorageClient } from '../storage/client';
8
+ import { nav, navigate, adminPath } from './router.svelte';
9
+ import { drafts, mergeDrafts, refreshDrafts, resetDraftMerge, } from '../drafts/merge.svelte';
10
+ import { getSchemaExtensions } from './schema.svelte';
11
+ export { drafts, refreshDrafts };
12
+ // Sorted collection names derived from virtual:nebula/collections.
13
+ export const collections = Object.keys(schemas).sort();
14
+ /*
15
+ * Uses .js extension because svelte-package does not rewrite URL string literals;
16
+ * the dist output must reference the compiled .js file, not the source .ts file.
17
+ */
18
+ const sharedWorker = new SharedWorker(new URL('../storage/workers/storage.js', import.meta.url), { type: 'module', name: 'cms-storage' });
19
+ // Main-thread StorageClient for editor and draft-merge I/O.
20
+ export const storageClient = new StorageClient(sharedWorker.port);
21
+ let backendType = $state(null);
22
+ let backendReady = $state(false);
23
+ let permissionState = $state('denied');
24
+ let contentList = $state([]);
25
+ let error = $state(null);
26
+ let loading = $state(false);
27
+ export const backend = {
28
+ // Active backend type, or null if not connected.
29
+ get type() {
30
+ return backendType;
31
+ },
32
+ // True if a backend is initialized and ready.
33
+ get ready() {
34
+ return backendReady;
35
+ },
36
+ // FSA permission state for the re-auth flow in BackendPicker.
37
+ get permission() {
38
+ return permissionState;
39
+ },
40
+ };
41
+ export const content = {
42
+ // Parsed content items for the selected collection.
43
+ get list() {
44
+ return contentList;
45
+ },
46
+ // True if the frontmatter worker is actively parsing.
47
+ get loading() {
48
+ return loading;
49
+ },
50
+ // Error message for display in the sidebar.
51
+ get error() {
52
+ return error;
53
+ },
54
+ };
55
+ let worker = null;
56
+ let loadedCollection = '';
57
+ let initPromise = null;
58
+ const contentCache = new Map();
59
+ /**
60
+ * Initializes the frontmatter worker and bridges a port to the SharedWorker.
61
+ * @return {Worker}
62
+ */
63
+ function ensureWorker() {
64
+ if (worker)
65
+ return worker;
66
+ // Uses .js extension because svelte-package does not rewrite URL string literals
67
+ worker = new Worker(new URL('../storage/workers/frontmatter.js', import.meta.url), { type: 'module' });
68
+ worker.addEventListener('message', (event) => {
69
+ const data = event.data;
70
+ if (data.type === 'result') {
71
+ const forCollection = data.collection;
72
+ // Always cache under the correct collection
73
+ contentCache.set(forCollection, data.items);
74
+ // Only update the visible list if this result is for the current collection
75
+ if (forCollection === loadedCollection) {
76
+ contentList = data.items;
77
+ loading = false;
78
+ error = null;
79
+ if (backendReady)
80
+ mergeDrafts(forCollection);
81
+ }
82
+ }
83
+ else if (data.type === 'error') {
84
+ error = data.message;
85
+ loading = false;
86
+ contentList = [];
87
+ }
88
+ });
89
+ // Bridge a port so the frontmatter worker can talk to the storage SharedWorker
90
+ const channel = new MessageChannel();
91
+ worker.postMessage({ type: 'port' }, [channel.port1]);
92
+ sharedWorker.port.postMessage({ type: 'connect-port' }, [channel.port2]);
93
+ return worker;
94
+ }
95
+ /**
96
+ * Sends a parse request to the frontmatter worker. Refresh mode keeps current sidebar visible.
97
+ * @param {string} collection - The collection name to parse
98
+ * @param {boolean} refresh - If true, keep current contentList and skip loading state
99
+ * @return {Promise<void>}
100
+ */
101
+ async function dispatchWorker(collection, refresh = false) {
102
+ if (!backendReady)
103
+ return;
104
+ if (!refresh) {
105
+ loading = true;
106
+ contentList = [];
107
+ }
108
+ error = null;
109
+ // Wait for the SharedWorker adapter to be ready before dispatching
110
+ if (initPromise)
111
+ await initPromise;
112
+ const w = ensureWorker();
113
+ const extensions = getSchemaExtensions(collection);
114
+ w.postMessage({ type: 'parse', collection, extensions });
115
+ }
116
+ /**
117
+ * Restores a stored backend config from IndexedDB and initializes the SharedWorker.
118
+ * @return {Promise<void>}
119
+ */
120
+ export async function restoreBackend() {
121
+ try {
122
+ const config = await loadBackend();
123
+ if (!config) {
124
+ backendType = null;
125
+ backendReady = false;
126
+ return;
127
+ }
128
+ if (config.type === 'fsa') {
129
+ // Check FSA permission state
130
+ const perm = await config.handle.queryPermission({ mode: 'readwrite' });
131
+ permissionState = perm;
132
+ backendType = 'fsa';
133
+ if (perm === 'granted') {
134
+ await storageClient.init({ type: 'init', backend: config });
135
+ backendReady = true;
136
+ navigateToFirstCollectionIfHome();
137
+ }
138
+ // If perm is 'prompt', BackendPicker shows re-auth button
139
+ }
140
+ else {
141
+ // GitHub — show UI optimistically, validate in background
142
+ backendType = 'github';
143
+ backendReady = true;
144
+ navigateToFirstCollectionIfHome();
145
+ initPromise = storageClient
146
+ .init({ type: 'init', backend: config })
147
+ .catch(async () => {
148
+ await clearBackend();
149
+ backendType = null;
150
+ backendReady = false;
151
+ contentList = [];
152
+ contentCache.clear();
153
+ loadedCollection = '';
154
+ navigate(adminPath());
155
+ })
156
+ .finally(() => {
157
+ initPromise = null;
158
+ });
159
+ }
160
+ }
161
+ catch {
162
+ backendType = null;
163
+ backendReady = false;
164
+ }
165
+ }
166
+ /**
167
+ * Re-requests FSA permission. Must be called from a user gesture.
168
+ * @return {Promise<void>}
169
+ */
170
+ export async function requestPermission() {
171
+ const config = await loadBackend();
172
+ if (!config || config.type !== 'fsa')
173
+ return;
174
+ try {
175
+ const perm = await config.handle.requestPermission({ mode: 'readwrite' });
176
+ permissionState = perm;
177
+ if (perm === 'granted') {
178
+ await storageClient.init({ type: 'init', backend: config });
179
+ backendReady = true;
180
+ navigateToFirstCollectionIfHome();
181
+ }
182
+ }
183
+ catch {
184
+ permissionState = 'denied';
185
+ }
186
+ }
187
+ /**
188
+ * Opens the directory picker and initializes the FSA backend. Must be called from a user gesture.
189
+ * @return {Promise<void>}
190
+ */
191
+ export async function pickDirectory() {
192
+ try {
193
+ const handle = await window.showDirectoryPicker({ mode: 'readwrite' });
194
+ const config = { type: 'fsa', handle };
195
+ await storageClient.init({ type: 'init', backend: config });
196
+ await saveBackend(config);
197
+ backendType = 'fsa';
198
+ permissionState = 'granted';
199
+ backendReady = true;
200
+ navigateToFirstCollectionIfHome();
201
+ }
202
+ catch (err) {
203
+ if (err instanceof DOMException && err.name === 'AbortError')
204
+ return;
205
+ error = err instanceof Error ? err.message : String(err);
206
+ }
207
+ }
208
+ /**
209
+ * Connects to a GitHub repository via PAT and persists the config.
210
+ * @param {string} token - GitHub Personal Access Token
211
+ * @param {string} repo - Repository in "owner/repo" format
212
+ * @return {Promise<void>}
213
+ */
214
+ export async function connectGitHub(token, repo) {
215
+ const config = { type: 'github', token, repo };
216
+ await storageClient.init({ type: 'init', backend: config });
217
+ await saveBackend(config);
218
+ backendType = 'github';
219
+ backendReady = true;
220
+ navigateToFirstCollectionIfHome();
221
+ }
222
+ /**
223
+ * Disconnects the backend, clears credentials, and resets all state.
224
+ * @return {Promise<void>}
225
+ */
226
+ export async function disconnect() {
227
+ worker?.terminate();
228
+ worker = null;
229
+ resetDraftMerge();
230
+ await storageClient.teardown();
231
+ await clearBackend();
232
+ backendType = null;
233
+ backendReady = false;
234
+ permissionState = 'denied';
235
+ contentList = [];
236
+ contentCache.clear();
237
+ loadedCollection = '';
238
+ error = null;
239
+ loading = false;
240
+ navigate(adminPath());
241
+ }
242
+ /**
243
+ * Navigates to the first collection if currently on the home view.
244
+ * @return {void}
245
+ */
246
+ function navigateToFirstCollectionIfHome() {
247
+ if (nav.route.view === 'home' && collections.length > 0) {
248
+ navigate(adminPath(collections[0]));
249
+ }
250
+ }
251
+ /**
252
+ * Loads a collection. Serves from cache instantly if available, then background refreshes.
253
+ * @param {string} collection - The collection name to load
254
+ * @return {void}
255
+ */
256
+ export function loadCollection(collection) {
257
+ if (collection === loadedCollection)
258
+ return;
259
+ loadedCollection = collection;
260
+ const cached = contentCache.get(collection);
261
+ if (cached) {
262
+ // Serve cached items instantly, then refresh in background
263
+ contentList = cached;
264
+ refreshDrafts(collection);
265
+ dispatchWorker(collection, true);
266
+ }
267
+ else {
268
+ dispatchWorker(collection);
269
+ }
270
+ }
271
+ /**
272
+ * Forces a background reload, keeping the sidebar visible.
273
+ * @param {string} collection - The collection to reload
274
+ * @return {void}
275
+ */
276
+ export function reloadCollection(collection) {
277
+ loadedCollection = collection;
278
+ dispatchWorker(collection, true);
279
+ }
280
+ /**
281
+ * Optimistically updates a single item's frontmatter in the content list and cache.
282
+ * @param {string} filename - The filename to update
283
+ * @param {Record<string, unknown>} data - The new frontmatter data
284
+ * @return {void}
285
+ */
286
+ export function updateContentItem(filename, data) {
287
+ const updated = contentList.map((item) => item.filename === filename ? { ...item, data } : item);
288
+ contentList = updated;
289
+ if (loadedCollection)
290
+ contentCache.set(loadedCollection, updated);
291
+ }
@@ -0,0 +1,24 @@
1
+ type ResolvedTheme = 'light' | 'dark';
2
+ type ThemeIcon = 'light_mode' | 'dark_mode' | 'brightness_auto';
3
+ type ThemeLabel = 'Light' | 'Dark' | 'Auto';
4
+ export declare const theme: {
5
+ readonly resolved: ResolvedTheme;
6
+ readonly icon: ThemeIcon;
7
+ readonly label: ThemeLabel;
8
+ };
9
+ /**
10
+ * Starts listening to OS color scheme changes via matchMedia.
11
+ * Preference and initial system state are already read at module init,
12
+ * so this only needs to register the change listener. Call once on mount.
13
+ * Safe to call multiple times — registers the listener only once.
14
+ * @return {() => void} Cleanup function that removes the listener
15
+ */
16
+ export declare function initTheme(): () => void;
17
+ /**
18
+ * Cycles the preference through auto -> light -> dark -> auto.
19
+ * Persists the new value to localStorage.
20
+ * @return {void}
21
+ */
22
+ export declare function cycleTheme(): void;
23
+ export {};
24
+ //# sourceMappingURL=theme.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.svelte.d.ts","sourceRoot":"","sources":["../../../../src/client/js/state/theme.svelte.ts"],"names":[],"mappings":"AAUA,KAAK,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAGtC,KAAK,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,iBAAiB,CAAC;AAGhE,KAAK,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAmF5C,eAAO,MAAM,KAAK;uBACA,aAAa;mBAGjB,SAAS;oBAGR,UAAU;CAGxB,CAAC;AAWF;;;;;;GAMG;AACH,wBAAgB,SAAS,IAAI,MAAM,IAAI,CAmBtC;AAQD;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAajC"}
@@ -3,121 +3,88 @@
3
3
  * Manages a three-way preference (light / dark / auto) and resolves the effective
4
4
  * theme by combining user preference with the OS-level color scheme.
5
5
  */
6
-
7
- // Tri-state preference: 'light', 'dark', or 'auto' (follow system)
8
- type ThemePreference = 'light' | 'dark' | 'auto';
9
-
10
- // Resolved theme applied to the DOM — always 'light' or 'dark'
11
- type ResolvedTheme = 'light' | 'dark';
12
-
13
- // Material Symbols icon name for each preference
14
- type ThemeIcon = 'light_mode' | 'dark_mode' | 'brightness_auto';
15
-
16
- // Human-readable label for each preference
17
- type ThemeLabel = 'Light' | 'Dark' | 'Auto';
18
-
19
6
  // localStorage key for persisting the user's preference
20
7
  const STORAGE_KEY = 'nebula-theme';
21
-
22
8
  /*
23
9
  //////////////////////////////
24
10
  // Preference → UI mapping
25
11
  //////////////////////////////
26
12
  */
27
-
28
13
  /*
29
14
  * Single source of truth for all preference-derived UI values.
30
15
  * Adding a new preference requires a new entry here — TypeScript
31
16
  * enforces exhaustiveness via the Record<ThemePreference, ...> type.
32
17
  */
33
- const THEME_MAP: Record<
34
- ThemePreference,
35
- { icon: ThemeIcon; label: ThemeLabel }
36
- > = {
37
- light: { icon: 'light_mode', label: 'Light' },
38
- dark: { icon: 'dark_mode', label: 'Dark' },
39
- auto: { icon: 'brightness_auto', label: 'Auto' },
18
+ const THEME_MAP = {
19
+ light: { icon: 'light_mode', label: 'Light' },
20
+ dark: { icon: 'dark_mode', label: 'Dark' },
21
+ auto: { icon: 'brightness_auto', label: 'Auto' },
40
22
  };
41
-
42
23
  /*
43
24
  //////////////////////////////
44
25
  // Module initialization
45
26
  //////////////////////////////
46
27
  */
47
-
48
28
  /*
49
29
  * Read preference from localStorage at module init to avoid a flash of wrong theme.
50
30
  * Safe because this module is only loaded client-side (client:only="svelte").
51
31
  */
52
- let stored: string | null = null;
32
+ let stored = null;
53
33
  try {
54
- if (typeof localStorage !== 'undefined') {
55
- stored = localStorage.getItem(STORAGE_KEY);
56
- }
57
- } catch {
58
- // Storage access blocked (SecurityError, private browsing, etc.)
34
+ if (typeof localStorage !== 'undefined') {
35
+ stored = localStorage.getItem(STORAGE_KEY);
36
+ }
37
+ }
38
+ catch {
39
+ // Storage access blocked (SecurityError, private browsing, etc.)
59
40
  }
60
-
61
41
  /*
62
42
  * Read system preference at module init so the first render has the correct
63
43
  * resolved theme — deferring this to onMount would cause a flash for auto+dark users.
64
44
  */
65
- const mq =
66
- typeof window !== 'undefined'
45
+ const mq = typeof window !== 'undefined'
67
46
  ? window.matchMedia('(prefers-color-scheme: dark)')
68
47
  : null;
69
-
70
48
  // The user's explicit preference
71
- let preference = $state<ThemePreference>(
72
- stored === 'light' || stored === 'dark' || stored === 'auto'
49
+ let preference = $state(stored === 'light' || stored === 'dark' || stored === 'auto'
73
50
  ? stored
74
- : 'auto',
75
- );
76
-
51
+ : 'auto');
77
52
  // Whether the OS prefers dark mode — updated via matchMedia listener
78
53
  let systemPrefersDark = $state(mq?.matches ?? false);
79
-
80
54
  /*
81
55
  //////////////////////////////
82
56
  // Derived state
83
57
  //////////////////////////////
84
58
  */
85
-
86
59
  /*
87
60
  * $derived can only be a variable declaration initializer, not an object
88
61
  * property — Svelte compiler restriction. These private derivations feed
89
62
  * the exported theme object via getters.
90
63
  */
91
- const resolved: ResolvedTheme = $derived(
92
- preference === 'auto' ? (systemPrefersDark ? 'dark' : 'light') : preference,
93
- );
64
+ const resolved = $derived(preference === 'auto' ? (systemPrefersDark ? 'dark' : 'light') : preference);
94
65
  const ui = $derived(THEME_MAP[preference]);
95
-
96
66
  /*
97
67
  * Reactive theme state. Consumers read properties directly: theme.resolved,
98
68
  * theme.icon, theme.label. The getters forward Svelte's reactive tracking.
99
69
  */
100
70
  export const theme = {
101
- get resolved(): ResolvedTheme {
102
- return resolved;
103
- },
104
- get icon(): ThemeIcon {
105
- return ui.icon;
106
- },
107
- get label(): ThemeLabel {
108
- return ui.label;
109
- },
71
+ get resolved() {
72
+ return resolved;
73
+ },
74
+ get icon() {
75
+ return ui.icon;
76
+ },
77
+ get label() {
78
+ return ui.label;
79
+ },
110
80
  };
111
-
112
81
  /*
113
82
  //////////////////////////////
114
83
  // System preference tracking
115
84
  //////////////////////////////
116
85
  */
117
-
118
86
  // Guard against duplicate listener registration (e.g. HMR remount)
119
87
  let initialized = false;
120
-
121
88
  /**
122
89
  * Starts listening to OS color scheme changes via matchMedia.
123
90
  * Preference and initial system state are already read at module init,
@@ -125,49 +92,45 @@ let initialized = false;
125
92
  * Safe to call multiple times — registers the listener only once.
126
93
  * @return {() => void} Cleanup function that removes the listener
127
94
  */
128
- export function initTheme(): () => void {
129
- if (initialized) return () => {};
130
- initialized = true;
131
-
132
- /**
133
- * Updates the systemPrefersDark flag when the OS color scheme changes.
134
- * @param {MediaQueryListEvent} e - The change event from matchMedia
135
- * @return {void}
136
- */
137
- const handler = (e: MediaQueryListEvent): void => {
138
- systemPrefersDark = e.matches;
139
- };
140
-
141
- mq?.addEventListener('change', handler);
142
-
143
- return () => {
144
- mq?.removeEventListener('change', handler);
145
- initialized = false;
146
- };
95
+ export function initTheme() {
96
+ if (initialized)
97
+ return () => { };
98
+ initialized = true;
99
+ /**
100
+ * Updates the systemPrefersDark flag when the OS color scheme changes.
101
+ * @param {MediaQueryListEvent} e - The change event from matchMedia
102
+ * @return {void}
103
+ */
104
+ const handler = (e) => {
105
+ systemPrefersDark = e.matches;
106
+ };
107
+ mq?.addEventListener('change', handler);
108
+ return () => {
109
+ mq?.removeEventListener('change', handler);
110
+ initialized = false;
111
+ };
147
112
  }
148
-
149
113
  /*
150
114
  //////////////////////////////
151
115
  // Actions
152
116
  //////////////////////////////
153
117
  */
154
-
155
118
  /**
156
119
  * Cycles the preference through auto -> light -> dark -> auto.
157
120
  * Persists the new value to localStorage.
158
121
  * @return {void}
159
122
  */
160
- export function cycleTheme(): void {
161
- const next: ThemePreference =
162
- preference === 'auto' ? 'light' : preference === 'light' ? 'dark' : 'auto';
163
- preference = next;
164
- try {
165
- localStorage.setItem(STORAGE_KEY, next);
166
- } catch {
167
- /*
168
- * Persistence failed (quota exceeded, storage disabled, etc.).
169
- * The in-memory preference is already updated, so the current
170
- * session works correctly — it just won't survive a page reload.
171
- */
172
- }
123
+ export function cycleTheme() {
124
+ const next = preference === 'auto' ? 'light' : preference === 'light' ? 'dark' : 'auto';
125
+ preference = next;
126
+ try {
127
+ localStorage.setItem(STORAGE_KEY, next);
128
+ }
129
+ catch {
130
+ /*
131
+ * Persistence failed (quota exceeded, storage disabled, etc.).
132
+ * The in-memory preference is already updated, so the current
133
+ * session works correctly — it just won't survive a page reload.
134
+ */
135
+ }
173
136
  }
@@ -0,0 +1,130 @@
1
+ export type FileEntry = {
2
+ filename: string;
3
+ content: string;
4
+ };
5
+ export type FileWrite = {
6
+ collection: string;
7
+ filename: string;
8
+ content: string;
9
+ };
10
+ export interface StorageAdapter {
11
+ /**
12
+ * Lists files in a collection matching the given extensions, returning their names and content.
13
+ * @param {string} collection - The collection name
14
+ * @param {string[]} extensions - File extensions to include (e.g. ['.md', '.mdx', '.yaml'])
15
+ * @return {Promise<FileEntry[]>} Array of filename + content pairs
16
+ */
17
+ listFiles(collection: string, extensions: string[]): Promise<FileEntry[]>;
18
+ /**
19
+ * Deletes a single file from the collection. Used during file type conversion to remove the old file after the new one is written.
20
+ * @param {string} collection - The collection name
21
+ * @param {string} filename - The filename to delete
22
+ * @return {Promise<void>}
23
+ */
24
+ deleteFile(collection: string, filename: string): Promise<void>;
25
+ /**
26
+ * Reads a single file's content.
27
+ * @param {string} collection - The collection name
28
+ * @param {string} filename - The filename within the collection
29
+ * @return {Promise<string>} The file content as a string
30
+ */
31
+ readFile(collection: string, filename: string): Promise<string>;
32
+ /**
33
+ * Writes content to a single file, creating it if it doesn't exist.
34
+ * @param {string} collection - The collection name
35
+ * @param {string} filename - The filename within the collection
36
+ * @param {string} content - The content to write
37
+ * @return {Promise<void>}
38
+ */
39
+ writeFile(collection: string, filename: string, content: string): Promise<void>;
40
+ /**
41
+ * Writes multiple files atomically (single commit for GitHub, sequential for FSA).
42
+ * @param {FileWrite[]} files - Array of files to write
43
+ * @return {Promise<void>}
44
+ */
45
+ writeFiles(files: FileWrite[]): Promise<void>;
46
+ }
47
+ export type StorageRequest = {
48
+ type: 'init';
49
+ backend: {
50
+ type: 'fsa';
51
+ handle: FileSystemDirectoryHandle;
52
+ } | {
53
+ type: 'github';
54
+ token: string;
55
+ repo: string;
56
+ };
57
+ } | {
58
+ type: 'listFiles';
59
+ collection: string;
60
+ extensions: string[];
61
+ } | {
62
+ type: 'readFile';
63
+ collection: string;
64
+ filename: string;
65
+ } | {
66
+ type: 'writeFile';
67
+ collection: string;
68
+ filename: string;
69
+ content: string;
70
+ } | {
71
+ type: 'writeFiles';
72
+ files: FileWrite[];
73
+ } | {
74
+ type: 'deleteFile';
75
+ collection: string;
76
+ filename: string;
77
+ } | {
78
+ type: 'teardown';
79
+ };
80
+ export type StorageResponse = {
81
+ type: 'init';
82
+ ok: true;
83
+ } | {
84
+ type: 'init';
85
+ ok: false;
86
+ error: string;
87
+ } | {
88
+ type: 'listFiles';
89
+ ok: true;
90
+ files: FileEntry[];
91
+ } | {
92
+ type: 'listFiles';
93
+ ok: false;
94
+ error: string;
95
+ } | {
96
+ type: 'readFile';
97
+ ok: true;
98
+ content: string;
99
+ } | {
100
+ type: 'readFile';
101
+ ok: false;
102
+ error: string;
103
+ } | {
104
+ type: 'writeFile';
105
+ ok: true;
106
+ } | {
107
+ type: 'writeFile';
108
+ ok: false;
109
+ error: string;
110
+ } | {
111
+ type: 'writeFiles';
112
+ ok: true;
113
+ } | {
114
+ type: 'writeFiles';
115
+ ok: false;
116
+ error: string;
117
+ } | {
118
+ type: 'deleteFile';
119
+ ok: true;
120
+ } | {
121
+ type: 'deleteFile';
122
+ ok: false;
123
+ error: string;
124
+ } | {
125
+ type: 'teardown';
126
+ ok: true;
127
+ } | {
128
+ type: 'port-connected';
129
+ };
130
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/client/js/storage/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /*
2
+ * Storage adapter interface and shared types.
3
+ * Defines the contract that FSA and GitHub storage backends implement.
4
+ */
5
+ export {};