@localess/client 3.0.6-dev.20260502214443 → 3.0.6-dev.20260512074100

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
@@ -50,14 +50,15 @@ const client = localessClient({
50
50
 
51
51
  ### Client Options
52
52
 
53
- | Option | Type | Required | Default | Description |
54
- |--------|------|----------|---------|-------------|
55
- | `origin` | `string` | ✅ | — | Fully qualified domain with protocol (e.g., `https://my-localess.web.app`) |
56
- | `spaceId` | `string` | ✅ | — | Localess Space ID, found in Space settings |
57
- | `token` | `string` | ✅ | — | Localess API token, found in Space settings |
58
- | `version` | `'draft' \| string` | ❌ | `'published'` | Default content version to fetch |
59
- | `debug` | `boolean` | ❌ | `false` | Enable debug logging |
60
- | `cacheTTL` | `number \| false` | ❌ | `300000` | Cache TTL in milliseconds (5 minutes). Set `false` to disable caching |
53
+ | Option | Type | Required | Default | Description |
54
+ |-------------------|---------------------|----------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
55
+ | `origin` | `string` | ✅ | — | Fully qualified domain with protocol (e.g., `https://my-localess.web.app`) |
56
+ | `spaceId` | `string` | ✅ | — | Localess Space ID, found in Space settings |
57
+ | `token` | `string` | ✅ | — | Localess API token, found in Space settings |
58
+ | `version` | `'draft' \| string` | ❌ | `'published'` | Default content version to fetch |
59
+ | `debug` | `boolean` | ❌ | `false` | Enable debug logging |
60
+ | `cacheTTL` | `number \| false` | ❌ | `300` | Cache TTL in **seconds** (default: 5 minutes). Set `false` to disable caching entirely — takes precedence over `fileSystemCache` |
61
+ | `fileSystemCache` | `boolean` | ❌ | `false` | Use a file-system cache instead of the default in-memory cache. Shared across all processes pointing to the same working directory (e.g. Next.js parallel build workers). Respects `cacheTTL` for TTL value |
61
62
 
62
63
  ---
63
64
 
@@ -94,12 +95,12 @@ const content = await client.getContentById<Page>('FRnIT7CUABoRCdSVVGGs', {
94
95
 
95
96
  ### Content Fetch Parameters
96
97
 
97
- | Parameter | Type | Default | Description |
98
- |-----------|------|---------|-------------|
99
- | `version` | `'draft' \| string` | Client default | Override the client's default content version |
100
- | `locale` | `string` | — | ISO 639-1 locale code (e.g., `'en'`, `'de'`) |
101
- | `resolveReference` | `boolean` | `false` | Resolve content references inline |
102
- | `resolveLink` | `boolean` | `false` | Resolve content links inline |
98
+ | Parameter | Type | Default | Description |
99
+ |--------------------|---------------------|----------------|-----------------------------------------------|
100
+ | `version` | `'draft' \| string` | Client default | Override the client's default content version |
101
+ | `locale` | `string` | — | ISO 639-1 locale code (e.g., `'en'`, `'de'`) |
102
+ | `resolveReference` | `boolean` | `false` | Resolve content references inline |
103
+ | `resolveLink` | `boolean` | `false` | Resolve content links inline |
103
104
 
104
105
  ---
105
106
 
@@ -121,11 +122,11 @@ const legalLinks = await client.getLinks({
121
122
  });
122
123
  ```
123
124
 
124
- | Parameter | Type | Description |
125
- |-----------|------|-------------|
126
- | `kind` | `'DOCUMENT' \| 'FOLDER'` | Filter results by content kind |
127
- | `parentSlug` | `string` | Filter by parent slug (e.g., `'legal/policy'`) |
128
- | `excludeChildren` | `boolean` | When `true`, excludes nested sub-slugs from results |
125
+ | Parameter | Type | Description |
126
+ |-------------------|--------------------------|-----------------------------------------------------|
127
+ | `kind` | `'DOCUMENT' \| 'FOLDER'` | Filter results by content kind |
128
+ | `parentSlug` | `string` | Filter by parent slug (e.g., `'legal/policy'`) |
129
+ | `excludeChildren` | `boolean` | When `true`, excludes nested sub-slugs from results |
129
130
 
130
131
  ---
131
132
 
@@ -239,33 +240,56 @@ if (window.localess) {
239
240
 
240
241
  ### Available Event Types
241
242
 
242
- | Event | Payload | Description |
243
- |-------|---------|-------------|
244
- | `input` | `{ type: 'input', data: any }` | Fired while a field is being edited (real-time) |
245
- | `change` | `{ type: 'change', data: any }` | Fired after a field value is confirmed |
246
- | `save` | `{ type: 'save' }` | Fired when content is saved |
247
- | `publish` | `{ type: 'publish' }` | Fired when content is published |
248
- | `pong` | `{ type: 'pong' }` | Heartbeat response from the editor |
249
- | `enterSchema` | `{ type: 'enterSchema', id, schema, field? }` | Fired when hovering over a schema element |
250
- | `hoverSchema` | `{ type: 'hoverSchema', id, schema, field? }` | Fired when entering a schema element |
243
+ | Event | Payload | Description |
244
+ |---------------|-----------------------------------------------|-------------------------------------------------|
245
+ | `input` | `{ type: 'input', data: any }` | Fired while a field is being edited (real-time) |
246
+ | `change` | `{ type: 'change', data: any }` | Fired after a field value is confirmed |
247
+ | `save` | `{ type: 'save' }` | Fired when content is saved |
248
+ | `publish` | `{ type: 'publish' }` | Fired when content is published |
249
+ | `pong` | `{ type: 'pong' }` | Heartbeat response from the editor |
250
+ | `enterSchema` | `{ type: 'enterSchema', id, schema, field? }` | Fired when hovering over a schema element |
251
+ | `hoverSchema` | `{ type: 'hoverSchema', id, schema, field? }` | Fired when entering a schema element |
251
252
 
252
253
  ---
253
254
 
254
255
  ## Caching
255
256
 
256
- All API responses are cached by default using a TTL (time-to-live) cache. You can configure caching when initializing the client.
257
+ All API responses are cached by default using an in-memory TTL cache. You can configure caching when initializing the client.
257
258
 
258
259
  ```ts
259
- // Default: 5-minute TTL cache
260
+ // Default: 5-minute in-memory TTL cache
260
261
  const client = localessClient({ origin, spaceId, token });
261
262
 
262
263
  // Custom TTL (e.g., 10 minutes)
263
- const client = localessClient({ origin, spaceId, token, cacheTTL: 600000 });
264
+ const client = localessClient({ origin, spaceId, token, cacheTTL: 600 });
264
265
 
265
- // Disable caching entirely
266
+ // Disable caching entirely (recommended for draft/preview mode)
266
267
  const client = localessClient({ origin, spaceId, token, cacheTTL: false });
267
268
  ```
268
269
 
270
+ ### Sharing cache across Next.js build workers
271
+
272
+ Next.js runs multiple worker processes in parallel during `next build`. Each worker has its own memory space, so the default in-memory cache is not shared — every worker re-fetches the same URLs independently.
273
+
274
+ Set `fileSystemCache: true` to persist cache entries to disk. All workers sharing the same working directory will read and write the same cache files:
275
+
276
+ ```ts
277
+ // File-system cache with default 5-minute TTL
278
+ const client = localessClient({ origin, spaceId, token, fileSystemCache: true });
279
+
280
+ // File-system cache with custom TTL
281
+ const client = localessClient({ origin, spaceId, token, fileSystemCache: true, cacheTTL: 60 });
282
+
283
+ // cacheTTL: false always wins — no cache even with fileSystemCache: true
284
+ const client = localessClient({ origin, spaceId, token, fileSystemCache: true, cacheTTL: false });
285
+ ```
286
+
287
+ Cache files are written to `.localess-cache/` in the current working directory. Add it to `.gitignore`:
288
+
289
+ ```
290
+ .localess-cache/
291
+ ```
292
+
269
293
  ---
270
294
 
271
295
  ## Type Reference
@@ -365,11 +389,11 @@ A key-value map of translation keys to translated string values.
365
389
 
366
390
  ## Utility Functions
367
391
 
368
- | Function | Returns | Description |
369
- |----------|---------|-------------|
370
- | `isBrowser()` | `boolean` | Returns `true` if code is running in a browser environment |
371
- | `isServer()` | `boolean` | Returns `true` if code is running in a server/Node.js environment |
372
- | `isIframe()` | `boolean` | Returns `true` if the page is rendered inside an iframe |
392
+ | Function | Returns | Description |
393
+ |---------------|-----------|-------------------------------------------------------------------|
394
+ | `isBrowser()` | `boolean` | Returns `true` if code is running in a browser environment |
395
+ | `isServer()` | `boolean` | Returns `true` if code is running in a server/Node.js environment |
396
+ | `isIframe()` | `boolean` | Returns `true` if the page is rendered inside an iframe |
373
397
 
374
398
  ---
375
399
 
package/SKILL.md CHANGED
@@ -25,9 +25,10 @@ const client = localessClient({
25
25
  origin: 'https://my-localess.web.app', // Full URL with protocol (required)
26
26
  spaceId: 'YOUR_SPACE_ID', // From Space settings (required)
27
27
  token: 'YOUR_API_TOKEN', // API token — NEVER expose client-side (required)
28
- version: 'draft', // undefined = published (default), 'draft' for preview
28
+ version: 'draft', // undefined = published (default), 'draft' for preview
29
29
  debug: false, // Logs requests; default: false
30
- cacheTTL: 300000, // Cache TTL in ms; false to disable; default: 5 min
30
+ cacheTTL: 300, // Cache TTL in seconds; false to disable; default: 300 (5 min)
31
+ fileSystemCache: false, // true = share cache across processes via filesystem; default: false
31
32
  });
32
33
  ```
33
34
 
@@ -88,25 +89,45 @@ const url = client.assetLink(content.data.image);
88
89
 
89
90
  ## Content Fetch Parameters
90
91
 
91
- | Parameter | Type | Default | Description |
92
- |--------------------|-----------|---------------|----------------------------------------|
93
- | `version` | `'draft' \| undefined` | `undefined` | `'draft'` for preview, omit for published |
94
- | `locale` | `string` | — | ISO 639-1 code: `'en'`, `'de'`, etc. |
95
- | `resolveReference` | `boolean` | `false` | Inline referenced content objects |
96
- | `resolveLink` | `boolean` | `false` | Inline linked content metadata |
92
+ | Parameter | Type | Default | Description |
93
+ |--------------------|------------------------|-------------|-------------------------------------------|
94
+ | `version` | `'draft' \| undefined` | `undefined` | `'draft'` for preview, omit for published |
95
+ | `locale` | `string` | — | ISO 639-1 code: `'en'`, `'de'`, etc. |
96
+ | `resolveReference` | `boolean` | `false` | Inline referenced content objects |
97
+ | `resolveLink` | `boolean` | `false` | Inline linked content metadata |
97
98
 
98
99
  ---
99
100
 
100
101
  ## Caching
101
102
 
102
- - Default: TTL-based, **5 minutes** (300,000 ms)
103
+ - Default: in-memory TTL cache, **5 minutes** (300,000 ms)
103
104
  - Cache key = full request URL (includes all parameters)
104
- - Adjust for content update frequency:
105
+ - `cacheTTL: false` always disables caching, regardless of other options
106
+
107
+ ### cacheTTL
108
+
109
+ Controls whether caching is enabled and the TTL duration (in **seconds**):
105
110
 
106
111
  ```typescript
107
- localessClient({ cacheTTL: 60000 }) // 1 minute — frequently updated
108
- localessClient({ cacheTTL: 3600000 }) // 1 hour — rarely updated
109
- localessClient({ cacheTTL: false }) // Disabled — always fresh (draft mode)
112
+ localessClient({ cacheTTL: 60 }) // 1 minute TTL — frequently updated content
113
+ localessClient({ cacheTTL: 3600 }) // 1 hour TTL — rarely updated content
114
+ localessClient({ cacheTTL: false }) // Disabled — always fresh (use in draft/preview mode)
115
+ ```
116
+
117
+ ### fileSystemCache
118
+
119
+ Next.js (and similar frameworks) spin up multiple worker processes during build. Each worker has its own memory, so the default in-memory cache is not shared — every worker re-fetches the same URLs. Set `fileSystemCache: true` to write cache entries to disk so all workers share the same cache:
120
+
121
+ ```typescript
122
+ localessClient({ fileSystemCache: true }) // filesystem cache, default 5 min TTL
123
+ localessClient({ fileSystemCache: true, cacheTTL: 60 }) // filesystem cache, 1 min TTL
124
+ localessClient({ fileSystemCache: true, cacheTTL: false }) // cacheTTL: false wins — no cache
125
+ ```
126
+
127
+ Cache files are written to `.localess-cache/` in the current working directory. Add it to `.gitignore`:
128
+
129
+ ```
130
+ .localess-cache/
110
131
  ```
111
132
 
112
133
  ---
package/dist/cache.d.ts CHANGED
@@ -27,3 +27,19 @@ export declare class TTLCache<V> {
27
27
  get(key: string): V | undefined;
28
28
  has(key: string): boolean;
29
29
  }
30
+ export declare class FileSystemCache<V> implements ICache<V> {
31
+ private dir;
32
+ private ttlMs;
33
+ /**
34
+ * Creates a FileSystemCache that persists entries as JSON files on disk.
35
+ * Shared across all processes that point to the same directory, making it
36
+ * suitable for Next.js parallel build workers.
37
+ * @param dir Directory to store cache files. Default: '.localess-cache'
38
+ * @param ttlMs Time-to-live in ms. Default: 5 minutes (300000 ms).
39
+ */
40
+ constructor(dir?: string, ttlMs?: number);
41
+ private keyToPath;
42
+ set(key: string, value: V): void;
43
+ get(key: string): V | undefined;
44
+ has(key: string): boolean;
45
+ }
package/dist/client.d.ts CHANGED
@@ -23,10 +23,36 @@ export type LocalessClientOptions = {
23
23
  */
24
24
  debug?: boolean;
25
25
  /**
26
- * Cache TTL (time to live) for API responses. Default is 5 minutes (300000 ms).
27
- * Set to false to disable caching.
26
+ * Cache TTL (time to live) in **seconds** for API responses.
27
+ *
28
+ * - `undefined` — use default in-memory TTL cache with 5 minutes TTL (default)
29
+ * - `number` — use in-memory TTL cache with the given TTL in seconds
30
+ * - `false` — disable caching entirely (always fetches fresh data); takes precedence over `fileSystemCache`
31
+ *
32
+ * @default 300 (5 minutes)
33
+ * @example
34
+ * cacheTTL: 60 // 1 minute
35
+ * cacheTTL: 300 // 5 minutes (default)
36
+ * cacheTTL: 3600 // 1 hour
37
+ * cacheTTL: false // disabled
28
38
  */
29
39
  cacheTTL?: number | false;
40
+ /**
41
+ * When `true`, uses a file-system cache instead of the default in-memory cache.
42
+ * All processes sharing the same working directory share the same cache, which makes it
43
+ * suitable for Next.js parallel build workers where each worker has its own memory space.
44
+ *
45
+ * Cache files are written to `.localess-cache/` in the current working directory.
46
+ * Add `.localess-cache/` to your `.gitignore`.
47
+ *
48
+ * `cacheTTL` still controls the TTL:
49
+ * - `cacheTTL: false` — caching is disabled; `fileSystemCache` is ignored
50
+ * - `cacheTTL: number` — file-system cache uses that TTL value (in seconds)
51
+ * - `cacheTTL` omitted — file-system cache uses the default 5 minutes TTL
52
+ *
53
+ * @default false
54
+ */
55
+ fileSystemCache?: boolean;
30
56
  };
31
57
  export type LinksFetchParams = {
32
58
  /**
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './cache';
1
2
  export * from './client';
2
3
  export * from './editable';
3
4
  export * from './models';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class{set(e,t){}get(e){}has(e){return!1}},t=class{cache=new Map;constructor(e=3e5){this.ttlMs=e}set(e,t){this.cache.set(e,{value:t,expiresAt:Date.now()+this.ttlMs})}get(e){let t=this.cache.get(e);if(t){if(Date.now()>t.expiresAt){this.cache.delete(e);return}return t.value}}has(e){return this.get(e)!==void 0}},n=`\x1B[0m`,r=`\x1B[34m`,i=()=>typeof window<`u`,a=()=>typeof window>`u`,o=()=>i()&&window.self!==window.top,s=`${r}[Localess:Client]${n}`;function c(n){n.debug&&console.log(s,`Client Options : `,n);let r=n.origin.replace(/\/+$/,``),i={redirect:`follow`,headers:{"Content-Type":`application/json`,Accept:`application/json`,"X-Localess-Agent":`Localess-JS-Client`,"X-Localess-Agent-Version":`0.9.0`}},a=n.cacheTTL===!1?new e:new t(n.cacheTTL);return{async getLinks(e){n.debug&&console.log(s,`getLinks() params : `,JSON.stringify(e));let t=``;e?.kind&&(t=`&kind=${e.kind}`);let o=``;e?.parentSlug&&(o=`&parentSlug=${e.parentSlug}`);let c=``;e?.excludeChildren&&(c=`&excludeChildren=${e.excludeChildren}`);let l=`${r}/api/v1/spaces/${n.spaceId}/links?token=${n.token}${t}${o}${c}`;if(n.debug&&console.log(s,`getLinks fetch url : `,l),a.has(l))return n.debug&&console.log(s,`getLinks cache hit`),a.get(l);try{let e=await fetch(l,i);n.debug&&console.log(s,`getLinks status : `,e.status);let t=await e.json();return a.set(l,t),t}catch(e){return console.error(s,`getLinks error : `,e),{}}},async getContentBySlug(e,t){n.debug&&(console.log(s,`getContentBySlug() slug : `,e),console.log(s,`getContentBySlug() params : `,JSON.stringify(t)));let o=``;n?.version&&n.version==`draft`&&(o=`&version=${n.version}`),t?.version&&t.version==`draft`&&(o=`&version=${t.version}`);let c=t?.locale?`&locale=${t.locale}`:``,l=t?.resolveReference?`&resolveReference=${t.resolveReference}`:``,u=t?.resolveLink?`&resolveLink=${t.resolveLink}`:``,d=`${r}/api/v1/spaces/${n.spaceId}/contents/slugs/${e}?token=${n.token}${o}${c}${l}${u}`;if(n.debug&&console.log(s,`getContentBySlug fetch url : `,d),a.has(d))return n.debug&&console.log(s,`getContentBySlug cache hit`),a.get(d);try{let e=await fetch(d,i);n.debug&&console.log(s,`getContentBySlug status : `,e.status);let t=await e.json();return a.set(d,t),t}catch(e){return console.error(s,`getContentBySlug error : `,e),{}}},async getContentById(e,t){n.debug&&(console.log(s,`getContentById() id : `,e),console.log(s,`getContentById() params : `,JSON.stringify(t)));let o=``;n?.version&&n.version==`draft`&&(o=`&version=${n.version}`),t?.version&&t.version==`draft`&&(o=`&version=${t.version}`);let c=t?.locale?`&locale=${t.locale}`:``,l=t?.resolveReference?`&resolveReference=${t.resolveReference}`:``,u=t?.resolveLink?`&resolveLink=${t.resolveLink}`:``,d=`${r}/api/v1/spaces/${n.spaceId}/contents/${e}?token=${n.token}${o}${c}${l}${u}`;if(n.debug&&console.log(s,`getContentById fetch url : `,d),a.has(d))return n.debug&&console.log(s,`getContentById cache hit`),a.get(d);try{let e=await fetch(d,i);n.debug&&console.log(s,`getContentById status : `,e.status);let t=await e.json();return a.set(d,t),t}catch(e){return console.error(s,`getContentById error : `,e),{}}},async getTranslations(e){n.debug&&console.log(s,`getTranslations() locale : `,e);let t=`${r}/api/v1/spaces/${n.spaceId}/translations/${e}?token=${n.token}`;if(n.debug&&console.log(s,`getTranslations fetch url : `,t),a.has(t))return n.debug&&console.log(s,`getTranslations cache hit`),a.get(t);try{let e=await fetch(t,i);n.debug&&console.log(s,`getTranslations status : `,e.status);let r=await e.json();return a.set(t,r),r}catch(e){return console.error(s,`getTranslations error : `,e),{}}},syncScriptUrl(){return`${r}/scripts/sync-v1.js`},assetLink(e){return typeof e==`string`?`${r}/api/v1/spaces/${n.spaceId}/assets/${e}`:`${r}/api/v1/spaces/${n.spaceId}/assets/${e.uri}`}}}function l(e){return{"data-ll-id":e._id,"data-ll-schema":e._schema}}function u(e){return{"data-ll-field":e}}var d=`localess-js-sync`;async function f(e,t=!1){return new Promise((t,n)=>{if(a()){n(void 0);return}if(!o()){console.warn(`Localess Sync is loaded only in Visual Editor.`),n(void 0);return}if(window.localess!==void 0){n(void 0);return}if(document.getElementById(d)){n(void 0);return}let r=document.createElement(`script`);r.id=d,r.type=`text/javascript`,r.src=`${e}/scripts/sync-v1.js`,r.async=!0,r.onerror=e=>n(e),r.onload=e=>{console.info(`Localess Sync Script loaded`),t()},document.head.appendChild(r)})}exports.isBrowser=i,exports.isIframe=o,exports.isServer=a,exports.loadLocalessSync=f,exports.localessClient=c,exports.localessEditable=l,exports.localessEditableField=u;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=((e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports))(((e,t)=>{t.exports={}}))(),t=class{cache=new Map;set(e,t){this.cache.set(e,t)}get(e){return this.cache.get(e)}has(e){return this.cache.has(e)}},n=class{set(e,t){}get(e){}has(e){return!1}},r=class{cache=new Map;constructor(e=3e5){this.ttlMs=e}set(e,t){this.cache.set(e,{value:t,expiresAt:Date.now()+this.ttlMs})}get(e){let t=this.cache.get(e);if(t){if(Date.now()>t.expiresAt){this.cache.delete(e);return}return t.value}}has(e){return this.get(e)!==void 0}},i=class{dir;ttlMs;constructor(t=`.localess/cache`,n=3e5){this.dir=t,this.ttlMs=n,(0,e.existsSync)(t)||(0,e.mkdirSync)(t,{recursive:!0})}keyToPath(t){let n=(0,e.createHash)(`md5`).update(t).digest(`hex`);return(0,e.join)(this.dir,`${n}.json`)}set(t,n){try{(0,e.writeFileSync)(this.keyToPath(t),JSON.stringify({value:n,expiresAt:Date.now()+this.ttlMs}))}catch{}}get(t){try{let n=(0,e.readFileSync)(this.keyToPath(t),`utf-8`),r=JSON.parse(n);if(Date.now()>r.expiresAt){try{(0,e.unlinkSync)(this.keyToPath(t))}catch{}return}return r.value}catch{return}}has(e){return this.get(e)!==void 0}},a=`\x1B[0m`,o=`\x1B[34m`,s=()=>typeof window<`u`,c=()=>typeof window>`u`,l=()=>s()&&window.self!==window.top,u=`${o}[Localess:Client]${a}`;function d(e){e.debug&&console.log(u,`Client Options : `,e);let t=e.origin.replace(/\/+$/,``),a={redirect:`follow`,headers:{"Content-Type":`application/json`,Accept:`application/json`,"X-Localess-Agent":`Localess-JS-Client`,"X-Localess-Agent-Version":`0.9.0`}},o=typeof e.cacheTTL==`number`?e.cacheTTL*1e3:void 0,s=e.cacheTTL===!1?new n:e.fileSystemCache?new i(void 0,o):new r(o);return{async getLinks(n){e.debug&&console.log(u,`getLinks() params : `,JSON.stringify(n));let r=``;n?.kind&&(r=`&kind=${n.kind}`);let i=``;n?.parentSlug&&(i=`&parentSlug=${n.parentSlug}`);let o=``;n?.excludeChildren&&(o=`&excludeChildren=${n.excludeChildren}`);let c=`${t}/api/v1/spaces/${e.spaceId}/links?token=${e.token}${r}${i}${o}`;if(e.debug&&console.log(u,`getLinks fetch url : `,c),s.has(c))return e.debug&&console.log(u,`getLinks cache hit`),s.get(c);try{let t=await fetch(c,a);e.debug&&console.log(u,`getLinks status : `,t.status);let n=await t.json();return s.set(c,n),n}catch(e){return console.error(u,`getLinks error : `,e),{}}},async getContentBySlug(n,r){e.debug&&(console.log(u,`getContentBySlug() slug : `,n),console.log(u,`getContentBySlug() params : `,JSON.stringify(r)));let i=``;e?.version&&e.version==`draft`&&(i=`&version=${e.version}`),r?.version&&r.version==`draft`&&(i=`&version=${r.version}`);let o=r?.locale?`&locale=${r.locale}`:``,c=r?.resolveReference?`&resolveReference=${r.resolveReference}`:``,l=r?.resolveLink?`&resolveLink=${r.resolveLink}`:``,d=`${t}/api/v1/spaces/${e.spaceId}/contents/slugs/${n}?token=${e.token}${i}${o}${c}${l}`;if(e.debug&&console.log(u,`getContentBySlug fetch url : `,d),s.has(d))return e.debug&&console.log(u,`getContentBySlug cache hit`),s.get(d);try{let t=await fetch(d,a);e.debug&&console.log(u,`getContentBySlug status : `,t.status);let n=await t.json();return s.set(d,n),n}catch(e){return console.error(u,`getContentBySlug error : `,e),{}}},async getContentById(n,r){e.debug&&(console.log(u,`getContentById() id : `,n),console.log(u,`getContentById() params : `,JSON.stringify(r)));let i=``;e?.version&&e.version==`draft`&&(i=`&version=${e.version}`),r?.version&&r.version==`draft`&&(i=`&version=${r.version}`);let o=r?.locale?`&locale=${r.locale}`:``,c=r?.resolveReference?`&resolveReference=${r.resolveReference}`:``,l=r?.resolveLink?`&resolveLink=${r.resolveLink}`:``,d=`${t}/api/v1/spaces/${e.spaceId}/contents/${n}?token=${e.token}${i}${o}${c}${l}`;if(e.debug&&console.log(u,`getContentById fetch url : `,d),s.has(d))return e.debug&&console.log(u,`getContentById cache hit`),s.get(d);try{let t=await fetch(d,a);e.debug&&console.log(u,`getContentById status : `,t.status);let n=await t.json();return s.set(d,n),n}catch(e){return console.error(u,`getContentById error : `,e),{}}},async getTranslations(n){e.debug&&console.log(u,`getTranslations() locale : `,n);let r=`${t}/api/v1/spaces/${e.spaceId}/translations/${n}?token=${e.token}`;if(e.debug&&console.log(u,`getTranslations fetch url : `,r),s.has(r))return e.debug&&console.log(u,`getTranslations cache hit`),s.get(r);try{let t=await fetch(r,a);e.debug&&console.log(u,`getTranslations status : `,t.status);let n=await t.json();return s.set(r,n),n}catch(e){return console.error(u,`getTranslations error : `,e),{}}},syncScriptUrl(){return`${t}/scripts/sync-v1.js`},assetLink(n){return typeof n==`string`?`${t}/api/v1/spaces/${e.spaceId}/assets/${n}`:`${t}/api/v1/spaces/${e.spaceId}/assets/${n.uri}`}}}function f(e){return{"data-ll-id":e._id,"data-ll-schema":e._schema}}function p(e){return{"data-ll-field":e}}var m=`localess-js-sync`;async function h(e,t=!1){return new Promise((t,n)=>{if(c()){n(void 0);return}if(!l()){console.warn(`Localess Sync is loaded only in Visual Editor.`),n(void 0);return}if(window.localess!==void 0){n(void 0);return}if(document.getElementById(m)){n(void 0);return}let r=document.createElement(`script`);r.id=m,r.type=`text/javascript`,r.src=`${e}/scripts/sync-v1.js`,r.async=!0,r.onerror=e=>n(e),r.onload=e=>{console.info(`Localess Sync Script loaded`),t()},document.head.appendChild(r)})}exports.Cache=t,exports.FileSystemCache=i,exports.NoCache=n,exports.TTLCache=r,exports.isBrowser=s,exports.isIframe=l,exports.isServer=c,exports.loadLocalessSync=h,exports.localessClient=d,exports.localessEditable=f,exports.localessEditableField=p;
package/dist/index.mjs CHANGED
@@ -1,11 +1,25 @@
1
+ //#endregion
1
2
  //#region src/cache.ts
2
- var e = class {
3
+ var e = (/* @__PURE__ */ ((e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports))(((e, t) => {
4
+ t.exports = {};
5
+ })))(), t = class {
6
+ cache = /* @__PURE__ */ new Map();
7
+ set(e, t) {
8
+ this.cache.set(e, t);
9
+ }
10
+ get(e) {
11
+ return this.cache.get(e);
12
+ }
13
+ has(e) {
14
+ return this.cache.has(e);
15
+ }
16
+ }, n = class {
3
17
  set(e, t) {}
4
18
  get(e) {}
5
19
  has(e) {
6
20
  return !1;
7
21
  }
8
- }, t = class {
22
+ }, r = class {
9
23
  cache = /* @__PURE__ */ new Map();
10
24
  constructor(e = 3e5) {
11
25
  this.ttlMs = e;
@@ -29,10 +43,45 @@ var e = class {
29
43
  has(e) {
30
44
  return this.get(e) !== void 0;
31
45
  }
32
- }, n = "\x1B[0m", r = "\x1B[34m", i = () => typeof window < "u", a = () => typeof window > "u", o = () => i() && window.self !== window.top, s = `${r}[Localess:Client]${n}`;
33
- function c(n) {
34
- n.debug && console.log(s, "Client Options : ", n);
35
- let r = n.origin.replace(/\/+$/, ""), i = {
46
+ }, i = class {
47
+ dir;
48
+ ttlMs;
49
+ constructor(t = ".localess/cache", n = 3e5) {
50
+ this.dir = t, this.ttlMs = n, (0, e.existsSync)(t) || (0, e.mkdirSync)(t, { recursive: !0 });
51
+ }
52
+ keyToPath(t) {
53
+ let n = (0, e.createHash)("md5").update(t).digest("hex");
54
+ return (0, e.join)(this.dir, `${n}.json`);
55
+ }
56
+ set(t, n) {
57
+ try {
58
+ (0, e.writeFileSync)(this.keyToPath(t), JSON.stringify({
59
+ value: n,
60
+ expiresAt: Date.now() + this.ttlMs
61
+ }));
62
+ } catch {}
63
+ }
64
+ get(t) {
65
+ try {
66
+ let n = (0, e.readFileSync)(this.keyToPath(t), "utf-8"), r = JSON.parse(n);
67
+ if (Date.now() > r.expiresAt) {
68
+ try {
69
+ (0, e.unlinkSync)(this.keyToPath(t));
70
+ } catch {}
71
+ return;
72
+ }
73
+ return r.value;
74
+ } catch {
75
+ return;
76
+ }
77
+ }
78
+ has(e) {
79
+ return this.get(e) !== void 0;
80
+ }
81
+ }, a = "\x1B[0m", o = "\x1B[34m", s = () => typeof window < "u", c = () => typeof window > "u", l = () => s() && window.self !== window.top, u = `${o}[Localess:Client]${a}`;
82
+ function d(e) {
83
+ e.debug && console.log(u, "Client Options : ", e);
84
+ let t = e.origin.replace(/\/+$/, ""), a = {
36
85
  redirect: "follow",
37
86
  headers: {
38
87
  "Content-Type": "application/json",
@@ -40,99 +89,99 @@ function c(n) {
40
89
  "X-Localess-Agent": "Localess-JS-Client",
41
90
  "X-Localess-Agent-Version": "0.9.0"
42
91
  }
43
- }, a = n.cacheTTL === !1 ? new e() : new t(n.cacheTTL);
92
+ }, o = typeof e.cacheTTL == "number" ? e.cacheTTL * 1e3 : void 0, s = e.cacheTTL === !1 ? new n() : e.fileSystemCache ? new i(void 0, o) : new r(o);
44
93
  return {
45
- async getLinks(e) {
46
- n.debug && console.log(s, "getLinks() params : ", JSON.stringify(e));
47
- let t = "";
48
- e?.kind && (t = `&kind=${e.kind}`);
94
+ async getLinks(n) {
95
+ e.debug && console.log(u, "getLinks() params : ", JSON.stringify(n));
96
+ let r = "";
97
+ n?.kind && (r = `&kind=${n.kind}`);
98
+ let i = "";
99
+ n?.parentSlug && (i = `&parentSlug=${n.parentSlug}`);
49
100
  let o = "";
50
- e?.parentSlug && (o = `&parentSlug=${e.parentSlug}`);
51
- let c = "";
52
- e?.excludeChildren && (c = `&excludeChildren=${e.excludeChildren}`);
53
- let l = `${r}/api/v1/spaces/${n.spaceId}/links?token=${n.token}${t}${o}${c}`;
54
- if (n.debug && console.log(s, "getLinks fetch url : ", l), a.has(l)) return n.debug && console.log(s, "getLinks cache hit"), a.get(l);
101
+ n?.excludeChildren && (o = `&excludeChildren=${n.excludeChildren}`);
102
+ let c = `${t}/api/v1/spaces/${e.spaceId}/links?token=${e.token}${r}${i}${o}`;
103
+ if (e.debug && console.log(u, "getLinks fetch url : ", c), s.has(c)) return e.debug && console.log(u, "getLinks cache hit"), s.get(c);
55
104
  try {
56
- let e = await fetch(l, i);
57
- n.debug && console.log(s, "getLinks status : ", e.status);
58
- let t = await e.json();
59
- return a.set(l, t), t;
105
+ let t = await fetch(c, a);
106
+ e.debug && console.log(u, "getLinks status : ", t.status);
107
+ let n = await t.json();
108
+ return s.set(c, n), n;
60
109
  } catch (e) {
61
- return console.error(s, "getLinks error : ", e), {};
110
+ return console.error(u, "getLinks error : ", e), {};
62
111
  }
63
112
  },
64
- async getContentBySlug(e, t) {
65
- n.debug && (console.log(s, "getContentBySlug() slug : ", e), console.log(s, "getContentBySlug() params : ", JSON.stringify(t)));
66
- let o = "";
67
- n?.version && n.version == "draft" && (o = `&version=${n.version}`), t?.version && t.version == "draft" && (o = `&version=${t.version}`);
68
- let c = t?.locale ? `&locale=${t.locale}` : "", l = t?.resolveReference ? `&resolveReference=${t.resolveReference}` : "", u = t?.resolveLink ? `&resolveLink=${t.resolveLink}` : "", d = `${r}/api/v1/spaces/${n.spaceId}/contents/slugs/${e}?token=${n.token}${o}${c}${l}${u}`;
69
- if (n.debug && console.log(s, "getContentBySlug fetch url : ", d), a.has(d)) return n.debug && console.log(s, "getContentBySlug cache hit"), a.get(d);
113
+ async getContentBySlug(n, r) {
114
+ e.debug && (console.log(u, "getContentBySlug() slug : ", n), console.log(u, "getContentBySlug() params : ", JSON.stringify(r)));
115
+ let i = "";
116
+ e?.version && e.version == "draft" && (i = `&version=${e.version}`), r?.version && r.version == "draft" && (i = `&version=${r.version}`);
117
+ let o = r?.locale ? `&locale=${r.locale}` : "", c = r?.resolveReference ? `&resolveReference=${r.resolveReference}` : "", l = r?.resolveLink ? `&resolveLink=${r.resolveLink}` : "", d = `${t}/api/v1/spaces/${e.spaceId}/contents/slugs/${n}?token=${e.token}${i}${o}${c}${l}`;
118
+ if (e.debug && console.log(u, "getContentBySlug fetch url : ", d), s.has(d)) return e.debug && console.log(u, "getContentBySlug cache hit"), s.get(d);
70
119
  try {
71
- let e = await fetch(d, i);
72
- n.debug && console.log(s, "getContentBySlug status : ", e.status);
73
- let t = await e.json();
74
- return a.set(d, t), t;
120
+ let t = await fetch(d, a);
121
+ e.debug && console.log(u, "getContentBySlug status : ", t.status);
122
+ let n = await t.json();
123
+ return s.set(d, n), n;
75
124
  } catch (e) {
76
- return console.error(s, "getContentBySlug error : ", e), {};
125
+ return console.error(u, "getContentBySlug error : ", e), {};
77
126
  }
78
127
  },
79
- async getContentById(e, t) {
80
- n.debug && (console.log(s, "getContentById() id : ", e), console.log(s, "getContentById() params : ", JSON.stringify(t)));
81
- let o = "";
82
- n?.version && n.version == "draft" && (o = `&version=${n.version}`), t?.version && t.version == "draft" && (o = `&version=${t.version}`);
83
- let c = t?.locale ? `&locale=${t.locale}` : "", l = t?.resolveReference ? `&resolveReference=${t.resolveReference}` : "", u = t?.resolveLink ? `&resolveLink=${t.resolveLink}` : "", d = `${r}/api/v1/spaces/${n.spaceId}/contents/${e}?token=${n.token}${o}${c}${l}${u}`;
84
- if (n.debug && console.log(s, "getContentById fetch url : ", d), a.has(d)) return n.debug && console.log(s, "getContentById cache hit"), a.get(d);
128
+ async getContentById(n, r) {
129
+ e.debug && (console.log(u, "getContentById() id : ", n), console.log(u, "getContentById() params : ", JSON.stringify(r)));
130
+ let i = "";
131
+ e?.version && e.version == "draft" && (i = `&version=${e.version}`), r?.version && r.version == "draft" && (i = `&version=${r.version}`);
132
+ let o = r?.locale ? `&locale=${r.locale}` : "", c = r?.resolveReference ? `&resolveReference=${r.resolveReference}` : "", l = r?.resolveLink ? `&resolveLink=${r.resolveLink}` : "", d = `${t}/api/v1/spaces/${e.spaceId}/contents/${n}?token=${e.token}${i}${o}${c}${l}`;
133
+ if (e.debug && console.log(u, "getContentById fetch url : ", d), s.has(d)) return e.debug && console.log(u, "getContentById cache hit"), s.get(d);
85
134
  try {
86
- let e = await fetch(d, i);
87
- n.debug && console.log(s, "getContentById status : ", e.status);
88
- let t = await e.json();
89
- return a.set(d, t), t;
135
+ let t = await fetch(d, a);
136
+ e.debug && console.log(u, "getContentById status : ", t.status);
137
+ let n = await t.json();
138
+ return s.set(d, n), n;
90
139
  } catch (e) {
91
- return console.error(s, "getContentById error : ", e), {};
140
+ return console.error(u, "getContentById error : ", e), {};
92
141
  }
93
142
  },
94
- async getTranslations(e) {
95
- n.debug && console.log(s, "getTranslations() locale : ", e);
96
- let t = `${r}/api/v1/spaces/${n.spaceId}/translations/${e}?token=${n.token}`;
97
- if (n.debug && console.log(s, "getTranslations fetch url : ", t), a.has(t)) return n.debug && console.log(s, "getTranslations cache hit"), a.get(t);
143
+ async getTranslations(n) {
144
+ e.debug && console.log(u, "getTranslations() locale : ", n);
145
+ let r = `${t}/api/v1/spaces/${e.spaceId}/translations/${n}?token=${e.token}`;
146
+ if (e.debug && console.log(u, "getTranslations fetch url : ", r), s.has(r)) return e.debug && console.log(u, "getTranslations cache hit"), s.get(r);
98
147
  try {
99
- let e = await fetch(t, i);
100
- n.debug && console.log(s, "getTranslations status : ", e.status);
101
- let r = await e.json();
102
- return a.set(t, r), r;
148
+ let t = await fetch(r, a);
149
+ e.debug && console.log(u, "getTranslations status : ", t.status);
150
+ let n = await t.json();
151
+ return s.set(r, n), n;
103
152
  } catch (e) {
104
- return console.error(s, "getTranslations error : ", e), {};
153
+ return console.error(u, "getTranslations error : ", e), {};
105
154
  }
106
155
  },
107
156
  syncScriptUrl() {
108
- return `${r}/scripts/sync-v1.js`;
157
+ return `${t}/scripts/sync-v1.js`;
109
158
  },
110
- assetLink(e) {
111
- return typeof e == "string" ? `${r}/api/v1/spaces/${n.spaceId}/assets/${e}` : `${r}/api/v1/spaces/${n.spaceId}/assets/${e.uri}`;
159
+ assetLink(n) {
160
+ return typeof n == "string" ? `${t}/api/v1/spaces/${e.spaceId}/assets/${n}` : `${t}/api/v1/spaces/${e.spaceId}/assets/${n.uri}`;
112
161
  }
113
162
  };
114
163
  }
115
164
  //#endregion
116
165
  //#region src/editable.ts
117
- function l(e) {
166
+ function f(e) {
118
167
  return {
119
168
  "data-ll-id": e._id,
120
169
  "data-ll-schema": e._schema
121
170
  };
122
171
  }
123
- function u(e) {
172
+ function p(e) {
124
173
  return { "data-ll-field": e };
125
174
  }
126
175
  //#endregion
127
176
  //#region src/sync.ts
128
- var d = "localess-js-sync";
129
- async function f(e, t = !1) {
177
+ var m = "localess-js-sync";
178
+ async function h(e, t = !1) {
130
179
  return new Promise((t, n) => {
131
- if (a()) {
180
+ if (c()) {
132
181
  n(void 0);
133
182
  return;
134
183
  }
135
- if (!o()) {
184
+ if (!l()) {
136
185
  console.warn("Localess Sync is loaded only in Visual Editor."), n(void 0);
137
186
  return;
138
187
  }
@@ -140,15 +189,15 @@ async function f(e, t = !1) {
140
189
  n(void 0);
141
190
  return;
142
191
  }
143
- if (document.getElementById(d)) {
192
+ if (document.getElementById(m)) {
144
193
  n(void 0);
145
194
  return;
146
195
  }
147
196
  let r = document.createElement("script");
148
- r.id = d, r.type = "text/javascript", r.src = `${e}/scripts/sync-v1.js`, r.async = !0, r.onerror = (e) => n(e), r.onload = (e) => {
197
+ r.id = m, r.type = "text/javascript", r.src = `${e}/scripts/sync-v1.js`, r.async = !0, r.onerror = (e) => n(e), r.onload = (e) => {
149
198
  console.info("Localess Sync Script loaded"), t();
150
199
  }, document.head.appendChild(r);
151
200
  });
152
201
  }
153
202
  //#endregion
154
- export { i as isBrowser, o as isIframe, a as isServer, f as loadLocalessSync, c as localessClient, l as localessEditable, u as localessEditableField };
203
+ export { t as Cache, i as FileSystemCache, n as NoCache, r as TTLCache, s as isBrowser, l as isIframe, c as isServer, h as loadLocalessSync, d as localessClient, f as localessEditable, p as localessEditableField };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@localess/client",
3
- "version": "3.0.6-dev.20260502214443",
3
+ "version": "3.0.6-dev.20260512074100",
4
4
  "description": "Universal JavaScript/TypeScript SDK for Localess's API.",
5
5
  "keywords": [
6
6
  "localess",