@sleekcms/client 1.0.1 → 2.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.
Files changed (6) hide show
  1. package/README.md +134 -325
  2. package/index.cjs +123 -104
  3. package/index.d.cts +22 -34
  4. package/index.d.ts +22 -34
  5. package/index.mjs +121 -102
  6. package/package.json +1 -1
package/index.cjs CHANGED
@@ -29,16 +29,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/index.ts
30
30
  var index_exports = {};
31
31
  __export(index_exports, {
32
- createClient: () => createClient,
33
- createSyncClient: () => createSyncClient
32
+ createAsyncClient: () => createAsyncClient,
33
+ createClient: () => createClient
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
- function isDevToken(token) {
40
- return token.startsWith("dev-");
41
- }
42
39
  function getBaseUrl(token, devEnv) {
43
40
  let [env, siteId, ...rest] = token.split("-");
44
41
  if (devEnv === "production") return `https://${env}.sleekcms.com/${siteId}`;
@@ -50,52 +47,59 @@ function applyJmes(data, query) {
50
47
  if (!query) return data;
51
48
  return jmespath.search(data, query);
52
49
  }
53
- function createFetchSiteContent(options) {
54
- const { siteToken, env = "latest", mock, devEnv = "production" } = options;
55
- const dev = isDevToken(siteToken);
56
- let cacheMode = !!options.cache || !!mock && dev;
57
- let cachedContent = null;
58
- return async function fetchSiteContent(searchQuery) {
59
- if (!siteToken) {
60
- throw new Error("[SleekCMS] siteToken is required");
61
- }
62
- if (cachedContent) {
63
- return applyJmes(cachedContent, searchQuery);
64
- }
65
- const baseUrl = getBaseUrl(siteToken, devEnv).replace(/\/$/, "");
66
- const url = new URL(`${baseUrl}/${env}`);
67
- if (searchQuery && !cacheMode && !cachedContent) {
68
- url.searchParams.set("search", searchQuery);
69
- }
70
- if (mock && dev) {
71
- url.searchParams.set("mock", "true");
72
- }
73
- const res = await fetch(url.toString(), {
74
- method: "GET",
50
+ function getUrl({ siteToken, env, search: search2, lang, devEnv = "production" }) {
51
+ const baseUrl = getBaseUrl(siteToken, devEnv).replace(/\/$/, "");
52
+ const url = new URL(`${baseUrl}/${env}`);
53
+ if (search2) url.searchParams.append("search", search2);
54
+ if (lang) url.searchParams.append("lang", lang);
55
+ return url.toString();
56
+ }
57
+ async function fetchEnvTag({ siteToken, env }) {
58
+ const url = getUrl({ siteToken, env });
59
+ try {
60
+ let res = await fetch(url, {
61
+ method: "POST",
75
62
  headers: {
76
63
  "Content-Type": "application/json",
77
64
  Authorization: siteToken
78
65
  }
79
66
  });
80
- if (!res.ok) {
81
- let message = res.statusText;
82
- try {
83
- const data2 = await res.json();
84
- if (data2 && data2.message) message = data2.message;
85
- } catch {
67
+ if (res.ok) {
68
+ let data = await res.json();
69
+ if (data.tag) {
70
+ return data.tag;
86
71
  }
87
- throw new Error(`[SleekCMS] Request failed (${res.status}): ${message}`);
88
72
  }
89
- const data = await res.json();
90
- if (!searchQuery) {
91
- cachedContent = data;
92
- cacheMode = true;
73
+ } catch (e) {
74
+ console.error("[SleekCMS] Unable to resolve env tag.");
75
+ }
76
+ return env;
77
+ }
78
+ async function fetchSiteContent(options) {
79
+ const { siteToken, env = "latest", cdn = false, search: search2, lang } = options;
80
+ 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 });
84
+ }
85
+ const res = await fetch(url, {
86
+ method: "GET",
87
+ headers: {
88
+ "Content-Type": "application/json",
89
+ Authorization: siteToken
93
90
  }
94
- return data;
95
- };
91
+ });
92
+ if (!res.ok) {
93
+ let message = res.statusText;
94
+ try {
95
+ const data = await res.json();
96
+ if (data && data.message) message = data.message;
97
+ } catch {
98
+ }
99
+ throw new Error(`[SleekCMS] Request failed (${res.status}): ${message}`);
100
+ }
101
+ return await res.json();
96
102
  }
97
-
98
- // src/index.ts
99
103
  function extractSlugs(pages, path) {
100
104
  const slugs = [];
101
105
  const pagesList = pages ?? [];
@@ -114,122 +118,137 @@ function filterPagesByPath(pages, path) {
114
118
  return pth.startsWith(path);
115
119
  });
116
120
  }
117
- function createClient(options) {
118
- const fetchSiteContent = createFetchSiteContent(options);
119
- async function getContent(query) {
120
- return await fetchSiteContent(query);
121
+
122
+ // src/index.ts
123
+ async function createClient(options) {
124
+ const data = await fetchSiteContent(options);
125
+ function getContent(query) {
126
+ return applyJmes(data, query);
121
127
  }
122
- async function getPages(path, query) {
128
+ function getPages(path) {
123
129
  if (!path) {
124
130
  throw new Error("[SleekCMS] path is required for getPages");
125
131
  }
126
- const data = await fetchSiteContent();
127
- const filtered = filterPagesByPath(data.pages, path);
128
- return applyJmes(filtered, query);
132
+ return filterPagesByPath(data.pages, path);
129
133
  }
130
- async function getPage(path) {
134
+ function getPage(path) {
131
135
  if (!path) {
132
136
  throw new Error("[SleekCMS] path is required for getPage");
133
137
  }
134
- const data = await fetchSiteContent();
135
138
  const pages = data.pages ?? [];
136
139
  const page = pages.find((p) => {
137
140
  const pth = typeof p._path === "string" ? p._path : "";
138
141
  return pth === path;
139
142
  });
140
- if (!page) {
141
- throw new Error(`[SleekCMS] Page not found: ${path}`);
143
+ return page ?? null;
144
+ }
145
+ function getEntry(handle) {
146
+ if (!handle) {
147
+ throw new Error("[SleekCMS] handle is required for getEntry");
142
148
  }
143
- return page;
149
+ const entries = data.entries ?? {};
150
+ const entry = entries[handle] ?? null;
151
+ return entry;
144
152
  }
145
- async function getSlugs(path) {
153
+ function getSlugs(path) {
146
154
  if (!path) {
147
155
  throw new Error("[SleekCMS] path is required for getSlugs");
148
156
  }
149
- const data = await fetchSiteContent();
150
157
  return extractSlugs(data.pages, path);
151
158
  }
152
- async function getImages() {
153
- const data = await fetchSiteContent();
154
- return data.images ?? {};
155
- }
156
- async function getImage(name) {
157
- if (!name) return void 0;
158
- const data = await fetchSiteContent();
159
- return data.images ? data.images[name] : void 0;
159
+ function getImage(name) {
160
+ if (!name) return null;
161
+ return data.images ? data.images[name] : null;
160
162
  }
161
- async function getList(name) {
162
- if (!name) return void 0;
163
- const data = await fetchSiteContent();
163
+ function getList(name) {
164
+ if (!name) return null;
164
165
  const lists = data.lists ?? {};
165
166
  const list = lists[name];
166
- return Array.isArray(list) ? list : void 0;
167
+ return Array.isArray(list) ? list : null;
167
168
  }
168
169
  return {
169
170
  getContent,
170
171
  getPages,
171
172
  getPage,
173
+ getEntry,
172
174
  getSlugs,
173
- getImages,
174
175
  getImage,
175
176
  getList
176
177
  };
177
178
  }
178
- async function createSyncClient(options) {
179
- const fetchSiteContent = createFetchSiteContent(options);
180
- const data = await fetchSiteContent();
181
- function getContent(query) {
182
- return applyJmes(data, query);
183
- }
184
- function getPages(path, query) {
185
- if (!path) {
186
- throw new Error("[SleekCMS] path is required for getPages");
179
+ function createAsyncClient({ siteToken, env = "latest", cdn, lang }) {
180
+ let syncClient = null;
181
+ let tag = null;
182
+ let cache = {};
183
+ async function getContent(search2) {
184
+ if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
185
+ if (!search2 && !syncClient) {
186
+ syncClient = await createClient({ siteToken, env: tag ?? env, cdn, lang });
187
+ cache = {};
187
188
  }
188
- const filtered = filterPagesByPath(data.pages, path);
189
- return applyJmes(filtered, query);
189
+ if (syncClient) return syncClient.getContent(search2);
190
+ if (!search2) return null;
191
+ if (!cache[search2]) cache[search2] = await fetchSiteContent({ siteToken, env: tag ?? env, search: search2, lang });
192
+ return cache[search2] ?? null;
193
+ }
194
+ async function getPages(path) {
195
+ if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
196
+ if (syncClient) return syncClient.getPages(path);
197
+ if (!cache.pages) cache.pages = await fetchSiteContent({ siteToken, env: tag ?? env, search: "pages", lang });
198
+ if (!path) return cache.pages;
199
+ else return filterPagesByPath(cache.pages, path);
190
200
  }
191
- function getPage(path) {
192
- if (!path) {
193
- throw new Error("[SleekCMS] path is required for getPage");
194
- }
195
- const pages = data.pages ?? [];
196
- const page = pages.find((p) => {
201
+ async function getPage(path) {
202
+ var _a;
203
+ if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
204
+ if (syncClient) return syncClient.getPage(path);
205
+ if (!cache.pages) cache.pages = await fetchSiteContent({ siteToken, env: tag ?? env, search: "pages", lang });
206
+ const page = (_a = cache.pages) == null ? void 0 : _a.find((p) => {
197
207
  const pth = typeof p._path === "string" ? p._path : "";
198
208
  return pth === path;
199
209
  });
200
210
  return page ?? null;
201
211
  }
202
- function getSlugs(path) {
203
- if (!path) {
204
- throw new Error("[SleekCMS] path is required for getSlugs");
212
+ async function getEntry(handle) {
213
+ if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
214
+ if (syncClient) return syncClient.getEntry(handle);
215
+ let search2 = `entries.${handle}`;
216
+ if (cache[search2] === void 0) {
217
+ cache[search2] = await fetchSiteContent({ siteToken, env: tag ?? env, search: search2, lang });
205
218
  }
206
- return extractSlugs(data.pages, path);
219
+ return cache[search2];
207
220
  }
208
- function getImages() {
209
- return data.images ?? {};
221
+ async function getSlugs(path) {
222
+ if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
223
+ if (syncClient) return syncClient.getSlugs(path);
224
+ if (!cache.pages) cache.pages = await fetchSiteContent({ siteToken, env: tag ?? env, search: "pages", lang });
225
+ return extractSlugs(cache.pages, path);
210
226
  }
211
- function getImage(name) {
212
- if (!name) return void 0;
213
- return data.images ? data.images[name] : void 0;
227
+ async function getImage(name) {
228
+ if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
229
+ if (syncClient) return syncClient.getImage(name);
230
+ if (!cache.images) cache.images = await fetchSiteContent({ siteToken, env: tag ?? env, search: "images", lang });
231
+ return cache.images ? cache.images[name] : null;
214
232
  }
215
- function getList(name) {
216
- if (!name) return void 0;
217
- const lists = data.lists ?? {};
218
- const list = lists[name];
219
- return Array.isArray(list) ? list : void 0;
233
+ async function getList(name) {
234
+ if (cdn && !tag) tag = await fetchEnvTag({ siteToken, env });
235
+ if (syncClient) return syncClient.getList(name);
236
+ if (!cache.lists) cache.lists = await fetchSiteContent({ siteToken, env: tag ?? env, search: "lists", lang });
237
+ const list = cache.lists[name];
238
+ return Array.isArray(list) ? list : null;
220
239
  }
221
240
  return {
222
241
  getContent,
223
242
  getPages,
224
243
  getPage,
244
+ getEntry,
225
245
  getSlugs,
226
- getImages,
227
246
  getImage,
228
247
  getList
229
248
  };
230
249
  }
231
250
  // Annotate the CommonJS export names for ESM import in node:
232
251
  0 && (module.exports = {
233
- createClient,
234
- createSyncClient
252
+ createAsyncClient,
253
+ createClient
235
254
  });
package/index.d.cts CHANGED
@@ -12,7 +12,9 @@ type List = Array<{
12
12
  value: string;
13
13
  }>;
14
14
  interface SleekSiteContent {
15
- entries?: Record<string, Entry> | Record<string, Entry[]>;
15
+ entries?: {
16
+ [handle: string]: Entry | Entry[];
17
+ };
16
18
  pages?: Array<Page>;
17
19
  images?: Record<string, Image>;
18
20
  lists?: Record<string, List>;
@@ -23,43 +25,29 @@ interface SleekSiteContent {
23
25
  interface ClientOptions {
24
26
  siteToken: string;
25
27
  env?: string;
26
- cache?: boolean;
27
- mock?: boolean;
28
- resolveEnv?: boolean;
29
- devEnv?: string;
28
+ cdn?: boolean;
29
+ lang?: string;
30
30
  }
31
-
32
- /**
33
- * Async SleekCMS client: methods return Promises.
34
- */
35
31
  interface SleekClient {
36
- getContent(query?: string): Promise<SleekSiteContent>;
37
- getPages(path: string, query?: string): Promise<SleekSiteContent["pages"]>;
38
- getPage(path: string): Promise<Page>;
39
- getSlugs(path: string): Promise<string[]>;
40
- getImages(): Promise<SleekSiteContent["images"]>;
41
- getImage(name: string): Promise<unknown | undefined>;
42
- getList<T = unknown>(name: string): Promise<T[] | undefined>;
43
- }
44
- /**
45
- * Sync client: prefetches full content once; subsequent calls are in-memory only.
46
- */
47
- interface SleekSyncClient {
48
32
  getContent(query?: string): SleekSiteContent;
49
- getPages(path: string, query?: string): SleekSiteContent["pages"];
33
+ getPages(path: string): SleekSiteContent["pages"];
50
34
  getPage(path: string): Page | null;
35
+ getEntry(handle: string): Entry | Entry[] | null;
51
36
  getSlugs(path: string): string[];
52
- getImages(): SleekSiteContent["images"];
53
- getImage(name: string): unknown | undefined;
54
- getList<T = unknown>(name: string): T[] | undefined;
37
+ getImage(name: string): Image | null;
38
+ getList(name: string): List | null;
55
39
  }
56
- declare function createClient(options: ClientOptions): SleekClient;
57
- /**
58
- * Create a sync SleekCMS client.
59
- *
60
- * - Prefetches full content once (no search=).
61
- * - All operations (including JMESPath) are local and synchronous.
62
- */
63
- declare function createSyncClient(options: ClientOptions): Promise<SleekSyncClient>;
40
+ interface SleekAsyncClient {
41
+ getContent(query?: string): Promise<SleekSiteContent>;
42
+ getPages(path: string): Promise<SleekSiteContent["pages"]>;
43
+ getPage(path: string): Promise<Page | null>;
44
+ getEntry(handle: string): Promise<Entry | Entry[] | null>;
45
+ getSlugs(path: string): Promise<string[]>;
46
+ getImage(name: string): Promise<Image | null>;
47
+ getList(name: string): Promise<List | null>;
48
+ }
49
+
50
+ declare function createClient(options: ClientOptions): Promise<SleekClient>;
51
+ declare function createAsyncClient({ siteToken, env, cdn, lang }: ClientOptions): SleekAsyncClient | any;
64
52
 
65
- export { type ClientOptions, type SleekClient, type SleekSiteContent, type SleekSyncClient, createClient, createSyncClient };
53
+ export { type ClientOptions, type Image, type List, type SleekSiteContent, createAsyncClient, createClient };
package/index.d.ts CHANGED
@@ -12,7 +12,9 @@ type List = Array<{
12
12
  value: string;
13
13
  }>;
14
14
  interface SleekSiteContent {
15
- entries?: Record<string, Entry> | Record<string, Entry[]>;
15
+ entries?: {
16
+ [handle: string]: Entry | Entry[];
17
+ };
16
18
  pages?: Array<Page>;
17
19
  images?: Record<string, Image>;
18
20
  lists?: Record<string, List>;
@@ -23,43 +25,29 @@ interface SleekSiteContent {
23
25
  interface ClientOptions {
24
26
  siteToken: string;
25
27
  env?: string;
26
- cache?: boolean;
27
- mock?: boolean;
28
- resolveEnv?: boolean;
29
- devEnv?: string;
28
+ cdn?: boolean;
29
+ lang?: string;
30
30
  }
31
-
32
- /**
33
- * Async SleekCMS client: methods return Promises.
34
- */
35
31
  interface SleekClient {
36
- getContent(query?: string): Promise<SleekSiteContent>;
37
- getPages(path: string, query?: string): Promise<SleekSiteContent["pages"]>;
38
- getPage(path: string): Promise<Page>;
39
- getSlugs(path: string): Promise<string[]>;
40
- getImages(): Promise<SleekSiteContent["images"]>;
41
- getImage(name: string): Promise<unknown | undefined>;
42
- getList<T = unknown>(name: string): Promise<T[] | undefined>;
43
- }
44
- /**
45
- * Sync client: prefetches full content once; subsequent calls are in-memory only.
46
- */
47
- interface SleekSyncClient {
48
32
  getContent(query?: string): SleekSiteContent;
49
- getPages(path: string, query?: string): SleekSiteContent["pages"];
33
+ getPages(path: string): SleekSiteContent["pages"];
50
34
  getPage(path: string): Page | null;
35
+ getEntry(handle: string): Entry | Entry[] | null;
51
36
  getSlugs(path: string): string[];
52
- getImages(): SleekSiteContent["images"];
53
- getImage(name: string): unknown | undefined;
54
- getList<T = unknown>(name: string): T[] | undefined;
37
+ getImage(name: string): Image | null;
38
+ getList(name: string): List | null;
55
39
  }
56
- declare function createClient(options: ClientOptions): SleekClient;
57
- /**
58
- * Create a sync SleekCMS client.
59
- *
60
- * - Prefetches full content once (no search=).
61
- * - All operations (including JMESPath) are local and synchronous.
62
- */
63
- declare function createSyncClient(options: ClientOptions): Promise<SleekSyncClient>;
40
+ interface SleekAsyncClient {
41
+ getContent(query?: string): Promise<SleekSiteContent>;
42
+ getPages(path: string): Promise<SleekSiteContent["pages"]>;
43
+ getPage(path: string): Promise<Page | null>;
44
+ getEntry(handle: string): Promise<Entry | Entry[] | null>;
45
+ getSlugs(path: string): Promise<string[]>;
46
+ getImage(name: string): Promise<Image | null>;
47
+ getList(name: string): Promise<List | null>;
48
+ }
49
+
50
+ declare function createClient(options: ClientOptions): Promise<SleekClient>;
51
+ declare function createAsyncClient({ siteToken, env, cdn, lang }: ClientOptions): SleekAsyncClient | any;
64
52
 
65
- export { type ClientOptions, type SleekClient, type SleekSiteContent, type SleekSyncClient, createClient, createSyncClient };
53
+ export { type ClientOptions, type Image, type List, type SleekSiteContent, createAsyncClient, createClient };