nebula-cms 0.1.4 → 0.1.7

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.
package/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  A streamlined, Git-based Content Management System built specifically for [Astro](https://astro.build/). Nebula CMS provides a beautiful, unified editing interface for your Markdown, MDX, JSON, YAML, TOML, and Markdoc files, driven directly by your existing Astro [Content Collections](https://docs.astro.build/en/guides/content-collections/).
6
6
 
7
+ ![Screnshot of NebulaCMS using the author's blog as an example](https://github.com/user-attachments/assets/8ca305e9-4f26-4719-aae5-b70a5f1958e1)
8
+
7
9
  ## Features
8
10
 
9
11
  - **Painless Integration**: Plugs perfectly into Astro as a standard integration.
@@ -56,7 +58,7 @@ import NebulaCMS from 'nebula-cms/client';
56
58
  <title>Nebula CMS</title>
57
59
  </head>
58
60
  <body>
59
- <NebulaCMS client:only="svelte" />
61
+ <NebulaCMS client:load />
60
62
  </body>
61
63
  </html>
62
64
  ```
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/astro/index.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,OAAO,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAmDnD;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,MAAM,GAAE,eAAoB,GAC3B,gBAAgB,CA6ElB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,sBAAsB,EAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC;;IAK/B;;;;;OAKG;4BACqB;QAAE,WAAW,EAAE;YAAE,GAAG,EAAE,QAAQ,CAAA;SAAE,CAAA;KAAE;IA0E1D;;;;OAIG;kBACW,MAAM;IAKpB;;;;OAIG;aACM,MAAM;EA6BlB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/astro/index.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,OAAO,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAmDnD;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,MAAM,GAAE,eAAoB,GAC3B,gBAAgB,CA8ElB;AA6BD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,sBAAsB,EAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC;;IAK/B;;;;;OAKG;4BACqB;QAAE,WAAW,EAAE;YAAE,GAAG,EAAE,QAAQ,CAAA;SAAE,CAAA;KAAE;IA0E1D;;;;OAIG;kBACW,MAAM;IAKpB;;;;OAIG;aACM,MAAM;EA6BlB"}
@@ -76,6 +76,7 @@ export default function NebulaCMS(config = {}) {
76
76
  vite: {
77
77
  plugins: [
78
78
  nebulaVitePlugin(logger, process.cwd(), normalizedConfig),
79
+ nebulaCSSFixPlugin(),
79
80
  ],
80
81
  /*
81
82
  * Workers use dynamic imports (e.g. storage worker lazy-loads
@@ -114,6 +115,32 @@ export default function NebulaCMS(config = {}) {
114
115
  },
115
116
  };
116
117
  }
118
+ /*
119
+ * Regex matching Svelte CSS virtual module IDs from nebula-cms.
120
+ * These IDs look like: .../nebula-cms/dist/client/Foo.svelte?svelte&type=style&lang.css
121
+ */
122
+ const NEBULA_CSS_RE = /nebula-cms\/dist\/client\/.*\.svelte\?svelte&type=style/;
123
+ /**
124
+ * Vite plugin that strips cssScopeTo metadata from nebula-cms CSS
125
+ * virtual modules. Without this, Astro's production build pipeline
126
+ * tree-shakes CSS for conditionally-rendered Svelte components
127
+ * (those behind {#if} blocks that don't execute during SSR),
128
+ * resulting in missing scoped styles in the production output.
129
+ * Removing cssScopeTo ensures the SSR build retains all component
130
+ * CSS regardless of which branches execute during prerendering.
131
+ * @return {object} Vite plugin
132
+ */
133
+ function nebulaCSSFixPlugin() {
134
+ return {
135
+ name: 'vite-plugin-nebula-css-fix',
136
+ transform(code, id) {
137
+ if (!NEBULA_CSS_RE.test(id))
138
+ return null;
139
+ // Return the CSS unchanged but replace vite meta to strip cssScopeTo
140
+ return { code, meta: { vite: {} } };
141
+ },
142
+ };
143
+ }
117
144
  /**
118
145
  * Vite plugin that serves collection schemas and CMS config via virtual modules.
119
146
  * @internal Not part of the public API — exported for testing only
@@ -113,25 +113,34 @@
113
113
  /*
114
114
  * Loads content for the file or draft view. Both branches gate on `backend.ready`
115
115
  * so they re-run when the directory handle is restored on page load.
116
+ * Route is captured as a const so TS can narrow the discriminated union
117
+ * through `view` checks — the getter re-access pattern defeats narrowing.
116
118
  */
117
119
  $effect(() => {
118
- if (backend.ready && nav.route.view === 'file' && content.list.length > 0) {
120
+ const currentRoute = nav.route;
121
+ if (
122
+ backend.ready &&
123
+ currentRoute.view === 'file' &&
124
+ content.list.length > 0
125
+ ) {
119
126
  const item = content.list.find(
120
- (i) => stripExtension(i.filename) === nav.route.slug,
127
+ (i) => stripExtension(i.filename) === currentRoute.slug,
121
128
  );
122
129
  if (!item) return;
123
130
 
124
131
  // preloadFile is async — it checks IDB for a draft first
125
- preloadFile(nav.route.collection, item.filename, item.data).then(() => {
126
- // If preloadFile loaded a draft (body already present), skip disk read
127
- const editorFile = getEditorFile();
128
- if (editorFile?.draftId) return;
132
+ preloadFile(currentRoute.collection, item.filename, item.data).then(
133
+ () => {
134
+ // If preloadFile loaded a draft (body already present), skip disk read
135
+ const editorFile = getEditorFile();
136
+ if (editorFile?.draftId) return;
129
137
 
130
- loadFileBody(nav.route.collection, item.filename);
131
- });
132
- } else if (backend.ready && nav.route.view === 'draft') {
133
- loadDraftById(nav.route.draftId, nav.route.collection);
134
- } else if (nav.route.view !== 'file' && nav.route.view !== 'draft') {
138
+ loadFileBody(currentRoute.collection, item.filename);
139
+ },
140
+ );
141
+ } else if (backend.ready && currentRoute.view === 'draft') {
142
+ loadDraftById(currentRoute.draftId, currentRoute.collection);
143
+ } else if (currentRoute.view !== 'file' && currentRoute.view !== 'draft') {
135
144
  clearEditor();
136
145
  }
137
146
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Admin.svelte.d.ts","sourceRoot":"","sources":["../../src/client/Admin.svelte.ts"],"names":[],"mappings":"AAuCA,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,eAAe,CAAC;AACvB,OAAO,uBAAuB,CAAC;AAC/B,OAAO,kBAAkB,CAAC;AAC1B,OAAO,gBAAgB,CAAC;AAiNxB,QAAA,MAAM,KAAK,2DAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"Admin.svelte.d.ts","sourceRoot":"","sources":["../../src/client/Admin.svelte.ts"],"names":[],"mappings":"AAuCA,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,iBAAiB,CAAC;AACzB,OAAO,eAAe,CAAC;AACvB,OAAO,uBAAuB,CAAC;AAC/B,OAAO,kBAAkB,CAAC;AAC1B,OAAO,gBAAgB,CAAC;AA0NxB,QAAA,MAAM,KAAK,2DAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
@@ -20,8 +20,7 @@
20
20
  // The dialog element ref for imperative showModal/close
21
21
  let dialogEl = $state<HTMLDialogElement | null>(null);
22
22
 
23
- // The slug input value, initialized from slugified title
24
- let slug = $state(slugify(title));
23
+ let slug = $derived(slugify(title));
25
24
 
26
25
  // Validation error message
27
26
  const error = $derived.by(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"FilenameDialog.svelte.d.ts","sourceRoot":"","sources":["../../../../src/client/components/dialogs/FilenameDialog.svelte.ts"],"names":[],"mappings":"AAME;;GAEG;AACH,UAAU,KAAK;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAE5B,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAEtC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAoEH,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"FilenameDialog.svelte.d.ts","sourceRoot":"","sources":["../../../../src/client/components/dialogs/FilenameDialog.svelte.ts"],"names":[],"mappings":"AAME;;GAEG;AACH,UAAU,KAAK;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAE5B,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAEtC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAmEH,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -54,10 +54,8 @@
54
54
  // Search query for filtering items by label
55
55
  let searchQuery = $state('');
56
56
 
57
- // Current sort mode, initialized from localStorage if storageKey is provided
58
- let sortMode = $state<SortMode>(
59
- storageKey ? readSortMode(storageKey) : 'alpha',
60
- );
57
+ // Current sort mode the $effect below sets the correct value reactively
58
+ let sortMode = $state<SortMode>('alpha');
61
59
 
62
60
  // Re-read sort mode when storageKey changes (switching collections)
63
61
  $effect(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"AdminSidebar.svelte.d.ts","sourceRoot":"","sources":["../../../../src/client/components/sidebar/AdminSidebar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,KAAK,WAAW,EAIjB,MAAM,qBAAqB,CAAC;AAU7B,UAAU,KAAK;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,KAAK,EAAE,WAAW,EAAE,CAAC;IAErB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAwJH,QAAA,MAAM,YAAY;iBADuD,OAAO,WAAW;MACjC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"AdminSidebar.svelte.d.ts","sourceRoot":"","sources":["../../../../src/client/components/sidebar/AdminSidebar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EACH,KAAK,WAAW,EAIjB,MAAM,qBAAqB,CAAC;AAU7B,UAAU,KAAK;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,KAAK,EAAE,WAAW,EAAE,CAAC;IAErB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAsJH,QAAA,MAAM,YAAY;iBADuD,OAAO,WAAW;MACjC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"router.svelte.d.ts","sourceRoot":"","sources":["../../../../src/client/js/state/router.svelte.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAQ3D,eAAO,MAAM,GAAG;oBAED,UAAU;CAGxB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAIvD;AAgDD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE3C;AAKD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,CAEjE;AAKD;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAwCjC"}
1
+ {"version":3,"file":"router.svelte.d.ts","sourceRoot":"","sources":["../../../../src/client/js/state/router.svelte.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAgB3D,eAAO,MAAM,GAAG;oBAED,UAAU;CAGxB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAIvD;AAgDD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE3C;AAKD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,CAEjE;AAKD;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAwCjC"}
@@ -6,8 +6,14 @@
6
6
  import config from 'virtual:nebula/config';
7
7
  // Build-time constant — configured via the Astro integration
8
8
  const basePath = config.basePath;
9
- // Current route, reactive via Svelte 5 runes
10
- let route = $state(parsePathname(location.pathname));
9
+ /*
10
+ * Current route, reactive via Svelte 5 runes.
11
+ * Defaults to 'home' during SSR where location is unavailable;
12
+ * the client re-initializes from the real pathname on hydration.
13
+ */
14
+ let route = $state(typeof location !== 'undefined'
15
+ ? parsePathname(location.pathname)
16
+ : { view: 'home' });
11
17
  export const nav = {
12
18
  // Current parsed admin route.
13
19
  get route() {
@@ -122,7 +128,7 @@ export function initRouter() {
122
128
  return;
123
129
  }
124
130
  event.intercept({
125
- handler() {
131
+ async handler() {
126
132
  route = parsePathname(url.pathname);
127
133
  },
128
134
  });
@@ -1 +1 @@
1
- {"version":3,"file":"state.svelte.d.ts","sourceRoot":"","sources":["../../../../src/client/js/state/state.svelte.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EACL,MAAM,EAEN,aAAa,EAEd,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AAGjC,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,CAAC;AAGF,KAAK,eAAe,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEvD,KAAK,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,IAAI,CAAC;AAE3C,eAAO,MAAM,WAAW,UAA8B,CAAC;AAUvD,eAAO,MAAM,aAAa,eAAuC,CAAC;AAQlE,eAAO,MAAM,OAAO;mBAEN,WAAW;oBAIV,OAAO;yBAIF,eAAe;CAGlC,CAAC;AAEF,eAAO,MAAM,OAAO;mBAEN,WAAW,EAAE;sBAIV,OAAO;oBAIT,MAAM,GAAG,IAAI;CAG3B,CAAC;AAoEF;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CA6CpD;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAcvD;AAED;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAcnD;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAOf;AAED;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAehD;AAYD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAYvD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAGzD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,IAAI,CAMN"}
1
+ {"version":3,"file":"state.svelte.d.ts","sourceRoot":"","sources":["../../../../src/client/js/state/state.svelte.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EACL,MAAM,EAEN,aAAa,EAEd,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AAGjC,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,CAAC;AAGF,KAAK,eAAe,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEvD,KAAK,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,IAAI,CAAC;AAE3C,eAAO,MAAM,WAAW,UAA8B,CAAC;AAoBvD,eAAO,MAAM,aAAa,EAErB,aAAa,CAAC;AAQnB,eAAO,MAAM,OAAO;mBAEN,WAAW;oBAIV,OAAO;yBAIF,eAAe;CAGlC,CAAC;AAEF,eAAO,MAAM,OAAO;mBAEN,WAAW,EAAE;sBAIV,OAAO;oBAIT,MAAM,GAAG,IAAI;CAG3B,CAAC;AAoEF;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CA6CpD;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAcvD;AAED;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAcnD;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAOf;AAED;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAehD;AAYD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAYvD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAGzD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,IAAI,CAMN"}
@@ -14,10 +14,19 @@ export const collections = Object.keys(schemas).sort();
14
14
  /*
15
15
  * Uses .js extension because svelte-package does not rewrite URL string literals;
16
16
  * the dist output must reference the compiled .js file, not the source .ts file.
17
+ *
18
+ * Guarded for SSR: SharedWorker only exists in browsers. All code paths
19
+ * that use sharedWorker/storageClient run exclusively on the client
20
+ * (inside onMount, event handlers, or user-initiated actions).
17
21
  */
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);
22
+ const sharedWorker = typeof SharedWorker !== 'undefined'
23
+ ? new SharedWorker(new URL('../storage/workers/storage.js', import.meta.url), { type: 'module', name: 'cms-storage' })
24
+ : null;
25
+ /*
26
+ * Main-thread StorageClient for editor and draft-merge I/O.
27
+ * Null during SSR but typed as non-null because every caller is client-only.
28
+ */
29
+ export const storageClient = (sharedWorker ? new StorageClient(sharedWorker.port) : null);
21
30
  let backendType = $state(null);
22
31
  let backendReady = $state(false);
23
32
  let permissionState = $state('denied');
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Type augmentations for browser APIs not fully covered by installed @types packages.
3
+ * The side-effect import makes this a module file so `declare global` adds to the
4
+ * global scope and `declare module` augments (rather than redeclares) the target.
5
+ */
6
+
7
+ import 'svelte/elements';
8
+
9
+ /*
10
+ //////////////////////////////
11
+ // Navigation API
12
+ //////////////////////////////
13
+ */
14
+
15
+ /*
16
+ * @types/dom-navigation provides the Navigation class and augments Window,
17
+ * but omits the global variable declaration that lets code use bare
18
+ * `navigation` (like bare `document` or `location`).
19
+ */
20
+ declare global {
21
+ var navigation: Navigation;
22
+ }
23
+
24
+ /*
25
+ //////////////////////////////
26
+ // Interest Invokers API
27
+ //////////////////////////////
28
+ */
29
+
30
+ /*
31
+ * No @types package exists for this spec.
32
+ * See: https://open-ui.org/components/interest-invokers.explainer/
33
+ */
34
+ declare module 'svelte/elements' {
35
+ // Extends all HTML elements with the interestfor attribute
36
+ interface HTMLAttributes<T> {
37
+ interestfor?: string;
38
+ }
39
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nebula-cms",
3
- "version": "0.1.4",
3
+ "version": "0.1.7",
4
4
  "description": "A native CMS for Astro",
5
5
  "type": "module",
6
6
  "repository": {
@@ -56,7 +56,11 @@
56
56
  "@sveltejs/package": "^2.5.7",
57
57
  "@sveltejs/vite-plugin-svelte": "^7.0.0",
58
58
  "@testing-library/svelte": "^5.3.1",
59
- "vitest": "^4.1.2",
59
+ "@types/dom-navigation": "^1.0.7",
60
+ "@types/js-yaml": "^4.0.9",
61
+ "@types/node": "^25.5.2",
62
+ "@types/sharedworker": "^0.0.223",
63
+ "@types/wicg-file-system-access": "^2023.10.7",
60
64
  "@vitest/browser": "^4.1.2",
61
65
  "@vitest/browser-playwright": "^4.1.2",
62
66
  "@vitest/coverage-v8": "^4.1.2",
@@ -68,12 +72,15 @@
68
72
  "prettier-plugin-astro": "^0.14.1",
69
73
  "prettier-plugin-svelte": "^3.5.1",
70
74
  "svelte": "^5.54.1",
71
- "typescript": "^5.9.3"
75
+ "svelte-check": "^4.4.6",
76
+ "typescript": "^5.9.3",
77
+ "vitest": "^4.1.2"
72
78
  },
73
79
  "scripts": {
74
80
  "prebuild": "node scripts/subset-icons.mjs",
75
81
  "build": "svelte-package --input src --output dist",
76
82
  "lint": "prettier -c .",
83
+ "check": "svelte-check",
77
84
  "fix": "prettier --write .",
78
85
  "test": "vitest run",
79
86
  "test:continuous": "vitest"