UNPKG

@localazy/cdn-client

Version:

Node.js module that allows you to easily interact with the Localazy CDN.

3 lines (2 loc) 10.1 kB
class e{context;constructor(e){this.context=e}async fetchLocale(e){return this.context.cache.has(e)?new Promise(t=>{t(this.context.cache.get(e))}):this.context.client.get(e.metafileLocale.uri)}async fetchMetafile(){return await this.context.client.get(this.context.metafile.params.jsonPath)}}class t{map;constructor(){this.map=new Map}get(e){return this.map.get(e)}has(e){return this.map.has(e)}set(e,t){this.map.set(e,t)}flush(){this.map=new Map}}const s=e=>"string"==typeof e,a=e=>void 0===e,i=e=>Array.isArray(e),l=e=>"[object Object]"===Object.prototype.toString.call(e),r=e=>[...new Set(e)],o=(e,t)=>{const s={};return e.filter(e=>{const a=t(e);return!Object.hasOwn(s,a)&&(s[a]=!0,!0)})};class c{context;cacheAdapter;constructor(e){this.context=e,this.cacheAdapter=new t}setIfMissed(e){const{metafileFile:t,metafileLocale:s,data:a}=e,i=this.keyFromMetafile({metafileFile:t,metafileLocale:s});this.cacheAdapter.has(i)||this.cacheAdapter.set(i,a)}has(e){const t=this.keyFromMetafile(e);return this.cacheAdapter.has(t)}get(e){const t=this.keyFromMetafile(e);return this.cacheAdapter.get(t)}flush(){this.cacheAdapter.flush()}keyFromMetafile(e){const{metafileFile:t,metafileLocale:s}=e,a=[...r(t.productFlavors)].sort().join("-");return[this.context.metafile.params.cdnId,t.id,t.file,t.path,t.library,t.module,t.buildType,a,s.locale,s.timestamp.toString()].filter(e=>""!==e).join("-")}}class n{context;constructor(e){this.context=e}createCdnResponse(e){const{requests:t,responses:s,hasSingleFileResponse:a,hasSingleLocaleResponse:i}=e;return 0===s.length||void 0===s[0]?{}:(this.cacheResponses(t,s),a&&i?s[0]:n.transformResponses(e))}cacheResponses(e,t){t.forEach((t,s)=>{if(void 0!==e[s]){const{metafileFile:a,metafileLocale:i}=e[s];a&&i&&this.context.cache.setIfMissed({metafileFile:a,metafileLocale:i,data:t})}})}static transformResponses(e){const{requests:t,responses:s,hasSingleFileResponse:a}=e;return s.reduce((e,s,i)=>{if(void 0!==t[i]){const{metafileFile:l,metafileLocale:r}=t[i];l&&r&&(a?e[r.locale]=s:(e[l.id]||(e[l.id]={}),e[l.id][r.locale]=s))}return e},{})}}class h{metafile;cdn;client;api;cache;responseFactory;constructor(t){this.metafile=t.metafileContext,this.cdn=t.cdn,this.client=t.client,this.api=new e(this),this.cache=new c(this),this.responseFactory=new n(this)}}class u{id;file;path;library;module;buildType;timestamp;productFlavors;locales;baseUrl;constructor(e){this.id=e.id,this.file=e.file,this.path=e.path,this.library=e.library,this.module=e.module,this.buildType=e.buildType,this.timestamp=e.timestamp,this.productFlavors=e.productFlavors,this.locales=e.locales,this.baseUrl=e.baseUrl}toCdnFile(){return{id:this.id,file:this.file,path:this.path,library:this.library,module:this.module,buildType:this.buildType,productFlavors:this.productFlavors,locales:this.locales.map(e=>({locale:e.locale,isBaseLocale:e.isBaseLocale,uri:`${this.baseUrl}${e.uri}`}))}}}class p{language;region;script;isRtl;name;localizedName;uri;timestamp;baseLocale;constructor(e,t){this.language=e.language,this.region=e.region,this.script=e.script,this.isRtl=e.isRtl,this.name=e.name,this.localizedName=e.localizedName,this.uri=e.uri,this.timestamp=e.timestamp,this.baseLocale=t}get locale(){return this.language&&this.region&&this.script?`${this.language}_${this.region}#${this.script}`:this.language&&this.script?`${this.language}#${this.script}`:this.language&&this.region?`${this.language}_${this.region}`:this.language}get isBaseLocale(){return this.locale===this.baseLocale}toCdnLocale(){return{locale:this.locale,isBaseLocale:this.isBaseLocale,language:this.language,region:this.region,script:this.script,isRtl:this.isRtl,name:this.name,localizedName:this.localizedName}}}class d{projectUrl;baseLocale;locales;timestamp;files;filesMap;constructor(e,t){this.projectUrl=e.projectUrl,this.timestamp=e.timestamp,this.files=d.filesFactory(e.files,e.baseLocale,t),this.filesMap=d.filesMapFactory(this.files),this.locales=d.localesFactory(this.files),this.baseLocale=this.locales.find(e=>e.isBaseLocale)}static createEmpty(e){return new d({projectUrl:"",baseLocale:"",timestamp:0,files:{}},e)}static filesFactory(e,t,s){return Object.keys(e).reduce((a,i)=>{if(void 0!==e[i]){const l=e[i].locales.map(e=>new p(e,t));a.push(new u({...e[i],id:i,locales:l,baseUrl:s.baseUrl}))}return a},[])}static filesMapFactory(e){return e.reduce((e,t)=>(e[t.id]=t,e),{})}static localesFactory(e){const t=e.reduce((e,t)=>(e.push(...t.locales.map(e=>e.toCdnLocale())),e),[]);return o(t,e=>e.locale)}}class f{options;constructor(e){this.options=f.parseMetafileUrl(e)}get url(){return this.options.url}get baseUrl(){return this.options.baseUrl}get cdnId(){return this.options.cdnId}get jsonPath(){return this.options.jsonPath}static parseMetafileUrl(e){let t;try{t=new URL(e)}catch{throw new Error('Invalid param: "options.metafile" cannot be parsed as url.')}const s=/^\/(.*?)\/(.*?)\.(v2.json|js|ts)$/.exec(t.pathname);if(null===s||4!==s.length||void 0===s[1]||void 0===s[2])throw new Error('Invalid param: "options.metafile" contains invalid metafile url.');const a=s[1],i=s[2];return{url:e,baseUrl:t.origin,cdnId:a,jsonPath:`/${a}/${i}.v2.json`}}}class m{params;parsedData;data;constructor(e){this.params=new f(e.metafile),this.parsedData=null,this.data=d.createEmpty(this.params)}setMetafile(e){this.parsedData=e,this.data=new d(e,this.params)}}class g{baseUrl;constructor(e){this.baseUrl=e}async get(e){const t=await fetch(`${this.baseUrl}${e}`),s=t.headers.get("content-type"),a="application/json5"===s||"application/json"===s;if(t.status>=400)throw new Error(`Request failed with status code ${t.status.toString()}`);let i;return i=a?await t.json():await t.text(),i}}class w{context;constructor(e){this.context=e}}class x extends w{flush=()=>{this.context.cache.flush()}}class y extends w{get projectUrl(){return this.context.metafile.data.projectUrl}get baseLocale(){return this.context.metafile.data.baseLocale}get url(){return this.context.metafile.params.url}get files(){return this.context.metafile.data.files.map(e=>e.toCdnFile())}locales=e=>{const{excludeBaseLocale:t}=e||{},{locales:s}=this.context.metafile.data;return t?s.filter(e=>!e.isBaseLocale):s};refresh=async()=>{const e=await this.context.api.fetchMetafile();this.context.metafile.setMetafile(e)};switch=async e=>{this.context.metafile.params=new f(e.metafile),await this.refresh()}}class b{data;context;constructor(e){this.context=e.context,this.data=e.data||{}}}class F{files;localesMap;hasSingleFileResponse;hasSingleLocaleResponse;context;constructor(e){this.files=[],this.localesMap=new b({context:e}),this.hasSingleFileResponse=!1,this.hasSingleLocaleResponse=!1,this.context=e}async execute(){const e=this.getPromises(),t=e.map(e=>e[0]),s=e.map(e=>e[1]),a=await Promise.all(t);return this.context.responseFactory.createCdnResponse({requests:s,responses:a,localesMap:this.localesMap,hasSingleFileResponse:this.hasSingleFileResponse,hasSingleLocaleResponse:this.hasSingleLocaleResponse})}getPromises(){return this.files.reduce((e,t)=>(void 0!==this.localesMap.data?.[t.id]&&e.push(...this.localesMap.data[t.id].map(e=>{const s={metafileFile:t,metafileLocale:e};return[this.context.api.fetchLocale(s),s]})),e),[])}}class L{context;request;constructor(e){this.context=e,this.request=new F(this.context)}addFiles(e){if(!(l(e)||s(e)||a(e)||i(e)))throw new Error('Invalid param: "request.files" must be object, array, string or undefined.');if(i(e)&&e.forEach(e=>{if(!l(e)&&!s(e))throw new Error('Invalid param: array "request.files" must contain objects or strings.')}),s(e)){this.request.hasSingleFileResponse=!0;const t=this.context.metafile.data.files.find(t=>t.id===e);if(!(t instanceof u))throw new Error(`File not found: "${e}".`);this.request.files=[t]}else if(a(e))this.request.files=[...this.context.metafile.data.files];else if(i(e))this.request.files=e.map(e=>{let t;if(s(e)){const s=this.context.metafile.data.files.find(t=>t.id===e);if(a(s))throw new Error(`File not found: "${e}".`);t=s}else{const s=this.context.metafile.data.files.find(t=>t.id===e.id);if(a(s))throw new Error(`File not found: "${e.id}".`);t=s}return t});else if(l(e)){this.request.hasSingleFileResponse=!0;const t=this.context.metafile.data.files.find(t=>t.id===e.id);if(a(t))throw new Error(`File not found: "${e.id}".`);this.request.files=[t]}return this}addLocales(e,t){if(!(s(e)||a(e)||i(e)))throw new Error('Invalid param: "request.locales" must be array, string or undefined.');return i(e)&&e.forEach(e=>{if(!s(e))throw new Error('Invalid param: array "request.locales" must contain strings.')}),s(e)?(this.request.hasSingleLocaleResponse=!0,this.request.files.reduce((t,s)=>(t.data[s.id]=s.locales.filter(t=>t.locale===e),t),this.request.localesMap)):a(e)?this.request.files.reduce((e,s)=>(e.data[s.id]=t?s.locales.filter(e=>!e.isBaseLocale):s.locales,e),this.request.localesMap):i(e)&&this.request.files.reduce((t,s)=>(t.data[s.id]=s.locales.filter(t=>e.includes(t.locale)),t),this.request.localesMap),this}getCdnRequest(){const e=this.request;return this.request=new F(this.context),e}}class R{metafile;cache;context;static version="1.5.13";constructor(e){const t=new m(e),s=new g(t.params.baseUrl);this.context=new h({metafileContext:t,cdn:this,client:s}),this.metafile=new y(this.context),this.cache=new x(this.context)}fetch=async e=>{const{files:t,locales:s,excludeBaseLocale:a}=e||{};return new L(this.context).addFiles(t).addLocales(s,a).getCdnRequest().execute()};static async create(e){if(!e)throw new Error('Invalid param: missing required "options" parameter.');if(!s(e.metafile))throw new Error('Invalid param: "options.metafile" must be string.');const t=new R(e);return await t.metafile.refresh(),t}}export{e as Api,w as CdnBase,x as CdnCache,R as CdnClient,y as CdnMetafile,h as Context,g as FetchHttpAdapter,c as LocalesCache,b as LocalesMap,t as MemoryCacheAdapter,m as MetafileContext,d as MetafileData,u as MetafileFile,p as MetafileLocale,f as MetafileParams,F as Request,L as RequestBuilder,n as ResponseFactory,i as isArray,l as isPlainObject,s as isString,a as isUndefined,r as uniq,o as uniqBy}; //# sourceMappingURL=localazy-cdn-client.min.js.map