nebula-cms 0.1.3 → 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 (380) 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 +4 -1
  156. package/.github/workflows/ci.yml +0 -27
  157. package/.github/workflows/publish.yml +0 -34
  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/astro.config.mjs +0 -7
  163. package/playground/node_modules/.bin/astro +0 -21
  164. package/playground/node_modules/.vite/deps/@astrojs_svelte_client__js.js +0 -85
  165. package/playground/node_modules/.vite/deps/@astrojs_svelte_client__js.js.map +0 -7
  166. package/playground/node_modules/.vite/deps/_metadata.json +0 -184
  167. package/playground/node_modules/.vite/deps/astro___aria-query.js +0 -6776
  168. package/playground/node_modules/.vite/deps/astro___aria-query.js.map +0 -7
  169. package/playground/node_modules/.vite/deps/astro___axobject-query.js +0 -3754
  170. package/playground/node_modules/.vite/deps/astro___axobject-query.js.map +0 -7
  171. package/playground/node_modules/.vite/deps/astro___html-escaper.js +0 -34
  172. package/playground/node_modules/.vite/deps/astro___html-escaper.js.map +0 -7
  173. package/playground/node_modules/.vite/deps/chunk-AJXJMYAF.js +0 -0
  174. package/playground/node_modules/.vite/deps/chunk-AJXJMYAF.js.map +0 -7
  175. package/playground/node_modules/.vite/deps/chunk-BUSYA2B4.js +0 -8
  176. package/playground/node_modules/.vite/deps/chunk-BUSYA2B4.js.map +0 -7
  177. package/playground/node_modules/.vite/deps/chunk-CNYJBM5F.js +0 -21
  178. package/playground/node_modules/.vite/deps/chunk-CNYJBM5F.js.map +0 -7
  179. package/playground/node_modules/.vite/deps/chunk-DBPNBGEI.js +0 -223
  180. package/playground/node_modules/.vite/deps/chunk-DBPNBGEI.js.map +0 -7
  181. package/playground/node_modules/.vite/deps/chunk-FPEUJ7DG.js +0 -27
  182. package/playground/node_modules/.vite/deps/chunk-FPEUJ7DG.js.map +0 -7
  183. package/playground/node_modules/.vite/deps/chunk-MHDZ3SK7.js +0 -1005
  184. package/playground/node_modules/.vite/deps/chunk-MHDZ3SK7.js.map +0 -7
  185. package/playground/node_modules/.vite/deps/chunk-RBDTDTPY.js +0 -204
  186. package/playground/node_modules/.vite/deps/chunk-RBDTDTPY.js.map +0 -7
  187. package/playground/node_modules/.vite/deps/chunk-RJGEXL5C.js +0 -688
  188. package/playground/node_modules/.vite/deps/chunk-RJGEXL5C.js.map +0 -7
  189. package/playground/node_modules/.vite/deps/chunk-YL4MIWGJ.js +0 -5099
  190. package/playground/node_modules/.vite/deps/chunk-YL4MIWGJ.js.map +0 -7
  191. package/playground/node_modules/.vite/deps/chunk-ZOV3DWEJ.js +0 -4376
  192. package/playground/node_modules/.vite/deps/chunk-ZOV3DWEJ.js.map +0 -7
  193. package/playground/node_modules/.vite/deps/chunk-ZP4UNCSN.js +0 -23
  194. package/playground/node_modules/.vite/deps/chunk-ZP4UNCSN.js.map +0 -7
  195. package/playground/node_modules/.vite/deps/chunk-ZREFNRZZ.js +0 -148
  196. package/playground/node_modules/.vite/deps/chunk-ZREFNRZZ.js.map +0 -7
  197. package/playground/node_modules/.vite/deps/package.json +0 -3
  198. package/playground/node_modules/.vite/deps/smol-toml.js +0 -843
  199. package/playground/node_modules/.vite/deps/smol-toml.js.map +0 -7
  200. package/playground/node_modules/.vite/deps/svelte.js +0 -55
  201. package/playground/node_modules/.vite/deps/svelte.js.map +0 -7
  202. package/playground/node_modules/.vite/deps/svelte___clsx.js +0 -9
  203. package/playground/node_modules/.vite/deps/svelte___clsx.js.map +0 -7
  204. package/playground/node_modules/.vite/deps/svelte_animate.js +0 -57
  205. package/playground/node_modules/.vite/deps/svelte_animate.js.map +0 -7
  206. package/playground/node_modules/.vite/deps/svelte_attachments.js +0 -15
  207. package/playground/node_modules/.vite/deps/svelte_attachments.js.map +0 -7
  208. package/playground/node_modules/.vite/deps/svelte_easing.js +0 -67
  209. package/playground/node_modules/.vite/deps/svelte_easing.js.map +0 -7
  210. package/playground/node_modules/.vite/deps/svelte_events.js +0 -11
  211. package/playground/node_modules/.vite/deps/svelte_events.js.map +0 -7
  212. package/playground/node_modules/.vite/deps/svelte_internal.js +0 -5
  213. package/playground/node_modules/.vite/deps/svelte_internal.js.map +0 -7
  214. package/playground/node_modules/.vite/deps/svelte_internal_client.js +0 -402
  215. package/playground/node_modules/.vite/deps/svelte_internal_client.js.map +0 -7
  216. package/playground/node_modules/.vite/deps/svelte_internal_disclose-version.js +0 -10
  217. package/playground/node_modules/.vite/deps/svelte_internal_disclose-version.js.map +0 -7
  218. package/playground/node_modules/.vite/deps/svelte_internal_flags_async.js +0 -8
  219. package/playground/node_modules/.vite/deps/svelte_internal_flags_async.js.map +0 -7
  220. package/playground/node_modules/.vite/deps/svelte_internal_flags_legacy.js +0 -8
  221. package/playground/node_modules/.vite/deps/svelte_internal_flags_legacy.js.map +0 -7
  222. package/playground/node_modules/.vite/deps/svelte_internal_flags_tracing.js +0 -8
  223. package/playground/node_modules/.vite/deps/svelte_internal_flags_tracing.js.map +0 -7
  224. package/playground/node_modules/.vite/deps/svelte_legacy.js +0 -35
  225. package/playground/node_modules/.vite/deps/svelte_legacy.js.map +0 -7
  226. package/playground/node_modules/.vite/deps/svelte_motion.js +0 -545
  227. package/playground/node_modules/.vite/deps/svelte_motion.js.map +0 -7
  228. package/playground/node_modules/.vite/deps/svelte_reactivity.js +0 -29
  229. package/playground/node_modules/.vite/deps/svelte_reactivity.js.map +0 -7
  230. package/playground/node_modules/.vite/deps/svelte_reactivity_window.js +0 -127
  231. package/playground/node_modules/.vite/deps/svelte_reactivity_window.js.map +0 -7
  232. package/playground/node_modules/.vite/deps/svelte_store.js +0 -103
  233. package/playground/node_modules/.vite/deps/svelte_store.js.map +0 -7
  234. package/playground/node_modules/.vite/deps/svelte_transition.js +0 -208
  235. package/playground/node_modules/.vite/deps/svelte_transition.js.map +0 -7
  236. package/playground/package.json +0 -16
  237. package/playground/pnpm-lock.yaml +0 -3167
  238. package/playground/src/content/authors/jane-doe.json +0 -8
  239. package/playground/src/content/config/build.toml +0 -2
  240. package/playground/src/content/courses/web-fundamentals.json +0 -29
  241. package/playground/src/content/docs/advanced.mdx +0 -6
  242. package/playground/src/content/docs/intro.md +0 -6
  243. package/playground/src/content/guides/getting-started.mdx +0 -6
  244. package/playground/src/content/posts/hello-world.md +0 -7
  245. package/playground/src/content/products/t-shirt.json +0 -16
  246. package/playground/src/content/recipes/pancakes.mdoc +0 -8
  247. package/playground/src/content/settings/site.yml +0 -2
  248. package/playground/src/content.config.ts +0 -198
  249. package/playground/src/env.d.ts +0 -1
  250. package/playground/src/pages/index.astro +0 -11
  251. package/playground/src/pages/nebula.astro +0 -14
  252. package/pnpm-workspace.yaml +0 -2
  253. package/scripts/subset-icons.mjs +0 -178
  254. package/src/astro/index.ts +0 -295
  255. package/src/client/js/drafts/merge.svelte.ts +0 -121
  256. package/src/client/js/drafts/ops.svelte.ts +0 -227
  257. package/src/client/js/drafts/storage.ts +0 -108
  258. package/src/client/js/drafts/workers/diff.ts +0 -40
  259. package/src/client/js/editor/editor.svelte.ts +0 -343
  260. package/src/client/js/editor/languages.ts +0 -98
  261. package/src/client/js/editor/markdown-shortcuts.ts +0 -261
  262. package/src/client/js/handlers/admin.ts +0 -246
  263. package/src/client/js/state/dialogs.svelte.ts +0 -35
  264. package/src/client/js/state/router.svelte.ts +0 -156
  265. package/src/client/js/state/state.svelte.ts +0 -334
  266. package/src/client/js/storage/adapter.ts +0 -102
  267. package/src/client/js/storage/client.ts +0 -150
  268. package/src/client/js/storage/db.ts +0 -36
  269. package/src/client/js/storage/fsa.ts +0 -110
  270. package/src/client/js/storage/github.ts +0 -297
  271. package/src/client/js/storage/storage.ts +0 -83
  272. package/src/client/js/storage/workers/frontmatter.ts +0 -320
  273. package/src/client/js/storage/workers/storage.ts +0 -177
  274. package/src/client/js/storage/workers/toml-parser.ts +0 -106
  275. package/src/client/js/storage/workers/yaml-parser.ts +0 -132
  276. package/src/client/js/utils/frontmatter.ts +0 -38
  277. package/src/client/js/utils/schema-utils.ts +0 -295
  278. package/src/client/js/utils/sort.ts +0 -84
  279. package/src/client/js/utils/stable-stringify.ts +0 -27
  280. package/src/types.ts +0 -25
  281. package/svelte.config.js +0 -4
  282. package/tests/astro/build.test.ts +0 -63
  283. package/tests/astro/index.test.ts +0 -689
  284. package/tests/client/components/Admin.test.ts +0 -446
  285. package/tests/client/components/BackendPicker.test.ts +0 -239
  286. package/tests/client/components/DraftChip.test.ts +0 -53
  287. package/tests/client/components/MetadataForm.test.ts +0 -164
  288. package/tests/client/components/dialogs/DeleteDraftDialog.test.ts +0 -91
  289. package/tests/client/components/dialogs/FilenameDialog.test.ts +0 -209
  290. package/tests/client/components/dialogs/dialog-stubs.ts +0 -19
  291. package/tests/client/components/editor/EditorPane.test.ts +0 -100
  292. package/tests/client/components/editor/EditorTabs.test.ts +0 -253
  293. package/tests/client/components/editor/EditorToolbar.test.ts +0 -252
  294. package/tests/client/components/editor/fixtures.ts +0 -31
  295. package/tests/client/components/fields/ArrayField.test.ts +0 -197
  296. package/tests/client/components/fields/BooleanField.test.ts +0 -206
  297. package/tests/client/components/fields/DateField.test.ts +0 -210
  298. package/tests/client/components/fields/EnumField.test.ts +0 -246
  299. package/tests/client/components/fields/NumberField.test.ts +0 -240
  300. package/tests/client/components/fields/ObjectField.test.ts +0 -157
  301. package/tests/client/components/fields/SchemaField.test.ts +0 -190
  302. package/tests/client/components/fields/StringField.test.ts +0 -223
  303. package/tests/client/components/sidebar/AdminSidebar.test.ts +0 -285
  304. package/tests/client/components/sidebar/AdminSidebarSort.test.ts +0 -135
  305. package/tests/client/components/sidebar/sort-mock.ts +0 -23
  306. package/tests/client/js/drafts/fixtures.ts +0 -22
  307. package/tests/client/js/drafts/merge.test.ts +0 -282
  308. package/tests/client/js/drafts/ops.test.ts +0 -658
  309. package/tests/client/js/drafts/storage.test.ts +0 -200
  310. package/tests/client/js/drafts/workers/diff.test.ts +0 -165
  311. package/tests/client/js/editor/editor.test.ts +0 -616
  312. package/tests/client/js/editor/link-wrap.test.ts +0 -225
  313. package/tests/client/js/editor/markdown-shortcuts.test.ts +0 -370
  314. package/tests/client/js/handlers/admin.test.ts +0 -467
  315. package/tests/client/js/state/router.test.ts +0 -619
  316. package/tests/client/js/state/schema.test.ts +0 -266
  317. package/tests/client/js/state/state.test.ts +0 -328
  318. package/tests/client/js/storage/adapter.test.ts +0 -115
  319. package/tests/client/js/storage/client.test.ts +0 -250
  320. package/tests/client/js/storage/db.test.ts +0 -59
  321. package/tests/client/js/storage/fsa.test.ts +0 -284
  322. package/tests/client/js/storage/github.test.ts +0 -349
  323. package/tests/client/js/storage/mock-port.ts +0 -95
  324. package/tests/client/js/storage/storage.test.ts +0 -77
  325. package/tests/client/js/storage/workers/frontmatter.test.ts +0 -479
  326. package/tests/client/js/storage/workers/storage.test.ts +0 -299
  327. package/tests/client/js/storage/workers/toml-parser.test.ts +0 -169
  328. package/tests/client/js/storage/workers/yaml-parser.test.ts +0 -168
  329. package/tests/client/js/utils/file-types.test.ts +0 -268
  330. package/tests/client/js/utils/frontmatter.test.ts +0 -87
  331. package/tests/client/js/utils/schema-utils.test.ts +0 -318
  332. package/tests/client/js/utils/slug.test.ts +0 -58
  333. package/tests/client/js/utils/sort.test.ts +0 -276
  334. package/tests/client/js/utils/stable-stringify.test.ts +0 -68
  335. package/tests/client/js/utils/url-utils.test.ts +0 -70
  336. package/tests/e2e/backend-connection.test.ts +0 -301
  337. package/tests/e2e/draft-lifecycle.test.ts +0 -388
  338. package/tests/e2e/editing.test.ts +0 -355
  339. package/tests/e2e/github-adapter.test.ts +0 -330
  340. package/tests/e2e/helpers/mock-adapter.ts +0 -166
  341. package/tests/e2e/helpers/test-app.ts +0 -155
  342. package/tests/e2e/navigation.test.ts +0 -358
  343. package/tests/e2e/publishing.test.ts +0 -345
  344. package/tests/e2e/unsaved-changes.test.ts +0 -317
  345. package/tests/setup.ts +0 -2
  346. package/tests/stubs/codemirror.ts +0 -197
  347. package/tsconfig.json +0 -19
  348. package/vitest.config.ts +0 -178
  349. /package/{src → dist}/client/Admin.svelte +0 -0
  350. /package/{src → dist}/client/components/BackendPicker.svelte +0 -0
  351. /package/{src → dist}/client/components/DraftChip.svelte +0 -0
  352. /package/{src → dist}/client/components/MetadataForm.svelte +0 -0
  353. /package/{src → dist}/client/components/ThemeToggle.svelte +0 -0
  354. /package/{src → dist}/client/components/dialogs/DeleteDraftDialog.svelte +0 -0
  355. /package/{src → dist}/client/components/dialogs/FilenameDialog.svelte +0 -0
  356. /package/{src → dist}/client/components/editor/EditorPane.svelte +0 -0
  357. /package/{src → dist}/client/components/editor/EditorTabs.svelte +0 -0
  358. /package/{src → dist}/client/components/editor/EditorToolbar.svelte +0 -0
  359. /package/{src → dist}/client/components/editor/FormatSelector.svelte +0 -0
  360. /package/{src → dist}/client/components/editor/Toolbar.svelte +0 -0
  361. /package/{src → dist}/client/components/fields/ArrayField.svelte +0 -0
  362. /package/{src → dist}/client/components/fields/ArrayItem.svelte +0 -0
  363. /package/{src → dist}/client/components/fields/BooleanField.svelte +0 -0
  364. /package/{src → dist}/client/components/fields/DateField.svelte +0 -0
  365. /package/{src → dist}/client/components/fields/EnumField.svelte +0 -0
  366. /package/{src → dist}/client/components/fields/FieldWrapper.svelte +0 -0
  367. /package/{src → dist}/client/components/fields/NumberField.svelte +0 -0
  368. /package/{src → dist}/client/components/fields/ObjectField.svelte +0 -0
  369. /package/{src → dist}/client/components/fields/SchemaField.svelte +0 -0
  370. /package/{src → dist}/client/components/fields/StringField.svelte +0 -0
  371. /package/{src → dist}/client/components/sidebar/AdminSidebar.svelte +0 -0
  372. /package/{src → dist}/client/components/sidebar/AdminSidebarSort.svelte +0 -0
  373. /package/{src → dist}/client/css/a11y.css +0 -0
  374. /package/{src → dist}/client/css/btn.css +0 -0
  375. /package/{src → dist}/client/css/dialog.css +0 -0
  376. /package/{src → dist}/client/css/field-input.css +0 -0
  377. /package/{src → dist}/client/css/reset.css +0 -0
  378. /package/{src → dist}/client/css/theme.css +0 -0
  379. /package/{src/client/index.ts → dist/client/index.js} +0 -0
  380. /package/{src → dist}/virtual.d.ts +0 -0
@@ -1,689 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import {
3
- mkdtempSync,
4
- mkdirSync,
5
- writeFileSync,
6
- rmSync,
7
- existsSync,
8
- readFileSync,
9
- } from 'node:fs';
10
- import { resolve, join } from 'node:path';
11
- import { tmpdir } from 'node:os';
12
- import { pathToFileURL } from 'node:url';
13
- import NebulaCMS, { nebulaVitePlugin } from '../../src/astro/index.js';
14
- import type { AstroIntegrationLogger } from 'astro';
15
-
16
- /*
17
- //////////////////////////////
18
- // Test Helpers
19
- //////////////////////////////
20
- */
21
-
22
- /**
23
- * Creates a minimal mock satisfying the AstroIntegrationLogger interface
24
- * @return {AstroIntegrationLogger} Mock logger with a spied warn method
25
- */
26
- function createMockLogger() {
27
- return { warn: vi.fn() } as unknown as AstroIntegrationLogger;
28
- }
29
-
30
- /*
31
- //////////////////////////////
32
- // NebulaCMS integration object
33
- //////////////////////////////
34
- */
35
-
36
- describe('NebulaCMS integration object', () => {
37
- it('returns an integration with name "nebula-cms"', () => {
38
- const integration = NebulaCMS();
39
- expect(integration.name).toBe('nebula-cms');
40
- });
41
-
42
- it('registers a Vite plugin via astro:config:setup', () => {
43
- const integration = NebulaCMS();
44
- const updateConfig = vi.fn();
45
- const logger = createMockLogger();
46
-
47
- const hook = integration.hooks['astro:config:setup'] as Function;
48
- hook({ updateConfig, logger });
49
-
50
- expect(updateConfig).toHaveBeenCalledWith({
51
- vite: {
52
- plugins: [expect.objectContaining({ name: 'vite-plugin-nebula-cms' })],
53
- worker: { format: 'es' },
54
- optimizeDeps: { include: ['smol-toml'] },
55
- },
56
- });
57
- });
58
-
59
- it('accepts a valid absolute basePath', () => {
60
- const integration = NebulaCMS({ basePath: '/dashboard' });
61
- expect(integration.name).toBe('nebula-cms');
62
- });
63
-
64
- it('normalizes basePath without leading slash', () => {
65
- // Should not throw — 'admin' is normalized to '/admin'
66
- const integration = NebulaCMS({ basePath: 'admin' });
67
- expect(integration.name).toBe('nebula-cms');
68
- });
69
-
70
- it('normalizes basePath with trailing slash', () => {
71
- // Should not throw — '/admin/' is normalized to '/admin'
72
- const integration = NebulaCMS({ basePath: '/admin/' });
73
- expect(integration.name).toBe('nebula-cms');
74
- });
75
-
76
- it('throws on basePath with invalid characters', () => {
77
- expect(() => NebulaCMS({ basePath: '/admin/<script>' })).toThrow(
78
- 'Invalid basePath',
79
- );
80
- });
81
-
82
- it('accepts a valid absolute collectionsPath', () => {
83
- const integration = NebulaCMS({ collectionsPath: '/schemas' });
84
- expect(integration.name).toBe('nebula-cms');
85
- });
86
-
87
- it('normalizes collectionsPath without leading slash', () => {
88
- const integration = NebulaCMS({ collectionsPath: 'schemas' });
89
- expect(integration.name).toBe('nebula-cms');
90
- });
91
-
92
- it('normalizes collectionsPath with trailing slash', () => {
93
- const integration = NebulaCMS({ collectionsPath: '/schemas/' });
94
- expect(integration.name).toBe('nebula-cms');
95
- });
96
-
97
- it('throws on collectionsPath with invalid characters', () => {
98
- expect(() => NebulaCMS({ collectionsPath: '/my schemas' })).toThrow(
99
- 'Invalid collectionsPath',
100
- );
101
- });
102
-
103
- it('throws on empty collectionsPath', () => {
104
- expect(() => NebulaCMS({ collectionsPath: '' })).toThrow(
105
- 'Invalid collectionsPath',
106
- );
107
- });
108
-
109
- it('accepts root basePath /', () => {
110
- const integration = NebulaCMS({ basePath: '/' });
111
- expect(integration.name).toBe('nebula-cms');
112
- });
113
-
114
- it('collapses consecutive slashes in basePath', () => {
115
- // '/admin//' is normalized to '/admin' via URL API
116
- const integration = NebulaCMS({ basePath: '/admin//' });
117
- expect(integration.name).toBe('nebula-cms');
118
- });
119
-
120
- it('throws on empty basePath', () => {
121
- expect(() => NebulaCMS({ basePath: '' })).toThrow('Invalid basePath ""');
122
- });
123
-
124
- it('throws on collectionsPath set to /', () => {
125
- expect(() => NebulaCMS({ collectionsPath: '/' })).toThrow(
126
- 'Collections require a path prefix',
127
- );
128
- });
129
-
130
- it('throws on protocol-relative basePath', () => {
131
- expect(() => NebulaCMS({ basePath: '//admin' })).toThrow(
132
- 'must not start with "//"',
133
- );
134
- });
135
- });
136
-
137
- /*
138
- //////////////////////////////
139
- // resolveId hook
140
- //////////////////////////////
141
- */
142
-
143
- describe('nebulaVitePlugin resolveId', () => {
144
- it('resolves virtual:nebula/collections to the internal ID', () => {
145
- const plugin = nebulaVitePlugin(createMockLogger(), '/fake', {
146
- basePath: '/admin',
147
- collectionsPath: '/collections',
148
- });
149
- expect(plugin.resolveId('virtual:nebula/collections')).toBe(
150
- '\0virtual:nebula/collections',
151
- );
152
- });
153
-
154
- it('resolves virtual:nebula/config to the internal ID', () => {
155
- const plugin = nebulaVitePlugin(createMockLogger(), '/fake', {
156
- basePath: '/admin',
157
- collectionsPath: '/collections',
158
- });
159
- expect(plugin.resolveId('virtual:nebula/config')).toBe(
160
- '\0virtual:nebula/config',
161
- );
162
- });
163
-
164
- it('returns undefined for unrelated module IDs', () => {
165
- const plugin = nebulaVitePlugin(createMockLogger(), '/fake', {
166
- basePath: '/admin',
167
- collectionsPath: '/collections',
168
- });
169
- expect(plugin.resolveId('some-other-module')).toBeUndefined();
170
- });
171
-
172
- it('does not resolve old virtual:collections ID', () => {
173
- const plugin = nebulaVitePlugin(createMockLogger(), '/fake', {
174
- basePath: '/admin',
175
- collectionsPath: '/collections',
176
- });
177
- expect(plugin.resolveId('virtual:collections')).toBeUndefined();
178
- });
179
- });
180
-
181
- /*
182
- //////////////////////////////
183
- // configureServer middleware
184
- //////////////////////////////
185
- */
186
-
187
- describe('nebulaVitePlugin configureServer', () => {
188
- let tmpDir: string;
189
- let logger: AstroIntegrationLogger;
190
-
191
- beforeEach(() => {
192
- tmpDir = mkdtempSync(join(tmpdir(), 'nebula-test-'));
193
- logger = createMockLogger();
194
- });
195
-
196
- afterEach(() => {
197
- rmSync(tmpDir, { recursive: true, force: true });
198
- });
199
-
200
- /**
201
- * Creates a fake Connect-style middleware stack to capture registered handlers.
202
- * @return {{ use: ReturnType<typeof vi.fn>, handlers: Function[] }}
203
- */
204
- function createMiddlewareStub() {
205
- const handlers: Function[] = [];
206
- return {
207
- use: vi.fn((fn: Function) => {
208
- handlers.push(fn);
209
- }),
210
- get handlers() {
211
- return handlers;
212
- },
213
- };
214
- }
215
-
216
- /**
217
- * Simulates a middleware request/response cycle for the schema middleware.
218
- * @param {Function} handler - The middleware handler
219
- * @param {string} url - The request URL
220
- * @return {{ status: 'served' | 'skipped', body?: string, contentType?: string }}
221
- */
222
- function callSchemaMiddleware(handler: Function, url: string) {
223
- let result: { status: string; body?: string; contentType?: string } = {
224
- status: 'skipped',
225
- };
226
- const req = { url };
227
- const headers: Record<string, string> = {};
228
- const res = {
229
- setHeader: (k: string, v: string) => {
230
- headers[k] = v;
231
- },
232
- end: (body: string) => {
233
- result = {
234
- status: 'served',
235
- body,
236
- contentType: headers['Content-Type'],
237
- };
238
- },
239
- };
240
- const next = () => {
241
- result = { status: 'skipped' };
242
- };
243
- handler(req, res, next);
244
- return result;
245
- }
246
-
247
- /**
248
- * Simulates a middleware request/response cycle for the SPA rewrite middleware.
249
- * @param {Function} handler - The middleware handler
250
- * @param {string} url - The request URL
251
- * @param {string} accept - The Accept header value
252
- * @return {{ rewritten: boolean, url: string, nextCalled: boolean }}
253
- */
254
- function callRewriteMiddleware(
255
- handler: Function,
256
- url: string,
257
- accept: string,
258
- ) {
259
- const req = { url, headers: { accept } };
260
- let nextCalled = false;
261
- const next = () => {
262
- nextCalled = true;
263
- };
264
- handler(req, {}, next);
265
- return { rewritten: req.url !== url, url: req.url, nextCalled };
266
- }
267
-
268
- it('serves schema files from .astro/collections', () => {
269
- const dir = resolve(tmpDir, '.astro/collections');
270
- mkdirSync(dir, { recursive: true });
271
- writeFileSync(resolve(dir, 'posts.schema.json'), '{"type":"object"}');
272
-
273
- const plugin = nebulaVitePlugin(logger, tmpDir, {
274
- basePath: '/admin',
275
- collectionsPath: '/collections',
276
- });
277
- const mw = createMiddlewareStub();
278
- plugin.configureServer({ middlewares: mw });
279
-
280
- // First handler is the schema middleware
281
- const result = callSchemaMiddleware(
282
- mw.handlers[0],
283
- '/collections/posts.schema.json',
284
- );
285
- expect(result.status).toBe('served');
286
- expect(result.body).toBe('{"type":"object"}');
287
- expect(result.contentType).toBe('application/json');
288
- });
289
-
290
- it('calls next() for non-schema requests', () => {
291
- const plugin = nebulaVitePlugin(logger, tmpDir, {
292
- basePath: '/admin',
293
- collectionsPath: '/collections',
294
- });
295
- const mw = createMiddlewareStub();
296
- plugin.configureServer({ middlewares: mw });
297
-
298
- const result = callSchemaMiddleware(mw.handlers[0], '/some/other/path');
299
- expect(result.status).toBe('skipped');
300
- });
301
-
302
- it('calls next() when schema file does not exist', () => {
303
- const plugin = nebulaVitePlugin(logger, tmpDir, {
304
- basePath: '/admin',
305
- collectionsPath: '/collections',
306
- });
307
- const mw = createMiddlewareStub();
308
- plugin.configureServer({ middlewares: mw });
309
-
310
- const result = callSchemaMiddleware(
311
- mw.handlers[0],
312
- '/collections/missing.schema.json',
313
- );
314
- expect(result.status).toBe('skipped');
315
- });
316
-
317
- it('uses custom collectionsPath prefix', () => {
318
- const dir = resolve(tmpDir, '.astro/collections');
319
- mkdirSync(dir, { recursive: true });
320
- writeFileSync(resolve(dir, 'posts.schema.json'), '{}');
321
-
322
- const plugin = nebulaVitePlugin(logger, tmpDir, {
323
- basePath: '/admin',
324
- collectionsPath: '/schemas',
325
- });
326
- const mw = createMiddlewareStub();
327
- plugin.configureServer({ middlewares: mw });
328
-
329
- const miss = callSchemaMiddleware(
330
- mw.handlers[0],
331
- '/collections/posts.schema.json',
332
- );
333
- expect(miss.status).toBe('skipped');
334
-
335
- const hit = callSchemaMiddleware(
336
- mw.handlers[0],
337
- '/schemas/posts.schema.json',
338
- );
339
- expect(hit.status).toBe('served');
340
- });
341
-
342
- it('rewrites HTML requests under basePath to basePath', () => {
343
- const plugin = nebulaVitePlugin(logger, tmpDir, {
344
- basePath: '/admin',
345
- collectionsPath: '/collections',
346
- });
347
- const mw = createMiddlewareStub();
348
- plugin.configureServer({ middlewares: mw });
349
-
350
- // Second handler is the SPA rewrite middleware
351
- const result = callRewriteMiddleware(
352
- mw.handlers[1],
353
- '/admin/posts/my-article',
354
- 'text/html',
355
- );
356
- expect(result.rewritten).toBe(true);
357
- expect(result.url).toBe('/admin');
358
- });
359
-
360
- it('does not rewrite exact basePath requests', () => {
361
- const plugin = nebulaVitePlugin(logger, tmpDir, {
362
- basePath: '/admin',
363
- collectionsPath: '/collections',
364
- });
365
- const mw = createMiddlewareStub();
366
- plugin.configureServer({ middlewares: mw });
367
-
368
- const result = callRewriteMiddleware(mw.handlers[1], '/admin', 'text/html');
369
- expect(result.rewritten).toBe(false);
370
- });
371
-
372
- it('does not rewrite non-HTML requests under basePath', () => {
373
- const plugin = nebulaVitePlugin(logger, tmpDir, {
374
- basePath: '/admin',
375
- collectionsPath: '/collections',
376
- });
377
- const mw = createMiddlewareStub();
378
- plugin.configureServer({ middlewares: mw });
379
-
380
- const result = callRewriteMiddleware(
381
- mw.handlers[1],
382
- '/admin/posts/my-article',
383
- 'application/json',
384
- );
385
- expect(result.rewritten).toBe(false);
386
- });
387
-
388
- it('respects segment boundary — /administrator does not rewrite', () => {
389
- const plugin = nebulaVitePlugin(logger, tmpDir, {
390
- basePath: '/admin',
391
- collectionsPath: '/collections',
392
- });
393
- const mw = createMiddlewareStub();
394
- plugin.configureServer({ middlewares: mw });
395
-
396
- const result = callRewriteMiddleware(
397
- mw.handlers[1],
398
- '/administrator',
399
- 'text/html',
400
- );
401
- expect(result.rewritten).toBe(false);
402
- });
403
-
404
- it('rewrites with custom basePath', () => {
405
- const plugin = nebulaVitePlugin(logger, tmpDir, {
406
- basePath: '/nebula',
407
- collectionsPath: '/collections',
408
- });
409
- const mw = createMiddlewareStub();
410
- plugin.configureServer({ middlewares: mw });
411
-
412
- const result = callRewriteMiddleware(
413
- mw.handlers[1],
414
- '/nebula/posts/draft-12345678',
415
- 'text/html',
416
- );
417
- expect(result.rewritten).toBe(true);
418
- expect(result.url).toBe('/nebula');
419
- });
420
-
421
- it('rewrites sub-routes when basePath is /', () => {
422
- const plugin = nebulaVitePlugin(logger, tmpDir, {
423
- basePath: '/',
424
- collectionsPath: '/collections',
425
- });
426
- const mw = createMiddlewareStub();
427
- plugin.configureServer({ middlewares: mw });
428
-
429
- const result = callRewriteMiddleware(
430
- mw.handlers[1],
431
- '/posts/my-article',
432
- 'text/html',
433
- );
434
- expect(result.rewritten).toBe(true);
435
- expect(result.url).toBe('/');
436
- });
437
-
438
- it('does not rewrite root path when basePath is /', () => {
439
- const plugin = nebulaVitePlugin(logger, tmpDir, {
440
- basePath: '/',
441
- collectionsPath: '/collections',
442
- });
443
- const mw = createMiddlewareStub();
444
- plugin.configureServer({ middlewares: mw });
445
-
446
- const result = callRewriteMiddleware(mw.handlers[1], '/', 'text/html');
447
- expect(result.rewritten).toBe(false);
448
- });
449
-
450
- it('rewrites HTML requests with query strings', () => {
451
- const plugin = nebulaVitePlugin(logger, tmpDir, {
452
- basePath: '/admin',
453
- collectionsPath: '/collections',
454
- });
455
- const mw = createMiddlewareStub();
456
- plugin.configureServer({ middlewares: mw });
457
-
458
- const result = callRewriteMiddleware(
459
- mw.handlers[1],
460
- '/admin/posts?draft=true',
461
- 'text/html',
462
- );
463
- expect(result.rewritten).toBe(true);
464
- // Query string preserved during rewrite
465
- expect(result.url).toBe('/admin?draft=true');
466
- });
467
-
468
- it('rejects path traversal in schema requests', () => {
469
- const dir = resolve(tmpDir, '.astro/collections');
470
- mkdirSync(dir, { recursive: true });
471
- writeFileSync(resolve(dir, 'posts.schema.json'), '{}');
472
-
473
- const plugin = nebulaVitePlugin(logger, tmpDir, {
474
- basePath: '/admin',
475
- collectionsPath: '/collections',
476
- });
477
- const mw = createMiddlewareStub();
478
- plugin.configureServer({ middlewares: mw });
479
-
480
- const result = callSchemaMiddleware(
481
- mw.handlers[0],
482
- '/collections/../../../etc/passwd.schema.json',
483
- );
484
- expect(result.status).toBe('skipped');
485
- });
486
- });
487
-
488
- /*
489
- //////////////////////////////
490
- // astro:build:done hook
491
- //////////////////////////////
492
- */
493
-
494
- describe('NebulaCMS astro:build:done', () => {
495
- let tmpDir: string;
496
- let logger: AstroIntegrationLogger;
497
-
498
- beforeEach(() => {
499
- tmpDir = mkdtempSync(join(tmpdir(), 'nebula-test-'));
500
- logger = createMockLogger();
501
- vi.spyOn(process, 'cwd').mockReturnValue(tmpDir);
502
- });
503
-
504
- afterEach(() => {
505
- vi.restoreAllMocks();
506
- rmSync(tmpDir, { recursive: true, force: true });
507
- });
508
-
509
- it('copies schema files into the build output directory', () => {
510
- const source = resolve(tmpDir, '.astro/collections');
511
- mkdirSync(source, { recursive: true });
512
- writeFileSync(resolve(source, 'posts.schema.json'), '{"type":"object"}');
513
- writeFileSync(resolve(source, 'authors.schema.json'), '{"a":1}');
514
-
515
- const outDir = resolve(tmpDir, 'dist');
516
- mkdirSync(outDir, { recursive: true });
517
-
518
- const integration = NebulaCMS();
519
- const hook = integration.hooks['astro:build:done'] as Function;
520
- hook({ dir: pathToFileURL(outDir + '/'), logger });
521
-
522
- const target = resolve(outDir, 'collections');
523
- expect(existsSync(resolve(target, 'posts.schema.json'))).toBe(true);
524
- expect(existsSync(resolve(target, 'authors.schema.json'))).toBe(true);
525
- expect(readFileSync(resolve(target, 'posts.schema.json'), 'utf-8')).toBe(
526
- '{"type":"object"}',
527
- );
528
- });
529
-
530
- it('warns when .astro/collections does not exist', () => {
531
- const outDir = resolve(tmpDir, 'dist');
532
- mkdirSync(outDir, { recursive: true });
533
-
534
- const integration = NebulaCMS();
535
- const hook = integration.hooks['astro:build:done'] as Function;
536
- hook({ dir: pathToFileURL(outDir + '/'), logger });
537
-
538
- expect(logger.warn).toHaveBeenCalledWith(
539
- expect.stringContaining('.astro/collections'),
540
- );
541
- });
542
-
543
- it('uses custom collectionsPath for the output directory', () => {
544
- const source = resolve(tmpDir, '.astro/collections');
545
- mkdirSync(source, { recursive: true });
546
- writeFileSync(resolve(source, 'posts.schema.json'), '{}');
547
-
548
- const outDir = resolve(tmpDir, 'dist');
549
- mkdirSync(outDir, { recursive: true });
550
-
551
- const integration = NebulaCMS({ collectionsPath: '/schemas' });
552
- const hook = integration.hooks['astro:build:done'] as Function;
553
- hook({ dir: pathToFileURL(outDir + '/'), logger });
554
-
555
- expect(existsSync(resolve(outDir, 'schemas/posts.schema.json'))).toBe(true);
556
- expect(existsSync(resolve(outDir, 'collections'))).toBe(false);
557
- });
558
- });
559
-
560
- /*
561
- //////////////////////////////
562
- // load hook
563
- //////////////////////////////
564
- */
565
-
566
- describe('nebulaVitePlugin load', () => {
567
- let tmpDir: string;
568
- let logger: AstroIntegrationLogger;
569
-
570
- beforeEach(() => {
571
- tmpDir = mkdtempSync(join(tmpdir(), 'nebula-test-'));
572
- logger = createMockLogger();
573
- });
574
-
575
- afterEach(() => {
576
- rmSync(tmpDir, { recursive: true, force: true });
577
- });
578
-
579
- it('returns undefined for unrelated module IDs', () => {
580
- const plugin = nebulaVitePlugin(logger, tmpDir, {
581
- basePath: '/admin',
582
- collectionsPath: '/collections',
583
- });
584
- expect(plugin.load('some-other-id')).toBeUndefined();
585
- });
586
-
587
- it('generates config module with basePath and collectionsPath', () => {
588
- const plugin = nebulaVitePlugin(logger, tmpDir, {
589
- basePath: '/dashboard',
590
- collectionsPath: '/schemas',
591
- });
592
- const result = plugin.load('\0virtual:nebula/config');
593
-
594
- expect(result).toContain('"/dashboard"');
595
- expect(result).toContain('"/schemas"');
596
- expect(result).toContain('export default');
597
- });
598
-
599
- it('generates collections module mapping names to schema URLs', () => {
600
- const dir = resolve(tmpDir, '.astro/collections');
601
- mkdirSync(dir, { recursive: true });
602
- writeFileSync(resolve(dir, 'posts.schema.json'), '{}');
603
-
604
- const plugin = nebulaVitePlugin(logger, tmpDir, {
605
- basePath: '/admin',
606
- collectionsPath: '/collections',
607
- });
608
- const result = plugin.load('\0virtual:nebula/collections');
609
-
610
- expect(result).toContain('"posts"');
611
- expect(result).toContain('"/collections/posts.schema.json"');
612
- });
613
-
614
- it('handles multiple schema files', () => {
615
- const dir = resolve(tmpDir, '.astro/collections');
616
- mkdirSync(dir, { recursive: true });
617
- writeFileSync(resolve(dir, 'posts.schema.json'), '{}');
618
- writeFileSync(resolve(dir, 'authors.schema.json'), '{}');
619
-
620
- const plugin = nebulaVitePlugin(logger, tmpDir, {
621
- basePath: '/admin',
622
- collectionsPath: '/collections',
623
- });
624
- const result = plugin.load('\0virtual:nebula/collections');
625
-
626
- expect(result).toContain('"posts"');
627
- expect(result).toContain('"authors"');
628
- });
629
-
630
- it('ignores non-.schema.json files in the directory', () => {
631
- const dir = resolve(tmpDir, '.astro/collections');
632
- mkdirSync(dir, { recursive: true });
633
- writeFileSync(resolve(dir, 'posts.schema.json'), '{}');
634
- writeFileSync(resolve(dir, 'README.md'), '');
635
-
636
- const plugin = nebulaVitePlugin(logger, tmpDir, {
637
- basePath: '/admin',
638
- collectionsPath: '/collections',
639
- });
640
- const result = plugin.load('\0virtual:nebula/collections');
641
-
642
- expect(result).toContain('"posts"');
643
- expect(result).not.toContain('README');
644
- });
645
-
646
- it('strips .schema.json suffix for collection names', () => {
647
- const dir = resolve(tmpDir, '.astro/collections');
648
- mkdirSync(dir, { recursive: true });
649
- writeFileSync(resolve(dir, 'my-collection.schema.json'), '{}');
650
-
651
- const plugin = nebulaVitePlugin(logger, tmpDir, {
652
- basePath: '/admin',
653
- collectionsPath: '/collections',
654
- });
655
- const result = plugin.load('\0virtual:nebula/collections');
656
-
657
- expect(result).toContain('"my-collection"');
658
- expect(result).not.toContain('.schema.json":');
659
- });
660
-
661
- it('returns empty default export and warns when directory is missing', () => {
662
- const plugin = nebulaVitePlugin(logger, tmpDir, {
663
- basePath: '/admin',
664
- collectionsPath: '/collections',
665
- });
666
- const result = plugin.load('\0virtual:nebula/collections');
667
-
668
- expect(result).toBe('export default {};');
669
- expect(logger.warn).toHaveBeenCalledWith(
670
- expect.stringContaining('.astro/collections'),
671
- );
672
- });
673
-
674
- it('generates URLs with custom collectionsPath prefix', () => {
675
- const dir = resolve(tmpDir, '.astro/collections');
676
- mkdirSync(dir, { recursive: true });
677
- writeFileSync(resolve(dir, 'posts.schema.json'), '{}');
678
-
679
- const plugin = nebulaVitePlugin(logger, tmpDir, {
680
- basePath: '/admin',
681
- collectionsPath: '/schemas',
682
- });
683
- const result = plugin.load('\0virtual:nebula/collections');
684
-
685
- expect(result).toContain('"posts"');
686
- expect(result).toContain('"/schemas/posts.schema.json"');
687
- expect(result).not.toContain('/collections/');
688
- });
689
- });