webhanger-front 1.0.1 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/browser.min.js +1 -0
  2. package/build.js +29 -0
  3. package/package.json +10 -3
package/browser.min.js ADDED
@@ -0,0 +1 @@
1
+ !function(e){const t="components",n="wh_";function r(e,t,n){if(!e)return"";const r=t+n,o=Uint8Array.from(atob(e),e=>e.charCodeAt(0)),a=(new TextEncoder).encode(r),s=new Uint8Array(o.length);for(let e=0;e<o.length;e++)s[e]=o[e]^a[e%a.length];return(new TextDecoder).decode(s)}function o(){return new Promise((e,n)=>{const r=indexedDB.open("webhanger_cache",1);r.onupgradeneeded=e=>e.target.result.createObjectStore(t),r.onsuccess=t=>e(t.target.result),r.onerror=()=>n(r.error)})}function a(e){return new Promise(t=>{if("style"===e.type?document.querySelector(`link[href="${e.url}"]`):document.querySelector(`script[src="${e.url}"]`))return t();if("style"===e.type){const n=document.createElement("link");n.rel="stylesheet",n.href=e.url,n.onload=t,n.onerror=t,document.head.appendChild(n)}else{const n=document.createElement("script");n.src=e.url,e.defer&&(n.defer=!0),e.async&&(n.async=!0),n.onload=t,n.onerror=t,document.head.appendChild(n)}})}e.WebHangerFront={load:async function(e,s,c,i,d="[data-wh]",l=null){if(!e||!s||!c||null==i)return void console.error("[WebHanger] Missing required params: cdnUrl, projectId, token, expires");if(0!==i&&Math.floor(Date.now()/1e3)>i)return void console.warn("[WebHanger] Token expired.");const u=function(e){return function(t,n={}){"function"==typeof e&&e({stage:t,...n})}}(l),h=function(e){const t=document.querySelector(e||"[data-wh]");if(!t)return{show:()=>{},hide:()=>{}};const n=document.createElement("div");return n.setAttribute("data-wh-loader",""),n.style.cssText="\n display:flex; align-items:center; justify-content:center;\n padding: 24px; width:100%; box-sizing:border-box;\n ",n.innerHTML='\n <div style="\n width:28px; height:28px;\n border:3px solid #e5e7eb;\n border-top-color:#6366f1;\n border-radius:50%;\n animation:wh-spin 0.7s linear infinite;\n "></div>\n <style>\n @keyframes wh-spin { to { transform: rotate(360deg); } }\n </style>\n ',{show(){t.appendChild(n)},hide(){n.parentNode&&n.parentNode.removeChild(n)}}}(d);u("start",{cdnUrl:e,selector:d}),h.show();const f=`${e}@${i}`;try{u("fetching");let l,m=await async function(e){try{const t=localStorage.getItem(n+e);if(t)return t}catch(e){}return await async function(e){const n=await o();return new Promise((r,o)=>{const a=n.transaction(t,"readonly").objectStore(t).get(e);a.onsuccess=()=>r(a.result),a.onerror=()=>o(a.error)})}(e)}(f);m||(m=await async function(e,t,n){const r=n?`${e}?token=${t}&expires=${n}`:`${e}?token=${t}`,o=await fetch(r);if(!o.ok)throw Error("Failed to fetch component: "+o.status);return await o.text()}(e,c,i),await async function(e,r){try{if(r.length<51200)return void localStorage.setItem(n+e,r)}catch(e){}await async function(e,n){const r=await o();return new Promise((o,a)=>{const s=r.transaction(t,"readwrite").objectStore(t).put(n,e);s.onsuccess=()=>o(),s.onerror=()=>a(s.error)})}(e,r)}(f,m));try{l=JSON.parse(m)}catch(e){l={}}l.assets&&l.assets.length&&(u("assets",{count:l.assets.length,assets:l.assets}),await async function(e=[]){for(const t of e)await a(t)}(l.assets)),u("injecting"),h.hide(),function(e,t,n){const o=document.querySelector(n||"[data-wh]");if(!o)return void console.warn("[WebHanger] No mount target found.");let a;try{a=JSON.parse(e)}catch(e){return void console.error("[WebHanger] Invalid component payload.")}const s=r(a.c,t,"::css");if(s){const e=document.createElement("style");e.textContent=s,document.head.appendChild(e)}const c=r(a.h,t,"::html");c&&(o.innerHTML=c);const i=r(a.j,t,"::js");if(i){const e=document.createElement("script");e.textContent=i,document.head.appendChild(e),document.head.removeChild(e)}}(m,s,d),u("done")}catch(e){h.hide(),u("error",{message:e.message}),console.error("[WebHanger] Load failed:",e.message)}},clearCache:async function(){Object.keys(localStorage).filter(e=>e.startsWith(n)).forEach(e=>localStorage.removeItem(e));try{(await o()).transaction(t,"readwrite").objectStore(t).clear()}catch(e){}if("caches"in window){const e=await caches.keys();await Promise.all(e.map(e=>caches.delete(e)))}if("serviceWorker"in navigator){const e=await navigator.serviceWorker.getRegistrations();await Promise.all(e.map(e=>e.unregister()))}Object.keys(sessionStorage).filter(e=>e.startsWith(n)).forEach(e=>sessionStorage.removeItem(e))},version:"1.0.0"}}(window);
package/build.js ADDED
@@ -0,0 +1,29 @@
1
+ import { minify } from "terser";
2
+ import fs from "fs-extra";
3
+
4
+ const src = await fs.readFile("./browser.js", "utf-8");
5
+
6
+ const result = await minify(src, {
7
+ compress: {
8
+ dead_code: true,
9
+ drop_console: false,
10
+ passes: 3,
11
+ unsafe: true,
12
+ unsafe_math: true,
13
+ pure_getters: true
14
+ },
15
+ mangle: {
16
+ toplevel: true, // mangle top-level names
17
+ properties: false // keep property names (needed for API surface)
18
+ },
19
+ format: {
20
+ comments: false, // strip all comments
21
+ ascii_only: true // ensure safe output
22
+ }
23
+ });
24
+
25
+ await fs.writeFile("./browser.min.js", result.code, "utf-8");
26
+
27
+ const orig = (await fs.stat("./browser.js")).size;
28
+ const mini = Buffer.byteLength(result.code);
29
+ console.log(`✅ Minified: ${(orig/1024).toFixed(1)}kB → ${(mini/1024).toFixed(1)}kB (${Math.round((1-mini/orig)*100)}% reduction)`);
package/package.json CHANGED
@@ -1,11 +1,15 @@
1
1
  {
2
2
  "name": "webhanger-front",
3
- "version": "1.0.1",
3
+ "version": "1.0.5",
4
4
  "description": "WebHanger browser SDK — load encrypted UI components from CDN",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
7
- "browser": "browser.js",
7
+ "browser": "browser.min.js",
8
8
  "type": "module",
9
+ "scripts": {
10
+ "build": "node build.js",
11
+ "prepublishOnly": "node build.js"
12
+ },
9
13
  "keywords": [
10
14
  "webhanger",
11
15
  "cdn",
@@ -13,5 +17,8 @@
13
17
  "frontend",
14
18
  "sdk"
15
19
  ],
16
- "license": "ISC"
20
+ "license": "ISC",
21
+ "devDependencies": {
22
+ "terser": "^5.0.0"
23
+ }
17
24
  }