@cedros/data-react 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.
@@ -1,4 +1,4 @@
1
- import { fetchJson, resolveServerUrl } from "./fetch.js";
1
+ import { fetchJson, resolveApiKey, resolveServerUrl } from "./fetch.js";
2
2
  /**
3
3
  * Fetches a single blog post by slug, optionally passing visitor_id for metered reads.
4
4
  *
@@ -8,6 +8,7 @@ import { fetchJson, resolveServerUrl } from "./fetch.js";
8
8
  */
9
9
  export async function fetchBlogPost(slug, options) {
10
10
  const serverUrl = resolveServerUrl(options);
11
+ const apiKey = resolveApiKey(options);
11
12
  const body = {
12
13
  collection_name: "blog",
13
14
  entry_keys: [slug],
@@ -20,6 +21,7 @@ export async function fetchBlogPost(slug, options) {
20
21
  const entries = await fetchJson(serverUrl, "/entries/query", {
21
22
  method: "POST",
22
23
  body,
24
+ apiKey,
23
25
  });
24
26
  return entries.length > 0 ? entries[0] : null;
25
27
  }
@@ -1,4 +1,8 @@
1
1
  import type { ServerFetchOptions } from "./types.js";
2
+ /**
3
+ * Resolves an optional API key from options or the CEDROS_X_API_KEY env var.
4
+ */
5
+ export declare function resolveApiKey(options?: ServerFetchOptions): string | undefined;
2
6
  /**
3
7
  * Resolves the cedros-data server URL from options or environment.
4
8
  * Throws if no URL is available.
@@ -8,4 +12,5 @@ export declare function resolveServerUrl(options?: ServerFetchOptions): string;
8
12
  export declare function fetchJson<T>(serverUrl: string, path: string, init?: {
9
13
  method?: string;
10
14
  body?: unknown;
15
+ apiKey?: string;
11
16
  }): Promise<T>;
@@ -1,3 +1,12 @@
1
+ /**
2
+ * Resolves an optional API key from options or the CEDROS_X_API_KEY env var.
3
+ */
4
+ export function resolveApiKey(options) {
5
+ return (options?.apiKey ??
6
+ (typeof process !== "undefined"
7
+ ? process.env.CEDROS_X_API_KEY
8
+ : undefined));
9
+ }
1
10
  /**
2
11
  * Resolves the cedros-data server URL from options or environment.
3
12
  * Throws if no URL is available.
@@ -18,6 +27,9 @@ export async function fetchJson(serverUrl, path, init) {
18
27
  const headers = {
19
28
  "Content-Type": "application/json",
20
29
  };
30
+ if (init?.apiKey) {
31
+ headers["x-api-key"] = init.apiKey;
32
+ }
21
33
  const response = await fetch(`${serverUrl}${path}`, {
22
34
  method: init?.method ?? "GET",
23
35
  headers,
@@ -1,4 +1,4 @@
1
- import { fetchJson, resolveServerUrl } from "./fetch.js";
1
+ import { fetchJson, resolveApiKey, resolveServerUrl } from "./fetch.js";
2
2
  /** Resolves a field from the wrapped payload or flat top-level. */
3
3
  function field(page, key) {
4
4
  const rec = page;
@@ -65,6 +65,7 @@ export function buildPageMetadata(page, options) {
65
65
  */
66
66
  export async function generatePageMetadata(slug, options) {
67
67
  const serverUrl = resolveServerUrl(options);
68
+ const apiKey = resolveApiKey(options);
68
69
  const collection = options?.collection ?? "pages";
69
70
  const entries = await fetchJson(serverUrl, "/entries/query", {
70
71
  method: "POST",
@@ -74,13 +75,14 @@ export async function generatePageMetadata(slug, options) {
74
75
  limit: 1,
75
76
  offset: 0,
76
77
  },
78
+ apiKey,
77
79
  });
78
80
  if (entries.length === 0) {
79
81
  return { title: slug };
80
82
  }
81
83
  let siteData = options?.siteData;
82
84
  if (!siteData) {
83
- siteData = await fetchSiteData(serverUrl);
85
+ siteData = await fetchSiteData(serverUrl, apiKey);
84
86
  }
85
87
  return buildPageMetadata(entries[0], {
86
88
  ...options,
@@ -88,7 +90,7 @@ export async function generatePageMetadata(slug, options) {
88
90
  path: options?.path ?? `/${slug}`,
89
91
  });
90
92
  }
91
- async function fetchSiteData(serverUrl) {
93
+ async function fetchSiteData(serverUrl, apiKey) {
92
94
  try {
93
95
  const entries = await fetchJson(serverUrl, "/entries/query", {
94
96
  method: "POST",
@@ -98,6 +100,7 @@ async function fetchSiteData(serverUrl) {
98
100
  limit: 1,
99
101
  offset: 0,
100
102
  },
103
+ apiKey,
101
104
  });
102
105
  if (entries.length > 0) {
103
106
  return entries[0].payload;
@@ -1,4 +1,4 @@
1
- import { fetchJson, resolveServerUrl } from "./fetch.js";
1
+ import { fetchJson, resolveApiKey, resolveServerUrl } from "./fetch.js";
2
2
  /** Map of content types to their collection names in cedros-data. */
3
3
  const CONTENT_TYPE_COLLECTIONS = {
4
4
  page: "pages",
@@ -51,8 +51,9 @@ const ALL_CONTENT_TYPES = [
51
51
  */
52
52
  export async function loadSitemapEntries(options) {
53
53
  const serverUrl = resolveServerUrl(options);
54
+ const apiKey = resolveApiKey(options);
54
55
  const contentTypes = options?.contentTypes ?? ALL_CONTENT_TYPES;
55
- const results = await Promise.allSettled(contentTypes.map((ct) => fetchCollectionSlugs(serverUrl, ct)));
56
+ const results = await Promise.allSettled(contentTypes.map((ct) => fetchCollectionSlugs(serverUrl, ct, apiKey)));
56
57
  const entries = [];
57
58
  for (let i = 0; i < results.length; i++) {
58
59
  const result = results[i];
@@ -65,7 +66,7 @@ export async function loadSitemapEntries(options) {
65
66
  }
66
67
  return entries;
67
68
  }
68
- async function fetchCollectionSlugs(serverUrl, contentType) {
69
+ async function fetchCollectionSlugs(serverUrl, contentType, apiKey) {
69
70
  const collectionName = CONTENT_TYPE_COLLECTIONS[contentType];
70
71
  const defaults = CONTENT_TYPE_DEFAULTS[contentType];
71
72
  const records = await fetchJson(serverUrl, "/entries/query", {
@@ -75,6 +76,7 @@ async function fetchCollectionSlugs(serverUrl, contentType) {
75
76
  limit: 1000,
76
77
  offset: 0,
77
78
  },
79
+ apiKey,
78
80
  });
79
81
  return records.map((record) => {
80
82
  const slug = record.payload.slug ??
@@ -1,4 +1,4 @@
1
- import { fetchJson, resolveServerUrl } from "./fetch.js";
1
+ import { fetchJson, resolveApiKey, resolveServerUrl } from "./fetch.js";
2
2
  /** Map of content types to their collection names in cedros-data. */
3
3
  const CONTENT_TYPE_COLLECTIONS = {
4
4
  page: "pages",
@@ -25,6 +25,7 @@ const CONTENT_TYPE_COLLECTIONS = {
25
25
  */
26
26
  export async function listContentSlugs(contentType, options) {
27
27
  const serverUrl = resolveServerUrl(options);
28
+ const apiKey = resolveApiKey(options);
28
29
  const collectionName = CONTENT_TYPE_COLLECTIONS[contentType];
29
30
  const records = await fetchJson(serverUrl, "/entries/query", {
30
31
  method: "POST",
@@ -33,6 +34,7 @@ export async function listContentSlugs(contentType, options) {
33
34
  limit: 1000,
34
35
  offset: 0,
35
36
  },
37
+ apiKey,
36
38
  });
37
39
  return records.map((record) => record.payload.slug ?? record.entry_key);
38
40
  }
@@ -92,6 +92,8 @@ export interface MeteredReadsInfo {
92
92
  export interface ServerFetchOptions {
93
93
  /** Base URL of the cedros-data server. Falls back to CEDROS_DATA_URL env var. */
94
94
  serverUrl?: string;
95
+ /** API key sent as x-api-key header. Falls back to CEDROS_X_API_KEY env var. */
96
+ apiKey?: string;
95
97
  /** Visitor ID for metered-reads tracking. Use `getOrCreateVisitorId()` on the client. */
96
98
  visitorId?: string;
97
99
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedros/data-react",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "React components, page templates, and Next.js integration for cedros-data",
5
5
  "type": "module",
6
6
  "main": "./dist/react/index.js",