@smartcorehub/localization-sdk 1.0.3542 → 1.0.3591

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
@@ -24,6 +24,80 @@ Quando o pacote estiver publicado no npm:
24
24
  npm install @smartcorehub/localization-sdk
25
25
  ~~~
26
26
 
27
+ ## Cenarios de consumo suportados
28
+
29
+ - TypeScript via npm (ESM/CJS + tipos `.d.ts`)
30
+ - JavaScript puro via npm (ESM/CJS)
31
+ - HTML simples via CDN com bundle global `window.LocalizationSDK`
32
+
33
+ ### 1) Projetos TypeScript (via npm)
34
+
35
+ ~~~ts
36
+ import { createLocalizationClient } from '@smartcorehub/localization-sdk';
37
+
38
+ const client = createLocalizationClient({
39
+ baseUrl: 'https://api.smartcorehub.io/',
40
+ token: 'SEU_TOKEN',
41
+ locale: 'pt-BR',
42
+ cache: {
43
+ enabled: true,
44
+ ttlMs: 60000
45
+ }
46
+ });
47
+
48
+ const title = await client.getCurrentLanguage('home.title');
49
+ console.log(title);
50
+ ~~~
51
+
52
+ ### 2) Projetos JavaScript puro (via npm)
53
+
54
+ ~~~js
55
+ const { createLocalizationClient, LocalStorageCacheProvider } = require('@smartcorehub/localization-sdk');
56
+
57
+ const client = createLocalizationClient({
58
+ baseUrl: 'https://api.smartcorehub.io/',
59
+ token: 'SEU_TOKEN',
60
+ cache: {
61
+ enabled: true,
62
+ provider: new LocalStorageCacheProvider(),
63
+ ttlMs: 120000
64
+ }
65
+ });
66
+
67
+ client.listResources()
68
+ .then((resources) => console.log(resources.length))
69
+ .catch((error) => console.error(error));
70
+ ~~~
71
+
72
+ ### 3) Sites HTML simples via CDN (`<script>`)
73
+
74
+ O pacote publica `dist/umd/localization-sdk.min.js`, consumivel por jsDelivr e unpkg.
75
+
76
+ ~~~html
77
+ <script src="https://cdn.jsdelivr.net/npm/@smartcorehub/localization-sdk/dist/umd/localization-sdk.min.js"></script>
78
+ <script>
79
+ const client = window.LocalizationSDK.createClient({
80
+ baseUrl: 'https://api.smartcorehub.io/',
81
+ token: 'SEU_TOKEN',
82
+ cache: {
83
+ enabled: true,
84
+ provider: new window.LocalizationSDK.MemoryCacheProvider(),
85
+ ttlMs: 60000
86
+ }
87
+ });
88
+
89
+ client.getCurrentLanguage('home.title')
90
+ .then((value) => console.log(value))
91
+ .catch((error) => console.error(error));
92
+ </script>
93
+ ~~~
94
+
95
+ Opcao equivalente em unpkg:
96
+
97
+ ~~~html
98
+ <script src="https://unpkg.com/@smartcorehub/localization-sdk/dist/umd/localization-sdk.min.js"></script>
99
+ ~~~
100
+
27
101
  ## Primeiro uso rapido (TypeScript, React, Next.js, Node)
28
102
 
29
103
  ~~~ts
@@ -49,6 +123,35 @@ const list = await localizationClient.listResources();
49
123
  // list retorna objetos { key, value, language }
50
124
  ~~~
51
125
 
126
+ ## API global do build UMD
127
+
128
+ No bundle UMD (CDN), o SDK e exposto como `window.LocalizationSDK` com os membros abaixo:
129
+
130
+ - `createClient(options)` (alias para `createLocalizationClient`)
131
+ - `createLocalizationClient(options)`
132
+ - `XAuthTokenProvider`
133
+ - `MemoryCacheProvider`
134
+ - `LocalStorageCacheProvider`
135
+ - `SessionStorageCacheProvider`
136
+ - `LocalizationError`, `LocalizationAuthError`, `LocalizationNetworkError`, `LocalizationServerError`, `LocalizationTimeoutError`, `ResourceNotFoundError`
137
+
138
+ Exemplo com autenticacao explicita via `X-Auth-Token` provider:
139
+
140
+ ~~~html
141
+ <script src="https://cdn.jsdelivr.net/npm/@smartcorehub/localization-sdk/dist/umd/localization-sdk.min.js"></script>
142
+ <script>
143
+ const tokenProvider = new window.LocalizationSDK.XAuthTokenProvider('SEU_TOKEN');
144
+
145
+ const client = window.LocalizationSDK.createClient({
146
+ baseUrl: 'https://api.smartcorehub.io/',
147
+ authProvider: tokenProvider,
148
+ cache: { enabled: true }
149
+ });
150
+
151
+ client.listResources().then(console.log).catch(console.error);
152
+ </script>
153
+ ~~~
154
+
52
155
  ## Locale via Accept-Language
53
156
 
54
157
  O SDK envia locale usando o header HTTP padrao `Accept-Language`.
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- 'use strict';var core=require('@angular/core'),rxjs=require('rxjs');var S=(o,e,r,t)=>{for(var n=e,i=o.length-1,s;i>=0;i--)(s=o[i])&&(n=(s(n))||n);return n},k=(o,e)=>(r,t)=>e(r,t,o);var u=class{constructor(e){this.token=e;}async getToken(){return this.token?.trim()?this.token:null}};var d=class{constructor(){this.store=new Map;}async get(e){let r=this.store.get(e);return r?r.expiresAt!==void 0&&Date.now()>r.expiresAt?(this.store.delete(e),null):r.value:null}async set(e,r,t){let n=t&&t>0?Date.now()+t:void 0;this.store.set(e,{value:r,expiresAt:n});}async delete(e){this.store.delete(e);}async clear(){this.store.clear();}};var a=class extends Error{constructor(r,t){super(r);this.metadata=t;this.name="LocalizationError";}},h=class extends a{constructor(e="Authentication failed",r){super(e,r),this.name="LocalizationAuthError";}},p=class extends a{constructor(e="Resource not found",r){super(e,r),this.name="ResourceNotFoundError";}},g=class extends a{constructor(e="Localization server error",r){super(e,r),this.name="LocalizationServerError";}},m=class extends a{constructor(e="Network error while contacting localization API",r){super(e,r),this.name="LocalizationNetworkError";}},f=class extends a{constructor(e="Localization request timeout",r){super(e,r),this.name="LocalizationTimeoutError";}};var v=class extends Error{constructor(r,t,n){super(`Request failed with status ${r}`);this.statusCode=r;this.responseBody=t;this.responseHeaders=n;this.name="HttpStatusError";}},y=class extends Error{constructor(r){super(`Request timed out after ${r}ms`);this.timeoutMs=r;this.name="HttpTimeoutError";}},l=class extends Error{constructor(r){super("Network error while sending request");this.causeError=r;this.name="HttpNetworkError";}},L=class{constructor(e){this.options=e;this.fetchFn=e.fetchFn??globalThis.fetch.bind(globalThis);}async request(e){let r=e.timeoutMs??this.options.timeoutMs,t=new AbortController,n=setTimeout(()=>t.abort(),r),i=new Request(this.resolveUrl(e),{method:e.method,headers:{"Content-Type":"application/json",...this.options.defaultHeaders,...e.headers},body:e.body===void 0?void 0:JSON.stringify(e.body),signal:t.signal});try{let s=await this.runRequestMiddleware(i),$;try{$=await this.fetchFn(s);}catch(T){throw this.isAbortError(T)?new y(r):new l(T)}let c=await this.runResponseMiddleware($);if(!c.ok){let T=await c.text();throw new v(c.status,T,c.headers)}let D=await this.parseResponse(c);return {status:c.status,headers:c.headers,data:D}}catch(s){throw await this.runErrorMiddleware(this.toError(s)),s}finally{clearTimeout(n);}}resolveUrl(e){let r=new URL(e.path,this.options.baseUrl);return e.query&&Object.entries(e.query).forEach(([t,n])=>{n!==void 0&&r.searchParams.set(t,String(n));}),r.toString()}async runRequestMiddleware(e){let r=e;for(let t of this.options.middleware??[])t.onRequest&&(r=await t.onRequest(r));return r}async runResponseMiddleware(e){let r=e;for(let t of this.options.middleware??[])t.onResponse&&(r=await t.onResponse(r));return r}async runErrorMiddleware(e){for(let r of this.options.middleware??[])r.onError&&await r.onError(e);}async parseResponse(e){return e.status===204?null:(e.headers.get("content-type")??"").includes("application/json")?await e.json():await e.text()}toError(e){return e instanceof Error?e:new Error("Unknown request error")}isAbortError(e){return e instanceof DOMException&&e.name==="AbortError"}};var M="localization:listResources",R=class{constructor(e,r,t){this.cacheProvider=e;this.cacheTtlMs=r;this.logger=t;}async getListResources(){this.logger.debug(`listResources:start cacheEnabled=${!!this.cacheProvider}`);let e=await this.cacheProvider?.get(M);return e?this.logger.info(`listResources:cache-hit count=${e.length}`):this.logger.debug("listResources:cache-miss"),e}async storeListResources(e){await this.cacheProvider?.set(M,e,this.cacheTtlMs),this.logger.debug(`listResources:cache-store ttlMs=${this.cacheTtlMs??0} count=${e.length}`);}async invalidate(e){if(this.logger.debug(`invalidateCache:start scope=${e??"all"}`),!this.cacheProvider){this.logger.debug("invalidateCache:skipped no-cache-provider");return}if(e){await this.cacheProvider.delete(e),this.logger.info(`invalidateCache:deleted key=${e}`);return}await this.cacheProvider.clear(),this.logger.info("invalidateCache:cleared-all");}};var z=class{constructor(e){this.logger=e;}async run(e,r){try{return await r()}catch(t){let n=this.map(t);throw this.logger.errorForOperation(e,n,t),n}}validateRequired(e,r){if(!e?.trim())throw new a(`${r} is required`)}map(e){return e instanceof a?e:e instanceof y?new f(e.message):e instanceof l?new m(e.message):e instanceof v?this.mapStatusError(e):new a("Unexpected localization SDK error")}preserveCause(e){let r=this.map(e);return r.cause??(r.cause=e),r}mapStatusError(e){return e.statusCode===401||e.statusCode===403?new h("Invalid token for localization endpoint",{statusCode:e.statusCode}):e.statusCode===404?new p("Localization resource was not found",{statusCode:e.statusCode}):e.statusCode>=500?new g("Localization API is unavailable",{statusCode:e.statusCode}):new a(e.message,{statusCode:e.statusCode})}};var K="[LocalizationSdk]",P=class{constructor(e=false){this.enabled=e;}debug(e){this.write("debug",e);}info(e){this.write("info",e);}errorForOperation(e,r,t){this.write("error",`${e}:error ${this.formatErrorDetails(r,t)}`);}formatErrorDetails(e,r){let t=this.getOriginalCause(e,r),n=this.getErrorMessage(t),i=[`type=${e.name}`,`message=${e.message}`];return n&&n!==e.message&&i.push(`original=${n}`),e instanceof a&&e.metadata?.statusCode&&i.push(`statusCode=${e.metadata.statusCode}`),i.join(" ")}getOriginalCause(e,r){let n=e.cause??r;return n instanceof l?n.causeError:n}getErrorMessage(e){return e instanceof Error?e.message:typeof e=="string"?e:"unknown-error"}write(e,r){if(!this.enabled)return;let t=this.resolveIcon(e,r),n=`${K} ${t} ${r}`;switch(e){case "debug":console.debug(n);break;case "info":console.info(n);break;case "error":console.error(n);break}}resolveIcon(e,r){return e==="error"||r.includes(":error")?"\u274C":r.includes("request:start")||r.includes(":api-call")?"\u{1F310}":r.includes("request:success")?"\u{1F4E1}":r.includes(":cache-hit")||r.includes("cache-hit")?"\u{1F5C4}\uFE0F":r.includes("cache-miss")?"\u{1F4ED}":r.includes("cache-store")?"\u{1F4BE}":r.includes("invalidateCache")?"\u{1F9F9}":r.includes("listResources")?"\u{1F4DA}":r.includes("getByLanguage")?"\u{1F30D}":r.includes("getCurrentLanguage")?"\u{1F22F}":r.includes(":start")?"\u{1F680}":r.includes(":success")?"\u2705":e==="info"?"\u2139\uFE0F":"\u{1F50E}"}};var x=class{constructor(e){this.dependencies=e;this.logger=new P(e.enableLogs),this.cacheHelper=new R(e.cacheProvider,e.cacheTtlMs,this.logger),this.errorHandler=new z(this.logger);}async getCurrentLanguage(e,r){return this.errorHandler.run("getCurrentLanguage",async()=>{if(this.errorHandler.validateRequired(e,"resourceKey"),this.logger.debug(`getCurrentLanguage:start resourceKey=${e}`),this.isCacheEnabled()){let n=await this.resolveFromCachedResources(e);return this.logger.info(`getCurrentLanguage:cache-${n?"hit":"miss"} resourceKey=${e} hasValue=${!!n}`),n}this.logger.info(`getCurrentLanguage:api-call path=api/localization/client/currentlanguage resourceKey=${e}`);let t=await this.send({method:"GET",path:"api/localization/client/currentlanguage",query:{resourceKey:e},headers:this.resolveLocaleHeader(r)});return this.logger.info(`getCurrentLanguage:success resourceKey=${e} hasValue=${!!t}`),t??""})}async getByLanguage(e,r,t){return this.errorHandler.run("getByLanguage",async()=>{if(this.errorHandler.validateRequired(e,"resourceKey"),this.errorHandler.validateRequired(r,"languageKey"),this.logger.debug(`getByLanguage:start resourceKey=${e} languageKey=${r}`),this.isCacheEnabled()){let i=await this.resolveFromCachedResources(e,r);return this.logger.info(`getByLanguage:cache-${i?"hit":"miss"} resourceKey=${e} languageKey=${r} hasValue=${!!i}`),i}this.logger.info(`getByLanguage:api-call path=api/localization/client/bylanguage resourceKey=${e} languageKey=${r}`);let n=await this.send({method:"GET",path:"api/localization/client/bylanguage",query:{resourceKey:e,languageKey:r},headers:this.resolveLocaleHeader(t)});return this.logger.info(`getByLanguage:success resourceKey=${e} languageKey=${r} hasValue=${!!n}`),n??""})}async listResources(){return this.errorHandler.run("listResources",async()=>{if(this.isCacheEnabled()){let t=await this.cacheHelper.getListResources();if(t)return this.logger.info(`listResources:cache-hit-return count=${t.length}`),t}else this.logger.debug("listResources:cache-disabled");this.logger.info("listResources:api-call path=api/localization/client/list");let r=(await this.send({method:"GET",path:"api/localization/client/list"})??[]).map(t=>({key:t.resourceKey,value:t.value,language:t.languageKey}));return this.isCacheEnabled()&&await this.cacheHelper.storeListResources(r),this.logger.info(`listResources:success count=${r.length}`),r})}async invalidateCache(e){return this.errorHandler.run("invalidateCache",async()=>this.cacheHelper.invalidate(e))}async clearCache(){return this.errorHandler.run("clearCache",async()=>this.cacheHelper.invalidate())}async resolveFromCachedResources(e,r){return (await this.listResources()).find(i=>i.key!==e?false:r===void 0?true:i.language===r)?.value??""}async send(e){try{let r=await this.dependencies.authProvider?.getToken(),t=r?{...e.headers,"X-Auth-Token":r}:e.headers;this.logger.debug(`request:start method=${e.method} path=${e.path} hasAuth=${!!r}`);let n=await this.dependencies.httpTransport.request({...e,headers:t});return this.logger.debug(`request:success method=${e.method} path=${e.path} status=${n.status}`),n.data}catch(r){throw this.errorHandler.preserveCause(r)}}resolveLocaleHeader(e){let r=e?.locale?.trim()||this.dependencies.locale?.trim()||this.resolveBrowserLocale();if(r)return {"Accept-Language":r}}resolveBrowserLocale(){return globalThis.navigator?.language?.trim()||void 0}isCacheEnabled(){if(this.dependencies.cacheEnabled!==void 0)return this.logger.debug(`isCacheEnabled: enabled=${this.dependencies.cacheEnabled} source=cacheEnabled-flag`),this.dependencies.cacheEnabled;let e=!!this.dependencies.cacheProvider;return this.logger.debug(`isCacheEnabled: enabled=${e} source=cacheProvider`),e}};function O(o){_(o);let e=o.cache?.enabled??false,r=e?o.cache?.provider??new d:void 0,t=new L({baseUrl:o.baseUrl,fetchFn:o.fetchFn,timeoutMs:o.timeoutMs??1e4,defaultHeaders:o.headers,middleware:o.middleware});return new x({httpTransport:t,authProvider:o.authProvider??(o.token?new u(o.token):void 0),locale:o.locale,cacheEnabled:e,cacheProvider:r,cacheTtlMs:o.cache?.ttlMs,enableLogs:o.enableLogs??false})}function _(o){if(!o?.baseUrl?.trim())throw new a("baseUrl is required to create localization client")}var w=class{constructor(e){this.storage=e;}async get(e){let r=this.storage.getItem(e);if(!r)return null;let t=this.safeParse(r);return t?t.expiresAt!==void 0&&Date.now()>t.expiresAt?(this.storage.removeItem(e),null):t.value:(this.storage.removeItem(e),null)}async set(e,r,t){let n=t&&t>0?Date.now()+t:void 0,i={value:r,expiresAt:n};this.storage.setItem(e,JSON.stringify(i));}async delete(e){this.storage.removeItem(e);}async clear(){this.storage.clear();}safeParse(e){try{return JSON.parse(e)}catch{return null}}},A=class extends w{constructor(){super(N("localStorage"));}},H=class extends w{constructor(){super(N("sessionStorage"));}};function N(o){let e=typeof window>"u"?void 0:window[o];return e||U()}function U(){let o=new Map;return {get length(){return o.size},clear:()=>{o.clear();},getItem:e=>o.get(e)??null,key:e=>Array.from(o.keys())[e]??null,removeItem:e=>{o.delete(e);},setItem:(e,r)=>{o.set(e,r);}}}var I=new core.InjectionToken("LOCALIZATION_SDK_OPTIONS"),C=new core.InjectionToken("LOCALIZATION_CLIENT");function Z(o){return core.makeEnvironmentProviders([{provide:I,useValue:o},{provide:C,useFactory:()=>O(o)}])}exports.LocalizationService=class E{constructor(e){this.client=e;}getCurrentLanguage(e){return rxjs.from(this.client.getCurrentLanguage(e))}getByLanguage(e,r){return rxjs.from(this.client.getByLanguage(e,r))}listResources(){return rxjs.from(this.client.listResources())}invalidateCache(e){return rxjs.from(this.client.invalidateCache(e))}clearCache(){return rxjs.from(this.client.clearCache())}};exports.LocalizationService=S([core.Injectable({providedIn:"root"}),k(0,core.Inject(C))],exports.LocalizationService);exports.FetchHttpTransport=L;exports.LOCALIZATION_CLIENT=C;exports.LOCALIZATION_SDK_OPTIONS=I;exports.LocalStorageCacheProvider=A;exports.LocalizationAuthError=h;exports.LocalizationError=a;exports.LocalizationNetworkError=m;exports.LocalizationServerError=g;exports.LocalizationTimeoutError=f;exports.MemoryCacheProvider=d;exports.ResourceNotFoundError=p;exports.SessionStorageCacheProvider=H;exports.StorageCacheProvider=w;exports.XAuthTokenProvider=u;exports.createLocalizationClient=O;exports.provideLocalization=Z;
1
+ 'use strict';var core=require('@angular/core'),rxjs=require('rxjs');var S=(o,e,r,t)=>{for(var n=e,i=o.length-1,s;i>=0;i--)(s=o[i])&&(n=(s(n))||n);return n},k=(o,e)=>(r,t)=>e(r,t,o);var u=class{constructor(e){this.token=e;}async getToken(){return this.token?.trim()?this.token:null}};var d=class{constructor(){this.store=new Map;}async get(e){let r=this.store.get(e);return r?r.expiresAt!==void 0&&Date.now()>r.expiresAt?(this.store.delete(e),null):r.value:null}async set(e,r,t){let n=t&&t>0?Date.now()+t:void 0;this.store.set(e,{value:r,expiresAt:n});}async delete(e){this.store.delete(e);}async clear(){this.store.clear();}};var a=class extends Error{constructor(r,t){super(r);this.metadata=t;this.name="LocalizationError";}},h=class extends a{constructor(e="Authentication failed",r){super(e,r),this.name="LocalizationAuthError";}},p=class extends a{constructor(e="Resource not found",r){super(e,r),this.name="ResourceNotFoundError";}},g=class extends a{constructor(e="Localization server error",r){super(e,r),this.name="LocalizationServerError";}},m=class extends a{constructor(e="Network error while contacting localization API",r){super(e,r),this.name="LocalizationNetworkError";}},f=class extends a{constructor(e="Localization request timeout",r){super(e,r),this.name="LocalizationTimeoutError";}};var v=class extends Error{constructor(r,t,n){super(`Request failed with status ${r}`);this.statusCode=r;this.responseBody=t;this.responseHeaders=n;this.name="HttpStatusError";}},y=class extends Error{constructor(r){super(`Request timed out after ${r}ms`);this.timeoutMs=r;this.name="HttpTimeoutError";}},l=class extends Error{constructor(r){super("Network error while sending request");this.causeError=r;this.name="HttpNetworkError";}},L=class{constructor(e){this.options=e;this.fetchFn=e.fetchFn??globalThis.fetch.bind(globalThis);}async request(e){let r=e.timeoutMs??this.options.timeoutMs,t=new AbortController,n=setTimeout(()=>t.abort(),r),i=new Request(this.resolveUrl(e),{method:e.method,headers:{"Content-Type":"application/json",...this.options.defaultHeaders,...e.headers},body:e.body===void 0?void 0:JSON.stringify(e.body),signal:t.signal});try{let s=await this.runRequestMiddleware(i),$;try{$=await this.fetchFn(s);}catch(T){throw this.isAbortError(T)?new y(r):new l(T)}let c=await this.runResponseMiddleware($);if(!c.ok){let T=await c.text();throw new v(c.status,T,c.headers)}let D=await this.parseResponse(c);return {status:c.status,headers:c.headers,data:D}}catch(s){throw await this.runErrorMiddleware(this.toError(s)),s}finally{clearTimeout(n);}}resolveUrl(e){let r=new URL(e.path,this.options.baseUrl);return e.query&&Object.entries(e.query).forEach(([t,n])=>{n!==void 0&&r.searchParams.set(t,String(n));}),r.toString()}async runRequestMiddleware(e){let r=e;for(let t of this.options.middleware??[])t.onRequest&&(r=await t.onRequest(r));return r}async runResponseMiddleware(e){let r=e;for(let t of this.options.middleware??[])t.onResponse&&(r=await t.onResponse(r));return r}async runErrorMiddleware(e){for(let r of this.options.middleware??[])r.onError&&await r.onError(e);}async parseResponse(e){return e.status===204?null:(e.headers.get("content-type")??"").includes("application/json")?await e.json():await e.text()}toError(e){return e instanceof Error?e:new Error("Unknown request error")}isAbortError(e){return e instanceof DOMException&&e.name==="AbortError"}};var M="localization:listResources",R=class{constructor(e,r,t){this.cacheProvider=e;this.cacheTtlMs=r;this.logger=t;}async getListResources(){this.logger.debug(`listResources:start cacheEnabled=${!!this.cacheProvider}`);let e=await this.cacheProvider?.get(M);return e?this.logger.info(`listResources:cache-hit count=${e.length}`):this.logger.debug("listResources:cache-miss"),e}async storeListResources(e){await this.cacheProvider?.set(M,e,this.cacheTtlMs),this.logger.debug(`listResources:cache-store ttlMs=${this.cacheTtlMs??0} count=${e.length}`);}async invalidate(e){if(this.logger.debug(`invalidateCache:start scope=${e??"all"}`),!this.cacheProvider){this.logger.debug("invalidateCache:skipped no-cache-provider");return}if(e){await this.cacheProvider.delete(e),this.logger.info(`invalidateCache:deleted key=${e}`);return}await this.cacheProvider.clear(),this.logger.info("invalidateCache:cleared-all");}};var z=class{constructor(e){this.logger=e;}async run(e,r){try{return await r()}catch(t){let n=this.map(t);throw this.logger.errorForOperation(e,n,t),n}}validateRequired(e,r){if(!e?.trim())throw new a(`${r} is required`)}map(e){return e instanceof a?e:e instanceof y?new f(e.message):e instanceof l?new m(e.message):e instanceof v?this.mapStatusError(e):new a("Unexpected localization SDK error")}preserveCause(e){let r=this.map(e);return r.cause??(r.cause=e),r}mapStatusError(e){return e.statusCode===401||e.statusCode===403?new h("Invalid token for localization endpoint",{statusCode:e.statusCode}):e.statusCode===404?new p("Localization resource was not found",{statusCode:e.statusCode}):e.statusCode>=500?new g("Localization API is unavailable",{statusCode:e.statusCode}):new a(e.message,{statusCode:e.statusCode})}};var K="[LocalizationSdk]",P=class{constructor(e=false){this.enabled=e;}debug(e){this.write("debug",e);}info(e){this.write("info",e);}errorForOperation(e,r,t){this.write("error",`${e}:error ${this.formatErrorDetails(r,t)}`);}formatErrorDetails(e,r){let t=this.getOriginalCause(e,r),n=this.getErrorMessage(t),i=[`type=${e.name}`,`message=${e.message}`];return n&&n!==e.message&&i.push(`original=${n}`),e instanceof a&&e.metadata?.statusCode&&i.push(`statusCode=${e.metadata.statusCode}`),i.join(" ")}getOriginalCause(e,r){let n=e.cause??r;return n instanceof l?n.causeError:n}getErrorMessage(e){return e instanceof Error?e.message:typeof e=="string"?e:"unknown-error"}write(e,r){if(!this.enabled)return;let t=this.resolveIcon(e,r),n=`${K} ${t} ${r}`;switch(e){case "debug":console.debug(n);break;case "info":console.info(n);break;case "error":console.error(n);break}}resolveIcon(e,r){return e==="error"||r.includes(":error")?"\u274C":r.includes("request:start")||r.includes(":api-call")?"\u{1F310}":r.includes("request:success")?"\u{1F4E1}":r.includes(":cache-hit")||r.includes("cache-hit")?"\u{1F5C4}\uFE0F":r.includes("cache-miss")?"\u{1F4ED}":r.includes("cache-store")?"\u{1F4BE}":r.includes("invalidateCache")?"\u{1F9F9}":r.includes("listResources")?"\u{1F4DA}":r.includes("getByLanguage")?"\u{1F30D}":r.includes("getCurrentLanguage")?"\u{1F22F}":r.includes(":start")?"\u{1F680}":r.includes(":success")?"\u2705":e==="info"?"\u2139\uFE0F":"\u{1F50E}"}};var x=class{constructor(e){this.dependencies=e;this.logger=new P(e.enableLogs),this.cacheHelper=new R(e.cacheProvider,e.cacheTtlMs,this.logger),this.errorHandler=new z(this.logger);}async getCurrentLanguage(e,r){return this.errorHandler.run("getCurrentLanguage",async()=>{if(this.errorHandler.validateRequired(e,"resourceKey"),this.logger.debug(`getCurrentLanguage:start resourceKey=${e}`),this.isCacheEnabled()){let n=await this.resolveFromCachedResources(e);return this.logger.info(`getCurrentLanguage:cache-${n?"hit":"miss"} resourceKey=${e} hasValue=${!!n}`),n}this.logger.info(`getCurrentLanguage:api-call path=api/localization/client/currentlanguage resourceKey=${e}`);let t=await this.send({method:"GET",path:"api/localization/client/currentlanguage",query:{resourceKey:e},headers:this.resolveLocaleHeader(r)});return this.logger.info(`getCurrentLanguage:success resourceKey=${e} hasValue=${!!t}`),t??""})}async getByLanguage(e,r,t){return this.errorHandler.run("getByLanguage",async()=>{if(this.errorHandler.validateRequired(e,"resourceKey"),this.errorHandler.validateRequired(r,"languageKey"),this.logger.debug(`getByLanguage:start resourceKey=${e} languageKey=${r}`),this.isCacheEnabled()){let i=await this.resolveFromCachedResources(e,r);return this.logger.info(`getByLanguage:cache-${i?"hit":"miss"} resourceKey=${e} languageKey=${r} hasValue=${!!i}`),i}this.logger.info(`getByLanguage:api-call path=api/localization/client/bylanguage resourceKey=${e} languageKey=${r}`);let n=await this.send({method:"GET",path:"api/localization/client/bylanguage",query:{resourceKey:e,languageKey:r},headers:this.resolveLocaleHeader(t)});return this.logger.info(`getByLanguage:success resourceKey=${e} languageKey=${r} hasValue=${!!n}`),n??""})}async listResources(){return this.errorHandler.run("listResources",async()=>{if(this.isCacheEnabled()){let t=await this.cacheHelper.getListResources();if(t)return this.logger.info(`listResources:cache-hit-return count=${t.length}`),t}else this.logger.debug("listResources:cache-disabled");this.logger.info("listResources:api-call path=api/localization/client/list");let r=(await this.send({method:"GET",path:"api/localization/client/list"})??[]).map(t=>({key:t.resourceKey,value:t.value,language:t.languageKey}));return this.isCacheEnabled()&&await this.cacheHelper.storeListResources(r),this.logger.info(`listResources:success count=${r.length}`),r})}async invalidateCache(e){return this.errorHandler.run("invalidateCache",async()=>this.cacheHelper.invalidate(e))}async clearCache(){return this.errorHandler.run("clearCache",async()=>this.cacheHelper.invalidate())}async resolveFromCachedResources(e,r){return (await this.listResources()).find(i=>i.key!==e?false:r===void 0?true:i.language===r)?.value??""}async send(e){try{let r=await this.dependencies.authProvider?.getToken(),t=r?{...e.headers,"X-Auth-Token":r}:e.headers;this.logger.debug(`request:start method=${e.method} path=${e.path} hasAuth=${!!r}`);let n=await this.dependencies.httpTransport.request({...e,headers:t});return this.logger.debug(`request:success method=${e.method} path=${e.path} status=${n.status}`),n.data}catch(r){throw this.errorHandler.preserveCause(r)}}resolveLocaleHeader(e){let r=e?.locale?.trim()||this.dependencies.locale?.trim()||this.resolveBrowserLocale();if(r)return {"Accept-Language":r}}resolveBrowserLocale(){return globalThis.navigator?.language?.trim()||void 0}isCacheEnabled(){if(this.dependencies.cacheEnabled!==void 0)return this.logger.debug(`isCacheEnabled: enabled=${this.dependencies.cacheEnabled} source=cacheEnabled-flag`),this.dependencies.cacheEnabled;let e=!!this.dependencies.cacheProvider;return this.logger.debug(`isCacheEnabled: enabled=${e} source=cacheProvider`),e}};function O(o){_(o);let e=o.cache?.enabled??false,r=e?o.cache?.provider??new d:void 0,t=new L({baseUrl:o.baseUrl,fetchFn:o.fetchFn,timeoutMs:o.timeoutMs??1e4,defaultHeaders:o.headers,middleware:o.middleware});return new x({httpTransport:t,authProvider:o.authProvider??(o.token?new u(o.token):void 0),locale:o.locale,cacheEnabled:e,cacheProvider:r,cacheTtlMs:o.cache?.ttlMs,enableLogs:o.enableLogs??false})}function _(o){if(!o?.baseUrl?.trim())throw new a("baseUrl is required to create localization client")}var w=class{constructor(e){this.storage=e;}async get(e){let r=this.storage.getItem(e);if(!r)return null;let t=this.safeParse(r);return t?t.expiresAt!==void 0&&Date.now()>t.expiresAt?(this.storage.removeItem(e),null):t.value:(this.storage.removeItem(e),null)}async set(e,r,t){let n=t&&t>0?Date.now()+t:void 0,i={value:r,expiresAt:n};this.storage.setItem(e,JSON.stringify(i));}async delete(e){this.storage.removeItem(e);}async clear(){this.storage.clear();}safeParse(e){try{return JSON.parse(e)}catch{return null}}},A=class extends w{constructor(){super(N("localStorage"));}},H=class extends w{constructor(){super(N("sessionStorage"));}};function N(o){let e=typeof globalThis.window>"u"?void 0:globalThis.window[o];return e||U()}function U(){let o=new Map;return {get length(){return o.size},clear:()=>{o.clear();},getItem:e=>o.get(e)??null,key:e=>Array.from(o.keys())[e]??null,removeItem:e=>{o.delete(e);},setItem:(e,r)=>{o.set(e,r);}}}var I=new core.InjectionToken("LOCALIZATION_SDK_OPTIONS"),C=new core.InjectionToken("LOCALIZATION_CLIENT");function Z(o){return core.makeEnvironmentProviders([{provide:I,useValue:o},{provide:C,useFactory:()=>O(o)}])}exports.LocalizationService=class E{constructor(e){this.client=e;}getCurrentLanguage(e){return rxjs.from(this.client.getCurrentLanguage(e))}getByLanguage(e,r){return rxjs.from(this.client.getByLanguage(e,r))}listResources(){return rxjs.from(this.client.listResources())}invalidateCache(e){return rxjs.from(this.client.invalidateCache(e))}clearCache(){return rxjs.from(this.client.clearCache())}};exports.LocalizationService=S([core.Injectable({providedIn:"root"}),k(0,core.Inject(C))],exports.LocalizationService);exports.FetchHttpTransport=L;exports.LOCALIZATION_CLIENT=C;exports.LOCALIZATION_SDK_OPTIONS=I;exports.LocalStorageCacheProvider=A;exports.LocalizationAuthError=h;exports.LocalizationError=a;exports.LocalizationNetworkError=m;exports.LocalizationServerError=g;exports.LocalizationTimeoutError=f;exports.MemoryCacheProvider=d;exports.ResourceNotFoundError=p;exports.SessionStorageCacheProvider=H;exports.StorageCacheProvider=w;exports.XAuthTokenProvider=u;exports.createLocalizationClient=O;exports.provideLocalization=Z;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import {InjectionToken,Injectable,Inject,makeEnvironmentProviders}from'@angular/core';import {from}from'rxjs';var S=(o,e,r,t)=>{for(var n=e,i=o.length-1,s;i>=0;i--)(s=o[i])&&(n=(s(n))||n);return n},k=(o,e)=>(r,t)=>e(r,t,o);var u=class{constructor(e){this.token=e;}async getToken(){return this.token?.trim()?this.token:null}};var d=class{constructor(){this.store=new Map;}async get(e){let r=this.store.get(e);return r?r.expiresAt!==void 0&&Date.now()>r.expiresAt?(this.store.delete(e),null):r.value:null}async set(e,r,t){let n=t&&t>0?Date.now()+t:void 0;this.store.set(e,{value:r,expiresAt:n});}async delete(e){this.store.delete(e);}async clear(){this.store.clear();}};var a=class extends Error{constructor(r,t){super(r);this.metadata=t;this.name="LocalizationError";}},h=class extends a{constructor(e="Authentication failed",r){super(e,r),this.name="LocalizationAuthError";}},p=class extends a{constructor(e="Resource not found",r){super(e,r),this.name="ResourceNotFoundError";}},g=class extends a{constructor(e="Localization server error",r){super(e,r),this.name="LocalizationServerError";}},m=class extends a{constructor(e="Network error while contacting localization API",r){super(e,r),this.name="LocalizationNetworkError";}},f=class extends a{constructor(e="Localization request timeout",r){super(e,r),this.name="LocalizationTimeoutError";}};var v=class extends Error{constructor(r,t,n){super(`Request failed with status ${r}`);this.statusCode=r;this.responseBody=t;this.responseHeaders=n;this.name="HttpStatusError";}},y=class extends Error{constructor(r){super(`Request timed out after ${r}ms`);this.timeoutMs=r;this.name="HttpTimeoutError";}},l=class extends Error{constructor(r){super("Network error while sending request");this.causeError=r;this.name="HttpNetworkError";}},L=class{constructor(e){this.options=e;this.fetchFn=e.fetchFn??globalThis.fetch.bind(globalThis);}async request(e){let r=e.timeoutMs??this.options.timeoutMs,t=new AbortController,n=setTimeout(()=>t.abort(),r),i=new Request(this.resolveUrl(e),{method:e.method,headers:{"Content-Type":"application/json",...this.options.defaultHeaders,...e.headers},body:e.body===void 0?void 0:JSON.stringify(e.body),signal:t.signal});try{let s=await this.runRequestMiddleware(i),$;try{$=await this.fetchFn(s);}catch(T){throw this.isAbortError(T)?new y(r):new l(T)}let c=await this.runResponseMiddleware($);if(!c.ok){let T=await c.text();throw new v(c.status,T,c.headers)}let D=await this.parseResponse(c);return {status:c.status,headers:c.headers,data:D}}catch(s){throw await this.runErrorMiddleware(this.toError(s)),s}finally{clearTimeout(n);}}resolveUrl(e){let r=new URL(e.path,this.options.baseUrl);return e.query&&Object.entries(e.query).forEach(([t,n])=>{n!==void 0&&r.searchParams.set(t,String(n));}),r.toString()}async runRequestMiddleware(e){let r=e;for(let t of this.options.middleware??[])t.onRequest&&(r=await t.onRequest(r));return r}async runResponseMiddleware(e){let r=e;for(let t of this.options.middleware??[])t.onResponse&&(r=await t.onResponse(r));return r}async runErrorMiddleware(e){for(let r of this.options.middleware??[])r.onError&&await r.onError(e);}async parseResponse(e){return e.status===204?null:(e.headers.get("content-type")??"").includes("application/json")?await e.json():await e.text()}toError(e){return e instanceof Error?e:new Error("Unknown request error")}isAbortError(e){return e instanceof DOMException&&e.name==="AbortError"}};var M="localization:listResources",R=class{constructor(e,r,t){this.cacheProvider=e;this.cacheTtlMs=r;this.logger=t;}async getListResources(){this.logger.debug(`listResources:start cacheEnabled=${!!this.cacheProvider}`);let e=await this.cacheProvider?.get(M);return e?this.logger.info(`listResources:cache-hit count=${e.length}`):this.logger.debug("listResources:cache-miss"),e}async storeListResources(e){await this.cacheProvider?.set(M,e,this.cacheTtlMs),this.logger.debug(`listResources:cache-store ttlMs=${this.cacheTtlMs??0} count=${e.length}`);}async invalidate(e){if(this.logger.debug(`invalidateCache:start scope=${e??"all"}`),!this.cacheProvider){this.logger.debug("invalidateCache:skipped no-cache-provider");return}if(e){await this.cacheProvider.delete(e),this.logger.info(`invalidateCache:deleted key=${e}`);return}await this.cacheProvider.clear(),this.logger.info("invalidateCache:cleared-all");}};var z=class{constructor(e){this.logger=e;}async run(e,r){try{return await r()}catch(t){let n=this.map(t);throw this.logger.errorForOperation(e,n,t),n}}validateRequired(e,r){if(!e?.trim())throw new a(`${r} is required`)}map(e){return e instanceof a?e:e instanceof y?new f(e.message):e instanceof l?new m(e.message):e instanceof v?this.mapStatusError(e):new a("Unexpected localization SDK error")}preserveCause(e){let r=this.map(e);return r.cause??(r.cause=e),r}mapStatusError(e){return e.statusCode===401||e.statusCode===403?new h("Invalid token for localization endpoint",{statusCode:e.statusCode}):e.statusCode===404?new p("Localization resource was not found",{statusCode:e.statusCode}):e.statusCode>=500?new g("Localization API is unavailable",{statusCode:e.statusCode}):new a(e.message,{statusCode:e.statusCode})}};var K="[LocalizationSdk]",P=class{constructor(e=false){this.enabled=e;}debug(e){this.write("debug",e);}info(e){this.write("info",e);}errorForOperation(e,r,t){this.write("error",`${e}:error ${this.formatErrorDetails(r,t)}`);}formatErrorDetails(e,r){let t=this.getOriginalCause(e,r),n=this.getErrorMessage(t),i=[`type=${e.name}`,`message=${e.message}`];return n&&n!==e.message&&i.push(`original=${n}`),e instanceof a&&e.metadata?.statusCode&&i.push(`statusCode=${e.metadata.statusCode}`),i.join(" ")}getOriginalCause(e,r){let n=e.cause??r;return n instanceof l?n.causeError:n}getErrorMessage(e){return e instanceof Error?e.message:typeof e=="string"?e:"unknown-error"}write(e,r){if(!this.enabled)return;let t=this.resolveIcon(e,r),n=`${K} ${t} ${r}`;switch(e){case "debug":console.debug(n);break;case "info":console.info(n);break;case "error":console.error(n);break}}resolveIcon(e,r){return e==="error"||r.includes(":error")?"\u274C":r.includes("request:start")||r.includes(":api-call")?"\u{1F310}":r.includes("request:success")?"\u{1F4E1}":r.includes(":cache-hit")||r.includes("cache-hit")?"\u{1F5C4}\uFE0F":r.includes("cache-miss")?"\u{1F4ED}":r.includes("cache-store")?"\u{1F4BE}":r.includes("invalidateCache")?"\u{1F9F9}":r.includes("listResources")?"\u{1F4DA}":r.includes("getByLanguage")?"\u{1F30D}":r.includes("getCurrentLanguage")?"\u{1F22F}":r.includes(":start")?"\u{1F680}":r.includes(":success")?"\u2705":e==="info"?"\u2139\uFE0F":"\u{1F50E}"}};var x=class{constructor(e){this.dependencies=e;this.logger=new P(e.enableLogs),this.cacheHelper=new R(e.cacheProvider,e.cacheTtlMs,this.logger),this.errorHandler=new z(this.logger);}async getCurrentLanguage(e,r){return this.errorHandler.run("getCurrentLanguage",async()=>{if(this.errorHandler.validateRequired(e,"resourceKey"),this.logger.debug(`getCurrentLanguage:start resourceKey=${e}`),this.isCacheEnabled()){let n=await this.resolveFromCachedResources(e);return this.logger.info(`getCurrentLanguage:cache-${n?"hit":"miss"} resourceKey=${e} hasValue=${!!n}`),n}this.logger.info(`getCurrentLanguage:api-call path=api/localization/client/currentlanguage resourceKey=${e}`);let t=await this.send({method:"GET",path:"api/localization/client/currentlanguage",query:{resourceKey:e},headers:this.resolveLocaleHeader(r)});return this.logger.info(`getCurrentLanguage:success resourceKey=${e} hasValue=${!!t}`),t??""})}async getByLanguage(e,r,t){return this.errorHandler.run("getByLanguage",async()=>{if(this.errorHandler.validateRequired(e,"resourceKey"),this.errorHandler.validateRequired(r,"languageKey"),this.logger.debug(`getByLanguage:start resourceKey=${e} languageKey=${r}`),this.isCacheEnabled()){let i=await this.resolveFromCachedResources(e,r);return this.logger.info(`getByLanguage:cache-${i?"hit":"miss"} resourceKey=${e} languageKey=${r} hasValue=${!!i}`),i}this.logger.info(`getByLanguage:api-call path=api/localization/client/bylanguage resourceKey=${e} languageKey=${r}`);let n=await this.send({method:"GET",path:"api/localization/client/bylanguage",query:{resourceKey:e,languageKey:r},headers:this.resolveLocaleHeader(t)});return this.logger.info(`getByLanguage:success resourceKey=${e} languageKey=${r} hasValue=${!!n}`),n??""})}async listResources(){return this.errorHandler.run("listResources",async()=>{if(this.isCacheEnabled()){let t=await this.cacheHelper.getListResources();if(t)return this.logger.info(`listResources:cache-hit-return count=${t.length}`),t}else this.logger.debug("listResources:cache-disabled");this.logger.info("listResources:api-call path=api/localization/client/list");let r=(await this.send({method:"GET",path:"api/localization/client/list"})??[]).map(t=>({key:t.resourceKey,value:t.value,language:t.languageKey}));return this.isCacheEnabled()&&await this.cacheHelper.storeListResources(r),this.logger.info(`listResources:success count=${r.length}`),r})}async invalidateCache(e){return this.errorHandler.run("invalidateCache",async()=>this.cacheHelper.invalidate(e))}async clearCache(){return this.errorHandler.run("clearCache",async()=>this.cacheHelper.invalidate())}async resolveFromCachedResources(e,r){return (await this.listResources()).find(i=>i.key!==e?false:r===void 0?true:i.language===r)?.value??""}async send(e){try{let r=await this.dependencies.authProvider?.getToken(),t=r?{...e.headers,"X-Auth-Token":r}:e.headers;this.logger.debug(`request:start method=${e.method} path=${e.path} hasAuth=${!!r}`);let n=await this.dependencies.httpTransport.request({...e,headers:t});return this.logger.debug(`request:success method=${e.method} path=${e.path} status=${n.status}`),n.data}catch(r){throw this.errorHandler.preserveCause(r)}}resolveLocaleHeader(e){let r=e?.locale?.trim()||this.dependencies.locale?.trim()||this.resolveBrowserLocale();if(r)return {"Accept-Language":r}}resolveBrowserLocale(){return globalThis.navigator?.language?.trim()||void 0}isCacheEnabled(){if(this.dependencies.cacheEnabled!==void 0)return this.logger.debug(`isCacheEnabled: enabled=${this.dependencies.cacheEnabled} source=cacheEnabled-flag`),this.dependencies.cacheEnabled;let e=!!this.dependencies.cacheProvider;return this.logger.debug(`isCacheEnabled: enabled=${e} source=cacheProvider`),e}};function O(o){_(o);let e=o.cache?.enabled??false,r=e?o.cache?.provider??new d:void 0,t=new L({baseUrl:o.baseUrl,fetchFn:o.fetchFn,timeoutMs:o.timeoutMs??1e4,defaultHeaders:o.headers,middleware:o.middleware});return new x({httpTransport:t,authProvider:o.authProvider??(o.token?new u(o.token):void 0),locale:o.locale,cacheEnabled:e,cacheProvider:r,cacheTtlMs:o.cache?.ttlMs,enableLogs:o.enableLogs??false})}function _(o){if(!o?.baseUrl?.trim())throw new a("baseUrl is required to create localization client")}var w=class{constructor(e){this.storage=e;}async get(e){let r=this.storage.getItem(e);if(!r)return null;let t=this.safeParse(r);return t?t.expiresAt!==void 0&&Date.now()>t.expiresAt?(this.storage.removeItem(e),null):t.value:(this.storage.removeItem(e),null)}async set(e,r,t){let n=t&&t>0?Date.now()+t:void 0,i={value:r,expiresAt:n};this.storage.setItem(e,JSON.stringify(i));}async delete(e){this.storage.removeItem(e);}async clear(){this.storage.clear();}safeParse(e){try{return JSON.parse(e)}catch{return null}}},A=class extends w{constructor(){super(N("localStorage"));}},H=class extends w{constructor(){super(N("sessionStorage"));}};function N(o){let e=typeof window>"u"?void 0:window[o];return e||U()}function U(){let o=new Map;return {get length(){return o.size},clear:()=>{o.clear();},getItem:e=>o.get(e)??null,key:e=>Array.from(o.keys())[e]??null,removeItem:e=>{o.delete(e);},setItem:(e,r)=>{o.set(e,r);}}}var I=new InjectionToken("LOCALIZATION_SDK_OPTIONS"),C=new InjectionToken("LOCALIZATION_CLIENT");function Z(o){return makeEnvironmentProviders([{provide:I,useValue:o},{provide:C,useFactory:()=>O(o)}])}var E=class{constructor(e){this.client=e;}getCurrentLanguage(e){return from(this.client.getCurrentLanguage(e))}getByLanguage(e,r){return from(this.client.getByLanguage(e,r))}listResources(){return from(this.client.listResources())}invalidateCache(e){return from(this.client.invalidateCache(e))}clearCache(){return from(this.client.clearCache())}};E=S([Injectable({providedIn:"root"}),k(0,Inject(C))],E);export{L as FetchHttpTransport,C as LOCALIZATION_CLIENT,I as LOCALIZATION_SDK_OPTIONS,A as LocalStorageCacheProvider,h as LocalizationAuthError,a as LocalizationError,m as LocalizationNetworkError,g as LocalizationServerError,E as LocalizationService,f as LocalizationTimeoutError,d as MemoryCacheProvider,p as ResourceNotFoundError,H as SessionStorageCacheProvider,w as StorageCacheProvider,u as XAuthTokenProvider,O as createLocalizationClient,Z as provideLocalization};
1
+ import {InjectionToken,Injectable,Inject,makeEnvironmentProviders}from'@angular/core';import {from}from'rxjs';var S=(o,e,r,t)=>{for(var n=e,i=o.length-1,s;i>=0;i--)(s=o[i])&&(n=(s(n))||n);return n},k=(o,e)=>(r,t)=>e(r,t,o);var u=class{constructor(e){this.token=e;}async getToken(){return this.token?.trim()?this.token:null}};var d=class{constructor(){this.store=new Map;}async get(e){let r=this.store.get(e);return r?r.expiresAt!==void 0&&Date.now()>r.expiresAt?(this.store.delete(e),null):r.value:null}async set(e,r,t){let n=t&&t>0?Date.now()+t:void 0;this.store.set(e,{value:r,expiresAt:n});}async delete(e){this.store.delete(e);}async clear(){this.store.clear();}};var a=class extends Error{constructor(r,t){super(r);this.metadata=t;this.name="LocalizationError";}},h=class extends a{constructor(e="Authentication failed",r){super(e,r),this.name="LocalizationAuthError";}},p=class extends a{constructor(e="Resource not found",r){super(e,r),this.name="ResourceNotFoundError";}},g=class extends a{constructor(e="Localization server error",r){super(e,r),this.name="LocalizationServerError";}},m=class extends a{constructor(e="Network error while contacting localization API",r){super(e,r),this.name="LocalizationNetworkError";}},f=class extends a{constructor(e="Localization request timeout",r){super(e,r),this.name="LocalizationTimeoutError";}};var v=class extends Error{constructor(r,t,n){super(`Request failed with status ${r}`);this.statusCode=r;this.responseBody=t;this.responseHeaders=n;this.name="HttpStatusError";}},y=class extends Error{constructor(r){super(`Request timed out after ${r}ms`);this.timeoutMs=r;this.name="HttpTimeoutError";}},l=class extends Error{constructor(r){super("Network error while sending request");this.causeError=r;this.name="HttpNetworkError";}},L=class{constructor(e){this.options=e;this.fetchFn=e.fetchFn??globalThis.fetch.bind(globalThis);}async request(e){let r=e.timeoutMs??this.options.timeoutMs,t=new AbortController,n=setTimeout(()=>t.abort(),r),i=new Request(this.resolveUrl(e),{method:e.method,headers:{"Content-Type":"application/json",...this.options.defaultHeaders,...e.headers},body:e.body===void 0?void 0:JSON.stringify(e.body),signal:t.signal});try{let s=await this.runRequestMiddleware(i),$;try{$=await this.fetchFn(s);}catch(T){throw this.isAbortError(T)?new y(r):new l(T)}let c=await this.runResponseMiddleware($);if(!c.ok){let T=await c.text();throw new v(c.status,T,c.headers)}let D=await this.parseResponse(c);return {status:c.status,headers:c.headers,data:D}}catch(s){throw await this.runErrorMiddleware(this.toError(s)),s}finally{clearTimeout(n);}}resolveUrl(e){let r=new URL(e.path,this.options.baseUrl);return e.query&&Object.entries(e.query).forEach(([t,n])=>{n!==void 0&&r.searchParams.set(t,String(n));}),r.toString()}async runRequestMiddleware(e){let r=e;for(let t of this.options.middleware??[])t.onRequest&&(r=await t.onRequest(r));return r}async runResponseMiddleware(e){let r=e;for(let t of this.options.middleware??[])t.onResponse&&(r=await t.onResponse(r));return r}async runErrorMiddleware(e){for(let r of this.options.middleware??[])r.onError&&await r.onError(e);}async parseResponse(e){return e.status===204?null:(e.headers.get("content-type")??"").includes("application/json")?await e.json():await e.text()}toError(e){return e instanceof Error?e:new Error("Unknown request error")}isAbortError(e){return e instanceof DOMException&&e.name==="AbortError"}};var M="localization:listResources",R=class{constructor(e,r,t){this.cacheProvider=e;this.cacheTtlMs=r;this.logger=t;}async getListResources(){this.logger.debug(`listResources:start cacheEnabled=${!!this.cacheProvider}`);let e=await this.cacheProvider?.get(M);return e?this.logger.info(`listResources:cache-hit count=${e.length}`):this.logger.debug("listResources:cache-miss"),e}async storeListResources(e){await this.cacheProvider?.set(M,e,this.cacheTtlMs),this.logger.debug(`listResources:cache-store ttlMs=${this.cacheTtlMs??0} count=${e.length}`);}async invalidate(e){if(this.logger.debug(`invalidateCache:start scope=${e??"all"}`),!this.cacheProvider){this.logger.debug("invalidateCache:skipped no-cache-provider");return}if(e){await this.cacheProvider.delete(e),this.logger.info(`invalidateCache:deleted key=${e}`);return}await this.cacheProvider.clear(),this.logger.info("invalidateCache:cleared-all");}};var z=class{constructor(e){this.logger=e;}async run(e,r){try{return await r()}catch(t){let n=this.map(t);throw this.logger.errorForOperation(e,n,t),n}}validateRequired(e,r){if(!e?.trim())throw new a(`${r} is required`)}map(e){return e instanceof a?e:e instanceof y?new f(e.message):e instanceof l?new m(e.message):e instanceof v?this.mapStatusError(e):new a("Unexpected localization SDK error")}preserveCause(e){let r=this.map(e);return r.cause??(r.cause=e),r}mapStatusError(e){return e.statusCode===401||e.statusCode===403?new h("Invalid token for localization endpoint",{statusCode:e.statusCode}):e.statusCode===404?new p("Localization resource was not found",{statusCode:e.statusCode}):e.statusCode>=500?new g("Localization API is unavailable",{statusCode:e.statusCode}):new a(e.message,{statusCode:e.statusCode})}};var K="[LocalizationSdk]",P=class{constructor(e=false){this.enabled=e;}debug(e){this.write("debug",e);}info(e){this.write("info",e);}errorForOperation(e,r,t){this.write("error",`${e}:error ${this.formatErrorDetails(r,t)}`);}formatErrorDetails(e,r){let t=this.getOriginalCause(e,r),n=this.getErrorMessage(t),i=[`type=${e.name}`,`message=${e.message}`];return n&&n!==e.message&&i.push(`original=${n}`),e instanceof a&&e.metadata?.statusCode&&i.push(`statusCode=${e.metadata.statusCode}`),i.join(" ")}getOriginalCause(e,r){let n=e.cause??r;return n instanceof l?n.causeError:n}getErrorMessage(e){return e instanceof Error?e.message:typeof e=="string"?e:"unknown-error"}write(e,r){if(!this.enabled)return;let t=this.resolveIcon(e,r),n=`${K} ${t} ${r}`;switch(e){case "debug":console.debug(n);break;case "info":console.info(n);break;case "error":console.error(n);break}}resolveIcon(e,r){return e==="error"||r.includes(":error")?"\u274C":r.includes("request:start")||r.includes(":api-call")?"\u{1F310}":r.includes("request:success")?"\u{1F4E1}":r.includes(":cache-hit")||r.includes("cache-hit")?"\u{1F5C4}\uFE0F":r.includes("cache-miss")?"\u{1F4ED}":r.includes("cache-store")?"\u{1F4BE}":r.includes("invalidateCache")?"\u{1F9F9}":r.includes("listResources")?"\u{1F4DA}":r.includes("getByLanguage")?"\u{1F30D}":r.includes("getCurrentLanguage")?"\u{1F22F}":r.includes(":start")?"\u{1F680}":r.includes(":success")?"\u2705":e==="info"?"\u2139\uFE0F":"\u{1F50E}"}};var x=class{constructor(e){this.dependencies=e;this.logger=new P(e.enableLogs),this.cacheHelper=new R(e.cacheProvider,e.cacheTtlMs,this.logger),this.errorHandler=new z(this.logger);}async getCurrentLanguage(e,r){return this.errorHandler.run("getCurrentLanguage",async()=>{if(this.errorHandler.validateRequired(e,"resourceKey"),this.logger.debug(`getCurrentLanguage:start resourceKey=${e}`),this.isCacheEnabled()){let n=await this.resolveFromCachedResources(e);return this.logger.info(`getCurrentLanguage:cache-${n?"hit":"miss"} resourceKey=${e} hasValue=${!!n}`),n}this.logger.info(`getCurrentLanguage:api-call path=api/localization/client/currentlanguage resourceKey=${e}`);let t=await this.send({method:"GET",path:"api/localization/client/currentlanguage",query:{resourceKey:e},headers:this.resolveLocaleHeader(r)});return this.logger.info(`getCurrentLanguage:success resourceKey=${e} hasValue=${!!t}`),t??""})}async getByLanguage(e,r,t){return this.errorHandler.run("getByLanguage",async()=>{if(this.errorHandler.validateRequired(e,"resourceKey"),this.errorHandler.validateRequired(r,"languageKey"),this.logger.debug(`getByLanguage:start resourceKey=${e} languageKey=${r}`),this.isCacheEnabled()){let i=await this.resolveFromCachedResources(e,r);return this.logger.info(`getByLanguage:cache-${i?"hit":"miss"} resourceKey=${e} languageKey=${r} hasValue=${!!i}`),i}this.logger.info(`getByLanguage:api-call path=api/localization/client/bylanguage resourceKey=${e} languageKey=${r}`);let n=await this.send({method:"GET",path:"api/localization/client/bylanguage",query:{resourceKey:e,languageKey:r},headers:this.resolveLocaleHeader(t)});return this.logger.info(`getByLanguage:success resourceKey=${e} languageKey=${r} hasValue=${!!n}`),n??""})}async listResources(){return this.errorHandler.run("listResources",async()=>{if(this.isCacheEnabled()){let t=await this.cacheHelper.getListResources();if(t)return this.logger.info(`listResources:cache-hit-return count=${t.length}`),t}else this.logger.debug("listResources:cache-disabled");this.logger.info("listResources:api-call path=api/localization/client/list");let r=(await this.send({method:"GET",path:"api/localization/client/list"})??[]).map(t=>({key:t.resourceKey,value:t.value,language:t.languageKey}));return this.isCacheEnabled()&&await this.cacheHelper.storeListResources(r),this.logger.info(`listResources:success count=${r.length}`),r})}async invalidateCache(e){return this.errorHandler.run("invalidateCache",async()=>this.cacheHelper.invalidate(e))}async clearCache(){return this.errorHandler.run("clearCache",async()=>this.cacheHelper.invalidate())}async resolveFromCachedResources(e,r){return (await this.listResources()).find(i=>i.key!==e?false:r===void 0?true:i.language===r)?.value??""}async send(e){try{let r=await this.dependencies.authProvider?.getToken(),t=r?{...e.headers,"X-Auth-Token":r}:e.headers;this.logger.debug(`request:start method=${e.method} path=${e.path} hasAuth=${!!r}`);let n=await this.dependencies.httpTransport.request({...e,headers:t});return this.logger.debug(`request:success method=${e.method} path=${e.path} status=${n.status}`),n.data}catch(r){throw this.errorHandler.preserveCause(r)}}resolveLocaleHeader(e){let r=e?.locale?.trim()||this.dependencies.locale?.trim()||this.resolveBrowserLocale();if(r)return {"Accept-Language":r}}resolveBrowserLocale(){return globalThis.navigator?.language?.trim()||void 0}isCacheEnabled(){if(this.dependencies.cacheEnabled!==void 0)return this.logger.debug(`isCacheEnabled: enabled=${this.dependencies.cacheEnabled} source=cacheEnabled-flag`),this.dependencies.cacheEnabled;let e=!!this.dependencies.cacheProvider;return this.logger.debug(`isCacheEnabled: enabled=${e} source=cacheProvider`),e}};function O(o){_(o);let e=o.cache?.enabled??false,r=e?o.cache?.provider??new d:void 0,t=new L({baseUrl:o.baseUrl,fetchFn:o.fetchFn,timeoutMs:o.timeoutMs??1e4,defaultHeaders:o.headers,middleware:o.middleware});return new x({httpTransport:t,authProvider:o.authProvider??(o.token?new u(o.token):void 0),locale:o.locale,cacheEnabled:e,cacheProvider:r,cacheTtlMs:o.cache?.ttlMs,enableLogs:o.enableLogs??false})}function _(o){if(!o?.baseUrl?.trim())throw new a("baseUrl is required to create localization client")}var w=class{constructor(e){this.storage=e;}async get(e){let r=this.storage.getItem(e);if(!r)return null;let t=this.safeParse(r);return t?t.expiresAt!==void 0&&Date.now()>t.expiresAt?(this.storage.removeItem(e),null):t.value:(this.storage.removeItem(e),null)}async set(e,r,t){let n=t&&t>0?Date.now()+t:void 0,i={value:r,expiresAt:n};this.storage.setItem(e,JSON.stringify(i));}async delete(e){this.storage.removeItem(e);}async clear(){this.storage.clear();}safeParse(e){try{return JSON.parse(e)}catch{return null}}},A=class extends w{constructor(){super(N("localStorage"));}},H=class extends w{constructor(){super(N("sessionStorage"));}};function N(o){let e=typeof globalThis.window>"u"?void 0:globalThis.window[o];return e||U()}function U(){let o=new Map;return {get length(){return o.size},clear:()=>{o.clear();},getItem:e=>o.get(e)??null,key:e=>Array.from(o.keys())[e]??null,removeItem:e=>{o.delete(e);},setItem:(e,r)=>{o.set(e,r);}}}var I=new InjectionToken("LOCALIZATION_SDK_OPTIONS"),C=new InjectionToken("LOCALIZATION_CLIENT");function Z(o){return makeEnvironmentProviders([{provide:I,useValue:o},{provide:C,useFactory:()=>O(o)}])}var E=class{constructor(e){this.client=e;}getCurrentLanguage(e){return from(this.client.getCurrentLanguage(e))}getByLanguage(e,r){return from(this.client.getByLanguage(e,r))}listResources(){return from(this.client.listResources())}invalidateCache(e){return from(this.client.invalidateCache(e))}clearCache(){return from(this.client.clearCache())}};E=S([Injectable({providedIn:"root"}),k(0,Inject(C))],E);export{L as FetchHttpTransport,C as LOCALIZATION_CLIENT,I as LOCALIZATION_SDK_OPTIONS,A as LocalStorageCacheProvider,h as LocalizationAuthError,a as LocalizationError,m as LocalizationNetworkError,g as LocalizationServerError,E as LocalizationService,f as LocalizationTimeoutError,d as MemoryCacheProvider,p as ResourceNotFoundError,H as SessionStorageCacheProvider,w as StorageCacheProvider,u as XAuthTokenProvider,O as createLocalizationClient,Z as provideLocalization};
@@ -0,0 +1 @@
1
+ var LocalizationSDK=(function(exports){'use strict';var l=class{constructor(e){this.token=e;}async getToken(){return this.token?.trim()?this.token:null}};var u=class{constructor(){this.store=new Map;}async get(e){let r=this.store.get(e);return r?r.expiresAt!==void 0&&Date.now()>r.expiresAt?(this.store.delete(e),null):r.value:null}async set(e,r,t){let n=t&&t>0?Date.now()+t:void 0;this.store.set(e,{value:r,expiresAt:n});}async delete(e){this.store.delete(e);}async clear(){this.store.clear();}};var a=class extends Error{constructor(r,t){super(r);this.metadata=t;this.name="LocalizationError";}},d=class extends a{constructor(e="Authentication failed",r){super(e,r),this.name="LocalizationAuthError";}},h=class extends a{constructor(e="Resource not found",r){super(e,r),this.name="ResourceNotFoundError";}},g=class extends a{constructor(e="Localization server error",r){super(e,r),this.name="LocalizationServerError";}},p=class extends a{constructor(e="Network error while contacting localization API",r){super(e,r),this.name="LocalizationNetworkError";}},f=class extends a{constructor(e="Localization request timeout",r){super(e,r),this.name="LocalizationTimeoutError";}};var m=class extends Error{constructor(r,t,n){super(`Request failed with status ${r}`);this.statusCode=r;this.responseBody=t;this.responseHeaders=n;this.name="HttpStatusError";}},v=class extends Error{constructor(r){super(`Request timed out after ${r}ms`);this.timeoutMs=r;this.name="HttpTimeoutError";}},c=class extends Error{constructor(r){super("Network error while sending request");this.causeError=r;this.name="HttpNetworkError";}},L=class{constructor(e){this.options=e;this.fetchFn=e.fetchFn??globalThis.fetch.bind(globalThis);}async request(e){let r=e.timeoutMs??this.options.timeoutMs,t=new AbortController,n=setTimeout(()=>t.abort(),r),i=new Request(this.resolveUrl(e),{method:e.method,headers:{"Content-Type":"application/json",...this.options.defaultHeaders,...e.headers},body:e.body===void 0?void 0:JSON.stringify(e.body),signal:t.signal});try{let y=await this.runRequestMiddleware(i),x;try{x=await this.fetchFn(y);}catch(w){throw this.isAbortError(w)?new v(r):new c(w)}let s=await this.runResponseMiddleware(x);if(!s.ok){let w=await s.text();throw new m(s.status,w,s.headers)}let A=await this.parseResponse(s);return {status:s.status,headers:s.headers,data:A}}catch(y){throw await this.runErrorMiddleware(this.toError(y)),y}finally{clearTimeout(n);}}resolveUrl(e){let r=new URL(e.path,this.options.baseUrl);return e.query&&Object.entries(e.query).forEach(([t,n])=>{n!==void 0&&r.searchParams.set(t,String(n));}),r.toString()}async runRequestMiddleware(e){let r=e;for(let t of this.options.middleware??[])t.onRequest&&(r=await t.onRequest(r));return r}async runResponseMiddleware(e){let r=e;for(let t of this.options.middleware??[])t.onResponse&&(r=await t.onResponse(r));return r}async runErrorMiddleware(e){for(let r of this.options.middleware??[])r.onError&&await r.onError(e);}async parseResponse(e){return e.status===204?null:(e.headers.get("content-type")??"").includes("application/json")?await e.json():await e.text()}toError(e){return e instanceof Error?e:new Error("Unknown request error")}isAbortError(e){return e instanceof DOMException&&e.name==="AbortError"}};var H="localization:listResources",b=class{constructor(e,r,t){this.cacheProvider=e;this.cacheTtlMs=r;this.logger=t;}async getListResources(){this.logger.debug(`listResources:start cacheEnabled=${!!this.cacheProvider}`);let e=await this.cacheProvider?.get(H);return e?this.logger.info(`listResources:cache-hit count=${e.length}`):this.logger.debug("listResources:cache-miss"),e}async storeListResources(e){await this.cacheProvider?.set(H,e,this.cacheTtlMs),this.logger.debug(`listResources:cache-store ttlMs=${this.cacheTtlMs??0} count=${e.length}`);}async invalidate(e){if(this.logger.debug(`invalidateCache:start scope=${e??"all"}`),!this.cacheProvider){this.logger.debug("invalidateCache:skipped no-cache-provider");return}if(e){await this.cacheProvider.delete(e),this.logger.info(`invalidateCache:deleted key=${e}`);return}await this.cacheProvider.clear(),this.logger.info("invalidateCache:cleared-all");}};var C=class{constructor(e){this.logger=e;}async run(e,r){try{return await r()}catch(t){let n=this.map(t);throw this.logger.errorForOperation(e,n,t),n}}validateRequired(e,r){if(!e?.trim())throw new a(`${r} is required`)}map(e){return e instanceof a?e:e instanceof v?new f(e.message):e instanceof c?new p(e.message):e instanceof m?this.mapStatusError(e):new a("Unexpected localization SDK error")}preserveCause(e){let r=this.map(e);return r.cause??(r.cause=e),r}mapStatusError(e){return e.statusCode===401||e.statusCode===403?new d("Invalid token for localization endpoint",{statusCode:e.statusCode}):e.statusCode===404?new h("Localization resource was not found",{statusCode:e.statusCode}):e.statusCode>=500?new g("Localization API is unavailable",{statusCode:e.statusCode}):new a(e.message,{statusCode:e.statusCode})}};var S="[LocalizationSdk]",E=class{constructor(e=false){this.enabled=e;}debug(e){this.write("debug",e);}info(e){this.write("info",e);}errorForOperation(e,r,t){this.write("error",`${e}:error ${this.formatErrorDetails(r,t)}`);}formatErrorDetails(e,r){let t=this.getOriginalCause(e,r),n=this.getErrorMessage(t),i=[`type=${e.name}`,`message=${e.message}`];return n&&n!==e.message&&i.push(`original=${n}`),e instanceof a&&e.metadata?.statusCode&&i.push(`statusCode=${e.metadata.statusCode}`),i.join(" ")}getOriginalCause(e,r){let n=e.cause??r;return n instanceof c?n.causeError:n}getErrorMessage(e){return e instanceof Error?e.message:typeof e=="string"?e:"unknown-error"}write(e,r){if(!this.enabled)return;let t=this.resolveIcon(e,r),n=`${S} ${t} ${r}`;switch(e){case "debug":console.debug(n);break;case "info":console.info(n);break;case "error":console.error(n);break}}resolveIcon(e,r){return e==="error"||r.includes(":error")?"\u274C":r.includes("request:start")||r.includes(":api-call")?"\u{1F310}":r.includes("request:success")?"\u{1F4E1}":r.includes(":cache-hit")||r.includes("cache-hit")?"\u{1F5C4}\uFE0F":r.includes("cache-miss")?"\u{1F4ED}":r.includes("cache-store")?"\u{1F4BE}":r.includes("invalidateCache")?"\u{1F9F9}":r.includes("listResources")?"\u{1F4DA}":r.includes("getByLanguage")?"\u{1F30D}":r.includes("getCurrentLanguage")?"\u{1F22F}":r.includes(":start")?"\u{1F680}":r.includes(":success")?"\u2705":e==="info"?"\u2139\uFE0F":"\u{1F50E}"}};var R=class{constructor(e){this.dependencies=e;this.logger=new E(e.enableLogs),this.cacheHelper=new b(e.cacheProvider,e.cacheTtlMs,this.logger),this.errorHandler=new C(this.logger);}async getCurrentLanguage(e,r){return this.errorHandler.run("getCurrentLanguage",async()=>{if(this.errorHandler.validateRequired(e,"resourceKey"),this.logger.debug(`getCurrentLanguage:start resourceKey=${e}`),this.isCacheEnabled()){let n=await this.resolveFromCachedResources(e);return this.logger.info(`getCurrentLanguage:cache-${n?"hit":"miss"} resourceKey=${e} hasValue=${!!n}`),n}this.logger.info(`getCurrentLanguage:api-call path=api/localization/client/currentlanguage resourceKey=${e}`);let t=await this.send({method:"GET",path:"api/localization/client/currentlanguage",query:{resourceKey:e},headers:this.resolveLocaleHeader(r)});return this.logger.info(`getCurrentLanguage:success resourceKey=${e} hasValue=${!!t}`),t??""})}async getByLanguage(e,r,t){return this.errorHandler.run("getByLanguage",async()=>{if(this.errorHandler.validateRequired(e,"resourceKey"),this.errorHandler.validateRequired(r,"languageKey"),this.logger.debug(`getByLanguage:start resourceKey=${e} languageKey=${r}`),this.isCacheEnabled()){let i=await this.resolveFromCachedResources(e,r);return this.logger.info(`getByLanguage:cache-${i?"hit":"miss"} resourceKey=${e} languageKey=${r} hasValue=${!!i}`),i}this.logger.info(`getByLanguage:api-call path=api/localization/client/bylanguage resourceKey=${e} languageKey=${r}`);let n=await this.send({method:"GET",path:"api/localization/client/bylanguage",query:{resourceKey:e,languageKey:r},headers:this.resolveLocaleHeader(t)});return this.logger.info(`getByLanguage:success resourceKey=${e} languageKey=${r} hasValue=${!!n}`),n??""})}async listResources(){return this.errorHandler.run("listResources",async()=>{if(this.isCacheEnabled()){let t=await this.cacheHelper.getListResources();if(t)return this.logger.info(`listResources:cache-hit-return count=${t.length}`),t}else this.logger.debug("listResources:cache-disabled");this.logger.info("listResources:api-call path=api/localization/client/list");let r=(await this.send({method:"GET",path:"api/localization/client/list"})??[]).map(t=>({key:t.resourceKey,value:t.value,language:t.languageKey}));return this.isCacheEnabled()&&await this.cacheHelper.storeListResources(r),this.logger.info(`listResources:success count=${r.length}`),r})}async invalidateCache(e){return this.errorHandler.run("invalidateCache",async()=>this.cacheHelper.invalidate(e))}async clearCache(){return this.errorHandler.run("clearCache",async()=>this.cacheHelper.invalidate())}async resolveFromCachedResources(e,r){return (await this.listResources()).find(i=>i.key!==e?false:r===void 0?true:i.language===r)?.value??""}async send(e){try{let r=await this.dependencies.authProvider?.getToken(),t=r?{...e.headers,"X-Auth-Token":r}:e.headers;this.logger.debug(`request:start method=${e.method} path=${e.path} hasAuth=${!!r}`);let n=await this.dependencies.httpTransport.request({...e,headers:t});return this.logger.debug(`request:success method=${e.method} path=${e.path} status=${n.status}`),n.data}catch(r){throw this.errorHandler.preserveCause(r)}}resolveLocaleHeader(e){let r=e?.locale?.trim()||this.dependencies.locale?.trim()||this.resolveBrowserLocale();if(r)return {"Accept-Language":r}}resolveBrowserLocale(){return globalThis.navigator?.language?.trim()||void 0}isCacheEnabled(){if(this.dependencies.cacheEnabled!==void 0)return this.logger.debug(`isCacheEnabled: enabled=${this.dependencies.cacheEnabled} source=cacheEnabled-flag`),this.dependencies.cacheEnabled;let e=!!this.dependencies.cacheProvider;return this.logger.debug(`isCacheEnabled: enabled=${e} source=cacheProvider`),e}};function $(o){M(o);let e=o.cache?.enabled??false,r=e?o.cache?.provider??new u:void 0,t=new L({baseUrl:o.baseUrl,fetchFn:o.fetchFn,timeoutMs:o.timeoutMs??1e4,defaultHeaders:o.headers,middleware:o.middleware});return new R({httpTransport:t,authProvider:o.authProvider??(o.token?new l(o.token):void 0),locale:o.locale,cacheEnabled:e,cacheProvider:r,cacheTtlMs:o.cache?.ttlMs,enableLogs:o.enableLogs??false})}function M(o){if(!o?.baseUrl?.trim())throw new a("baseUrl is required to create localization client")}var T=class{constructor(e){this.storage=e;}async get(e){let r=this.storage.getItem(e);if(!r)return null;let t=this.safeParse(r);return t?t.expiresAt!==void 0&&Date.now()>t.expiresAt?(this.storage.removeItem(e),null):t.value:(this.storage.removeItem(e),null)}async set(e,r,t){let n=t&&t>0?Date.now()+t:void 0,i={value:r,expiresAt:n};this.storage.setItem(e,JSON.stringify(i));}async delete(e){this.storage.removeItem(e);}async clear(){this.storage.clear();}safeParse(e){try{return JSON.parse(e)}catch{return null}}},P=class extends T{constructor(){super(k("localStorage"));}},z=class extends T{constructor(){super(k("sessionStorage"));}};function k(o){let e=typeof globalThis.window>"u"?void 0:globalThis.window[o];return e||O()}function O(){let o=new Map;return {get length(){return o.size},clear:()=>{o.clear();},getItem:e=>o.get(e)??null,key:e=>Array.from(o.keys())[e]??null,removeItem:e=>{o.delete(e);},setItem:(e,r)=>{o.set(e,r);}}}exports.LocalStorageCacheProvider=P;exports.LocalizationAuthError=d;exports.LocalizationError=a;exports.LocalizationNetworkError=p;exports.LocalizationServerError=g;exports.LocalizationTimeoutError=f;exports.MemoryCacheProvider=u;exports.ResourceNotFoundError=h;exports.SessionStorageCacheProvider=z;exports.XAuthTokenProvider=l;exports.createClient=$;exports.createLocalizationClient=$;return exports;})({});
package/package.json CHANGED
@@ -6,8 +6,9 @@
6
6
  "version:auto": "node ./scripts/auto-version.cjs",
7
7
  "prebuild": "npm run version:auto",
8
8
  "build": "tsup",
9
+ "build:umd": "tsup --config tsup.config.umd.ts",
9
10
  "prebuild:prod": "npm run version:auto",
10
- "build:prod": "tsup --config tsup.config.prod.ts",
11
+ "build:prod": "tsup --config tsup.config.prod.ts && npm run build:umd",
11
12
  "test": "jest --config jest.config.js",
12
13
  "manual:smoke": "node ./scripts/manual-smoke-test.mjs"
13
14
  },
@@ -20,7 +21,9 @@
20
21
  "publishConfig": {
21
22
  "access": "public"
22
23
  },
23
- "version": "1.0.3542",
24
+ "unpkg": "./dist/umd/localization-sdk.min.js",
25
+ "jsdelivr": "./dist/umd/localization-sdk.min.js",
26
+ "version": "1.0.3591",
24
27
  "devDependencies": {
25
28
  "@angular/core": "^20.3.15",
26
29
  "@angular/common": "^20.3.15",