@dispatchcms/react 0.0.6 → 0.0.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
@@ -1,6 +1,6 @@
1
1
  # @dispatchcms/react
2
2
 
3
- React hooks and provider for [Dispatch](https://dispatch-cms.vercel.app) CMS. Use `DispatchProvider` and `usePost` / `usePosts` to fetch published posts in any React app (Next.js, Vite, etc.).
3
+ React hooks and provider for [Dispatch](https://dispatch-cms.vercel.app) CMS. Use `DispatchProvider` and `useEntry` / `useEntries` to fetch published entries in any React app (Next.js, Vite, etc.).
4
4
 
5
5
  ## Install
6
6
 
@@ -32,29 +32,29 @@ To use a different API base URL, pass the `apiBase` prop to the provider.
32
32
 
33
33
  ## API
34
34
 
35
- ### `usePost(slug)`
35
+ ### `useEntry(collection, slug)`
36
36
 
37
- Fetches a single published post by slug.
37
+ Fetches a single published entry.
38
38
 
39
- - **Returns:** `{ post: Post | null, isLoading: boolean, error?: string }`
40
- - On failure or missing site key, does not throw; returns `post: null`, `isLoading: false`, and `error` set.
39
+ - **Returns:** `{ entry: Entry | null, isLoading: boolean, error?: string }`
40
+ - On failure or missing site key, does not throw; returns `entry: null`, `isLoading: false`, and `error` set.
41
41
 
42
- ### `usePosts()`
42
+ ### `useEntries(collection)`
43
43
 
44
- Fetches all published posts for the site.
44
+ Fetches published entries for a collection.
45
45
 
46
- - **Returns:** `{ posts: Post[], isLoading: boolean, error?: string }`
47
- - On failure or missing site key, does not throw; returns `posts: []`, `isLoading: false`, and `error` set.
46
+ - **Returns:** `{ entries: Entry[], isLoading: boolean, error?: string }`
47
+ - On failure or missing site key, does not throw; returns `entries: []`, `isLoading: false`, and `error` set.
48
48
 
49
49
  ### Graceful failure
50
50
 
51
- - If the API request fails, hooks return `post: null` / `posts: []`, `isLoading: false`, and `error: "Failed to load"`. The React tree is never crashed.
51
+ - If the API request fails, hooks return `entry: null` / `entries: []`, `isLoading: false`, and `error: "Failed to load"`. The React tree is never crashed.
52
52
  - If no `siteKey` is provided to the provider, `console.warn` is logged and hooks return the same safe empty/error state with `error: "Missing site key"`.
53
53
 
54
54
  ## Types
55
55
 
56
- - **`Post`** – Post from the CMS. Fields include `id`, `title`, `slug`, `content`, `excerpt`, `featured_image`, `published`, `published_at`, `created_at`, `updated_at`, `site_id`. The `content` field is **TipTap (ProseMirror) JSON**.
57
- - **`UsePostResult`** / **`UsePostsResult`** – Return types of the hooks.
56
+ - **`Entry`** – Entry from a collection. Fields include `id`, `collection`, `title`, `slug`, `data`, `published`, `published_at`, `sort_order`. Rich text values inside `data` are **TipTap (ProseMirror) JSON**.
57
+ - **`UseEntryResult`** / **`UseEntriesResult`** – Return types of the hooks.
58
58
 
59
59
  ## Rendering content
60
60
 
@@ -78,26 +78,26 @@ function TipTapContent({ content }: { content: unknown }) {
78
78
  }
79
79
 
80
80
  // In your post page:
81
- <TipTapContent content={post.content} />
81
+ <TipTapContent content={entry.data.body} />
82
82
  ```
83
83
 
84
84
  ## Example
85
85
 
86
86
  ```tsx
87
87
  // List posts (e.g. homepage)
88
- import { usePosts } from "@dispatchcms/react";
88
+ import { useEntries } from "@dispatchcms/react";
89
89
 
90
90
  export default function HomePage() {
91
- const { posts, isLoading, error } = usePosts();
91
+ const { entries, isLoading, error } = useEntries("posts");
92
92
 
93
93
  if (isLoading) return <p>Loading…</p>;
94
94
  if (error) return <p>{error}</p>;
95
95
 
96
96
  return (
97
97
  <ul>
98
- {posts.map((post) => (
99
- <li key={post.id}>
100
- <a href={`/blog/${post.slug}`}>{post.title}</a>
98
+ {entries.map((entry) => (
99
+ <li key={entry.id}>
100
+ <a href={`/blog/${entry.slug}`}>{entry.title}</a>
101
101
  </li>
102
102
  ))}
103
103
  </ul>
@@ -107,20 +107,19 @@ export default function HomePage() {
107
107
 
108
108
  ```tsx
109
109
  // Single post page (e.g. /blog/:slug)
110
- import { usePost } from "@dispatchcms/react";
110
+ import { useEntry } from "@dispatchcms/react";
111
111
  import { TipTapContent } from "./TipTapContent"; // or inline renderToReactElement
112
112
 
113
113
  export default function PostPage({ slug }) {
114
- const { post, isLoading, error } = usePost(slug);
114
+ const { entry, isLoading, error } = useEntry("posts", slug);
115
115
 
116
116
  if (isLoading) return <p>Loading…</p>;
117
- if (error || !post) return <p>{error ?? "Not found"}</p>;
117
+ if (error || !entry) return <p>{error ?? "Not found"}</p>;
118
118
 
119
119
  return (
120
120
  <article>
121
- <h1>{post.title}</h1>
122
- {post.excerpt && <p>{post.excerpt}</p>}
123
- <TipTapContent content={post.content} />
121
+ <h1>{entry.title}</h1>
122
+ <TipTapContent content={entry.data.body} />
124
123
  </article>
125
124
  );
126
125
  }
package/dist/index.d.mts CHANGED
@@ -1,16 +1,16 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
- type Post = {
3
+ type Entry = {
4
4
  id: string;
5
5
  created_at: string;
6
- published_at: string;
6
+ published_at: string | null;
7
7
  updated_at: string;
8
8
  site_id: string;
9
+ collection: string;
9
10
  title: string;
10
- slug: string;
11
- content: unknown;
12
- excerpt: string | null;
13
- featured_image: string | null;
11
+ slug: string | null;
12
+ data: Record<string, unknown>;
13
+ sort_order: number;
14
14
  published: boolean;
15
15
  };
16
16
 
@@ -26,17 +26,17 @@ type DispatchProviderProps = {
26
26
  };
27
27
  declare function DispatchProvider({ siteKey, apiBase, children, }: DispatchProviderProps): react_jsx_runtime.JSX.Element;
28
28
 
29
- type UsePostResult = {
30
- post: Post | null;
29
+ type UseEntryResult = {
30
+ entry: Entry | null;
31
31
  isLoading: boolean;
32
32
  error?: string;
33
33
  };
34
- declare function usePost(slug: string | undefined): UsePostResult;
35
- type UsePostsResult = {
36
- posts: Post[];
34
+ declare function useEntry(collection: string | undefined, slug: string | undefined): UseEntryResult;
35
+ type UseEntriesResult = {
36
+ entries: Entry[];
37
37
  isLoading: boolean;
38
38
  error?: string;
39
39
  };
40
- declare function usePosts(): UsePostsResult;
40
+ declare function useEntries(collection: string | undefined): UseEntriesResult;
41
41
 
42
- export { DispatchProvider, type Post, type UsePostResult, type UsePostsResult, useDispatchContext, usePost, usePosts };
42
+ export { DispatchProvider, type Entry, type UseEntriesResult, type UseEntryResult, useDispatchContext, useEntries, useEntry };
package/dist/index.d.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
- type Post = {
3
+ type Entry = {
4
4
  id: string;
5
5
  created_at: string;
6
- published_at: string;
6
+ published_at: string | null;
7
7
  updated_at: string;
8
8
  site_id: string;
9
+ collection: string;
9
10
  title: string;
10
- slug: string;
11
- content: unknown;
12
- excerpt: string | null;
13
- featured_image: string | null;
11
+ slug: string | null;
12
+ data: Record<string, unknown>;
13
+ sort_order: number;
14
14
  published: boolean;
15
15
  };
16
16
 
@@ -26,17 +26,17 @@ type DispatchProviderProps = {
26
26
  };
27
27
  declare function DispatchProvider({ siteKey, apiBase, children, }: DispatchProviderProps): react_jsx_runtime.JSX.Element;
28
28
 
29
- type UsePostResult = {
30
- post: Post | null;
29
+ type UseEntryResult = {
30
+ entry: Entry | null;
31
31
  isLoading: boolean;
32
32
  error?: string;
33
33
  };
34
- declare function usePost(slug: string | undefined): UsePostResult;
35
- type UsePostsResult = {
36
- posts: Post[];
34
+ declare function useEntry(collection: string | undefined, slug: string | undefined): UseEntryResult;
35
+ type UseEntriesResult = {
36
+ entries: Entry[];
37
37
  isLoading: boolean;
38
38
  error?: string;
39
39
  };
40
- declare function usePosts(): UsePostsResult;
40
+ declare function useEntries(collection: string | undefined): UseEntriesResult;
41
41
 
42
- export { DispatchProvider, type Post, type UsePostResult, type UsePostsResult, useDispatchContext, usePost, usePosts };
42
+ export { DispatchProvider, type Entry, type UseEntriesResult, type UseEntryResult, useDispatchContext, useEntries, useEntry };
package/dist/index.js CHANGED
@@ -23,8 +23,8 @@ var index_exports = {};
23
23
  __export(index_exports, {
24
24
  DispatchProvider: () => DispatchProvider,
25
25
  useDispatchContext: () => useDispatchContext,
26
- usePost: () => usePost,
27
- usePosts: () => usePosts
26
+ useEntries: () => useEntries,
27
+ useEntry: () => useEntry
28
28
  });
29
29
  module.exports = __toCommonJS(index_exports);
30
30
 
@@ -64,110 +64,116 @@ function DispatchProvider({
64
64
 
65
65
  // src/hooks.ts
66
66
  var import_react2 = require("react");
67
- function usePost(slug) {
67
+ function useEntry(collection, slug) {
68
68
  const ctx = useDispatchContext();
69
- const [post, setPost] = (0, import_react2.useState)(null);
69
+ const [entry, setEntry] = (0, import_react2.useState)(null);
70
70
  const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
71
71
  const [error, setError] = (0, import_react2.useState)(void 0);
72
72
  (0, import_react2.useEffect)(() => {
73
- if (!slug?.trim()) {
74
- setPost(null);
73
+ if (!collection?.trim() || !slug?.trim()) {
74
+ setEntry(null);
75
75
  setIsLoading(false);
76
76
  setError(void 0);
77
77
  return;
78
78
  }
79
79
  if (!ctx?.siteKey) {
80
- setPost(null);
80
+ setEntry(null);
81
81
  setIsLoading(false);
82
82
  setError("Missing site key");
83
83
  return;
84
84
  }
85
85
  let cancelled = false;
86
- setPost(null);
86
+ setEntry(null);
87
87
  setError(void 0);
88
88
  setIsLoading(true);
89
- const url = `${ctx.apiBase}/api/posts/${encodeURIComponent(slug.trim())}`;
89
+ const url = `${ctx.apiBase}/api/content/${encodeURIComponent(collection.trim())}/${encodeURIComponent(slug.trim())}`;
90
90
  fetch(url, {
91
91
  headers: { "X-Site-Key": ctx.siteKey }
92
92
  }).then((res) => {
93
93
  if (cancelled) return;
94
94
  if (res.status === 404) {
95
- setPost(null);
95
+ setEntry(null);
96
96
  setIsLoading(false);
97
97
  return;
98
98
  }
99
99
  if (!res.ok) {
100
- setPost(null);
100
+ setEntry(null);
101
101
  setIsLoading(false);
102
102
  setError("Failed to load");
103
103
  return;
104
104
  }
105
105
  return res.json();
106
106
  }).then((data) => {
107
- if (cancelled) return;
108
- setPost(data);
107
+ if (cancelled || data == null) return;
108
+ setEntry(data);
109
109
  setIsLoading(false);
110
110
  }).catch(() => {
111
111
  if (cancelled) return;
112
- setPost(null);
112
+ setEntry(null);
113
113
  setIsLoading(false);
114
114
  setError("Failed to load");
115
115
  });
116
116
  return () => {
117
117
  cancelled = true;
118
118
  };
119
- }, [slug, ctx?.siteKey, ctx?.apiBase]);
120
- return { post, isLoading, error };
119
+ }, [collection, slug, ctx?.siteKey, ctx?.apiBase]);
120
+ return { entry, isLoading, error };
121
121
  }
122
- function usePosts() {
122
+ function useEntries(collection) {
123
123
  const ctx = useDispatchContext();
124
- const [posts, setPosts] = (0, import_react2.useState)([]);
124
+ const [entries, setEntries] = (0, import_react2.useState)([]);
125
125
  const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
126
126
  const [error, setError] = (0, import_react2.useState)(void 0);
127
127
  (0, import_react2.useEffect)(() => {
128
+ if (!collection?.trim()) {
129
+ setEntries([]);
130
+ setIsLoading(false);
131
+ setError(void 0);
132
+ return;
133
+ }
128
134
  if (!ctx?.siteKey) {
129
- setPosts([]);
135
+ setEntries([]);
130
136
  setIsLoading(false);
131
137
  setError("Missing site key");
132
138
  return;
133
139
  }
134
140
  let cancelled = false;
135
- setPosts([]);
141
+ setEntries([]);
136
142
  setError(void 0);
137
143
  setIsLoading(true);
138
- const url = `${ctx.apiBase}/api/posts`;
144
+ const url = `${ctx.apiBase}/api/content/${encodeURIComponent(collection.trim())}`;
139
145
  fetch(url, {
140
146
  headers: { "X-Site-Key": ctx.siteKey }
141
147
  }).then((res) => {
142
148
  if (cancelled) return;
143
149
  if (!res.ok) {
144
- setPosts([]);
150
+ setEntries([]);
145
151
  setIsLoading(false);
146
152
  setError("Failed to load");
147
153
  return;
148
154
  }
149
155
  return res.json();
150
156
  }).then((data) => {
151
- if (cancelled) return;
152
- setPosts(Array.isArray(data) ? data : []);
157
+ if (cancelled || data == null) return;
158
+ setEntries(Array.isArray(data) ? data : []);
153
159
  setIsLoading(false);
154
160
  }).catch(() => {
155
161
  if (cancelled) return;
156
- setPosts([]);
162
+ setEntries([]);
157
163
  setIsLoading(false);
158
164
  setError("Failed to load");
159
165
  });
160
166
  return () => {
161
167
  cancelled = true;
162
168
  };
163
- }, [ctx?.siteKey, ctx?.apiBase]);
164
- return { posts, isLoading, error };
169
+ }, [collection, ctx?.siteKey, ctx?.apiBase]);
170
+ return { entries, isLoading, error };
165
171
  }
166
172
  // Annotate the CommonJS export names for ESM import in node:
167
173
  0 && (module.exports = {
168
174
  DispatchProvider,
169
175
  useDispatchContext,
170
- usePost,
171
- usePosts
176
+ useEntries,
177
+ useEntry
172
178
  });
173
179
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/context.tsx","../src/config.ts","../src/hooks.ts"],"sourcesContent":["export type { Post } from \"./types\";\nexport { DispatchProvider, useDispatchContext } from \"./context\";\nexport { usePost, usePosts } from \"./hooks\";\nexport type { UsePostResult, UsePostsResult } from \"./hooks\";\n","\"use client\";\n\nimport React, { createContext, useContext } from \"react\";\nimport { getApiBase } from \"./config\";\n\ntype DispatchContextValue = {\n siteKey: string | null;\n apiBase: string;\n};\n\nconst DispatchContext = createContext<DispatchContextValue | null>(null);\n\nexport function useDispatchContext(): DispatchContextValue | null {\n return useContext(DispatchContext);\n}\n\ntype DispatchProviderProps = {\n siteKey?: string | null;\n apiBase?: string;\n children?: unknown;\n};\n\nexport function DispatchProvider({\n siteKey = null,\n apiBase = getApiBase(),\n children,\n}: DispatchProviderProps) {\n const value: DispatchContextValue = {\n siteKey: siteKey?.trim() || null,\n apiBase,\n };\n\n if (!value.siteKey) {\n if (typeof console !== \"undefined\" && console.warn) {\n console.warn(\n \"[Dispatch] No siteKey provided. Pass siteKey to DispatchProvider. Hooks will return empty/error state.\"\n );\n }\n }\n\n return (\n <DispatchContext.Provider value={value}>\n {children as React.ReactNode}\n </DispatchContext.Provider>\n );\n}\n","const DEFAULT_API_BASE = \"https://dispatch-cms.vercel.app\";\n\nexport function getApiBase(): string {\n return DEFAULT_API_BASE;\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { Post } from \"./types\";\nimport { useDispatchContext } from \"./context\";\n\nexport type UsePostResult = {\n post: Post | null;\n isLoading: boolean;\n error?: string;\n};\n\nexport function usePost(slug: string | undefined): UsePostResult {\n const ctx = useDispatchContext();\n const [post, setPost] = useState<Post | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n if (!slug?.trim()) {\n setPost(null);\n setIsLoading(false);\n setError(undefined);\n return;\n }\n\n if (!ctx?.siteKey) {\n setPost(null);\n setIsLoading(false);\n setError(\"Missing site key\");\n return;\n }\n\n let cancelled = false;\n setPost(null);\n setError(undefined);\n setIsLoading(true);\n\n const url = `${ctx.apiBase}/api/posts/${encodeURIComponent(slug.trim())}`;\n fetch(url, {\n headers: { \"X-Site-Key\": ctx.siteKey },\n })\n .then((res) => {\n if (cancelled) return;\n if (res.status === 404) {\n setPost(null);\n setIsLoading(false);\n return;\n }\n if (!res.ok) {\n setPost(null);\n setIsLoading(false);\n setError(\"Failed to load\");\n return;\n }\n return res.json();\n })\n .then((data) => {\n if (cancelled) return;\n setPost(data as Post);\n setIsLoading(false);\n })\n .catch(() => {\n if (cancelled) return;\n setPost(null);\n setIsLoading(false);\n setError(\"Failed to load\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [slug, ctx?.siteKey, ctx?.apiBase]);\n\n return { post, isLoading, error };\n}\n\nexport type UsePostsResult = {\n posts: Post[];\n isLoading: boolean;\n error?: string;\n};\n\nexport function usePosts(): UsePostsResult {\n const ctx = useDispatchContext();\n const [posts, setPosts] = useState<Post[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n if (!ctx?.siteKey) {\n setPosts([]);\n setIsLoading(false);\n setError(\"Missing site key\");\n return;\n }\n\n let cancelled = false;\n setPosts([]);\n setError(undefined);\n setIsLoading(true);\n\n const url = `${ctx.apiBase}/api/posts`;\n fetch(url, {\n headers: { \"X-Site-Key\": ctx.siteKey },\n })\n .then((res) => {\n if (cancelled) return;\n if (!res.ok) {\n setPosts([]);\n setIsLoading(false);\n setError(\"Failed to load\");\n return;\n }\n return res.json();\n })\n .then((data) => {\n if (cancelled) return;\n setPosts(Array.isArray(data) ? data : []);\n setIsLoading(false);\n })\n .catch(() => {\n if (cancelled) return;\n setPosts([]);\n setIsLoading(false);\n setError(\"Failed to load\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [ctx?.siteKey, ctx?.apiBase]);\n\n return { posts, isLoading, error };\n}\n"],"mappings":"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","names":["import_react"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/context.tsx","../src/config.ts","../src/hooks.ts"],"sourcesContent":["export type { Entry } from \"./types\";\nexport { DispatchProvider, useDispatchContext } from \"./context\";\nexport { useEntry, useEntries } from \"./hooks\";\nexport type { UseEntryResult, UseEntriesResult } from \"./hooks\";\n","\"use client\";\n\nimport React, { createContext, useContext } from \"react\";\nimport { getApiBase } from \"./config\";\n\ntype DispatchContextValue = {\n siteKey: string | null;\n apiBase: string;\n};\n\nconst DispatchContext = createContext<DispatchContextValue | null>(null);\n\nexport function useDispatchContext(): DispatchContextValue | null {\n return useContext(DispatchContext);\n}\n\ntype DispatchProviderProps = {\n siteKey?: string | null;\n apiBase?: string;\n children?: unknown;\n};\n\nexport function DispatchProvider({\n siteKey = null,\n apiBase = getApiBase(),\n children,\n}: DispatchProviderProps) {\n const value: DispatchContextValue = {\n siteKey: siteKey?.trim() || null,\n apiBase,\n };\n\n if (!value.siteKey) {\n if (typeof console !== \"undefined\" && console.warn) {\n console.warn(\n \"[Dispatch] No siteKey provided. Pass siteKey to DispatchProvider. Hooks will return empty/error state.\"\n );\n }\n }\n\n return (\n <DispatchContext.Provider value={value}>\n {children as React.ReactNode}\n </DispatchContext.Provider>\n );\n}\n","const DEFAULT_API_BASE = \"https://dispatch-cms.vercel.app\";\n\nexport function getApiBase(): string {\n return DEFAULT_API_BASE;\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { Entry } from \"./types\";\nimport { useDispatchContext } from \"./context\";\n\nexport type UseEntryResult = {\n entry: Entry | null;\n isLoading: boolean;\n error?: string;\n};\n\nexport function useEntry(collection: string | undefined, slug: string | undefined): UseEntryResult {\n const ctx = useDispatchContext();\n const [entry, setEntry] = useState<Entry | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n if (!collection?.trim() || !slug?.trim()) {\n setEntry(null);\n setIsLoading(false);\n setError(undefined);\n return;\n }\n\n if (!ctx?.siteKey) {\n setEntry(null);\n setIsLoading(false);\n setError(\"Missing site key\");\n return;\n }\n\n let cancelled = false;\n setEntry(null);\n setError(undefined);\n setIsLoading(true);\n\n const url = `${ctx.apiBase}/api/content/${encodeURIComponent(collection.trim())}/${encodeURIComponent(slug.trim())}`;\n fetch(url, {\n headers: { \"X-Site-Key\": ctx.siteKey },\n })\n .then((res) => {\n if (cancelled) return;\n if (res.status === 404) {\n setEntry(null);\n setIsLoading(false);\n return;\n }\n if (!res.ok) {\n setEntry(null);\n setIsLoading(false);\n setError(\"Failed to load\");\n return;\n }\n return res.json();\n })\n .then((data) => {\n if (cancelled || data == null) return;\n setEntry(data as Entry);\n setIsLoading(false);\n })\n .catch(() => {\n if (cancelled) return;\n setEntry(null);\n setIsLoading(false);\n setError(\"Failed to load\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [collection, slug, ctx?.siteKey, ctx?.apiBase]);\n\n return { entry, isLoading, error };\n}\n\nexport type UseEntriesResult = {\n entries: Entry[];\n isLoading: boolean;\n error?: string;\n};\n\nexport function useEntries(collection: string | undefined): UseEntriesResult {\n const ctx = useDispatchContext();\n const [entries, setEntries] = useState<Entry[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n if (!collection?.trim()) {\n setEntries([]);\n setIsLoading(false);\n setError(undefined);\n return;\n }\n\n if (!ctx?.siteKey) {\n setEntries([]);\n setIsLoading(false);\n setError(\"Missing site key\");\n return;\n }\n\n let cancelled = false;\n setEntries([]);\n setError(undefined);\n setIsLoading(true);\n\n const url = `${ctx.apiBase}/api/content/${encodeURIComponent(collection.trim())}`;\n fetch(url, {\n headers: { \"X-Site-Key\": ctx.siteKey },\n })\n .then((res) => {\n if (cancelled) return;\n if (!res.ok) {\n setEntries([]);\n setIsLoading(false);\n setError(\"Failed to load\");\n return;\n }\n return res.json();\n })\n .then((data) => {\n if (cancelled || data == null) return;\n setEntries(Array.isArray(data) ? data : []);\n setIsLoading(false);\n })\n .catch(() => {\n if (cancelled) return;\n setEntries([]);\n setIsLoading(false);\n setError(\"Failed to load\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [collection, ctx?.siteKey, ctx?.apiBase]);\n\n return { entries, isLoading, error };\n}\n"],"mappings":"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","names":["import_react"]}
package/dist/index.mjs CHANGED
@@ -36,109 +36,115 @@ function DispatchProvider({
36
36
 
37
37
  // src/hooks.ts
38
38
  import { useEffect, useState } from "react";
39
- function usePost(slug) {
39
+ function useEntry(collection, slug) {
40
40
  const ctx = useDispatchContext();
41
- const [post, setPost] = useState(null);
41
+ const [entry, setEntry] = useState(null);
42
42
  const [isLoading, setIsLoading] = useState(true);
43
43
  const [error, setError] = useState(void 0);
44
44
  useEffect(() => {
45
- if (!slug?.trim()) {
46
- setPost(null);
45
+ if (!collection?.trim() || !slug?.trim()) {
46
+ setEntry(null);
47
47
  setIsLoading(false);
48
48
  setError(void 0);
49
49
  return;
50
50
  }
51
51
  if (!ctx?.siteKey) {
52
- setPost(null);
52
+ setEntry(null);
53
53
  setIsLoading(false);
54
54
  setError("Missing site key");
55
55
  return;
56
56
  }
57
57
  let cancelled = false;
58
- setPost(null);
58
+ setEntry(null);
59
59
  setError(void 0);
60
60
  setIsLoading(true);
61
- const url = `${ctx.apiBase}/api/posts/${encodeURIComponent(slug.trim())}`;
61
+ const url = `${ctx.apiBase}/api/content/${encodeURIComponent(collection.trim())}/${encodeURIComponent(slug.trim())}`;
62
62
  fetch(url, {
63
63
  headers: { "X-Site-Key": ctx.siteKey }
64
64
  }).then((res) => {
65
65
  if (cancelled) return;
66
66
  if (res.status === 404) {
67
- setPost(null);
67
+ setEntry(null);
68
68
  setIsLoading(false);
69
69
  return;
70
70
  }
71
71
  if (!res.ok) {
72
- setPost(null);
72
+ setEntry(null);
73
73
  setIsLoading(false);
74
74
  setError("Failed to load");
75
75
  return;
76
76
  }
77
77
  return res.json();
78
78
  }).then((data) => {
79
- if (cancelled) return;
80
- setPost(data);
79
+ if (cancelled || data == null) return;
80
+ setEntry(data);
81
81
  setIsLoading(false);
82
82
  }).catch(() => {
83
83
  if (cancelled) return;
84
- setPost(null);
84
+ setEntry(null);
85
85
  setIsLoading(false);
86
86
  setError("Failed to load");
87
87
  });
88
88
  return () => {
89
89
  cancelled = true;
90
90
  };
91
- }, [slug, ctx?.siteKey, ctx?.apiBase]);
92
- return { post, isLoading, error };
91
+ }, [collection, slug, ctx?.siteKey, ctx?.apiBase]);
92
+ return { entry, isLoading, error };
93
93
  }
94
- function usePosts() {
94
+ function useEntries(collection) {
95
95
  const ctx = useDispatchContext();
96
- const [posts, setPosts] = useState([]);
96
+ const [entries, setEntries] = useState([]);
97
97
  const [isLoading, setIsLoading] = useState(true);
98
98
  const [error, setError] = useState(void 0);
99
99
  useEffect(() => {
100
+ if (!collection?.trim()) {
101
+ setEntries([]);
102
+ setIsLoading(false);
103
+ setError(void 0);
104
+ return;
105
+ }
100
106
  if (!ctx?.siteKey) {
101
- setPosts([]);
107
+ setEntries([]);
102
108
  setIsLoading(false);
103
109
  setError("Missing site key");
104
110
  return;
105
111
  }
106
112
  let cancelled = false;
107
- setPosts([]);
113
+ setEntries([]);
108
114
  setError(void 0);
109
115
  setIsLoading(true);
110
- const url = `${ctx.apiBase}/api/posts`;
116
+ const url = `${ctx.apiBase}/api/content/${encodeURIComponent(collection.trim())}`;
111
117
  fetch(url, {
112
118
  headers: { "X-Site-Key": ctx.siteKey }
113
119
  }).then((res) => {
114
120
  if (cancelled) return;
115
121
  if (!res.ok) {
116
- setPosts([]);
122
+ setEntries([]);
117
123
  setIsLoading(false);
118
124
  setError("Failed to load");
119
125
  return;
120
126
  }
121
127
  return res.json();
122
128
  }).then((data) => {
123
- if (cancelled) return;
124
- setPosts(Array.isArray(data) ? data : []);
129
+ if (cancelled || data == null) return;
130
+ setEntries(Array.isArray(data) ? data : []);
125
131
  setIsLoading(false);
126
132
  }).catch(() => {
127
133
  if (cancelled) return;
128
- setPosts([]);
134
+ setEntries([]);
129
135
  setIsLoading(false);
130
136
  setError("Failed to load");
131
137
  });
132
138
  return () => {
133
139
  cancelled = true;
134
140
  };
135
- }, [ctx?.siteKey, ctx?.apiBase]);
136
- return { posts, isLoading, error };
141
+ }, [collection, ctx?.siteKey, ctx?.apiBase]);
142
+ return { entries, isLoading, error };
137
143
  }
138
144
  export {
139
145
  DispatchProvider,
140
146
  useDispatchContext,
141
- usePost,
142
- usePosts
147
+ useEntries,
148
+ useEntry
143
149
  };
144
150
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context.tsx","../src/config.ts","../src/hooks.ts"],"sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext } from \"react\";\nimport { getApiBase } from \"./config\";\n\ntype DispatchContextValue = {\n siteKey: string | null;\n apiBase: string;\n};\n\nconst DispatchContext = createContext<DispatchContextValue | null>(null);\n\nexport function useDispatchContext(): DispatchContextValue | null {\n return useContext(DispatchContext);\n}\n\ntype DispatchProviderProps = {\n siteKey?: string | null;\n apiBase?: string;\n children?: unknown;\n};\n\nexport function DispatchProvider({\n siteKey = null,\n apiBase = getApiBase(),\n children,\n}: DispatchProviderProps) {\n const value: DispatchContextValue = {\n siteKey: siteKey?.trim() || null,\n apiBase,\n };\n\n if (!value.siteKey) {\n if (typeof console !== \"undefined\" && console.warn) {\n console.warn(\n \"[Dispatch] No siteKey provided. Pass siteKey to DispatchProvider. Hooks will return empty/error state.\"\n );\n }\n }\n\n return (\n <DispatchContext.Provider value={value}>\n {children as React.ReactNode}\n </DispatchContext.Provider>\n );\n}\n","const DEFAULT_API_BASE = \"https://dispatch-cms.vercel.app\";\n\nexport function getApiBase(): string {\n return DEFAULT_API_BASE;\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { Post } from \"./types\";\nimport { useDispatchContext } from \"./context\";\n\nexport type UsePostResult = {\n post: Post | null;\n isLoading: boolean;\n error?: string;\n};\n\nexport function usePost(slug: string | undefined): UsePostResult {\n const ctx = useDispatchContext();\n const [post, setPost] = useState<Post | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n if (!slug?.trim()) {\n setPost(null);\n setIsLoading(false);\n setError(undefined);\n return;\n }\n\n if (!ctx?.siteKey) {\n setPost(null);\n setIsLoading(false);\n setError(\"Missing site key\");\n return;\n }\n\n let cancelled = false;\n setPost(null);\n setError(undefined);\n setIsLoading(true);\n\n const url = `${ctx.apiBase}/api/posts/${encodeURIComponent(slug.trim())}`;\n fetch(url, {\n headers: { \"X-Site-Key\": ctx.siteKey },\n })\n .then((res) => {\n if (cancelled) return;\n if (res.status === 404) {\n setPost(null);\n setIsLoading(false);\n return;\n }\n if (!res.ok) {\n setPost(null);\n setIsLoading(false);\n setError(\"Failed to load\");\n return;\n }\n return res.json();\n })\n .then((data) => {\n if (cancelled) return;\n setPost(data as Post);\n setIsLoading(false);\n })\n .catch(() => {\n if (cancelled) return;\n setPost(null);\n setIsLoading(false);\n setError(\"Failed to load\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [slug, ctx?.siteKey, ctx?.apiBase]);\n\n return { post, isLoading, error };\n}\n\nexport type UsePostsResult = {\n posts: Post[];\n isLoading: boolean;\n error?: string;\n};\n\nexport function usePosts(): UsePostsResult {\n const ctx = useDispatchContext();\n const [posts, setPosts] = useState<Post[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n if (!ctx?.siteKey) {\n setPosts([]);\n setIsLoading(false);\n setError(\"Missing site key\");\n return;\n }\n\n let cancelled = false;\n setPosts([]);\n setError(undefined);\n setIsLoading(true);\n\n const url = `${ctx.apiBase}/api/posts`;\n fetch(url, {\n headers: { \"X-Site-Key\": ctx.siteKey },\n })\n .then((res) => {\n if (cancelled) return;\n if (!res.ok) {\n setPosts([]);\n setIsLoading(false);\n setError(\"Failed to load\");\n return;\n }\n return res.json();\n })\n .then((data) => {\n if (cancelled) return;\n setPosts(Array.isArray(data) ? data : []);\n setIsLoading(false);\n })\n .catch(() => {\n if (cancelled) return;\n setPosts([]);\n setIsLoading(false);\n setError(\"Failed to load\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [ctx?.siteKey, ctx?.apiBase]);\n\n return { posts, isLoading, error };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/context.tsx","../src/config.ts","../src/hooks.ts"],"sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext } from \"react\";\nimport { getApiBase } from \"./config\";\n\ntype DispatchContextValue = {\n siteKey: string | null;\n apiBase: string;\n};\n\nconst DispatchContext = createContext<DispatchContextValue | null>(null);\n\nexport function useDispatchContext(): DispatchContextValue | null {\n return useContext(DispatchContext);\n}\n\ntype DispatchProviderProps = {\n siteKey?: string | null;\n apiBase?: string;\n children?: unknown;\n};\n\nexport function DispatchProvider({\n siteKey = null,\n apiBase = getApiBase(),\n children,\n}: DispatchProviderProps) {\n const value: DispatchContextValue = {\n siteKey: siteKey?.trim() || null,\n apiBase,\n };\n\n if (!value.siteKey) {\n if (typeof console !== \"undefined\" && console.warn) {\n console.warn(\n \"[Dispatch] No siteKey provided. Pass siteKey to DispatchProvider. Hooks will return empty/error state.\"\n );\n }\n }\n\n return (\n <DispatchContext.Provider value={value}>\n {children as React.ReactNode}\n </DispatchContext.Provider>\n );\n}\n","const DEFAULT_API_BASE = \"https://dispatch-cms.vercel.app\";\n\nexport function getApiBase(): string {\n return DEFAULT_API_BASE;\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { Entry } from \"./types\";\nimport { useDispatchContext } from \"./context\";\n\nexport type UseEntryResult = {\n entry: Entry | null;\n isLoading: boolean;\n error?: string;\n};\n\nexport function useEntry(collection: string | undefined, slug: string | undefined): UseEntryResult {\n const ctx = useDispatchContext();\n const [entry, setEntry] = useState<Entry | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n if (!collection?.trim() || !slug?.trim()) {\n setEntry(null);\n setIsLoading(false);\n setError(undefined);\n return;\n }\n\n if (!ctx?.siteKey) {\n setEntry(null);\n setIsLoading(false);\n setError(\"Missing site key\");\n return;\n }\n\n let cancelled = false;\n setEntry(null);\n setError(undefined);\n setIsLoading(true);\n\n const url = `${ctx.apiBase}/api/content/${encodeURIComponent(collection.trim())}/${encodeURIComponent(slug.trim())}`;\n fetch(url, {\n headers: { \"X-Site-Key\": ctx.siteKey },\n })\n .then((res) => {\n if (cancelled) return;\n if (res.status === 404) {\n setEntry(null);\n setIsLoading(false);\n return;\n }\n if (!res.ok) {\n setEntry(null);\n setIsLoading(false);\n setError(\"Failed to load\");\n return;\n }\n return res.json();\n })\n .then((data) => {\n if (cancelled || data == null) return;\n setEntry(data as Entry);\n setIsLoading(false);\n })\n .catch(() => {\n if (cancelled) return;\n setEntry(null);\n setIsLoading(false);\n setError(\"Failed to load\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [collection, slug, ctx?.siteKey, ctx?.apiBase]);\n\n return { entry, isLoading, error };\n}\n\nexport type UseEntriesResult = {\n entries: Entry[];\n isLoading: boolean;\n error?: string;\n};\n\nexport function useEntries(collection: string | undefined): UseEntriesResult {\n const ctx = useDispatchContext();\n const [entries, setEntries] = useState<Entry[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n if (!collection?.trim()) {\n setEntries([]);\n setIsLoading(false);\n setError(undefined);\n return;\n }\n\n if (!ctx?.siteKey) {\n setEntries([]);\n setIsLoading(false);\n setError(\"Missing site key\");\n return;\n }\n\n let cancelled = false;\n setEntries([]);\n setError(undefined);\n setIsLoading(true);\n\n const url = `${ctx.apiBase}/api/content/${encodeURIComponent(collection.trim())}`;\n fetch(url, {\n headers: { \"X-Site-Key\": ctx.siteKey },\n })\n .then((res) => {\n if (cancelled) return;\n if (!res.ok) {\n setEntries([]);\n setIsLoading(false);\n setError(\"Failed to load\");\n return;\n }\n return res.json();\n })\n .then((data) => {\n if (cancelled || data == null) return;\n setEntries(Array.isArray(data) ? data : []);\n setIsLoading(false);\n })\n .catch(() => {\n if (cancelled) return;\n setEntries([]);\n setIsLoading(false);\n setError(\"Failed to load\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [collection, ctx?.siteKey, ctx?.apiBase]);\n\n return { entries, isLoading, error };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dispatchcms/react",
3
- "version": "0.0.6",
4
- "description": "React hooks and provider for Dispatch CMS",
3
+ "version": "0.0.7",
4
+ "description": "React hooks and provider for Dispatch CMS entries",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
7
7
  "types": "./dist/index.d.ts",
@@ -12,9 +12,6 @@
12
12
  "require": "./dist/index.js"
13
13
  }
14
14
  },
15
- "scripts": {
16
- "build": "tsup"
17
- },
18
15
  "peerDependencies": {
19
16
  "react": ">=18.0.0"
20
17
  },
@@ -27,6 +24,15 @@
27
24
  "engines": {
28
25
  "node": ">=20.9"
29
26
  },
30
- "keywords": ["dispatch", "cms", "react", "nextjs", "content"],
31
- "license": "MIT"
32
- }
27
+ "keywords": [
28
+ "dispatch",
29
+ "cms",
30
+ "react",
31
+ "nextjs",
32
+ "content"
33
+ ],
34
+ "license": "MIT",
35
+ "scripts": {
36
+ "build": "tsup"
37
+ }
38
+ }
package/src/hooks.ts CHANGED
@@ -1,54 +1,54 @@
1
1
  "use client";
2
2
 
3
3
  import { useEffect, useState } from "react";
4
- import type { Post } from "./types";
4
+ import type { Entry } from "./types";
5
5
  import { useDispatchContext } from "./context";
6
6
 
7
- export type UsePostResult = {
8
- post: Post | null;
7
+ export type UseEntryResult = {
8
+ entry: Entry | null;
9
9
  isLoading: boolean;
10
10
  error?: string;
11
11
  };
12
12
 
13
- export function usePost(slug: string | undefined): UsePostResult {
13
+ export function useEntry(collection: string | undefined, slug: string | undefined): UseEntryResult {
14
14
  const ctx = useDispatchContext();
15
- const [post, setPost] = useState<Post | null>(null);
15
+ const [entry, setEntry] = useState<Entry | null>(null);
16
16
  const [isLoading, setIsLoading] = useState(true);
17
17
  const [error, setError] = useState<string | undefined>(undefined);
18
18
 
19
19
  useEffect(() => {
20
- if (!slug?.trim()) {
21
- setPost(null);
20
+ if (!collection?.trim() || !slug?.trim()) {
21
+ setEntry(null);
22
22
  setIsLoading(false);
23
23
  setError(undefined);
24
24
  return;
25
25
  }
26
26
 
27
27
  if (!ctx?.siteKey) {
28
- setPost(null);
28
+ setEntry(null);
29
29
  setIsLoading(false);
30
30
  setError("Missing site key");
31
31
  return;
32
32
  }
33
33
 
34
34
  let cancelled = false;
35
- setPost(null);
35
+ setEntry(null);
36
36
  setError(undefined);
37
37
  setIsLoading(true);
38
38
 
39
- const url = `${ctx.apiBase}/api/posts/${encodeURIComponent(slug.trim())}`;
39
+ const url = `${ctx.apiBase}/api/content/${encodeURIComponent(collection.trim())}/${encodeURIComponent(slug.trim())}`;
40
40
  fetch(url, {
41
41
  headers: { "X-Site-Key": ctx.siteKey },
42
42
  })
43
43
  .then((res) => {
44
44
  if (cancelled) return;
45
45
  if (res.status === 404) {
46
- setPost(null);
46
+ setEntry(null);
47
47
  setIsLoading(false);
48
48
  return;
49
49
  }
50
50
  if (!res.ok) {
51
- setPost(null);
51
+ setEntry(null);
52
52
  setIsLoading(false);
53
53
  setError("Failed to load");
54
54
  return;
@@ -56,13 +56,13 @@ export function usePost(slug: string | undefined): UsePostResult {
56
56
  return res.json();
57
57
  })
58
58
  .then((data) => {
59
- if (cancelled) return;
60
- setPost(data as Post);
59
+ if (cancelled || data == null) return;
60
+ setEntry(data as Entry);
61
61
  setIsLoading(false);
62
62
  })
63
63
  .catch(() => {
64
64
  if (cancelled) return;
65
- setPost(null);
65
+ setEntry(null);
66
66
  setIsLoading(false);
67
67
  setError("Failed to load");
68
68
  });
@@ -70,44 +70,51 @@ export function usePost(slug: string | undefined): UsePostResult {
70
70
  return () => {
71
71
  cancelled = true;
72
72
  };
73
- }, [slug, ctx?.siteKey, ctx?.apiBase]);
73
+ }, [collection, slug, ctx?.siteKey, ctx?.apiBase]);
74
74
 
75
- return { post, isLoading, error };
75
+ return { entry, isLoading, error };
76
76
  }
77
77
 
78
- export type UsePostsResult = {
79
- posts: Post[];
78
+ export type UseEntriesResult = {
79
+ entries: Entry[];
80
80
  isLoading: boolean;
81
81
  error?: string;
82
82
  };
83
83
 
84
- export function usePosts(): UsePostsResult {
84
+ export function useEntries(collection: string | undefined): UseEntriesResult {
85
85
  const ctx = useDispatchContext();
86
- const [posts, setPosts] = useState<Post[]>([]);
86
+ const [entries, setEntries] = useState<Entry[]>([]);
87
87
  const [isLoading, setIsLoading] = useState(true);
88
88
  const [error, setError] = useState<string | undefined>(undefined);
89
89
 
90
90
  useEffect(() => {
91
+ if (!collection?.trim()) {
92
+ setEntries([]);
93
+ setIsLoading(false);
94
+ setError(undefined);
95
+ return;
96
+ }
97
+
91
98
  if (!ctx?.siteKey) {
92
- setPosts([]);
99
+ setEntries([]);
93
100
  setIsLoading(false);
94
101
  setError("Missing site key");
95
102
  return;
96
103
  }
97
104
 
98
105
  let cancelled = false;
99
- setPosts([]);
106
+ setEntries([]);
100
107
  setError(undefined);
101
108
  setIsLoading(true);
102
109
 
103
- const url = `${ctx.apiBase}/api/posts`;
110
+ const url = `${ctx.apiBase}/api/content/${encodeURIComponent(collection.trim())}`;
104
111
  fetch(url, {
105
112
  headers: { "X-Site-Key": ctx.siteKey },
106
113
  })
107
114
  .then((res) => {
108
115
  if (cancelled) return;
109
116
  if (!res.ok) {
110
- setPosts([]);
117
+ setEntries([]);
111
118
  setIsLoading(false);
112
119
  setError("Failed to load");
113
120
  return;
@@ -115,13 +122,13 @@ export function usePosts(): UsePostsResult {
115
122
  return res.json();
116
123
  })
117
124
  .then((data) => {
118
- if (cancelled) return;
119
- setPosts(Array.isArray(data) ? data : []);
125
+ if (cancelled || data == null) return;
126
+ setEntries(Array.isArray(data) ? data : []);
120
127
  setIsLoading(false);
121
128
  })
122
129
  .catch(() => {
123
130
  if (cancelled) return;
124
- setPosts([]);
131
+ setEntries([]);
125
132
  setIsLoading(false);
126
133
  setError("Failed to load");
127
134
  });
@@ -129,7 +136,7 @@ export function usePosts(): UsePostsResult {
129
136
  return () => {
130
137
  cancelled = true;
131
138
  };
132
- }, [ctx?.siteKey, ctx?.apiBase]);
139
+ }, [collection, ctx?.siteKey, ctx?.apiBase]);
133
140
 
134
- return { posts, isLoading, error };
141
+ return { entries, isLoading, error };
135
142
  }
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type { Post } from "./types";
1
+ export type { Entry } from "./types";
2
2
  export { DispatchProvider, useDispatchContext } from "./context";
3
- export { usePost, usePosts } from "./hooks";
4
- export type { UsePostResult, UsePostsResult } from "./hooks";
3
+ export { useEntry, useEntries } from "./hooks";
4
+ export type { UseEntryResult, UseEntriesResult } from "./hooks";
package/src/types.ts CHANGED
@@ -1,13 +1,13 @@
1
- export type Post = {
1
+ export type Entry = {
2
2
  id: string;
3
3
  created_at: string;
4
- published_at: string;
4
+ published_at: string | null;
5
5
  updated_at: string;
6
6
  site_id: string;
7
+ collection: string;
7
8
  title: string;
8
- slug: string;
9
- content: unknown;
10
- excerpt: string | null;
11
- featured_image: string | null;
9
+ slug: string | null;
10
+ data: Record<string, unknown>;
11
+ sort_order: number;
12
12
  published: boolean;
13
13
  };