forlogic-core 2.3.0 → 2.3.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.
Files changed (39) hide show
  1. package/.note/memory/patterns/dynamic-supabase-config.md +2 -2
  2. package/.note/memory/patterns/environment-detection-logic.md +21 -15
  3. package/README.md +1 -1
  4. package/dist/action-plans/config/environments.d.ts +18 -3
  5. package/dist/action-plans/config/index.d.ts +3 -3
  6. package/dist/action-plans/index.d.ts +1 -1
  7. package/dist/action-plans/index.esm.js +1 -1
  8. package/dist/action-plans/index.js +1 -1
  9. package/dist/audit-trail/config/environments.d.ts +18 -3
  10. package/dist/audit-trail/config/index.d.ts +3 -3
  11. package/dist/audit-trail/index.d.ts +1 -1
  12. package/dist/audit-trail/index.esm.js +1 -1
  13. package/dist/audit-trail/index.js +1 -1
  14. package/dist/config/environments.d.ts +18 -3
  15. package/dist/config/index.d.ts +3 -3
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.esm.js +1 -1
  18. package/dist/index.js +1 -1
  19. package/dist/leadership/config/environments.d.ts +18 -3
  20. package/dist/leadership/config/index.d.ts +3 -3
  21. package/dist/leadership/index.d.ts +1 -1
  22. package/dist/leadership/index.esm.js +1 -1
  23. package/dist/leadership/index.js +1 -1
  24. package/dist/places/config/environments.d.ts +18 -3
  25. package/dist/places/config/index.d.ts +3 -3
  26. package/dist/places/index.d.ts +1 -1
  27. package/dist/places/index.esm.js +1 -1
  28. package/dist/places/index.js +1 -1
  29. package/dist/sign/config/environments.d.ts +18 -3
  30. package/dist/sign/config/index.d.ts +3 -3
  31. package/dist/sign/index.d.ts +1 -1
  32. package/dist/sign/index.esm.js +1 -1
  33. package/dist/sign/index.js +1 -1
  34. package/dist/vite/index.esm.js +24 -1
  35. package/dist/vite/index.js +24 -0
  36. package/docs/WORKSPACE_KNOWLEDGE.md +1 -1
  37. package/docs/design-system/patterns/core-providers.md +11 -2
  38. package/docs/design-system/patterns/feature-flags.md +53 -21
  39. package/package.json +1 -1
@@ -1 +1 @@
1
- "use strict";var e=require("react/jsx-runtime"),t=require("react");require("@tanstack/react-query");var a=require("i18next"),s=require("@supabase/supabase-js"),n=require("sonner"),r=require("lucide-react"),o=require("react-i18next"),i=require("class-variance-authority"),c=require("clsx"),l=require("tailwind-merge");require("date-fns");var d=require("@radix-ui/react-slot"),u=require("@radix-ui/react-label"),m=require("@radix-ui/react-select");function g(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(a){if("default"!==a){var s=Object.getOwnPropertyDescriptor(e,a);Object.defineProperty(t,a,s.get?s:{enumerable:!0,get:function(){return e[a]}})}}),t.default=e,Object.freeze(t)}var h=g(t),p=g(u),f=g(m);class x{static normalizeBase64Url(e){let t=e.replace(/-/g,"+").replace(/_/g,"/");const a=(4-t.length%4)%4;return t+="=".repeat(a),t}static parseJwtPayload(e){try{const n=e.split(".");if(3!==n.length)return null;const r=n[1];r.length,this.LARGE_PAYLOAD_THRESHOLD;try{const e=this.normalizeBase64Url(r),t=atob(e),a=new Uint8Array(t.length);for(let n=0;n<t.length;n++)a[n]=t.charCodeAt(n);const s=new TextDecoder("utf-8").decode(a);return JSON.parse(s)}catch(t){try{const e=this.normalizeBase64Url(r),t=decodeURIComponent(atob(e).split("").map(e=>"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2)).join(""));return JSON.parse(t)}catch(a){try{const e=this.normalizeBase64Url(r),t=atob(e);return JSON.parse(t)}catch(s){throw s}}}}catch(n){return null}}static validateTokens(e,t){const a=[],s=[];try{t.split(".")[1],e.split(".")[1];const n=this.parseJwtPayload(t),r=this.parseJwtPayload(e);if(!n){const e="ID token decode falhou - possível problema com base64url encoding";return s.push(e),{isValid:!1,idTokenValid:!1,accessTokenValid:!1,warnings:a,errors:s}}let o=!0;if(!r){const e="Access token decode falhou - será tentado novamente nas chamadas de API";a.push(e),o=!1}const i=Math.floor(Date.now()/1e3);if(r?.exp&&r.exp<i){const e="Access token expirado - pode precisar de refresh";a.push(e),o=!1}if(n.exp&&n.exp<i){const e="ID token expirado - autenticação inválida";return s.push(e),{isValid:!1,idTokenValid:!1,accessTokenValid:o,warnings:a,errors:s}}return{isValid:!0,idTokenValid:!0,accessTokenValid:o,warnings:a,errors:s}}catch(n){const e=`Erro na validação de tokens: ${n}`;return s.push(e),{isValid:!1,idTokenValid:!1,accessTokenValid:!1,warnings:a,errors:s}}}static isTokenExpired(e){const t=this.parseJwtPayload(e);return!t||!t.exp||1e3*t.exp<Date.now()}}x.LARGE_PAYLOAD_THRESHOLD=1e3;const v="qualiex_access_token",y="qualiex_id_token",b="supabase_token",_="oauth_state",k="oauth_nonce",w="selected_alias",S="manual_logout",j="supabase_project_id",N={setAccessToken:e=>localStorage.setItem(v,e),getAccessToken:()=>localStorage.getItem(v),setIdToken:e=>localStorage.setItem(y,e),getIdToken:()=>localStorage.getItem(y),getSupabaseToken:()=>localStorage.getItem(b),setOAuthState:e=>sessionStorage.setItem(_,e),getOAuthState:()=>sessionStorage.getItem(_),clearOAuthState:()=>sessionStorage.removeItem(_),setOAuthNonce:e=>sessionStorage.setItem(k,e),getOAuthNonce:()=>sessionStorage.getItem(k),clearOAuthNonce:()=>sessionStorage.removeItem(k),setSelectedAlias:e=>localStorage.setItem(w,e),getSelectedAlias:()=>localStorage.getItem(w),clearSelectedAlias:()=>localStorage.removeItem(w),generateOAuthNonce:()=>{const e=new Uint8Array(32);return crypto.getRandomValues(e),btoa(String.fromCharCode(...e)).replace(/[+/=]/g,"")},hasAllTokens:()=>!(!N.getAccessToken()||!N.getIdToken()),checkProjectMismatch:()=>{const e=(void 0).VITE_SUPABASE_PROJECT_ID;if(!e)return!1;const t=localStorage.getItem(j);return t&&t!==e?(N.clearAll(),localStorage.setItem(j,e),!0):(t||localStorage.setItem(j,e),!1)},setSupabaseToken:e=>{localStorage.setItem(b,e),N._clearValidationCache()},areAllTokensValid:()=>{const e=N.getAccessToken(),t=N.getIdToken();if(!e||!t)return!1;try{const a=x.validateTokens(e,t);return!!a.idTokenValid&&a.idTokenValid}catch(a){return!1}},clearExpiredTokens:()=>{let e=!1;const t=N.getAccessToken(),a=N.getIdToken(),s=N.getSupabaseToken();return t&&N.isTokenExpired(t)&&(localStorage.removeItem(v),e=!0),a&&N.isTokenExpired(a)&&(localStorage.removeItem(y),e=!0),s&&N.isTokenExpired(s)&&(localStorage.removeItem(b),e=!0),e},clearAll:()=>{localStorage.removeItem(v),localStorage.removeItem(y),localStorage.removeItem(b),localStorage.removeItem(w),localStorage.removeItem(S),sessionStorage.removeItem(_),sessionStorage.removeItem(k),N._clearValidationCache()},setManualLogout:()=>localStorage.setItem(S,"true"),isManualLogout:()=>"true"===localStorage.getItem(S),clearManualLogout:()=>localStorage.removeItem(S),isTokenExpired:e=>{try{return x.isTokenExpired(e)}catch{return!0}},_validationCache:{isValid:!1,timestamp:0,cacheValidityMs:3e5},_clearValidationCache:()=>{N._validationCache.isValid=!1,N._validationCache.timestamp=0},isSupabaseTokenValid:()=>{const e=N.getSupabaseToken();if(!e)return!1;if(N.isTokenExpired(e))return N._clearValidationCache(),N._handleExpiredToken(),!1;const t=Date.now();return t-N._validationCache.timestamp<N._validationCache.cacheValidityMs?N._validationCache.isValid:(N._validationCache.isValid=!0,N._validationCache.timestamp=t,!0)},getValidSupabaseToken:()=>N.isSupabaseTokenValid()?N.getSupabaseToken():null,_handleExpiredToken:()=>{N.clearAll()},extractTokenData:()=>{if(!N.isSupabaseTokenValid())return null;const e=N.getSupabaseToken();if(!e)return null;try{const t=x.parseJwtPayload(e);if(!t)return null;const a=t.alias||t.default||t.user_alias,s=t.place_id||null,n=t.place_name||null;let r=t.company_id;if(!r&&a)for(const e in t)if(e.startsWith("co")&&/^co\d+$/.test(e)){const s=t[e];if(s&&"string"==typeof s){const e=s.split(";");if(e.length>7&&e[0]===a){r=e[7];break}}}return{alias:a,companyId:r,placeId:s,placeName:n,payload:t}}catch(t){return N._handleExpiredToken(),null}},getCompanyId:e=>{const t=N.getAccessToken();if(t)try{const a=x.parseJwtPayload(t);if(a)for(const t in a)if(t.startsWith("co")&&/^co\d+$/.test(t)){const s=a[t];if(s&&"string"==typeof s){const t=s.split(";");if(e&&t.length>7&&t[0]===e)return t[7];if(!e&&t.length>7)return t[7]}}}catch(n){}const a=N.extractTokenData();if(a?.companyId)return a.companyId;const s=N.getIdToken();if(s)try{const t=x.parseJwtPayload(s);if(t)for(const a in t)if(a.startsWith("co")&&/^co\d+$/.test(a)){const s=t[a];if(s&&"string"==typeof s){const t=s.split(";");if(e&&t.length>7&&t[0]===e)return t[7];if(!e&&t.length>7)return t[7]}}}catch(n){}return null},getCompanyIdInt:e=>{const t=[N.getAccessToken(),N.getIdToken()];for(const a of t)if(a)try{const t=x.parseJwtPayload(a);if(!t)continue;for(const a in t)if(a.startsWith("co")&&/^co\d+$/.test(a)){const s=t[a];if(s&&"string"==typeof s){const t=s.split(";");if(e&&t.length>1&&t[0]===e)return t[1];if(!e&&t.length>1)return t[1]}}}catch{}return null},getCurrentCompanyId:()=>{const e=N.extractTokenData();return e?.companyId||null},getAllCompaniesData:()=>{const e=N.getIdToken();if(!e)return[];try{const t=x.parseJwtPayload(e);if(!t)return[];const a=[];for(const e in t)if(e.startsWith("co")&&/^co\d+$/.test(e)){const s=t[e];if(s&&"string"==typeof s){const e=s.split(";");e.length>=4&&a.push({id:e.length>7?e[7]:"",alias:e[0].trim(),name:e[3].trim(),payload:t})}}return a}catch{return[]}}},T={storageProjectId:"ccjfvpnndclajkleyqkc",oauth:{authUrl:"https://login.qualiex.com/oauth2/authorize",clientId:"ae6021a0-e874-4aab-9716-b478e59cec20"},qualiexApiUrl:"https://common-v4-api.qualiex.com"},I={storageProjectId:"ccjfvpnndclajkleyqkc",oauth:{authUrl:"https://login-dev.qualiex.com/oauth2/authorize",clientId:"ae6021a0-e874-4aab-9716-b478e59cec20"},qualiexApiUrl:"https://common-v4-api-dev.qualiex.com"};const A={get oauth(){const e=function(){let e=(void 0).VITE_SUPABASE_PROJECT_ID;if(!e)try{const t=(void 0).VITE_SUPABASE_URL;t&&(e=new URL(t).hostname.split(".")[0])}catch{}return"ccjfvpnndclajkleyqkc"===e?T:I}();return{authUrl:e.oauth.authUrl,clientId:e.oauth.clientId,responseType:"id_token token",scope:"openid profile email"}}};(void 0).VITE_IS_QUALIEX;const E=new class{constructor(){this.errors=[],this.toastCount=0,this.lastToastTime=0}handleError(e,t=!0){const a="string"==typeof e?e:e.message;if(this.errors.push({id:Date.now().toString(),message:a,timestamp:Date.now(),count:1}),this.errors.length>50&&(this.errors=this.errors.slice(-50)),t&&this.shouldShowToast()){const e=this.getErrorTitle(a);n.toast.error(e,{description:a})}}getErrorTitle(e){const t=e.toLowerCase();return t.includes("401")||t.includes("unauthorized")||t.includes("expirou")?a.t("error_session_expired"):t.includes("token")||t.includes("autenticação")?a.t("error_authentication"):t.includes("api")||t.includes("network")?a.t("error_connection"):"Erro"}success(e,t){n.toast.success(e,{description:t})}shouldShowToast(){const e=Date.now();return e-this.lastToastTime>6e4&&(this.toastCount=0),this.toastCount<3&&(this.toastCount++,this.lastToastTime=e,!0)}getErrors(){return this.errors.slice(-50)}clearErrors(){this.errors=[]}};["[forlogic-core] ⚠️ VITE_SUPABASE_PUBLISHABLE_KEY contém uma legacy anon key (JWT).","O Supabase desativou legacy API keys. Substitua pela nova publishable key (formato sb_publishable_*).","Todas as requests retornarão 401 Unauthorized.","Causa provável: a integração Supabase do Lovable sobrescreveu o .env com a anon key legada.","Solução: defina VITE_SUPABASE_PK_OVERRIDE no .env com a publishable key correta."].join(" ");function C(e){return!!e&&e.startsWith("eyJ")}function P(){const e=(void 0).VITE_SUPABASE_PK_OVERRIDE;return e||((void 0).VITE_SUPABASE_PUBLISHABLE_KEY??"")}let L=!1;class R{constructor(e){this.currentToken=null,this.config=e,function(){const e=(void 0).VITE_SUPABASE_PK_OVERRIDE,t=(void 0).VITE_SUPABASE_PUBLISHABLE_KEY;L?C(t):e&&C(t)?L=!0:C(t)?L=!0:L=!0}(),this.client=this.createClientWithToken(null)}createClientWithToken(e){const t={apikey:this.config.key};e&&this.isTokenValid(e)&&(t.Authorization=`Bearer ${e}`);return s.createClient(this.config.url,this.config.key,{auth:{persistSession:!1,autoRefreshToken:!1,detectSessionInUrl:!1,storage:void 0},global:{headers:t,fetch:async(e,t)=>("string"==typeof e?e:e.url).includes("/auth/v1/user")?new Response(JSON.stringify({error:"blocked"}),{status:401,headers:{"Content-Type":"application/json"}}):fetch(e,t)}})}static getInstance(){if(!R.instance){const e=function(){const e=(void 0).VITE_SUPABASE_URL,t=P();return e&&t?{url:e,key:t}:null}();if(!e)throw new Error("[forlogic-core] Supabase não configurado. Defina VITE_SUPABASE_URL e VITE_SUPABASE_PUBLISHABLE_KEY no .env, ou não invoque getSupabaseClient() (use isSupabaseConfigured() para checar antes).");R.instance=new R(e)}return R.instance}getClient(){const e=N.getValidSupabaseToken();return e!==this.currentToken&&(this.client=this.createClientWithToken(e),this.currentToken=e),this.client}isTokenValid(e){try{return!x.isTokenExpired(e)}catch(t){return E.handleError(t instanceof Error?t:"Supabase - Error validating token",!1),!1}}}function V(){return R.getInstance().getClient()}class U{static async generateToken(e,t,a,s=!1){try{if(!s){const e=N.getSupabaseToken();if(e&&N.isSupabaseTokenValid())return e}const n=V(),{data:r,error:o}=await n.functions.invoke("validate-token",{body:{access_token:e,alias:t}});return o&&(o.message?.includes("401")||o.message?.includes("Unauthorized"))?(a?.(),null):r?.access_token?(N.setSupabaseToken(r.access_token),r.access_token):null}catch(n){return n instanceof Error&&(n.message.includes("401")||n.message.includes("Unauthorized"))&&a?.(),null}}}class D{static setLogoutCallback(e){this.onLogoutCallback=e}static async attemptRegeneration(e=!1){if(this.regenerationPromise)return this.regenerationPromise;this.regenerationPromise=this._doRegenerate(e);try{return await this.regenerationPromise}finally{this.regenerationPromise=null}}static async _doRegenerate(e=!1){try{const t=N.getAccessToken(),a=N.getSelectedAlias();if(!t||!a)return null;const s=await U.generateToken(t,a,this.onLogoutCallback||void 0,e);return s||null}catch(t){return null}}}D.regenerationPromise=null,D.onLogoutCallback=null;var O;const q={isAuthenticated:!1,isLoading:!1,user:null,alias:null,companies:[],selectedUnit:null,userId:null,userAlias:null,placeId:null,placeName:null,activePlaceId:null,activePlaceName:null};O=class{static async initialize(){try{const e=!0;if(e){if(N.checkProjectMismatch())return{...q}}if(!N.hasAllTokens()||!N.areAllTokensValid())return N.clearExpiredTokens(),{...q};const t=N.getAccessToken(),a=N.getIdToken();N.clearManualLogout();const s=this.extractUserFromIdToken(a,t),n=this.extractCompaniesFromIdToken(a),r=this.extractAliasFromAccessToken(t),o=e?N.extractTokenData():null,i=o?.alias;let c=null;if(i&&n.some(e=>e.alias===i))c=i;else{const e=N.getSelectedAlias(),t=e&&n.some(t=>t.alias===e);c=t?e:r||n[0]?.alias||null}if(e&&(!N.isSupabaseTokenValid()&&c&&await D.attemptRegeneration(),!N.isSupabaseTokenValid()))return{...q};let l=null;if(c){const e=N.getCompanyId(c),t=n.find(e=>e.alias===c);t&&(l={id:e||t.id,name:t.name,alias:t.alias})}const d=o?.placeId??null,u=o?.placeName??null;return{isAuthenticated:!0,isLoading:!1,user:s,alias:c,companies:n,selectedUnit:l,userId:s?.id||null,userAlias:s?.id||null,placeId:d,placeName:u,activePlaceId:d,activePlaceName:u}}catch(e){return{...q}}}static async loginDev(){try{const e=V(),{data:t,error:a}=await e.functions.invoke("dev-tokens",{body:{environment:"development"}});if(a)return!1;if(!t?.access_token||!t?.id_token)return!1;const s=new URL("/callback",window.location.origin);return s.hash=`access_token=${t.access_token}&id_token=${t.id_token}&token_type=bearer`,window.location.href=s.toString(),!0}catch(e){return!1}}static loginProd(){const e="Lw==";N.setOAuthState(e);const t=N.generateOAuthNonce();N.setOAuthNonce(t);const a=`${window.location.origin}/callback`,s=new URL(A.oauth.authUrl);s.searchParams.set("client_id",A.oauth.clientId),s.searchParams.set("response_type",A.oauth.responseType),s.searchParams.set("scope",A.oauth.scope),s.searchParams.set("redirect_uri",a),s.searchParams.set("state",e),s.searchParams.set("nonce",t),s.searchParams.set("response_mode","fragment"),window.location.href=s.toString()}static async processCallback(){try{const e=new URLSearchParams(window.location.hash.startsWith("#")?window.location.hash.substring(1):window.location.hash),t=new URLSearchParams(window.location.search),a=a=>e.get(a)||t.get(a),s=a("access_token"),n=a("id_token"),r=a("error");if(r)throw new Error(`Erro OAuth: ${r}`);if(s&&n){const e=N.getAccessToken();e!==s&&N.clearAll()}const o=!0;if(N.hasAllTokens()){if(o){N.getValidSupabaseToken()||await D.attemptRegeneration(!0)}return!0}const i=s,c=n;if(!i||!c)throw new Error("Tokens não encontrados na URL de callback");N.setAccessToken(i),N.setIdToken(c),N.clearManualLogout();const l=this.extractAliasFromAccessToken(i);if(l)N.setSelectedAlias(l);else{const e=this.extractCompaniesFromIdToken(c);if(0===e.length)throw new Error("Nenhuma empresa encontrada nos tokens");N.setSelectedAlias(e[0].alias)}if(o){if(!await D.attemptRegeneration(!0))throw new Error("Falha ao gerar token Supabase")}return N.clearOAuthState(),N.clearOAuthNonce(),!0}catch(e){throw e}}static async logout(){N.setManualLogout(),N.clearAll(),localStorage.removeItem("auth_return_url"),sessionStorage.clear();try{if("caches"in window){const e=await caches.keys();await Promise.all(e.map(e=>caches.delete(e)))}}catch{}window.location.href="/login"}static decodeToken(e){return x.parseJwtPayload(e)}static extractUserFromIdToken(e,t){const a=this.decodeToken(e);if(!a)return null;const s=t?this.decodeToken(t):null;return{id:a.subNewId,email:a.email,name:a.name,identifier:a.identifier,isSysAdmin:"1"===s?.admin}}static extractCompaniesFromIdToken(e){const t=this.decodeToken(e);if(!t)return[];const a=[];return Object.keys(t).forEach(e=>{if(e.match(/^co(\d+)$/)&&"string"==typeof t[e]){const s=t[e].split(";");if(s.length>=4)a.push({id:s.length>7?s[7].trim():"",alias:s[0].trim(),name:s[3].trim()});else{const[s,n]=t[e].split("|");s&&n&&a.push({id:"",alias:s.trim(),name:n.trim()})}}}),a}static extractAliasFromAccessToken(e){const t=this.decodeToken(e);return t?.default||null}},D.setLogoutCallback(()=>{O.logout()});const B=t.createContext(void 0),$=()=>{const e=t.useContext(B);if(void 0===e)throw new Error("useAuth deve ser usado dentro de um AuthProvider");return e};function z(){const{alias:e}=$(),[a,s]=t.useState(null),[n,r]=t.useState(!0);t.useEffect(()=>{if(!e)return void r(!1);let t=!1;return(async()=>{r(!0);try{const a=V(),{data:n,error:r}=await a.schema("common").from("sign_configs").select("*").eq("alias",e).is("deleted_at",null).maybeSingle();t||s(n)}catch(a){t||s(null)}finally{t||r(!1)}})(),()=>{t=!0}},[e]);return{config:a,isLoading:n,saveConfig:t.useCallback(async(t,a)=>{if(!e)throw new Error("Alias not available");const n=V(),{data:r,error:o}=await n.schema("common").from("sign_configs").upsert({alias:e,api_key:t,environment:a,updated_at:(new Date).toISOString()},{onConflict:"alias"}).select().maybeSingle();if(o)throw o;return s(r),r},[e])}}const J=(void 0).VITE_SUPABASE_URL,F=P();async function W(e,t,a){const s=N.getSupabaseToken(),n={"Content-Type":"application/json",apikey:F};s&&(n.Authorization=`Bearer ${s}`);const r=await fetch(`${J}/functions/v1/${e}`,{method:"POST",headers:n,body:JSON.stringify({action:t,data:a})});if(!r.ok){const e=await r.json().catch(()=>({}));throw new Error(e.error||`Erro na requisição: ${r.status}`)}return r}const M={async createEnvelopeWithSigner(e){const t="d4sign"===e.provider?"d4sign":"clicksign",a="d4sign"===e.provider?"create_and_send":"create_envelope_with_signer";return(await W(t,a,{content_base64:e.contentBase64,filename:e.filename,signer_email:e.signerEmail,signer_name:e.signerName})).json()},async getSignedDocument(e){const t="d4sign"===e.provider?"d4sign":"clicksign";return(await W(t,"get_signed_document",{envelope_id:e.envelopeId,document_id:e.documentId})).json()}};let H=null;function K(){return window.Clicksign?Promise.resolve():H||(H=new Promise((e,t)=>{const a=document.createElement("script");a.src="https://cdn-public-library.clicksign.com/embedded/embedded.min-2.1.0.js",a.onload=()=>e(),a.onerror=()=>t(new Error("Falha ao carregar script do Clicksign")),document.head.appendChild(a)}),H)}const Y="clicksign-container";function G({signerId:a,environment:s="sandbox",onSign:n,onError:i,onClose:c}){const{t:l}=o.useTranslation(),d=t.useRef(null),[u,m]=t.useState(!0),[g,h]=t.useState(null);return t.useEffect(()=>{let e=!1;return d.current&&(d.current.unmount(),d.current=null),h(null),m(!0),K().then(()=>{if(e)return;const t=new window.Clicksign(a);t.endpoint="production"===s?"https://app.clicksign.com":"https://sandbox.clicksign.com",t.origin=window.origin,t.mount(Y),t.on("loaded",function(){m(!1)}),t.on("signed",function(){n?.()}),t.on("resized",function(e){const t=e,a=document.getElementById(Y);a&&t?.data?.height&&(a.style.height=t.data.height+"px")}),t.on("error",function(e){m(!1),i?.(e instanceof Error?e:new Error(l("sign_widget_error")))}),t.on("closed",function(){c?.()}),d.current=t}).catch(t=>{e||(h("Falha ao carregar o script de assinatura."),m(!1),i?.(t))}),()=>{e=!0,d.current&&(d.current.unmount(),d.current=null)}},[a,s]),e.jsxs("div",{className:"relative h-full",children:[u&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground",children:[e.jsx(r.Loader2,{className:"h-5 w-5 animate-spin"}),e.jsx("span",{className:"text-sm",children:"Carregando documento..."})]})}),g&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsx("p",{className:"text-sm text-destructive",children:g})}),e.jsx("div",{id:Y,style:{height:"600px"}})]})}function Q(...e){return l.twMerge(c.clsx(e))}const X=i.cva("relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4",{variants:{variant:{info:"bg-[hsl(var(--alert-info-bg))] border-[hsl(var(--alert-info-border))] text-[hsl(var(--alert-info-foreground))] [&>svg]:text-[hsl(var(--alert-info-foreground))]",warning:"bg-[hsl(var(--alert-warning-bg))] border-[hsl(var(--alert-warning-border))] text-[hsl(var(--alert-warning-foreground))] [&>svg]:text-[hsl(var(--alert-warning-foreground))]",danger:"bg-[hsl(var(--alert-danger-bg))] border-[hsl(var(--alert-danger-border))] text-[hsl(var(--alert-danger-foreground))] [&>svg]:text-[hsl(var(--alert-danger-foreground))]",success:"bg-[hsl(var(--alert-success-bg))] border-[hsl(var(--alert-success-border))] text-[hsl(var(--alert-success-foreground))] [&>svg]:text-[hsl(var(--alert-success-foreground))]"}},defaultVariants:{variant:"info"}}),Z={info:r.Info,warning:r.Info,danger:r.AlertTriangle,success:r.CheckCircle},ee=h.forwardRef(({className:t,variant:a="info",showIcon:s=!0,children:n,...r},o)=>{const i=Z[a||"info"];return e.jsxs("div",{ref:o,role:"alert",className:Q(X({variant:a}),t),...r,children:[s&&e.jsx(i,{className:"h-4 w-4"}),n]})});ee.displayName="Alert";const te=h.forwardRef(({className:t,...a},s)=>e.jsx("h5",{ref:s,className:Q("mb-1 font-medium leading-none tracking-tight",t),...a}));te.displayName="AlertTitle";const ae=h.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:Q("text-sm [&_p]:leading-relaxed",t),...a}));ae.displayName="AlertDescription";function se({documentKey:s,signerEmail:n,signerName:o,keySigner:i,environment:c,onSign:l,onError:d}){const u=t.useRef(null),[m,g]=t.useState("loading"),[h,p]=t.useState(null),f="production"===c?"https://secure.d4sign.com.br/embed/viewblob":"https://sandbox.d4sign.com.br/embed/viewblob",x=(()=>{const e=new URLSearchParams({email:n,display_name:o||"",disable_preview:"0"});return i&&e.set("key_signer",i),`${f}/${s}?${e.toString()}`})(),v=t.useCallback(e=>"signed"===e.data?(g("ready"),void l?.()):"wrong-data"===e.data?(g("error"),p(a.t("sign_incorrect_data")),void d?.(new Error(a.t("sign_incorrect_data")))):void 0,[l,d]);t.useEffect(()=>(window.addEventListener("message",v,!1),()=>{window.removeEventListener("message",v,!1)}),[v]);const y=t.useCallback(()=>{"loading"===m&&g("ready")},[m]);return"error"===m?e.jsxs(ee,{variant:"danger",className:"my-4",children:[e.jsx(te,{children:a.t("sign_doc_load_error")}),e.jsx(ae,{children:h||"Ocorreu um erro inesperado ao carregar o documento para assinatura. Tente novamente."})]}):e.jsxs("div",{className:"relative h-full",children:["loading"===m&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground",children:[e.jsx(r.Loader2,{className:"h-5 w-5 animate-spin"}),e.jsx("span",{className:"text-sm",children:"Carregando documento..."})]})}),e.jsx("iframe",{ref:u,id:"d4sign-container",src:x,width:"100%",style:{height:"600px",border:0},allow:"geolocation",onLoad:y})]})}const ne=i.cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",{variants:{variant:{primary:"bg-primary text-primary-foreground hover:bg-primary-hover shadow-sm hover:shadow-md active:scale-[0.98]",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary-hover border border-input shadow-sm",tertiary:"bg-background text-foreground hover:bg-accent hover:text-accent-foreground border border-border",outline:"border border-input bg-background hover:bg-accent hover:text-accent-foreground",ghost:"hover:bg-accent hover:text-accent-foreground",subtle:"text-muted-foreground hover:text-foreground hover:bg-accent/50",destructive:"bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm hover:shadow-md",danger:"bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm hover:shadow-md",link:"text-primary underline-offset-4 hover:underline",icon:"bg-transparent border border-input hover:bg-accent hover:text-accent-foreground p-2",loading:"bg-primary/50 text-primary-foreground cursor-wait",default:"bg-primary text-primary-foreground hover:bg-primary/90",action:"bg-primary/10 text-primary hover:bg-primary/20 border border-primary/30","icon-only":"bg-transparent border border-input hover:bg-accent hover:text-accent-foreground p-2","external-link":"bg-transparent text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors","action-primary":"bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm","action-secondary":"bg-secondary text-secondary-foreground hover:bg-secondary/80 border border-input"},size:{sm:"h-8 px-3 text-xs rounded-lg",md:"h-10 px-4 py-2 text-sm rounded-md",lg:"h-12 px-8 text-base rounded-lg",xl:"h-14 px-10 text-lg rounded-lg",icon:"h-10 w-10","icon-sm":"h-8 w-8","icon-xs":"h-6 w-6",default:"h-10 px-4 py-2"}},defaultVariants:{variant:"primary",size:"md"}}),re=h.forwardRef(({className:t,variant:a,size:s,asChild:n=!1,...r},o)=>{const i=n?d.Slot:"button";return e.jsx(i,{className:Q(ne({variant:a,size:s,className:t})),ref:o,...r})});re.displayName="Button";const oe=h.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:Q("rounded-lg border bg-card text-card-foreground shadow-sm",t),...a}));oe.displayName="Card";const ie=h.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:Q("flex flex-col space-y-1.5 p-6",t),...a}));ie.displayName="CardHeader";const ce=h.forwardRef(({className:t,...a},s)=>e.jsx("h3",{ref:s,className:Q("text-2xl font-semibold leading-none tracking-tight",t),...a}));ce.displayName="CardTitle";h.forwardRef(({className:t,...a},s)=>e.jsx("p",{ref:s,className:Q("text-sm text-muted-foreground",t),...a})).displayName="CardDescription";const le=h.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:Q("p-6 pt-0",t),...a}));le.displayName="CardContent";h.forwardRef(({className:t,...a},s)=>e.jsx("div",{ref:s,className:Q("flex items-center p-6 pt-0",t),...a})).displayName="CardFooter";const de=h.forwardRef(({className:t,type:a,showCharCount:s,maxLength:n,onChange:r,...o},i)=>{const[c,l]=h.useState(0);h.useEffect(()=>{"string"==typeof o.value?l(o.value.length):"string"==typeof o.defaultValue&&l(o.defaultValue.length)},[o.value,o.defaultValue]);return e.jsxs("div",{className:"w-full",children:[e.jsx("input",{type:a,className:Q("flex h-10 w-full rounded-lg border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground hover:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition-colors md:text-sm",t),ref:i,maxLength:n,onChange:e=>{l(e.target.value.length),r?.(e)},...o}),s&&n&&e.jsxs("div",{className:"text-right text-xs text-muted-foreground mt-1",children:[c," / ",n]})]})});de.displayName="Input";const ue=i.cva("text-xs font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70"),me=h.forwardRef(({className:t,...a},s)=>e.jsx(p.Root,{ref:s,className:Q(ue(),t),...a}));me.displayName=p.Root.displayName;const ge=h.createContext({showCheck:!1}),he=({showCheck:t=!1,...a})=>e.jsx(ge.Provider,{value:{showCheck:t},children:e.jsx(f.Root,{...a})}),pe=f.Value,fe=h.forwardRef(({className:t,children:a,...s},n)=>e.jsxs(f.Trigger,{ref:n,className:Q("flex h-10 w-full items-center justify-between rounded-lg border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground hover:border-primary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition-colors [&>span]:line-clamp-1",t),...s,children:[a,e.jsx(f.Icon,{asChild:!0,children:e.jsx(r.ChevronDown,{className:"h-4 w-4 opacity-50"})})]}));fe.displayName=f.Trigger.displayName;const xe=h.forwardRef(({className:t,...a},s)=>e.jsx(f.ScrollUpButton,{ref:s,className:Q("flex cursor-default items-center justify-center py-1",t),...a,children:e.jsx(r.ChevronUp,{className:"h-4 w-4"})}));xe.displayName=f.ScrollUpButton.displayName;const ve=h.forwardRef(({className:t,...a},s)=>e.jsx(f.ScrollDownButton,{ref:s,className:Q("flex cursor-default items-center justify-center py-1",t),...a,children:e.jsx(r.ChevronDown,{className:"h-4 w-4"})}));ve.displayName=f.ScrollDownButton.displayName;const ye=h.forwardRef(({className:t,children:a,position:s="popper",container:n,collisionBoundary:r,...o},i)=>e.jsx(f.Portal,{container:n,children:e.jsxs(f.Content,{ref:i,className:Q("relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2","popper"===s&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",t),position:s,collisionBoundary:r,...o,children:[e.jsx(xe,{}),e.jsx(f.Viewport,{className:Q("p-1","popper"===s&&"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"),children:a}),e.jsx(ve,{})]})}));ye.displayName=f.Content.displayName;h.forwardRef(({className:t,...a},s)=>e.jsx(f.Label,{ref:s,className:Q("py-1.5 pl-8 pr-2 text-sm font-semibold",t),...a})).displayName=f.Label.displayName;const be=h.forwardRef(({className:t,children:a,...s},n)=>{const{showCheck:o}=h.useContext(ge);return e.jsxs(f.Item,{ref:n,className:Q("relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",o?"pl-8":"pl-2","data-[state=checked]:bg-accent data-[state=checked]:text-accent-foreground data-[state=checked]:font-medium data-[state=checked]:border-l-2 data-[state=checked]:border-primary",o?"data-[state=checked]:pl-[calc(2rem-2px)]":"data-[state=checked]:pl-[calc(0.5rem-2px)]",t),...s,children:[o&&e.jsx("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:e.jsx(f.ItemIndicator,{children:e.jsx(r.Check,{className:"h-4 w-4"})})}),e.jsx(f.ItemText,{children:a})]})});be.displayName=f.Item.displayName;h.forwardRef(({className:t,...a},s)=>e.jsx(f.Separator,{ref:s,className:Q("-mx-1 my-1 h-px bg-muted",t),...a})).displayName=f.Separator.displayName,exports.D4SignWidget=se,exports.DocumentSigner=function({file:s,onDocumentSigned:i,onError:c,showEventLog:l=!1}){const{user:d,alias:u}=$(),{config:m,isLoading:g}=z(),{t:h}=o.useTranslation(),[p,f]=t.useState(null),[x,v]=t.useState(!1),[y,b]=t.useState(null),[_,k]=t.useState("sandbox"),[w,S]=t.useState("clicksign"),[j,N]=t.useState(null),[T,I]=t.useState(null),[A,E]=t.useState(!1),[C,P]=t.useState(0),[L,R]=t.useState(!1),[V,U]=t.useState([]),D=t.useRef(null),O=t.useRef(null),q=t.useCallback(e=>{l&&U(t=>[...t,`[${(new Date).toLocaleTimeString()}] ${e}`])},[l]),B=t.useCallback(async e=>{if(f(e),b(null),N(null),I(null),q(`Arquivo selecionado: ${e.name}`),u&&d){v(!0);try{const t=m?.provider??"clicksign";S(t),q(`Provedor resolvido: ${t}`);const s=new FileReader,r=await new Promise((t,a)=>{s.onload=()=>{const e=s.result;t(e)},s.onerror=a,s.readAsDataURL(e)});q(`Criando envelope para assinatura via ${t}...`);const o=await M.createEnvelopeWithSigner({alias:u,contentBase64:r,filename:e.name,signerEmail:d.email||"",signerName:d.name||"",provider:t});q(`Envelope criado: ${o.envelope_id}`),N({envelope_id:o.envelope_id,document_id:o.document_id,signer_email:o.signer_email,key_signer:o.signer_id}),k(o.environment),S(o.provider||t),"d4sign"===t?(q("Documento enviado para D4Sign. Abrindo widget de assinatura..."),await new Promise(e=>setTimeout(e,2e3)),b(o.document_id),n.toast.success(h("sign_doc_sent","Documento enviado! Assine abaixo."))):o.signer_id?(q(`Signer ID obtido: ${o.signer_id}. Aguardando processamento (3s)...`),await new Promise(e=>setTimeout(e,3e3)),b(o.signer_id),n.toast.success(h("sign_doc_sent","Documento enviado! Assine abaixo."))):(q(a.t("sign_signer_unavailable")),n.toast.error(h("sign_access_error","Não foi possível obter o acesso para assinatura. Tente novamente.")),c?.(new Error(h("sign_signer_unavailable"))))}catch(t){const e=t instanceof Error?t:new Error(h("sign_process_error",h("sign_doc_process_error"))),s=e.message||"";s.includes("MONTHLY_LIMIT_REACHED")?(q(a.t("sign_monthly_limit")),n.toast.error(h("sign_monthly_limit","Limite mensal de assinaturas atingido. Entre em contato com o administrador para ampliar seu plano."))):(q(`Erro: ${s}`),n.toast.error(s)),c?.(e)}finally{v(!1)}}},[u,d,q,c,m]);t.useEffect(()=>{s&&u&&d&&!g&&s!==O.current&&(O.current=s,B(s))},[s,u,d,g,B]);const J=t.useCallback(async()=>{if(!j||!u)return;E(!0),P(0),R(!1),q("Buscando documento assinado...");for(let t=1;t<=6;t++){P(t),q(`Tentativa ${t}/6...`);try{const e=await M.getSignedDocument({alias:u,envelopeId:j.envelope_id,documentId:j.document_id,provider:w});if(e.download_url)return q(a.t("sign_doc_available")),I(e.download_url),void E(!1)}catch(e){q(`Erro na tentativa ${t}: ${e instanceof Error?e.message:h("unknown_error")}`)}t<6&&(q("Aguardando 10 segundos para próxima tentativa..."),await new Promise(e=>setTimeout(e,1e4)))}q(a.t("sign_fetch_failed")),E(!1),R(!0)},[j,u,q,w]),F=t.useCallback(async()=>{q("Documento assinado com sucesso!"),n.toast.success(h("sign_signed_success","Documento assinado com sucesso!")),b(null),j&&u&&(i?.({success:!0,provider:w,envelope_id:j.envelope_id,document_id:j.document_id,signer_id:y||"",environment:_}),await J())},[q,i,j,y,u,_,w,J]);if(!u)return e.jsx(oe,{className:"border-amber-200 bg-amber-50",children:e.jsx(le,{className:"flex items-start gap-3 py-6",children:e.jsxs("div",{children:[e.jsx("p",{className:"font-medium text-amber-800",children:h("sign_auth_required","Autenticação necessária")}),e.jsx("p",{className:"text-sm text-amber-700 mt-1",children:h("sign_login_required","Faça login para utilizar a assinatura digital.")})]})})});const W="d4sign"===w?"D4Sign":"Clicksign",H=()=>l&&V.length>0?e.jsx("div",{className:"bg-muted p-3 rounded-md text-xs font-mono space-y-1 max-h-40 overflow-auto",children:V.map((t,a)=>e.jsx("div",{children:t},a))}):null;return j&&!y&&(T||A||L)?e.jsxs("div",{className:"space-y-4",children:[e.jsx(oe,{className:"border-green-200 bg-green-50",children:e.jsxs(le,{className:"flex flex-col items-center gap-4 py-8",children:[e.jsx(r.CheckCircle2,{className:"h-12 w-12 text-green-600"}),e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"text-lg font-semibold text-green-800",children:h("sign_signed_success","Documento assinado com sucesso!")}),e.jsx("p",{className:"text-sm text-green-700 mt-1",children:p?.name})]}),A?e.jsxs("div",{className:"flex flex-col items-center gap-2 text-sm text-muted-foreground",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(r.Loader2,{className:"h-4 w-4 animate-spin"}),h("sign_preparing_doc","Preparando documento assinado...")," (",h("sign_attempt","tentativa")," ",C,"/6)"]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:h("sign_waiting_provider",`Aguardando processamento pelo ${W}...`)})]}):T?e.jsx(re,{asChild:!0,variant:"default",className:"gap-2",children:e.jsxs("a",{href:T,target:"_blank",rel:"noopener noreferrer",children:[e.jsx(r.Download,{className:"h-4 w-4"}),h("sign_download_signed","Baixar documento assinado")]})}):L?e.jsxs("div",{className:"text-center space-y-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:h("sign_fetch_failed","Não foi possível obter o documento assinado após 1 minuto.")}),e.jsx("p",{className:"text-xs text-muted-foreground",children:h("sign_email_fallback","O documento será enviado para o seu e-mail assim que estiver disponível.")})]}),e.jsxs(re,{variant:"secondary",className:"gap-2",onClick:J,children:[e.jsx(r.RefreshCw,{className:"h-4 w-4"}),h("sign_try_again","Tentar novamente")]})]}):null]})}),e.jsx(H,{})]}):y?e.jsxs("div",{className:"space-y-4",children:["d4sign"===w?e.jsx(se,{documentKey:y,signerEmail:j?.signer_email||d?.email||"",signerName:d?.name,keySigner:j?.key_signer,environment:_,onSign:F,onError:c}):e.jsx(G,{signerId:y,environment:_,onSign:F,onError:c}),e.jsx(H,{})]}):s&&(x||g)?e.jsx(oe,{children:e.jsxs(le,{className:"flex items-center justify-center gap-3 py-10",children:[e.jsx(r.Loader2,{className:"h-6 w-6 animate-spin text-primary"}),e.jsx("p",{className:"font-medium",children:h("sign_sending_doc","Enviando documento para assinatura...")})]})}):e.jsxs("div",{className:"space-y-4",children:[e.jsx("input",{ref:D,type:"file",accept:"application/pdf",className:"hidden",onChange:e=>{const t=e.target.files?.[0];t&&"application/pdf"===t.type?B(t):n.toast.error(h("sign_select_pdf","Selecione um arquivo PDF"))}}),x?e.jsx(oe,{children:e.jsxs(le,{className:"flex items-center justify-center gap-3 py-10",children:[e.jsx(r.Loader2,{className:"h-6 w-6 animate-spin text-primary"}),e.jsx("p",{className:"font-medium",children:h("sign_sending_doc","Enviando documento para assinatura...")})]})}):e.jsx(oe,{className:"border-dashed border-2 cursor-pointer hover:bg-muted/50 transition-colors",onClick:()=>D.current?.click(),children:e.jsxs(le,{className:"flex flex-col items-center justify-center py-10 gap-3",children:[e.jsx(r.Upload,{className:"h-8 w-8 text-muted-foreground"}),e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"font-medium",children:h("sign_select_pdf","Selecione um arquivo PDF")}),e.jsx("p",{className:"text-sm text-muted-foreground",children:h("sign_click_to_select","Clique para escolher o documento para assinatura")})]})]})}),e.jsx(H,{})]})},exports.SignConfigForm=function({onSaved:a}){const{config:s,isLoading:i,saveConfig:c}=z(),{t:l}=o.useTranslation(),[d,u]=t.useState(""),[m,g]=t.useState("sandbox"),[h,p]=t.useState(!1);return t.useEffect(()=>{!i&&s&&(u(s.api_key),g(s.environment))},[s,i]),i?e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsx(r.Loader2,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):e.jsxs("div",{className:"space-y-4",children:[s?e.jsxs("div",{className:"flex items-center gap-2 text-sm text-emerald-600",children:[e.jsx(r.CheckCircle,{className:"h-4 w-4"}),e.jsx("span",{children:l("sign_configured",l("sign_configured_unit"))})]}):e.jsxs("div",{className:"flex items-center gap-2 text-sm text-amber-600",children:[e.jsx(r.AlertCircle,{className:"h-4 w-4"}),e.jsx("span",{children:l("sign_not_configured",l("sign_not_configured_unit"))})]}),e.jsxs(oe,{children:[e.jsx(ie,{children:e.jsx(ce,{className:"text-base",children:l("sign_digital_config")})}),e.jsx(le,{children:e.jsxs("form",{onSubmit:async e=>{if(e.preventDefault(),d.trim()){p(!0);try{await c(d.trim(),m),n.toast.success(l("sign_config_saved",l("sign_config_saved_success"))),a?.()}catch(t){n.toast.error(l("sign_config_save_error",l("sign_config_save_err")))}finally{p(!1)}}else n.toast.error(l("sign_api_key_required",l("sign_api_key_info")))},className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(me,{htmlFor:"sign-api-key",children:"API Key"}),e.jsx(de,{id:"sign-api-key",type:"password",placeholder:l("sign_api_key_placeholder",l("sign_api_key_input")),value:d,onChange:e=>u(e.target.value)})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(me,{children:l("sign_environment","Ambiente")}),e.jsxs(he,{value:m,onValueChange:e=>g(e),children:[e.jsx(fe,{children:e.jsx(pe,{})}),e.jsxs(ye,{children:[e.jsx(be,{value:"sandbox",children:"Sandbox (Testes)"}),e.jsx(be,{value:"production",children:"Produção"})]})]})]}),e.jsxs(re,{type:"submit",disabled:h,children:[h&&e.jsx(r.Loader2,{className:"mr-2 h-4 w-4 animate-spin"}),s?l("sign_update_config",l("sign_update_config_btn")):l("sign_save_config",l("sign_save_config_btn"))]})]})})]})]})},exports.SignWidget=G,exports.loadClicksignScript=K,exports.signService=M,exports.useSignConfig=z;
1
+ "use strict";var e=require("react/jsx-runtime"),n=require("react"),s=require("forlogic-core"),a=require("lucide-react"),i=require("react-i18next"),t=require("i18next");function r(){const{alias:e}=s.useAuth(),[a,i]=n.useState(null),[t,r]=n.useState(!0);n.useEffect(()=>{if(!e)return void r(!1);let n=!1;return(async()=>{r(!0);try{const a=s.getSupabaseClient(),{data:t,error:r}=await a.schema("common").from("sign_configs").select("*").eq("alias",e).is("deleted_at",null).maybeSingle();n||i(t)}catch(a){n||i(null)}finally{n||r(!1)}})(),()=>{n=!0}},[e]);return{config:a,isLoading:t,saveConfig:n.useCallback(async(n,a)=>{if(!e)throw new Error("Alias not available");const t=s.getSupabaseClient(),{data:r,error:o}=await t.schema("common").from("sign_configs").upsert({alias:e,api_key:n,environment:a,updated_at:(new Date).toISOString()},{onConflict:"alias"}).select().maybeSingle();if(o)throw o;return i(r),r},[e])}}const o=(void 0).VITE_SUPABASE_URL,c=s.resolvePublishableKey();async function l(e,n,a){const i=s.TokenManager.getSupabaseToken(),t={"Content-Type":"application/json",apikey:c};i&&(t.Authorization=`Bearer ${i}`);const r=await fetch(`${o}/functions/v1/${e}`,{method:"POST",headers:t,body:JSON.stringify({action:n,data:a})});if(!r.ok){const e=await r.json().catch(()=>({}));throw new Error(e.error||`Erro na requisição: ${r.status}`)}return r}const d={async createEnvelopeWithSigner(e){const n="d4sign"===e.provider?"d4sign":"clicksign",s="d4sign"===e.provider?"create_and_send":"create_envelope_with_signer";return(await l(n,s,{content_base64:e.contentBase64,filename:e.filename,signer_email:e.signerEmail,signer_name:e.signerName})).json()},async getSignedDocument(e){const n="d4sign"===e.provider?"d4sign":"clicksign";return(await l(n,"get_signed_document",{envelope_id:e.envelopeId,document_id:e.documentId})).json()}};let u=null;function m(){return window.Clicksign?Promise.resolve():u||(u=new Promise((e,n)=>{const s=document.createElement("script");s.src="https://cdn-public-library.clicksign.com/embedded/embedded.min-2.1.0.js",s.onload=()=>e(),s.onerror=()=>n(new Error("Falha ao carregar script do Clicksign")),document.head.appendChild(s)}),u)}const g="clicksign-container";function p({signerId:s,environment:t="sandbox",onSign:r,onError:o,onClose:c}){const{t:l}=i.useTranslation(),d=n.useRef(null),[u,p]=n.useState(!0),[x,_]=n.useState(null);return n.useEffect(()=>{let e=!1;return d.current&&(d.current.unmount(),d.current=null),_(null),p(!0),m().then(()=>{if(e)return;const n=new window.Clicksign(s);n.endpoint="production"===t?"https://app.clicksign.com":"https://sandbox.clicksign.com",n.origin=window.origin,n.mount(g),n.on("loaded",function(){p(!1)}),n.on("signed",function(){r?.()}),n.on("resized",function(e){const n=e,s=document.getElementById(g);s&&n?.data?.height&&(s.style.height=n.data.height+"px")}),n.on("error",function(e){p(!1),o?.(e instanceof Error?e:new Error(l("sign_widget_error")))}),n.on("closed",function(){c?.()}),d.current=n}).catch(n=>{e||(_("Falha ao carregar o script de assinatura."),p(!1),o?.(n))}),()=>{e=!0,d.current&&(d.current.unmount(),d.current=null)}},[s,t]),e.jsxs("div",{className:"relative h-full",children:[u&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground",children:[e.jsx(a.Loader2,{className:"h-5 w-5 animate-spin"}),e.jsx("span",{className:"text-sm",children:"Carregando documento..."})]})}),x&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsx("p",{className:"text-sm text-destructive",children:x})}),e.jsx("div",{id:g,style:{height:"600px"}})]})}function x({documentKey:i,signerEmail:r,signerName:o,keySigner:c,environment:l,onSign:d,onError:u}){const m=n.useRef(null),[g,p]=n.useState("loading"),[x,_]=n.useState(null),h="production"===l?"https://secure.d4sign.com.br/embed/viewblob":"https://sandbox.d4sign.com.br/embed/viewblob",f=(()=>{const e=new URLSearchParams({email:r,display_name:o||"",disable_preview:"0"});return c&&e.set("key_signer",c),`${h}/${i}?${e.toString()}`})(),v=n.useCallback(e=>"signed"===e.data?(p("ready"),void d?.()):"wrong-data"===e.data?(p("error"),_(t.t("sign_incorrect_data")),void u?.(new Error(t.t("sign_incorrect_data")))):void 0,[d,u]);n.useEffect(()=>(window.addEventListener("message",v,!1),()=>{window.removeEventListener("message",v,!1)}),[v]);const j=n.useCallback(()=>{"loading"===g&&p("ready")},[g]);return"error"===g?e.jsxs(s.Alert,{variant:"danger",className:"my-4",children:[e.jsx(s.AlertTitle,{children:t.t("sign_doc_load_error")}),e.jsx(s.AlertDescription,{children:x||"Ocorreu um erro inesperado ao carregar o documento para assinatura. Tente novamente."})]}):e.jsxs("div",{className:"relative h-full",children:["loading"===g&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground",children:[e.jsx(a.Loader2,{className:"h-5 w-5 animate-spin"}),e.jsx("span",{className:"text-sm",children:"Carregando documento..."})]})}),e.jsx("iframe",{ref:m,id:"d4sign-container",src:f,width:"100%",style:{height:"600px",border:0},allow:"geolocation",onLoad:j})]})}exports.D4SignWidget=x,exports.DocumentSigner=function({file:o,onDocumentSigned:c,onError:l,showEventLog:u=!1}){const{user:m,alias:g}=s.useAuth(),{config:_,isLoading:h}=r(),{t:f}=i.useTranslation(),[v,j]=n.useState(null),[y,w]=n.useState(!1),[b,N]=n.useState(null),[S,C]=n.useState("sandbox"),[k,E]=n.useState("clicksign"),[D,L]=n.useState(null),[A,T]=n.useState(null),[$,q]=n.useState(!1),[I,P]=n.useState(0),[B,R]=n.useState(!1),[F,O]=n.useState([]),U=n.useRef(null),K=n.useRef(null),W=n.useCallback(e=>{u&&O(n=>[...n,`[${(new Date).toLocaleTimeString()}] ${e}`])},[u]),z=n.useCallback(async e=>{if(j(e),N(null),L(null),T(null),W(`Arquivo selecionado: ${e.name}`),g&&m){w(!0);try{const n=_?.provider??"clicksign";E(n),W(`Provedor resolvido: ${n}`);const a=new FileReader,i=await new Promise((n,s)=>{a.onload=()=>{const e=a.result;n(e)},a.onerror=s,a.readAsDataURL(e)});W(`Criando envelope para assinatura via ${n}...`);const r=await d.createEnvelopeWithSigner({alias:g,contentBase64:i,filename:e.name,signerEmail:m.email||"",signerName:m.name||"",provider:n});W(`Envelope criado: ${r.envelope_id}`),L({envelope_id:r.envelope_id,document_id:r.document_id,signer_email:r.signer_email,key_signer:r.signer_id}),C(r.environment),E(r.provider||n),"d4sign"===n?(W("Documento enviado para D4Sign. Abrindo widget de assinatura..."),await new Promise(e=>setTimeout(e,2e3)),N(r.document_id),s.toast.success(f("sign_doc_sent","Documento enviado! Assine abaixo."))):r.signer_id?(W(`Signer ID obtido: ${r.signer_id}. Aguardando processamento (3s)...`),await new Promise(e=>setTimeout(e,3e3)),N(r.signer_id),s.toast.success(f("sign_doc_sent","Documento enviado! Assine abaixo."))):(W(t.t("sign_signer_unavailable")),s.toast.error(f("sign_access_error","Não foi possível obter o acesso para assinatura. Tente novamente.")),l?.(new Error(f("sign_signer_unavailable"))))}catch(n){const e=n instanceof Error?n:new Error(f("sign_process_error",f("sign_doc_process_error"))),a=e.message||"";a.includes("MONTHLY_LIMIT_REACHED")?(W(t.t("sign_monthly_limit")),s.toast.error(f("sign_monthly_limit","Limite mensal de assinaturas atingido. Entre em contato com o administrador para ampliar seu plano."))):(W(`Erro: ${a}`),s.toast.error(a)),l?.(e)}finally{w(!1)}}},[g,m,W,l,_]);n.useEffect(()=>{o&&g&&m&&!h&&o!==K.current&&(K.current=o,z(o))},[o,g,m,h,z]);const H=n.useCallback(async()=>{if(!D||!g)return;q(!0),P(0),R(!1),W("Buscando documento assinado...");for(let n=1;n<=6;n++){P(n),W(`Tentativa ${n}/6...`);try{const e=await d.getSignedDocument({alias:g,envelopeId:D.envelope_id,documentId:D.document_id,provider:k});if(e.download_url)return W(t.t("sign_doc_available")),T(e.download_url),void q(!1)}catch(e){W(`Erro na tentativa ${n}: ${e instanceof Error?e.message:f("unknown_error")}`)}n<6&&(W("Aguardando 10 segundos para próxima tentativa..."),await new Promise(e=>setTimeout(e,1e4)))}W(t.t("sign_fetch_failed")),q(!1),R(!0)},[D,g,W,k]),M=n.useCallback(async()=>{W("Documento assinado com sucesso!"),s.toast.success(f("sign_signed_success","Documento assinado com sucesso!")),N(null),D&&g&&(c?.({success:!0,provider:k,envelope_id:D.envelope_id,document_id:D.document_id,signer_id:b||"",environment:S}),await H())},[W,c,D,b,g,S,k,H]);if(!g)return e.jsx(s.Card,{className:"border-amber-200 bg-amber-50",children:e.jsx(s.CardContent,{className:"flex items-start gap-3 py-6",children:e.jsxs("div",{children:[e.jsx("p",{className:"font-medium text-amber-800",children:f("sign_auth_required","Autenticação necessária")}),e.jsx("p",{className:"text-sm text-amber-700 mt-1",children:f("sign_login_required","Faça login para utilizar a assinatura digital.")})]})})});const V="d4sign"===k?"D4Sign":"Clicksign",J=()=>u&&F.length>0?e.jsx("div",{className:"bg-muted p-3 rounded-md text-xs font-mono space-y-1 max-h-40 overflow-auto",children:F.map((n,s)=>e.jsx("div",{children:n},s))}):null;return D&&!b&&(A||$||B)?e.jsxs("div",{className:"space-y-4",children:[e.jsx(s.Card,{className:"border-green-200 bg-green-50",children:e.jsxs(s.CardContent,{className:"flex flex-col items-center gap-4 py-8",children:[e.jsx(a.CheckCircle2,{className:"h-12 w-12 text-green-600"}),e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"text-lg font-semibold text-green-800",children:f("sign_signed_success","Documento assinado com sucesso!")}),e.jsx("p",{className:"text-sm text-green-700 mt-1",children:v?.name})]}),$?e.jsxs("div",{className:"flex flex-col items-center gap-2 text-sm text-muted-foreground",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(a.Loader2,{className:"h-4 w-4 animate-spin"}),f("sign_preparing_doc","Preparando documento assinado...")," (",f("sign_attempt","tentativa")," ",I,"/6)"]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:f("sign_waiting_provider",`Aguardando processamento pelo ${V}...`)})]}):A?e.jsx(s.Button,{asChild:!0,variant:"default",className:"gap-2",children:e.jsxs("a",{href:A,target:"_blank",rel:"noopener noreferrer",children:[e.jsx(a.Download,{className:"h-4 w-4"}),f("sign_download_signed","Baixar documento assinado")]})}):B?e.jsxs("div",{className:"text-center space-y-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:f("sign_fetch_failed","Não foi possível obter o documento assinado após 1 minuto.")}),e.jsx("p",{className:"text-xs text-muted-foreground",children:f("sign_email_fallback","O documento será enviado para o seu e-mail assim que estiver disponível.")})]}),e.jsxs(s.Button,{variant:"secondary",className:"gap-2",onClick:H,children:[e.jsx(a.RefreshCw,{className:"h-4 w-4"}),f("sign_try_again","Tentar novamente")]})]}):null]})}),e.jsx(J,{})]}):b?e.jsxs("div",{className:"space-y-4",children:["d4sign"===k?e.jsx(x,{documentKey:b,signerEmail:D?.signer_email||m?.email||"",signerName:m?.name,keySigner:D?.key_signer,environment:S,onSign:M,onError:l}):e.jsx(p,{signerId:b,environment:S,onSign:M,onError:l}),e.jsx(J,{})]}):o&&(y||h)?e.jsx(s.Card,{children:e.jsxs(s.CardContent,{className:"flex items-center justify-center gap-3 py-10",children:[e.jsx(a.Loader2,{className:"h-6 w-6 animate-spin text-primary"}),e.jsx("p",{className:"font-medium",children:f("sign_sending_doc","Enviando documento para assinatura...")})]})}):e.jsxs("div",{className:"space-y-4",children:[e.jsx("input",{ref:U,type:"file",accept:"application/pdf",className:"hidden",onChange:e=>{const n=e.target.files?.[0];n&&"application/pdf"===n.type?z(n):s.toast.error(f("sign_select_pdf","Selecione um arquivo PDF"))}}),y?e.jsx(s.Card,{children:e.jsxs(s.CardContent,{className:"flex items-center justify-center gap-3 py-10",children:[e.jsx(a.Loader2,{className:"h-6 w-6 animate-spin text-primary"}),e.jsx("p",{className:"font-medium",children:f("sign_sending_doc","Enviando documento para assinatura...")})]})}):e.jsx(s.Card,{className:"border-dashed border-2 cursor-pointer hover:bg-muted/50 transition-colors",onClick:()=>U.current?.click(),children:e.jsxs(s.CardContent,{className:"flex flex-col items-center justify-center py-10 gap-3",children:[e.jsx(a.Upload,{className:"h-8 w-8 text-muted-foreground"}),e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"font-medium",children:f("sign_select_pdf","Selecione um arquivo PDF")}),e.jsx("p",{className:"text-sm text-muted-foreground",children:f("sign_click_to_select","Clique para escolher o documento para assinatura")})]})]})}),e.jsx(J,{})]})},exports.SignConfigForm=function({onSaved:t}){const{config:o,isLoading:c,saveConfig:l}=r(),{t:d}=i.useTranslation(),[u,m]=n.useState(""),[g,p]=n.useState("sandbox"),[x,_]=n.useState(!1);return n.useEffect(()=>{!c&&o&&(m(o.api_key),p(o.environment))},[o,c]),c?e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsx(a.Loader2,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):e.jsxs("div",{className:"space-y-4",children:[o?e.jsxs("div",{className:"flex items-center gap-2 text-sm text-emerald-600",children:[e.jsx(a.CheckCircle,{className:"h-4 w-4"}),e.jsx("span",{children:d("sign_configured",d("sign_configured_unit"))})]}):e.jsxs("div",{className:"flex items-center gap-2 text-sm text-amber-600",children:[e.jsx(a.AlertCircle,{className:"h-4 w-4"}),e.jsx("span",{children:d("sign_not_configured",d("sign_not_configured_unit"))})]}),e.jsxs(s.Card,{children:[e.jsx(s.CardHeader,{children:e.jsx(s.CardTitle,{className:"text-base",children:d("sign_digital_config")})}),e.jsx(s.CardContent,{children:e.jsxs("form",{onSubmit:async e=>{if(e.preventDefault(),u.trim()){_(!0);try{await l(u.trim(),g),s.toast.success(d("sign_config_saved",d("sign_config_saved_success"))),t?.()}catch(n){s.toast.error(d("sign_config_save_error",d("sign_config_save_err")))}finally{_(!1)}}else s.toast.error(d("sign_api_key_required",d("sign_api_key_info")))},className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(s.Label,{htmlFor:"sign-api-key",children:"API Key"}),e.jsx(s.Input,{id:"sign-api-key",type:"password",placeholder:d("sign_api_key_placeholder",d("sign_api_key_input")),value:u,onChange:e=>m(e.target.value)})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(s.Label,{children:d("sign_environment","Ambiente")}),e.jsxs(s.Select,{value:g,onValueChange:e=>p(e),children:[e.jsx(s.SelectTrigger,{children:e.jsx(s.SelectValue,{})}),e.jsxs(s.SelectContent,{children:[e.jsx(s.SelectItem,{value:"sandbox",children:"Sandbox (Testes)"}),e.jsx(s.SelectItem,{value:"production",children:"Produção"})]})]})]}),e.jsxs(s.Button,{type:"submit",disabled:x,children:[x&&e.jsx(a.Loader2,{className:"mr-2 h-4 w-4 animate-spin"}),o?d("sign_update_config",d("sign_update_config_btn")):d("sign_save_config",d("sign_save_config_btn"))]})]})})]})]})},exports.SignWidget=p,exports.loadClicksignScript=m,exports.signService=d,exports.useSignConfig=r;
@@ -1,3 +1,5 @@
1
+ import { loadEnv } from 'vite';
2
+
1
3
  const DEFAULT_SCRIPT_SRC = [
2
4
  "'self'",
3
5
  "https://cdn.gpteng.co",
@@ -207,4 +209,25 @@ function createForlogicViteConfig(options = {}) {
207
209
  }
208
210
  const defaultForlogicViteConfig = createForlogicViteConfig();
209
211
 
210
- export { createForlogicViteConfig, createSecurityHeadersPlugin, defaultForlogicViteConfig, generateCSPPolicy };
212
+ function resolveSupabaseEnv(mode, cwd = process.cwd()) {
213
+ const env = loadEnv(mode, cwd, "");
214
+ const url = env.VITE_SUPABASE_URL || env.SUPABASE_URL || "";
215
+ const publishableKey = env.VITE_SUPABASE_PUBLISHABLE_KEY || env.SUPABASE_PUBLISHABLE_KEY || "";
216
+ const pkOverride = env.VITE_SUPABASE_PK_OVERRIDE || "";
217
+ let projectId = env.VITE_SUPABASE_PROJECT_ID || env.SUPABASE_PROJECT_ID || "";
218
+ if (!projectId && url) {
219
+ try {
220
+ projectId = new URL(url).hostname.split(".")[0];
221
+ } catch {
222
+ }
223
+ }
224
+ const define = {
225
+ "import.meta.env.VITE_SUPABASE_URL": JSON.stringify(url),
226
+ "import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY": JSON.stringify(publishableKey),
227
+ "import.meta.env.VITE_SUPABASE_PROJECT_ID": JSON.stringify(projectId),
228
+ "import.meta.env.VITE_SUPABASE_PK_OVERRIDE": JSON.stringify(pkOverride)
229
+ };
230
+ return { url, publishableKey, projectId, pkOverride, define };
231
+ }
232
+
233
+ export { createForlogicViteConfig, createSecurityHeadersPlugin, defaultForlogicViteConfig, generateCSPPolicy, resolveSupabaseEnv };
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var vite = require('vite');
4
+
3
5
  const DEFAULT_SCRIPT_SRC = [
4
6
  "'self'",
5
7
  "https://cdn.gpteng.co",
@@ -209,7 +211,29 @@ function createForlogicViteConfig(options = {}) {
209
211
  }
210
212
  const defaultForlogicViteConfig = createForlogicViteConfig();
211
213
 
214
+ function resolveSupabaseEnv(mode, cwd = process.cwd()) {
215
+ const env = vite.loadEnv(mode, cwd, "");
216
+ const url = env.VITE_SUPABASE_URL || env.SUPABASE_URL || "";
217
+ const publishableKey = env.VITE_SUPABASE_PUBLISHABLE_KEY || env.SUPABASE_PUBLISHABLE_KEY || "";
218
+ const pkOverride = env.VITE_SUPABASE_PK_OVERRIDE || "";
219
+ let projectId = env.VITE_SUPABASE_PROJECT_ID || env.SUPABASE_PROJECT_ID || "";
220
+ if (!projectId && url) {
221
+ try {
222
+ projectId = new URL(url).hostname.split(".")[0];
223
+ } catch {
224
+ }
225
+ }
226
+ const define = {
227
+ "import.meta.env.VITE_SUPABASE_URL": JSON.stringify(url),
228
+ "import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY": JSON.stringify(publishableKey),
229
+ "import.meta.env.VITE_SUPABASE_PROJECT_ID": JSON.stringify(projectId),
230
+ "import.meta.env.VITE_SUPABASE_PK_OVERRIDE": JSON.stringify(pkOverride)
231
+ };
232
+ return { url, publishableKey, projectId, pkOverride, define };
233
+ }
234
+
212
235
  exports.createForlogicViteConfig = createForlogicViteConfig;
213
236
  exports.createSecurityHeadersPlugin = createSecurityHeadersPlugin;
214
237
  exports.defaultForlogicViteConfig = defaultForlogicViteConfig;
215
238
  exports.generateCSPPolicy = generateCSPPolicy;
239
+ exports.resolveSupabaseEnv = resolveSupabaseEnv;
@@ -87,7 +87,7 @@ supabase.from('tabela').select('*');
87
87
 
88
88
  | Modo | Quando usar | Envs exigidas |
89
89
  |------|-------------|---------------|
90
- | `'supabase'` (default) | App usa tabelas/edge functions do Supabase | `VITE_SUPABASE_URL`, `VITE_SUPABASE_PUBLISHABLE_KEY`, `VITE_SUPABASE_PK_OVERRIDE` |
90
+ | `'supabase'` (default) | App usa tabelas/edge functions do Supabase | `SUPABASE_URL` + `SUPABASE_PUBLISHABLE_KEY` (ou `VITE_SUPABASE_*` legadas — consolidadas pelo `resolveSupabaseEnv()` no `vite.config.ts`) + `VITE_SUPABASE_PK_OVERRIDE` |
91
91
  | `'dotnet'` | App consome apenas a API .NET do Qualiex (ex.: Documentos) | nenhuma do Supabase |
92
92
 
93
93
  ```tsx
@@ -39,8 +39,8 @@
39
39
 
40
40
  A prop `backend` controla se a lib usa o stack Supabase ou apenas a API .NET do Qualiex.
41
41
 
42
- - `'supabase'` (default, retrocompat): inicializa o cliente Supabase, valida tokens via Edge Function `validate-token` e exige `VITE_SUPABASE_URL` + `VITE_SUPABASE_PUBLISHABLE_KEY` no `.env`.
43
- - `'dotnet'`: a lib **não** chama Supabase em nenhum momento da inicialização. O `AuthProvider` autentica apenas com os tokens OAuth do Qualiex (`access_token` + `id_token`). Não exige envs do Supabase.
42
+ - `'supabase'` (default, retrocompat): inicializa o cliente Supabase, valida tokens via Edge Function `validate-token` e exige `SUPABASE_URL` + `SUPABASE_PUBLISHABLE_KEY` (ou as versões `VITE_SUPABASE_*` legadas) no `.env`. O `vite.config.ts` consolida ambos os formatos via `resolveSupabaseEnv()` — ver `docs/design-system/patterns/feature-flags.md`.
43
+ - `'dotnet'`: a lib **não** chama Supabase em nenhum momento da inicialização. O `AuthProvider` autentica apenas com os tokens OAuth do Qualiex (`access_token` + `id_token`). Não exige envs do Supabase. **Importante:** defina `VITE_APP_ENV="DEV"` no `.env` quando o app rodar contra o ambiente dev do Qualiex — sem essa variável, o failsafe assume `PROD`.
44
44
 
45
45
  ```tsx
46
46
  // Módulo sem Supabase (ex.: Documentos)
@@ -49,6 +49,15 @@ A prop `backend` controla se a lib usa o stack Supabase ou apenas a API .NET do
49
49
  </CoreProviders>
50
50
  ```
51
51
 
52
+ ### O que funciona sem Supabase em `backend="dotnet"`
53
+
54
+ A lib mantém os seguintes recursos funcionando 100% sem nenhuma env var Supabase:
55
+
56
+ - **Logos e favicon** (`assets`, `logoSrc`, `smallLogoSrc`): servidos a partir de bucket público fixo embutido na lib.
57
+ - **Login automático em dev/preview**: `shouldUseDevTokens()` agora exige modo Supabase, então em modo dotnet o `ProtectedRoute` sempre vai para `loginProd()` (OAuth real), mesmo em `localhost`/Lovable preview.
58
+ - **Logoff manual**: `TokenManager.clearAll()` preserva o flag `manual_logout`, garantindo que `logout()` realmente deslogue (sem auto-login no próximo render).
59
+ - **`LegacyKeyBanner`**: oculto automaticamente em modo dotnet.
60
+
52
61
  ### Features que continuam exigindo Supabase
53
62
 
54
63
  Mesmo com `backend="dotnet"`, se você importar qualquer um dos módulos abaixo eles vão falhar em runtime sem Supabase configurado:
@@ -4,13 +4,14 @@
4
4
 
5
5
  | Variável | Descrição | Padrão |
6
6
  |----------|-----------|--------|
7
+ | `VITE_APP_ENV` | Define o ambiente alvo da API/OAuth Qualiex. Valores aceitos: `"PROD"` ou `"DEV"`. Ausente ou qualquer outro valor = `PROD` (failsafe). Ver [seção abaixo](#vite_app_env). | `"PROD"` |
7
8
  | `VITE_SHOW_USER_PREFERENCES` | Exibe "Preferências" no menu do usuário (idioma, timezone, formato de data) | Não exibe |
8
9
  | `VITE_I18N_DEBUG_MODE` | Modo debug de i18n (mostra chaves ao invés de traduções) | `"false"` |
9
10
  | `VITE_IS_QUALIEX` | Usa logos Qualiex ao invés de Forlogic | `"false"` |
10
11
  | `VITE_SHOW_EDIT_PROFILE` | Exibe "Editar Perfil" no menu do usuário (foto e idioma) | Não exibe |
11
12
  | `VITE_WIKI_URL` | Exibe botão "Wiki" no header da aplicação. O valor é a URL que será aberta ao clicar | Não exibe |
12
13
  | `VITE_SHOW_ADMIN_REPORTS` | Exibe relatórios administrativos | `"false"` |
13
- | `VITE_SUPABASE_PK_OVERRIDE` | **Obrigatória.** Publishable key correta do Supabase. Ver [seção abaixo](#vite_supabase_pk_override). | — |
14
+ | `VITE_SUPABASE_PK_OVERRIDE` | **Obrigatória (modo Supabase).** Publishable key correta do Supabase. Ver [seção abaixo](#vite_supabase_pk_override). | — |
14
15
 
15
16
  ## Uso
16
17
 
@@ -27,54 +28,85 @@ Variáveis Vite precisam do prefixo `VITE_` para serem expostas ao cliente.
27
28
 
28
29
  ---
29
30
 
31
+ ## Resolução unificada das envs Supabase (sem duplicação)
32
+
33
+ A partir do `vite.config.ts`, o helper `resolveSupabaseEnv(mode)` (de `forlogic-core/vite`) lê **ambos os formatos** de variáveis e injeta um valor único via `define`:
34
+
35
+ - Aceita `VITE_SUPABASE_*` (legado) **ou** `SUPABASE_*` (formato novo Lovable Cloud).
36
+ - Prioridade: `VITE_SUPABASE_*` → `SUPABASE_*` → fallback derivado (`projectId` extraído da URL).
37
+ - Injeta `import.meta.env.VITE_SUPABASE_URL` / `VITE_SUPABASE_PUBLISHABLE_KEY` / `VITE_SUPABASE_PROJECT_ID` / `VITE_SUPABASE_PK_OVERRIDE` no bundle.
38
+ - O código do app/lib continua usando os nomes `VITE_*` — nada muda no consumo.
39
+
40
+ **Resultado:** o `.env` precisa apenas de **uma** versão de cada variável. Recomendado o formato sem prefixo (Lovable Cloud auto-injeta):
41
+
42
+ ```env
43
+ SUPABASE_URL="https://ccjfvpnndclajkleyqkc.supabase.co"
44
+ SUPABASE_PUBLISHABLE_KEY="sb_publishable_w-TKU0hE4bjM_uOgt3fK1g_ewrXKJ8J"
45
+ VITE_SUPABASE_PK_OVERRIDE="sb_publishable_w-TKU0hE4bjM_uOgt3fK1g_ewrXKJ8J"
46
+ ```
47
+
48
+ Ver `mem://patterns/dynamic-supabase-config`.
49
+
50
+ ---
51
+
52
+ ## `VITE_APP_ENV`
53
+
54
+ Define **explicitamente** o ambiente alvo da API Qualiex e do OAuth, sem depender de pistas indiretas (project ID do Supabase, hostname, etc).
55
+
56
+ | Valor | Resultado |
57
+ |--------------------------------|------------------------------------------------------------------|
58
+ | `"PROD"` | API `common-v4-api.qualiex.com`, OAuth `login.qualiex.com` |
59
+ | `"DEV"` | API `common-v4-api-dev.qualiex.com`, OAuth `login-dev.qualiex.com` |
60
+ | ausente / qualquer outro valor | **PROD (failsafe)** — esquecer a variável nunca aponta para dev |
61
+
62
+ Apps em produção podem omitir a variável; apps que rodam contra dev **precisam** declarar `VITE_APP_ENV="DEV"` no `.env`. Não existe fallback derivado do Supabase.
63
+
64
+ Helpers disponíveis em `forlogic-core`:
65
+
66
+ - `getAppEnv(): 'PROD' | 'DEV'`
67
+ - `isDevEnv(): boolean`
68
+ - `getEnvironmentConfig(): EnvironmentConfig`
69
+
70
+ ---
71
+
30
72
  ## `VITE_SUPABASE_PK_OVERRIDE`
31
73
 
32
74
  ### Problema
33
75
 
34
- O Supabase desativou as legacy API keys (formato JWT `eyJhbGci...`). A integração Supabase do Lovable **sobrescreve automaticamente** `VITE_SUPABASE_PUBLISHABLE_KEY` no `.env` com a legacy anon key a cada prompt, causando `401 Unauthorized` em todas as requests.
76
+ O Supabase desativou as legacy API keys (formato JWT `eyJhbGci...`). A integração Supabase do Lovable **sobrescreve automaticamente** `SUPABASE_PUBLISHABLE_KEY` (e a versão `VITE_*` quando presente) no `.env` com a legacy anon key a cada prompt, causando `401 Unauthorized` em todas as requests.
35
77
 
36
78
  ### Solução
37
79
 
38
80
  A lib `forlogic-core` implementa um mecanismo de override:
39
81
 
40
- 1. Se `VITE_SUPABASE_PK_OVERRIDE` existir no `.env` → a lib usa essa key (ignora `VITE_SUPABASE_PUBLISHABLE_KEY`)
41
- 2. Se não existir → usa `VITE_SUPABASE_PUBLISHABLE_KEY` normalmente
42
- 3. Se a key ativa for uma JWT legada → exibe banner vermelho no preview (DEV) + erro no console
82
+ 1. Se `VITE_SUPABASE_PK_OVERRIDE` existir no `.env` → a lib usa essa key (ignora a publishable key resolvida)
83
+ 2. Se não existir → usa a key resolvida por `resolveSupabaseEnv()`
84
+ 3. Se a key ativa for uma JWT legada → exibe banner vermelho no preview (DEV, apenas `backend="supabase"`) + erro no console
43
85
 
44
- O Lovable **nunca toca** em `VITE_SUPABASE_PK_OVERRIDE` porque só auto-popula estas 3 variáveis:
45
- - `VITE_SUPABASE_URL`
46
- - `VITE_SUPABASE_PUBLISHABLE_KEY`
47
- - `VITE_SUPABASE_PROJECT_ID`
48
-
49
- ### Configuração obrigatória
50
-
51
- **Todo projeto consumidor** que aponta para o Supabase `ccjfvpnndclajkleyqkc` deve adicionar no `.env`:
52
-
53
- ```env
54
- VITE_SUPABASE_PK_OVERRIDE="sb_publishable_w-TKU0hE4bjM_uOgt3fK1g_ewrXKJ8J"
55
- ```
86
+ O Lovable **nunca toca** em `VITE_SUPABASE_PK_OVERRIDE` porque só auto-popula as envs Supabase padrão.
56
87
 
57
88
  ### Como funciona internamente
58
89
 
59
90
  ```text
60
91
  VITE_SUPABASE_PK_OVERRIDE existe?
61
- ├─ SIM → usar ela (ignora VITE_SUPABASE_PUBLISHABLE_KEY)
92
+ ├─ SIM → usar ela
62
93
  │ console.info: "✅ Usando VITE_SUPABASE_PK_OVERRIDE..."
63
- └─ NÃO → usar VITE_SUPABASE_PUBLISHABLE_KEY
94
+ └─ NÃO → usar a key resolvida por resolveSupabaseEnv()
64
95
  ├─ Formato sb_publishable_* → OK
65
96
  └─ Formato eyJ* (JWT legada) → ⛔ Erro
66
97
  ├─ console.error com diagnóstico completo
67
- └─ Banner vermelho fixo no topo (apenas DEV)
98
+ └─ Banner vermelho fixo no topo (apenas DEV, modo supabase)
68
99
  ```
69
100
 
70
101
  ### Arquivos relevantes na lib
71
102
 
72
103
  | Arquivo | Responsabilidade |
73
104
  |---------|-----------------|
105
+ | `lib/vite/resolve-supabase-env.ts` | `resolveSupabaseEnv()` — consolida envs Supabase no `define` do Vite |
74
106
  | `lib/supabase/legacyKeyGuard.ts` | `resolvePublishableKey()`, `isLegacyAnonKey()`, `warnIfLegacyKey()` |
75
107
  | `lib/supabase/SupabaseSingleton.ts` | Usa `resolvePublishableKey()` para a key do client |
76
108
  | `lib/supabase/publicClient.ts` | Idem para o client público |
77
- | `lib/providers/CoreProviders.tsx` | Renderiza `LegacyKeyBanner` em DEV |
109
+ | `lib/providers/CoreProviders.tsx` | Renderiza `LegacyKeyBanner` em DEV (apenas `backend="supabase"`) |
78
110
 
79
111
  ### ⚠️ Nunca remova esta variável do `.env`
80
112
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forlogic-core",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",