@sleekcms/client 2.3.1 → 3.0.0

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
@@ -13,9 +13,9 @@ npm install @sleekcms/client
13
13
  ## Quick Start
14
14
 
15
15
  ```typescript
16
- import { createClient } from '@sleekcms/client';
16
+ import { createSyncClient } from '@sleekcms/client';
17
17
 
18
- const client = await createClient({
18
+ const client = await createSyncClient({
19
19
  siteToken: 'your-site-token',
20
20
  env: 'latest'
21
21
  });
@@ -34,11 +34,11 @@ const footer = client.getEntry('footer');
34
34
 
35
35
  ### Sync Client (Recommended for SSG)
36
36
 
37
- **`createClient()`** fetches all content upfront and returns a client with synchronous methods. Best for static site generation where you build once and want instant access to content.
37
+ **`createSyncClient()`** fetches all content upfront and returns a client with synchronous methods. Best for static site generation where you build once and want instant access to content.
38
38
 
39
39
  ```typescript
40
40
  // Async initialization, sync usage
41
- const client = await createClient({
41
+ const client = await createSyncClient({
42
42
  siteToken: 'your-site-token'
43
43
  });
44
44
 
@@ -59,7 +59,7 @@ const slugs = client.getSlugs('/blog');
59
59
  ```typescript
60
60
  const client = createAsyncClient({
61
61
  siteToken: 'your-site-token',
62
- cdn: true // optional: cache-friendly URLs
62
+ resolveEnv: true // optional: cache-friendly URLs
63
63
  });
64
64
 
65
65
  // All methods are async
@@ -78,8 +78,8 @@ const posts = await client.getPages('/blog');
78
78
  |--------|------|---------|-------------|
79
79
  | `siteToken` | `string` | required | Your site token from SleekCMS |
80
80
  | `env` | `string` | `'latest'` | Environment/alias name |
81
- | `cdn` | `boolean` | `false` | Resolve env name to bypass CDN cache. Adds latency. |
82
- | `lang` | `string` | - | Language code for internationalized content (e.g., `'en'`, `'es'`, `'fr'`) |
81
+ | `resolveEnv` | `boolean` | `false` | Env is an alias to version. This flag resolves env to version tag, so as to bypass CDN cache. Add's some latency.|
82
+ | `lang` | `string` | - | Language code for internationalized content |
83
83
  | `cache` | `SyncCacheAdapter \| AsyncCacheAdapter` | In-memory cache | Custom cache adapter for storing fetched content |
84
84
  | `cacheMinutes` | `number` | - | Cache expiration time in minutes. If not set, cache never expires |
85
85
 
@@ -87,7 +87,7 @@ const posts = await client.getPages('/blog');
87
87
 
88
88
  ```typescript
89
89
  // Fetch Spanish content
90
- const client = await createClient({
90
+ const client = await createSyncClient({
91
91
  siteToken: 'your-site-token',
92
92
  lang: 'es'
93
93
  });
@@ -103,7 +103,7 @@ The client includes built-in caching support to improve performance and reduce A
103
103
  ### Default In-Memory Cache
104
104
 
105
105
  ```typescript
106
- const client = await createClient({
106
+ const client = await createSyncClient({
107
107
  siteToken: 'your-site-token'
108
108
  });
109
109
  // Uses built-in memory cache automatically
@@ -112,7 +112,7 @@ const client = await createClient({
112
112
  ### Using localStorage
113
113
 
114
114
  ```typescript
115
- const client = await createClient({
115
+ const client = await createSyncClient({
116
116
  siteToken: 'your-site-token',
117
117
  cache: localStorage, // Use browser's localStorage
118
118
  cacheMinutes: 60*24 // Cache expires after 1 day
@@ -142,7 +142,7 @@ interface AsyncCacheAdapter {
142
142
  Use `cacheMinutes` to set when cached content expires:
143
143
 
144
144
  ```typescript
145
- const client = await createClient({
145
+ const client = await createSyncClient({
146
146
  siteToken: 'your-site-token',
147
147
  cache: localStorage,
148
148
  cacheMinutes: 60*24 // Cache expires after 1 day
@@ -228,10 +228,10 @@ const categories = client.getOptions('categories');
228
228
 
229
229
  ```typescript
230
230
  // app/blog/page.tsx
231
- import { createClient } from '@sleekcms/client';
231
+ import { createSyncClient } from '@sleekcms/client';
232
232
 
233
233
  export default async function BlogPage() {
234
- const client = await createClient({
234
+ const client = await createSyncClient({
235
235
  siteToken: process.env.SLEEKCMS_SITE_TOKEN!
236
236
  });
237
237
 
@@ -253,10 +253,10 @@ export default async function BlogPage() {
253
253
 
254
254
  ```typescript
255
255
  // app/blog/[slug]/page.tsx
256
- import { createClient } from '@sleekcms/client';
256
+ import { createSyncClient } from '@sleekcms/client';
257
257
 
258
258
  export async function generateStaticParams() {
259
- const client = await createClient({
259
+ const client = await createSyncClient({
260
260
  siteToken: process.env.SLEEKCMS_SITE_TOKEN!
261
261
  });
262
262
 
@@ -266,7 +266,7 @@ export async function generateStaticParams() {
266
266
  }
267
267
 
268
268
  export default async function Post({ params }: { params: { slug: string } }) {
269
- const client = await createClient({
269
+ const client = await createSyncClient({
270
270
  siteToken: process.env.SLEEKCMS_SITE_TOKEN!
271
271
  });
272
272
 
@@ -284,7 +284,7 @@ import { createAsyncClient } from '@sleekcms/client';
284
284
 
285
285
  const client = createAsyncClient({
286
286
  siteToken: process.env.SLEEKCMS_SITE_TOKEN,
287
- cdn: true
287
+ resolveEnv: true
288
288
  });
289
289
 
290
290
  export async function load() {
@@ -298,9 +298,9 @@ export async function load() {
298
298
  ```astro
299
299
  ---
300
300
  // src/pages/blog/index.astro
301
- import { createClient } from '@sleekcms/client';
301
+ import { createSyncClient } from '@sleekcms/client';
302
302
 
303
- const client = await createClient({
303
+ const client = await createSyncClient({
304
304
  siteToken: import.meta.env.SLEEKCMS_SITE_TOKEN
305
305
  });
306
306
 
package/index.cjs CHANGED
@@ -30,12 +30,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  var index_exports = {};
31
31
  __export(index_exports, {
32
32
  createAsyncClient: () => createAsyncClient,
33
- createClient: () => createClient
33
+ createSyncClient: () => createSyncClient
34
34
  });
35
35
  module.exports = __toCommonJS(index_exports);
36
36
 
37
37
  // src/lib.ts
38
38
  var jmespath = __toESM(require("jmespath"), 1);
39
+ var envTagCache = /* @__PURE__ */ new Map();
39
40
  function getBaseUrl(token, devEnv) {
40
41
  let [env, siteId, ...rest] = token.split("-");
41
42
  if (devEnv === "production") return `https://pub.sleekcms.com/${siteId}`;
@@ -76,11 +77,20 @@ async function fetchEnvTag({ siteToken, env }) {
76
77
  return env;
77
78
  }
78
79
  async function fetchSiteContent(options) {
79
- const { siteToken, env = "latest", cdn = false, search: search2, lang, cache, cacheMinutes } = options;
80
+ const { siteToken, env = "latest", resolveEnv = false, search: search2, lang, cache, cacheMinutes } = options;
80
81
  let url = getUrl({ siteToken, env, search: search2, lang });
81
- if (cdn && !search2) {
82
- let tag = await fetchEnvTag({ siteToken, env });
83
- url = getUrl({ siteToken, env: tag, search: search2, lang });
82
+ if (!resolveEnv) {
83
+ const cacheKey2 = `${siteToken}:${env}`;
84
+ let tag = envTagCache.get(cacheKey2);
85
+ try {
86
+ if (!tag) {
87
+ tag = await fetchEnvTag({ siteToken, env });
88
+ envTagCache.set(cacheKey2, tag);
89
+ }
90
+ url = getUrl({ siteToken, env: tag, search: search2, lang });
91
+ } catch (error) {
92
+ console.warn("[SleekCMS] Failed to resolve env tag, using cached content instead.");
93
+ }
84
94
  }
85
95
  const cacheKey = url;
86
96
  const fetchAndCache = async () => {
@@ -123,7 +133,11 @@ async function fetchSiteContent(options) {
123
133
  const expiryMs = cacheMinutes * 60 * 1e3;
124
134
  const age = now - cachedData._ts;
125
135
  if (age >= expiryMs) {
126
- return await fetchAndCache();
136
+ try {
137
+ return await fetchAndCache();
138
+ } catch (error) {
139
+ console.warn("[SleekCMS] Fetch failed, using expired cache:", error);
140
+ }
127
141
  }
128
142
  }
129
143
  return cachedData.data;
@@ -168,7 +182,7 @@ var MemoryCache = class {
168
182
  this.cache.set(key, value);
169
183
  }
170
184
  };
171
- async function createClient(options) {
185
+ async function createSyncClient(options) {
172
186
  const cache = options.cache ?? new MemoryCache();
173
187
  const data = await fetchSiteContent({ ...options, cache });
174
188
  function getContent(query) {
@@ -226,30 +240,26 @@ async function createClient(options) {
226
240
  };
227
241
  }
228
242
  function createAsyncClient(options) {
229
- const { siteToken, env = "latest", cdn, lang } = options;
243
+ const { siteToken, env = "latest", resolveEnv, lang } = options;
230
244
  const cache = options.cache ?? new MemoryCache();
231
245
  let syncClient = null;
232
- let tag = null;
233
246
  async function getContent(search2) {
234
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
235
247
  if (!search2 && !syncClient) {
236
- syncClient = await createClient({ siteToken, env: tag ?? env, cdn, lang, cache });
248
+ syncClient = await createSyncClient({ siteToken, env, resolveEnv, lang, cache });
237
249
  }
238
250
  if (syncClient) return syncClient.getContent(search2);
239
251
  if (!search2) return null;
240
- return await fetchSiteContent({ siteToken, env: tag ?? env, search: search2, lang, cache });
252
+ return await fetchSiteContent({ siteToken, env, search: search2, lang, cache, resolveEnv });
241
253
  }
242
254
  async function getPages(path) {
243
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
244
255
  if (syncClient) return syncClient.getPages(path);
245
- const pages = await fetchSiteContent({ siteToken, env: tag ?? env, search: "pages", lang, cache });
256
+ const pages = await fetchSiteContent({ siteToken, env, search: "pages", lang, cache, resolveEnv });
246
257
  if (!path) return pages;
247
258
  else return filterPagesByPath(pages, path);
248
259
  }
249
260
  async function getPage(path) {
250
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
251
261
  if (syncClient) return syncClient.getPage(path);
252
- const pages = await fetchSiteContent({ siteToken, env: tag ?? env, search: "pages", lang, cache });
262
+ const pages = await fetchSiteContent({ siteToken, env, search: "pages", lang, cache, resolveEnv });
253
263
  const page = pages == null ? void 0 : pages.find((p) => {
254
264
  const pth = typeof p._path === "string" ? p._path : "";
255
265
  return pth === path;
@@ -257,27 +267,23 @@ function createAsyncClient(options) {
257
267
  return page ?? null;
258
268
  }
259
269
  async function getEntry(handle) {
260
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
261
270
  if (syncClient) return syncClient.getEntry(handle);
262
271
  let search2 = `entries.${handle}`;
263
- return await fetchSiteContent({ siteToken, env: tag ?? env, search: search2, lang, cache });
272
+ return await fetchSiteContent({ siteToken, env, search: search2, lang, cache, resolveEnv });
264
273
  }
265
274
  async function getSlugs(path) {
266
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
267
275
  if (syncClient) return syncClient.getSlugs(path);
268
- const pages = await fetchSiteContent({ siteToken, env: tag ?? env, search: "pages", lang, cache });
276
+ const pages = await fetchSiteContent({ siteToken, env, search: "pages", lang, cache, resolveEnv });
269
277
  return extractSlugs(pages, path);
270
278
  }
271
279
  async function getImage(name) {
272
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
273
280
  if (syncClient) return syncClient.getImage(name);
274
- const images = await fetchSiteContent({ siteToken, env: tag ?? env, search: "images", lang, cache });
281
+ const images = await fetchSiteContent({ siteToken, env, search: "images", lang, cache, resolveEnv });
275
282
  return images ? images[name] : null;
276
283
  }
277
284
  async function getOptions(name) {
278
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
279
285
  if (syncClient) return syncClient.getOptions(name);
280
- const options2 = await fetchSiteContent({ siteToken, env: tag ?? env, search: "options", lang, cache });
286
+ const options2 = await fetchSiteContent({ siteToken, env, search: "options", lang, cache, resolveEnv });
281
287
  const optionSet = options2[name];
282
288
  return Array.isArray(optionSet) ? optionSet : null;
283
289
  }
@@ -303,5 +309,5 @@ function createAsyncClient(options) {
303
309
  // Annotate the CommonJS export names for ESM import in node:
304
310
  0 && (module.exports = {
305
311
  createAsyncClient,
306
- createClient
312
+ createSyncClient
307
313
  });
package/index.d.cts CHANGED
@@ -33,7 +33,7 @@ interface AsyncCacheAdapter {
33
33
  interface ClientOptions {
34
34
  siteToken: string;
35
35
  env?: string;
36
- cdn?: boolean;
36
+ resolveEnv?: boolean;
37
37
  lang?: string;
38
38
  cache?: SyncCacheAdapter | AsyncCacheAdapter;
39
39
  cacheMinutes?: number;
@@ -59,7 +59,7 @@ interface SleekAsyncClient {
59
59
  _getEnvTag(): Promise<string>;
60
60
  }
61
61
 
62
- declare function createClient(options: ClientOptions): Promise<SleekClient>;
62
+ declare function createSyncClient(options: ClientOptions): Promise<SleekClient>;
63
63
  declare function createAsyncClient(options: ClientOptions): SleekAsyncClient | any;
64
64
 
65
- export { type AsyncCacheAdapter, type ClientOptions, type Entry, type Image, type Options, type Page, type SleekAsyncClient, type SleekClient, type SleekSiteContent, type SyncCacheAdapter, createAsyncClient, createClient };
65
+ export { type AsyncCacheAdapter, type ClientOptions, type Entry, type Image, type Options, type Page, type SleekAsyncClient, type SleekClient, type SleekSiteContent, type SyncCacheAdapter, createAsyncClient, createSyncClient };
package/index.d.ts CHANGED
@@ -33,7 +33,7 @@ interface AsyncCacheAdapter {
33
33
  interface ClientOptions {
34
34
  siteToken: string;
35
35
  env?: string;
36
- cdn?: boolean;
36
+ resolveEnv?: boolean;
37
37
  lang?: string;
38
38
  cache?: SyncCacheAdapter | AsyncCacheAdapter;
39
39
  cacheMinutes?: number;
@@ -59,7 +59,7 @@ interface SleekAsyncClient {
59
59
  _getEnvTag(): Promise<string>;
60
60
  }
61
61
 
62
- declare function createClient(options: ClientOptions): Promise<SleekClient>;
62
+ declare function createSyncClient(options: ClientOptions): Promise<SleekClient>;
63
63
  declare function createAsyncClient(options: ClientOptions): SleekAsyncClient | any;
64
64
 
65
- export { type AsyncCacheAdapter, type ClientOptions, type Entry, type Image, type Options, type Page, type SleekAsyncClient, type SleekClient, type SleekSiteContent, type SyncCacheAdapter, createAsyncClient, createClient };
65
+ export { type AsyncCacheAdapter, type ClientOptions, type Entry, type Image, type Options, type Page, type SleekAsyncClient, type SleekClient, type SleekSiteContent, type SyncCacheAdapter, createAsyncClient, createSyncClient };
package/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/lib.ts
2
2
  import * as jmespath from "jmespath";
3
+ var envTagCache = /* @__PURE__ */ new Map();
3
4
  function getBaseUrl(token, devEnv) {
4
5
  let [env, siteId, ...rest] = token.split("-");
5
6
  if (devEnv === "production") return `https://pub.sleekcms.com/${siteId}`;
@@ -40,11 +41,20 @@ async function fetchEnvTag({ siteToken, env }) {
40
41
  return env;
41
42
  }
42
43
  async function fetchSiteContent(options) {
43
- const { siteToken, env = "latest", cdn = false, search: search2, lang, cache, cacheMinutes } = options;
44
+ const { siteToken, env = "latest", resolveEnv = false, search: search2, lang, cache, cacheMinutes } = options;
44
45
  let url = getUrl({ siteToken, env, search: search2, lang });
45
- if (cdn && !search2) {
46
- let tag = await fetchEnvTag({ siteToken, env });
47
- url = getUrl({ siteToken, env: tag, search: search2, lang });
46
+ if (!resolveEnv) {
47
+ const cacheKey2 = `${siteToken}:${env}`;
48
+ let tag = envTagCache.get(cacheKey2);
49
+ try {
50
+ if (!tag) {
51
+ tag = await fetchEnvTag({ siteToken, env });
52
+ envTagCache.set(cacheKey2, tag);
53
+ }
54
+ url = getUrl({ siteToken, env: tag, search: search2, lang });
55
+ } catch (error) {
56
+ console.warn("[SleekCMS] Failed to resolve env tag, using cached content instead.");
57
+ }
48
58
  }
49
59
  const cacheKey = url;
50
60
  const fetchAndCache = async () => {
@@ -87,7 +97,11 @@ async function fetchSiteContent(options) {
87
97
  const expiryMs = cacheMinutes * 60 * 1e3;
88
98
  const age = now - cachedData._ts;
89
99
  if (age >= expiryMs) {
90
- return await fetchAndCache();
100
+ try {
101
+ return await fetchAndCache();
102
+ } catch (error) {
103
+ console.warn("[SleekCMS] Fetch failed, using expired cache:", error);
104
+ }
91
105
  }
92
106
  }
93
107
  return cachedData.data;
@@ -132,7 +146,7 @@ var MemoryCache = class {
132
146
  this.cache.set(key, value);
133
147
  }
134
148
  };
135
- async function createClient(options) {
149
+ async function createSyncClient(options) {
136
150
  const cache = options.cache ?? new MemoryCache();
137
151
  const data = await fetchSiteContent({ ...options, cache });
138
152
  function getContent(query) {
@@ -190,30 +204,26 @@ async function createClient(options) {
190
204
  };
191
205
  }
192
206
  function createAsyncClient(options) {
193
- const { siteToken, env = "latest", cdn, lang } = options;
207
+ const { siteToken, env = "latest", resolveEnv, lang } = options;
194
208
  const cache = options.cache ?? new MemoryCache();
195
209
  let syncClient = null;
196
- let tag = null;
197
210
  async function getContent(search2) {
198
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
199
211
  if (!search2 && !syncClient) {
200
- syncClient = await createClient({ siteToken, env: tag ?? env, cdn, lang, cache });
212
+ syncClient = await createSyncClient({ siteToken, env, resolveEnv, lang, cache });
201
213
  }
202
214
  if (syncClient) return syncClient.getContent(search2);
203
215
  if (!search2) return null;
204
- return await fetchSiteContent({ siteToken, env: tag ?? env, search: search2, lang, cache });
216
+ return await fetchSiteContent({ siteToken, env, search: search2, lang, cache, resolveEnv });
205
217
  }
206
218
  async function getPages(path) {
207
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
208
219
  if (syncClient) return syncClient.getPages(path);
209
- const pages = await fetchSiteContent({ siteToken, env: tag ?? env, search: "pages", lang, cache });
220
+ const pages = await fetchSiteContent({ siteToken, env, search: "pages", lang, cache, resolveEnv });
210
221
  if (!path) return pages;
211
222
  else return filterPagesByPath(pages, path);
212
223
  }
213
224
  async function getPage(path) {
214
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
215
225
  if (syncClient) return syncClient.getPage(path);
216
- const pages = await fetchSiteContent({ siteToken, env: tag ?? env, search: "pages", lang, cache });
226
+ const pages = await fetchSiteContent({ siteToken, env, search: "pages", lang, cache, resolveEnv });
217
227
  const page = pages == null ? void 0 : pages.find((p) => {
218
228
  const pth = typeof p._path === "string" ? p._path : "";
219
229
  return pth === path;
@@ -221,27 +231,23 @@ function createAsyncClient(options) {
221
231
  return page ?? null;
222
232
  }
223
233
  async function getEntry(handle) {
224
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
225
234
  if (syncClient) return syncClient.getEntry(handle);
226
235
  let search2 = `entries.${handle}`;
227
- return await fetchSiteContent({ siteToken, env: tag ?? env, search: search2, lang, cache });
236
+ return await fetchSiteContent({ siteToken, env, search: search2, lang, cache, resolveEnv });
228
237
  }
229
238
  async function getSlugs(path) {
230
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
231
239
  if (syncClient) return syncClient.getSlugs(path);
232
- const pages = await fetchSiteContent({ siteToken, env: tag ?? env, search: "pages", lang, cache });
240
+ const pages = await fetchSiteContent({ siteToken, env, search: "pages", lang, cache, resolveEnv });
233
241
  return extractSlugs(pages, path);
234
242
  }
235
243
  async function getImage(name) {
236
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
237
244
  if (syncClient) return syncClient.getImage(name);
238
- const images = await fetchSiteContent({ siteToken, env: tag ?? env, search: "images", lang, cache });
245
+ const images = await fetchSiteContent({ siteToken, env, search: "images", lang, cache, resolveEnv });
239
246
  return images ? images[name] : null;
240
247
  }
241
248
  async function getOptions(name) {
242
- if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
243
249
  if (syncClient) return syncClient.getOptions(name);
244
- const options2 = await fetchSiteContent({ siteToken, env: tag ?? env, search: "options", lang, cache });
250
+ const options2 = await fetchSiteContent({ siteToken, env, search: "options", lang, cache, resolveEnv });
245
251
  const optionSet = options2[name];
246
252
  return Array.isArray(optionSet) ? optionSet : null;
247
253
  }
@@ -266,5 +272,5 @@ function createAsyncClient(options) {
266
272
  }
267
273
  export {
268
274
  createAsyncClient,
269
- createClient
275
+ createSyncClient
270
276
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleekcms/client",
3
- "version": "2.3.1",
3
+ "version": "3.0.0",
4
4
  "description": "Official SleekCMS content client for Node 18+ and browser",
5
5
  "type": "module",
6
6
  "main": "index.cjs",