max-remotes-helper 1.0.0 → 1.0.2

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
@@ -25,7 +25,7 @@ npm install bo-remotes-helper
25
25
  ### Basic Setup
26
26
 
27
27
  ```tsx
28
- import { RemoteWrapper, useRemoteAuth, Secured } from 'bo-remotes-helper';
28
+ import { RemoteWrapper, useRemoteAuth, Secured } from "bo-remotes-helper";
29
29
 
30
30
  // Wrap your remote component
31
31
  export const MyRemoteComponent = ({ token }) => {
@@ -39,11 +39,11 @@ export const MyRemoteComponent = ({ token }) => {
39
39
  // Use authentication context
40
40
  const MyContent = () => {
41
41
  const { state, hasPermission } = useRemoteAuth();
42
-
42
+
43
43
  return (
44
44
  <div>
45
45
  <h1>Welcome {state.user?.name}</h1>
46
-
46
+
47
47
  <Secured permission="edit">
48
48
  <button>Edit Content</button>
49
49
  </Secured>
@@ -55,12 +55,12 @@ const MyContent = () => {
55
55
  ### Module Federation Configuration
56
56
 
57
57
  ```javascript
58
- import { useRemoteConfig } from 'bo-remotes-helper';
58
+ import { useRemoteConfig } from "bo-remotes-helper";
59
59
 
60
60
  const { getWebpackConfig } = useRemoteConfig();
61
61
 
62
- const config = getWebpackConfig('my-remote', {
63
- './MyComponent': './src/MyComponent',
62
+ const config = getWebpackConfig("my-remote", {
63
+ "./MyComponent": "./src/MyComponent",
64
64
  });
65
65
  ```
66
66
 
@@ -69,38 +69,75 @@ const config = getWebpackConfig('my-remote', {
69
69
  ### Components
70
70
 
71
71
  #### `RemoteWrapper`
72
+
72
73
  Main wrapper component that provides authentication context.
73
74
 
74
75
  #### `Secured`
76
+
75
77
  Conditional rendering component based on permissions.
76
78
 
77
79
  ### Hooks
78
80
 
79
81
  #### `useRemoteAuth()`
82
+
80
83
  Access authentication state and methods.
81
84
 
85
+ **[📖 Ver documentación completa de useRemoteAuth](./docs/useRemoteAuth.md)**
86
+
87
+ ```tsx
88
+ const { state, hasPermission, setToken, clearAuth } = useRemoteAuth();
89
+
90
+ // Verificar autenticación
91
+ if (state.isAuthenticated) {
92
+ console.log("User:", state.user?.name);
93
+ console.log("Permissions:", state.permissions);
94
+ }
95
+
96
+ // Verificar permisos específicos
97
+ if (hasPermission("users:write")) {
98
+ // Usuario puede editar
99
+ }
100
+ ```
101
+
82
102
  #### `useRemoteConfig()`
103
+
83
104
  Get standard Module Federation configuration.
84
105
 
106
+ ### Components
107
+
108
+ #### `<Secured />`
109
+
110
+ Conditional rendering based on permissions.
111
+
112
+ **[📖 Ver documentación completa de Secured](./docs/Secured.md)**
113
+
114
+ ```tsx
115
+ <Secured permission="admin:all" fallback={<div>No autorizado</div>}>
116
+ <AdminPanel />
117
+ </Secured>
118
+ ```
119
+
85
120
  ### Utils
86
121
 
87
122
  #### Token utilities
123
+
88
124
  - `decodeToken(token)` - Decode JWT safely
89
125
  - `isTokenExpired(token)` - Check token expiration
90
126
  - `tokenStorage` - Browser storage utilities
91
127
 
92
128
  #### Module utilities
129
+
93
130
  - `loadRemoteModule()` - Dynamic remote loading
94
131
  - `isRemoteAvailable()` - Check remote availability
95
132
 
96
133
  ## Differences from bo-library
97
134
 
98
- | Feature | bo-library | bo-remotes-helper |
99
- |---------|------------|-------------------|
100
- | Authentication | Full JWT verification | Client-side decode only |
101
- | Node.js APIs | Required (crypto, etc.) | Browser-only |
102
- | Bundle size | Large | Lightweight |
103
- | Use case | Host applications | Remote modules |
135
+ | Feature | bo-library | bo-remotes-helper |
136
+ | -------------- | ----------------------- | ----------------------- |
137
+ | Authentication | Full JWT verification | Client-side decode only |
138
+ | Node.js APIs | Required (crypto, etc.) | Browser-only |
139
+ | Bundle size | Large | Lightweight |
140
+ | Use case | Host applications | Remote modules |
104
141
 
105
142
  ## Development
106
143
 
@@ -118,6 +155,18 @@ npm run dev
118
155
  npm run test
119
156
  ```
120
157
 
158
+ ## Documentation
159
+
160
+ 📚 **[Documentación Completa](./docs/README.md)** - Guías, tutoriales y referencia completa
161
+
162
+ ### Quick Links
163
+
164
+ - 🔐 **[Hook useRemoteAuth](./docs/useRemoteAuth.md)** - Autenticación y permisos
165
+ - 🛡️ **[Componente Secured](./docs/Secured.md)** - Renderizado condicional
166
+ - 🚀 **[Quick Start Guide](./docs/quick-start.md)** - Comenzar en 5 minutos
167
+ - 🧪 **[Testing Guide](./docs/guides/testing.md)** - Probar componentes
168
+ - ❓ **[FAQ](./docs/FAQ.md)** - Preguntas frecuentes
169
+
121
170
  ## Integration with bo-module-react-template
122
171
 
123
- This library is designed to be the standard authentication solution for all remote modules created from `bo-module-react-template`.
172
+ This library is designed to be the standard authentication solution for all remote modules created from `bo-module-react-template`.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * DevButton.tsx
3
+ *
4
+ * Componente de botón simple para componentes de desarrollo (DevWrapper, TokenInput, etc.)
5
+ * No depende de Aurora Web para facilitar la separación del código de desarrollo.
6
+ */
7
+ import React from "react";
8
+ type ButtonVariant = "primary" | "secondary" | "text";
9
+ type ButtonSize = "small" | "medium" | "large";
10
+ interface DevButtonProps {
11
+ label: string;
12
+ onClick?: () => void;
13
+ disabled?: boolean;
14
+ variant?: ButtonVariant;
15
+ size?: ButtonSize;
16
+ className?: string;
17
+ type?: "button" | "submit" | "reset";
18
+ }
19
+ declare const DevButton: React.FC<DevButtonProps>;
20
+ export default DevButton;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * DevCard.tsx
3
+ *
4
+ * Componente de tarjeta simple para componentes de desarrollo.
5
+ * Reemplaza EmptyCard de Aurora Web para eliminar dependencias.
6
+ */
7
+ import React from "react";
8
+ interface DevCardProps {
9
+ children: React.ReactNode;
10
+ className?: string;
11
+ }
12
+ declare const DevCard: React.FC<DevCardProps>;
13
+ export default DevCard;
@@ -0,0 +1,6 @@
1
+ import React from "react";
2
+ interface DevWrapperProps {
3
+ children: React.ReactNode;
4
+ }
5
+ declare const DevWrapper: React.FC<DevWrapperProps>;
6
+ export default DevWrapper;
@@ -0,0 +1,6 @@
1
+ import React from "react";
2
+ interface FloatingTokenButtonProps {
3
+ onClick: () => void;
4
+ }
5
+ declare const FloatingTokenButton: React.FC<FloatingTokenButtonProps>;
6
+ export default FloatingTokenButton;
@@ -1,5 +1,5 @@
1
- import React from 'react';
2
- import { AuthProviderProps } from '../types';
1
+ import React from "react";
2
+ import { AuthProviderProps } from "../types";
3
3
  /**
4
4
  * Wrapper component that provides authentication context to remote components
5
5
  * This is the main component that remote applications should use
@@ -0,0 +1,11 @@
1
+ import React from "react";
2
+ interface TokenGeneratorProps {
3
+ onSubmit: (token: string) => void;
4
+ onCancel: () => void;
5
+ onClearStorage: () => void;
6
+ currentToken?: string;
7
+ jsonExample?: string;
8
+ defaultDevRoles?: string[];
9
+ }
10
+ declare const TokenGenerator: React.FC<TokenGeneratorProps>;
11
+ export default TokenGenerator;
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ interface TokenInputProps {
3
+ onSubmit: (token: string) => void;
4
+ onCancel: () => void;
5
+ onClearStorage: () => void;
6
+ currentToken?: string;
7
+ }
8
+ declare const TokenInput: React.FC<TokenInputProps>;
9
+ export default TokenInput;
@@ -1,5 +1,5 @@
1
- import React, { ReactNode } from 'react';
2
- import { RemoteAuthContextValue } from '../types';
1
+ import React, { ReactNode } from "react";
2
+ import { RemoteAuthContextValue } from "../types";
3
3
  interface RemoteAuthProviderProps {
4
4
  children: ReactNode;
5
5
  initialToken?: string;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- export { RemoteAuthProvider, useRemoteAuth } from './context/RemoteAuthContext';
2
- export { Secured } from './components/Secured';
3
- export { RemoteWrapper } from './components/RemoteWrapper';
4
- export { useRemoteConfig } from './hooks/useRemoteConfig';
5
- export { decodeToken, isTokenExpired, extractPermissions, tokenStorage } from './utils/tokenUtils';
6
- export { loadRemoteModule, isRemoteAvailable, createRemoteComponentLoader, getRemoteEnvironment } from './utils/moduleUtils';
7
- export type { RemoteAuthState, RemoteAuthContextValue, AuthProviderProps, SecuredProps, TokenInfo, RemoteConfig, SharedDependencies, } from './types';
1
+ export { RemoteAuthProvider, useRemoteAuth } from "./context/RemoteAuthContext";
2
+ export { Secured } from "./components/Secured";
3
+ export { RemoteWrapper } from "./components/RemoteWrapper";
4
+ export { default as DevWrapper } from "./components/DevWrapper";
5
+ export { useRemoteConfig } from "./hooks/useRemoteConfig";
6
+ export { decodeToken, isTokenExpired, extractPermissions, tokenStorage, } from "./utils/tokenUtils";
7
+ export { loadRemoteModule, isRemoteAvailable, createRemoteComponentLoader, getRemoteEnvironment, } from "./utils/moduleUtils";
8
+ export type { RemoteAuthState, RemoteAuthContextValue, AuthProviderProps, SecuredProps, TokenInfo, RemoteConfig, SharedDependencies, } from "./types";
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /*! For license information please see index.js.LICENSE.txt */
2
- (()=>{var e={20:(e,r,t)=>{"use strict";var o=t(953),n=Symbol.for("react.element"),s=Symbol.for("react.fragment"),a=Object.prototype.hasOwnProperty,i=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};r.Fragment=s,r.jsx=function(e,r,t){var o,s={},c=null,d=null;for(o in void 0!==t&&(c=""+t),void 0!==r.key&&(c=""+r.key),void 0!==r.ref&&(d=r.ref),r)a.call(r,o)&&!l.hasOwnProperty(o)&&(s[o]=r[o]);if(e&&e.defaultProps)for(o in r=e.defaultProps)void 0===s[o]&&(s[o]=r[o]);return{$$typeof:n,type:e,key:c,ref:d,props:s,_owner:i.current}}},60:(e,r,t)=>{var o={"./moduleUtils":226,"./moduleUtils.ts":226,"./tokenUtils":433,"./tokenUtils.ts":433};function n(e){return Promise.resolve().then(()=>{if(!t.o(o,e)){var r=new Error("Cannot find module '"+e+"'");throw r.code="MODULE_NOT_FOUND",r}return t(o[e])})}n.keys=()=>Object.keys(o),n.id=60,e.exports=n},226:(e,r,t)=>{"use strict";t.r(r),t.d(r,{createRemoteComponentLoader:()=>i,getRemoteEnvironment:()=>l,isRemoteAvailable:()=>a,loadRemoteModule:()=>s});var o=t(953),n=t.n(o);const s=async(e,r)=>{try{return await t(60)(`${e}/${r}`)}catch(t){throw console.error(`Failed to load remote module ${e}/${r}:`,t),t}},a=async e=>{try{const r=window[e];return"function"==typeof r?.get}catch(e){return!1}},i=(e,r,t)=>n().lazy(async()=>{try{return await s(e,r)}catch(o){return console.error(`Remote component loading failed: ${e}/${r}`,o),t?{default:t}:{default:()=>n().createElement("div",{style:{padding:"20px",color:"red"}},`Failed to load remote component: ${e}/${r}`)}}}),l=()=>({isDevelopment:!1,apiBaseUrl:process.env.REACT_APP_API_URL||"",frontUrl:process.env.REACT_APP_FRONT_URL||""})},433:(e,r,t)=>{"use strict";t.r(r),t.d(r,{decodeToken:()=>o,extractPermissions:()=>s,isTokenExpired:()=>n,tokenStorage:()=>a});const o=e=>{try{if(!e)return null;const r=e.split(".");if(3!==r.length)return null;const t=r[1],o=t+"=".repeat((4-t.length%4)%4),n=atob(o);return JSON.parse(n)}catch(e){return console.error("Error decoding token:",e),null}},n=e=>{const r=o(e);if(!r||!r.exp)return!0;const t=Math.floor(Date.now()/1e3);return r.exp<t},s=e=>{if(!e)return[];const r=["permissions","roles","authorities","scope"];for(const t of r){const r=e[t];if(Array.isArray(r))return r;if("string"==typeof r)return r.split(" ").filter(Boolean)}return[]},a={key:"bo-remote-token",save:e=>{try{sessionStorage.setItem(a.key,e)}catch(e){console.error("Error saving token:",e)}},get:()=>{try{return sessionStorage.getItem(a.key)}catch(e){return console.error("Error getting token:",e),null}},remove:()=>{try{sessionStorage.removeItem(a.key)}catch(e){console.error("Error removing token:",e)}},clear:()=>{try{sessionStorage.clear()}catch(e){console.error("Error clearing storage:",e)}}}},848:(e,r,t)=>{"use strict";e.exports=t(20)},953:e=>{"use strict";e.exports=require("react")}},r={};function t(o){var n=r[o];if(void 0!==n)return n.exports;var s=r[o]={exports:{}};return e[o](s,s.exports,t),s.exports}t.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return t.d(r,{a:r}),r},t.d=(e,r)=>{for(var o in r)t.o(r,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:r[o]})},t.e=()=>Promise.resolve(),t.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),t.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};(()=>{"use strict";t.r(o),t.d(o,{RemoteAuthProvider:()=>l,RemoteWrapper:()=>u,Secured:()=>d,createRemoteComponentLoader:()=>p.createRemoteComponentLoader,decodeToken:()=>n.decodeToken,extractPermissions:()=>n.extractPermissions,getRemoteEnvironment:()=>p.getRemoteEnvironment,isRemoteAvailable:()=>p.isRemoteAvailable,isTokenExpired:()=>n.isTokenExpired,loadRemoteModule:()=>p.loadRemoteModule,tokenStorage:()=>n.tokenStorage,useRemoteAuth:()=>c,useRemoteConfig:()=>m});var e=t(848),r=t(953),n=t(433);const s={token:null,isAuthenticated:!1,permissions:[],user:void 0},a=(e,r)=>{switch(r.type){case"SET_TOKEN":const t=(0,n.decodeToken)(r.payload),o=t?(0,n.extractPermissions)(t):[];return{...e,token:r.payload,isAuthenticated:!(0,n.isTokenExpired)(r.payload),permissions:o,user:t?{id:t.sub||"",email:t.email||"",name:t.name||t.email||""}:void 0};case"CLEAR_AUTH":return{...s};case"SET_USER_INFO":return{...e,user:{id:r.payload.sub||"",email:r.payload.email||"",name:r.payload.name||r.payload.email||""}};default:return e}},i=(0,r.createContext)(void 0),l=({children:t,initialToken:o})=>{const[l,c]=(0,r.useReducer)(a,s);(0,r.useEffect)(()=>{const e=n.tokenStorage.get(),r=o||e;r&&!(0,n.isTokenExpired)(r)?c({type:"SET_TOKEN",payload:r}):e&&n.tokenStorage.remove()},[o]);const d={state:l,setToken:e=>{e&&(n.tokenStorage.save(e),c({type:"SET_TOKEN",payload:e}))},clearAuth:()=>{n.tokenStorage.remove(),c({type:"CLEAR_AUTH"})},hasPermission:e=>!!l.isAuthenticated&&l.permissions.includes(e)};return(0,e.jsx)(i.Provider,{value:d,children:t})},c=()=>{const e=(0,r.useContext)(i);if(void 0===e)throw new Error("useRemoteAuth must be used within a RemoteAuthProvider");return e},d=({children:r,permission:t,fallback:o=null})=>{const{hasPermission:n,state:s}=c();return s.isAuthenticated&&n(t)?(0,e.jsx)(e.Fragment,{children:r}):(0,e.jsx)(e.Fragment,{children:o})},u=({children:r,token:t,apiBaseUrl:o,module:n})=>(0,e.jsx)(l,{initialToken:t,children:(0,e.jsx)("div",{"data-remote-module":n,"data-api-base":o,children:r})}),m=()=>{const e=(0,r.useMemo)(()=>({react:{singleton:!0,eager:!1},"react-dom":{singleton:!0,eager:!1},"aurora-web":{singleton:!0,eager:!1},"react-i18next":{singleton:!0,eager:!1},i18next:{singleton:!0,eager:!1}}),[]);return{sharedDependencies:e,getWebpackConfig:(r,t)=>({name:r,filename:"remoteEntry.js",exposes:t,shared:e})}};var p=t(226)})(),module.exports=o})();
2
+ (()=>{var e={20:(e,t,r)=>{"use strict";var o=r(953),n=Symbol.for("react.element"),a=Symbol.for("react.fragment"),s=Object.prototype.hasOwnProperty,i=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,r){var o,a={},c=null,d=null;for(o in void 0!==r&&(c=""+r),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(d=t.ref),t)s.call(t,o)&&!l.hasOwnProperty(o)&&(a[o]=t[o]);if(e&&e.defaultProps)for(o in t=e.defaultProps)void 0===a[o]&&(a[o]=t[o]);return{$$typeof:n,type:e,key:c,ref:d,props:a,_owner:i.current}}t.Fragment=a,t.jsx=c,t.jsxs=c},60:(e,t,r)=>{var o={"./moduleUtils":226,"./moduleUtils.ts":226,"./tokenUtils":433,"./tokenUtils.ts":433};function n(e){return Promise.resolve().then(()=>{if(!r.o(o,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r(o[e])})}n.keys=()=>Object.keys(o),n.id=60,e.exports=n},87:(e,t,r)=>{(()=>{var t={20:(e,t,r)=>{"use strict";var o=r(953),n=Symbol.for("react.element"),a=Symbol.for("react.fragment"),s=Object.prototype.hasOwnProperty,i=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};t.Fragment=a,t.jsx=function(e,t,r){var o,a={},c=null,d=null;for(o in void 0!==r&&(c=""+r),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(d=t.ref),t)s.call(t,o)&&!l.hasOwnProperty(o)&&(a[o]=t[o]);if(e&&e.defaultProps)for(o in t=e.defaultProps)void 0===a[o]&&(a[o]=t[o]);return{$$typeof:n,type:e,key:c,ref:d,props:a,_owner:i.current}}},60:(e,t,r)=>{var o={"./moduleUtils":226,"./moduleUtils.ts":226,"./tokenUtils":433,"./tokenUtils.ts":433};function n(e){return Promise.resolve().then(()=>{if(!r.o(o,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r(o[e])})}n.keys=()=>Object.keys(o),n.id=60,e.exports=n},226:(e,t,r)=>{"use strict";r.r(t),r.d(t,{createRemoteComponentLoader:()=>i,getRemoteEnvironment:()=>l,isRemoteAvailable:()=>s,loadRemoteModule:()=>a});var o=r(953),n=r.n(o);const a=async(e,t)=>{try{return await r(60)(`${e}/${t}`)}catch(r){throw console.error(`Failed to load remote module ${e}/${t}:`,r),r}},s=async e=>{try{const t=window[e];return"function"==typeof t?.get}catch(e){return!1}},i=(e,t,r)=>n().lazy(async()=>{try{return await a(e,t)}catch(o){return console.error(`Remote component loading failed: ${e}/${t}`,o),r?{default:r}:{default:()=>n().createElement("div",{style:{padding:"20px",color:"red"}},`Failed to load remote component: ${e}/${t}`)}}}),l=()=>({isDevelopment:!1,apiBaseUrl:process.env.REACT_APP_API_URL||"",frontUrl:process.env.REACT_APP_FRONT_URL||""})},433:(e,t,r)=>{"use strict";r.r(t),r.d(t,{decodeToken:()=>o,extractPermissions:()=>a,isTokenExpired:()=>n,tokenStorage:()=>s});const o=e=>{try{if(!e)return null;const t=e.split(".");if(3!==t.length)return null;const r=t[1],o=r+"=".repeat((4-r.length%4)%4),n=atob(o);return JSON.parse(n)}catch(e){return console.error("Error decoding token:",e),null}},n=e=>{const t=o(e);if(!t||!t.exp)return!0;const r=Math.floor(Date.now()/1e3);return t.exp<r},a=e=>{if(!e)return[];const t=["permissions","roles","authorities","scope"];for(const r of t){const t=e[r];if(Array.isArray(t))return t;if("string"==typeof t)return t.split(" ").filter(Boolean)}return[]},s={key:"bo-remote-token",save:e=>{try{sessionStorage.setItem(s.key,e)}catch(e){console.error("Error saving token:",e)}},get:()=>{try{return sessionStorage.getItem(s.key)}catch(e){return console.error("Error getting token:",e),null}},remove:()=>{try{sessionStorage.removeItem(s.key)}catch(e){console.error("Error removing token:",e)}},clear:()=>{try{sessionStorage.clear()}catch(e){console.error("Error clearing storage:",e)}}}},848:(e,t,r)=>{"use strict";e.exports=r(20)},953:e=>{"use strict";e.exports=r(953)}},o={};function n(e){var r=o[e];if(void 0!==r)return r.exports;var a=o[e]={exports:{}};return t[e](a,a.exports,n),a.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.e=()=>Promise.resolve(),n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var a={};(()=>{"use strict";n.r(a),n.d(a,{RemoteAuthProvider:()=>l,RemoteWrapper:()=>u,Secured:()=>d,createRemoteComponentLoader:()=>g.createRemoteComponentLoader,decodeToken:()=>r.decodeToken,extractPermissions:()=>r.extractPermissions,getRemoteEnvironment:()=>g.getRemoteEnvironment,isRemoteAvailable:()=>g.isRemoteAvailable,isTokenExpired:()=>r.isTokenExpired,loadRemoteModule:()=>g.loadRemoteModule,tokenStorage:()=>r.tokenStorage,useRemoteAuth:()=>c,useRemoteConfig:()=>m});var e=n(848),t=n(953),r=n(433);const o={token:null,isAuthenticated:!1,permissions:[],user:void 0},s=(e,t)=>{switch(t.type){case"SET_TOKEN":const n=(0,r.decodeToken)(t.payload),a=n?(0,r.extractPermissions)(n):[];return{...e,token:t.payload,isAuthenticated:!(0,r.isTokenExpired)(t.payload),permissions:a,user:n?{id:n.sub||"",email:n.email||"",name:n.name||n.email||""}:void 0};case"CLEAR_AUTH":return{...o};case"SET_USER_INFO":return{...e,user:{id:t.payload.sub||"",email:t.payload.email||"",name:t.payload.name||t.payload.email||""}};default:return e}},i=(0,t.createContext)(void 0),l=({children:n,initialToken:a})=>{const[l,c]=(0,t.useReducer)(s,o);(0,t.useEffect)(()=>{if(console.log("🔍 RemoteAuthContext: useEffect triggered",{initialToken:a?a.substring(0,30)+"...":"No initialToken"}),a)console.log("✅ RemoteAuthContext: Using initialToken from prop"),(0,r.isTokenExpired)(a)?(console.log("🔴 RemoteAuthContext: Provided token is expired, clearing auth"),r.tokenStorage.remove(),c({type:"CLEAR_AUTH"})):(console.log("🟢 RemoteAuthContext: Token is valid, dispatching SET_TOKEN"),c({type:"SET_TOKEN",payload:a}),r.tokenStorage.save(a));else{console.log("⚪ RemoteAuthContext: No initialToken, checking stored token");const e=r.tokenStorage.get();e&&!(0,r.isTokenExpired)(e)?(console.log("💾 RemoteAuthContext: Using stored token"),c({type:"SET_TOKEN",payload:e})):e&&(console.log("🗑️ RemoteAuthContext: Stored token expired, clearing"),r.tokenStorage.remove(),c({type:"CLEAR_AUTH"}))}},[a]);const d={state:l,setToken:e=>{e&&(r.tokenStorage.save(e),c({type:"SET_TOKEN",payload:e}))},clearAuth:()=>{r.tokenStorage.remove(),c({type:"CLEAR_AUTH"})},hasPermission:e=>!!l.isAuthenticated&&l.permissions.includes(e)};return(0,e.jsx)(i.Provider,{value:d,children:n})},c=()=>{const e=(0,t.useContext)(i);if(void 0===e)throw new Error("useRemoteAuth must be used within a RemoteAuthProvider");return e},d=({children:t,permission:r,fallback:o=null})=>{const{hasPermission:n,state:a}=c();return a.isAuthenticated&&n(r)?(0,e.jsx)(e.Fragment,{children:t}):(0,e.jsx)(e.Fragment,{children:o})},u=({children:t,token:r,apiBaseUrl:o,module:n})=>(0,e.jsx)(l,{initialToken:r,children:(0,e.jsx)("div",{"data-remote-module":n,"data-api-base":o,children:t})}),m=()=>{const e=(0,t.useMemo)(()=>({react:{singleton:!0,eager:!1},"react-dom":{singleton:!0,eager:!1},"aurora-web":{singleton:!0,eager:!1},"react-i18next":{singleton:!0,eager:!1},i18next:{singleton:!0,eager:!1}}),[]);return{sharedDependencies:e,getWebpackConfig:(t,r)=>({name:t,filename:"remoteEntry.js",exposes:r,shared:e})}};var g=n(226)})(),e.exports=a})()},226:(e,t,r)=>{"use strict";r.r(t),r.d(t,{createRemoteComponentLoader:()=>i,getRemoteEnvironment:()=>l,isRemoteAvailable:()=>s,loadRemoteModule:()=>a});var o=r(953),n=r.n(o);const a=async(e,t)=>{try{return await r(60)(`${e}/${t}`)}catch(r){throw console.error(`Failed to load remote module ${e}/${t}:`,r),r}},s=async e=>{try{const t=window[e];return"function"==typeof t?.get}catch(e){return!1}},i=(e,t,r)=>n().lazy(async()=>{try{return await a(e,t)}catch(o){return console.error(`Remote component loading failed: ${e}/${t}`,o),r?{default:r}:{default:()=>n().createElement("div",{style:{padding:"20px",color:"red"}},`Failed to load remote component: ${e}/${t}`)}}}),l=()=>({isDevelopment:!1,apiBaseUrl:process.env.REACT_APP_API_URL||"",frontUrl:process.env.REACT_APP_FRONT_URL||""})},433:(e,t,r)=>{"use strict";r.r(t),r.d(t,{decodeToken:()=>o,extractPermissions:()=>a,isTokenExpired:()=>n,tokenStorage:()=>s});const o=e=>{try{if(!e)return null;const t=e.split(".");if(3!==t.length)return null;const r=t[1],o=r+"=".repeat((4-r.length%4)%4),n=atob(o);return JSON.parse(n)}catch(e){return console.error("Error decoding token:",e),null}},n=e=>{const t=o(e);if(!t||!t.exp)return!0;const r=Math.floor(Date.now()/1e3);return t.exp<r},a=e=>{if(!e)return[];const t=["permissions","roles","authorities","scope"];for(const r of t){const t=e[r];if(Array.isArray(t))return t;if("string"==typeof t)return t.split(" ").filter(Boolean)}return[]},s={key:"bo-remote-token",save:e=>{try{sessionStorage.setItem(s.key,e)}catch(e){console.error("Error saving token:",e)}},get:()=>{try{return sessionStorage.getItem(s.key)}catch(e){return console.error("Error getting token:",e),null}},remove:()=>{try{sessionStorage.removeItem(s.key)}catch(e){console.error("Error removing token:",e)}},clear:()=>{try{sessionStorage.clear()}catch(e){console.error("Error clearing storage:",e)}}}},848:(e,t,r)=>{"use strict";e.exports=r(20)},953:e=>{"use strict";e.exports=require("react")}},t={};function r(o){var n=t[o];if(void 0!==n)return n.exports;var a=t[o]={exports:{}};return e[o](a,a.exports,r),a.exports}r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.e=()=>Promise.resolve(),r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};(()=>{"use strict";r.r(o),r.d(o,{DevWrapper:()=>y,RemoteAuthProvider:()=>l,RemoteWrapper:()=>u,Secured:()=>d,createRemoteComponentLoader:()=>b.createRemoteComponentLoader,decodeToken:()=>n.decodeToken,extractPermissions:()=>n.extractPermissions,getRemoteEnvironment:()=>b.getRemoteEnvironment,isRemoteAvailable:()=>b.isRemoteAvailable,isTokenExpired:()=>n.isTokenExpired,loadRemoteModule:()=>b.loadRemoteModule,tokenStorage:()=>n.tokenStorage,useRemoteAuth:()=>c,useRemoteConfig:()=>v});var e=r(848),t=r(953),n=r(433);const a={token:null,isAuthenticated:!1,permissions:[],user:void 0},s=(e,t)=>{switch(t.type){case"SET_TOKEN":const r=(0,n.decodeToken)(t.payload),o=r?(0,n.extractPermissions)(r):[];return{...e,token:t.payload,isAuthenticated:!(0,n.isTokenExpired)(t.payload),permissions:o,user:r?{id:r.sub||"",email:r.email||"",name:r.name||r.email||""}:void 0};case"CLEAR_AUTH":return{...a};case"SET_USER_INFO":return{...e,user:{id:t.payload.sub||"",email:t.payload.email||"",name:t.payload.name||t.payload.email||""}};default:return e}},i=(0,t.createContext)(void 0),l=({children:r,initialToken:o})=>{const[l,c]=(0,t.useReducer)(s,a),d="dev"===process.env.REACT_APP_ENVIRONMENT?console.log:()=>{};(0,t.useEffect)(()=>{if(d("🔍 RemoteAuthContext: useEffect triggered",{initialToken:o?o.substring(0,30)+"...":"No initialToken"}),o)d("✅ RemoteAuthContext: Using initialToken from prop"),(0,n.isTokenExpired)(o)?(d("🔴 RemoteAuthContext: Provided token is expired, clearing auth"),n.tokenStorage.remove(),c({type:"CLEAR_AUTH"})):(d("🟢 RemoteAuthContext: Token is valid, dispatching SET_TOKEN"),c({type:"SET_TOKEN",payload:o}),n.tokenStorage.save(o));else{d("⚪ RemoteAuthContext: No initialToken, checking stored token");const e=n.tokenStorage.get();e&&!(0,n.isTokenExpired)(e)?(d("💾 RemoteAuthContext: Using stored token"),c({type:"SET_TOKEN",payload:e})):e&&(d("🗑️ RemoteAuthContext: Stored token expired, clearing"),n.tokenStorage.remove(),c({type:"CLEAR_AUTH"}))}},[o]);const u={state:l,setToken:e=>{e&&(n.tokenStorage.save(e),c({type:"SET_TOKEN",payload:e}))},clearAuth:()=>{n.tokenStorage.remove(),c({type:"CLEAR_AUTH"})},hasPermission:e=>!!l.isAuthenticated&&l.permissions.includes(e)};return(0,e.jsx)(i.Provider,{value:u,children:r})},c=()=>{const e=(0,t.useContext)(i);if(void 0===e)throw new Error("useRemoteAuth must be used within a RemoteAuthProvider");return e},d=({children:t,permission:r,fallback:o=null})=>{const{hasPermission:n,state:a}=c();return a.isAuthenticated&&n(r)?(0,e.jsx)(e.Fragment,{children:t}):(0,e.jsx)(e.Fragment,{children:o})},u=({children:t,token:r})=>(0,e.jsx)(l,{initialToken:r,children:(0,e.jsx)("div",{children:t})});var m=r(87);const g=({children:t,className:r=""})=>(0,e.jsx)("div",{className:`bg-white rounded-lg shadow-md border border-gray-20 ${r}`,children:t}),p=({label:t,onClick:r,disabled:o=!1,variant:n="primary",size:a="medium",className:s="",type:i="button"})=>(0,e.jsx)("button",{type:i,onClick:r,disabled:o,className:`rounded-lg font-medium transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed ${{primary:"bg-gradient-to-br from-blue-40 to-blue-70 hover:from-blue-50 hover:to-blue-90 text-white focus:ring-blue-50 shadow-sm hover:shadow-md",secondary:"bg-gray-20 hover:bg-gray-30 text-gray-80 focus:ring-gray-40 border border-gray-30",text:"bg-transparent hover:bg-gray-10 text-blue-60 hover:text-blue-80 focus:ring-blue-30"}[n]} ${{small:"px-4 py-2 text-sm",medium:"px-5 py-2.5 text-base",large:"px-6 py-3 text-lg"}[a]} ${s}`,children:t}),x=({onSubmit:r,onCancel:o,onClearStorage:n,defaultDevRoles:a=[],currentToken:s=""})=>{const[i,l]=(0,t.useState)(!1),[c,d]=(0,t.useState)(""),[u,m]=(0,t.useState)({user:"usuario@bdsol.com.ar",roles:a,channel:"mf-testing",sessionId:crypto.randomUUID()}),[x,h]=(0,t.useState)(a.join("\n")),f=(e,t)=>{m(r=>({...r,[e]:t}))};return(0,e.jsx)("div",{className:"p-6 w-full overflow-y-auto",children:(0,e.jsx)(g,{className:"p-6",children:(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("h2",{className:"text-2xl font-bold text-gray-80 mb-4",children:"🔧 Generador de Tokens (Desarrollo)"}),(0,e.jsx)("p",{className:"text-gray-60 mb-6",children:"Genera un token JWT para desarrollo usando el BFF. Solo disponible cuando ENVIRONMENT=dev."}),c&&(0,e.jsx)("div",{className:"mb-4 p-3 bg-red-10 border border-red-40 text-red-70 rounded",children:c}),(0,e.jsxs)("div",{className:"space-y-4 mb-6",children:[(0,e.jsxs)("div",{children:[(0,e.jsx)("label",{className:"block text-sm font-medium text-gray-70 mb-1",children:"Email del usuario"}),(0,e.jsx)("input",{type:"email",value:u.user,onChange:e=>f("user",e.target.value),className:"w-full p-2 border border-gray-30 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-50",placeholder:"usuario@bdsol.com.ar"})]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("label",{className:"block text-sm font-medium text-gray-70 mb-1",children:"Roles (uno por línea)"}),(0,e.jsx)("textarea",{value:x,onChange:e=>h(e.target.value),className:"w-full h-32 p-2 border border-gray-30 rounded-lg font-mono text-sm focus:outline-none focus:ring-2 focus:ring-blue-50",placeholder:a.join("&#10;")}),(0,e.jsx)("p",{className:"text-xs text-gray-50 mt-1",children:"Roles definidos en src/config/roles.ts"})]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("label",{className:"block text-sm font-medium text-gray-70 mb-1",children:"Channel"}),(0,e.jsx)("input",{type:"text",value:u.channel,onChange:e=>f("channel",e.target.value),className:"w-full p-2 border border-gray-30 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-50",placeholder:"mf-testing"})]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("label",{className:"block text-sm font-medium text-gray-70 mb-1",children:"Session ID"}),(0,e.jsxs)("div",{className:"flex gap-2",children:[(0,e.jsx)("input",{type:"text",value:u.sessionId,onChange:e=>f("sessionId",e.target.value),className:"flex-1 p-2 border border-gray-30 rounded-lg font-mono text-sm focus:outline-none focus:ring-2 focus:ring-blue-50",placeholder:"uuid-session-id"}),(0,e.jsx)(p,{label:"🎲",variant:"primary",size:"small",onClick:()=>{m(e=>({...e,sessionId:crypto.randomUUID()}))},className:"px-3"})]})]})]}),(0,e.jsxs)("div",{className:"flex gap-3 flex-wrap mb-4",children:[(0,e.jsx)(p,{label:i?"Generando...":"🚀 Generar Token",variant:"primary",size:"small",onClick:async()=>{l(!0),d(""),n();try{const e=x.split("\n").map(e=>e.trim()).filter(e=>e.length>0),t={...u,roles:e},o=process.env.REACT_APP_API_URL||"http://localhost:3020",n=await fetch(`${o}/template/api/dev/generate-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!n.ok){const e=await n.json();throw new Error(e.error||"Error al generar token")}const a=await n.json();r(a.token)}catch(e){d(e instanceof Error?e.message:"Error desconocido")}finally{l(!1)}},disabled:i||!u.user.trim()}),(0,e.jsx)(p,{label:"Limpiar almacenamiento",variant:"primary",size:"small",onClick:()=>{n(),alert("SessionStorage limpiado correctamente")}}),(0,e.jsx)(p,{label:"Cancelar",size:"small",variant:"secondary",onClick:o})]}),s&&(0,e.jsxs)("div",{className:"mt-4 p-4 bg-green-50 rounded-lg",children:[(0,e.jsx)("h3",{className:"font-semibold text-green-70 mb-2",children:"✅ Token cargado"}),(0,e.jsx)("p",{className:"text-sm text-green-60",children:"Tienes un token activo en el almacenamiento local."})]})," "]})})})},h=({onSubmit:r,onCancel:o,onClearStorage:n,currentToken:a=""})=>{const[s,i]=(0,t.useState)(a),[l,c]=(0,t.useState)(!0);return(0,e.jsxs)("div",{className:"bg-white rounded-lg shadow-lg p-6 w-full max-w-2xl",children:[(0,e.jsx)("h2",{className:"text-2xl font-bold text-gray-80 mb-4",children:"Modo Desarrollo - Cargar Token JWT"}),(0,e.jsx)("p",{className:"text-gray-60 mb-6",children:"Ingresa el token JWT decodificado (JSON) que normalmente recibiría desde el host:"}),(0,e.jsxs)("div",{className:"mb-4",children:[(0,e.jsx)("textarea",{value:s,onChange:e=>{const t=e.target.value;i(t),l||c(!0)},placeholder:"Pegue aquí el token JWT en formato JSON",className:`w-full h-40 p-3 border rounded-lg font-mono text-sm ${l?"border-gray-30":"border-red-50"} focus:outline-none focus:ring-2 focus:ring-blue-50`}),!l&&(0,e.jsx)("p",{className:"text-red-50 text-sm mt-2",children:"El JSON no es válido. Por favor verifica la sintaxis."})]}),(0,e.jsxs)("div",{className:"flex gap-3 flex-wrap",children:[(0,e.jsx)(p,{label:"Cargar Token",variant:"primary",size:"small",onClick:()=>{try{JSON.parse(s),c(!0),r(s)}catch(e){c(!1)}},disabled:!s.trim()}),(0,e.jsx)(p,{label:"Limpiar",size:"small",variant:"text",onClick:()=>i("")}),(0,e.jsx)(p,{label:"Limpiar Storage",variant:"primary",size:"small",onClick:()=>{n(),i(""),alert("SessionStorage limpiado correctamente")}}),(0,e.jsx)(p,{label:"Cancelar",variant:"secondary",size:"small",onClick:o})]})]})},f=({onClick:t})=>(0,e.jsxs)("button",{onClick:t,className:"fixed bottom-6 right-6 bg-gradient-to-br from-blue-40 to-blue-70 hover:from-blue-50 hover:to-blue-90 text-white p-4 rounded-full shadow-dropdown hover:shadow-2xl transition-all duration-300 z-50 group transform hover:scale-110",title:"Recargar Token",children:[(0,e.jsx)("svg",{className:"w-5 h-5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,e.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"})}),(0,e.jsx)("span",{className:"absolute bottom-full right-0 mb-3 px-3 py-1 text-xs text-white bg-gray-90/90 rounded-lg opacity-0 group-hover:opacity-100 transition-opacity duration-200 whitespace-nowrap backdrop-blur-sm",children:"Recargar Token"})]}),y=({children:r})=>{const[o,n]=(0,t.useState)(""),[a,s]=(0,t.useState)(!1),[i,l]=(0,t.useState)(!1),[c,d]=(0,t.useState)(!0),u="dev"===process.env.REACT_APP_ENVIRONMENT&&!o;(0,t.useEffect)(()=>{const e=m.tokenStorage.get();e?(n(e),l(!1)):u&&l(!0)},[u]);const g=e=>{console.log("🔄 DevWrapper: Nuevo token generado",{token:e.substring(0,50)+"..."}),n(e),m.tokenStorage.save(e),console.log("💾 DevWrapper: Token guardado en storage"),s(!1),l(!1)},p=()=>{m.tokenStorage.clear(),n(""),l(u)};return i?(0,e.jsx)("div",{className:"min-h-screen bg-gray-50 flex items-center justify-center p-4",children:(0,e.jsx)(x,{onSubmit:g,onCancel:()=>l(!1),onClearStorage:p,currentToken:o})}):(0,e.jsxs)("div",{className:"min-h-screen bg-gray-50",children:[a&&(0,e.jsx)("div",{className:"fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50",children:(0,e.jsxs)("div",{className:"bg-white rounded-lg shadow-lg max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto",children:[(0,e.jsxs)("div",{className:"flex border-b",children:[(0,e.jsx)("button",{onClick:()=>d(!0),className:"flex-1 py-3 px-4 text-sm font-medium "+(c?"bg-blue-50 ":"bg-gray-10 text-gray-70 hover:bg-gray-20"),children:"Generar Token"}),(0,e.jsx)("button",{onClick:()=>d(!1),className:"flex-1 py-3 px-4 text-sm font-medium "+(c?"bg-gray-10 text-gray-70 hover:bg-gray-20":"bg-blue-50 text-gray-50"),children:"Input Manual"})]}),(0,e.jsx)("div",{className:"p-0",children:c?(0,e.jsx)(x,{onSubmit:g,onCancel:()=>s(!1),onClearStorage:p,currentToken:o}):(0,e.jsx)("div",{className:"p-6",children:(0,e.jsx)(h,{onSubmit:g,onCancel:()=>s(!1),onClearStorage:p,currentToken:o})})})]})}),(0,e.jsx)(f,{onClick:()=>{s(!a)}}),(0,e.jsx)(m.RemoteWrapper,{token:o,children:r})]})},v=()=>{const e=(0,t.useMemo)(()=>({react:{singleton:!0,eager:!1},"react-dom":{singleton:!0,eager:!1},"aurora-web":{singleton:!0,eager:!1},"react-i18next":{singleton:!0,eager:!1},i18next:{singleton:!0,eager:!1}}),[]);return{sharedDependencies:e,getWebpackConfig:(t,r)=>({name:t,filename:"remoteEntry.js",exposes:r,shared:e})}};var b=r(226)})(),module.exports=o})();
@@ -1,3 +1,5 @@
1
+ /*! For license information please see index.js.LICENSE.txt */
2
+
1
3
  /**
2
4
  * @license React
3
5
  * react-jsx-runtime.production.min.js