jails.stdlib 1.0.0

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 (101) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +22 -0
  3. package/build.js +34 -0
  4. package/cancelable/README.md +41 -0
  5. package/cancelable/index.d.ts +1 -0
  6. package/cancelable/index.js +16 -0
  7. package/cancelable/index.ts +18 -0
  8. package/cancelable/index.umd.js +1 -0
  9. package/debounce/README.md +21 -0
  10. package/debounce/index.d.ts +1 -0
  11. package/debounce/index.js +11 -0
  12. package/debounce/index.ts +8 -0
  13. package/debounce/index.umd.js +1 -0
  14. package/delay/README.md +17 -0
  15. package/delay/index.d.ts +1 -0
  16. package/delay/index.js +6 -0
  17. package/delay/index.ts +6 -0
  18. package/delay/index.umd.js +1 -0
  19. package/form-validation/index.d.ts +18 -0
  20. package/form-validation/index.js +119 -0
  21. package/form-validation/index.ts +198 -0
  22. package/form-validation/index.umd.js +1 -0
  23. package/form-validation/readme.md +117 -0
  24. package/import-css/README.md +22 -0
  25. package/import-css/index.d.ts +1 -0
  26. package/import-css/index.js +7 -0
  27. package/import-css/index.ts +11 -0
  28. package/import-css/index.umd.js +1 -0
  29. package/import-html/README.md +18 -0
  30. package/import-html/index.d.ts +4 -0
  31. package/import-html/index.js +4 -0
  32. package/import-html/index.ts +4 -0
  33. package/import-html/index.umd.js +1 -0
  34. package/import-js/README.md +22 -0
  35. package/import-js/index.d.ts +5 -0
  36. package/import-js/index.js +7 -0
  37. package/import-js/index.ts +15 -0
  38. package/import-js/index.umd.js +1 -0
  39. package/is-touch/README.md +18 -0
  40. package/is-touch/index.d.ts +1 -0
  41. package/is-touch/index.js +4 -0
  42. package/is-touch/index.ts +4 -0
  43. package/is-touch/index.umd.js +1 -0
  44. package/is-visible/README.md +24 -0
  45. package/is-visible/index.d.ts +7 -0
  46. package/is-visible/index.js +11 -0
  47. package/is-visible/index.ts +20 -0
  48. package/is-visible/index.umd.js +1 -0
  49. package/lazyload-image/README.md +28 -0
  50. package/lazyload-image/index.d.ts +1 -0
  51. package/lazyload-image/index.js +235 -0
  52. package/lazyload-image/index.ts +3 -0
  53. package/lazyload-image/index.umd.js +1 -0
  54. package/messenger/README.md +109 -0
  55. package/messenger/index.d.ts +9 -0
  56. package/messenger/index.js +39 -0
  57. package/messenger/index.ts +38 -0
  58. package/messenger/index.umd.js +1 -0
  59. package/mfe/README.md +90 -0
  60. package/mfe/index.d.ts +11 -0
  61. package/mfe/index.js +99 -0
  62. package/mfe/index.ts +141 -0
  63. package/mfe/index.umd.js +1 -0
  64. package/outlet/README.md +46 -0
  65. package/outlet/index.d.ts +6 -0
  66. package/outlet/index.js +550 -0
  67. package/outlet/index.ts +101 -0
  68. package/outlet/index.umd.js +1 -0
  69. package/package.json +25 -0
  70. package/querystring/README.md +19 -0
  71. package/querystring/index.d.ts +1 -0
  72. package/querystring/index.js +9 -0
  73. package/querystring/index.ts +9 -0
  74. package/querystring/index.umd.js +1 -0
  75. package/router/README.md +23 -0
  76. package/router/index.d.ts +1 -0
  77. package/router/index.js +134 -0
  78. package/router/index.ts +3 -0
  79. package/router/index.umd.js +1 -0
  80. package/storage/README.md +34 -0
  81. package/storage/index.d.ts +12 -0
  82. package/storage/index.js +39 -0
  83. package/storage/index.ts +45 -0
  84. package/storage/index.umd.js +1 -0
  85. package/store/README.md +44 -0
  86. package/store/index.d.ts +1 -0
  87. package/store/index.js +50 -0
  88. package/store/index.ts +1 -0
  89. package/store/index.umd.js +1 -0
  90. package/third-party/README.md +44 -0
  91. package/third-party/index.d.ts +8 -0
  92. package/third-party/index.js +15 -0
  93. package/third-party/index.ts +30 -0
  94. package/third-party/index.umd.js +1 -0
  95. package/throttle/README.md +21 -0
  96. package/throttle/index.d.ts +1 -0
  97. package/throttle/index.js +9 -0
  98. package/throttle/index.ts +10 -0
  99. package/throttle/index.umd.js +1 -0
  100. package/tsconfig.json +14 -0
  101. package/vite-env.d.ts +1 -0
@@ -0,0 +1 @@
1
+ (function(b,i){typeof exports=="object"&&typeof module!="undefined"?i(exports):typeof define=="function"&&define.amd?define(["exports"],i):(b=typeof globalThis!="undefined"?globalThis:b||self,i(b["lazyload-image"]={}))})(this,(function(b){"use strict";const i=typeof window!="undefined",S=i&&!("onscroll"in window)||typeof navigator!="undefined"&&/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),H=i&&window.devicePixelRatio>1,fe={elements_selector:".lazy",container:S||i?document:null,threshold:300,thresholds:null,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",data_bg:"bg",data_bg_hidpi:"bg-hidpi",data_bg_multi:"bg-multi",data_bg_multi_hidpi:"bg-multi-hidpi",data_bg_set:"bg-set",data_poster:"poster",class_applied:"applied",class_loading:"loading",class_loaded:"loaded",class_error:"error",class_entered:"entered",class_exited:"exited",unobserve_completed:!0,unobserve_entered:!1,cancel_on_exit:!0,callback_enter:null,callback_exit:null,callback_applied:null,callback_loading:null,callback_loaded:null,callback_error:null,callback_finish:null,callback_cancel:null,use_native:!1,restore_on_error:!1},V=e=>Object.assign({},fe,e),B=function(e,t){let n;const s="LazyLoad::Initialized",a=new e(t);try{n=new CustomEvent(s,{detail:{instance:a}})}catch(o){n=document.createEvent("CustomEvent"),n.initCustomEvent(s,!1,!1,{instance:a})}window.dispatchEvent(n)},he=(e,t)=>{if(t)if(t.length)for(let n,s=0;n=t[s];s+=1)B(e,n);else B(e,t)},r="src",x="srcset",O="sizes",F="poster",m="llOriginalAttrs",J="data",w="loading",P="loaded",U="applied",me="entered",C="error",q="native",K="data-",Q="ll-status",l=(e,t)=>e.getAttribute(K+t),pe=(e,t,n)=>{const s=K+t;n!==null?e.setAttribute(s,n):e.removeAttribute(s)},p=e=>l(e,Q),g=(e,t)=>pe(e,Q,t),I=e=>g(e,null),M=e=>p(e)===null,ve=e=>p(e)===w,Ee=e=>p(e)===C,z=e=>p(e)===q,Ie=[w,P,U,C],ye=e=>Ie.indexOf(p(e))>=0,d=(e,t,n,s)=>{e&&typeof e=="function"&&(s===void 0?n===void 0?e(t):e(t,n):e(t,n,s))},f=(e,t)=>{i&&t!==""&&e.classList.add(t)},c=(e,t)=>{i&&t!==""&&e.classList.remove(t)},ke=e=>{e.llTempImage=document.createElement("IMG")},Ae=e=>{delete e.llTempImage},W=e=>e.llTempImage,y=(e,t)=>{if(!t)return;const n=t._observer;n&&n.unobserve(e)},Le=e=>{e.disconnect()},xe=(e,t,n)=>{t.unobserve_entered&&y(e,n)},N=(e,t)=>{e&&(e.loadingCount+=t)},Oe=e=>{e&&(e.toLoadCount-=1)},X=(e,t)=>{e&&(e.toLoadCount=t)},we=e=>e.loadingCount>0,Ce=e=>e.toLoadCount>0,Y=e=>{let t=[];for(let n,s=0;n=e.children[s];s+=1)n.tagName==="SOURCE"&&t.push(n);return t},T=(e,t)=>{const n=e.parentNode;n&&n.tagName==="PICTURE"&&Y(n).forEach(t)},Z=(e,t)=>{Y(e).forEach(t)},k=[r],ee=[r,F],v=[r,x,O],te=[J],A=e=>!!e[m],ne=e=>e[m],se=e=>delete e[m],h=(e,t)=>{if(A(e))return;const n={};t.forEach((s=>{n[s]=e.getAttribute(s)})),e[m]=n},Me=e=>{A(e)||(e[m]={backgroundImage:e.style.backgroundImage})},$=(e,t)=>{if(!A(e))return;const n=ne(e);t.forEach((s=>{((a,o,u)=>{u?a.setAttribute(o,u):a.removeAttribute(o)})(e,s,n[s])}))},ze=e=>{if(!A(e))return;const t=ne(e);e.style.backgroundImage=t.backgroundImage},ae=(e,t,n)=>{f(e,t.class_applied),g(e,U),n&&(t.unobserve_completed&&y(e,t),d(t.callback_applied,e,n))},oe=(e,t,n)=>{f(e,t.class_loading),g(e,w),n&&(N(n,1),d(t.callback_loading,e,n))},_=(e,t,n)=>{n&&e.setAttribute(t,n)},le=(e,t)=>{_(e,O,l(e,t.data_sizes)),_(e,x,l(e,t.data_srcset)),_(e,r,l(e,t.data_src))},Ne=(e,t)=>{T(e,(n=>{h(n,v),le(n,t)})),h(e,v),le(e,t)},Te=(e,t)=>{h(e,k),_(e,r,l(e,t.data_src))},Re=(e,t)=>{Z(e,(n=>{h(n,k),_(n,r,l(n,t.data_src))})),h(e,ee),_(e,F,l(e,t.data_poster)),_(e,r,l(e,t.data_src)),e.load()},De=(e,t)=>{h(e,te),_(e,J,l(e,t.data_src))},je=(e,t,n)=>{const s=l(e,t.data_bg),a=l(e,t.data_bg_hidpi),o=H&&a?a:s;o&&(e.style.backgroundImage=`url("${o}")`,W(e).setAttribute(r,o),oe(e,t,n))},Ge=(e,t,n)=>{const s=l(e,t.data_bg_multi),a=l(e,t.data_bg_multi_hidpi),o=H&&a?a:s;o&&(e.style.backgroundImage=o,ae(e,t,n))},Se=(e,t,n)=>{const s=l(e,t.data_bg_set);if(!s)return;let a=s.split("|").map((o=>`image-set(${o})`));e.style.backgroundImage=a.join(),ae(e,t,n)},ie={IMG:Ne,IFRAME:Te,VIDEO:Re,OBJECT:De},He=(e,t)=>{const n=ie[e.tagName];n&&n(e,t)},Ve=(e,t,n)=>{const s=ie[e.tagName];s&&(s(e,t),oe(e,t,n))},Be=["IMG","IFRAME","VIDEO","OBJECT"],Fe=e=>Be.indexOf(e.tagName)>-1,ce=(e,t)=>{!t||we(t)||Ce(t)||d(e.callback_finish,t)},re=(e,t,n)=>{e.addEventListener(t,n),e.llEvLisnrs[t]=n},Je=(e,t,n)=>{e.removeEventListener(t,n)},R=e=>!!e.llEvLisnrs,Pe=(e,t,n)=>{R(e)||(e.llEvLisnrs={});const s=e.tagName==="VIDEO"?"loadeddata":"load";re(e,s,t),re(e,"error",n)},D=e=>{if(!R(e))return;const t=e.llEvLisnrs;for(let n in t){const s=t[n];Je(e,n,s)}delete e.llEvLisnrs},de=(e,t,n)=>{Ae(e),N(n,-1),Oe(n),c(e,t.class_loading),t.unobserve_completed&&y(e,n)},Ue=(e,t,n,s)=>{const a=z(t);de(t,n,s),f(t,n.class_loaded),g(t,P),d(n.callback_loaded,t,s),a||ce(n,s)},qe=(e,t,n,s)=>{const a=z(t);de(t,n,s),f(t,n.class_error),g(t,C),d(n.callback_error,t,s),n.restore_on_error&&$(t,v),a||ce(n,s)},j=(e,t,n)=>{const s=W(e)||e;R(s)||Pe(s,(a=>{Ue(0,e,t,n),D(s)}),(a=>{qe(0,e,t,n),D(s)}))},G=(e,t,n)=>{Fe(e)?((s,a,o)=>{j(s,a,o),Ve(s,a,o)})(e,t,n):((s,a,o)=>{ke(s),j(s,a,o),Me(s),je(s,a,o),Ge(s,a,o),Se(s,a,o)})(e,t,n)},Ke=(e,t,n)=>{e.setAttribute("loading","lazy"),j(e,t,n),He(e,t),g(e,q)},_e=e=>{e.removeAttribute(r),e.removeAttribute(x),e.removeAttribute(O)},Qe=e=>{T(e,(t=>{_e(t)})),_e(e)},ue=e=>{T(e,(t=>{$(t,v)})),$(e,v)},We=e=>{Z(e,(t=>{$(t,k)})),$(e,ee),e.load()},Xe=e=>{$(e,k)},Ye=e=>{$(e,te)},Ze={IMG:ue,IFRAME:Xe,VIDEO:We,OBJECT:Ye},et=(e,t)=>{(n=>{const s=Ze[n.tagName];s?s(n):ze(n)})(e),((n,s)=>{M(n)||z(n)||(c(n,s.class_entered),c(n,s.class_exited),c(n,s.class_applied),c(n,s.class_loading),c(n,s.class_loaded),c(n,s.class_error))})(e,t),I(e),se(e)},tt=(e,t,n,s)=>{n.cancel_on_exit&&ve(e)&&e.tagName==="IMG"&&(D(e),Qe(e),ue(e),c(e,n.class_loading),N(s,-1),I(e),d(n.callback_cancel,e,t,s))},nt=(e,t,n,s)=>{const a=ye(e);g(e,me),f(e,n.class_entered),c(e,n.class_exited),xe(e,n,s),d(n.callback_enter,e,t,s),a||G(e,n,s)},st=(e,t,n,s)=>{M(e)||(f(e,n.class_exited),tt(e,t,n,s),d(n.callback_exit,e,t,s))},at=["IMG","IFRAME","VIDEO"],ge=e=>e.use_native&&"loading"in HTMLImageElement.prototype,ot=(e,t,n)=>{e.forEach((s=>{at.indexOf(s.tagName)!==-1&&Ke(s,t,n)})),X(n,0)},lt=e=>e.isIntersecting||e.intersectionRatio>0,it=(e,t)=>{t.forEach((n=>{e.observe(n)}))},ct=(e,t)=>{Le(e),it(e,t)},rt=(e,t)=>{ge(e)||(t._observer=new IntersectionObserver((n=>{((s,a,o)=>{s.forEach((u=>lt(u)?nt(u.target,u,a,o):st(u.target,u,a,o)))})(n,e,t)}),(n=>({root:n.container===document?null:n.container,rootMargin:n.thresholds||n.threshold+"px"}))(e)))},$e=e=>Array.prototype.slice.call(e),L=e=>e.container.querySelectorAll(e.elements_selector),dt=e=>$e(e).filter(M),_t=e=>Ee(e),ut=e=>$e(e).filter(_t),be=(e,t)=>dt(e||L(t)),gt=(e,t)=>{ut(L(e)).forEach((n=>{c(n,e.class_error),I(n)})),t.update()},$t=(e,t)=>{i&&(t._onlineHandler=()=>{gt(e,t)},window.addEventListener("online",t._onlineHandler))},bt=e=>{i&&window.removeEventListener("online",e._onlineHandler)},E=function(e,t){const n=V(e);this._settings=n,this.loadingCount=0,rt(n,this),$t(n,this),this.update(t)};E.prototype={update:function(e){const t=this._settings,n=be(e,t);X(this,n.length),S?this.loadAll(n):ge(t)?ot(n,t,this):ct(this._observer,n)},destroy:function(){this._observer&&this._observer.disconnect(),bt(this),L(this._settings).forEach((e=>{se(e)})),delete this._observer,delete this._settings,delete this._onlineHandler,delete this.loadingCount,delete this.toLoadCount},loadAll:function(e){const t=this._settings;be(e,t).forEach((n=>{y(n,this),G(n,t,this)}))},restoreAll:function(){const e=this._settings;L(e).forEach((t=>{et(t,e)}))}},E.load=(e,t)=>{const n=V(t);G(e,n)},E.resetStatus=e=>{I(e)},i&&he(E,window.lazyLoadOptions);const ft=E;b.Lazyload=ft,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})}));
@@ -0,0 +1,109 @@
1
+ # messenger
2
+
3
+ ```ts
4
+ messenger({
5
+ target?: Window | HTMLIFrameElement,
6
+ accept?: string[],
7
+ actions?: Record<string, (payload: any) => void>,
8
+ origin?: string
9
+ })
10
+ ```
11
+ # 📬 Messenger API Documentation
12
+
13
+ The `messenger` utility provides a lightweight, secure interface for sending and receiving messages between windows or iframes using `postMessage`.
14
+
15
+ ---
16
+
17
+ ## ✅ Features
18
+
19
+ * Easy dispatch and subscription to custom message actions.
20
+ * Secure origin validation.
21
+ * Works with iframes or separate window contexts.
22
+ * Extensible via `subscribe`.
23
+
24
+ ---
25
+
26
+ ## 🧪 Usage
27
+
28
+ ### Parent Page
29
+
30
+ ```ts
31
+ import { messenger } from 'jails.std/messenger'
32
+
33
+ const msg = messenger({
34
+ target: document.getElementById('myIframe'), // <iframe id="myIframe" />
35
+ accept: ['https://child-app.com'], // Allowed origins
36
+ actions: {
37
+ reply(data) {
38
+ console.log('Received from iframe:', data)
39
+ }
40
+ }
41
+ })
42
+
43
+ // Send message to iframe
44
+ msg.dispatch('init', { user: 'Alice' })
45
+
46
+ // Add more listeners later
47
+ msg.subscribe({
48
+ status: (msg) => console.log('Status update:', msg)
49
+ })
50
+ ```
51
+
52
+ ### Iframe Page
53
+
54
+ ```ts
55
+ const msg = messenger({
56
+ target: window.parent,
57
+ accept: ['https://parent-app.com'],
58
+ actions: {
59
+ init(data){
60
+ console.log('Init from parent:', data)
61
+ msg.dispatch('reply', { received: true })
62
+ }
63
+ }
64
+ })
65
+ ```
66
+
67
+ ---
68
+
69
+ ## 🧹 API
70
+
71
+ ### `messenger(options)`
72
+
73
+ Creates a new Messenger instance.
74
+
75
+ #### Options:
76
+
77
+ | Option | Type | Description |
78
+ | --------- | ----------------------------- | --------------------------------------- |
79
+ | `target` | `Window \| HTMLIFrameElement` | Target to send messages to |
80
+ | `accept` | `string[]` | Allowed origins (`['*']` to accept all) |
81
+ | `actions` | `Record<string, Function>` | Message handlers keyed by action name |
82
+ | `origin` | `string` | The origin used when sending messages |
83
+
84
+ ---
85
+
86
+ ### `.dispatch(action: string, payload?: any)`
87
+
88
+ Sends a message to the target window.
89
+
90
+ ```ts
91
+ msg.dispatch('sayHello', { name: 'Bob' })
92
+ ```
93
+
94
+ ---
95
+
96
+ ### `.subscribe(newActions: Record<string, Function>)`
97
+
98
+ Adds more actions to the messenger at runtime.
99
+
100
+ ```ts
101
+ msg.subscribe({ logout: () => console.log('Logging out...') })
102
+ ```
103
+
104
+ ---
105
+
106
+ ## 🔒 Security Notes
107
+
108
+ * Always **specify allowed origins** in `accept` to avoid cross-site scripting risks.
109
+ * Avoid using `'*'` unless absolutely necessary (e.g., during development).
@@ -0,0 +1,9 @@
1
+ export declare const messenger: ({ target, accept, actions, origin }?: {
2
+ target?: any;
3
+ accept?: any;
4
+ actions?: any;
5
+ origin?: string;
6
+ }) => {
7
+ dispatch(action: string, payload?: any): void;
8
+ subscribe(actions_: any): void;
9
+ };
@@ -0,0 +1,39 @@
1
+ var w = Object.defineProperty;
2
+ var l = Object.getOwnPropertySymbols;
3
+ var a = Object.prototype.hasOwnProperty, p = Object.prototype.propertyIsEnumerable;
4
+ var r = (n, i, s) => i in n ? w(n, i, { enumerable: !0, configurable: !0, writable: !0, value: s }) : n[i] = s, d = (n, i) => {
5
+ for (var s in i || (i = {}))
6
+ a.call(i, s) && r(n, s, i[s]);
7
+ if (l)
8
+ for (var s of l(i))
9
+ p.call(i, s) && r(n, s, i[s]);
10
+ return n;
11
+ };
12
+ const f = ({
13
+ target: n = null,
14
+ accept: i = [],
15
+ actions: s = {},
16
+ origin: c = location.origin
17
+ } = {}) => {
18
+ const m = (n == null ? void 0 : n.contentWindow) || n;
19
+ return window.addEventListener("message", (e) => {
20
+ if (i.includes("*") || i.includes(e.origin)) {
21
+ const { action: o, payload: u } = e.data;
22
+ o in s && s[o](u);
23
+ } else
24
+ throw {
25
+ type: "ACCESS DENIED",
26
+ message: "Cant receive message from: " + e.origin
27
+ };
28
+ }), {
29
+ dispatch(e, o) {
30
+ m.postMessage({ action: e, payload: o }, c);
31
+ },
32
+ subscribe(e) {
33
+ s = d(d({}, e), s);
34
+ }
35
+ };
36
+ };
37
+ export {
38
+ f as messenger
39
+ };
@@ -0,0 +1,38 @@
1
+
2
+ export const messenger = ({
3
+
4
+ target = null as any,
5
+ accept = [] as any,
6
+ actions = {} as any,
7
+ origin = location.origin
8
+
9
+ } = {}) => {
10
+
11
+ const win = target?.contentWindow || target
12
+
13
+ window.addEventListener('message', ( event ) => {
14
+
15
+ if( accept.includes('*') || accept.includes(event.origin) ) {
16
+ const { action, payload } = event.data
17
+ if( action in actions ) {
18
+ actions[ action ]( payload as any )
19
+ }
20
+ } else {
21
+ throw {
22
+ type : 'ACCESS DENIED',
23
+ message : 'Cant receive message from: ' + event.origin
24
+ }
25
+ }
26
+ })
27
+
28
+ return {
29
+
30
+ dispatch( action: string, payload?: any ) {
31
+ win.postMessage({ action, payload }, origin)
32
+ },
33
+
34
+ subscribe( actions_: any ) {
35
+ actions = { ...actions_, ...actions }
36
+ }
37
+ }
38
+ }
@@ -0,0 +1 @@
1
+ (function(i,e){typeof exports=="object"&&typeof module!="undefined"?e(exports):typeof define=="function"&&define.amd?define(["exports"],e):(i=typeof globalThis!="undefined"?globalThis:i||self,e(i.messenger={}))})(this,(function(i){"use strict";var p=Object.defineProperty;var u=Object.getOwnPropertySymbols;var g=Object.prototype.hasOwnProperty,y=Object.prototype.propertyIsEnumerable;var l=(i,e,n)=>e in i?p(i,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):i[e]=n,f=(i,e)=>{for(var n in e||(e={}))g.call(e,n)&&l(i,n,e[n]);if(u)for(var n of u(e))y.call(e,n)&&l(i,n,e[n]);return i};const e=({target:n=null,accept:t=[],actions:o={},origin:r=location.origin}={})=>{const c=(n==null?void 0:n.contentWindow)||n;return window.addEventListener("message",s=>{if(t.includes("*")||t.includes(s.origin)){const{action:d,payload:m}=s.data;d in o&&o[d](m)}else throw{type:"ACCESS DENIED",message:"Cant receive message from: "+s.origin}}),{dispatch(s,d){c.postMessage({action:s,payload:d},r)},subscribe(s){o=f(f({},s),o)}}};i.messenger=e,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})}));
package/mfe/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # mfe
2
+
3
+ ```ts
4
+ mfe ({ timeout?= 5000 } = {}): MFEInstance
5
+ ```
6
+
7
+ A package to embed an external front-end application into the current application.
8
+
9
+ If resources failed to load, promise is rejected after **timeout** milisseconds.
10
+
11
+ ### Usage
12
+
13
+ It can embed a full html, css, js from an external url.
14
+
15
+ ```ts
16
+
17
+ import { mfe } from 'jails.std/mfe'
18
+
19
+ function main () {
20
+
21
+ const microfrontend = mfe()
22
+ const target = document.querySelector('#target')
23
+
24
+ microfrontend
25
+ .render( helloworld, 'http://localhost:4000' )
26
+ .then(( target ) => console.log(target, 'is ready'))
27
+ .catch( err => console.error(err) )
28
+ }
29
+ ```
30
+
31
+ **Important** : Loading html files externally means that you will face some issues with C.O.R.S, so be aware of that.
32
+
33
+ It can also embed a single page app from a external `.js` file.
34
+
35
+ ```ts
36
+
37
+ import { mfe } from 'jails.std/mfe'
38
+
39
+ function main () {
40
+
41
+ const microfrontend = mfe()
42
+ const target = document.querySelector('#target')
43
+
44
+ microfrontend.renderJS({
45
+ target: test,
46
+ tag : 'my-component', // <my-component></my-component> your external js should mount in this custom element.
47
+ src : 'http://localhost:8000/test.js'
48
+ })
49
+ .then(( target ) => console.log(target, 'is ready'))
50
+ .catch( err => console.error(err) )
51
+ }
52
+ ```
53
+
54
+ ### Shell()
55
+ You might need to share data from your shell to your microfrontends.
56
+ Instead of doing that manually by using a global variable, you can use `Shell()` function to create
57
+ a channel where you can communicate your shell with your MFE's.
58
+
59
+ Example:
60
+
61
+ #### On shell
62
+
63
+ `main.ts`
64
+
65
+ ```ts
66
+ import { Shell } from 'jails.std/mfe'
67
+
68
+ export const shell = Shell({
69
+ somevariable,
70
+ someFunction,
71
+ someInstance,
72
+ ...etc
73
+ })
74
+
75
+ ```
76
+
77
+ #### On MFE
78
+
79
+ `main.ts`
80
+
81
+ ```ts
82
+ import { Shell } from 'jails.std/mfe'
83
+
84
+ export const shell = Shell({
85
+ somevariable,
86
+ somefunction
87
+ })
88
+ ```
89
+
90
+ You have to guarantee that you'll provide the MFE dependencies on your Shell aswell.
package/mfe/index.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ export declare const mfe: ({ timeout }?: {
2
+ timeout?: number;
3
+ }) => {
4
+ renderJS({ target, tag, src }: {
5
+ target: any;
6
+ tag: any;
7
+ src: any;
8
+ }): Promise<unknown>;
9
+ render(target: any, uri: string): Promise<unknown>;
10
+ };
11
+ export declare const Shell: (config?: {}) => any;
package/mfe/index.js ADDED
@@ -0,0 +1,99 @@
1
+ var T = Object.defineProperty;
2
+ var b = Object.getOwnPropertySymbols;
3
+ var A = Object.prototype.hasOwnProperty, E = Object.prototype.propertyIsEnumerable;
4
+ var L = (n, e, t) => e in n ? T(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t, p = (n, e) => {
5
+ for (var t in e || (e = {}))
6
+ A.call(e, t) && L(n, t, e[t]);
7
+ if (b)
8
+ for (var t of b(e))
9
+ E.call(e, t) && L(n, t, e[t]);
10
+ return n;
11
+ };
12
+ var w = (n, e, t) => new Promise((l, s) => {
13
+ var h = (r) => {
14
+ try {
15
+ a(t.next(r));
16
+ } catch (d) {
17
+ s(d);
18
+ }
19
+ }, u = (r) => {
20
+ try {
21
+ a(t.throw(r));
22
+ } catch (d) {
23
+ s(d);
24
+ }
25
+ }, a = (r) => r.done ? l(r.value) : Promise.resolve(r.value).then(h, u);
26
+ a((t = t.apply(n, e)).next());
27
+ });
28
+ const P = ({ timeout: n = 5e3 } = {}) => {
29
+ const e = {};
30
+ return {
31
+ renderJS({ target: l, tag: s, src: h }) {
32
+ return l.innerHTML = `<${s}></${s}>`, new Promise((u, a) => {
33
+ const r = document.createElement("script");
34
+ r.src = h, r.async = !0, r.onload = () => u(l), r.onerror = (d) => a({
35
+ type: "error",
36
+ message: `[mfe] - ${d.type} loading script`
37
+ }), document.head.appendChild(r);
38
+ });
39
+ },
40
+ render(l, s) {
41
+ return w(this, null, function* () {
42
+ if (!l)
43
+ return new Promise((h, u) => {
44
+ throw {
45
+ type: "not-found",
46
+ data: { target: l, path: s },
47
+ message: "[mfe] - Target not found"
48
+ };
49
+ });
50
+ if (e[s])
51
+ e[s].push({ target: l });
52
+ else {
53
+ e[s] = [];
54
+ const h = yield fetch(s).then((o) => o.text()), a = new DOMParser().parseFromString(h, "text/html"), r = a.querySelectorAll('link[rel="stylesheet"], style'), d = a.querySelectorAll("script"), f = new URL(s), y = [];
55
+ r.forEach((o) => {
56
+ switch (o.localName) {
57
+ case "link":
58
+ const c = document.createElement("link");
59
+ c.setAttribute("rel", "stylesheet"), c.setAttribute("href", new URL(o.getAttribute("href") || "", f).href), y.push(new Promise((i, m) => {
60
+ c.onload = () => i(!0), c.onerror = () => m(new Error(`Failed to load ${c.href}`));
61
+ })), document.head.appendChild(c);
62
+ break;
63
+ case "style":
64
+ const _ = document.createElement("style");
65
+ _.innerHTML = o.innerHTML, document.head.appendChild(_);
66
+ break;
67
+ }
68
+ });
69
+ const S = [];
70
+ return d.forEach((o) => {
71
+ S.push(() => new Promise((c, _) => {
72
+ const i = document.createElement("script");
73
+ for (const m of o.attributes)
74
+ i.setAttribute(m.name, m.value);
75
+ if (o.text) {
76
+ i.text = o.text, document.head.appendChild(i), c(o);
77
+ return;
78
+ }
79
+ o.src && (i.setAttribute("src", new URL(o.getAttribute("src") || "", f).href), i.onload = c, i.onerror = _, document.head.appendChild(i));
80
+ }));
81
+ }), new Promise((o) => {
82
+ Promise.allSettled(y).then(() => l.innerHTML = a.body.innerHTML).then(() => M(S)).then(() => setTimeout(o, 1e3)).then(() => e[s].forEach(({ target: c }) => c.innerHTML = a.body.innerHTML));
83
+ });
84
+ }
85
+ });
86
+ }
87
+ };
88
+ }, k = (n = {}) => window.___Shell___ ? (window.___Shell___ = p(p({}, n), window.___Shell___), window.___Shell___) : (window.___Shell___ = p({}, n), window.___Shell___), M = (n) => w(null, null, function* () {
89
+ const e = [];
90
+ for (const t of n) {
91
+ const l = yield t();
92
+ e.push(l);
93
+ }
94
+ return e;
95
+ });
96
+ export {
97
+ k as Shell,
98
+ P as mfe
99
+ };
package/mfe/index.ts ADDED
@@ -0,0 +1,141 @@
1
+ declare const window: any
2
+
3
+ export const mfe = ({ timeout = 5000 } = {}) => {
4
+
5
+ const cache = {}
6
+
7
+ return {
8
+
9
+ renderJS({ target, tag, src }) {
10
+
11
+ target.innerHTML = `<${tag}></${tag}>`
12
+
13
+ return new Promise((resolve, reject) => {
14
+ const script = document.createElement('script')
15
+ script.src = src
16
+ script.async = true
17
+ script.onload = () => resolve( target )
18
+ script.onerror = (e:Event) => reject({
19
+ type: 'error',
20
+ message: `[mfe] - ${e.type} loading script`
21
+ })
22
+ document.head.appendChild(script)
23
+ })
24
+ },
25
+
26
+ async render( target: any, uri: string ) {
27
+
28
+ if( !target ) {
29
+ return new Promise((resolve, reject) => {
30
+ throw {
31
+ type: 'not-found',
32
+ data: { target, path: uri },
33
+ message: '[mfe] - Target not found'
34
+ }
35
+ })
36
+ }
37
+
38
+ if( !cache[uri] ) {
39
+
40
+ cache[uri] = []
41
+ const html = await fetch( uri ).then( res => res.text() )
42
+ const parser = new DOMParser()
43
+ const doc = parser.parseFromString( html, 'text/html' )
44
+ const assets = doc.querySelectorAll( 'link[rel="stylesheet"], style' )
45
+ const scripts = doc.querySelectorAll( 'script' )
46
+ const url = new URL( uri )
47
+ const promises: any = []
48
+
49
+ assets.forEach((asset: any) => {
50
+
51
+ switch( asset.localName ) {
52
+
53
+ case 'link':
54
+
55
+ const link = document.createElement( 'link' )
56
+
57
+ link.setAttribute( 'rel', 'stylesheet' )
58
+ link.setAttribute( 'href', new URL( asset.getAttribute( 'href' ) || '', url ).href )
59
+
60
+ promises.push( new Promise((resolve, reject) => {
61
+ link.onload = () => resolve( true )
62
+ link.onerror = () => reject( new Error( `Failed to load ${link.href}` ))
63
+ }))
64
+
65
+ document.head.appendChild( link )
66
+
67
+ break
68
+
69
+ case 'style':
70
+
71
+ const style = document.createElement( 'style' )
72
+ style.innerHTML = asset.innerHTML
73
+ document.head.appendChild( style )
74
+
75
+ break
76
+ }
77
+
78
+ })
79
+
80
+ const promiseScripts = []
81
+
82
+ scripts.forEach( script => {
83
+ promiseScripts.push(() => {
84
+ return new Promise((resolve, reject) => {
85
+ const s = document.createElement('script')
86
+
87
+ // Copy attributes
88
+ for (const attr of script.attributes) {
89
+ s.setAttribute(attr.name, attr.value)
90
+ }
91
+
92
+ if( script.text ) {
93
+ s.text = script.text
94
+ document.head.appendChild(s)
95
+ resolve(script)
96
+ return
97
+ }
98
+
99
+ if( script.src ) {
100
+ s.setAttribute( 'src', new URL( script.getAttribute( 'src' ) || '', url ).href )
101
+ s.onload = resolve
102
+ s.onerror = reject
103
+ document.head.appendChild(s)
104
+ }
105
+ })
106
+ })
107
+ })
108
+
109
+ return new Promise((resolve) => {
110
+ Promise.allSettled( promises )
111
+ .then(() => target.innerHTML = doc.body.innerHTML )
112
+ .then(() => runSequentially(promiseScripts))
113
+ .then(() => setTimeout(resolve, 1000))
114
+ .then(() => cache[uri].forEach(({target}) => target.innerHTML = doc.body.innerHTML))
115
+ })
116
+ } else {
117
+ cache[uri].push({ target })
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ export const Shell = ( config = {} ) => {
124
+
125
+ if( !window.___Shell___ ) {
126
+ window.___Shell___ = { ...config }
127
+ return window.___Shell___
128
+ } else {
129
+ window.___Shell___ = { ...config, ...window.___Shell___ }
130
+ return window.___Shell___
131
+ }
132
+ }
133
+
134
+ const runSequentially = async ( promiseFactories ) => {
135
+ const results = []
136
+ for (const factory of promiseFactories) {
137
+ const result = await factory()
138
+ results.push(result)
139
+ }
140
+ return results
141
+ }
@@ -0,0 +1 @@
1
+ (function(n,e){typeof exports=="object"&&typeof module!="undefined"?e(exports):typeof define=="function"&&define.amd?define(["exports"],e):(n=typeof globalThis!="undefined"?globalThis:n||self,e(n.mfe={}))})(this,(function(n){"use strict";var P=Object.defineProperty;var A=Object.getOwnPropertySymbols;var H=Object.prototype.hasOwnProperty,k=Object.prototype.propertyIsEnumerable;var E=(n,e,r)=>e in n?P(n,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):n[e]=r,_=(n,e)=>{for(var r in e||(e={}))H.call(e,r)&&E(n,r,e[r]);if(A)for(var r of A(e))k.call(e,r)&&E(n,r,e[r]);return n};var b=(n,e,r)=>new Promise((p,d)=>{var c=t=>{try{s(r.next(t))}catch(a){d(a)}},w=t=>{try{s(r.throw(t))}catch(a){d(a)}},s=t=>t.done?p(t.value):Promise.resolve(t.value).then(c,w);s((r=r.apply(n,e)).next())});const e=({timeout:d=5e3}={})=>{const c={};return{renderJS({target:s,tag:t,src:a}){return s.innerHTML=`<${t}></${t}>`,new Promise((y,u)=>{const h=document.createElement("script");h.src=a,h.async=!0,h.onload=()=>y(s),h.onerror=S=>u({type:"error",message:`[mfe] - ${S.type} loading script`}),document.head.appendChild(h)})},render(s,t){return b(this,null,function*(){if(!s)return new Promise((a,y)=>{throw{type:"not-found",data:{target:s,path:t},message:"[mfe] - Target not found"}});if(c[t])c[t].push({target:s});else{c[t]=[];const a=yield fetch(t).then(o=>o.text()),u=new DOMParser().parseFromString(a,"text/html"),h=u.querySelectorAll('link[rel="stylesheet"], style'),S=u.querySelectorAll("script"),T=new URL(t),L=[];h.forEach(o=>{switch(o.localName){case"link":const l=document.createElement("link");l.setAttribute("rel","stylesheet"),l.setAttribute("href",new URL(o.getAttribute("href")||"",T).href),L.push(new Promise((i,f)=>{l.onload=()=>i(!0),l.onerror=()=>f(new Error(`Failed to load ${l.href}`))})),document.head.appendChild(l);break;case"style":const m=document.createElement("style");m.innerHTML=o.innerHTML,document.head.appendChild(m);break}});const M=[];return S.forEach(o=>{M.push(()=>new Promise((l,m)=>{const i=document.createElement("script");for(const f of o.attributes)i.setAttribute(f.name,f.value);if(o.text){i.text=o.text,document.head.appendChild(i),l(o);return}o.src&&(i.setAttribute("src",new URL(o.getAttribute("src")||"",T).href),i.onload=l,i.onerror=m,document.head.appendChild(i))}))}),new Promise(o=>{Promise.allSettled(L).then(()=>s.innerHTML=u.body.innerHTML).then(()=>p(M)).then(()=>setTimeout(o,1e3)).then(()=>c[t].forEach(({target:l})=>l.innerHTML=u.body.innerHTML))})}})}}},r=(d={})=>window.___Shell___?(window.___Shell___=_(_({},d),window.___Shell___),window.___Shell___):(window.___Shell___=_({},d),window.___Shell___),p=d=>b(null,null,function*(){const c=[];for(const w of d){const s=yield w();c.push(s)}return c});n.Shell=r,n.mfe=e,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}));
@@ -0,0 +1,46 @@
1
+ # outlet
2
+ ```ts
3
+ outlet( target: string ) : OutletInstance
4
+ ```
5
+ Outlet allows you to render external pages within your application as if it were a SPA. It loads the HTML, JavaScript, and CSS of the target page into a designated DOM element of your choice.
6
+
7
+ ---
8
+
9
+ ## Markup
10
+ ```html
11
+ <main data-outlet></main>
12
+ ```
13
+
14
+ ## .render
15
+ ```ts
16
+ render( url: string ) : Promise<target: HTMLElement>
17
+ ```
18
+
19
+ ```ts
20
+ import { Oultet } from 'jails.std/outlet'
21
+
22
+ const target = document.querySelector('[data-outlet]')
23
+ const outlet = Outlet({ target })
24
+
25
+ outlet.render('http://localhost:3001/') // Renders html, css and javascript from a application running on localhost:3001
26
+ outlet.render() // Renders the initial state from the page before rendering localhost:3001 and clear css, js and html loaded from the last
27
+ ```
28
+
29
+ ## .renderJS
30
+ ```ts
31
+ renderJS( element: string, url: string ) : Promise<element: HTMLElement>
32
+ ```
33
+
34
+ If you have a JavaScript-based SPA hosted at a URL—meaning the script is self-executing and handles rendering the HTML, CSS, and JavaScript functionalities—you can use the renderJS method.
35
+
36
+ This method requires a custom element, provided as a string in the first argument, and the second argument should be the URL of the hosted JavaScript file.
37
+
38
+ ```ts
39
+ renderJS('my-component', 'http://localhost:8000/test.js')
40
+ ```
41
+
42
+ In the example above, make sure your JavaScript initializes the application targeting the my-component element. This ensures a contract between your shell application and the remote application.
43
+
44
+
45
+ ## Important
46
+ For the render version, you need to ensure that the target application has CORS enabled, as Outlet makes a fetch request to the target application behind the scenes to render its HTML within your current application.
@@ -0,0 +1,6 @@
1
+ export declare const Outlet: ({ target: outlet }: {
2
+ target: any;
3
+ }) => {
4
+ renderJS(name: any, path?: any): Promise<any>;
5
+ render(path?: any): Promise<any>;
6
+ };