@salla.sa/embedded-sdk 0.2.5 → 0.2.7
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 +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +416 -270
- package/dist/esm/index.js.map +1 -1
- package/dist/system/index.js +2 -2
- package/dist/system/index.js.map +1 -1
- package/dist/types/index.d.ts +83 -22
- package/dist/umd/index.js +2 -2
- package/dist/umd/index.js.map +1 -1
- package/package.json +1 -1
package/dist/system/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
System.register("SallaEmbeddedSDK",[],(function(I,De){"use strict";return{execute:(function(){I({getEmbeddedApp:M,resetEmbeddedApp:$e});const o="embedded::",C={INIT:`${o}iframe.ready`,READY:`${o}ready`,DESTROY:`${o}destroy`},L={PROVIDE:`${o}context.provide`,THEME_CHANGE:`${o}theme.change`},h={LOADING:`${o}ui.loading`,BREADCRUMBS:`${o}ui.breadcrumbs`,TOAST:`${o}ui.toast`,CONFIRM:`${o}ui.confirm`,CONFIRM_RESPONSE:`${o}ui.confirm.response`},B={},x={REFRESH:`${o}auth.refresh`},b={NAVIGATE:`${o}page.navigate`,REDIRECT:`${o}page.redirect`,SET_TITLE:`${o}page.setTitle`},c={SET_ACTION:`${o}nav.setAction`,CLEAR_ACTION:`${o}nav.clearAction`,ACTION_CLICK:`${o}nav.actionClick`,ADD_ITEM:`${o}nav.addItem`,ADD_ITEM_RESPONSE:`${o}nav.addItem.response`,UPDATE_ITEM:`${o}nav.updateItem`,REMOVE_ITEM:`${o}nav.removeItem`,ITEM_CLICK:`${o}nav.itemClick`},g={CREATE:`${o}checkout.create`,RESPONSE:`${o}checkout.response`,GET_ADDONS:`${o}checkout.getAddons`,GET_ADDONS_RESPONSE:`${o}checkout.getAddons.response`,RESET_CACHE:`${o}checkout.resetCache`},S=B.version||"",X=1e4,W=["localhost","merchants.workers.dev","s.salla.sa",".salla.group",".salla.sa"],Y=new Set(["ar","he","fa","ur","ps","sd","yi"]);function Q(t){const e=(t??"ar").toLowerCase().split(/[-_]/)[0];return Y.has(e)?"rtl":"ltr"}let A={showVersion:!0,debug:!1};function J(t){A={...A,...t}}function k(t){return`%c${t}`}function q(t,e="#fff"){return`background-color: ${t}; color: ${e}; padding: 2px 6px; border-radius: 3px; font-weight: 500; font-size: 11px;`}function y(t,...e){if(t==="debug"&&!A.debug)return;const r=[],i=[];r.push(k("EmbeddedSDK")),i.push(q("#10b981","#fff")),A.showVersion&&(r.push(k(`v${S}`)),i.push(q("#6b7280","#fff")));const n=r.join("").trim();(console[t]||console.log)(n,...i,...e)}const a={log:(...t)=>{y("log",...t)},warn:(...t)=>{y("warn",...t)},error:(...t)=>{y("error",...t)},info:(...t)=>{y("info",...t)},debug:(...t)=>{y("debug",...t)}};function Z(t){try{const r=new URL(t).hostname;return W.some(i=>i.startsWith(".")?r.endsWith(i)||r===i.slice(1):r===i||r.startsWith(`${i}:`))}catch{return!1}}function ee(){return typeof window>"u"||window.parent===window?null:window.parent}function u(t,e,r="*",i,n){const s=ee();if(!s){a.warn("Not running in an iframe, cannot post to host");return}const d={event:t,payload:e||{},timestamp:Date.now(),source:"embedded-app",...i&&{requestId:i},metadata:{version:S}};s.postMessage(d,r)}const p=new Map;let R=!1;function z(t){if(process.env.NODE_ENV==="production"&&!Z(t.origin))return;const e=t.data;if(!e||typeof e.event!="string"||!e.payload||typeof e.timestamp!="number"||!e.source){a.warn("Invalid message structure received:",e);return}const r=p.get(e.event);r&&r.forEach(n=>{try{n(e)}catch(s){a.error("Error in message handler:",s)}});const i=p.get("*");i&&i.forEach(n=>{try{n(e)}catch(s){a.error("Error in wildcard handler:",s)}})}function te(){R||typeof window>"u"||(window.addEventListener("message",z),R=!0)}function m(t,e){te(),p.has(t)||p.set(t,new Set);const r=p.get(t);return r.add(e),()=>{r.delete(e),r.size===0&&p.delete(t)}}function re(t,e=X){return new Promise((r,i)=>{const n=setTimeout(()=>{s(),i(new Error(`[EmbeddedSDK] Timeout waiting for "${t}" message`))},e),s=m(t,d=>{clearTimeout(n),s(),r(d)})})}function ie(){p.clear(),R&&typeof window<"u"&&(window.removeEventListener("message",z),R=!1)}function ne(){return typeof window>"u"?!1:window.parent!==window}function se(t,e,r){const i={event:t,payload:e,timestamp:Date.now(),source:"merchant-dashboard",...r,metadata:{version:S,synthetic:!0}};p.get(t)?.forEach(s=>{try{s(i)}catch(d){a.error("Error in message handler:",d)}})}const E=new Map,ae=3e4;function P(){const t=Date.now(),e=Math.random().toString(36).slice(2,9);return`req_${t}_${e}`}function _(t,e={},r=ae){const i=P();return new Promise((n,s)=>{const d=setTimeout(()=>{E.get(i)&&(E.delete(i),s(new Error(`[EmbeddedSDK] Request "${t}" timed out after ${r}ms`)))},r);E.set(i,{resolve:n,reject:s,timeout:d,event:t}),u(t,e,"*",i)})}function $(t,e,r){const i=E.get(t);if(!i){a.warn(`Received response for unknown request: ${t}`);return}clearTimeout(i.timeout),E.delete(t),i.resolve(e)}function oe(t="SDK cleanup"){E.forEach((e,r)=>{clearTimeout(e.timeout),e.reject(new Error(`[EmbeddedSDK] Request ${r} cancelled: ${t}`))}),E.clear()}function T(){const t=new Set;return{subscribe(e){return t.add(e),()=>{t.delete(e)}},notify(...e){t.forEach(r=>{try{r(...e)}catch(i){a.error("Error in subscription callback:",i)}})},clear(){t.clear()},size(){return t.size}}}const ue="https://api.salla.dev";class w extends Error{constructor(e,r,i){super(e),this.status=r,this.response=i,this.name="ApiError"}}async function de(t,e={}){const{method:r="GET",headers:i={},body:n,timeout:s=3e4}=e,d=`${ue}${t}`,O=new AbortController,K=setTimeout(()=>{O.abort()},s);try{const l=await fetch(d,{method:r,headers:{"Content-Type":"application/json",...i},body:n?JSON.stringify(n):void 0,signal:O.signal});clearTimeout(K);let N;if(l.headers.get("content-type")?.includes("application/json")?N=await l.json():N=await l.text(),!l.ok)throw new w(`API request failed: ${l.statusText}`,l.status,N);return N}catch(l){throw clearTimeout(K),l instanceof w?l:l instanceof Error?l.name==="AbortError"?new w(`Request timeout after ${s}ms`):new w(`Request failed: ${l.message}`):new w("Unknown error occurred")}}function D(t){return{isVerified:!1,isError:!0,error:t,data:null}}async function ce(t){const{token:e,appId:r,refreshOnError:i=!0}=t;if(!e){const n="Token is required. Provide it as a parameter or in URL as ?token=XXX";return a.error("Error in introspect:",n),D(n)}if(!r){const n="App ID is required. Provide it as a parameter or in URL as ?app_id=XXX";return a.error("Error in introspect:",n),D(n)}try{const n=await de("/exchange-authority/v1/introspect",{method:"POST",headers:{"S-Source":r,"Content-Type":"application/json"},body:{env:"prod",token:e,iss:"merchant-dashboard",subject:"embedded-page"}}),s=n.success;return{isVerified:s,isError:!s,error:s?void 0:"API request failed",data:s?n.data:null}}catch(n){i&&(M().ui.toast.error(n?.toString()??"Introspect error"),u(x.REFRESH,{})),a.error("Error in introspect:",n);const s=n instanceof Error?n.message:n;return D(s)}}function le(t){return{getToken(){return new URLSearchParams(window.location.search).get("token")},getAppId(){return new URLSearchParams(window.location.search).get("app_id")},refresh(){u(x.REFRESH,{})},async introspect(e={}){const r=e.token??this.getToken()??"",i=e.appId??this.getAppId()??"";return ce({token:r,appId:i,refreshOnError:e.refreshOnError})}}}const U=["success","error","warning","info"];function fe(t){const e=[];return t.type===void 0||t.type===null?e.push("Toast type is required"):(typeof t.type!="string"||!U.includes(t.type))&&e.push(`Invalid toast type "${t.type}". Expected: ${U.join(" | ")}`),t.message===void 0||t.message===null?e.push("Toast message is required"):typeof t.message!="string"?e.push("Toast message must be a string"):t.message.trim()===""&&e.push("Toast message cannot be empty"),t.duration!==void 0&&t.duration!==null&&(typeof t.duration!="number"?e.push("Toast duration must be a number"):t.duration<0&&e.push("Toast duration cannot be negative")),{valid:e.length===0,errors:e}}function V(t,e){const r=[];return typeof t!="object"||t===null?(r.push(`${e} must be an object`),r):((typeof t.type!="string"||t.type.trim()==="")&&r.push(`${e} must have a valid type`),(typeof t.slug!="string"||t.slug.trim()==="")&&r.push(`${e} must have a valid slug`),t.quantity!==void 0&&(typeof t.quantity!="number"||t.quantity<1)&&r.push(`${e} must have a quantity >= 1`),r)}function he(t){const e=[];if(typeof t!="object"||t===null)return e.push("Checkout options must be an object"),{valid:!1,errors:e};const r="item"in t,i="items"in t;if(!r&&!i)return e.push("Checkout requires either 'item' or 'items'"),{valid:!1,errors:e};if(r){const n=V(t.item,"Item");return e.push(...n),{valid:e.length===0,errors:e}}return Array.isArray(t.items)?t.items.length===0?(e.push("At least one item is required"),{valid:!1,errors:e}):(t.items.forEach((n,s)=>{const d=V(n,`Item at index ${s}`);e.push(...d)}),{valid:e.length===0,errors:e}):(e.push("Checkout items must be an array"),{valid:!1,errors:e})}function pe(t){const e=[];return t.path===void 0||t.path===null?e.push("Navigation path is required"):typeof t.path!="string"?e.push("Navigation path must be a string"):t.path.trim()===""&&e.push("Navigation path cannot be empty"),t.replace!==void 0&&typeof t.replace!="boolean"&&e.push("Navigation replace option must be a boolean"),{valid:e.length===0,errors:e}}function me(t){const e=[];if(t.url===void 0||t.url===null)e.push("Redirect URL is required");else if(typeof t.url!="string")e.push("Redirect URL must be a string");else if(t.url.trim()==="")e.push("Redirect URL cannot be empty");else try{new URL(t.url)}catch{e.push(`Invalid redirect URL: "${t.url}"`)}return{valid:e.length===0,errors:e}}function ge(t){const e=[];return t.title?typeof t.title!="string"&&e.push("Nav action title must be a string"):e.push("Nav action title is required"),t.value?typeof t.value!="string"&&e.push("Nav action value must be a string"):e.push("Nav action value is required"),t.subTitle!==void 0&&t.subTitle!==null&&typeof t.subTitle!="string"&&e.push("Nav action subTitle must be a string"),t.icon!==void 0&&t.icon!==null&&typeof t.icon!="string"&&e.push("Nav action icon must be a string"),t.disabled!==void 0&&t.disabled!==null&&typeof t.disabled!="boolean"&&e.push("Nav action disabled must be a boolean"),t.extendedActions!==void 0&&t.extendedActions!==null&&(Array.isArray(t.extendedActions)?t.extendedActions.forEach((r,i)=>{if(typeof r!="object"||r===null){e.push(`Extended action at index ${i} must be an object`);return}const n=r;(!n.title||typeof n.title!="string")&&e.push(`Extended action at index ${i} is missing required "title" property`),(!n.value||typeof n.value!="string")&&e.push(`Extended action at index ${i} is missing required "value" property`),n.subTitle!==void 0&&typeof n.subTitle!="string"&&e.push(`Extended action at index ${i} subTitle must be a string`),n.icon!==void 0&&typeof n.icon!="string"&&e.push(`Extended action at index ${i} icon must be a string`),n.disabled!==void 0&&typeof n.disabled!="boolean"&&e.push(`Extended action at index ${i} disabled must be a boolean`)}):e.push("Nav action extendedActions must be an array")),{valid:e.length===0,errors:e}}function Ee(t){const e=[];if(typeof t!="object"||t===null)return e.push("Nav addItem expects an object item"),{valid:!1,errors:e};const r=t;return["title","value","url"].forEach(i=>{(typeof r[i]!="string"||!String(r[i]).trim())&&e.push(`Sub-nav addItem "${i}" must be non-empty string`)}),r.disabled!==void 0&&typeof r.disabled!="boolean"&&e.push('Sub-nav addItem "disabled" must be boolean'),r.active!==void 0&&typeof r.active!="boolean"&&e.push('Sub-nav addItem "active" must be boolean'),{valid:e.length===0,errors:e}}function be(t){const e=[];if(typeof t!="object"||t===null)return e.push("Nav updateItem expects an object item"),{valid:!1,errors:e};const r=t;if(typeof r.id!="string"||!r.id.trim())return e.push('Sub-nav updateItem requires string "id"'),{valid:!1,errors:e};let i=0;return r.title!==void 0&&i++,r.value!==void 0&&i++,r.url!==void 0&&i++,r.disabled!==void 0&&i++,r.active!==void 0&&i++,i===0?(e.push("Sub-nav updateItem must include at least one of title, value, url, disabled, active"),{valid:!1,errors:e}):(["title","value","url"].forEach(n=>{r[n]!==void 0&&(typeof r[n]!="string"||!r[n].trim())&&e.push(`Sub-nav updateItem "${n}" must be non-empty`)}),r.disabled!==void 0&&typeof r.disabled!="boolean"&&e.push('Sub-nav updateItem "disabled" must be boolean'),r.active!==void 0&&typeof r.active!="boolean"&&e.push('Sub-nav updateItem "active" must be boolean'),{valid:e.length===0,errors:e})}function ve(t){const e=[];return(typeof t!="string"||!t.trim())&&e.push("Nav removeItem id must be non-empty string"),{valid:e.length===0,errors:e}}const j=["danger","warning","info"];function ye(t){const e=[];return t.title===void 0||t.title===null?e.push("Confirm dialog title is required"):typeof t.title!="string"?e.push("Confirm dialog title must be a string"):t.title.trim()===""&&e.push("Confirm dialog title cannot be empty"),t.message===void 0||t.message===null?e.push("Confirm dialog message is required"):typeof t.message!="string"?e.push("Confirm dialog message must be a string"):t.message.trim()===""&&e.push("Confirm dialog message cannot be empty"),t.confirmText!==void 0&&t.confirmText!==null&&typeof t.confirmText!="string"&&e.push("Confirm dialog confirmText must be a string"),t.cancelText!==void 0&&t.cancelText!==null&&typeof t.cancelText!="string"&&e.push("Confirm dialog cancelText must be a string"),t.variant!==void 0&&t.variant!==null&&(typeof t.variant!="string"||!j.includes(t.variant))&&e.push(`Invalid confirm variant "${t.variant}". Expected: ${j.join(" | ")}`),{valid:e.length===0,errors:e}}function f(t,e){a.error(`Validation failed for ${t}:
|
|
1
|
+
System.register("SallaEmbeddedSDK",[],(function(S,We){"use strict";return{execute:(function(){S({getEmbeddedApp:x,resetEmbeddedApp:Xe});const u="embedded::",L={INIT:`${u}iframe.ready`,READY:`${u}ready`,DESTROY:`${u}destroy`},H={PROVIDE:`${u}context.provide`,THEME_CHANGE:`${u}theme.change`},g={LOADING:`${u}ui.loading`,BREADCRUMBS:`${u}ui.breadcrumbs`,TOAST:`${u}ui.toast`,CONFIRM:`${u}ui.confirm`,CONFIRM_RESPONSE:`${u}ui.confirm.response`},ae={},K={REFRESH:`${u}auth.refresh`},T={NAVIGATE:`${u}page.navigate`,REDIRECT:`${u}page.redirect`,SET_TITLE:`${u}page.setTitle`},h={SET_ACTION:`${u}nav.setAction`,CLEAR_ACTION:`${u}nav.clearAction`,ACTION_CLICK:`${u}nav.actionClick`,ADD_ITEM:`${u}nav.addItem`,ADD_ITEM_RESPONSE:`${u}nav.addItem.response`,UPDATE_ITEM:`${u}nav.updateItem`,REMOVE_ITEM:`${u}nav.removeItem`,ITEM_CLICK:`${u}nav.itemClick`},v={CREATE:`${u}checkout.create`,RESPONSE:`${u}checkout.response`,GET_ADDONS:`${u}checkout.getAddons`,GET_ADDONS_RESPONSE:`${u}checkout.getAddons.response`,RESET_CACHE:`${u}checkout.resetCache`},N=ae.version||"",oe=1e4,ue=["localhost","merchants.workers.dev","s.salla.sa",".salla.group",".salla.sa"],de=new Set(["ar","he","fa","ur","ps","sd","yi"]);function ce(t){const e=(t??"ar").toLowerCase().split(/[-_]/)[0];return de.has(e)?"rtl":"ltr"}let C={showVersion:!0,debug:!1};function le(t){C={...C,...t}}function F(t){return`%c${t}`}function G(t,e="#fff"){return`background-color: ${t}; color: ${e}; padding: 2px 6px; border-radius: 3px; font-weight: 500; font-size: 11px;`}function A(t,...e){if(t==="debug"&&!C.debug)return;const r=[],i=[];r.push(F("EmbeddedSDK")),i.push(G("#10b981","#fff")),C.showVersion&&(r.push(F(`v${N}`)),i.push(G("#6b7280","#fff")));const n=r.join("").trim();(console[t]||console.log)(n,...i,...e)}const o={log:(...t)=>{A("log",...t)},warn:(...t)=>{A("warn",...t)},error:(...t)=>{A("error",...t)},info:(...t)=>{A("info",...t)},debug:(...t)=>{A("debug",...t)}};function fe(t){try{const r=new URL(t).hostname;return ue.some(i=>i.startsWith(".")?r.endsWith(i)||r===i.slice(1):r===i||r.startsWith(`${i}:`))}catch{return!1}}function he(){return typeof window>"u"||window.parent===window?null:window.parent}function c(t,e,r="*",i,n){const s=he();if(!s){o.warn("Not running in an iframe, cannot post to host");return}const a={event:t,payload:e||{},timestamp:Date.now(),source:"embedded-app",...i&&{requestId:i},metadata:{version:N}};s.postMessage(a,r)}const b=new Map;let $=!1;function B(t){if(process.env.NODE_ENV==="production"&&!fe(t.origin))return;const e=t.data;if(!e||typeof e.event!="string"||!e.payload||typeof e.timestamp!="number"||!e.source){o.warn("Invalid message structure received:",e);return}const r=b.get(e.event);r&&r.forEach(n=>{try{n(e)}catch(s){o.error("Error in message handler:",s)}});const i=b.get("*");i&&i.forEach(n=>{try{n(e)}catch(s){o.error("Error in wildcard handler:",s)}})}function me(){$||typeof window>"u"||(window.addEventListener("message",B),$=!0)}function y(t,e){me(),b.has(t)||b.set(t,new Set);const r=b.get(t);return r.add(e),()=>{r.delete(e),r.size===0&&b.delete(t)}}function pe(t,e=oe){return new Promise((r,i)=>{const n=setTimeout(()=>{s(),i(new Error(`[EmbeddedSDK] Timeout waiting for "${t}" message`))},e),s=y(t,a=>{clearTimeout(n),s(),r(a)})})}function ge(){b.clear(),$&&typeof window<"u"&&(window.removeEventListener("message",B),$=!1)}function ve(){return typeof window>"u"?!1:window.parent!==window}function be(t,e,r){const i={event:t,payload:e,timestamp:Date.now(),source:"merchant-dashboard",...r,metadata:{version:N,synthetic:!0}};b.get(t)?.forEach(s=>{try{s(i)}catch(a){o.error("Error in message handler:",a)}})}const E=new Map,ye=3e4;function X(){const t=Date.now(),e=Math.random().toString(36).slice(2,9);return`req_${t}_${e}`}function k(t,e={},r=ye){const i=X();return new Promise((n,s)=>{const a=setTimeout(()=>{E.get(i)&&(E.delete(i),s(new Error(`[EmbeddedSDK] Request "${t}" timed out after ${r}ms`)))},r);E.set(i,{resolve:n,reject:s,timeout:a,event:t}),c(t,e,"*",i)})}function D(t,e,r){const i=E.get(t);if(!i){o.warn(`Received response for unknown request: ${t}`);return}clearTimeout(i.timeout),E.delete(t),r?i.reject(new Error(r)):i.resolve(e)}function Ee(t="SDK cleanup"){E.forEach((e,r)=>{clearTimeout(e.timeout),e.reject(new Error(`[EmbeddedSDK] Request ${r} cancelled: ${t}`))}),E.clear()}function w(){const t=new Set;return{subscribe(e){return t.add(e),()=>{t.delete(e)}},notify(...e){t.forEach(r=>{try{r(...e)}catch(i){o.error("Error in subscription callback:",i)}})},clear(){t.clear()},size(){return t.size}}}const Te="https://api.salla.dev";class R extends Error{constructor(e,r,i){super(e),this.status=r,this.response=i,this.name="ApiError"}}async function Ie(t,e={}){const{method:r="GET",headers:i={},body:n,timeout:s=3e4}=e,a=`${Te}${t}`,l=new AbortController,f=setTimeout(()=>{l.abort()},s);try{const d=await fetch(a,{method:r,headers:{"Content-Type":"application/json",...i},body:n?JSON.stringify(n):void 0,signal:l.signal});clearTimeout(f);let p;if(d.headers.get("content-type")?.includes("application/json")?p=await d.json():p=await d.text(),!d.ok)throw new R(`API request failed: ${d.statusText}`,d.status,p);return p}catch(d){throw clearTimeout(f),d instanceof R?d:d instanceof Error?d.name==="AbortError"?new R(`Request timeout after ${s}ms`):new R(`Request failed: ${d.message}`):new R("Unknown error occurred")}}function q(t){return{isVerified:!1,isError:!0,error:t,data:null}}async function Se(t){const{token:e,appId:r,refreshOnError:i=!0}=t;if(!e){const n="Token is required. Provide it as a parameter or in URL as ?token=XXX";return o.error("Error in introspect:",n),q(n)}if(!r){const n="App ID is required. Provide it as a parameter or in URL as ?app_id=XXX";return o.error("Error in introspect:",n),q(n)}try{const n=await Ie("/exchange-authority/v1/introspect",{method:"POST",headers:{"S-Source":r,"Content-Type":"application/json"},body:{env:"prod",token:e,iss:"merchant-dashboard",subject:"embedded-page"}}),s=n.success;return{isVerified:s,isError:!s,error:s?void 0:"API request failed",data:s?n.data:null}}catch(n){i&&(x().ui.toast.error(n?.toString()??"Introspect error"),c(K.REFRESH,{})),o.error("Error in introspect:",n);const s=n instanceof Error?n.message:n;return q(s)}}function Ae(t){return{getToken(){return new URLSearchParams(window.location.search).get("token")},getAppId(){return new URLSearchParams(window.location.search).get("app_id")},refresh(){c(K.REFRESH,{})},async introspect(e={}){const r=e.token??this.getToken()??"",i=e.appId??this.getAppId()??"";return Se({token:r,appId:i,refreshOnError:e.refreshOnError})}}}const W=["success","error","warning","info"];function we(t){const e=[];return t.type===void 0||t.type===null?e.push("Toast type is required"):(typeof t.type!="string"||!W.includes(t.type))&&e.push(`Invalid toast type "${t.type}". Expected: ${W.join(" | ")}`),t.message===void 0||t.message===null?e.push("Toast message is required"):typeof t.message!="string"?e.push("Toast message must be a string"):t.message.trim()===""&&e.push("Toast message cannot be empty"),t.duration!==void 0&&t.duration!==null&&(typeof t.duration!="number"?e.push("Toast duration must be a number"):t.duration<0&&e.push("Toast duration cannot be negative")),{valid:e.length===0,errors:e}}function Y(t,e){const r=[];return typeof t!="object"||t===null?(r.push(`${e} must be an object`),r):((typeof t.type!="string"||t.type.trim()==="")&&r.push(`${e} must have a valid type`),(typeof t.slug!="string"||t.slug.trim()==="")&&r.push(`${e} must have a valid slug`),t.quantity!==void 0&&(typeof t.quantity!="number"||t.quantity<1)&&r.push(`${e} must have a quantity >= 1`),r)}const Re=/^[A-Za-z0-9_-]+$/,Q=64,U="checkout_id cannot be combined with item or items";function _e(t){return typeof t!="string"||t===""?["checkout_id must be a non-empty string"]:t.length>Q?[`checkout_id must be at most ${Q} characters`]:Re.test(t)?[]:["checkout_id may only contain letters, numbers, '_' and '-'"]}function J(t){const e=[];if(typeof t!="object"||t===null)return e.push("Checkout options must be an object"),{valid:!1,errors:e};const r="item"in t,i="items"in t;if("checkout_id"in t)return r||i?(e.push(U),{valid:!1,errors:e}):(e.push(..._e(t.checkout_id)),{valid:e.length===0,errors:e});if(!r&&!i)return e.push("Checkout requires either 'item' or 'items'"),{valid:!1,errors:e};if(r){const n=Y(t.item,"Item");return e.push(...n),{valid:e.length===0,errors:e}}return Array.isArray(t.items)?t.items.length===0?(e.push("At least one item is required"),{valid:!1,errors:e}):(t.items.forEach((n,s)=>{const a=Y(n,`Item at index ${s}`);e.push(...a)}),{valid:e.length===0,errors:e}):(e.push("Checkout items must be an array"),{valid:!1,errors:e})}function Ne(t){const e=[];return t.path===void 0||t.path===null?e.push("Navigation path is required"):typeof t.path!="string"?e.push("Navigation path must be a string"):t.path.trim()===""&&e.push("Navigation path cannot be empty"),t.replace!==void 0&&typeof t.replace!="boolean"&&e.push("Navigation replace option must be a boolean"),{valid:e.length===0,errors:e}}function Ce(t){const e=[];if(t.url===void 0||t.url===null)e.push("Redirect URL is required");else if(typeof t.url!="string")e.push("Redirect URL must be a string");else if(t.url.trim()==="")e.push("Redirect URL cannot be empty");else try{new URL(t.url)}catch{e.push(`Invalid redirect URL: "${t.url}"`)}return{valid:e.length===0,errors:e}}function $e(t){const e=[];return t.title?typeof t.title!="string"&&e.push("Nav action title must be a string"):e.push("Nav action title is required"),t.value?typeof t.value!="string"&&e.push("Nav action value must be a string"):e.push("Nav action value is required"),t.subTitle!==void 0&&t.subTitle!==null&&typeof t.subTitle!="string"&&e.push("Nav action subTitle must be a string"),t.icon!==void 0&&t.icon!==null&&typeof t.icon!="string"&&e.push("Nav action icon must be a string"),t.disabled!==void 0&&t.disabled!==null&&typeof t.disabled!="boolean"&&e.push("Nav action disabled must be a boolean"),t.extendedActions!==void 0&&t.extendedActions!==null&&(Array.isArray(t.extendedActions)?t.extendedActions.forEach((r,i)=>{if(typeof r!="object"||r===null){e.push(`Extended action at index ${i} must be an object`);return}const n=r;(!n.title||typeof n.title!="string")&&e.push(`Extended action at index ${i} is missing required "title" property`),(!n.value||typeof n.value!="string")&&e.push(`Extended action at index ${i} is missing required "value" property`),n.subTitle!==void 0&&typeof n.subTitle!="string"&&e.push(`Extended action at index ${i} subTitle must be a string`),n.icon!==void 0&&typeof n.icon!="string"&&e.push(`Extended action at index ${i} icon must be a string`),n.disabled!==void 0&&typeof n.disabled!="boolean"&&e.push(`Extended action at index ${i} disabled must be a boolean`)}):e.push("Nav action extendedActions must be an array")),{valid:e.length===0,errors:e}}const M=50;function O(t,e){return t?`${t}.${e}`:e}function De(t,e){const r=[];["title","value","url"].forEach(s=>{(typeof t[s]!="string"||!String(t[s]).trim())&&r.push(`Sub-nav addItem "${O(e,s)}" must be non-empty string`)});const i=O(e,"disabled"),n=O(e,"active");return t.disabled!==void 0&&typeof t.disabled!="boolean"&&r.push(`Sub-nav addItem "${i}" must be boolean`),t.active!==void 0&&typeof t.active!="boolean"&&r.push(`Sub-nav addItem "${n}" must be boolean`),r}function V(t,e,r){if(typeof t!="object"||t===null)return[`Sub-nav addItem "${e||"item"}" must be an object`];const i=t,n=De(i,e),s=O(e,"children");return i.children===void 0?n:r?Array.isArray(i.children)?i.children.length>M?(n.push(`Sub-nav addItem "${s}" must have at most ${M} items`),n):(i.children.forEach((a,l)=>{const f=e?`${e}.children[${l}]`:`children[${l}]`;n.push(...V(a,f,!1))}),n):(n.push(`Sub-nav addItem "${s}" must be an array`),n):(Array.isArray(i.children)&&i.children.length===0||n.push(`Sub-nav addItem "${s}" is not supported on submenu rows (only one dropdown level)`),n)}function Z(t,e,r,i){if(typeof t!="object"||t===null)return i;const n=t;return typeof n.value=="string"&&n.value.trim()&&i.push(n.value.trim()),!r||!Array.isArray(n.children)||n.children.forEach((s,a)=>{const l=e?`${e}.children[${a}]`:`children[${a}]`;Z(s,l,!1,i)}),i}function Me(t){const e=Z(t,"",!0,[]),r=new Set,i=[];for(const n of e)r.has(n)&&i.push(n),r.add(n);return i.length===0?[]:[`Sub-nav addItem "value" must be globally unique within the item tree (duplicate: ${[...new Set(i)].join(", ")})`]}function Oe(t){if(typeof t!="object"||t===null)return{valid:!1,errors:["Nav addItem expects an object item"]};const e=[...V(t,"",!0),...Me(t)];return{valid:e.length===0,errors:e}}function Le(t){const e=[];if(typeof t!="object"||t===null)return e.push("Nav updateItem expects an object item"),{valid:!1,errors:e};const r=t,i=typeof r.value=="string"&&String(r.value).trim().length>0,n=typeof r.id=="string"&&String(r.id).trim().length>0,s=i?String(r.value).trim():"",a=n?String(r.id).trim():"";if(!i&&!n)return e.push('Sub-nav updateItem requires non-empty string "value"'),{valid:!1,errors:e};if(i&&n&&s!==a)return e.push('Sub-nav updateItem must not specify different "id" and "value"; "value" is the immutable row key and cannot be renamed via patch'),{valid:!1,errors:e};const l=s||a;let f=0;if(r.title!==void 0&&f++,r.url!==void 0&&f++,r.disabled!==void 0&&f++,r.active!==void 0&&f++,r.children!==void 0&&f++,f===0)return e.push("Sub-nav updateItem must include at least one of title, url, disabled, active, children"),{valid:!1,errors:e};if(["title","url"].forEach(d=>{r[d]!==void 0&&(typeof r[d]!="string"||!r[d].trim())&&e.push(`Sub-nav updateItem "${d}" must be non-empty`)}),r.disabled!==void 0&&typeof r.disabled!="boolean"&&e.push('Sub-nav updateItem "disabled" must be boolean'),r.active!==void 0&&typeof r.active!="boolean"&&e.push('Sub-nav updateItem "active" must be boolean'),r.children!==void 0)if(!Array.isArray(r.children))e.push('Sub-nav updateItem "children" must be an array');else if(r.children.length>M)e.push(`Sub-nav updateItem "children" must have at most ${M} items`);else{const d=new Set;r.children.forEach((p,se)=>{const z=`children[${se}]`;if(e.push(...V(p,z,!1)),typeof p=="object"&&p!==null){const P=p.value;if(typeof P=="string"&&P.trim()){const j=P.trim();j===l&&e.push(`Sub-nav updateItem "${z}.value" must not equal the parent row identifier`),d.has(j)&&e.push(`Sub-nav updateItem "${z}.value" must be unique within children`),d.add(j)}}})}return{valid:e.length===0,errors:e}}function ke(t){const e=[];return(typeof t!="string"||!t.trim())&&e.push("Nav removeItem value must be non-empty string"),{valid:e.length===0,errors:e}}const ee=["danger","warning","info"];function qe(t){const e=[];return t.title===void 0||t.title===null?e.push("Confirm dialog title is required"):typeof t.title!="string"?e.push("Confirm dialog title must be a string"):t.title.trim()===""&&e.push("Confirm dialog title cannot be empty"),t.message===void 0||t.message===null?e.push("Confirm dialog message is required"):typeof t.message!="string"?e.push("Confirm dialog message must be a string"):t.message.trim()===""&&e.push("Confirm dialog message cannot be empty"),t.confirmText!==void 0&&t.confirmText!==null&&typeof t.confirmText!="string"&&e.push("Confirm dialog confirmText must be a string"),t.cancelText!==void 0&&t.cancelText!==null&&typeof t.cancelText!="string"&&e.push("Confirm dialog cancelText must be a string"),t.variant!==void 0&&t.variant!==null&&(typeof t.variant!="string"||!ee.includes(t.variant))&&e.push(`Invalid confirm variant "${t.variant}". Expected: ${ee.join(" | ")}`),{valid:e.length===0,errors:e}}function m(t,e){o.error(`Validation failed for ${t}:
|
|
2
2
|
`+e.map(r=>` • ${r}`).join(`
|
|
3
|
-
`))}function
|
|
3
|
+
`))}function Ue(){return{resize:i=>{},autoResize:()=>{},stopAutoResize:()=>{}}}function Ve(){const{resize:t,autoResize:e,stopAutoResize:r}=Ue();return{navigate(i,n){const s=Ne({path:i,...n});if(!s.valid){m(T.NAVIGATE,s.errors);return}c(T.NAVIGATE,{path:i,state:n?.state,replace:n?.replace})},redirect(i){const n=Ce({url:i});if(!n.valid){m(T.REDIRECT,n.errors);return}c(T.REDIRECT,{url:i})},navTo(i,n){if(i.startsWith("http://")||i.startsWith("https://")){this.redirect(i);return}this.navigate(i,n)},setTitle(i){if(typeof i!="string"||!i.trim()){m(T.SET_TITLE,["Title must be a non-empty string"]);return}c(T.SET_TITLE,{title:i})},resize:t,autoResize:e,stopAutoResize:r}}function xe(){const t=w(),e=w(),r=[];return r.push(y(h.ACTION_CLICK,i=>{t.notify(i.payload.value)})),r.push(y(h.ADD_ITEM_RESPONSE,i=>{if(!i.requestId)return;const n=i.payload;if(typeof n.error=="string"&&n.error.trim()){const a=n.error.trim();o.warn(`embedded::nav.addItem failed: ${a}`),D(i.requestId,{},a);return}const s=n.item;if(s&&typeof s.value=="string"&&s.value.trim()){const a=s.value.trim(),l={value:a,id:a};D(i.requestId,l)}})),r.push(y(h.ITEM_CLICK,i=>{const n=i.payload,s=typeof n.value=="string"&&n.value.trim()?n.value.trim():typeof n.id=="string"&&n.id.trim()?n.id.trim():"";if(!s){e.notify(n);return}e.notify({...n,value:s,id:s})})),{setAction(i){const n=$e(i);if(!n.valid){m(h.SET_ACTION,n.errors);return}c(h.SET_ACTION,{title:i.title,value:i.value,subTitle:i.subTitle,icon:i.icon,disabled:i.disabled,extendedActions:i.extendedActions?.map(s=>({title:s.title,value:s.value,subTitle:s.subTitle,icon:s.icon,disabled:s.disabled}))})},clearAction(){c(h.CLEAR_ACTION,{})},onActionClick(i){return t.subscribe(i)},addNavItem(i){const n=Oe(i);return n.valid?k(h.ADD_ITEM,{item:i},2e3):(m(h.ADD_ITEM,n.errors),Promise.reject(new Error(n.errors[0])))},updateNavItem(i){const n=Le(i);if(!n.valid){m(h.UPDATE_ITEM,n.errors);return}const s=i,a=typeof s.value=="string"?s.value.trim():"",l=typeof s.id=="string"?s.id.trim():"",f=a||l,{id:d,...p}=s;c(h.UPDATE_ITEM,{item:{...p,value:f}})},removeNavItem(i){const n=ke(i);if(!n.valid){m(h.REMOVE_ITEM,n.errors);return}c(h.REMOVE_ITEM,{value:i})},onNavItemClick(i){return e.subscribe(i)},destroy(){r.forEach(i=>i()),r.length=0,t.clear(),e.clear()}}}function ze(){return{show(){c(g.LOADING,{action:"show"})},hide(){c(g.LOADING,{action:"hide"})}}}function Pe(){return{hide(){c(g.BREADCRUMBS,{action:"hide"})},show(){c(g.BREADCRUMBS,{action:"show"})}}}function je(){const t=e=>{const r=we(e);if(!r.valid){m(g.TOAST,r.errors);return}c(g.TOAST,{type:e.type,message:e.message,duration:e.duration})};return{show:t,success(e,r){t({type:"success",message:e,duration:r})},error(e,r){t({type:"error",message:e,duration:r})},warning(e,r){t({type:"warning",message:e,duration:r})},info(e,r){t({type:"info",message:e,duration:r})}}}function He(){return async t=>{const e=qe(t);return e.valid?k(g.CONFIRM,{title:t.title,message:t.message,confirmText:t.confirmText??"Confirm",cancelText:t.cancelText??"Cancel",variant:t.variant??"info"}):(m(g.CONFIRM,e.errors),Promise.reject(new Error(e.errors.join(", "))))}}function Ke(){return{loading:ze(),breadcrumbs:Pe(),toast:je(),confirm:He()}}const Fe=S("INVALID_CHECKOUT_INPUT","INVALID_CHECKOUT_INPUT");function _(t){const e=new Error(t);return e.code=Fe,e}const Ge=["type","slug","quantity"];function te(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)&&"checkout_id"in t&&t.checkout_id!==void 0}function Be(){const t=w(),e=[];return e.push(y(v.RESPONSE,r=>{t.notify({success:r.payload.success,order_id:r.payload.order_id,checkout_id:r.payload.checkout_id,status:r.payload.status,error:r.payload.error,context:r.payload.context})})),e.push(y(v.GET_ADDONS_RESPONSE,r=>{r.requestId&&D(r.requestId,{success:r.payload.success,addons:r.payload.addons,error:r.payload.error})})),{create(r,i){if(Array.isArray(r)&&r.some(s=>te(s)))throw _(U);let n;if(te(r)){if("context"in r)throw _("context must be passed as the second argument (config.context)");if(Ge.some(a=>a in r))throw _(U);const s=J(r);if(!s.valid)throw m(v.CREATE,s.errors),_(s.errors[0]);n={checkout_id:r.checkout_id}}else{const s=Array.isArray(r)?r:[r],a=J({items:s});if(!a.valid)throw m(v.CREATE,a.errors),_(a.errors[0]);n={items:s.map(l=>({type:l.type,slug:l.slug,quantity:l.quantity??1}))}}c(v.CREATE,{...n,...i?.context!==void 0&&{context:i.context}},"*",X())},onResult(r){return t.subscribe(r)},async getAddons(){try{return await k(v.GET_ADDONS,{},3e4)}catch(r){return{success:!1,error:{code:"REQUEST_FAILED",message:r instanceof Error?r.message:"Unknown error"}}}},resetCache(){c(v.RESET_CACHE,{},"*")},destroy(){e.forEach(r=>r()),e.length=0,t.clear()}}}const re={theme:"light",dir:"rtl",width:0,locale:"ar",currency:"SAR"};class ie{constructor(){this.initialized=!1,this.initializing=!1,this.debugMode=!1,this.appReady=!1,this.layout={...re},this.postInitHooks=[],this.themeSubscription=w(),this.initSubscription=w(),this.auth=Ae(),this.page=Ve(),this.nav=xe(),this.ui=Ke(),this.checkout=Be(),this.registerPostInitHook(e=>{const r=e.payload.pendingCheckoutResult;r&&(o.debug("Dispatching pending checkout result:",r),queueMicrotask(()=>{be(v.RESPONSE,{success:r.success,status:r.status,checkout_id:r.checkout_id,error:r.error,context:r.context})}))}),this.setupListeners()}registerPostInitHook(e){this.postInitHooks.push(e)}setupListeners(){y(H.THEME_CHANGE,e=>{this.layout.theme=e.payload.theme,o.debug("Theme changed:",e.payload.theme),this.themeSubscription.notify(e.payload.theme)}),y(g.CONFIRM_RESPONSE,e=>{o.debug("Received confirm response:",e),e.requestId&&D(e.requestId,{confirmed:e.payload.confirmed})})}getState(){return{ready:this.initialized,initializing:this.initializing,layout:{...this.layout}}}isReady(){return this.initialized}onThemeChange(e){return this.themeSubscription.subscribe(e)}onInit(e){if(this.initialized)try{e(this.getState())}catch(r){o.error("Error in init callback:",r)}return this.initSubscription.subscribe(e)}ready(){if(this.appReady){o.debug("App already signaled as ready");return}if(!this.initialized){o.warn("Cannot signal ready before init() is called");return}this.appReady=!0,c(L.READY,{}),o.debug("Sent ready signal to host")}async init(e={}){if(this.initialized)return o.debug("Already initialized, returning current layout"),{layout:{...this.layout}};if(this.initializing)return o.warn("Initialization already in progress"),new Promise(r=>{const i=this.onInit(n=>{i(),r({layout:{...n.layout}})})});this.initializing=!0,this.debugMode=e.debug??!1,le({debug:this.debugMode}),ve()||o.warn("Not running in an iframe. Some features may not work."),o.debug("Initializing SDK...");try{c(L.INIT,{height:document.documentElement.scrollHeight}),o.debug("Sent iframe.ready message, waiting for context...");const r=await pe(H.PROVIDE);o.debug("Received context from host:",r);const{layout:i}=r.payload;return this.layout={theme:i?.theme??"light",dir:i?.dir??ce(i?.locale),width:i?.width??0,locale:i?.locale??"ar",currency:i?.currency??"SAR"},this.postInitHooks.forEach(n=>{try{n(r)}catch(s){o.error("Error in post-init hook:",s)}}),this.initialized=!0,this.initializing=!1,o.debug("Initialization complete. Layout:",this.layout),this.initSubscription.notify(this.getState()),{layout:{...this.layout}}}catch(r){throw this.initializing=!1,r}}destroy(){o.debug("Destroying SDK instance"),this.initialized&&(c(L.DESTROY,{}),o.debug("Sent destroy event to host")),this.checkout.destroy(),this.nav.destroy(),Ee("SDK destroyed"),ge(),this.themeSubscription.clear(),this.initSubscription.clear(),this.postInitHooks=[],this.initialized=!1,this.initializing=!1,this.appReady=!1,this.layout={...re}}}S("EmbeddedApp",ie);let I=null;function x(){return I||(I=new ie),I}function Xe(){I&&(I.destroy(),I=null)}const ne=S("embedded",x()),Ye=S("version",N);typeof window<"u"&&(window.salla=window.salla||window.Salla||{},window.Salla=window.salla,window.salla.embedded||(window.salla.embedded=ne),window.Salla.embedded||(window.Salla.embedded=ne))})}}));
|
|
4
4
|
//# sourceMappingURL=index.js.map
|