@smartcorehub/localization-sdk 1.0.3507 → 1.0.3514

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
@@ -49,45 +49,42 @@ const list = await localizationClient.listResources();
49
49
 
50
50
  ## Integracao com Angular
51
51
 
52
- Use o provider para registrar o SDK na injecao de dependencia.
52
+ Forma validada e recomendada (mesma usada no exampleangular): facade com `createLocalizationClient`.
53
53
 
54
54
  ~~~ts
55
- import { ApplicationConfig } from '@angular/core';
56
- import { provideLocalization } from '@smartcorehub/localization-sdk';
57
-
58
- export const appConfig: ApplicationConfig = {
59
- providers: [
60
- provideLocalization({
61
- baseUrl: 'https://api.smartcorehub.io/',
62
- token: 'SEU_TOKEN',
63
- cache: { enabled: true, ttlMs: 60000 }
64
- })
65
- ]
66
- };
67
- ~~~
55
+ import { Injectable } from '@angular/core';
56
+ import { from, Observable } from 'rxjs';
57
+ import { createLocalizationClient, LocalizationListResource } from '@smartcorehub/localization-sdk';
58
+
59
+ @Injectable({ providedIn: 'root' })
60
+ export class LocalizationFacadeService {
61
+ private readonly client = createLocalizationClient({
62
+ baseUrl: 'https://api.smartcorehub.io/',
63
+ token: 'SEU_TOKEN',
64
+ cache: { enabled: false },
65
+ enableLogs: true
66
+ });
68
67
 
69
- Consumindo no service/componente Angular:
68
+ getCurrentLanguage(resourceKey: string): Observable<string> {
69
+ return from(this.client.getCurrentLanguage(resourceKey));
70
+ }
70
71
 
71
- ~~~ts
72
- import { Component, inject } from '@angular/core';
73
- import { LocalizationService } from '@smartcorehub/localization-sdk';
74
-
75
- @Component({
76
- selector: 'app-home-title',
77
- template: '{{ title }}'
78
- })
79
- export class HomeTitleComponent {
80
- private readonly localizationService = inject(LocalizationService);
81
- title = '';
82
-
83
- ngOnInit(): void {
84
- this.localizationService.getCurrentLanguage('home.title').subscribe((result) => {
85
- this.title = result;
86
- });
72
+ getByLanguage(resourceKey: string, languageKey: string): Observable<string> {
73
+ return from(this.client.getByLanguage(resourceKey, languageKey));
74
+ }
75
+
76
+ listResources(): Observable<readonly LocalizationListResource[]> {
77
+ return from(this.client.listResources());
87
78
  }
88
79
  }
89
80
  ~~~
90
81
 
82
+ ### Forma com provider Angular (opcional)
83
+
84
+ Modo alternativo em teste alpha: integracao via provider Angular (`provideLocalization` + `LocalizationService`).
85
+
86
+ Status atual: nao validado como fluxo principal no exemplo oficial. Use apenas para experimentacao, sem garantia de estabilidade nesta versao.
87
+
91
88
  ## Integracao com React
92
89
 
93
90
  ~~~tsx
@@ -222,6 +219,18 @@ Para automacao completa de CI/CD da publicacao, consulte NPM-AUTOMATION-GUIDE.md
222
219
 
223
220
  Para fluxo interno de contribuicao e troubleshooting de desenvolvimento, consulte o arquivo DEVELOPMENT-GUIDE.md.
224
221
 
222
+ ## Validar pacote publicado (npm)
223
+
224
+ No projeto `frontendsdk/exampleangular`, rode:
225
+
226
+ ~~~bash
227
+ npm run sdk:use:npm
228
+ npm run sdk:status
229
+ npm run build
230
+ ~~~
231
+
232
+ Atualmente, o comando `sdk:use:npm` fixa o pacote publicado em `@smartcorehub/localization-sdk@1.0.3507`.
233
+
225
234
  ## Licensing / Licenciamento
226
235
 
227
236
  ### English
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- 'use strict';var core=require('@angular/core'),rxjs=require('rxjs');var H=(o,e,t,r)=>{for(var n=e,i=o.length-1,s;i>=0;i--)(s=o[i])&&(n=(s(n))||n);return n},I=(o,e)=>(t,r)=>e(t,r,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 t=this.store.get(e);return t?t.expiresAt!==void 0&&Date.now()>t.expiresAt?(this.store.delete(e),null):t.value:null}async set(e,t,r){let n=r&&r>0?Date.now()+r:void 0;this.store.set(e,{value:t,expiresAt:n});}async delete(e){this.store.delete(e);}async clear(){this.store.clear();}};var a=class extends Error{constructor(t,r){super(t);this.metadata=r;this.name="LocalizationError";}},p=class extends a{constructor(e="Authentication failed",t){super(e,t),this.name="LocalizationAuthError";}},h=class extends a{constructor(e="Resource not found",t){super(e,t),this.name="ResourceNotFoundError";}},g=class extends a{constructor(e="Localization server error",t){super(e,t),this.name="LocalizationServerError";}},m=class extends a{constructor(e="Network error while contacting localization API",t){super(e,t),this.name="LocalizationNetworkError";}},f=class extends a{constructor(e="Localization request timeout",t){super(e,t),this.name="LocalizationTimeoutError";}};var v=class extends Error{constructor(t,r,n){super(`Request failed with status ${t}`);this.statusCode=t;this.responseBody=r;this.responseHeaders=n;this.name="HttpStatusError";}},L=class extends Error{constructor(t){super(`Request timed out after ${t}ms`);this.timeoutMs=t;this.name="HttpTimeoutError";}},l=class extends Error{constructor(t){super("Network error while sending request");this.causeError=t;this.name="HttpNetworkError";}},y=class{constructor(e){this.options=e;this.fetchFn=e.fetchFn??globalThis.fetch.bind(globalThis);}async request(e){let t=e.timeoutMs??this.options.timeoutMs,r=new AbortController,n=setTimeout(()=>r.abort(),t),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:r.signal});try{let s=await this.runRequestMiddleware(i),O;try{O=await this.fetchFn(s);}catch(E){throw this.isAbortError(E)?new L(t):new l(E)}let c=await this.runResponseMiddleware(O);if(!c.ok){let E=await c.text();throw new v(c.status,E,c.headers)}let $=await this.parseResponse(c);return {status:c.status,headers:c.headers,data:$}}catch(s){throw await this.runErrorMiddleware(this.toError(s)),s}finally{clearTimeout(n);}}resolveUrl(e){let t=new URL(e.path,this.options.baseUrl);return e.query&&Object.entries(e.query).forEach(([r,n])=>{n!==void 0&&t.searchParams.set(r,String(n));}),t.toString()}async runRequestMiddleware(e){let t=e;for(let r of this.options.middleware??[])r.onRequest&&(t=await r.onRequest(t));return t}async runResponseMiddleware(e){let t=e;for(let r of this.options.middleware??[])r.onResponse&&(t=await r.onResponse(t));return t}async runErrorMiddleware(e){for(let t of this.options.middleware??[])t.onError&&await t.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 k="localization:listResources",T=class{constructor(e,t,r){this.cacheProvider=e;this.cacheTtlMs=t;this.logger=r;}async getListResources(){this.logger.debug(`listResources:start cacheEnabled=${!!this.cacheProvider}`);let e=await this.cacheProvider?.get(k);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(k,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 b=class{constructor(e){this.logger=e;}async run(e,t){try{return await t()}catch(r){let n=this.map(r);throw this.logger.errorForOperation(e,n,r),n}}validateRequired(e,t){if(!e?.trim())throw new a(`${t} is required`)}map(e){return e instanceof a?e:e instanceof L?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 t=this.map(e);return t.cause??(t.cause=e),t}mapStatusError(e){return e.statusCode===401||e.statusCode===403?new p("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 q="[LocalizationSdk]",R=class{constructor(e=false){this.enabled=e;}debug(e){this.write("debug",e);}info(e){this.write("info",e);}errorForOperation(e,t,r){this.write("error",`${e}:error ${this.formatErrorDetails(t,r)}`);}formatErrorDetails(e,t){let r=this.getOriginalCause(e,t),n=this.getErrorMessage(r),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,t){let n=e.cause??t;return n instanceof l?n.causeError:n}getErrorMessage(e){return e instanceof Error?e.message:typeof e=="string"?e:"unknown-error"}write(e,t){if(!this.enabled)return;let r=`${q} ${t}`;switch(e){case "debug":console.debug(r);break;case "info":console.info(r);break;case "error":console.error(r);break}}};var z=class{constructor(e){this.dependencies=e;this.logger=new R(e.enableLogs),this.cacheHelper=new T(e.cacheProvider,e.cacheTtlMs,this.logger),this.errorHandler=new b(this.logger);}async getCurrentLanguage(e){return this.errorHandler.run("getCurrentLanguage",async()=>{this.errorHandler.validateRequired(e,"resourceKey"),this.logger.debug(`getCurrentLanguage:start resourceKey=${e}`);let t=await this.send({method:"GET",path:"api/localization/client/currentlanguage",query:{resourceKey:e}});return this.logger.info(`getCurrentLanguage:success resourceKey=${e} hasValue=${!!t}`),t??""})}async getByLanguage(e,t){return this.errorHandler.run("getByLanguage",async()=>{this.errorHandler.validateRequired(e,"resourceKey"),this.errorHandler.validateRequired(t,"languageKey"),this.logger.debug(`getByLanguage:start resourceKey=${e} languageKey=${t}`);let r=await this.send({method:"GET",path:"api/localization/client/bylanguage",query:{resourceKey:e,languageKey:t}});return this.logger.info(`getByLanguage:success resourceKey=${e} languageKey=${t} hasValue=${!!r}`),r??""})}async listResources(){return this.errorHandler.run("listResources",async()=>{let e=await this.cacheHelper.getListResources();if(e)return e;let r=(await this.send({method:"GET",path:"api/localization/client/list"})??[]).map(n=>({key:n.resourceKey,value:n.value,language:n.languageKey}));return 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 send(e){try{let t=await this.dependencies.authProvider?.getToken(),r=t?{...e.headers,"X-Auth-Token":t}:e.headers;this.logger.debug(`request:start method=${e.method} path=${e.path} hasAuth=${!!t}`);let n=await this.dependencies.httpTransport.request({...e,headers:r});return this.logger.debug(`request:success method=${e.method} path=${e.path} status=${n.status}`),n.data}catch(t){throw this.errorHandler.preserveCause(t)}}};function x(o){D(o);let t=o.cache?.enabled??false?o.cache?.provider??new d:void 0,r=new y({baseUrl:o.baseUrl,fetchFn:o.fetchFn,timeoutMs:o.timeoutMs??1e4,defaultHeaders:o.headers,middleware:o.middleware});return new z({httpTransport:r,authProvider:o.authProvider??(o.token?new u(o.token):void 0),cacheProvider:t,cacheTtlMs:o.cache?.ttlMs,enableLogs:o.enableLogs??false})}function D(o){if(!o?.baseUrl?.trim())throw new a("baseUrl is required to create localization client")}var A=new core.InjectionToken("LOCALIZATION_SDK_OPTIONS"),w=new core.InjectionToken("LOCALIZATION_CLIENT");function F(o){return core.makeEnvironmentProviders([{provide:A,useValue:o},{provide:w,useFactory:()=>x(o)}])}exports.LocalizationService=class C{constructor(e){this.client=e;}getCurrentLanguage(e){return rxjs.from(this.client.getCurrentLanguage(e))}getByLanguage(e,t){return rxjs.from(this.client.getByLanguage(e,t))}listResources(){return rxjs.from(this.client.listResources())}invalidateCache(e){return rxjs.from(this.client.invalidateCache(e))}};exports.LocalizationService=H([core.Injectable({providedIn:"root"}),I(0,core.Inject(w))],exports.LocalizationService);exports.FetchHttpTransport=y;exports.LOCALIZATION_CLIENT=w;exports.LOCALIZATION_SDK_OPTIONS=A;exports.LocalizationAuthError=p;exports.LocalizationError=a;exports.LocalizationNetworkError=m;exports.LocalizationServerError=g;exports.LocalizationTimeoutError=f;exports.MemoryCacheProvider=d;exports.ResourceNotFoundError=h;exports.XAuthTokenProvider=u;exports.createLocalizationClient=x;exports.provideLocalization=F;
1
+ 'use strict';var core=require('@angular/core'),rxjs=require('rxjs');var H=(o,e,r,t)=>{for(var n=e,a=o.length-1,s;a>=0;a--)(s=o[a])&&(n=(s(n))||n);return n},I=(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 i=class extends Error{constructor(r,t){super(r);this.metadata=t;this.name="LocalizationError";}},p=class extends i{constructor(e="Authentication failed",r){super(e,r),this.name="LocalizationAuthError";}},h=class extends i{constructor(e="Resource not found",r){super(e,r),this.name="ResourceNotFoundError";}},g=class extends i{constructor(e="Localization server error",r){super(e,r),this.name="LocalizationServerError";}},m=class extends i{constructor(e="Network error while contacting localization API",r){super(e,r),this.name="LocalizationNetworkError";}},f=class extends i{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";}},L=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";}},y=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),a=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(a),O;try{O=await this.fetchFn(s);}catch(E){throw this.isAbortError(E)?new L(r):new l(E)}let c=await this.runResponseMiddleware(O);if(!c.ok){let E=await c.text();throw new v(c.status,E,c.headers)}let $=await this.parseResponse(c);return {status:c.status,headers:c.headers,data:$}}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 k="localization:listResources",T=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(k);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(k,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 b=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 i(`${r} is required`)}map(e){return e instanceof i?e:e instanceof L?new f(e.message):e instanceof l?new m(e.message):e instanceof v?this.mapStatusError(e):new i("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 p("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 i(e.message,{statusCode:e.statusCode})}};var q="[LocalizationSdk]",R=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),a=[`type=${e.name}`,`message=${e.message}`];return n&&n!==e.message&&a.push(`original=${n}`),e instanceof i&&e.metadata?.statusCode&&a.push(`statusCode=${e.metadata.statusCode}`),a.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=`${q} ${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")?"\u{1F310}":r.includes("request:success")?"\u{1F4E1}":r.includes("cache-hit")?"\u26A1":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 z=class{constructor(e){this.dependencies=e;this.logger=new R(e.enableLogs),this.cacheHelper=new T(e.cacheProvider,e.cacheTtlMs,this.logger),this.errorHandler=new b(this.logger);}async getCurrentLanguage(e){return this.errorHandler.run("getCurrentLanguage",async()=>{this.errorHandler.validateRequired(e,"resourceKey"),this.logger.debug(`getCurrentLanguage:start resourceKey=${e}`);let r=await this.send({method:"GET",path:"api/localization/client/currentlanguage",query:{resourceKey:e}});return this.logger.info(`getCurrentLanguage:success resourceKey=${e} hasValue=${!!r}`),r??""})}async getByLanguage(e,r){return this.errorHandler.run("getByLanguage",async()=>{this.errorHandler.validateRequired(e,"resourceKey"),this.errorHandler.validateRequired(r,"languageKey"),this.logger.debug(`getByLanguage:start resourceKey=${e} languageKey=${r}`);let t=await this.send({method:"GET",path:"api/localization/client/bylanguage",query:{resourceKey:e,languageKey:r}});return this.logger.info(`getByLanguage:success resourceKey=${e} languageKey=${r} hasValue=${!!t}`),t??""})}async listResources(){return this.errorHandler.run("listResources",async()=>{let e=await this.cacheHelper.getListResources();if(e)return e;let t=(await this.send({method:"GET",path:"api/localization/client/list"})??[]).map(n=>({key:n.resourceKey,value:n.value,language:n.languageKey}));return await this.cacheHelper.storeListResources(t),this.logger.info(`listResources:success count=${t.length}`),t})}async invalidateCache(e){return this.errorHandler.run("invalidateCache",async()=>this.cacheHelper.invalidate(e))}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)}}};function x(o){D(o);let r=o.cache?.enabled??false?o.cache?.provider??new d:void 0,t=new y({baseUrl:o.baseUrl,fetchFn:o.fetchFn,timeoutMs:o.timeoutMs??1e4,defaultHeaders:o.headers,middleware:o.middleware});return new z({httpTransport:t,authProvider:o.authProvider??(o.token?new u(o.token):void 0),cacheProvider:r,cacheTtlMs:o.cache?.ttlMs,enableLogs:o.enableLogs??false})}function D(o){if(!o?.baseUrl?.trim())throw new i("baseUrl is required to create localization client")}var A=new core.InjectionToken("LOCALIZATION_SDK_OPTIONS"),w=new core.InjectionToken("LOCALIZATION_CLIENT");function F(o){return core.makeEnvironmentProviders([{provide:A,useValue:o},{provide:w,useFactory:()=>x(o)}])}exports.LocalizationService=class C{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))}};exports.LocalizationService=H([core.Injectable({providedIn:"root"}),I(0,core.Inject(w))],exports.LocalizationService);exports.FetchHttpTransport=y;exports.LOCALIZATION_CLIENT=w;exports.LOCALIZATION_SDK_OPTIONS=A;exports.LocalizationAuthError=p;exports.LocalizationError=i;exports.LocalizationNetworkError=m;exports.LocalizationServerError=g;exports.LocalizationTimeoutError=f;exports.MemoryCacheProvider=d;exports.ResourceNotFoundError=h;exports.XAuthTokenProvider=u;exports.createLocalizationClient=x;exports.provideLocalization=F;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import {InjectionToken,Injectable,Inject,makeEnvironmentProviders}from'@angular/core';import {from}from'rxjs';var H=(o,e,t,r)=>{for(var n=e,i=o.length-1,s;i>=0;i--)(s=o[i])&&(n=(s(n))||n);return n},I=(o,e)=>(t,r)=>e(t,r,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 t=this.store.get(e);return t?t.expiresAt!==void 0&&Date.now()>t.expiresAt?(this.store.delete(e),null):t.value:null}async set(e,t,r){let n=r&&r>0?Date.now()+r:void 0;this.store.set(e,{value:t,expiresAt:n});}async delete(e){this.store.delete(e);}async clear(){this.store.clear();}};var a=class extends Error{constructor(t,r){super(t);this.metadata=r;this.name="LocalizationError";}},p=class extends a{constructor(e="Authentication failed",t){super(e,t),this.name="LocalizationAuthError";}},h=class extends a{constructor(e="Resource not found",t){super(e,t),this.name="ResourceNotFoundError";}},g=class extends a{constructor(e="Localization server error",t){super(e,t),this.name="LocalizationServerError";}},m=class extends a{constructor(e="Network error while contacting localization API",t){super(e,t),this.name="LocalizationNetworkError";}},f=class extends a{constructor(e="Localization request timeout",t){super(e,t),this.name="LocalizationTimeoutError";}};var v=class extends Error{constructor(t,r,n){super(`Request failed with status ${t}`);this.statusCode=t;this.responseBody=r;this.responseHeaders=n;this.name="HttpStatusError";}},L=class extends Error{constructor(t){super(`Request timed out after ${t}ms`);this.timeoutMs=t;this.name="HttpTimeoutError";}},l=class extends Error{constructor(t){super("Network error while sending request");this.causeError=t;this.name="HttpNetworkError";}},y=class{constructor(e){this.options=e;this.fetchFn=e.fetchFn??globalThis.fetch.bind(globalThis);}async request(e){let t=e.timeoutMs??this.options.timeoutMs,r=new AbortController,n=setTimeout(()=>r.abort(),t),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:r.signal});try{let s=await this.runRequestMiddleware(i),O;try{O=await this.fetchFn(s);}catch(E){throw this.isAbortError(E)?new L(t):new l(E)}let c=await this.runResponseMiddleware(O);if(!c.ok){let E=await c.text();throw new v(c.status,E,c.headers)}let $=await this.parseResponse(c);return {status:c.status,headers:c.headers,data:$}}catch(s){throw await this.runErrorMiddleware(this.toError(s)),s}finally{clearTimeout(n);}}resolveUrl(e){let t=new URL(e.path,this.options.baseUrl);return e.query&&Object.entries(e.query).forEach(([r,n])=>{n!==void 0&&t.searchParams.set(r,String(n));}),t.toString()}async runRequestMiddleware(e){let t=e;for(let r of this.options.middleware??[])r.onRequest&&(t=await r.onRequest(t));return t}async runResponseMiddleware(e){let t=e;for(let r of this.options.middleware??[])r.onResponse&&(t=await r.onResponse(t));return t}async runErrorMiddleware(e){for(let t of this.options.middleware??[])t.onError&&await t.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 k="localization:listResources",T=class{constructor(e,t,r){this.cacheProvider=e;this.cacheTtlMs=t;this.logger=r;}async getListResources(){this.logger.debug(`listResources:start cacheEnabled=${!!this.cacheProvider}`);let e=await this.cacheProvider?.get(k);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(k,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 b=class{constructor(e){this.logger=e;}async run(e,t){try{return await t()}catch(r){let n=this.map(r);throw this.logger.errorForOperation(e,n,r),n}}validateRequired(e,t){if(!e?.trim())throw new a(`${t} is required`)}map(e){return e instanceof a?e:e instanceof L?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 t=this.map(e);return t.cause??(t.cause=e),t}mapStatusError(e){return e.statusCode===401||e.statusCode===403?new p("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 q="[LocalizationSdk]",R=class{constructor(e=false){this.enabled=e;}debug(e){this.write("debug",e);}info(e){this.write("info",e);}errorForOperation(e,t,r){this.write("error",`${e}:error ${this.formatErrorDetails(t,r)}`);}formatErrorDetails(e,t){let r=this.getOriginalCause(e,t),n=this.getErrorMessage(r),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,t){let n=e.cause??t;return n instanceof l?n.causeError:n}getErrorMessage(e){return e instanceof Error?e.message:typeof e=="string"?e:"unknown-error"}write(e,t){if(!this.enabled)return;let r=`${q} ${t}`;switch(e){case "debug":console.debug(r);break;case "info":console.info(r);break;case "error":console.error(r);break}}};var z=class{constructor(e){this.dependencies=e;this.logger=new R(e.enableLogs),this.cacheHelper=new T(e.cacheProvider,e.cacheTtlMs,this.logger),this.errorHandler=new b(this.logger);}async getCurrentLanguage(e){return this.errorHandler.run("getCurrentLanguage",async()=>{this.errorHandler.validateRequired(e,"resourceKey"),this.logger.debug(`getCurrentLanguage:start resourceKey=${e}`);let t=await this.send({method:"GET",path:"api/localization/client/currentlanguage",query:{resourceKey:e}});return this.logger.info(`getCurrentLanguage:success resourceKey=${e} hasValue=${!!t}`),t??""})}async getByLanguage(e,t){return this.errorHandler.run("getByLanguage",async()=>{this.errorHandler.validateRequired(e,"resourceKey"),this.errorHandler.validateRequired(t,"languageKey"),this.logger.debug(`getByLanguage:start resourceKey=${e} languageKey=${t}`);let r=await this.send({method:"GET",path:"api/localization/client/bylanguage",query:{resourceKey:e,languageKey:t}});return this.logger.info(`getByLanguage:success resourceKey=${e} languageKey=${t} hasValue=${!!r}`),r??""})}async listResources(){return this.errorHandler.run("listResources",async()=>{let e=await this.cacheHelper.getListResources();if(e)return e;let r=(await this.send({method:"GET",path:"api/localization/client/list"})??[]).map(n=>({key:n.resourceKey,value:n.value,language:n.languageKey}));return 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 send(e){try{let t=await this.dependencies.authProvider?.getToken(),r=t?{...e.headers,"X-Auth-Token":t}:e.headers;this.logger.debug(`request:start method=${e.method} path=${e.path} hasAuth=${!!t}`);let n=await this.dependencies.httpTransport.request({...e,headers:r});return this.logger.debug(`request:success method=${e.method} path=${e.path} status=${n.status}`),n.data}catch(t){throw this.errorHandler.preserveCause(t)}}};function x(o){D(o);let t=o.cache?.enabled??false?o.cache?.provider??new d:void 0,r=new y({baseUrl:o.baseUrl,fetchFn:o.fetchFn,timeoutMs:o.timeoutMs??1e4,defaultHeaders:o.headers,middleware:o.middleware});return new z({httpTransport:r,authProvider:o.authProvider??(o.token?new u(o.token):void 0),cacheProvider:t,cacheTtlMs:o.cache?.ttlMs,enableLogs:o.enableLogs??false})}function D(o){if(!o?.baseUrl?.trim())throw new a("baseUrl is required to create localization client")}var A=new InjectionToken("LOCALIZATION_SDK_OPTIONS"),w=new InjectionToken("LOCALIZATION_CLIENT");function F(o){return makeEnvironmentProviders([{provide:A,useValue:o},{provide:w,useFactory:()=>x(o)}])}var C=class{constructor(e){this.client=e;}getCurrentLanguage(e){return from(this.client.getCurrentLanguage(e))}getByLanguage(e,t){return from(this.client.getByLanguage(e,t))}listResources(){return from(this.client.listResources())}invalidateCache(e){return from(this.client.invalidateCache(e))}};C=H([Injectable({providedIn:"root"}),I(0,Inject(w))],C);export{y as FetchHttpTransport,w as LOCALIZATION_CLIENT,A as LOCALIZATION_SDK_OPTIONS,p as LocalizationAuthError,a as LocalizationError,m as LocalizationNetworkError,g as LocalizationServerError,C as LocalizationService,f as LocalizationTimeoutError,d as MemoryCacheProvider,h as ResourceNotFoundError,u as XAuthTokenProvider,x as createLocalizationClient,F as provideLocalization};
1
+ import {InjectionToken,Injectable,Inject,makeEnvironmentProviders}from'@angular/core';import {from}from'rxjs';var H=(o,e,r,t)=>{for(var n=e,a=o.length-1,s;a>=0;a--)(s=o[a])&&(n=(s(n))||n);return n},I=(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 i=class extends Error{constructor(r,t){super(r);this.metadata=t;this.name="LocalizationError";}},p=class extends i{constructor(e="Authentication failed",r){super(e,r),this.name="LocalizationAuthError";}},h=class extends i{constructor(e="Resource not found",r){super(e,r),this.name="ResourceNotFoundError";}},g=class extends i{constructor(e="Localization server error",r){super(e,r),this.name="LocalizationServerError";}},m=class extends i{constructor(e="Network error while contacting localization API",r){super(e,r),this.name="LocalizationNetworkError";}},f=class extends i{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";}},L=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";}},y=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),a=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(a),O;try{O=await this.fetchFn(s);}catch(E){throw this.isAbortError(E)?new L(r):new l(E)}let c=await this.runResponseMiddleware(O);if(!c.ok){let E=await c.text();throw new v(c.status,E,c.headers)}let $=await this.parseResponse(c);return {status:c.status,headers:c.headers,data:$}}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 k="localization:listResources",T=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(k);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(k,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 b=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 i(`${r} is required`)}map(e){return e instanceof i?e:e instanceof L?new f(e.message):e instanceof l?new m(e.message):e instanceof v?this.mapStatusError(e):new i("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 p("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 i(e.message,{statusCode:e.statusCode})}};var q="[LocalizationSdk]",R=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),a=[`type=${e.name}`,`message=${e.message}`];return n&&n!==e.message&&a.push(`original=${n}`),e instanceof i&&e.metadata?.statusCode&&a.push(`statusCode=${e.metadata.statusCode}`),a.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=`${q} ${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")?"\u{1F310}":r.includes("request:success")?"\u{1F4E1}":r.includes("cache-hit")?"\u26A1":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 z=class{constructor(e){this.dependencies=e;this.logger=new R(e.enableLogs),this.cacheHelper=new T(e.cacheProvider,e.cacheTtlMs,this.logger),this.errorHandler=new b(this.logger);}async getCurrentLanguage(e){return this.errorHandler.run("getCurrentLanguage",async()=>{this.errorHandler.validateRequired(e,"resourceKey"),this.logger.debug(`getCurrentLanguage:start resourceKey=${e}`);let r=await this.send({method:"GET",path:"api/localization/client/currentlanguage",query:{resourceKey:e}});return this.logger.info(`getCurrentLanguage:success resourceKey=${e} hasValue=${!!r}`),r??""})}async getByLanguage(e,r){return this.errorHandler.run("getByLanguage",async()=>{this.errorHandler.validateRequired(e,"resourceKey"),this.errorHandler.validateRequired(r,"languageKey"),this.logger.debug(`getByLanguage:start resourceKey=${e} languageKey=${r}`);let t=await this.send({method:"GET",path:"api/localization/client/bylanguage",query:{resourceKey:e,languageKey:r}});return this.logger.info(`getByLanguage:success resourceKey=${e} languageKey=${r} hasValue=${!!t}`),t??""})}async listResources(){return this.errorHandler.run("listResources",async()=>{let e=await this.cacheHelper.getListResources();if(e)return e;let t=(await this.send({method:"GET",path:"api/localization/client/list"})??[]).map(n=>({key:n.resourceKey,value:n.value,language:n.languageKey}));return await this.cacheHelper.storeListResources(t),this.logger.info(`listResources:success count=${t.length}`),t})}async invalidateCache(e){return this.errorHandler.run("invalidateCache",async()=>this.cacheHelper.invalidate(e))}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)}}};function x(o){D(o);let r=o.cache?.enabled??false?o.cache?.provider??new d:void 0,t=new y({baseUrl:o.baseUrl,fetchFn:o.fetchFn,timeoutMs:o.timeoutMs??1e4,defaultHeaders:o.headers,middleware:o.middleware});return new z({httpTransport:t,authProvider:o.authProvider??(o.token?new u(o.token):void 0),cacheProvider:r,cacheTtlMs:o.cache?.ttlMs,enableLogs:o.enableLogs??false})}function D(o){if(!o?.baseUrl?.trim())throw new i("baseUrl is required to create localization client")}var A=new InjectionToken("LOCALIZATION_SDK_OPTIONS"),w=new InjectionToken("LOCALIZATION_CLIENT");function F(o){return makeEnvironmentProviders([{provide:A,useValue:o},{provide:w,useFactory:()=>x(o)}])}var C=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))}};C=H([Injectable({providedIn:"root"}),I(0,Inject(w))],C);export{y as FetchHttpTransport,w as LOCALIZATION_CLIENT,A as LOCALIZATION_SDK_OPTIONS,p as LocalizationAuthError,i as LocalizationError,m as LocalizationNetworkError,g as LocalizationServerError,C as LocalizationService,f as LocalizationTimeoutError,d as MemoryCacheProvider,h as ResourceNotFoundError,u as XAuthTokenProvider,x as createLocalizationClient,F as provideLocalization};
package/package.json CHANGED
@@ -20,7 +20,7 @@
20
20
  "publishConfig": {
21
21
  "access": "public"
22
22
  },
23
- "version": "1.0.3507",
23
+ "version": "1.0.3514",
24
24
  "devDependencies": {
25
25
  "@angular/core": "^20.3.15",
26
26
  "@angular/common": "^20.3.15",