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